You've already forked macports-base
mirror of
https://github.com/macports/macports-base.git
synced 2026-07-12 18:18:43 -07:00
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.
git-svn-id: https://svn.macports.org/repository/macports/trunk/base@68996 d073be05-634f-4543-b044-5fe20cf6d1d6
This commit is contained in:
@@ -34,6 +34,7 @@ include Mk/macports.subdir.mk
|
||||
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
|
||||
|
||||
@@ -688,6 +688,7 @@ ZIP
|
||||
UNZIP
|
||||
TAR
|
||||
SED
|
||||
OPENSSL
|
||||
RSYNC
|
||||
RMDIR
|
||||
PATCH
|
||||
@@ -816,6 +817,7 @@ OBJCFLAGS
|
||||
MTREE
|
||||
CVS
|
||||
SVN
|
||||
OPENSSL
|
||||
RSYNC
|
||||
SED
|
||||
TAR
|
||||
@@ -1495,6 +1497,7 @@ Some influential environment variables:
|
||||
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 @@ $as_echo "no" >&6; }
|
||||
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 @@ 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
|
||||
@@ -9365,7 +9409,7 @@ prefix=$oldprefix
|
||||
|
||||
|
||||
# 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 @@ do
|
||||
"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" ;;
|
||||
|
||||
@@ -103,6 +103,7 @@ AC_PATH_PROG(LIPO, [lipo], [])
|
||||
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_PATH_PROG(OPEN, [open], [])
|
||||
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 @@ AC_CONFIG_FILES([
|
||||
doc/prefix.mtree
|
||||
doc/macosx.mtree
|
||||
doc/macports.conf
|
||||
doc/pubkeys.conf
|
||||
portmgr/freebsd/Makefile
|
||||
src/Makefile
|
||||
src/macports1.0/macports_autoconf.tcl
|
||||
|
||||
+9
-16
@@ -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 @@ clean:
|
||||
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 @@ install: all
|
||||
$(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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@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
|
||||
@@ -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-----
|
||||
@@ -51,8 +51,8 @@ namespace eval macports {
|
||||
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 @@ proc mportinit {{up_ui_options {}} {up_options {}} {up_variations {}}} {
|
||||
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 @@ proc mportinit {{up_ui_options {}} {up_options {}} {up_variations {}}} {
|
||||
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"
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace eval portarchivefetch {
|
||||
|
||||
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.password ""
|
||||
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 @@ proc portarchivefetch::checkfiles {urls} {
|
||||
# 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 @@ proc portarchivefetch::fetchfiles {args} {
|
||||
}
|
||||
}
|
||||
}
|
||||
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 @@ proc portarchivefetch::fetchfiles {args} {
|
||||
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 @@ proc portarchivefetch::fetchfiles {args} {
|
||||
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 {
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace eval portutil::autoconf {
|
||||
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@"
|
||||
|
||||
Reference in New Issue
Block a user