[68996] trunk/base

jmr at macports.org jmr at macports.org
Sat Jun 19 16:21:04 PDT 2010


Revision: 68996
          http://trac.macports.org/changeset/68996
Author:   jmr at macports.org
Date:     2010-06-19 16:21:02 -0700 (Sat, 19 Jun 2010)
Log Message:
-----------
Added integrity checking for fetched archives via signed digests. New pubkeys.conf file allows configuring keys to trust. The private counterpart of the installed public key will of course need to live on our binary building server.

Modified Paths:
--------------
    trunk/base/Makefile.in
    trunk/base/configure
    trunk/base/configure.ac
    trunk/base/doc/Makefile
    trunk/base/src/macports1.0/macports.tcl
    trunk/base/src/package1.0/portarchivefetch.tcl
    trunk/base/src/port1.0/port_autoconf.tcl.in

Added Paths:
-----------
    trunk/base/doc/pubkeys.conf.in
    trunk/base/macports-pubkey.pem

Property Changed:
----------------
    trunk/base/doc/

Modified: trunk/base/Makefile.in
===================================================================
--- trunk/base/Makefile.in	2010-06-19 23:15:31 UTC (rev 68995)
+++ trunk/base/Makefile.in	2010-06-19 23:21:02 UTC (rev 68996)
@@ -34,6 +34,7 @@
 install::
 	[ ! -f $(DESTDIR)${sysconfdir}/macports/mp_version ] || rm -vf $(DESTDIR)${sysconfdir}/macports/mp_version
 	$(INSTALL) -o ${DSTUSR} -g ${DSTGRP} -m 444 setupenv.bash  $(DESTDIR)${datadir}/macports/
+	$(INSTALL) -o ${DSTUSR} -g ${DSTGRP} -m 444 macports-pubkey.pem  $(DESTDIR)${datadir}/macports/
 # Only run these scripts when not building in a destroot
 ifeq ($(DESTDIR),)
 # Add [default] tag to the central MacPorts repository, if it isn't already

Modified: trunk/base/configure
===================================================================
--- trunk/base/configure	2010-06-19 23:15:31 UTC (rev 68995)
+++ trunk/base/configure	2010-06-19 23:21:02 UTC (rev 68996)
@@ -688,6 +688,7 @@
 UNZIP
 TAR
 SED
+OPENSSL
 RSYNC
 RMDIR
 PATCH
@@ -816,6 +817,7 @@
 MTREE
 CVS
 SVN
+OPENSSL
 RSYNC
 SED
 TAR
@@ -1495,6 +1497,7 @@
   MTREE       path to mtree command
   CVS         path to cvs command
   SVN         path to svn command
+  OPENSSL     path to openssl command
   RSYNC       path to rsync command
   SED         path to sed command
   TAR         path to tar command
@@ -4810,6 +4813,46 @@
 fi
 
 
+# Extract the first word of "openssl", so it can be a program name with args.
+set dummy openssl; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_OPENSSL+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $OPENSSL in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_OPENSSL="$OPENSSL" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_OPENSSL="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+OPENSSL=$ac_cv_path_OPENSSL
+if test -n "$OPENSSL"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENSSL" >&5
+$as_echo "$OPENSSL" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
 # Extract the first word of "sed", so it can be a program name with args.
 set dummy sed; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@@ -5607,6 +5650,7 @@
 
 
 
+
 	# Extract the first word of "sed", so it can be a program name with args.
 set dummy sed; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@@ -9365,7 +9409,7 @@
 
 
 # Output
-ac_config_files="$ac_config_files Doxyfile Makefile Mk/macports.autoconf.mk doc/prefix.mtree doc/macosx.mtree doc/macports.conf portmgr/freebsd/Makefile src/Makefile src/macports1.0/macports_autoconf.tcl src/port1.0/port_autoconf.tcl src/registry2.0/registry_autoconf.tcl src/programs/Makefile src/macports1.0/macports_fastload.tcl setupenv.bash"
+ac_config_files="$ac_config_files Doxyfile Makefile Mk/macports.autoconf.mk doc/prefix.mtree doc/macosx.mtree doc/macports.conf doc/pubkeys.conf portmgr/freebsd/Makefile src/Makefile src/macports1.0/macports_autoconf.tcl src/port1.0/port_autoconf.tcl src/registry2.0/registry_autoconf.tcl src/programs/Makefile src/macports1.0/macports_fastload.tcl setupenv.bash"
 
 
 ac_config_files="$ac_config_files src/pkg_mkindex.sh"
@@ -10062,6 +10106,7 @@
     "doc/prefix.mtree") CONFIG_FILES="$CONFIG_FILES doc/prefix.mtree" ;;
     "doc/macosx.mtree") CONFIG_FILES="$CONFIG_FILES doc/macosx.mtree" ;;
     "doc/macports.conf") CONFIG_FILES="$CONFIG_FILES doc/macports.conf" ;;
+    "doc/pubkeys.conf") CONFIG_FILES="$CONFIG_FILES doc/pubkeys.conf" ;;
     "portmgr/freebsd/Makefile") CONFIG_FILES="$CONFIG_FILES portmgr/freebsd/Makefile" ;;
     "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
     "src/macports1.0/macports_autoconf.tcl") CONFIG_FILES="$CONFIG_FILES src/macports1.0/macports_autoconf.tcl" ;;

Modified: trunk/base/configure.ac
===================================================================
--- trunk/base/configure.ac	2010-06-19 23:15:31 UTC (rev 68995)
+++ trunk/base/configure.ac	2010-06-19 23:21:02 UTC (rev 68996)
@@ -103,6 +103,7 @@
 AC_PATH_PROG(PATCH, [patch], [])
 AC_PATH_PROG(RMDIR, [rmdir], [])
 AC_PATH_PROG(RSYNC, [rsync], [])
+AC_PATH_PROG(OPENSSL, [openssl], [])
 AC_PATH_PROG(SED, [sed])
 AC_PATH_PROG(TAR, [tar])
 AC_PATH_PROG(UNZIP, [unzip])
@@ -127,6 +128,7 @@
 AC_ARG_VAR(MTREE, [path to mtree command])
 AC_ARG_VAR(CVS, [path to cvs command])
 AC_ARG_VAR(SVN, [path to svn command])
+AC_ARG_VAR(OPENSSL, [path to openssl command])
 AC_ARG_VAR(RSYNC, [path to rsync command])
 AC_ARG_VAR(SED, [path to sed command])
 AC_ARG_VAR(TAR, [path to tar command])
@@ -346,6 +348,7 @@
 	doc/prefix.mtree
 	doc/macosx.mtree
 	doc/macports.conf
+	doc/pubkeys.conf
 	portmgr/freebsd/Makefile
 	src/Makefile
 	src/macports1.0/macports_autoconf.tcl


Property changes on: trunk/base/doc
___________________________________________________________________
Modified: svn:ignore
   - macports.conf
prefix.mtree
macosx.mtree
*[0-9].gz

   + macports.conf
pubkeys.conf
prefix.mtree
macosx.mtree
*[0-9].gz


Modified: trunk/base/doc/Makefile
===================================================================
--- trunk/base/doc/Makefile	2010-06-19 23:15:31 UTC (rev 68995)
+++ trunk/base/doc/Makefile	2010-06-19 23:21:02 UTC (rev 68996)
@@ -1,6 +1,7 @@
 MAN1=		port.1
 MAN5=		macports.conf.5
 MAN7=		portfile.7 portstyle.7 porthier.7 portgroup.7
+CONF=       macports.conf pubkeys.conf sources.conf variants.conf
 INSTALLDIR=	${DESTDIR}${prefix}
 TOPSRCDIR=	..
 
@@ -16,7 +17,7 @@
 test:
 
 distclean: clean
-	rm -f prefix.mtree macports.conf macosx.mtree
+	rm -f macports.conf macosx.mtree prefix.mtree pubkeys.conf
 
 %.1.gz: %.1
 	gzip -c $^ > $@
@@ -40,21 +41,13 @@
 		$(LN_S) share/man ${INSTALLDIR}/man; \
 	fi
 
-	$(INSTALL) -o ${DSTUSR} -g ${DSTGRP} -m 444 macports.conf ${DESTDIR}${mpconfigdir}/macports.conf.default
-	if test ! -e ${DESTDIR}${mpconfigdir}/macports.conf ; then \
-		set -x; \
-		$(INSTALL) -o ${DSTUSR} -g ${DSTGRP} -m 644 macports.conf ${DESTDIR}${mpconfigdir}; \
-	fi
-	$(INSTALL) -o ${DSTUSR} -g ${DSTGRP} -m 444 sources.conf ${DESTDIR}${mpconfigdir}/sources.conf.default
-	if test ! -e ${DESTDIR}${mpconfigdir}/sources.conf ; then \
-		set -x; \
-		$(INSTALL) -o ${DSTUSR} -g ${DSTGRP} -m 644 sources.conf ${DESTDIR}${mpconfigdir}; \
-	fi
-	$(INSTALL) -o ${DSTUSR} -g ${DSTGRP} -m 444 variants.conf ${DESTDIR}${mpconfigdir}/variants.conf.default
-	if test ! -e ${DESTDIR}${mpconfigdir}/variants.conf ; then \
-		set -x; \
-		$(INSTALL) -o ${DSTUSR} -g ${DSTGRP} -m 644 variants.conf ${DESTDIR}${mpconfigdir}; \
-	fi
+	for f in ${CONF}; do \
+		$(INSTALL) -o ${DSTUSR} -g ${DSTGRP} -m 444 $$f ${DESTDIR}${mpconfigdir}/$${f}.default; \
+		if test ! -e ${DESTDIR}${mpconfigdir}/$$f ; then \
+			set -x; \
+			$(INSTALL) -o ${DSTUSR} -g ${DSTGRP} -m 644 $$f ${DESTDIR}${mpconfigdir}; \
+		fi; \
+	done
 
 	# delete old uncompressed man pages if they exist
 	for m in ${MAN1}; do rm -f ${INSTALLDIR}/share/man/man1/$$m ; done

Added: trunk/base/doc/pubkeys.conf.in
===================================================================
--- trunk/base/doc/pubkeys.conf.in	                        (rev 0)
+++ trunk/base/doc/pubkeys.conf.in	2010-06-19 23:21:02 UTC (rev 68996)
@@ -0,0 +1,10 @@
+# Downloaded archives will only be used if they can be verified by a public
+# key listed here. Use full paths, one per line.
+
+ at prefix_expanded@/share/macports/macports-pubkey.pem
+
+# To distribute archives of your own, you need a key pair generated like so:
+# openssl genrsa -des3 -out privkey.pem 2048
+# openssl rsa -in privkey.pem -pubout -out pubkey.pem
+# Then sign the archives like this:
+# openssl dgst -ripemd160 -sign privkey.pem -out archive.tbz2.rmd160 archive.tbz2

Added: trunk/base/macports-pubkey.pem
===================================================================
--- trunk/base/macports-pubkey.pem	                        (rev 0)
+++ trunk/base/macports-pubkey.pem	2010-06-19 23:21:02 UTC (rev 68996)
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxPlw2FSMEavmtuHq5O+f
+XPUXndBnUyoX8iJvQ7NlsNY+hleE307kOAly79WFq2aAGIyKB/Ob8V+qCLW4FGOO
+4NfvOnte1WxQP8oVxOM9ai3CeN6AnUxDWUTYVJ1R+a5ZQVnJyGBKkV+jLlj0PD/z
+d8PCJ/j7Wzizw3d4s9uBIR1zpLY8lVgTivsj5FM3RP6hS7ww7I47goQshoL+YFVg
+NhE9I63oZXqFF130l9jJI9axHUqza7a42WCv04J8iv8SQhgv6fY9ZQnIBMQ4hPDH
+klGusdf4HlCbUViKhxmUpfj6FJabh2jV48ymaoTZB767GJyACF4mvnNDkenEXf41
+/wIDAQAB
+-----END PUBLIC KEY-----

Modified: trunk/base/src/macports1.0/macports.tcl
===================================================================
--- trunk/base/src/macports1.0/macports.tcl	2010-06-19 23:15:31 UTC (rev 68995)
+++ trunk/base/src/macports1.0/macports.tcl	2010-06-19 23:21:02 UTC (rev 68996)
@@ -51,8 +51,8 @@
     variable portinterp_options "\
         portdbpath porturl portpath portbuildpath auto_path prefix prefix_frozen portsharepath \
         registry.path registry.format registry.installtype portarchivemode portarchivepath \
-        portarchivetype portautoclean porttrace keeplogs portverbose destroot_umask rsync_server \
-        rsync_options rsync_dir startupitem_type place_worksymlink macportsuser \
+        portarchivetype archivefetch_pubkeys portautoclean porttrace keeplogs portverbose destroot_umask \
+        rsync_server rsync_options rsync_dir startupitem_type place_worksymlink macportsuser \
         mp_remote_url mp_remote_submit_url configureccache configuredistcc configurepipe buildnicevalue buildmakejobs \
         applications_dir current_phase frameworks_dir developer_dir universal_archs build_arch \
         os_arch os_endian os_version os_major os_platform macosx_version macosx_deployment_target $user_options"
@@ -464,6 +464,7 @@
     global macports::os_platform
     global macports::macosx_version
     global macports::macosx_deployment_target
+    global macports::archivefetch_pubkeys
 
     # Set the system encoding to utf-8
     encoding system utf-8
@@ -602,6 +603,21 @@
     global macports::global_variations
     array set macports::global_variations [array get variations]
 
+    # pubkeys.conf
+    set macports::archivefetch_pubkeys {}
+    if {[file isfile [file join ${macports_conf_path} pubkeys.conf]]} {
+        set fd [open [file join ${macports_conf_path} pubkeys.conf] r]
+        while {[gets $fd line] >= 0} {
+            set line [string trim $line]
+            if {![regexp {^[\ \t]*#.*$|^$} $line]} {
+                lappend macports::archivefetch_pubkeys $line
+            }
+        }
+        close $fd
+    } else {
+        ui_debug "pubkeys.conf does not exist."
+    }
+
     if {![info exists portdbpath]} {
         return -code error "portdbpath must be set in ${macports_conf_path}/macports.conf or in your ${macports_user_dir}/macports.conf"
     }

Modified: trunk/base/src/package1.0/portarchivefetch.tcl
===================================================================
--- trunk/base/src/package1.0/portarchivefetch.tcl	2010-06-19 23:15:31 UTC (rev 68995)
+++ trunk/base/src/package1.0/portarchivefetch.tcl	2010-06-19 23:21:02 UTC (rev 68996)
@@ -47,7 +47,7 @@
 
 options archive_sites archivefetch.user archivefetch.password \
     archivefetch.use_epsv archivefetch.ignore_sslcert \
-    archive_sites.mirror_subdir
+    archive_sites.mirror_subdir archivefetch.pubkeys
 
 # user name & password
 default archivefetch.user ""
@@ -56,6 +56,7 @@
 default archivefetch.use_epsv no
 # Ignore SSL certificate
 default archivefetch.ignore_sslcert no
+default archivefetch.pubkeys {$archivefetch_pubkeys}
 
 default archive_sites macports_archives
 default archive_sites.listfile {"archive_sites.tcl"}
@@ -125,7 +126,7 @@
 # Perform a standard fetch, assembling fetch urls from
 # the listed url variable and associated archive file
 proc portarchivefetch::fetchfiles {args} {
-    global archivefetch.fulldestpath UI_PREFIX
+    global portarchivepath archivefetch.fulldestpath UI_PREFIX
     global archivefetch.user archivefetch.password archivefetch.use_epsv \
            archivefetch.ignore_sslcert
     global portverbose ports_binary_only
@@ -141,7 +142,18 @@
             }
         }
     }
+    set incoming_path [file join ${portarchivepath} incoming]
+    if {![file isdirectory $incoming_path]} {
+        if {[catch {file mkdir $incoming_path} result]} {
+            elevateToRoot "archivefetch"
+            set elevated yes
+            if {[catch {file mkdir $incoming_path} result]} {
+                return -code error [format [msgcat::mc "Unable to create archive fetch path: %s"] $result]
+            }
+        }
+    }
     chownAsRoot ${archivefetch.fulldestpath}
+    chownAsRoot $incoming_path
     if {[info exists elevated] && $elevated == yes} {
         dropPrivileges
     }
@@ -168,6 +180,9 @@
             if {![file writable ${archivefetch.fulldestpath}]} {
                 return -code error [format [msgcat::mc "%s must be writable"] ${archivefetch.fulldestpath}]
             }
+            if {![file writable $incoming_path]} {
+                return -code error [format [msgcat::mc "%s must be writable"] $incoming_path]
+            }
             if {!$sorted} {
                 portfetch::sortsites archivefetch_urls {} archive_sites
                 set sorted yes
@@ -181,17 +196,43 @@
                 ui_msg "$UI_PREFIX [format [msgcat::mc "Attempting to fetch %s from %s"] $archive $site]"
                 set file_url [portfetch::assemble_url $site $archive]
                 set effectiveURL ""
-                if {![catch {eval curl fetch --effective-url effectiveURL $fetch_options {$file_url} ${archivefetch.fulldestpath}/${archive}.TMP} result] &&
-                    ![catch {file rename -force "${archivefetch.fulldestpath}/${archive}.TMP" "${archivefetch.fulldestpath}/${archive}"} result]} {
+                if {![catch {eval curl fetch --effective-url effectiveURL $fetch_options {$file_url} {"${incoming_path}/${archive}.TMP"}} result]} {
                     # Successful fetch
                     set fetched 1
                     break
                 } else {
                     ui_debug "[msgcat::mc "Fetching archive failed:"]: $result"
-                    file delete -force "${archivefetch.fulldestpath}/${archive}.TMP"
+                    file delete -force "${incoming_path}/${archive}.TMP"
                 }
             }
             if {[info exists fetched]} {
+                # there should be an rmd160 digest of the archive signed with one of the trusted keys
+                set signature "${incoming_path}/${archive}.rmd160"
+                ui_msg "$UI_PREFIX [format [msgcat::mc "Attempting to fetch %s from %s"] ${archive}.rmd160 $site]"
+                # reusing $file_url from the last iteration of the loop above
+                if {[catch {eval curl fetch --effective-url effectiveURL $fetch_options {${file_url}.rmd160} {$signature}} result]} {
+                    ui_debug "$::errorInfo"
+                    return -code error "Failed to fetch signature for archive: $result"
+                }
+                set verified 0
+                foreach pubkey [option archivefetch.pubkeys] {
+                    set openssl [findBinary openssl $portutil::autoconf::openssl_path]
+                    if {![catch {exec $openssl dgst -ripemd160 -verify $pubkey -signature $signature "${incoming_path}/${archive}.TMP"} result]} {
+                        set verified 1
+                        break
+                    } else {
+                        ui_debug "failed verification with key $pubkey"
+                        ui_debug "openssl output: $result"
+                    }
+                }
+                if {!$verified} {
+                    return -code error "Failed to verify signature for archive!"
+                }
+                if {[catch {file rename -force "${incoming_path}/${archive}.TMP" "${archivefetch.fulldestpath}/${archive}"} result]} {
+                    ui_debug "$::errorInfo"
+                    return -code error "Failed to move downloaded archive into place: $result"
+                }
+                file delete -force $signature
                 return 0
             }
         } else {

Modified: trunk/base/src/port1.0/port_autoconf.tcl.in
===================================================================
--- trunk/base/src/port1.0/port_autoconf.tcl.in	2010-06-19 23:15:31 UTC (rev 68995)
+++ trunk/base/src/port1.0/port_autoconf.tcl.in	2010-06-19 23:21:02 UTC (rev 68996)
@@ -44,6 +44,7 @@
 	variable hg_path "@HG@"
 	variable gzip_path "@GZIP@"
 	variable lipo_path "@LIPO@"
+	variable openssl_path "@OPENSSL@"
 	variable patch_path "@PATCH@"
 	variable gnupatch_path "@GNUPATCH@"
 	variable rmdir_path "@RMDIR@"
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20100619/24754027/attachment.html>


More information about the macports-changes mailing list