diff options
author | joerg <joerg@pkgsrc.org> | 2009-02-02 12:34:59 +0000 |
---|---|---|
committer | joerg <joerg@pkgsrc.org> | 2009-02-02 12:34:59 +0000 |
commit | d7cc6db11bfefd0006364a122a40572d9eb9b739 (patch) | |
tree | 4c0fb6728ab9db1b5dc2233bb02e4ef34022a604 | |
parent | ea71974691a75ab2e2b9c62a6fb9dcc136b266de (diff) | |
download | pkgsrc-d7cc6db11bfefd0006364a122a40572d9eb9b739.tar.gz |
Merge pkg_install-20090201 from pkg_install-renovation branch.
- DB support is always included from libnbcompat if needed
- pkg_view and linkfarm are not installed any more; they are not moved
into the attic yet, so they can easily be installed as separte package
- common configuration file to customise the behavior of various
components; this supersedes the old audit-packages.conf
- support for PKSC7 signatures (using X509 certs) and GPG signatures for
packages in a secure way. See pkg_admin(8) for how to create them and
pkg_install.conf(5) for the options to use them
- audit-packages and download-vulnerability-list are wrapper scripts
around pkg_admin. They try to mimic the classic options if used sanely.
"pkg_admin audit" is now an order of magnitude faster than before
- pkg_add uses libarchive and libfetch instead of external ftp and tar:
- progress bar is currently missing for downloads
- "pkg_add -" is no longer supported
- no adhoc check for conficts between dependencies and already
installed packages
- "pkg_add -s" has been replaced with an option in pkg_install.conf,
verification of plain detached GPG signatures is no longer supported
- optional check for vulnerabilities before adding a package
- if /var and /usr/pkg are on different fileystems it is twice as fast
now
- conflicts due to overlapping plists are checked before installation
- pkg_add no longer plays with the process limits
- pkg_add and pkg_delete have a new destdir option; scripts have to
either be modified to use PKG_DESTDIR or should be disabled
- pkg_add -u for now can't be used to update to the exact same version
- internal "rm -rf" and "mkdir_p" code
- all memory allocation failures are not explicitly fatal
- if a file is not removed due to a failed checksum, still remove the
entry from pkgdb
88 files changed, 4908 insertions, 8172 deletions
diff --git a/pkgtools/pkg_install/DESCR b/pkgtools/pkg_install/DESCR index 1d4096a0c9b..f59aa3b77e6 100644 --- a/pkgtools/pkg_install/DESCR +++ b/pkgtools/pkg_install/DESCR @@ -5,8 +5,6 @@ from around the globe. The following tools are included: -audit-packages audit installed packages for security vulnerabilities -download-vulnerability-list download the latest vulnerabilities list pkg_add install and upgrade binary packages pkg_admin perform various pkgsrc administrative tasks pkg_create create software package distributions @@ -14,3 +12,8 @@ pkg_delete delete installed packages pkg_info display information about installed or binary packages pkg_view manage package views linkfarm manage symbolic links for package views + +For the following tools compatibility wrappers are included: + +audit-packages audit installed packages for security vulnerabilities +download-vulnerability-list download the latest vulnerabilities list diff --git a/pkgtools/pkg_install/MESSAGE b/pkgtools/pkg_install/MESSAGE index 07b3f544782..f7e76143a08 100644 --- a/pkgtools/pkg_install/MESSAGE +++ b/pkgtools/pkg_install/MESSAGE @@ -1,12 +1,12 @@ =========================================================================== -$NetBSD: MESSAGE,v 1.4 2008/01/13 22:31:25 rillig Exp $ +$NetBSD: MESSAGE,v 1.5 2009/02/02 12:34:59 joerg Exp $ You may wish to have the vulnerabilities file downloaded daily so that it remains current. This may be done by adding an appropriate entry to a user's crontab(5) entry. For example the entry # download vulnerabilities file -0 3 * * * ${PREFIX}/sbin/download-vulnerability-list >/dev/null 2>&1 +0 3 * * * ${PREFIX}/sbin/pkg_admin fetch-pkg-vulnerabilities >/dev/null 2>&1 will update the vulnerability list every day at 3AM. You may wish to do this more often than once a day. @@ -15,28 +15,23 @@ In addition, you may wish to run the package audit from the daily security script. This may be accomplished by adding the following lines to /etc/security.local -if [ -x ${PREFIX}/sbin/audit-packages ]; then - ${PREFIX}/sbin/audit-packages +if [ -x ${PREFIX}/sbin/pkg_admin ]; then + ${PREFIX}/sbin/pkg_admin audit fi Alternatively this can also be acomplished by adding an entry to a user's crontab(5) file. e.g.: # run audit-packages -0 3 * * * ${PREFIX}/sbin/audit-packages +0 3 * * * ${PREFIX}/sbin/pkg_admin audit -audit-packages and/or download-vulnerability-list need not be run by -the root user. They will function as an unprivileged user, as long -as the user chosen has permission to write the pkg-vulnerabilites -to ${PKGVULNDIR}. +Both pkg_admin subcommands can be run as as an unprivileged user, +as long as the user chosen has permission to read the pkgdb and to write +the pkg-vulnerabilites to ${PKGVULNDIR}. -A sample audit-packages.conf has been installed to: +The behavior of pkg_admin and pkg_add can be customised with +pkg_install.conf. Please see pkg_install.conf(5) for details. - ${EGDIR}/audit-packages.conf - -You may want to customise this file and copy it to -${PKG_SYSCONFDIR}/audit-packages.conf. -If you want to use signature verification you will need to install GnuPG and -set the path for GPG appropriately in your audit-packages.conf. See -audit-packages.conf(5) and audit-packages(8) for further information. +If you want to use GPG signature verification you will need to install +GnuPG and set the path for GPG appropriately in your pkg_install.conf. =========================================================================== diff --git a/pkgtools/pkg_install/Makefile b/pkgtools/pkg_install/Makefile index 9c63f569517..d11114899cb 100644 --- a/pkgtools/pkg_install/Makefile +++ b/pkgtools/pkg_install/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.158 2008/07/14 14:56:50 joerg Exp $ +# $NetBSD: Makefile,v 1.159 2009/02/02 12:34:59 joerg Exp $ # Notes to package maintainers: # @@ -24,18 +24,10 @@ CONFLICTS+= audit-packages-[0-9]* GNU_CONFIGURE= yes CONFIGURE_ARGS+= --sysconfdir=${PKG_SYSCONFDIR:Q} CONFIGURE_ARGS+= --with-pkgdbdir=${PKG_DBDIR:Q} -CONFIGURE_ARGS+= --with-ftp=${FETCH_CMD:Q} -CONFIGURE_ARGS+= --with-pax=${PAX:Q} -CONFIGURE_ARGS+= --with-tar=${TAR:Q} -USE_TOOLS+= pax:run tar:run gzcat:run ftp:run - -# The following tools are needed by pkg_view and linkfarm. -USE_TOOLS+= chmod cmp cp env find grep ln mkdir rm rmdir \ - sed sort touch USE_FEATURES= nbcompat -NBCOMPAT_CONFIGURE_ARGS+= --enable-bsd-getopt +NBCOMPAT_CONFIGURE_ARGS+= --enable-bsd-getopt --enable-db SKIP_AUDIT_PACKAGES= yes NO_PKGTOOLS_REQD_CHECK= yes @@ -52,11 +44,11 @@ CHECK_PERMS= no # # We also use the newly built pkg_{add,create,delete} since upgrading # from an older pkg_install might required features of the new program. +# # Note that the definitions are only overriden for the phases that are # supposed to use them. pkg_admin pmatch might be used when looking for # dependencies. If that is ever changed in a incompatible way, this has to # be rethought. -# USE_NATIVE_GCC= yes .if defined(_PKGSRC_BARRIER) @@ -92,21 +84,20 @@ MESSAGE_SUBST+= PKGVULNDIR=${PKG_DBDIR:Q} \ VERSION!= ${AWK} -F '"' '/PKGTOOLS_VERSION/ {print $$2}' \ ${FILESDIR}/lib/version.h -# Make sure the audit-packages files pick up the right tools in the right -# places. -# -SUBST_CLASSES= paths -SUBST_STAGE.paths= pre-configure -SUBST_MESSAGE.paths= Fixing paths in scripts. -SUBST_FILES.paths= audit-packages/Makefile.in -SUBST_SED.paths= -e 's,_gzcat_,${GZCAT},g' - -# linkresolver interface appeared in libarchive 2.5. -BUILDLINK_API_DEPENDS.libarchive+= libarchive>=2.5 +# linkresolver interface appeared in libarchive 2.5 and extract +# requires version 2.5.4b to handle hardlinks correctly. +BUILDLINK_API_DEPENDS.libarchive+= libarchive>=2.5.4b .include "../../archivers/bzip2/builtin.mk" .include "../../archivers/libarchive/builtin.mk" .include "../../devel/zlib/builtin.mk" +.include "../../security/openssl/builtin.mk" + +.if !empty(USE_BUILTIN.openssl:M[yY][eE][sS]) +CONFIGURE_ARGS+= --with-ssl + +.include "../../security/openssl/buildlink3.mk" +.endif .if empty(USE_BUILTIN.bzip2:M[yY][eE][sS]) || \ empty(USE_BUILTIN.zlib:M[yY][eE][sS]) diff --git a/pkgtools/pkg_install/PLIST b/pkgtools/pkg_install/PLIST index 7d9e1fd5252..5315493265f 100644 --- a/pkgtools/pkg_install/PLIST +++ b/pkgtools/pkg_install/PLIST @@ -1,35 +1,24 @@ -@comment $NetBSD: PLIST,v 1.10 2007/07/16 13:23:02 joerg Exp $ -man/cat1/audit-packages.0 -man/cat1/download-vulnerability-list.0 -man/cat1/linkfarm.0 +@comment $NetBSD: PLIST,v 1.11 2009/02/02 12:34:59 joerg Exp $ man/cat1/pkg_add.0 man/cat1/pkg_admin.0 man/cat1/pkg_create.0 man/cat1/pkg_delete.0 man/cat1/pkg_info.0 -man/cat1/pkg_view.0 -man/cat5/audit-packages.conf.0 +man/cat5/pkg_install.conf.0 man/cat5/pkg_summary.0 man/cat7/pkgsrc.0 -man/man1/audit-packages.1 -man/man1/download-vulnerability-list.1 -man/man1/linkfarm.1 man/man1/pkg_add.1 man/man1/pkg_admin.1 man/man1/pkg_create.1 man/man1/pkg_delete.1 man/man1/pkg_info.1 -man/man1/pkg_view.1 -man/man5/audit-packages.conf.5 +man/man5/pkg_install.conf.5 man/man5/pkg_summary.5 man/man7/pkgsrc.7 sbin/audit-packages sbin/download-vulnerability-list -sbin/linkfarm sbin/pkg_add sbin/pkg_admin sbin/pkg_create sbin/pkg_delete sbin/pkg_info -sbin/pkg_view -share/examples/pkg_install/audit-packages.conf diff --git a/pkgtools/pkg_install/files/Makefile.in b/pkgtools/pkg_install/files/Makefile.in index ed1f2264c75..6871dcd26f1 100644 --- a/pkgtools/pkg_install/files/Makefile.in +++ b/pkgtools/pkg_install/files/Makefile.in @@ -1,9 +1,9 @@ -# $NetBSD: Makefile.in,v 1.8 2007/08/03 13:15:58 joerg Exp $ +# $NetBSD: Makefile.in,v 1.9 2009/02/02 12:35:00 joerg Exp $ BOOTSTRAP= @bootstrap@ .if empty(BOOTSTRAP) -SUBDIRS= lib add admin create delete info view audit-packages +SUBDIRS= lib add admin create delete info .else SUBDIRS= lib admin create info .endif @@ -22,5 +22,4 @@ distclean: clean rm -f config.log config.status configure.lineno rm -f Makefile */Makefile rm -f lib/config.h - rm -f view/linkfarm.sh - rm -f view/pkg_view.sh + rm -f bmp/bmp.sh diff --git a/pkgtools/pkg_install/files/add/Makefile.in b/pkgtools/pkg_install/files/add/Makefile.in index 39cdc1b6767..1b45ed175b8 100644 --- a/pkgtools/pkg_install/files/add/Makefile.in +++ b/pkgtools/pkg_install/files/add/Makefile.in @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.in,v 1.18 2008/04/26 17:40:01 joerg Exp $ +# $NetBSD: Makefile.in,v 1.19 2009/02/02 12:35:00 joerg Exp $ srcdir= @srcdir@ @@ -13,17 +13,25 @@ cat1dir= $(mandir)/cat1 CC= @CC@ CCLD= $(CC) -LIBS= -linstall @LIBS@ CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I../lib -DEFS= @DEFS@ -DOPSYS_NAME=\"$(OPSYS)\" -DMACHINE_ARCH=\"$(MACHINE_ARCH)\" -DBINDIR=\"$(sbindir)\" -DTAR_CMD=\"@tar@\" -DPAX_CMD=\"@pax@\" +DEFS= @DEFS@ -DOPSYS_NAME=\"$(OPSYS)\" -DMACHINE_ARCH=\"$(MACHINE_ARCH)\" -DBINDIR=\"$(sbindir)\" CFLAGS= @CFLAGS@ LDFLAGS= @LDFLAGS@ -L../lib +SSL_SUPPORT= @ssl_support@ + +LIBS= -linstall -lfetch -larchive -lbz2 -lz +.if !empty(SSL_SUPPORT) +LIBS+= -lcrypto +CPPFLAGS+= -DHAVE_SSL +.endif +LIBS+= @LIBS@ + INSTALL= @INSTALL@ PROG= pkg_add -OBJS= main.o perform.o futil.o extract.o verify.o +OBJS= main.o perform.o all: $(PROG) diff --git a/pkgtools/pkg_install/files/add/add.h b/pkgtools/pkg_install/files/add/add.h index 9fbba20125a..3a6262aa9ae 100644 --- a/pkgtools/pkg_install/files/add/add.h +++ b/pkgtools/pkg_install/files/add/add.h @@ -1,4 +1,4 @@ -/* $NetBSD: add.h,v 1.12 2008/04/26 17:40:01 joerg Exp $ */ +/* $NetBSD: add.h,v 1.13 2009/02/02 12:35:00 joerg Exp $ */ /* from FreeBSD Id: add.h,v 1.8 1997/02/22 16:09:15 peter Exp */ @@ -25,6 +25,7 @@ #ifndef _INST_ADD_H_INCLUDE #define _INST_ADD_H_INCLUDE +extern char *Destdir; extern char *OverrideMachine; extern char *Prefix; extern char *View; @@ -35,15 +36,8 @@ extern Boolean NoRecord; extern Boolean Force; extern Boolean Automatic; extern int Replace; -extern char *Mode; -extern char *Owner; -extern char *Group; -extern char *Directory; -extern char *PkgName; -extern char FirstPen[]; int make_hierarchy(char *); -int extract_plist(char *, package_t *); void apply_perms(char *, char **, int); int pkg_perform(lpkg_head_t *); diff --git a/pkgtools/pkg_install/files/add/extract.c b/pkgtools/pkg_install/files/add/extract.c deleted file mode 100644 index 0a303e701dd..00000000000 --- a/pkgtools/pkg_install/files/add/extract.c +++ /dev/null @@ -1,340 +0,0 @@ -/* $NetBSD: extract.c,v 1.18 2008/04/26 17:40:01 joerg Exp $ */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include <nbcompat.h> -#if HAVE_SYS_CDEFS_H -#include <sys/cdefs.h> -#endif -#if HAVE_SYS_QUEUE_H -#include <sys/queue.h> -#endif -#ifndef lint -#if 0 -static const char *rcsid = "FreeBSD - Id: extract.c,v 1.17 1997/10/08 07:45:35 charnier Exp"; -#else -__RCSID("$NetBSD: extract.c,v 1.18 2008/04/26 17:40:01 joerg Exp $"); -#endif -#endif - -/* - * FreeBSD install - a package for the installation and maintainance - * of non-core utilities. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Jordan K. Hubbard - * 18 July 1993 - * - * This is the package extraction code for the add module. - * - */ - -#if HAVE_ERR_H -#include <err.h> -#endif -#include "lib.h" -#include "add.h" - -lfile_head_t files; -lfile_head_t perms; - -/* - * Copy files from staging area to todir. - * This is only used when the files cannot be directory rename()ed. - */ -static void -pushout(char *todir) -{ - pipe_to_system_t *pipe_to; - char *file_args[4]; - char **perm_argv; - int perm_argc = 1; - lfile_t *lfp; - int count; - - /* set up arguments to run "pax -r -w -p e" */ - file_args[0] = (char *)strrchr(PAX_CMD, '/'); - if (file_args[0] == NULL) - file_args[0] = PAX_CMD; - else - file_args[0]++; - file_args[1] = "-rwpe"; - file_args[2] = todir; - file_args[3] = NULL; - - /* count entries for files */ - count = 0; - TAILQ_FOREACH(lfp, &files, lf_link) - count++; - - if (count > 0) { - /* open pipe, feed it files, close pipe */ - pipe_to = pipe_to_system_begin(PAX_CMD, file_args, NULL); - while ((lfp = TAILQ_FIRST(&files)) != NULL) { - fprintf(pipe_to->fp, "%s\n", lfp->lf_name); - TAILQ_REMOVE(&files, lfp, lf_link); - free(lfp); - } - pipe_to_system_end(pipe_to); - } - - /* count entries for permissions */ - count = 0; - TAILQ_FOREACH(lfp, &perms, lf_link) - count++; - - if (count > 0) { - perm_argv = malloc((count + 1) * sizeof(char *)); - perm_argc = 0; - TAILQ_FOREACH(lfp, &perms, lf_link) - perm_argv[perm_argc++] = lfp->lf_name; - perm_argv[perm_argc] = NULL; - apply_perms(todir, perm_argv, perm_argc); - - /* empty the perm list */ - while ((lfp = TAILQ_FIRST(&perms)) != NULL) { - TAILQ_REMOVE(&perms, lfp, lf_link); - free(lfp); - } - free(perm_argv); - } -} - -static void -rollback(char *name, char *home, plist_t *start, plist_t *stop) -{ - plist_t *q; - char try[MaxPathSize], bup[MaxPathSize], *dir; - - dir = home; - for (q = start; q != stop; q = q->next) { - if (q->type == PLIST_FILE) { - (void) snprintf(try, sizeof(try), "%s/%s", dir, q->name); - if (make_preserve_name(bup, sizeof(bup), name, try) && fexists(bup)) { -#if HAVE_CHFLAGS - (void) chflags(try, 0); -#endif - (void) unlink(try); - if (rename(bup, try)) - warnx("rollback: unable to rename %s back to %s", bup, try); - } - } else if (q->type == PLIST_CWD) { - if (strcmp(q->name, ".")) - dir = q->name; - else - dir = home; - } - } -} - - -/* - * Return 0 on error, 1 for success. - */ -int -extract_plist(char *home, package_t *pkg) -{ - plist_t *p = pkg->head; - char *last_file; - char *last_chdir; - Boolean preserve; - lfile_t *lfp; - - TAILQ_INIT(&files); - TAILQ_INIT(&perms); - - last_chdir = 0; - preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE; - - /* Reset the world */ - Owner = NULL; - Group = NULL; - Mode = NULL; - last_file = NULL; - Directory = home; - - if (!NoRecord) { - /* Open Package Database for writing */ - if (!pkgdb_open(ReadWrite)) { - cleanup(0); - err(EXIT_FAILURE, "can't open pkgdb"); - } - } - /* Do it */ - while (p) { - char cmd[MaxPathSize]; - - switch (p->type) { - case PLIST_NAME: - PkgName = p->name; - if (Verbose) - printf("extract: Package name is %s\n", p->name); - break; - - case PLIST_FILE: - last_file = p->name; - if (Verbose) - printf("extract: %s/%s\n", Directory, p->name); - if (!Fake) { - char try[MaxPathSize]; - - if (strrchr(p->name, '\'')) { - cleanup(0); - errx(2, "Bogus filename \"%s\"", p->name); - } - - /* first try to rename it into place */ - (void) snprintf(try, sizeof(try), "%s/%s", Directory, p->name); - if (fexists(try)) { -#if HAVE_CHFLAGS - (void) chflags(try, 0); /* XXX hack - if truly immutable, rename fails */ -#endif - if (preserve && PkgName) { - char pf[MaxPathSize]; - - if (make_preserve_name(pf, sizeof(pf), PkgName, try)) { - if (rename(try, pf)) { - warnx( - "unable to back up %s to %s, aborting pkg_add", - try, pf); - rollback(PkgName, home, pkg->head, p); - return 0; - } - } - } - } - if (rename(p->name, try) == 0) { - if (!NoRecord) { - /* note in pkgdb */ - char *s, t[MaxPathSize]; - int rc; - - (void) snprintf(t, sizeof(t), "%s/%s", Directory, p->name); - - s = pkgdb_retrieve(t); -#ifdef PKGDB_DEBUG - printf("pkgdb_retrieve(\"%s\")=\"%s\"\n", t, s); /* pkgdb-debug - HF */ -#endif - if (s) - warnx("Overwriting %s - pkg %s bogus/conflicting?", t, s); - else { - rc = pkgdb_store(t, PkgName); -#ifdef PKGDB_DEBUG - printf("pkgdb_store(\"%s\", \"%s\") = %d\n", t, PkgName, rc); /* pkgdb-debug - HF */ -#endif - - } - } - - /* try to add to list of perms to be changed and run in bulk. */ - if (p->name[0] == '/') - pushout(Directory); - - LFILE_ADD(&perms, lfp, p->name); - } else { - /* rename failed, try copying with a big tar command */ - if (last_chdir != Directory) { - if (last_chdir != NULL) - pushout(last_chdir); - last_chdir = Directory; - } else if (p->name[0] == '/') { - pushout(Directory); - } - - if (!NoRecord) { - /* note in pkgdb */ - /* XXX would be better to store in PUSHOUT, but - * that would probably affect too much code I prefer - * not to touch - HF */ - - char *s, t[MaxPathSize]; - int rc; - - LFILE_ADD(&files, lfp, p->name); - LFILE_ADD(&perms, lfp, p->name); - if (p->name[0] == '/') - errx(EXIT_FAILURE, "File names must not be absolute (%s).", p->name); - else { - (void) snprintf(t, sizeof(t), "%s/%s", Directory, p->name); - } - - s = pkgdb_retrieve(t); -#ifdef PKGDB_DEBUG - printf("pkgdb_retrieve(\"%s\")=\"%s\"\n", t, s); /* pkgdb-debug - HF */ -#endif - if (s) - warnx("Overwriting %s - pkg %s bogus/conflicting?", t, s); - else { - rc = pkgdb_store(t, PkgName); -#ifdef PKGDB_DEBUG - printf("pkgdb_store(\"%s\", \"%s\") = %d\n", t, PkgName, rc); /* pkgdb-debug - HF */ -#endif - } - } - } - } - break; - - case PLIST_CWD: - if (Verbose) - printf("extract: CWD to %s\n", p->name); - pushout(Directory); - if (strcmp(p->name, ".")) { - if (!Fake && make_hierarchy(p->name) == FAIL) { - cleanup(0); - errx(2, "unable to make directory '%s'", p->name); - } - Directory = p->name; - } else - Directory = home; - break; - - case PLIST_CMD: - format_cmd(cmd, sizeof(cmd), p->name, Directory, last_file); - pushout(Directory); - printf("Executing '%s'\n", cmd); - if (!Fake && system(cmd)) - warnx("command '%s' failed", cmd); - break; - - case PLIST_CHMOD: - pushout(Directory); - Mode = p->name; - break; - - case PLIST_CHOWN: - pushout(Directory); - Owner = p->name; - break; - - case PLIST_CHGRP: - pushout(Directory); - Group = p->name; - break; - - case PLIST_COMMENT: - break; - - case PLIST_IGNORE: - p = p->next; - break; - - default: - break; - } - p = p->next; - } - pushout(Directory); - if (!NoRecord) - pkgdb_close(); - return 1; -} diff --git a/pkgtools/pkg_install/files/add/futil.c b/pkgtools/pkg_install/files/add/futil.c deleted file mode 100644 index ee4c2984fd3..00000000000 --- a/pkgtools/pkg_install/files/add/futil.c +++ /dev/null @@ -1,151 +0,0 @@ -/* $NetBSD: futil.c,v 1.11 2008/04/26 17:40:01 joerg Exp $ */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include <nbcompat.h> -#if HAVE_SYS_CDEFS_H -#include <sys/cdefs.h> -#endif -#ifndef lint -#if 0 -static const char *rcsid = "from FreeBSD Id: futil.c,v 1.7 1997/10/08 07:45:39 charnier Exp"; -#else -__RCSID("$NetBSD: futil.c,v 1.11 2008/04/26 17:40:01 joerg Exp $"); -#endif -#endif - -/* - * FreeBSD install - a package for the installation and maintainance - * of non-core utilities. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Jordan K. Hubbard - * 18 July 1993 - * - * Miscellaneous file access utilities. - * - */ - -#if HAVE_ERR_H -#include <err.h> -#endif -#include "lib.h" -#include "add.h" - -/* - * Assuming dir is a desired directory name, make it and all intervening - * directories necessary. - */ -int -make_hierarchy(char *dir) -{ - char *cp1, *cp2; - char *argv[2]; - - argv[0] = dir; - argv[1] = NULL; - - if (dir[0] == '/') - cp1 = cp2 = dir + 1; - else - cp1 = cp2 = dir; - while (cp2) { - if ((cp2 = strchr(cp1, '/')) != NULL) - *cp2 = '\0'; - if (fexists(dir)) { - if (!(isdir(dir) || islinktodir(dir))) - return FAIL; - } else { - if (fexec("mkdir", dir, NULL)) - return FAIL; - apply_perms(NULL, argv, 1); - } - /* Put it back */ - if (cp2) { - *cp2 = '/'; - cp1 = cp2 + 1; - } - } - return SUCCESS; -} - -/* - * Using permission defaults, apply them as necessary - */ -void -apply_perms(char *dir, char **args, int nargs) -{ - char *cd_to; - char owner_group[128]; - const char **argv; - int i; - - argv = malloc((nargs + 4) * sizeof(char *)); - /* - * elements 0..2 are set later depending on Mode. - * args is a NULL terminated list of file names. - * by appending them to argv, argv becomes NULL terminated also. - */ - for (i = 0; i <= nargs; i++) - argv[i + 3] = args[i]; - - if (!dir || args[0][0] == '/') /* absolute path? */ - cd_to = "/"; - else - cd_to = dir; - - if (Mode) { - argv[0] = CHMOD_CMD; - argv[1] = "-R"; - argv[2] = Mode; - if (pfcexec(cd_to, argv[0], argv)) - warnx("couldn't change modes of '%s' ... to '%s'", - args[0], Mode); - } - if (Owner != NULL && Group != NULL) { - if (snprintf(owner_group, sizeof(owner_group), - "%s:%s", Owner, Group) > sizeof(owner_group)) { - warnx("'%s:%s' is too long (%lu max)", - Owner, Group, (unsigned long) sizeof(owner_group)); - free(argv); - return; - } - argv[0] = CHOWN_CMD; - argv[1] = "-R"; - argv[2] = owner_group; - if (pfcexec(cd_to, argv[0], argv)) - warnx("couldn't change owner/group of '%s' ... to '%s:%s'", - args[0], Owner, Group); - free(argv); - return; - } - if (Owner != NULL) { - argv[0] = CHOWN_CMD; - argv[1] = "-R"; - argv[2] = Owner; - if (pfcexec(cd_to, argv[0], argv)) - warnx("couldn't change owner of '%s' ... to '%s'", - args[0], Owner); - free(argv); - - return; - } - if (Group != NULL) { - argv[0] = CHGRP_CMD; - argv[1] = "-R"; - argv[2] = Group; - if (pfcexec(cd_to, argv[0], argv)) - warnx("couldn't change group of '%s' ... to '%s'", - args[0], Group); - } - free(argv); -} diff --git a/pkgtools/pkg_install/files/add/main.c b/pkgtools/pkg_install/files/add/main.c index 0a722e9b168..4f8280cbcca 100644 --- a/pkgtools/pkg_install/files/add/main.c +++ b/pkgtools/pkg_install/files/add/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.16 2008/04/26 17:40:01 joerg Exp $ */ +/* $NetBSD: main.c,v 1.17 2009/02/02 12:35:00 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,13 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -#if 0 -static char *rcsid = "from FreeBSD Id: main.c,v 1.16 1997/10/08 07:45:43 charnier Exp"; -#else -__RCSID("$NetBSD: main.c,v 1.16 2008/04/26 17:40:01 joerg Exp $"); -#endif -#endif +__RCSID("$NetBSD: main.c,v 1.17 2009/02/02 12:35:00 joerg Exp $"); /* * @@ -47,10 +41,10 @@ __RCSID("$NetBSD: main.c,v 1.16 2008/04/26 17:40:01 joerg Exp $"); #endif #include "lib.h" #include "add.h" -#include "verify.h" -static char Options[] = "AIK:LRVW:fhm:np:s:t:uvw:"; +static char Options[] = "AIK:LP:RVW:fhm:np:t:uvw:"; +char *Destdir = NULL; char *OverrideMachine = NULL; char *Prefix = NULL; char *View = NULL; @@ -60,20 +54,15 @@ Boolean NoInstall = FALSE; Boolean NoRecord = FALSE; Boolean Automatic = FALSE; -char *Mode = NULL; -char *Owner = NULL; -char *Group = NULL; -char *PkgName = NULL; -char *Directory = NULL; -char FirstPen[MaxPathSize]; int Replace = 0; static void usage(void) { - (void) fprintf(stderr, "%s\n%s\n%s\n", - "usage: pkg_add [-AfhILnRuVv] [-K pkg_dbdir] [-m machine] [-p prefix]", - " [-s verification-type] [-t template] [-W viewbase] [-w view]", + (void) fprintf(stderr, "%s\n%s\n%s\n%s\n", + "usage: pkg_add [-AfhILnRuVv] [-C config] [-P destdir] [-K pkg_dbdir]", + " [-m machine] [-p prefix] [-s verification-type", + " [-W viewbase] [-w view]\n", " [[ftp|http]://[user[:password]@]host[:port]][/path/]pkg-name ..."); exit(1); } @@ -83,8 +72,6 @@ main(int argc, char **argv) { int ch, error=0; lpkg_head_t pkgs; - struct rlimit rlim; - int rc; setprogname(argv[0]); while ((ch = getopt(argc, argv, Options)) != -1) { @@ -93,6 +80,13 @@ main(int argc, char **argv) Automatic = TRUE; break; + case 'C': + config_file = optarg; + + case 'P': + Destdir = optarg; + break; + case 'f': Force = TRUE; break; @@ -126,14 +120,6 @@ main(int argc, char **argv) Prefix = optarg; break; - case 's': - set_verification(optarg); - break; - - case 't': - strlcpy(FirstPen, optarg, sizeof(FirstPen)); - break; - case 'u': Replace++; break; @@ -164,6 +150,8 @@ main(int argc, char **argv) argc -= optind; argv += optind; + pkg_install_config(); + path_create(getenv("PKG_PATH")); TAILQ_INIT(&pkgs); @@ -184,22 +172,6 @@ main(int argc, char **argv) TAILQ_INSERT_TAIL(&pkgs, lpp, lp_link); } - - /* Increase # of max. open file descriptors as high as possible */ - /* XXX: Why is this necessary? */ - rc = getrlimit(RLIMIT_NOFILE, &rlim); - if (rc == -1) { - warn("cannot retrieve max. number of open files resource limit"); - } else { - rlim.rlim_cur = rlim.rlim_max; - rc = setrlimit(RLIMIT_NOFILE, &rlim); - if (rc == -1) { - warn("cannot increase max. number of open files resource limit, try 'ulimit'"); - } else { - if (Verbose) - printf("increasing RLIMIT_NOFILE to max. %ld open files\n", (long)rlim.rlim_cur); - } - } error += pkg_perform(&pkgs); if (error != 0) { diff --git a/pkgtools/pkg_install/files/add/perform.c b/pkgtools/pkg_install/files/add/perform.c index b2a178557a3..5a2d09f98de 100644 --- a/pkgtools/pkg_install/files/add/perform.c +++ b/pkgtools/pkg_install/files/add/perform.c @@ -1,5 +1,4 @@ -/* $NetBSD: perform.c,v 1.73 2008/09/17 15:21:30 joerg Exp $ */ - +/* $NetBSD: perform.c,v 1.74 2009/02/02 12:35:00 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" #endif @@ -7,1045 +6,1427 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#if HAVE_SYS_QUEUE_H -#include <sys/queue.h> -#endif -#ifndef lint -#if 0 -static const char *rcsid = "from FreeBSD Id: perform.c,v 1.44 1997/10/13 15:03:46 jkh Exp"; -#else -__RCSID("$NetBSD: perform.c,v 1.73 2008/09/17 15:21:30 joerg Exp $"); -#endif -#endif - -/* - * FreeBSD install - a package for the installation and maintainance - * of non-core utilities. +__RCSID("$NetBSD: perform.c,v 1.74 2009/02/02 12:35:00 joerg Exp $"); + +/*- + * Copyright (c) 2003 Grant Beattie <grant@NetBSD.org> + * Copyright (c) 2005 Dieter Baron <dillo@NetBSD.org> + * Copyright (c) 2007 Roland Illig <rillig@NetBSD.org> + * Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org> + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Jordan K. Hubbard - * 18 July 1993 - * - * This is the main body of the add module. + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ -#if HAVE_ASSERT_H -#include <assert.h> -#endif +#include <sys/utsname.h> #if HAVE_ERR_H #include <err.h> #endif -#if HAVE_ERRNO_H #include <errno.h> -#endif -#include "defs.h" +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <archive.h> +#include <archive_entry.h> + #include "lib.h" #include "add.h" -#include "verify.h" -#if HAVE_INTTYPES_H -#include <inttypes.h> -#endif -#if HAVE_SIGNAL_H -#include <signal.h> -#endif -#if HAVE_STRING_H -#include <string.h> -#endif -#if HAVE_STDLIB_H -#include <stdlib.h> -#endif -#if HAVE_SYS_UTSNAME_H -#include <sys/utsname.h> -#endif +struct pkg_meta { + char *meta_contents; + char *meta_comment; + char *meta_desc; + char *meta_mtree; + char *meta_build_version; + char *meta_build_info; + char *meta_size_pkg; + char *meta_size_all; + char *meta_required_by; + char *meta_display; + char *meta_install; + char *meta_deinstall; + char *meta_preserve; + char *meta_views; + char *meta_installed_info; +}; + +struct pkg_task { + char *pkgname; + + const char *prefix; + char *install_prefix; + + char *logdir; + char *install_logdir; + char *other_version; + + package_t plist; -static char LogDir[MaxPathSize]; -static int zapLogDir; /* Should we delete LogDir? */ + struct pkg_meta meta_data; -static package_t Plist; -static char *Home; + struct archive *archive; + struct archive_entry *entry; -static lfile_head_t files; + char *buildinfo[BI_ENUM_COUNT]; -/* used in build information */ -enum { - Good, - Missing, - Warning, - Fatal + size_t dep_length, dep_allocated; + char **dependencies; }; -static void -normalise_platform(struct utsname *host_name) -{ -#ifdef NUMERIC_VERSION_ONLY - size_t span; +static const struct pkg_meta_desc { + size_t entry_offset; + const char *entry_filename; + int required_file; + mode_t perm; +} pkg_meta_descriptors[] = { + { offsetof(struct pkg_meta, meta_contents), CONTENTS_FNAME, 1, 0644 }, + { offsetof(struct pkg_meta, meta_comment), COMMENT_FNAME, 1, 0444}, + { offsetof(struct pkg_meta, meta_desc), DESC_FNAME, 1, 0444}, + { offsetof(struct pkg_meta, meta_install), INSTALL_FNAME, 0, 0555 }, + { offsetof(struct pkg_meta, meta_deinstall), DEINSTALL_FNAME, 0, 0555 }, + { offsetof(struct pkg_meta, meta_display), DISPLAY_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_mtree), MTREE_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_build_version), BUILD_VERSION_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_build_info), BUILD_INFO_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_size_pkg), SIZE_PKG_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_size_all), SIZE_ALL_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_preserve), PRESERVE_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_views), VIEWS_FNAME, 0, 0444 }, + { offsetof(struct pkg_meta, meta_required_by), REQUIRED_BY_FNAME, 0, 0644 }, + { offsetof(struct pkg_meta, meta_installed_info), INSTALLED_INFO_FNAME, 0, 0644 }, + { 0, NULL, 0 }, +}; - span = strspn(host_name->release, "0123456789."); - host_name->release[span] = '\0'; -#endif -} +static int pkg_do(const char *, int); -/* Read package build information */ static int -read_buildinfo(char **buildinfo) +mkdir_p(const char *path) { - char *key; - char *line; - size_t len; - FILE *fp; + char *p, *cur_end; + int done; - if ((fp = fopen(BUILD_INFO_FNAME, "r")) == NULL) { - warnx("unable to open %s file.", BUILD_INFO_FNAME); + /* + * Handle the easy case of direct success or + * pre-existing directory first. + */ + if (mkdir(path, 0777) == 0 || errno == EEXIST) return 0; - } + if (errno != ENOENT) + return -1; - while ((line = fgetln(fp, &len)) != NULL) { - if (line[len - 1] == '\n') - line[len - 1] = '\0'; + cur_end = p = xstrdup(path); - if ((key = strsep(&line, "=")) == NULL) - continue; + for (;;) { + /* + * First skip leading slashes either from / or + * from the last iteration. + */ + cur_end += strspn(cur_end, "/"); + /* Find end of actual directory name. */ + cur_end += strcspn(cur_end, "/"); /* - * pkgsrc used to create the BUILDINFO file using - * "key= value", so skip the space if it's there. + * Remember if this is the last component and + * overwrite / if needed. */ - if (line == NULL) - continue; - if (line[0] == ' ') - line += sizeof(char); + done = (*cur_end == '\0'); + *cur_end = '\0'; /* - * we only care about opsys, arch, version, and - * dependency recommendations + * ENOENT can only happen if something else races us, + * in which case we should better give up. */ - if (line[0] != '\0') { - if (strcmp(key, "OPSYS") == 0) - buildinfo[BI_OPSYS] = strdup(line); - else if (strcmp(key, "OS_VERSION") == 0) - buildinfo[BI_OS_VERSION] = strdup(line); - else if (strcmp(key, "MACHINE_ARCH") == 0) - buildinfo[BI_MACHINE_ARCH] = strdup(line); - else if (strcmp(key, "IGNORE_RECOMMENDED") == 0) - buildinfo[BI_IGNORE_RECOMMENDED] = strdup(line); - else if (strcmp(key, "USE_ABI_DEPENDS") == 0) - buildinfo[BI_USE_ABI_DEPENDS] = strdup(line); + if (mkdir(p, 0777) == -1 && errno != EEXIST) { + free(p); + return -1; } + if (done) + break; + *cur_end = '/'; } - (void) fclose(fp); - if (buildinfo[BI_OPSYS] == NULL || - buildinfo[BI_OS_VERSION] == NULL || - buildinfo[BI_MACHINE_ARCH] == NULL) { - warnx("couldn't extract build information from package."); - return 0; + + free(p); + return 0; +} + +/* + * Read meta data from archive. + * Bail out if a required entry is missing or entries are in the wrong order. + */ +static int +read_meta_data(struct pkg_task *pkg) +{ + const struct pkg_meta_desc *descr, *last_descr; + const char *fname; + char **target; + int64_t size; + int r, found_required; + + found_required = 0; + + r = ARCHIVE_OK; + last_descr = 0; + + if (pkg->entry != NULL) + goto skip_header; + + for (;;) { + r = archive_read_next_header(pkg->archive, &pkg->entry); + if (r != ARCHIVE_OK) + break; +skip_header: + fname = archive_entry_pathname(pkg->entry); + + for (descr = pkg_meta_descriptors; descr->entry_filename; + ++descr) { + if (strcmp(descr->entry_filename, fname) == 0) + break; + } + if (descr->entry_filename == NULL) + break; + + if (descr->required_file) + ++found_required; + + target = (char **)((char *)&pkg->meta_data + + descr->entry_offset); + if (*target) { + warnx("duplicate entry, package corrupt"); + return -1; + } + if (descr < last_descr) { + warnx("misordered package"); + return -1; + } + last_descr = descr; + + size = archive_entry_size(pkg->entry); + if (size > SSIZE_MAX - 1) { + warnx("package meta data too large to process"); + return -1; + } + *target = xmalloc(size + 1); + if (archive_read_data(pkg->archive, *target, size) != size) { + warnx("cannot read package meta data"); + return -1; + } + (*target)[size] = '\0'; + } + + if (r != ARCHIVE_OK) + pkg->entry = NULL; + if (r == ARCHIVE_EOF) + r = ARCHIVE_OK; + + for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { + if (descr->required_file) + --found_required; + } + + return !found_required && r == ARCHIVE_OK ? 0 : -1; +} + +/* + * Free meta data. + */ +static void +free_meta_data(struct pkg_task *pkg) +{ + const struct pkg_meta_desc *descr; + char **target; + + for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { + target = (char **)((char *)&pkg->meta_data + + descr->entry_offset); + free(*target); + *target = NULL; } - return 1; } +/* + * Parse PLIST and populate pkg. + */ static int -sanity_check(const char *pkg) +pkg_parse_plist(struct pkg_task *pkg) { - int errc = 0; - - if (!fexists(CONTENTS_FNAME)) { - warnx("package %s has no CONTENTS file!", pkg); - errc = 1; - } else if (!fexists(COMMENT_FNAME)) { - warnx("package %s has no COMMENT file!", pkg); - errc = 1; - } else if (!fexists(DESC_FNAME)) { - warnx("package %s has no DESC file!", pkg); - errc = 1; + plist_t *p; + + parse_plist(&pkg->plist, pkg->meta_data.meta_contents); + if ((p = find_plist(&pkg->plist, PLIST_NAME)) == NULL) { + warnx("Invalid PLIST: missing @name"); + return -1; } - return errc; + if (pkg->pkgname == NULL) + pkg->pkgname = xstrdup(p->name); + else if (strcmp(pkg->pkgname, p->name) != 0) { + warnx("Signature and PLIST differ on package name"); + return -1; + } + if ((p = find_plist(&pkg->plist, PLIST_CWD)) == NULL) { + warnx("Invalid PLIST: missing @cwd"); + return -1; + } + + if (Prefix != NULL && + strcmp(p->name, Prefix) != 0) { + size_t len; + + delete_plist(&pkg->plist, FALSE, PLIST_CWD, NULL); + add_plist_top(&pkg->plist, PLIST_CWD, Prefix); + free(pkg->meta_data.meta_contents); + stringify_plist(&pkg->plist, &pkg->meta_data.meta_contents, &len, + Prefix); + pkg->prefix = Prefix; + } else + pkg->prefix = p->name; + + if (Destdir != NULL) + pkg->install_prefix = xasprintf("%s/%s", Destdir, pkg->prefix); + else + pkg->install_prefix = xstrdup(pkg->prefix); + + return 0; +} + +/* + * Helper function to extract value from a string of the + * form key=value ending at eol. + */ +static char * +dup_value(const char *line, const char *eol) +{ + const char *key; + char *val; + + key = strchr(line, '='); + val = xmalloc(eol - key); + memcpy(val, key + 1, eol - key - 1); + val[eol - key - 1] = '\0'; + return val; } -/* install a pre-requisite package. Returns 1 if it installed it */ static int -installprereq(const char *name, int *errc, int doupdate) +check_already_installed(struct pkg_task *pkg) { - int ret; - ret = 0; + char *filename; + int fd; - if (Verbose) - printf("Loading it from %s.\n", name); - path_setenv("PKG_PATH"); - - if (fexec_skipempty(BINDIR "/pkg_add", "-K", _pkgdb_getPKGDB_DIR(), - "-s", get_verification(), - doupdate > 1 ? "-uu" : (doupdate ? "-u" : ""), - Fake ? "-n" : "", - NoView ? "-L" : "", - View ? "-w" : "", View ? View : "", - Viewbase ? "-W" : "", Viewbase ? Viewbase : "", - Force ? "-f" : "", - Prefix ? "-p" : "", Prefix ? Prefix : "", - Verbose ? "-v" : "", - OverrideMachine ? "-m" : "", - OverrideMachine ? OverrideMachine : "", - NoInstall ? "-I" : "", - "-A", name, NULL)) { - warnx("autoload of dependency `%s' failed%s", - name, Force ? " (proceeding anyway)" : "!"); - if (!Force) - ++(*errc); + if (Force) + return -1; + + filename = pkgdb_pkg_file(pkg->pkgname, CONTENTS_FNAME); + fd = open(filename, O_RDONLY); + free(filename); + if (fd == -1) + return -1; + + /* We can only arrive here for explicitly requested packages. */ + if (!Automatic && is_automatic_installed(pkg->pkgname)) { + if (Fake || + mark_as_automatic_installed(pkg->pkgname, 0) == 0) + warnx("package `%s' was already installed as " + "dependency, now marked as installed " + "manually", pkg->pkgname); } else { - ret = 1; + warnx("package `%s' already recorded as installed", + pkg->pkgname); } + return 0; - return ret; } static int -pkg_do_installed(int *replacing, char replace_via[MaxPathSize], char replace_to[MaxPathSize], - Boolean is_depoted_pkg, const char *dbdir) +check_other_installed(struct pkg_task *pkg) { - char replace_from[MaxPathSize]; - char *s; - char buf[MaxPathSize]; - char *best_installed; + FILE *f, *f_pkg; + size_t len; + char *pkgbase, *iter, *filename; + package_t plist; + plist_t *p; + int status; - const size_t replace_via_size = MaxPathSize; - const size_t replace_to_size = MaxPathSize; + pkgbase = xstrdup(pkg->pkgname); - if ((s = strrchr(PkgName, '-')) == NULL) { - warnx("Package name %s does not contain a version, bailing out", PkgName); + if ((iter = strrchr(pkgbase, '-')) == NULL) { + free(pkgbase); + warnx("Invalid package name %s", pkg->pkgname); return -1; } - - /* - * See if the pkg is already installed. If so, we might want to - * upgrade/replace it. Otherwise, just return and let pkg_do work. - */ - (void) snprintf(buf, sizeof(buf), "%.*s[0-9]*", - (int)(s - PkgName) + 1, PkgName); - best_installed = find_best_matching_installed_pkg(buf); - if (best_installed == NULL) + *iter = '\0'; + pkg->other_version = find_best_matching_installed_pkg(pkgbase); + free(pkgbase); + if (pkg->other_version == NULL) return 0; - if (!Replace || Fake) { - if (is_depoted_pkg) { - free(best_installed); - return 0; - } else { - warnx("other version '%s' already installed", best_installed); - free(best_installed); - return 1; /* close enough for government work */ - } + if (!Replace) { + /* XXX This is redundant to the implicit conflict check. */ + warnx("A different version of %s is already installed: %s", + pkg->pkgname, pkg->other_version); + return -1; } - /* XXX Should list the steps in Fake mode */ - snprintf(replace_from, sizeof(replace_from), "%s/%s/" REQUIRED_BY_FNAME, - dbdir, best_installed); - snprintf(replace_via, replace_via_size, "%s/.%s." REQUIRED_BY_FNAME, - dbdir, best_installed); - snprintf(replace_to, replace_to_size, "%s/%s/" REQUIRED_BY_FNAME, - dbdir, PkgName); - - if (Verbose) - printf("Upgrading %s to %s.\n", best_installed, PkgName); + filename = pkgdb_pkg_file(pkg->other_version, REQUIRED_BY_FNAME); + errno = 0; + f = fopen(filename, "r"); + free(filename); + if (f == NULL) { + if (errno == ENOENT) { + /* No packages depend on this, so everything is well. */ + return 0; + } + warnx("Can't open +REQUIRED_BY of %s", pkg->other_version); + return -1; + } - if (fexists(replace_from)) { /* Are there any dependencies? */ - /* - * Upgrade step 1/4: Check if the new version is ok with all pkgs - * (from +REQUIRED_BY) that require this pkg - */ - FILE *rb; /* +REQUIRED_BY file */ - char pkg2chk[MaxPathSize]; - - rb = fopen(replace_from, "r"); - if (! rb) { - warnx("Cannot open '%s' for reading%s", replace_from, - Force ? " (proceeding anyways)" : ""); - if (Force) - goto ignore_replace_depends_check; - else - return -1; + status = 0; + + while ((iter = fgetln(f, &len)) != NULL) { + if (iter[len - 1] == '\n') + iter[len - 1] = '\0'; + filename = pkgdb_pkg_file(iter, CONTENTS_FNAME); + if ((f_pkg = fopen(filename, "r")) == NULL) { + warnx("Can't open +CONTENTS of depending package %s", + iter); + fclose(f); + return -1; } - while (fgets(pkg2chk, sizeof(pkg2chk), rb)) { - package_t depPlist; - FILE *depf; - plist_t *depp; - char depC[MaxPathSize]; - - s = strrchr(pkg2chk, '\n'); - if (s) - *s = '\0'; /* strip trailing '\n' */ - - /* - * step into pkg2chk, read it's +CONTENTS file and see if - * all @pkgdep lines agree with PkgName (using pkg_match()) + read_plist(&plist, f_pkg); + fclose(f_pkg); + for (p = plist.head; p != NULL; p = p->next) { + if (p->type == PLIST_IGNORE) { + p = p->next; + continue; + } else if (p->type != PLIST_PKGDEP) + continue; + /* + * XXX This is stricter than necessary. + * XXX One pattern might be fulfilled by + * XXX a different package and still need this + * XXX one for a different pattern. */ - snprintf(depC, sizeof(depC), "%s/%s/%s", dbdir, pkg2chk, CONTENTS_FNAME); - depf = fopen(depC , "r"); - if (depf == NULL) { - warnx("Cannot check depends in '%s'%s", depC, - Force ? " (proceeding anyways)" : "!" ); - if (Force) - goto ignore_replace_depends_check; - else - return -1; - } - read_plist(&depPlist, depf); - fclose(depf); - - for (depp = depPlist.head; depp; depp = depp->next) { - char base_new[MaxPathSize]; - char base_exist[MaxPathSize]; - char *s2; - - if (depp->type != PLIST_PKGDEP) - continue; - - /* - * Prepare basename (no versions) of both pkgs, - * to see if we want to compare against that - * one at all. - */ - strlcpy(base_new, PkgName, sizeof(base_new)); - s2 = strpbrk(base_new, "<>[]?*{"); /* } */ - if (s2) - *s2 = '\0'; - else { - s2 = strrchr(base_new, '-'); - if (s2) - *s2 = '\0'; - } - strlcpy(base_exist, depp->name, sizeof(base_exist)); - s2 = strpbrk(base_exist, "<>[]?*{"); /* } */ - if (s2) - *s2 = '\0'; - else { - s2 = strrchr(base_exist, '-'); - if (s2) - *s2 = '\0'; - } - if (strcmp(base_new, base_exist) == 0) { - /* Same pkg, so do the interesting compare */ - if (pkg_match(depp->name, PkgName)) { - if (Verbose) - printf("@pkgdep check: %s is ok for %s (in %s pkg)\n", - PkgName, depp->name, pkg2chk); - } else { - printf("Package %s requires %s, \n\tCannot replace with %s%s\n", - pkg2chk, depp->name, PkgName, - Force? " (proceeding anyways)" : "!"); - if (! Force) - return -1; - } - } - } + if (pkg_match(p->name, pkg->other_version) == 0) + continue; + if (pkg_match(p->name, pkg->pkgname) == 1) + continue; /* Both match, ok. */ + warnx("Dependency of %s fulfilled by %s, but not by %s", + iter, pkg->other_version, pkg->pkgname); + if (!Force) + status = -1; + break; } - fclose(rb); + free_plist(&plist); + } -ignore_replace_depends_check: - /* - * Upgrade step 2/4: Do the actual update by moving aside - * the +REQUIRED_BY file, deinstalling the old pkg, adding - * the new one and moving the +REQUIRED_BY file back - * into place (finished in step 3/4) - */ - if (Verbose) - printf("mv %s %s\n", replace_from, replace_via); - if (rename(replace_from, replace_via) != 0) - err(EXIT_FAILURE, "renaming \"%s\" to \"%s\" failed", replace_from, replace_via); + fclose(f); - *replacing = 1; - } + return status; +} - if (Verbose) { - printf("%s/pkg_delete -K %s '%s'\n", - BINDIR, dbdir, best_installed); +/* + * Read package build information from meta data. + */ +static int +read_buildinfo(struct pkg_task *pkg) +{ + const char *data, *eol, *next_line; + + data = pkg->meta_data.meta_build_info; + + for (; *data != '\0'; data = next_line) { + if ((eol = strchr(data, '\n')) == NULL) { + eol = data + strlen(data); + next_line = eol; + } else + next_line = eol + 1; + + if (strncmp(data, "OPSYS=", 6) == 0) + pkg->buildinfo[BI_OPSYS] = dup_value(data, eol); + else if (strncmp(data, "OS_VERSION=", 11) == 0) + pkg->buildinfo[BI_OS_VERSION] = dup_value(data, eol); + else if (strncmp(data, "MACHINE_ARCH=", 13) == 0) + pkg->buildinfo[BI_MACHINE_ARCH] = dup_value(data, eol); + else if (strncmp(data, "IGNORE_RECOMMENDED=", 19) == 0) + pkg->buildinfo[BI_IGNORE_RECOMMENDED] = dup_value(data, + eol); + else if (strncmp(data, "USE_ABI_DEPENDS=", 16) == 0) + pkg->buildinfo[BI_USE_ABI_DEPENDS] = dup_value(data, + eol); + } + if (pkg->buildinfo[BI_OPSYS] == NULL || + pkg->buildinfo[BI_OS_VERSION] == NULL || + pkg->buildinfo[BI_MACHINE_ARCH] == NULL) { + warnx("Not all required build information are present."); + return -1; } - fexec(BINDIR "/pkg_delete", "-K", dbdir, best_installed, NULL); - free(best_installed); + if ((pkg->buildinfo[BI_USE_ABI_DEPENDS] != NULL && + strcasecmp(pkg->buildinfo[BI_USE_ABI_DEPENDS], "YES") != 0) || + (pkg->buildinfo[BI_IGNORE_RECOMMENDED] != NULL && + strcasecmp(pkg->buildinfo[BI_IGNORE_RECOMMENDED], "NO") != 0)) { + warnx("%s was built to ignore ABI dependencies", pkg->pkgname); + } return 0; } /* - * Install a single package - * Returns 0 if everything is ok, >0 else + * Free buildinfo. */ -static int -pkg_do(const char *pkg, lpkg_head_t *pkgs) +static void +free_buildinfo(struct pkg_task *pkg) { - char playpen[MaxPathSize]; - char replace_via[MaxPathSize]; - char replace_to[MaxPathSize]; - char *buildinfo[BI_ENUM_COUNT]; - int replacing = 0; - char dbdir[MaxPathSize]; - const char *tmppkg; - FILE *cfile; - int errc, err_prescan; - plist_t *p; - struct stat sb; - struct utsname host_uname; - uint64_t needed; - Boolean is_depoted_pkg = FALSE; - lfile_t *lfp; - int result; - - errc = 0; - zapLogDir = 0; - LogDir[0] = '\0'; - strlcpy(playpen, FirstPen, sizeof(playpen)); - memset(buildinfo, '\0', sizeof(buildinfo)); - - umask(DEF_UMASK); - - tmppkg = fileFindByPath(pkg); - if (tmppkg == NULL) { - warnx("no pkg found for '%s', sorry.", pkg); - return 1; + size_t i; + + for (i = 0; i < BI_ENUM_COUNT; ++i) { + free(pkg->buildinfo[i]); + pkg->buildinfo[i] = NULL; } +} - pkg = tmppkg; +/* + * Write meta data files to pkgdb after creating the directory. + */ +static int +write_meta_data(struct pkg_task *pkg) +{ + const struct pkg_meta_desc *descr; + char *filename, **target; + size_t len; + ssize_t ret; + int fd; - if (IS_URL(pkg)) { - Home = fileGetURL(pkg); - if (Home == NULL) { - warnx("unable to fetch `%s' by URL", pkg); - } + if (Fake) + return 0; - /* make sure the pkg is verified */ - if (!verify(pkg)) { - warnx("Package %s will not be extracted", pkg); - goto bomb; + if (mkdir_p(pkg->install_logdir)) { + warn("Can't create pkgdb entry: %s", pkg->install_logdir); + return -1; + } + + for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { + target = (char **)((char *)&pkg->meta_data + + descr->entry_offset); + if (*target == NULL) + continue; + filename = xasprintf("%s/%s", pkg->install_logdir, + descr->entry_filename); + (void)unlink(filename); + fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, descr->perm); + if (fd == -1) { + warn("Can't open meta data file: %s", filename); + return -1; } - } else { /* local */ - if (!IS_STDIN(pkg)) { - /* not stdin */ - if (!ispkgpattern(pkg)) { - if (stat(pkg, &sb) == FAIL) { - warnx("can't stat package file '%s'", pkg); - goto bomb; - } - /* make sure the pkg is verified */ - if (!verify(pkg)) { - warnx("Package %s will not be extracted", pkg); - goto bomb; - } + len = strlen(*target); + do { + ret = write(fd, *target, len); + if (ret == -1) { + warn("Can't write meta data file: %s", + filename); + free(filename); + return -1; } - LFILE_ADD(&files, lfp, CONTENTS_FNAME); - } else { - /* some values for stdin */ - sb.st_size = 100000; /* Make up a plausible average size */ + len -= ret; + } while (ret > 0); + if (close(fd) == -1) { + warn("Can't close meta data file: %s", filename); + free(filename); + return -1; } - Home = make_playpen(playpen, sizeof(playpen), sb.st_size * 4); - if (!Home) - warnx("unable to make playpen for %ld bytes", - (long) (sb.st_size * 4)); - result = unpack(pkg, &files); - while ((lfp = TAILQ_FIRST(&files)) != NULL) { - TAILQ_REMOVE(&files, lfp, lf_link); - free(lfp); + free(filename); + } + + return 0; +} + +/* + * Helper function for extract_files. + */ +static int +copy_data_to_disk(struct archive *reader, struct archive *writer, + const char *filename) +{ + int r; + const void *buff; + size_t size; + off_t offset; + + for (;;) { + r = archive_read_data_block(reader, &buff, &size, &offset); + if (r == ARCHIVE_EOF) + return 0; + if (r != ARCHIVE_OK) { + warnx("Read error for %s: %s", filename, + archive_error_string(reader)); + return -1; } - if (result) { - warnx("unable to extract table of contents file from `%s' - not a package?", - pkg); - goto bomb; + r = archive_write_data_block(writer, buff, size, offset); + if (r != ARCHIVE_OK) { + warnx("Write error for %s: %s", filename, + archive_error_string(writer)); + return -1; } } +} - cfile = fopen(CONTENTS_FNAME, "r"); - if (!cfile) { - warnx("unable to open table of contents file `%s' - not a package?", - CONTENTS_FNAME); - goto bomb; - } - read_plist(&Plist, cfile); - fclose(cfile); +/* + * Extract package. + * Any misordered, missing or unlisted file in the package is an error. + */ - if (!IS_URL(pkg)) { - /* - * Apply a crude heuristic to see how much space the package will - * take up once it's unpacked. I've noticed that most packages - * compress an average of 75%, so multiply by 4 for good measure. - */ +static const int extract_flags = /* ARCHIVE_EXTRACT_OWNER | */ + ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_UNLINK | + ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR; - needed = 4 * (uint64_t) sb.st_size; - if (min_free(playpen) < needed) { - warnx("projected size of %" MY_PRIu64 " bytes exceeds available free space\n" - "in %s. Please set your PKG_TMPDIR variable to point\n" - "to a location with more free space and try again.", - needed, playpen); - goto bomb; - } +static int +extract_files(struct pkg_task *pkg) +{ + char cmd[MaxPathSize]; + const char *owner, *group, *permissions; + struct archive *writer; + int r; + plist_t *p; + const char *last_file; + char *fullpath; - /* Finally unpack the whole mess */ - if (unpack(pkg, NULL)) { - warnx("unable to extract `%s'!", pkg); - goto bomb; - } + if (Fake) + return 0; + + if (mkdir_p(pkg->install_prefix)) { + warn("Can't create prefix: %s", pkg->install_prefix); + return -1; } - /* Check for sanity */ - if (sanity_check(pkg)) - goto bomb; + if (!NoRecord && !pkgdb_open(ReadWrite)) { + warn("Can't open pkgdb for writing"); + return -1; + } - /* Read the OS, version and architecture from BUILD_INFO file */ - if (!read_buildinfo(buildinfo)) { - warn("can't read build information from %s", BUILD_INFO_FNAME); - if (!Force) { - warnx("aborting."); - goto bomb; - } + if (chdir(pkg->install_prefix) == -1) { + warn("Can't change into prefix: %s", pkg->install_prefix); + return -1; } - if (uname(&host_uname) < 0) { - warnx("uname() failed."); - if (!Force) { - warnx("aborting."); - goto bomb; - } - } else { - int status = Good; + writer = archive_write_disk_new(); + archive_write_disk_set_options(writer, extract_flags); + archive_write_disk_set_standard_lookup(writer); + + owner = NULL; + group = NULL; + permissions = NULL; + last_file = NULL; + + r = -1; + + for (p = pkg->plist.head; p != NULL; p = p->next) { + switch (p->type) { + case PLIST_FILE: + last_file = p->name; + if (pkg->entry == NULL) { + warnx("PLIST entry not in package (%s)", + archive_entry_pathname(pkg->entry)); + goto out; + } + if (strcmp(p->name, archive_entry_pathname(pkg->entry))) { + warnx("PLIST entry and package don't match (%s vs %s)", + p->name, archive_entry_pathname(pkg->entry)); + goto out; + } + fullpath = xasprintf("%s/%s", pkg->prefix, p->name); + pkgdb_store(fullpath, pkg->pkgname); + free(fullpath); + if (Verbose) + printf("%s", p->name); + break; - normalise_platform(&host_uname); + case PLIST_CMD: + if (format_cmd(cmd, sizeof(cmd), p->name, pkg->prefix, last_file)) + return -1; + printf("Executing '%s'\n", cmd); + if (!Fake && system(cmd)) + warnx("command '%s' failed", cmd); /* XXX bail out? */ + continue; - /* check that we have read some values from buildinfo */ - if (buildinfo[BI_OPSYS] == NULL) { - warnx("Missing operating system value from build information"); - status = Missing; - } - if (buildinfo[BI_MACHINE_ARCH] == NULL) { - warnx("Missing machine architecture value from build information"); - status = Missing; - } - if (buildinfo[BI_OS_VERSION] == NULL) { - warnx("Missing operating system version value from build information"); - status = Missing; + case PLIST_CHMOD: + permissions = p->name; + continue; + + case PLIST_CHOWN: + owner = p->name; + continue; + + case PLIST_CHGRP: + group = p->name; + continue; + + case PLIST_IGNORE: + p = p->next; + continue; + + default: + continue; } - if (status == Good) { - const char *effective_arch; - - if (OverrideMachine != NULL) - effective_arch = OverrideMachine; - else - effective_arch = MACHINE_ARCH; - - /* If either the OS or arch are different, bomb */ - if (strcmp(OPSYS_NAME, buildinfo[BI_OPSYS]) != 0) - status = Fatal; - if (strcmp(effective_arch, buildinfo[BI_MACHINE_ARCH]) != 0) - status = Fatal; - - /* If OS and arch are the same, warn if version differs */ - if (status == Good && - strcmp(host_uname.release, buildinfo[BI_OS_VERSION]) != 0) - status = Warning; - - if (status != Good) { - warnx("Warning: package `%s' was built for a different version of the OS:", pkg); - warnx("%s/%s %s (pkg) vs. %s/%s %s (this host)", - buildinfo[BI_OPSYS], - buildinfo[BI_MACHINE_ARCH], - buildinfo[BI_OS_VERSION], - OPSYS_NAME, - effective_arch, - host_uname.release); - } + r = archive_write_header(writer, pkg->entry); + if (r != ARCHIVE_OK) { + warnx("Failed to write %s: %s", + archive_entry_pathname(pkg->entry), + archive_error_string(writer)); + goto out; } - if (!Force && status == Fatal) { - warnx("aborting."); - goto bomb; + if (owner != NULL) + archive_entry_set_uname(pkg->entry, owner); + if (group != NULL) + archive_entry_set_uname(pkg->entry, group); + if (permissions != NULL) { + mode_t mode; + + mode = archive_entry_mode(pkg->entry); + mode = getmode(setmode(permissions), mode); + archive_entry_set_mode(pkg->entry, mode); } - } - /* Check if USE_ABI_DEPENDS or IGNORE_RECOMMENDED was set - * when this package was built. IGNORE_RECOMMENDED is historical. */ + r = copy_data_to_disk(pkg->archive, writer, + archive_entry_pathname(pkg->entry)); + if (r) + goto out; + if (Verbose) + printf("\n"); - if ((buildinfo[BI_USE_ABI_DEPENDS] != NULL && - strcasecmp(buildinfo[BI_USE_ABI_DEPENDS], "YES") != 0) || - (buildinfo[BI_IGNORE_RECOMMENDED] != NULL && - strcasecmp(buildinfo[BI_IGNORE_RECOMMENDED], "NO") != 0)) { - warnx("%s was built", pkg); - warnx("\tto ignore recommended ABI dependencies, this may cause problems!\n"); + r = archive_read_next_header(pkg->archive, &pkg->entry); + if (r == ARCHIVE_EOF) { + pkg->entry = NULL; + continue; + } + if (r != ARCHIVE_OK) { + warnx("Failed to read from archive: %s", + archive_error_string(pkg->archive)); + goto out; + } } - /* - * If we have a prefix, delete the first one we see and add this - * one in place of it. - */ - if (Prefix) { - delete_plist(&Plist, FALSE, PLIST_CWD, NULL); - add_plist_top(&Plist, PLIST_CWD, Prefix); + if (pkg->entry != NULL) { + warnx("Package contains entries not in PLIST: %s", + archive_entry_pathname(pkg->entry)); + goto out; } - /* Protect against old packages with bogus @name fields */ - p = find_plist(&Plist, PLIST_NAME); - if (p->name == NULL) { - warnx("PLIST contains no @name field"); - goto bomb; - } - PkgName = p->name; + r = 0; - if (fexists(VIEWS_FNAME)) - is_depoted_pkg = TRUE; - - /* - * Depoted packages' dbdir is the same as DEPOTBASE. Non-depoted - * packages' dbdir comes from the command-line or the environment. - */ - if (is_depoted_pkg) { - p = find_plist(&Plist, PLIST_CWD); - if (p == NULL) { - warn("no @cwd in +CONTENTS file?! aborting."); - goto bomb; - } - (void) strlcpy(dbdir, dirname_of(p->name), sizeof(dbdir)); - (void) strlcpy(LogDir, p->name, sizeof(LogDir)); - } else { - (void) strlcpy(dbdir, _pkgdb_getPKGDB_DIR(), sizeof(dbdir)); - (void) snprintf(LogDir, sizeof(LogDir), "%s/%s", dbdir, PkgName); - } +out: + if (!NoRecord) + pkgdb_close(); + archive_write_close(writer); + archive_write_finish(writer); - /* Set environment variables expected by the +INSTALL script. */ - setenv(PKG_PREFIX_VNAME, (p = find_plist(&Plist, PLIST_CWD)) ? p->name : ".", 1); - setenv(PKG_METADATA_DIR_VNAME, LogDir, 1); - setenv(PKG_REFCOUNT_DBDIR_VNAME, pkgdb_refcount_dir(), 1); - - /* make sure dbdir actually exists! */ - if (!(isdir(dbdir) || islinktodir(dbdir))) { - if (fexec("mkdir", "-p", dbdir, NULL)) { - errx(EXIT_FAILURE, - "Database-dir %s cannot be generated, aborting.", - dbdir); - } + return r; +} + +/* + * Register dependencies after sucessfully installing the package. + */ +static void +pkg_register_depends(struct pkg_task *pkg) +{ + int fd; + size_t text_len, i; + char *required_by, *text; + + if (Fake) + return; + + if (pkg->other_version != NULL) + return; /* XXX It's using the old dependencies. */ + + text = xasprintf("%s\n", pkg->pkgname); + text_len = strlen(text); + + for (i = 0; i < pkg->dep_length; ++i) { + required_by = pkgdb_pkg_file(pkg->dependencies[i], REQUIRED_BY_FNAME); + + fd = open(required_by, O_WRONLY | O_APPEND | O_CREAT, 0644); + if (fd == -1) + warn("can't open dependency file '%s'," + "registration is incomplete!", required_by); + else if (write(fd, text, text_len) != text_len) + warn("can't write to dependency file `%s'", required_by); + else if (close(fd) == -1) + warn("cannot close file %s", required_by); + + free(required_by); } - /* See if this package (exact version) is already registered */ - if (isdir(LogDir) && !Force) { - if (!Automatic && is_automatic_installed(PkgName)) { - if (mark_as_automatic_installed(PkgName, 0) == 0) - warnx("package `%s' was already installed as " - "dependency, now marked as installed " - "manually", PkgName); + free(text); +} + +/* + * Reduce the result from uname(3) to a canonical form. + */ +static void +normalise_platform(struct utsname *host_name) +{ +#ifdef NUMERIC_VERSION_ONLY + size_t span; + + span = strspn(host_name->release, "0123456789."); + host_name->release[span] = '\0'; +#endif +} + +/* + * Check build platform of the package against local host. + */ +static int +check_platform(struct pkg_task *pkg) +{ + struct utsname host_uname; + const char *effective_arch; + int fatal; + + if (uname(&host_uname) < 0) { + if (Force) { + warnx("uname() failed, continuing."); + return 0; } else { - warnx("package `%s' already recorded as installed", - PkgName); + warnx("uname() failed, aborting."); + return -1; } - goto success; /* close enough for government work */ } - /* See if some other version of us is already installed */ - switch (pkg_do_installed(&replacing, replace_via, replace_to, is_depoted_pkg, dbdir)) { - case 0: - break; - case 1: - errc = 1; - goto success; - case -1: - goto bomb; + normalise_platform(&host_uname); + + if (OverrideMachine != NULL) + effective_arch = OverrideMachine; + else + effective_arch = MACHINE_ARCH; + + /* If either the OS or arch are different, bomb */ + if (strcmp(OPSYS_NAME, pkg->buildinfo[BI_OPSYS]) || + strcmp(effective_arch, pkg->buildinfo[BI_MACHINE_ARCH]) != 0) + fatal = 1; + else + fatal = 0; + + if (fatal || + strcmp(host_uname.release, pkg->buildinfo[BI_OS_VERSION]) != 0) { + warnx("Warning: package `%s' was built for a platform:", + pkg->pkgname); + warnx("%s/%s %s (pkg) vs. %s/%s %s (this host)", + pkg->buildinfo[BI_OPSYS], + pkg->buildinfo[BI_MACHINE_ARCH], + pkg->buildinfo[BI_OS_VERSION], + OPSYS_NAME, + effective_arch, + host_uname.release); + if (!Force && fatal) + return -1; } + return 0; +} - /* See if there are conflicting packages installed */ - for (p = Plist.head; p; p = p->next) { - char *best_installed; +/* + * Run the install script. + */ +static int +run_install_script(struct pkg_task *pkg, const char *argument) +{ + int ret; + char *filename; + + if (pkg->meta_data.meta_install == NULL || NoInstall) + return 0; + + if (Destdir != NULL) + setenv(PKG_DESTDIR_VNAME, Destdir, 1); + setenv(PKG_PREFIX_VNAME, pkg->prefix, 1); + setenv(PKG_METADATA_DIR_VNAME, pkg->logdir, 1); + setenv(PKG_REFCOUNT_DBDIR_VNAME, pkgdb_refcount_dir(), 1); + + if (Verbose) + printf("Running install with PRE-INSTALL for %s.\n", pkg->pkgname); + if (Fake) + return 0; - if (p->type != PLIST_PKGCFL) + filename = pkgdb_pkg_file(pkg->pkgname, INSTALL_FNAME); + + ret = 0; + errno = 0; + if (fcexec(pkg->install_logdir, filename, pkg->pkgname, argument, + (void *)NULL)) { + if (errno != 0) + warn("exec of install script failed"); + else + warnx("install script returned error status"); + ret = -1; + } + free(filename); + + return ret; +} + +static int +check_explicit_conflict(struct pkg_task *pkg) +{ + char *installed, *installed_pattern; + plist_t *p; + int status; + + status = 0; + + for (p = pkg->plist.head; p != NULL; p = p->next) { + if (p->type == PLIST_IGNORE) { + p = p->next; continue; - if (Verbose) - printf("Package `%s' conflicts with `%s'.\n", PkgName, p->name); - best_installed = find_best_matching_installed_pkg(p->name); - if (best_installed) { + } else if (p->type != PLIST_PKGCFL) + continue; + installed = find_best_matching_installed_pkg(p->name); + if (installed) { warnx("Package `%s' conflicts with `%s', and `%s' is installed.", - PkgName, p->name, best_installed); - free(best_installed); - ++errc; + pkg->pkgname, p->name, installed); + free(installed); + status = -1; } } - /* See if any of the installed packages conflicts with this one. */ - { - char *inst_pkgname, *inst_pattern; + if (some_installed_package_conflicts_with(pkg->pkgname, + pkg->other_version, &installed, &installed_pattern)) { + warnx("Installed package `%s' conflicts with `%s' when trying to install `%s'.", + installed, installed_pattern, pkg->pkgname); + free(installed); + free(installed_pattern); + status = -1; + } + + return status; +} - if (some_installed_package_conflicts_with(PkgName, &inst_pkgname, &inst_pattern)) { - warnx("Installed package `%s' conflicts with `%s' when trying to install `%s'.", - inst_pkgname, inst_pattern, PkgName); - free(inst_pkgname); - free(inst_pattern); - errc++; - } +static int +check_implicit_conflict(struct pkg_task *pkg) +{ + plist_t *p; + char *fullpath, *existing; + int status; + + if (!pkgdb_open(ReadOnly)) { +#if notyet /* XXX empty pkgdb without database? */ + warn("Can't open pkgdb for reading"); + return -1; +#else + return 0; +#endif } - /* Quick pre-check if any conflicting dependencies are installed - * (e.g. version X is installed, but version Y is required) - */ - err_prescan=0; - for (p = Plist.head; p; p = p->next) { - char *best_installed; - - if (p->type != PLIST_PKGDEP) + status = 0; + + for (p = pkg->plist.head; p != NULL; p = p->next) { + if (p->type == PLIST_IGNORE) { + p = p->next; continue; - if (Verbose) - printf("Depends pre-scan: `%s' required.\n", p->name); - best_installed = find_best_matching_installed_pkg(p->name); - if (best_installed == NULL) { - /* - * required pkg not found. look if it's available with a more liberal - * pattern. If so, this will lead to problems later (check on "some - * other version of us is already installed" will fail, see above), - * and we better stop right now. - */ - char *s; - int skip = -1; - - /* doing this right required to parse the full version(s), - * do a 99% solution here for now */ - if (strchr(p->name, '{')) - continue; /* would remove trailing '}' else */ - - if ((s = strpbrk(p->name, "<>")) != NULL) { - skip = 0; - } else if (((s = strstr(p->name, "-[0-9]*")) != NULL) && - (*(s + sizeof("-[0-9]*") - 1) == '\0')) { - /* -[0-9]* already present so no need to */ - /* add it a second time */ - skip = -1; - } else if ((s = strrchr(p->name, '-')) != NULL) { - skip = 1; - } - - if (skip >= 0) { - char buf[MaxPathSize]; - - (void) snprintf(buf, sizeof(buf), - skip ? "%.*s[0-9]*" : "%.*s-[0-9]*", - (int)(s - p->name) + skip, p->name); - best_installed = find_best_matching_installed_pkg(buf); - if (best_installed) { - int done = 0; - - if (Replace > 1) - { - int errc0 = 0; - char tmp[MaxPathSize]; - - warnx("Attempting to update `%s' using binary package\n", p->name); - /* Yes, append .tgz after the version so the */ - /* pattern can match a filename. */ - snprintf(tmp, sizeof(tmp), "%s.tgz", p->name); - done = installprereq(tmp, &errc0, 2); - } - else if (Replace) - { - warnx("To perform necessary upgrades on required packages specify -u twice.\n"); - } - - if (!done) - { - warnx("pkg `%s' required, but `%s' found installed.", - p->name, best_installed); - if (Force) { - warnx("Proceeding anyway."); - } else { - err_prescan++; - } - } - free(best_installed); - } - } - } else { - free(best_installed); + } else if (p->type != PLIST_FILE) + continue; + + fullpath = xasprintf("%s/%s", pkg->prefix, p->name); + existing = pkgdb_retrieve(fullpath); + free(fullpath); + if (existing == NULL) + continue; + if (pkg->other_version != NULL && + strcmp(pkg->other_version, existing) == 0) + continue; + + warnx("Conflicting PLIST with %s: %s", existing, p->name); + if (!Force) { + status = -1; + if (!Verbose) + break; } } - if (err_prescan > 0) { - warnx("Please resolve this conflict!"); - errc += err_prescan; - goto success; /* close enough */ - } - - - /* Now check the packing list for dependencies */ - for (p = Plist.head; p; p = p->next) { - char *best_installed; - - if (p->type != PLIST_PKGDEP) + + pkgdb_close(); + return status; +} + +static int +check_dependencies(struct pkg_task *pkg) +{ + plist_t *p; + char *best_installed; + int status; + size_t i; + + status = 0; + + for (p = pkg->plist.head; p != NULL; p = p->next) { + if (p->type == PLIST_IGNORE) { + p = p->next; + continue; + } else if (p->type != PLIST_PKGDEP) continue; - if (Verbose) - printf("Package `%s' depends on `%s'.\n", PkgName, p->name); best_installed = find_best_matching_installed_pkg(p->name); if (best_installed == NULL) { - /* required pkg not found - need to pull in */ - - if (Fake) { - /* fake install (???) */ - if (Verbose) - printf("Package dependency %s for %s not installed%s\n", p->name, pkg, - Force ? " (proceeding anyway)" : "!"); - } else { - int done = 0; - int errc0 = 0; - - done = installprereq(p->name, &errc0, (Replace > 1) ? 2 : 0); - if (!done && !Force) { - errc += errc0; + /* XXX check cyclic dependencies? */ + if (Fake || NoRecord) { + if (!Force) { + warnx("Missing dependency %s\n", + p->name); + status = -1; + break; } + warnx("Missing dependency %s, continuing", + p->name); + continue; } - } else { - if (Verbose) - printf(" - %s already installed.\n", best_installed); + if (pkg_do(p->name, 1)) { + warnx("Can't install dependency %s", p->name); + status = -1; + break; + } + best_installed = find_best_matching_installed_pkg(p->name); + if (best_installed == NULL && Force) { + warnx("Missing dependency %s ignored", p->name); + continue; + } else if (best_installed == NULL) { + warnx("Just installed dependency %s disappeared", p->name); + status = -1; + break; + } + } + for (i = 0; i < pkg->dep_length; ++i) { + if (strcmp(best_installed, pkg->dependencies[i]) == 0) + break; + } + if (i < pkg->dep_length) { + /* Already used as dependency, so skip it. */ free(best_installed); + continue; } + if (pkg->dep_length + 1 >= pkg->dep_allocated) { + char **tmp; + pkg->dep_allocated = 2 * pkg->dep_allocated + 1; + pkg->dependencies = xrealloc(pkg->dependencies, + pkg->dep_allocated * sizeof(*tmp)); + } + pkg->dependencies[pkg->dep_length++] = best_installed; } - if (errc != 0) - goto bomb; + return status; +} - /* If we're really installing, and have an installation file, run it */ - if (!NoInstall && fexists(INSTALL_FNAME)) { - (void) fexec(CHMOD_CMD, "+x", INSTALL_FNAME, NULL); /* make sure */ - if (Verbose) - printf("Running install with PRE-INSTALL for %s.\n", PkgName); - errno = 0; - if (!Fake && fexec("./" INSTALL_FNAME, PkgName, "PRE-INSTALL", NULL)) { - if (errno != 0) - warn("exec of install script failed"); - else - warnx("install script returned error status"); - errc = 1; - goto success; /* nothing to uninstall yet */ - } +/* + * If this package uses pkg_views, register it in the default view. + */ +static void +pkg_register_views(struct pkg_task *pkg) +{ + if (Fake || NoView || pkg->meta_data.meta_views == NULL) + return; + + if (Verbose) { + printf("%s/pkg_view -d %s %s%s %s%s %sadd %s\n", + BINDIR, _pkgdb_getPKGDB_DIR(), + View ? "-w " : "", View ? View : "", + Viewbase ? "-W " : "", Viewbase ? Viewbase : "", + Verbose ? "-v " : "", pkg->pkgname); } - /* - * Now finally extract the entire show if we're not going direct. - * We need to reset the package dbdir so that extract_plist() - * updates the correct pkgdb.byfile.db database. - */ - if (!Fake) { - _pkgdb_setPKGDB_DIR(dbdir); - if (!extract_plist(".", &Plist)) { - errc = 1; - goto fail; - } + fexec_skipempty(BINDIR "/pkg_view", "-d", _pkgdb_getPKGDB_DIR(), + View ? "-w " : "", View ? View : "", + Viewbase ? "-W " : "", Viewbase ? Viewbase : "", + Verbose ? "-v " : "", "add", pkg->pkgname, + (void *)NULL); +} + +static int +preserve_meta_data_file(struct pkg_task *pkg, const char *name) +{ + char *old_file, *new_file; + int rv; + + if (Fake) + return 0; + + old_file = pkgdb_pkg_file(pkg->other_version, name); + new_file = pkgdb_pkg_file(pkg->pkgname, name); + rv = 0; + if (rename(old_file, new_file) == -1 && errno != ENOENT) { + warn("Can't move %s from %s to %s", name, old_file, new_file); + rv = -1; } + free(old_file); + free(new_file); + return rv; +} - if (!Fake && fexists(MTREE_FNAME)) { - warnx("Mtree file ignored for package %s", PkgName); +static int +start_replacing(struct pkg_task *pkg) +{ + if (preserve_meta_data_file(pkg, REQUIRED_BY_FNAME)) + return -1; + + if (pkg->meta_data.meta_preserve == NULL && + preserve_meta_data_file(pkg, PRESERVE_FNAME)) + return -1; + + if (pkg->meta_data.meta_installed_info == NULL && + preserve_meta_data_file(pkg, INSTALLED_INFO_FNAME)) + return -1; + + if (Verbose || Fake) { + printf("%s/pkg_delete -K %s -p %s%s%s '%s'\n", + BINDIR, _pkgdb_getPKGDB_DIR(), pkg->prefix, + Destdir ? " -P ": "", Destdir ? Destdir : "", + pkg->other_version); } + if (!Fake) + fexec_skipempty(BINDIR "/pkg_delete", "-K", _pkgdb_getPKGDB_DIR(), + "-p", pkg->prefix, + Destdir ? "-P": "", Destdir ? Destdir : "", + pkg->other_version, NULL); - /* Run the installation script one last time? */ - if (!NoInstall && fexists(INSTALL_FNAME)) { - if (Verbose) - printf("Running install with POST-INSTALL for %s.\n", PkgName); - if (!Fake && fexec("./" INSTALL_FNAME, PkgName, "POST-INSTALL", NULL)) { - warnx("install script returned error status"); - errc = 1; - goto fail; - } + /* XXX Check return value and do what? */ + return 0; +} + +static int check_input(const char *line, size_t len) +{ + if (line == NULL || len == 0) + return 1; + switch (*line) { + case 'Y': + case 'y': + case 'T': + case 't': + case '1': + return 0; + default: + return 1; } +} - /* Time to record the deed? */ - if (!NoRecord && !Fake) { - char contents[MaxPathSize]; +static int +check_signature(struct pkg_task *pkg, void *signature_cookie, int invalid_sig) +{ + char *line; + size_t len; - if (!PkgName) { - warnx("no package name! can't record package, sorry"); - errc = 1; - goto success; /* well, partial anyway */ - } - (void) snprintf(LogDir, sizeof(LogDir), "%s/%s", dbdir, PkgName); - zapLogDir = 1; /* LogDir contains something valid now */ - if (Verbose) - printf("Attempting to record package into %s.\n", LogDir); - if (make_hierarchy(LogDir)) { - warnx("can't record package into '%s', you're on your own!", - LogDir); - memset(LogDir, 0, sizeof(LogDir)); - errc = 1; - goto success; /* close enough for government work */ + if (strcasecmp(verified_installation, "never") == 0) + return 0; + if (strcasecmp(verified_installation, "always") == 0) { + if (invalid_sig) + warnx("No valid signature found, rejected"); + return invalid_sig; + } + if (strcasecmp(verified_installation, "trusted") == 0) { + if (!invalid_sig) + return 0; + fprintf(stderr, "No valid signature found for %s.\n", + pkg->pkgname); + fprintf(stderr, + "Do you want to proceed with the installation [y/n]?\n"); + line = fgetln(stdin, &len); + if (check_input(line, len)) { + fprintf(stderr, "Cancelling installation\n"); + return 1; } - /* Make sure pkg_info can read the entry */ - (void) fexec(CHMOD_CMD, "a+rx", LogDir, NULL); - - /* Move all of the +-files into place */ - move_files(".", "+*", LogDir); - - /* Generate the +CONTENTS file in-place from the Plist */ - (void) snprintf(contents, sizeof(contents), "%s/%s", LogDir, CONTENTS_FNAME); - cfile = fopen(contents, "w"); - if (!cfile) { - warnx("can't open new contents file '%s'! can't register pkg", - contents); - goto success; /* can't log, but still keep pkg */ + return 0; + } + if (strcasecmp(verified_installation, "interactive") == 0) { + fprintf(stderr, "Do you want to proceed with " + "the installation of %s [y/n]?\n", pkg->pkgname); + line = fgetln(stdin, &len); + if (check_input(line, len)) { + fprintf(stderr, "Cancelling installation\n"); + return 1; } - write_plist(&Plist, cfile, NULL); - fclose(cfile); - - /* register dependencies */ - /* we could save some cycles here if we remembered what we - * installed above (in case we got a wildcard dependency) */ - /* XXX remembering in p->name would NOT be good! */ - for (p = Plist.head; p; p = p->next) { - if (p->type != PLIST_PKGDEP) - continue; - if (Verbose) - printf("Attempting to record dependency on package `%s'\n", p->name); - (void) snprintf(contents, sizeof(contents), "%s/%s", dbdir, - basename_of(p->name)); - if (ispkgpattern(p->name)) { - char *s; + return 0; + } + warnx("Unknown value of configuration variable VERIFIED_INSTALLATION"); + return 1; +} - s = find_best_matching_installed_pkg(p->name); +static int +check_vulnerable(struct pkg_task *pkg) +{ + static struct pkg_vulnerabilities *pv; + int require_check; + char *line; + size_t len; - if (s == NULL) - errx(EXIT_FAILURE, "Where did our dependency go?!"); + if (strcasecmp(check_vulnerabilities, "never") == 0) + return 0; + else if (strcasecmp(check_vulnerabilities, "always")) + require_check = 1; + else if (strcasecmp(check_vulnerabilities, "interactive")) + require_check = 0; + else { + warnx("Unknown value of the configuration variable" + "CHECK_VULNERABILITIES"); + return 1; + } - (void) snprintf(contents, sizeof(contents), "%s/%s", dbdir, s); - free(s); - } - strlcat(contents, "/", sizeof(contents)); - strlcat(contents, REQUIRED_BY_FNAME, sizeof(contents)); - - cfile = fopen(contents, "a"); - if (!cfile) - warnx("can't open dependency file '%s'!\n" - "dependency registration is incomplete", contents); - else { - fprintf(cfile, "%s\n", PkgName); - if (fclose(cfile) == EOF) - warnx("cannot properly close file %s", contents); - } - } - if (Automatic) - mark_as_automatic_installed(PkgName, 1); - if (Verbose) - printf("Package %s registered in %s\n", PkgName, LogDir); + if (pv == NULL) { + pv = read_pkg_vulnerabilities(pkg_vulnerabilities_file, + require_check, 0); + if (pv == NULL) + return require_check; } - if ((p = find_plist(&Plist, PLIST_DISPLAY)) != NULL) { - FILE *fp; - char buf[BUFSIZ]; - - (void) snprintf(buf, sizeof(buf), "%s/%s", LogDir, p->name); - fp = fopen(buf, "r"); - if (fp) { - putc('\n', stdout); - while (fgets(buf, sizeof(buf), fp)) - fputs(buf, stdout); - putc('\n', stdout); - (void) fclose(fp); - } else - warnx("cannot open %s as display file", buf); + if (!audit_package(pv, pkg->pkgname, NULL, 0, 2)) + return 0; + + if (require_check) + return 1; + + fprintf(stderr, "Do you want to proceed with the installation of %s" + " [y/n]?\n", pkg->pkgname); + line = fgetln(stdin, &len); + if (check_input(line, len)) { + fprintf(stderr, "Cancelling installation\n"); + return 1; + } + return 0; +} + +/* + * Install a single package. + */ +static int +pkg_do(const char *pkgpath, int mark_automatic) +{ + int status, invalid_sig; + void *archive_cookie; + void *signature_cookie; + struct pkg_task *pkg; + + pkg = xcalloc(1, sizeof(*pkg)); + + status = -1; + + if ((pkg->archive = find_archive(pkgpath, &archive_cookie)) == NULL) { + warnx("no pkg found for '%s', sorry.", pkgpath); + goto clean_find_archive; } - /* Add the package to a default view. */ - if (!Fake && !NoView && is_depoted_pkg) { - if (Verbose) { - printf("%s/pkg_view -d %s %s%s %s%s %sadd %s\n", - BINDIR, dbdir, - View ? "-w " : "", View ? View : "", - Viewbase ? "-W " : "", Viewbase ? Viewbase : "", - Verbose ? "-v " : "", PkgName); +#ifdef HAVE_SSL + invalid_sig = pkg_verify_signature(&pkg->archive, &pkg->entry, + &pkg->pkgname, &signature_cookie); +#else + invalid_sig = 1; + signature_cookie = NULL; +#endif + + if (read_meta_data(pkg)) + goto clean_memory; + + /* Parse PLIST early, so that messages can use real package name. */ + if (pkg_parse_plist(pkg)) + goto clean_memory; + + if (check_signature(pkg, &signature_cookie, invalid_sig)) + goto clean_memory; + + if (check_vulnerable(pkg)) + goto clean_memory; + + if (pkg->meta_data.meta_mtree != NULL) + warnx("mtree specification in pkg `%s' ignored", pkg->pkgname); + + if (pkg->meta_data.meta_views != NULL) { + pkg->logdir = xstrdup(pkg->prefix); + _pkgdb_setPKGDB_DIR(dirname_of(pkg->logdir)); + } else { + pkg->logdir = xasprintf("%s/%s", _pkgdb_getPKGDB_DIR(), + pkg->pkgname); + } + + if (Destdir != NULL) { + pkg->install_logdir = xasprintf("%s/%s", Destdir, pkg->logdir); + _pkgdb_setPKGDB_DIR(dirname_of(pkg->install_logdir)); + } else + pkg->install_logdir = xstrdup(pkg->logdir); + + if (NoRecord && !Fake) { + const char *tmpdir; + + tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) + tmpdir = "/tmp"; + + free(pkg->install_logdir); + pkg->install_logdir = xasprintf("%s/pkg_install.XXXXXX", tmpdir); + /* XXX pkg_add -u... */ + if (mkdtemp(pkg->install_logdir) == NULL) { + warn("mkdtemp failed"); + goto clean_memory; } + } - fexec_skipempty(BINDIR "/pkg_view", "-d", dbdir, - View ? "-w " : "", View ? View : "", - Viewbase ? "-W " : "", Viewbase ? Viewbase : "", - Verbose ? "-v " : "", "add", PkgName, NULL); + if (check_already_installed(pkg) == 0) { + status = 0; + goto clean_memory; } - goto success; + if (read_buildinfo(pkg)) + goto clean_memory; -bomb: - errc = 1; - goto success; + if (check_platform(pkg)) + goto clean_memory; -fail: - /* Nuke the whole (installed) show, XXX but don't clean directories */ - if (!Fake) - delete_package(FALSE, FALSE, &Plist, FALSE); + if (check_other_installed(pkg)) + goto clean_memory; -success: - /* delete the packing list contents */ - free_plist(&Plist); - leave_playpen(Home); + if (check_explicit_conflict(pkg)) + goto clean_memory; - if (replacing) { + if (check_implicit_conflict(pkg)) + goto clean_memory; + + if (pkg->other_version != NULL) { /* - * Upgrade step 3/4: move back +REQUIRED_BY file - * (see also step 2/4) + * Replacing an existing package. + * Write meta-data, get rid of the old version, + * install/update dependencies and finally extract. */ - if (rename(replace_via, replace_to) != 0) - err(EXIT_FAILURE, "renaming \"%s\" to \"%s\" failed", replace_via, replace_to); - + if (write_meta_data(pkg)) + goto nuke_pkgdb; + + if (start_replacing(pkg)) + goto nuke_pkgdb; + + if (check_dependencies(pkg)) + goto nuke_pkgdb; + } else { /* - * Upgrade step 4/4: Fix pkgs that depend on us to - * depend on the new version instead of the old - * one by fixing @pkgdep lines in +CONTENTS files. - */ - /* TODO */ + * Normal installation. + * Install/update dependencies first and + * write the current package to disk afterwards. + */ + if (check_dependencies(pkg)) + goto clean_memory; + + if (write_meta_data(pkg)) + goto nuke_pkgdb; } - return errc; -} + if (run_install_script(pkg, "PRE-INSTALL")) + goto nuke_pkgdb; -void -cleanup(int signo) -{ - static int alreadyCleaning; - void (*oldint) (int); - void (*oldhup) (int); - int saved_errno; - - saved_errno = errno; - oldint = signal(SIGINT, SIG_IGN); - oldhup = signal(SIGHUP, SIG_IGN); - - if (!alreadyCleaning) { - alreadyCleaning = 1; - if (signo) - printf("Signal %d received, cleaning up.\n", signo); - if (!Fake && zapLogDir && LogDir[0]) - (void) fexec(REMOVE_CMD, "-fr", LogDir, NULL); - leave_playpen(Home); - if (signo) - exit(1); + if (extract_files(pkg)) + goto nuke_pkg; + + if (run_install_script(pkg, "POST-INSTALL")) + goto nuke_pkgdb; + + /* XXX keep +INSTALL_INFO for updates? */ + /* XXX keep +PRESERVE for updates? */ + if (mark_automatic) + mark_as_automatic_installed(pkg->pkgname, 1); + + pkg_register_depends(pkg); + + if (Verbose) + printf("Package %s registered in %s\n", pkg->pkgname, pkg->install_logdir); + + if (pkg->meta_data.meta_display != NULL) + fputs(pkg->meta_data.meta_display, stdout); + + pkg_register_views(pkg); + + status = 0; + goto clean_memory; + +nuke_pkg: + if (!Fake) { + if (pkg->other_version) { + warnx("Updating of %s to %s failed.", + pkg->other_version, pkg->pkgname); + warnx("Remember to run pkg_admin rebuild-tree after fixing this."); + } + delete_package(FALSE, FALSE, &pkg->plist, FALSE, Destdir); + } + +nuke_pkgdb: + if (!Fake) { + if (recursive_remove(pkg->install_logdir, 1)) + warn("Couldn't remove %s", pkg->install_logdir); + free(pkg->install_logdir); + free(pkg->logdir); + pkg->install_logdir = NULL; + pkg->logdir = NULL; + } + +clean_memory: + if (pkg->logdir != NULL && NoRecord && !Fake) { + if (recursive_remove(pkg->install_logdir, 1)) + warn("Couldn't remove %s", pkg->install_logdir); + } + free(pkg->install_prefix); + free(pkg->install_logdir); + free(pkg->logdir); + free_buildinfo(pkg); + free_plist(&pkg->plist); + free_meta_data(pkg); + if (pkg->archive) { + archive_read_close(pkg->archive); + close_archive(archive_cookie); } - signal(SIGINT, oldint); - signal(SIGHUP, oldhup); - errno = saved_errno; + free(pkg->other_version); + free(pkg->pkgname); +#ifdef HAVE_SSL + pkg_free_signature(signature_cookie); +#endif +clean_find_archive: + free(pkg); + return status; } int pkg_perform(lpkg_head_t *pkgs) { - int err_cnt = 0; + int oldcwd, errors = 0; lpkg_t *lpp; - signal(SIGINT, cleanup); - signal(SIGHUP, cleanup); - - TAILQ_INIT(&files); + if ((oldcwd = open(".", O_RDONLY, 0)) == -1) + err(EXIT_FAILURE, "unable to open cwd"); while ((lpp = TAILQ_FIRST(pkgs)) != NULL) { path_prepend_from_pkgname(lpp->lp_name); - err_cnt += pkg_do(lpp->lp_name, pkgs); + if (pkg_do(lpp->lp_name, Automatic)) + ++errors; path_prepend_clear(); TAILQ_REMOVE(pkgs, lpp, lp_link); free_lpkg(lpp); + + if (fchdir(oldcwd) == -1) + err(EXIT_FAILURE, "unable to restore cwd"); } - - ftp_stop(); - - return err_cnt; + + close(oldcwd); + + return errors; } diff --git a/pkgtools/pkg_install/files/add/pkg_add.1 b/pkgtools/pkg_install/files/add/pkg_add.1 index ced8fd613c9..5472b414d13 100644 --- a/pkgtools/pkg_install/files/add/pkg_add.1 +++ b/pkgtools/pkg_install/files/add/pkg_add.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: pkg_add.1,v 1.30 2008/04/26 17:40:01 joerg Exp $ +.\" $NetBSD: pkg_add.1,v 1.31 2009/02/02 12:35:00 joerg Exp $ .\" .\" FreeBSD install - a package for the installation and maintenance .\" of non-core utilities. @@ -17,7 +17,7 @@ .\" .\" @(#)pkg_add.1 .\" -.Dd August 23, 2007 +.Dd October 10, 2008 .Dt PKG_ADD 1 .Os .Sh NAME @@ -28,9 +28,8 @@ .Op Fl AfILnRuVv .Op Fl K Ar pkg_dbdir .Op Fl m Ar machine +.Op Fl P Ar destdir .Op Fl p Ar prefix -.Op Fl s Ar verification-type -.Op Fl t Ar template .Op Fl W Ar viewbase .Op Fl w Ar view .Ar \fR[[ftp|http]://[\fIuser\fR[:\fIpassword]\fR@]\fIhost\fR[:\fIport\fR]][/\fIpath/\fR]pkg-name ... @@ -60,8 +59,8 @@ You are advised to verify the competence and identity of those who provide installable package files. For extra protection, use the digital signatures provided where possible (see the -.Fl s -option), or, failing that, use +.Xr pkg_install.conf 5 ) , +or, failing that, use .Xr tar 1 to extract the package file, and inspect its contents and scripts to ensure it poses no danger to your system's integrity. @@ -143,6 +142,11 @@ Override the machine architecture returned by uname with .It Fl n Don't actually install a package, just report the steps that would be taken if it was. +.It Fl P Ar destdir +Prefix all file and directory names with +.Ar destdir . +For packages without install scripts this has the same behavior as +using chroot. .It Fl p Ar prefix Set .Ar prefix @@ -160,56 +164,14 @@ into .Ar pkgdb . .It Fl R Do not record the installation of a package. +This implies +.Fl I . This means that you cannot deinstall it later, so only use this option if you know what you are doing! -.It Fl s Ar verification-type -Use a callout to an external program to verify the binary package -being installed against an existing detached signature file. -The signature file must reside in the same directory -as the binary package. -At the present time, the following verification types -are defined: none, gpg and pgp5. -The signature will be verified at install time, and the results -will be displayed. -If the signature type is anything other than none, the user will be asked if -.Nm -should proceed to install the binary package. -The user must then take the decision whether to proceed or not, depending -upon the amount of trust that is placed in the signatory of the binary -package. -Please note that, at the current time, it is not possible to use -the verification feature when using -.Nm -to add a binary package via a URL - the package, and the related -detached signature file, must be local -for the verification to work. -.It Fl t Ar template -Use -.Ar template -as the input to -.Xr mktemp 3 -when creating a -.Dq staging area . -By default, this is the string -.Pa /var/tmp/instmp.XXXXXX , -but it may be necessary to override it in the situation where -space in your -.Pa /var/tmp -directory is limited. -Be sure to leave some number of -.Sq X -characters for -.Xr mktemp 3 -to fill in with a unique ID. -.Pp -You can get a performance boost by setting the staging area -.Ar template -to reside on the same disk partition as target directories for package -file installation; often this is -.Pa /usr . .It Fl u -If the package that's being installed is already installed, either -in the same or a different version, an update is performed. +If the package that's being installed is already installed, +an update is performed. +It is currently not possible to update to an identical version. If this is specified twice, then any dependant packages that are too old will also be updated to fulfill the dependency. See below for a more detailed description of the process. @@ -275,11 +237,10 @@ passive mode ftp. .Sh TECHNICAL DETAILS .Nm -extracts each package's -.Dq packing list -into a special staging directory in /var/tmp (or $PKG_TMPDIR if set) -and then runs through the following sequence to fully extract the contents -of the package: +extracts each package's meta data (including the +.Dq packing list ) +to memory and then runs through the following sequence to fully extract +the contents of the package: .Bl -enum -offset indent .It A check is made to determine if the package or another version of it @@ -305,13 +266,37 @@ was not installed, and restores the .Pa +REQUIRED_BY file afterwards. .It +The package build information is extracted from the +.Pa +BUILD_INFO +file and compared against the result of +.Xr uname 3 . +If the operating system or architecture of the package differ from +that of the host, installation is aborted. +This behavior is overridable with the +.Fl f +flag. +.It +The package build information from +.Pa +BUILD_INFO +is then checked for +.Ev USE_ABI_DEPENDS=NO +(or +.Ev IGNORE_RECOMMENDED ) . +If the package was built with ABI dependency recommendations ignored, +a warning will be issued. +.It A check is made to determine if the package conflicts (from .Cm @pkgcfl directives, see .Xr pkg_create 1 ) -with an already recorded as installed package. +with an already recorded as installed package or if an installed package +conflicts with the package. If it is, installation is terminated. .It +The file list of the package is compared to the file lists of the +installed packeges. +If there is any overlap, the installation is terminated. +.It All package dependencies (from .Cm @pkgdep directives, see @@ -330,34 +315,6 @@ The dependant packages are found according to the normal .Ev PKG_PATH rules. .It -A search is made for any -.Cm @option -directives which control how the package is added to the system. -The only currently implemented option is -.Cm @option preserve , -which tells pkg_add to move any existing files out of the way, -preserving the previous contents (which are also resurrected on -pkg_delete, so caveat emptor). -.It -The package build information is extracted from the -.Pa +BUILD_INFO -file and compared against the result of -.Xr uname 3 . -If the operating system or architecture of the package differ from -that of the host, installation is aborted. -This behavior is overridable with the -.Fl f -flag. -.It -The package build information from -.Pa +BUILD_INFO -is then checked for -.Ev USE_ABI_DEPENDS=NO -(or -.Ev IGNORE_RECOMMENDED ) . -If the package was built with ABI dependency recommendations ignored, -a warning will be issued. -.It If the package contains an .Ar install script, it is executed with the following arguments: @@ -373,8 +330,7 @@ If the .Ar install script exits with a non-zero status code, the installation is terminated. .It -It is used as a guide for moving (or copying, as necessary) files from -the staging area into their final locations. +The files from the file list are extracted to the choosen prefix. .It If an .Ar install @@ -403,8 +359,6 @@ path shown above). .It If the package is a depoted package, then add it to the default view. .It -The staging area is deleted and the program terminates. -.It Finally, if we were upgrading a package, any .Pa +REQUIRED_BY file that was moved aside before upgrading was started is now moved @@ -432,6 +386,13 @@ meta-data files, and with the .Ev PKG_REFCOUNT_DBDIR environment variable set to the location of the package reference counts database directory. +If the +.Fl P +flag was given to +.Nm , +.Ev PKG_DESTDIR +will be set to +.Ar destdir . .Sh ENVIRONMENT .Bl -tag -width PKG_TMPDIR .It Ev LOCALBASE @@ -467,10 +428,6 @@ The default location is the path to the package database directory with .Dq .refcount appended to the path, e.g. .Pa /var/db/pkg.refcount . -.It Ev PKG_TMPDIR -Staging directory for installing packages, defaults to /var/tmp. -Set to directory with lots of free disk if you run out of -space when installing a binary package. .It Ev PKG_VIEW The default view can be specified in the .Ev PKG_VIEW @@ -532,6 +489,16 @@ If you do this, consider installing and using the .Pa security/audit-packages package and running it after every .Nm . +.Sh CONFIGURATION VARIABLES +The following variables change the behaviour of +.Nm +and are described in +.Xr pkg_install.conf 5 : +.Bl -tag -width CERTIFICATE_ANCHOR_PKGS +.It Ev CERTIFICATE_ANCHOR_PKGS +.It Ev CERTIFICATE_CHAIN +.It Ev VERIFIED_INSTALLATION +.El .Sh SEE ALSO .Xr pkg_admin 1 , .Xr pkg_create 1 , @@ -540,6 +507,7 @@ package and running it after every .Xr tar 1 , .Xr mktemp 3 , .Xr sysconf 3 , +.Xr pkg_install.conf 5 , .Xr pkgsrc 7 .Sh AUTHORS .Bl -tag -width indent -compact @@ -553,21 +521,10 @@ refinements. wildcard dependency processing, pkgdb, upgrading, etc. .It Thomas Klausner HTTP support. +.It Joerg Sonnenberger +Rewrote most of the code base to work without external commands. .El .Sh BUGS -Hard links between files in a distribution are only preserved if either -(1) the staging area is on the same file system as the target directory of -all the links to the file, or (2) all the links to the file are bracketed by -.Cm @cwd -directives in the contents file, -.Em and -and the link names are extracted with a single -.Cm tar -command (not split between -invocations due to exec argument-space limitations--this depends on the -value returned by -.Fn sysconf _SC_ARG_MAX ) . -.Pp Package upgrading needs a lot more work to be really universal. .Pp Sure to be others. diff --git a/pkgtools/pkg_install/files/add/pkg_add.cat1 b/pkgtools/pkg_install/files/add/pkg_add.cat1 index 6ff5af89037..299b76c5f9d 100644 --- a/pkgtools/pkg_install/files/add/pkg_add.cat1 +++ b/pkgtools/pkg_install/files/add/pkg_add.cat1 @@ -5,8 +5,8 @@ NNAAMMEE tributions SSYYNNOOPPSSIISS - ppkkgg__aadddd [--AAffIILLnnRRuuVVvv] [--KK _p_k_g___d_b_d_i_r] [--mm _m_a_c_h_i_n_e] [--pp _p_r_e_f_i_x] - [--ss _v_e_r_i_f_i_c_a_t_i_o_n_-_t_y_p_e] [--tt _t_e_m_p_l_a_t_e] [--WW _v_i_e_w_b_a_s_e] [--ww _v_i_e_w] + ppkkgg__aadddd [--AAffIILLnnRRuuVVvv] [--KK _p_k_g___d_b_d_i_r] [--mm _m_a_c_h_i_n_e] [--PP _d_e_s_t_d_i_r] [--pp _p_r_e_f_i_x] + [--WW _v_i_e_w_b_a_s_e] [--ww _v_i_e_w] [[ftp|http]://[_u_s_e_r[:_p_a_s_s_w_o_r_d_]@]_h_o_s_t[:_p_o_r_t]][/_p_a_t_h_/]pkg-name ... DDEESSCCRRIIPPTTIIOONN @@ -25,13 +25,13 @@ WWAARRNNIINNGG _Y_o_u _a_r_e _a_d_v_i_s_e_d _t_o _v_e_r_i_f_y _t_h_e _c_o_m_p_e_t_e_n_c_e _a_n_d _i_d_e_n_t_i_t_y _o_f _t_h_o_s_e _w_h_o _p_r_o_- _v_i_d_e _i_n_s_t_a_l_l_a_b_l_e _p_a_c_k_a_g_e _f_i_l_e_s_. _F_o_r _e_x_t_r_a _p_r_o_t_e_c_t_i_o_n_, _u_s_e _t_h_e _d_i_g_i_t_a_l - _s_i_g_n_a_t_u_r_e_s _p_r_o_v_i_d_e_d _w_h_e_r_e _p_o_s_s_i_b_l_e _(_s_e_e _t_h_e --ss _o_p_t_i_o_n_)_, _o_r_, _f_a_i_l_i_n_g _t_h_a_t_, - _u_s_e tar(_1) _t_o _e_x_t_r_a_c_t _t_h_e _p_a_c_k_a_g_e _f_i_l_e_, _a_n_d _i_n_s_p_e_c_t _i_t_s _c_o_n_t_e_n_t_s _a_n_d - _s_c_r_i_p_t_s _t_o _e_n_s_u_r_e _i_t _p_o_s_e_s _n_o _d_a_n_g_e_r _t_o _y_o_u_r _s_y_s_t_e_m_'_s _i_n_t_e_g_r_i_t_y_. _P_a_y - _p_a_r_t_i_c_u_l_a_r _a_t_t_e_n_t_i_o_n _t_o _a_n_y _+_I_N_S_T_A_L_L _o_r _+_D_E_I_N_S_T_A_L_L _f_i_l_e_s_, _a_n_d _i_n_s_p_e_c_t _t_h_e - _+_C_O_N_T_E_N_T_S _f_i_l_e _f_o_r @@ccwwdd_, @@mmooddee _(_c_h_e_c_k _f_o_r _s_e_t_u_i_d_)_, @@ddiirrrrmm_, @@eexxeecc_, _a_n_d - @@uunneexxeecc _d_i_r_e_c_t_i_v_e_s_, _a_n_d_/_o_r _u_s_e _t_h_e pkg_info(_1) _c_o_m_m_a_n_d _t_o _e_x_a_m_i_n_e _t_h_e - _p_a_c_k_a_g_e _f_i_l_e_. + _s_i_g_n_a_t_u_r_e_s _p_r_o_v_i_d_e_d _w_h_e_r_e _p_o_s_s_i_b_l_e _(_s_e_e _t_h_e pkg_install.conf(_5)_)_, _o_r_, + _f_a_i_l_i_n_g _t_h_a_t_, _u_s_e tar(_1) _t_o _e_x_t_r_a_c_t _t_h_e _p_a_c_k_a_g_e _f_i_l_e_, _a_n_d _i_n_s_p_e_c_t _i_t_s + _c_o_n_t_e_n_t_s _a_n_d _s_c_r_i_p_t_s _t_o _e_n_s_u_r_e _i_t _p_o_s_e_s _n_o _d_a_n_g_e_r _t_o _y_o_u_r _s_y_s_t_e_m_'_s + _i_n_t_e_g_r_i_t_y_. _P_a_y _p_a_r_t_i_c_u_l_a_r _a_t_t_e_n_t_i_o_n _t_o _a_n_y _+_I_N_S_T_A_L_L _o_r _+_D_E_I_N_S_T_A_L_L _f_i_l_e_s_, + _a_n_d _i_n_s_p_e_c_t _t_h_e _+_C_O_N_T_E_N_T_S _f_i_l_e _f_o_r @@ccwwdd_, @@mmooddee _(_c_h_e_c_k _f_o_r _s_e_t_u_i_d_)_, + @@ddiirrrrmm_, @@eexxeecc_, _a_n_d @@uunneexxeecc _d_i_r_e_c_t_i_v_e_s_, _a_n_d_/_o_r _u_s_e _t_h_e pkg_info(_1) _c_o_m_m_a_n_d + _t_o _e_x_a_m_i_n_e _t_h_e _p_a_c_k_a_g_e _f_i_l_e_. OOPPTTIIOONNSS The following command line arguments are supported: @@ -77,6 +77,11 @@ OOPPTTIIOONNSS --nn Don't actually install a package, just report the steps that would be taken if it was. + --PP _d_e_s_t_d_i_r + Prefix all file and directory names with _d_e_s_t_d_i_r. For packages + without install scripts this has the same behavior as using + chroot. + --pp _p_r_e_f_i_x Set _p_r_e_f_i_x as the directory in which to extract files from a package. If a package has set its default directory, it will be @@ -86,44 +91,16 @@ OOPPTTIIOONNSS directory transition is supported and the second one is expected to go into _p_k_g_d_b. - --RR Do not record the installation of a package. This means that you - cannot deinstall it later, so only use this option if you know - what you are doing! - - --ss _v_e_r_i_f_i_c_a_t_i_o_n_-_t_y_p_e - Use a callout to an external program to verify the binary package - being installed against an existing detached signature file. The - signature file must reside in the same directory as the binary - package. At the present time, the following verification types - are defined: none, gpg and pgp5. The signature will be verified - at install time, and the results will be displayed. If the sig- - nature type is anything other than none, the user will be asked - if ppkkgg__aadddd should proceed to install the binary package. The - user must then take the decision whether to proceed or not, - depending upon the amount of trust that is placed in the signa- - tory of the binary package. Please note that, at the current - time, it is not possible to use the verification feature when - using ppkkgg__aadddd to add a binary package via a URL - the package, - and the related detached signature file, must be local for the - verification to work. - - --tt _t_e_m_p_l_a_t_e - Use _t_e_m_p_l_a_t_e as the input to mktemp(3) when creating a ``staging - area''. By default, this is the string _/_v_a_r_/_t_m_p_/_i_n_s_t_m_p_._X_X_X_X_X_X, - but it may be necessary to override it in the situation where - space in your _/_v_a_r_/_t_m_p directory is limited. Be sure to leave - some number of `X' characters for mktemp(3) to fill in with a - unique ID. - - You can get a performance boost by setting the staging area - _t_e_m_p_l_a_t_e to reside on the same disk partition as target directo- - ries for package file installation; often this is _/_u_s_r. - - --uu If the package that's being installed is already installed, - either in the same or a different version, an update is per- - formed. If this is specified twice, then any dependant packages - that are too old will also be updated to fulfill the dependency. - See below for a more detailed description of the process. + --RR Do not record the installation of a package. This implies --II. + This means that you cannot deinstall it later, so only use this + option if you know what you are doing! + + --uu If the package that's being installed is already installed, an + update is performed. It is currently not possible to update to + an identical version. If this is specified twice, then any + dependant packages that are too old will also be updated to ful- + fill the dependency. See below for a more detailed description + of the process. --VV Print version number and exit. @@ -153,9 +130,9 @@ OOPPTTIIOONNSS a firewall that demands the usage of _p_a_s_s_i_v_e _m_o_d_e ftp. TTEECCHHNNIICCAALL DDEETTAAIILLSS - ppkkgg__aadddd extracts each package's ``packing list'' into a special staging - directory in /var/tmp (or $PKG_TMPDIR if set) and then runs through the - following sequence to fully extract the contents of the package: + ppkkgg__aadddd extracts each package's meta data (including the ``packing + list'') to memory and then runs through the following sequence to fully + extract the contents of the package: 1. A check is made to determine if the package or another version of it is already recorded as installed. If it is, installa- @@ -171,12 +148,28 @@ TTEECCHHNNIICCAALL DDEETTAAIILLSS age was not installed, and restores the _+_R_E_Q_U_I_R_E_D___B_Y file afterwards. - 2. A check is made to determine if the package conflicts (from + 2. The package build information is extracted from the + _+_B_U_I_L_D___I_N_F_O file and compared against the result of uname(3). + If the operating system or architecture of the package differ + from that of the host, installation is aborted. This behavior + is overridable with the --ff flag. + + 3. The package build information from _+_B_U_I_L_D___I_N_F_O is then checked + for USE_ABI_DEPENDS=NO (or IGNORE_RECOMMENDED). If the pack- + age was built with ABI dependency recommendations ignored, a + warning will be issued. + + 4. A check is made to determine if the package conflicts (from @@ppkkggccffll directives, see pkg_create(1)) with an already - recorded as installed package. If it is, installation is ter- - minated. + recorded as installed package or if an installed package con- + flicts with the package. If it is, installation is termi- + nated. + + 5. The file list of the package is compared to the file lists of + the installed packeges. If there is any overlap, the instal- + lation is terminated. - 3. All package dependencies (from @@ppkkggddeepp directives, see + 6. All package dependencies (from @@ppkkggddeepp directives, see pkg_create(1)) are read from the packing list. If any of these required packages are not currently installed, an attempt is made to find and install it; if the missing package @@ -186,24 +179,6 @@ TTEECCHHNNIICCAALL DDEETTAAIILLSS considered to be too old, are also updated. The dependant packages are found according to the normal PKG_PATH rules. - 4. A search is made for any @@ooppttiioonn directives which control how - the package is added to the system. The only currently imple- - mented option is @@ooppttiioonn pprreesseerrvvee, which tells pkg_add to move - any existing files out of the way, preserving the previous - contents (which are also resurrected on pkg_delete, so caveat - emptor). - - 5. The package build information is extracted from the - _+_B_U_I_L_D___I_N_F_O file and compared against the result of uname(3). - If the operating system or architecture of the package differ - from that of the host, installation is aborted. This behavior - is overridable with the --ff flag. - - 6. The package build information from _+_B_U_I_L_D___I_N_F_O is then checked - for USE_ABI_DEPENDS=NO (or IGNORE_RECOMMENDED). If the pack- - age was built with ABI dependency recommendations ignored, a - warning will be issued. - 7. If the package contains an _i_n_s_t_a_l_l script, it is executed with the following arguments: @@ -216,8 +191,8 @@ TTEECCHHNNIICCAALL DDEETTAAIILLSS If the _i_n_s_t_a_l_l script exits with a non-zero status code, the installation is terminated. - 8. It is used as a guide for moving (or copying, as necessary) - files from the staging area into their final locations. + 8. The files from the file list are extracted to the choosen pre- + fix. 9. If an _i_n_s_t_a_l_l script exists for the package, it is executed with the following arguments: @@ -239,9 +214,7 @@ TTEECCHHNNIICCAALL DDEETTAAIILLSS 11. If the package is a depoted package, then add it to the default view. - 12. The staging area is deleted and the program terminates. - - 13. Finally, if we were upgrading a package, any _+_R_E_Q_U_I_R_E_D___B_Y file + 12. Finally, if we were upgrading a package, any _+_R_E_Q_U_I_R_E_D___B_Y file that was moved aside before upgrading was started is now moved back into place. @@ -252,7 +225,8 @@ TTEECCHHNNIICCAALL DDEETTAAIILLSS change it with the --pp flag to ppkkgg__aadddd. The scripts are also called with the PKG_METADATA_DIR environment variable set to the location of the _+_* meta-data files, and with the PKG_REFCOUNT_DBDIR environment variable set - to the location of the package reference counts database directory. + to the location of the package reference counts database directory. If + the --PP flag was given to ppkkgg__aadddd, PKG_DESTDIR will be set to _d_e_s_t_d_i_r. EENNVVIIRROONNMMEENNTT LOCALBASE This is the location of the _v_i_e_w_b_a_s_e directory in which all @@ -277,10 +251,6 @@ EENNVVIIRROONNMMEENNTT directory with ``.refcount'' appended to the path, e.g. _/_v_a_r_/_d_b_/_p_k_g_._r_e_f_c_o_u_n_t. - PKG_TMPDIR Staging directory for installing packages, defaults to - /var/tmp. Set to directory with lots of free disk if you run - out of space when installing a binary package. - PKG_VIEW The default view can be specified in the PKG_VIEW environment variable. @@ -316,9 +286,19 @@ EEXXAAMMPPLLEESS ter.) If you do this, consider installing and using the _s_e_c_u_r_i_t_y_/_a_u_d_i_t_-_p_a_c_k_a_g_e_s package and running it after every ppkkgg__aadddd. +CCOONNFFIIGGUURRAATTIIOONN VVAARRIIAABBLLEESS + The following variables change the behaviour of ppkkgg__aadddd and are described + in pkg_install.conf(5): + + CERTIFICATE_ANCHOR_PKGS + + CERTIFICATE_CHAIN + + VERIFIED_INSTALLATION + SSEEEE AALLSSOO pkg_admin(1), pkg_create(1), pkg_delete(1), pkg_info(1), tar(1), - mktemp(3), sysconf(3), pkgsrc(7) + mktemp(3), sysconf(3), pkg_install.conf(5), pkgsrc(7) AAUUTTHHOORRSS Jordan Hubbard @@ -329,18 +309,12 @@ AAUUTTHHOORRSS NetBSD wildcard dependency processing, pkgdb, upgrading, etc. Thomas Klausner HTTP support. + Joerg Sonnenberger + Rewrote most of the code base to work without external commands. BBUUGGSS - Hard links between files in a distribution are only preserved if either - (1) the staging area is on the same file system as the target directory - of all the links to the file, or (2) all the links to the file are brack- - eted by @@ccwwdd directives in the contents file, _a_n_d and the link names are - extracted with a single ttaarr command (not split between invocations due to - exec argument-space limitations--this depends on the value returned by - ssyyssccoonnff(___S_C___A_R_G___M_A_X)). - Package upgrading needs a lot more work to be really universal. Sure to be others. -NetBSD 4.0 August 23, 2007 NetBSD 4.0 +NetBSD 5.0 October 10, 2008 NetBSD 5.0 diff --git a/pkgtools/pkg_install/files/add/verify.c b/pkgtools/pkg_install/files/add/verify.c deleted file mode 100644 index 00fb8f2770c..00000000000 --- a/pkgtools/pkg_install/files/add/verify.c +++ /dev/null @@ -1,179 +0,0 @@ -/* $NetBSD: verify.c,v 1.7 2004/12/29 12:16:56 agc Exp $ */ - -/* - * Copyright (c) 2001 Alistair G. Crooks. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Alistair G. Crooks. - * 4. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include <nbcompat.h> -#if HAVE_SYS_CDEFS_H -#include <sys/cdefs.h> -#endif - -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1999 \ - The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: verify.c,v 1.7 2004/12/29 12:16:56 agc Exp $"); -#endif - -#if HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#if HAVE_SYS_PARAM_H -#include <sys/param.h> -#endif -#if HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif - -#if HAVE_STDIO_H -#include <stdio.h> -#endif -#if HAVE_STDLIB_H -#include <stdlib.h> -#endif -#if HAVE_STRING_H -#include <string.h> -#endif -#if HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include "verify.h" -#include "lib.h" - -enum { - MaxExtensions = 10 -}; - -/* this struct defines a verification type */ -typedef struct ver_t { - const char *name; /* name of type */ - const char *command1; /* command to execute to verify */ - const char *command2; /* command to execute to verify */ - const char *extensions[MaxExtensions]; /* signature file extensions */ -} ver_t; - -static char *verification_type; /* the verification type which has been selected */ - -/* called when gpg verification type is selected */ -static int -do_verify(const char *pkgname, const char *cmd1, const char *cmd2, const char *const *extensions) -{ - struct stat st; - const char *const *ep; - char buf[BUFSIZ]; - char f[MaxPathSize]; - int ret; - int i; - - if (cmd1 == NULL) { - return 1; - } - for (i = 0, ep = extensions ; i < MaxExtensions && *ep ; ep++, i++) { - (void) snprintf(f, sizeof(f), "%s%s", pkgname, *ep); - if (stat(f, &st) == 0) { - (void) fprintf(stderr, "pkg_add: Using signature file: %s\n", f); - ret = (cmd2 == NULL) ? fexec(cmd1, f, NULL) : fexec(cmd1, cmd2, f, NULL); - if (ret != 0) { - (void) fprintf(stderr, "*** WARNING ***: `%s' has a bad signature\n", f); - return 0; - } - (void) fprintf(stderr, "Proceed with addition of %s: [y/n]? ", pkgname); - if (fgets(buf, sizeof(buf), stdin) == NULL) { - (void) fprintf(stderr, "Exiting now..."); - exit(EXIT_FAILURE); - } - switch(buf[0]) { - case 'Y': - case 'y': - case '1': - return 1; - } - (void) fprintf(stderr, "Package `%s' will not be added\n", pkgname); - return 0; - } - } - (void) fprintf(stderr, "No valid signature file found for `%s'\n", pkgname); - return 0; -} - -/* table holding possible verifications which can be made */ -static const ver_t vertab[] = { - { "none", NULL, NULL, { NULL } }, - { "gpg", "gpg", "--verify", { ".sig", ".asc", NULL } }, - { "pgp5", "pgpv", NULL, { ".sig", ".asc", ".pgp", NULL } }, - { NULL } -}; - -/* set the verification type - usually called during command line processing */ -void -set_verification(const char *type) -{ - if (verification_type) { - (void) free(verification_type); - } - verification_type = strdup(type); -} - -/* return the type of verification that is being used */ -char * -get_verification(void) -{ - const ver_t *vp; - - if (verification_type != NULL) { - for (vp = vertab ; vp->name ; vp++) { - if (strcasecmp(verification_type, vp->name) == 0) { - return verification_type; - } - } - } - return "none"; -} - -/* verify the digital signature (if any) on a package */ -int -verify(const char *pkg) -{ - const ver_t *vp; - - if (verification_type == NULL) { - return do_verify(pkg, NULL, NULL, NULL); - } - for (vp = vertab ; vp->name ; vp++) { - if (strcasecmp(verification_type, vp->name) == 0) { - return do_verify(pkg, vp->command1, vp->command2, vp->extensions); - } - } - (void) fprintf(stderr, "Can't find `%s' verification details\n", verification_type); - return 0; -} diff --git a/pkgtools/pkg_install/files/add/verify.h b/pkgtools/pkg_install/files/add/verify.h deleted file mode 100644 index 52a4c07d81d..00000000000 --- a/pkgtools/pkg_install/files/add/verify.h +++ /dev/null @@ -1,40 +0,0 @@ -/* $NetBSD: verify.h,v 1.3 2003/09/23 07:13:47 grant Exp $ */ - -/* - * Copyright (c) 2001 Alistair G. Crooks. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Alistair G. Crooks. - * 4. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef VERIFY_H_ -#define VERIFY_H_ - -void set_verification(const char *); -char *get_verification(void); -int verify(const char *); - -#endif /* VERIFY_H_ */ diff --git a/pkgtools/pkg_install/files/admin/Makefile.in b/pkgtools/pkg_install/files/admin/Makefile.in index 43b96bf5ffb..8906c19d87c 100644 --- a/pkgtools/pkg_install/files/admin/Makefile.in +++ b/pkgtools/pkg_install/files/admin/Makefile.in @@ -1,10 +1,9 @@ -# $NetBSD: Makefile.in,v 1.15 2008/04/04 20:46:59 tnn Exp $ +# $NetBSD: Makefile.in,v 1.16 2009/02/02 12:35:00 joerg Exp $ srcdir= @srcdir@ prefix= @prefix@ exec_prefix= @exec_prefix@ -sysconfdir= @sysconfdir@ sbindir= @sbindir@ mandir= @mandir@ datarootdir= @datarootdir@ @@ -13,6 +12,7 @@ man1dir= $(mandir)/man1 cat1dir= $(mandir)/cat1 BOOTSTRAP= @bootstrap@ +SSL_SUPPORT= @ssl_support@ CC= @CC@ CCLD= $(CC) @@ -23,20 +23,24 @@ LDFLAGS= @LDFLAGS@ -L../lib INSTALL= @INSTALL@ PROG= pkg_admin +SCRIPTS= audit-packages download-vulnerability-list .if empty(BOOTSTRAP) -LIBS= -linstall -lbz2 -lfetch -lz @LIBS@ -OBJS= audit.o check.o config.o main.o -CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I../lib \ - -DSYSCONFDIR=\"$(sysconfdir)\" +LIBS= -linstall -lbz2 -lfetch -larchive -lbz2 -lz +.if !empty(SSL_SUPPORT) +LIBS+= -lcrypto +CPPFLAGS+= -DHAVE_SSL +.endif +LIBS+= @LIBS@ +OBJS= audit.o check.o main.o +CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I../lib .else LIBS= -linstall @LIBS@ -OBJS= check.o config.o main.o -CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I../lib -DBOOTSTRAP \ - -DSYSCONFDIR=\"$(sysconfdir)\" +OBJS= check.o main.o +CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I../lib -DBOOTSTRAP .endif -all: $(PROG) +all: $(PROG) $(SCRIPTS) .c.o: $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c $< @@ -52,5 +56,14 @@ install: $(INSTALL) -m 755 -d ${DESTDIR}$(man1dir) $(INSTALL) -m 755 -d ${DESTDIR}$(cat1dir) $(INSTALL) $(PROG) ${DESTDIR}$(sbindir)/$(PROG) + $(INSTALL) -m 555 $(SCRIPTS) ${DESTDIR}$(sbindir) $(INSTALL) -m 444 $(PROG).1 ${DESTDIR}$(man1dir)/$(PROG).1 $(INSTALL) -m 444 $(PROG).cat1 ${DESTDIR}$(cat1dir)/$(PROG).0 + +audit-packages: audit-packages.sh.in + sed -e 's|@PKG_ADMIN@|${sbindir}/pkg_admin|' \ + ${.CURDIR}/audit-packages.sh.in > $@ + +download-vulnerability-list: download-vulnerability-list.sh.in + sed -e 's|@PKG_ADMIN@|${sbindir}/pkg_admin|' \ + ${.CURDIR}/download-vulnerability-list.sh.in > $@ diff --git a/pkgtools/pkg_install/files/admin/admin.h b/pkgtools/pkg_install/files/admin/admin.h index b892a29be02..ea5b783d91e 100644 --- a/pkgtools/pkg_install/files/admin/admin.h +++ b/pkgtools/pkg_install/files/admin/admin.h @@ -27,12 +27,6 @@ extern int quiet; extern int verbose; -extern const char *pkg_vulnerabilities_dir; -extern const char *pkg_vulnerabilities_file; -extern const char *pkg_vulnerabilities_url; -extern const char *ignore_advisories; -extern const char tnf_vulnerability_base[]; - void check(char **); void audit_pkgdb(int, char **); @@ -42,7 +36,4 @@ void audit_history(int, char **); void check_pkg_vulnerabilities(int, char **); void fetch_pkg_vulnerabilities(int, char **); -void pkg_install_config(const char *); -void pkg_install_show_variable(const char *); - void usage(void); diff --git a/pkgtools/pkg_install/files/admin/audit-packages.sh.in b/pkgtools/pkg_install/files/admin/audit-packages.sh.in new file mode 100644 index 00000000000..8e619a7bcdd --- /dev/null +++ b/pkgtools/pkg_install/files/admin/audit-packages.sh.in @@ -0,0 +1,128 @@ +#!/bin/sh + +pkg_admin=@PKG_ADMIN@ + +usage() { + echo 'Usage: audit-packages [-deqsVv] [-c config_file] [-F file]' >& $2 + echo ' [-g file] [-h file]' >& $2 + echo ' [-K pkg_dbdir] [-n package] [-p package]' >& $2 + echo ' [-Q varname] [-t type]' >& $2 + echo "Please use \`\`pkg_admin fetch-pkg-vulnerabilities'' instead." >& $2 + exit $1 +} + +do_pkgdb= +do_eol= +do_fetch= +do_quiet= +do_sign= +do_verbose= +do_check_file= +do_check_pattern= +do_check_installed= +do_check_vul_file= +do_limit_type= +do_print_var= + +args=`getopt F:K:Q:Vc:deg:h:n:p:qst:v $*` +if [ $? -ne 0 ]; then + usage 1 2 +fi + +set -- $args + +while [ $# -gt 0 ]; do + case "$1" in + -F) + do_check_file=$2 + shift + ;; + -K) + do_pkgdb="$1 $2" + shift + ;; + -Q) + do_print_var="$2" + shift + ;; + -V) + exec ${pkg_admin} -V + ;; + -c) + echo "The audit-packages wrapper does not support -c" >&2 + echo "Please switch to \`\`pkg_admin fetch-pkg-vulnerabilities''." >&2 + exit 1 + ;; + -d) + do_fetch=1 + ;; + -e) + do_eol=-e + ;; + -g) + echo "The audit-packages wrapper does not support -g" >&2 + echo "Please switch to \`\`pkg_admin fetch-pkg-vulnerabilities''." >&2 + exit 1 + ;; + -h) + do_check_vul_file=$2 + shift + ;; + -n) + do_check_pattern=$2 + shift + ;; + -p) + do_check_installed=$2 + shift + ;; + -q) + do_quiet=-q + ;; + -s) + do_sign=-s + ;; + -t) + do_limit_type="-t $2" + shift + ;; + -v) + do_verbose="$do_verbose -v" + ;; + esac + shift +done + +if [ -n "${do_fetch}" ]; then + exec ${pkg_admin} ${do_pkgdb} fetch-pkg-vulnerabilities ${do_sign} +fi + +if [ -n "${do_check_vul_file}" ]; then + exec ${pkg_admin} ${do_pkgdb} check-pkg-vulnerabilities ${do_sign} "${do_check_vul_file}" +fi + +if [ -n "${do_print_var}" ]; then + exec ${pkg_admin} ${do_pkgdb} config-var "${do_print_var}" +fi + +if [ -n "${do_check_file}" ]; then + if [ -n "${do_check_pattern}" -o -n "${do_check_installed}" ]; then + echo "Only one of -F, -n or -p is interpreted at a time." >& 2 + usage 1 2 + fi + exec ${pkg_admin} ${do_pkgdb} ${do_verbose} ${do_quiet} audit-pkg \ + ${do_eol} ${do_limit_type} ${do_check_file} +fi + +if [ -n "${do_check_pattern}" ]; then + if [ -n "${do_check_installed}" ]; then + echo "Only one of -F, -n or -p is interpreted at a time." >& 2 + usage 1 2 + fi + exec ${pkg_admin} ${do_pkgdb} ${do_verbose} ${do_quiet} audit-pkg \ + ${do_eol} ${do_limit_type} ${do_check_pattern} +fi + +# If do_check_installed is empty, all packages are checked. +exec ${pkg_admin} ${do_pkgdb} ${do_verbose} ${do_quiet} audit \ + ${do_eol} ${do_limit_type} ${do_check_installed} diff --git a/pkgtools/pkg_install/files/admin/audit.c b/pkgtools/pkg_install/files/admin/audit.c index a8cf56239fe..056f6ada365 100644 --- a/pkgtools/pkg_install/files/admin/audit.c +++ b/pkgtools/pkg_install/files/admin/audit.c @@ -1,4 +1,4 @@ -/* $NetBSD: audit.c,v 1.10 2008/10/02 20:46:56 joerg Exp $ */ +/* $NetBSD: audit.c,v 1.11 2009/02/02 12:35:00 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,9 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -__RCSID("$NetBSD: audit.c,v 1.10 2008/10/02 20:46:56 joerg Exp $"); -#endif +__RCSID("$NetBSD: audit.c,v 1.11 2009/02/02 12:35:00 joerg Exp $"); /*- * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. @@ -117,66 +115,10 @@ parse_options(int argc, char **argv) } static int -check_ignored_entry(size_t i) -{ - const char *iter, *next; - size_t entry_len, url_len; - - if (ignore_advisories == NULL) - return 0; - - url_len = strlen(pv->advisory[i]); - - for (iter = ignore_advisories; *iter; iter = next) { - if ((next = strchr(iter, '\n')) == NULL) { - entry_len = strlen(iter); - next = iter + entry_len; - } else { - entry_len = next - iter; - ++next; - } - if (url_len != entry_len) - continue; - if (strncmp(pv->advisory[i], iter, entry_len) == 0) - return 1; - } - return 0; -} - -static int check_exact_pkg(const char *pkg) { - int ret; - size_t i; - - ret = 0; - for (i = 0; i < pv->entries; ++i) { - if (check_ignored_entry(i)) - continue; - if (limit_vul_types != NULL && - strcmp(limit_vul_types, pv->classification[i])) - continue; - if (!pkg_match(pv->vulnerability[i], pkg)) - continue; - if (strcmp("eol", pv->classification[i]) == 0) { - if (!check_eol) - continue; - if (quiet) - puts(pkg); - else - printf("Package %s has reached end-of-life (eol), " - "see %s/eol-packages\n", pkg, - tnf_vulnerability_base); - continue; - } - if (quiet) - puts(pkg); - else - printf("Package %s has a %s vulnerability, see %s\n", - pkg, pv->classification[i], pv->advisory[i]); - ret = 1; - } - return ret; + return audit_package(pv, pkg, limit_vul_types, check_eol, + quiet ? 0 : 1); } static int @@ -343,7 +285,8 @@ fetch_pkg_vulnerabilities(int argc, char **argv) { struct pkg_vulnerabilities *pv_check; char *buf, *decompressed_input; - size_t buf_len, decompressed_len; + size_t buf_len, buf_fetched, decompressed_len; + ssize_t cur_fetched; struct url_stat st; fetchIO *f; int fd; @@ -355,7 +298,7 @@ fetch_pkg_vulnerabilities(int argc, char **argv) if (verbose >= 2) fprintf(stderr, "Fetching %s\n", pkg_vulnerabilities_url); - f = fetchXGetURL(pkg_vulnerabilities_url, &st, ""); + f = fetchXGetURL(pkg_vulnerabilities_url, &st, fetch_flags); if (f == NULL) errx(EXIT_FAILURE, "Could not fetch vulnerability file: %s", fetchLastErrString); @@ -364,13 +307,22 @@ fetch_pkg_vulnerabilities(int argc, char **argv) errx(EXIT_FAILURE, "pkg-vulnerabilities is too large"); buf_len = st.size; - if ((buf = malloc(buf_len + 1)) == NULL) - err(EXIT_FAILURE, "malloc failed"); + buf = xmalloc(buf_len + 1); + buf_fetched = 0; - if (fetchIO_read(f, buf, buf_len) != buf_len) - errx(EXIT_FAILURE, - "Failure during fetch of pkg-vulnerabilities: %s", - fetchLastErrString); + while (buf_fetched < buf_len) { + cur_fetched = fetchIO_read(f, buf + buf_fetched, + buf_len - buf_fetched); + if (cur_fetched == 0) + errx(EXIT_FAILURE, + "Truncated pkg-vulnerabilities received"); + else if (cur_fetched == -1) + errx(EXIT_FAILURE, + "IO error while fetching pkg-vulnerabilities: %s", + fetchLastErrString); + buf_fetched += cur_fetched; + } + buf[buf_len] = '\0'; if (decompress_buffer(buf, buf_len, &decompressed_input, @@ -458,9 +410,7 @@ check_pkg_history1(const char *pkg, const char *pattern) open_brace = inner_brace; } - expanded_pkg = malloc(strlen(pattern)); /* {} are going away... */ - if (expanded_pkg == NULL) - err(EXIT_FAILURE, "malloc failed"); + expanded_pkg = xmalloc(strlen(pattern)); /* {} are going away... */ prefix_len = open_brace - pattern; suffix = close_brace + 1; @@ -495,6 +445,8 @@ check_pkg_history(const char *pkg) size_t i; for (i = 0; i < pv->entries; ++i) { + if (!quick_pkg_match(pv->vulnerability[i], pkg)) + continue; if (strcmp("eol", pv->classification[i]) == 0) continue; if (check_pkg_history1(pkg, pv->vulnerability[i]) == 0) diff --git a/pkgtools/pkg_install/files/admin/check.c b/pkgtools/pkg_install/files/admin/check.c index 2aaac0b7a2e..e71f67e1575 100644 --- a/pkgtools/pkg_install/files/admin/check.c +++ b/pkgtools/pkg_install/files/admin/check.c @@ -1,4 +1,4 @@ -/* $NetBSD: check.c,v 1.5 2008/09/17 15:21:30 joerg Exp $ */ +/* $NetBSD: check.c,v 1.6 2009/02/02 12:35:00 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,9 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -__RCSID("$NetBSD: check.c,v 1.5 2008/09/17 15:21:30 joerg Exp $"); -#endif +__RCSID("$NetBSD: check.c,v 1.6 2009/02/02 12:35:00 joerg Exp $"); /*- * Copyright (c) 1999-2008 The NetBSD Foundation, Inc. @@ -119,10 +117,6 @@ check1pkg(const char *pkgdir, int *filecnt, int *pkgcnt) if (strncmp(p->next->name, CHECKSUM_HEADER, ChecksumHeaderLen) == 0) { if ((md5file = MD5File(file, NULL)) != NULL) { /* Mismatch? */ -#ifdef PKGDB_DEBUG - printf("%s: md5 should=<%s>, is=<%s>\n", - file, p->next->name + ChecksumHeaderLen, md5file); -#endif if (strcmp(md5file, p->next->name + ChecksumHeaderLen) != 0) printf("%s fails MD5 checksum\n", file); @@ -233,8 +227,7 @@ check_pkg(const char *pkg, int *filecnt, int *pkgcnt, int allow_unmatched) errx(EXIT_FAILURE, "No matching pkg for %s.", pkg); } - if (asprintf(&pattern, "%s-[0-9]*", pkg) == -1) - errx(EXIT_FAILURE, "asprintf failed"); + pattern = xasprintf("%s-[0-9]*", pkg); if (match_installed_pkgs(pattern, checkpattern_fn, &arg) == -1) errx(EXIT_FAILURE, "Cannot process pkdbdb"); diff --git a/pkgtools/pkg_install/files/admin/download-vulnerability-list.sh.in b/pkgtools/pkg_install/files/admin/download-vulnerability-list.sh.in new file mode 100644 index 00000000000..1038c0d293c --- /dev/null +++ b/pkgtools/pkg_install/files/admin/download-vulnerability-list.sh.in @@ -0,0 +1,37 @@ +#!/bin/sh + +pkg_admin=@PKG_ADMIN@ + +usage() { + echo 'Usage: download-vulnerability-list -hs [-c config_file]' >& $2 + echo "Please use \`\`pkg_admin fetch-pkg-vulnerabilities'' instead." >& $2 + exit $1 +} + +do_sign= + +args=`getopt c:hs $*` +if [ $? -ne 0 ]; then + usage 1 2 +fi + +set -- $args + +while [ $# -gt 0 ]; do + case "$1" in + -c) + echo "The download-vulnerability-list wrapper does not support -c" >&2 + echo "Please switch to \`\`pkg_admin fetch-pkg-vulnerabilities''." >&2 + exit 1 + ;; + -h) + usage 0 1 + ;; + -s) + do_sign=-s + ;; + esac + shift +done + +exec ${pkg_admin} fetch-pkg-vulnerabilities ${do_sign} diff --git a/pkgtools/pkg_install/files/admin/main.c b/pkgtools/pkg_install/files/admin/main.c index 159b9cbc0c2..41e9838a09a 100644 --- a/pkgtools/pkg_install/files/admin/main.c +++ b/pkgtools/pkg_install/files/admin/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.45 2008/09/17 15:21:30 joerg Exp $ */ +/* $NetBSD: main.c,v 1.46 2009/02/02 12:35:00 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,9 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -__RCSID("$NetBSD: main.c,v 1.45 2008/09/17 15:21:30 joerg Exp $"); -#endif +__RCSID("$NetBSD: main.c,v 1.46 2009/02/02 12:35:00 joerg Exp $"); /*- * Copyright (c) 1999-2008 The NetBSD Foundation, Inc. @@ -98,10 +96,6 @@ usage(void) " delete pkg ... - delete file entries for pkg in database\n" " set variable=value pkg ... - set installation variable for package\n" " unset variable pkg ... - unset installation variable for package\n" -#ifdef PKGDB_DEBUG - " addkey key value - add key and value\n" - " delkey key - delete reference to key\n" -#endif " lsall /path/to/pkgpattern - list all pkgs matching the pattern\n" " lsbest /path/to/pkgpattern - list pkgs matching the pattern best\n" " dump - dump database\n" @@ -112,7 +106,10 @@ usage(void) " audit-pkg [-es] [-t type] ... - check listed packages for vulnerabilities\n" " audit-batch [-es] [-t type] ... - check packages in listed files for vulnerabilities\n" " audit-history [-t type] ... - print all advisories for package names\n" - " config-var name - print current value of the configuration variable\n", + " config-var name - print current value of the configuration variable\n" + " check-signature ... - verify the signature of packages\n" + " x509-sign-package pkg spkg key cert - create X509 signature\n" + " gpg-sign-package pkg spkg - create GPG signature\n", getprogname()); exit(EXIT_FAILURE); } @@ -341,7 +338,6 @@ rebuild_tree(void) int main(int argc, char *argv[]) { - const char *config_file = SYSCONFDIR"/pkg_install.conf"; Boolean use_default_sfx = TRUE; Boolean show_basename_only = FALSE; char lsdir[MaxPathSize]; @@ -407,7 +403,7 @@ main(int argc, char *argv[]) usage(); } - pkg_install_config(config_file); + pkg_install_config(); if (use_default_sfx) (void) snprintf(sfx, sizeof(sfx), "%s", DEFAULT_SFX); @@ -536,48 +532,43 @@ main(int argc, char *argv[]) audit_batch(--argc, ++argv); } else if (strcasecmp(argv[0], "audit-history") == 0) { audit_history(--argc, ++argv); - } -#endif -#ifdef PKGDB_DEBUG - else if (strcasecmp(argv[0], "delkey") == 0) { - int rc; - - if (!pkgdb_open(ReadWrite)) - err(EXIT_FAILURE, "cannot open pkgdb"); - - rc = pkgdb_remove(argv[2]); - if (rc) { - if (errno) - perror("pkgdb_remove"); - else - printf("Key not present in pkgdb.\n"); - } - - pkgdb_close(); - - } else if (strcasecmp(argv[0], "addkey") == 0) { - - int rc; - - if (!pkgdb_open(ReadWrite)) { - err(EXIT_FAILURE, "cannot open pkgdb"); - } - - rc = pkgdb_store(argv[2], argv[3]); - switch (rc) { - case -1: - perror("pkgdb_store"); - break; - case 1: - printf("Key already present.\n"); - break; - default: - /* 0: everything ok */ - break; + } else if (strcasecmp(argv[0], "check-signature") == 0) { +#ifdef HAVE_SSL + struct archive *pkg; + void *cookie; + int rc; + + rc = 0; + for (--argc, ++argv; argc > 0; --argc, ++argv) { + pkg = open_archive(*argv, &cookie); + if (pkg == NULL) { + warnx("%s could not be opened", *argv); + continue; + } + if (pkg_full_signature_check(pkg)) + rc = 1; + close_archive(pkg); } - - pkgdb_close(); - + return rc; +#else + errx(EXIT_FAILURE, "OpenSSL support is not included"); +#endif + } else if (strcasecmp(argv[0], "x509-sign-package") == 0) { +#ifdef HAVE_SSL + --argc; + ++argv; + if (argc != 4) + errx(EXIT_FAILURE, "x509-sign-package takes exactly four arguments"); + pkg_sign_x509(argv[0], argv[1], argv[2], argv[3]); +#else + errx(EXIT_FAILURE, "OpenSSL support is not included"); +#endif + } else if (strcasecmp(argv[0], "gpg-sign-package") == 0) { + --argc; + ++argv; + if (argc != 2) + errx(EXIT_FAILURE, "gpg-sign-package takes exactly two arguments"); + pkg_sign_gpg(argv[0], argv[1]); } #endif else { @@ -631,7 +622,7 @@ set_unset_variable(char **argv, Boolean unset) if ((eq=strchr(argv[0], '=')) == NULL) usage(); - variable = malloc(eq-argv[0]+1); + variable = xmalloc(eq-argv[0]+1); strlcpy(variable, argv[0], eq-argv[0]+1); arg.variable = variable; @@ -663,8 +654,7 @@ set_unset_variable(char **argv, Boolean unset) warnx("no matching pkg for `%s'", *argv); ret++; } else { - if (asprintf(&pattern, "%s-[0-9]*", *argv) == -1) - errx(EXIT_FAILURE, "asprintf failed"); + pattern = xasprintf("%s-[0-9]*", *argv); if (match_installed_pkgs(pattern, set_installed_info_var, &arg) == -1) errx(EXIT_FAILURE, "Cannot process pkdbdb"); diff --git a/pkgtools/pkg_install/files/admin/pkg_admin.1 b/pkgtools/pkg_install/files/admin/pkg_admin.1 index 03e813b848c..061972c31b9 100644 --- a/pkgtools/pkg_install/files/admin/pkg_admin.1 +++ b/pkgtools/pkg_install/files/admin/pkg_admin.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: pkg_admin.1,v 1.18 2008/04/16 00:53:06 joerg Exp $ +.\" $NetBSD: pkg_admin.1,v 1.19 2009/02/02 12:35:00 joerg Exp $ .\" .\" Copyright (c) 1999-2008 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -34,7 +34,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd March 10, 2007 +.Dd May 30, 2008 .Dt PKG_ADMIN 1 .Os .Sh NAME @@ -166,6 +166,10 @@ Check format and hashes in the pkg-vulnerabilties file If .Fl s is given, also check the embedded signature. +.It Cm check-signature Ar file ... +Reports if +.Ar file +is a correctly signed package. .It Cm config-var Ar variable Print the current value of .Ar variable @@ -261,6 +265,20 @@ to remove a variable. Packages that are not installed directly by the user but pulled in as dependencies are marked by setting .Dq automatic=YES . +.It Cm gpg-sign-package pkg +Sign the binary package +.Ar pkg +using GPG. +.It Cm x509-sign-package pkg spkg key cert +Sign the binary package +.Ar pkg +using the key +.Ar key +and the certificate +.Ar cert , +using +.Ar spkg +as output file. .It Cm unset Ar variable pkg ... Remove an installation variable. .El @@ -275,6 +293,20 @@ is the location of the package database directory. The default package database directory is .Pa /var/db/pkg . .El +.Sh CONFIGURATION VARIABLES +The following variables change the behaviour of +.Nm +and are described in +.Xr pkg_install.conf 5 : +.Bl -tag -width CERTIFICATE_ANCHOR_PKGS +.It Ev CERTIFICATE_ANCHOR_PKGS +.It Ev CERTIFICATE_ANCHOR_PKGVULN +.It Ev CERTIFICATE_CHAIN +.It Ev GPG +.It Ev PKGVULNDIR +.It Ev PKGVULNURL +.It Ev IGNORE_URL +.El .Sh FILES .Bl -tag -width /var/db/pkg/pkgdb.byfile.db -compact .It Pa /var/db/pkg/pkgdb.byfile.db @@ -286,6 +318,7 @@ The default package database directory is .Xr pkg_delete 1 , .Xr pkg_info 1 , .Xr pkg_view 1 , +.Xr pkg_install.conf 5 , .Xr pkgsrc 7 .Sh HISTORY The diff --git a/pkgtools/pkg_install/files/admin/pkg_admin.cat1 b/pkgtools/pkg_install/files/admin/pkg_admin.cat1 index 74a53e3a807..f66f88d01aa 100644 --- a/pkgtools/pkg_install/files/admin/pkg_admin.cat1 +++ b/pkgtools/pkg_install/files/admin/pkg_admin.cat1 @@ -181,13 +181,31 @@ EENNVVIIRROONNMMEENNTT package database directory. The default package database direc- tory is _/_v_a_r_/_d_b_/_p_k_g. +CCOONNFFIIGGUURRAATTIIOONN VVAARRIIAABBLLEESS + The following variables change the behaviour of ppkkgg__aaddmmiinn and are + described in pkg_install.conf(5): + + CERTIFICATE_ANCHOR_PKGS + + CERTIFICATE_ANCHOR_PKGVULN + + CERTIFICATE_CHAIN + + GPG + + PKGVULNDIR + + PKGVULNURL + + IGNORE_URL + FFIILLEESS /var/db/pkg/pkgdb.byfile.db /var/db/pkg/<pkg>/+CONTENTS SSEEEE AALLSSOO pkg_add(1), pkg_create(1), pkg_delete(1), pkg_info(1), pkg_view(1), - pkgsrc(7) + pkg_install.conf(5), pkgsrc(7) HHIISSTTOORRYY The ppkkgg__aaddmmiinn command first appeared in NetBSD 1.4. @@ -195,4 +213,4 @@ HHIISSTTOORRYY AAUUTTHHOORRSS The ppkkgg__aaddmmiinn command was written by Hubert Feyrer. -NetBSD 4.0 March 10, 2007 NetBSD 4.0 +NetBSD 4.0 May 26, 2008 NetBSD 4.0 diff --git a/pkgtools/pkg_install/files/audit-packages/AUTHORS b/pkgtools/pkg_install/files/audit-packages/AUTHORS deleted file mode 100644 index f8cf8bc04ae..00000000000 --- a/pkgtools/pkg_install/files/audit-packages/AUTHORS +++ /dev/null @@ -1,11 +0,0 @@ -# $NetBSD: AUTHORS,v 1.1 2007/07/14 20:17:08 adrianp Exp $ - -* The functions that deal with finding packages such as fixpkgname() - foundpkg() and checkforpkg() were taken from the pkg_install - set of tools. Authors for this include Jordan Hubbard, John Kohl, - Alistair Crooks, Hubert Feyrer, Thorsten Frueauf, Rene Hexel, - Christian E. Hopps, Thomas Klausner, Johnny Lam, and Matthias Scheler. - -* This is basically a re-write in C of the audit-packages tool - by Adrian Portelli (adrianp@NetBSD.org). The tool was originally - authored by Alistair G. Crooks (agc@NetBSD.org). diff --git a/pkgtools/pkg_install/files/audit-packages/COPYING b/pkgtools/pkg_install/files/audit-packages/COPYING deleted file mode 100644 index 06166a71426..00000000000 --- a/pkgtools/pkg_install/files/audit-packages/COPYING +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2007 Adrian Portelli <adrianp@NetBSD.org>. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * 3. Neither the name of author(s) nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/pkgtools/pkg_install/files/audit-packages/Makefile.in b/pkgtools/pkg_install/files/audit-packages/Makefile.in deleted file mode 100644 index cd0101d7da9..00000000000 --- a/pkgtools/pkg_install/files/audit-packages/Makefile.in +++ /dev/null @@ -1,81 +0,0 @@ -# $NetBSD: Makefile.in,v 1.5 2008/03/10 12:13:55 wiz Exp $ - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -sbindir = @sbindir@ -mandir = @mandir@ -datarootdir= @datarootdir@ - -pkgdbdir = @pkgdbdir@ -sysconfdir = @sysconfdir@ - -man5dir = $(mandir)/man5 -man1dir = $(mandir)/man1 -cat5dir = $(mandir)/cat5 -cat1dir = $(mandir)/cat1 -sharedir = $(prefix)/share/examples/pkg_install - -do_subst = sed -e 's,@gzcat@,_gzcat_,g' - -CC = @CC@ -CCLD= $(CC) -LIBS= -linstall @LIBS@ -CPPFLAGS= @CPPFLAGS@ -I. -I../lib -DHOST=\"$(CANONICAL_HOST)\" -DPKGSRC -CPPFLAGS+= -DPREFIX=\"$(prefix)\" -DSYSCONFDIR=\"$(sysconfdir)\" -DEFS= @DEFS@ -CFLAGS= @CFLAGS@ -LDFLAGS= @LDFLAGS@ -L../lib -SUBST_FILES= audit-packages.conf.5 audit-packages.conf.cat5 audit-packages.conf download-vulnerability-list.sh - -INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -CANONICAL_HOST = @CANONICAL_HOST@ - -LINK= $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@ -COMPILE= $(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) - -audit-packages_OBJS = audit-packages.o - -.c.o: - $(COMPILE) -c $< -o $@ - -all: subst audit-packages - -audit-packages: $(audit-packages_OBJS) - $(LINK) $(audit-packages_OBJS) $(LIBS) - -subst: - @list='$(SUBST_FILES)'; for f in $$list; do \ - $(do_subst) $$f > $$f.tmp; \ - rm $$f; mv $$f.tmp $$f; \ - done - -clean: - rm -f *.o audit-packages - -install: - $(INSTALL) -m 755 -d ${DESTDIR}$(sbindir) - $(INSTALL) -m 755 -d ${DESTDIR}$(man1dir) - $(INSTALL) -m 755 -d ${DESTDIR}$(man5dir) - $(INSTALL) -m 755 -d ${DESTDIR}$(cat1dir) - $(INSTALL) -m 755 -d ${DESTDIR}$(cat5dir) - $(INSTALL) -m 755 -d ${DESTDIR}$(sharedir) - - $(INSTALL_PROGRAM) audit-packages $(DESTDIR)$(sbindir)/audit-packages - $(INSTALL_SCRIPT) download-vulnerability-list.sh \ - $(DESTDIR)$(sbindir)/download-vulnerability-list - $(INSTALL_DATA) audit-packages.conf \ - $(DESTDIR)$(sharedir)/audit-packages.conf - $(INSTALL_DATA) audit-packages.1 $(DESTDIR)$(man1dir)/audit-packages.1 - $(INSTALL_DATA) audit-packages.cat1 \ - $(DESTDIR)$(cat1dir)/audit-packages.0 - $(INSTALL_DATA) audit-packages.conf.5 \ - $(DESTDIR)$(man5dir)/audit-packages.conf.5 - $(INSTALL_DATA) audit-packages.conf.cat5 \ - $(DESTDIR)$(cat5dir)/audit-packages.conf.0 - $(INSTALL_DATA) download-vulnerability-list.1 \ - $(DESTDIR)$(man1dir)/download-vulnerability-list.1 - $(INSTALL_DATA) download-vulnerability-list.cat1 \ - $(DESTDIR)$(cat1dir)/download-vulnerability-list.0 diff --git a/pkgtools/pkg_install/files/audit-packages/README b/pkgtools/pkg_install/files/audit-packages/README deleted file mode 100644 index d1fd769acc1..00000000000 --- a/pkgtools/pkg_install/files/audit-packages/README +++ /dev/null @@ -1,5 +0,0 @@ -# $NetBSD: README,v 1.1 2007/07/14 20:17:08 adrianp Exp $ - -audit-packages, an easy way to audit the current machine, checking -for each vulnerability listed by the security officer. If a vulnerable -package is installed, it will be shown by output to stdout. diff --git a/pkgtools/pkg_install/files/audit-packages/audit-packages.1.in b/pkgtools/pkg_install/files/audit-packages/audit-packages.1.in deleted file mode 100644 index fcfe3d777be..00000000000 --- a/pkgtools/pkg_install/files/audit-packages/audit-packages.1.in +++ /dev/null @@ -1,378 +0,0 @@ -.\" $NetBSD: audit-packages.1.in,v 1.6 2008/01/07 22:27:59 adrianp Exp $ -.\" -.\" Copyright (c) 2003 Jeremy C. Reed. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by Jeremy C. Reed -.\" for the NetBSD project. -.\" 4. The name of the author may not be used to endorse or promote -.\" products derived from this software without specific prior written -.\" permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS -.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -.\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd January 7, 2008 -.Os -.Dt AUDIT-PACKAGES 1 -.Sh NAME -.Nm audit-packages , -.Nm download-vulnerability-list -.Nd show vulnerabilities in installed packages -.Sh SYNOPSIS -.Nm -.Op Fl deqsVv -.Op Fl c Ar config_file -.Op Fl F Ar file -.Op Fl g Ar file -.Op Fl h Ar file -.Op Fl K Ar pkg_dbdir -.Op Fl n Ar package -.Op Fl p Ar package -.Op Fl Q Ar varname -.Op Fl t Ar type -.Nm download-vulnerability-list -.Op Fl hs -.Op Fl c Ar config_file -.Sh DESCRIPTION -The -.Nm -program compares the installed packages with the -.Pa pkg-vulnerabilities -file and reports any known security issues to standard output. -This output contains the name and version of the package, the -type of vulnerability, and an URL for further information for each -vulnerable package. -.Pp -The following flags are supported: -.Bl -tag -width XcXconfigXfileXX -.It Fl d -Attempt to download the vulnerabilities file using the -.Nm download-vulnerability-list -script before scanning the installed packages for vulnerabilities. -.It Fl e -Check for end-of-life (eol) packages. -.It Fl q -Be ``quiet'' in emitting report headers and such, just dump the -raw info (basically, assume a non-human reading). -.It Fl s -Verify the signature of the current -.Pa pkg-vulnerabilities -file. -The key used to sign the file is available from: -.Pa ftp://ftp.netbsd.org/pub/NetBSD/security/PGP/pkgsrc-security@NetBSD.org.asc -.Pp -In order for this to function correctly the above key must be -added to the gpg keyring of the user who runs -.Ic audit-packages -s -and/or -.Ic download-vulnerability-list -s . -In addition to this the gpg binary must be installed on your system. -The path to the gpg binary can be set in -.Xr audit-packages.conf 5 . -.Pp -The requirement for GnuPG may go away in the future when a suitable -replacement is implemented. -.It Fl V -Display the version number and exit. -.It Fl v -Be more verbose. -Specify multiple -.Fl v -flags to increase verbosity. -Currently a maximum level of three is supported. -.It Fl c Ar config_file -Specify a custom -.Ar config_file -configuration file to use. -.It Fl F Ar file -Load a -.Ar file -containing a list of package names and or package patterns to check. -.It Fl g Ar file -Compute the SHA512 hash on -.Ar file . -.It Fl h Ar file -Check the SHA512 hash of a -.Ar file -against the internally stored value. -.It Fl K Ar pkg_dbdir -Use package database directory -.Ar pkg_dbdir . -.It Fl n Ar package -Check only the package -.Ar package -for vulnerabilities. -.It Fl p Ar package -Check only the installed package -.Ar package -for vulnerabilities. -.It Fl Q Ar varname -Display the current value of -.Ar varname -and exit. -Currently supported -.Ar varname -are -.Dv GPG , -.Dv PKGVULNDIR , -and -.Dv IGNORE_URLS . -.It Fl t Ar type -Only check for the specified -.Ar type -of vulnerability. -.El -.Pp -The -.Nm download-vulnerability-list -program downloads the -.Pa pkg-vulnerabilities -file from -.Pa ftp.NetBSD.org -using -.Xr ftp 1 -by default. -This vulnerabilities file documents all known security issues in -pkgsrc packages and is kept up-to-date by the -.Nx -pkgsrc-security team. -.Pp -The following flags are supported: -.Bl -tag -width XcXconfigXfileXX -.It Fl c Ar config_file -Specify a custom -.Ar config_file -configuration file to use. -.It Fl h -Display program usage. -.It Fl s -Verify the signature of the current -.Pa pkg-vulnerabilities -file. -In order for this to function correctly you will need to add the -pkgsrc Security Team key to your gpg keyring and trust it. -The key is available from: -.Pa ftp://ftp.netbsd.org/pub/NetBSD/security/PGP/pkgsrc-security@NetBSD.org.asc -In addition to this the gpg binary must be installed on your system. -The path to the gpg binary can be set in -.Xr audit-packages.conf 5 . -.El -.Pp -By default -.Nm download-vulnerability-list -will download a compressed version of -.Pa pkg-vulnerabilities -from ftp.netbsd.org. -The default file downloaded is compressed using -.Xr gzip 1 . -The compression tool used can set in -.Xr audit-packages.conf 5 . -Currently only -.Xr gzcat 1 -and -.Xr bzcat 1 -are supported. -.Pp -.Nm audit-packages -and/or -.Nm download-vulnerability-list -need not be run by the root user. They will function as an unpriveleged -user just so long as the user chosen has permmission to write the -downloded -.Pa pkg-vulnerabilites -file to the location specified in -.Xr audit-packages.conf 5 . -.Pp -Each line lists the package and vulnerable versions, the type of exploit, -and an Internet address for further information: -.Bl -item -.It -.Aq package pattern -.Aq type -.Aq url -.El -.Pp -The type of exploit can be any text, although -some common types of exploits listed are: -.Bl -bullet -compact -offset indent -.It -cross-site-html -.It -cross-site-scripting -.It -denial-of-service -.It -eol -.It -file-permissions -.It -local-access -.It -local-code-execution -.It -local-file-read -.It -local-file-removal -.It -local-file-write -.It -local-root-file-view -.It -local-root-shell -.It -local-symlink-race -.It -local-user-file-view -.It -local-user-shell -.It -privacy-leak -.It -remote-code-execution -.It -remote-command-inject -.It -remote-file-creation -.It -remote-file-read -.It -remote-file-view -.It -remote-file-write -.It -remote-key-theft -.It -remote-root-access -.It -remote-root-shell -.It -remote-script-inject -.It -remote-server-admin -.It -remote-use-of-secret -.It -remote-user-access -.It -remote-user-file-view -.It -remote-user-shell -.It -unknown -.It -weak-authentication -.It -weak-encryption -.It -weak-ssl-authentication -.El -.Pp -The type -.Pa eol -implies that the package is no longer maintained by the software vendor but -is provided by the pkgsrc team for your convenience only. -It may contain any number of the above mentioned vulnerabilities. -Any packages of type eol are not reported by default. -Run -.Nm Fl e -to also report on eol packages. -.Pp -By default, the vulnerabilities file is stored in the -.Dv PKG_DBDIR -directory. -On a standard installation this will be set to @pkgdbdir@. -If you have installed pkgsrc on a supported platform this will be what -ever you specifed when bootstrapping pkgsrc i.e., -.Fl -pkgdbdir Aq Ar pkgdbdir . -The path to the -.Pa pkg-vulnerabilities -file can be set in -.Xr audit-packages.conf 5 . -.Sh EXIT STATUS -.Ex -std audit-packages -.Sh FILES -.Bl -tag -.It Pa @pkgdbdir@/pkg-vulnerabilities -Vulnerabilities database. -.It Pa @sysconfdir@/audit-packages.conf -.Nm -configuration file. -.It Pa ftp://ftp.netbsd.org/pub/NetBSD/security/PGP/pkgsrc-security@NetBSD.org.asc -Key used to sign the vulnerabilities file. -.El -.Sh EXAMPLES -The -.Nm download-vulnerability-list -command can be run via -.Xr cron 8 -to update the -.Pa pkg-vulnerabilities -file daily. -.Nm -can be run via -.Xr cron 8 -(or with -.Nx Ap s -.Pa /etc/security.local -daily security script). -.Pp -The -.Nm download-vulnerability-list -command can be forced to use IPv4 with the following setting in -@sysconfdir@/audit-packages.conf: -.Pp -FETCH_ARGS="-4" -.Pp -The -.Nm download-vulnerability-list -command can be forced to use http to download the -.Pa pkg-vulnerabilities -file with the following setting in -@sysconfdir@/audit-packages.conf: -.Pp -FETCH_PROTO="http" -.Sh SEE ALSO -.Xr pkg_info 1 , -.Xr audit-packages.conf 5 , -.Xr mk.conf 5 , -.Xr pkgsrc 7 , -.Rs -.%T "Documentation on the NetBSD Package System" -.Re -.Sh HISTORY -.An -nosplit -The -.Nm -and -.Nm download-vulnerability-list -commands were originally implemented and added to -.Nx Ap s -pkgsrc by -.An Alistair Crooks -on September 19, 2000. -During April 2007 -.Nm -was re-written by -.An Adrian Portelli -and support was added for compressed files and checking signatures -on downloaded files. -The original idea came from Roland Dowdeswell and Bill Sommerfeld. diff --git a/pkgtools/pkg_install/files/audit-packages/audit-packages.c b/pkgtools/pkg_install/files/audit-packages/audit-packages.c deleted file mode 100644 index a03ac51b008..00000000000 --- a/pkgtools/pkg_install/files/audit-packages/audit-packages.c +++ /dev/null @@ -1,1156 +0,0 @@ -/* $NetBSD: audit-packages.c,v 1.12 2008/01/07 22:27:59 adrianp Exp $ */ - -/* - * Copyright (c) 2007 Adrian Portelli <adrianp@NetBSD.org>. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * 3. Neither the name of author(s) nor the names of its contributors - * may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <nbcompat.h> -#include <stdio.h> -#include <stdlib.h> -#include <limits.h> -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#ifdef HAVE_STDINT_H -#include <stdint.h> -#endif -#if defined(HAVE_ERR_H) || !defined(PKGSRC) -#include <err.h> -#else -#include <nbcompat/err.h> -#endif -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/time.h> - -/* depending where we are being built pull in crypto support */ -#ifdef PKGSRC -#include <nbcompat/sha2.h> -#else -#include <sha2.h> -#endif - -#include "lib.h" - -#ifndef PATH_MAX -# ifdef MAXPATHLEN -# define PATH_MAX MAXPATHLEN -# else -# define PATH_MAX 1024 -# endif -#endif - -/* NetBSD has a special layout as it is included in the base OS */ -#ifdef NETBSD -# define PREFIX "/usr" -# define PKGPREFIX "/usr/pkg" -# define SYSCONFDIR "/etc" -#else -# define PKGPREFIX PREFIX -#endif - -/* macros */ -#define STRIP(c) ((c) == '\n' || (c) == '\'' || (c) == '\"' || \ - (c) == '\t' || (c) == ' ' || (c) == '=') - -/* default for src/ install */ -const char DVL_BIN[] = PREFIX"/sbin/download-vulnerability-list"; -const char EOL_URL[] = "ftp://ftp.NetBSD.org/pub/NetBSD/packages/vulns"; - -const int MSGSIZE = 1024; /* max message size */ -const int MAXLINELEN = 4092; /* max line length */ -const int MAXPKGNAMELEN = 1024; /* max pkg name */ -const int FORMAT[] = {1, 1, 0}; /* file format ver */ -const int MAXVERBOSE = 3; /* max verbosity */ - -/* globals (from config file) */ -char *verify_bin = PKGPREFIX"/bin/gpg"; /* verify bin location */ -char *pvfile = NULL; /* p-v file location */ -char *pvdir = NULL; /* p-v dir location */ -char *ignore = NULL; /* ignore urls */ - -/* globals */ -char *conf_file = SYSCONFDIR"/audit-packages.conf"; /* config file location */ -char *program_name; /* the program name */ - -/* program defaults */ -int verbose = 0; /* be quiet */ -Boolean eol = FALSE; /* don't check eol */ -Boolean quiet = FALSE; /* display full data */ - -int main(int, char **); -static void *safe_calloc(size_t, size_t); -static char *checkforpkg(const char *); -static void usage(void); -static int dvl(void); -static void old_pvfile(void); -static void pv_format(FILE *); -static char *gen_hash(char *); -static char *get_hash(char *); -static int check_hash(char *); -static int check_sig(char *); -static int pv_message(char *[], char *); -static int ap_ignore(char *[]); -static void show_info(char *); -static void set_pvfile(const char *); -static char *clean_conf(char *); -static int get_confvalues(void); -static char *safe_strdup(const char *); -static int checkforvuln(FILE *, char *, Boolean, char *, Boolean); -static char *trim_r(char *); - -/* - * TODO: - * - * built in gz/bzip2 support - * merge download-vulnerability-list(1) - * - */ - -/* - * get the options for what we are doing, and do the actual processing of - * the pkg-vulnerabilities file - */ -int -main(int argc, char **argv) -{ - char *bpkg = NULL; - char *bpkg_ptr = NULL; - char *pkg_type = NULL; - char *check_hash_file = NULL; - char *gen_hash_file = NULL; - char *hash_generated = NULL; - char *query_var = NULL; - char *pkgname = NULL; - char *bulk_file = NULL; - - int ch = 0; - int retval = -1; - - Boolean download = FALSE; - Boolean pkg_installed = FALSE; - Boolean verify_sig = FALSE; - Boolean check_one = FALSE; - Boolean type = FALSE; - Boolean cli_check_hash = FALSE; - Boolean cli_gen_hash = FALSE; - Boolean info = FALSE; - Boolean bulk = FALSE; - Boolean vuln_found = FALSE; - - FILE *pv, *bf; - - program_name = argv[0]; - - setprogname(program_name); - - set_pvfile(_pkgdb_getPKGDB_DIR()); - - opterr = 0; - - while ((ch = getopt(argc, argv, ":dveqK:n:h:g:c:p:st:F:Q:V")) != -1) { - - switch (ch) { - - case 'h': - check_hash_file = optarg; - cli_check_hash = TRUE; - break; - - case 'g': - gen_hash_file = optarg; - cli_gen_hash = TRUE; - break; - - case 'd': - download = TRUE; - break; - - case 'e': - eol = TRUE; - break; - - case 'K': - _pkgdb_setPKGDB_DIR(optarg); - break; - - case 'n': - pkgname = optarg; - check_one = TRUE; - pkg_installed = FALSE; - break; - - case 'c': - conf_file = optarg; - break; - - case 'p': - pkgname = optarg; - check_one = TRUE; - pkg_installed = TRUE; - break; - - case 'q': - quiet = TRUE; - break; - - case 'F': - bulk_file = optarg; - bulk = TRUE; - break; - - case 's': - verify_sig = TRUE; - break; - - case 't': - pkg_type = optarg; - type = TRUE; - break; - - case 'v': - if (verbose <= MAXVERBOSE) - ++verbose; - break; - - case 'Q': - query_var = optarg; - info = TRUE; - break; - - case 'V': - show_version(); - /* not reached */ - - default: - usage(); - break; - } - } - argc -= optind; - argc += optind; - - /* - * generate the hash for a specified file (-g <file>) - * - * this is purely for download-vulnerability-list, users - * should not be directly calling audit-packages with -g <file>. - */ - if (cli_gen_hash == TRUE) { - - hash_generated = gen_hash(gen_hash_file); - fprintf(stdout, "%s\n", hash_generated); - - exit(EXIT_SUCCESS); - } - - /* - * check the hash and/or sig for a specified file - * - * if -h <file> is given then just the hash is checked - * but if -s -h <file> are given then both the hash and the - * sig are checked. this is purely for - * download-vulnerability-list, users should not be directly - * calling audit-packages with -h <file> or -s -h <file>. - */ - if (cli_check_hash == TRUE) { - - retval = check_hash(check_hash_file); - - if (retval != 0) { - exit(EXIT_FAILURE); - } else { - if (verify_sig == TRUE) { - retval = check_sig(check_hash_file); - - if (retval != 0) { - exit(EXIT_FAILURE); - } else { - exit(EXIT_SUCCESS); - } - } else { - exit(EXIT_SUCCESS); - } - } - } - - /* get the config file values */ - retval = get_confvalues(); - - /* if we found some IGNORE_URLS lines */ - if (verbose >= 2) { - fprintf(stderr, "debug2: Using PKGDB_DIR: %s\n", _pkgdb_getPKGDB_DIR()); - fprintf(stderr, "debug2: Using pkg-vulnerabilities file: %s\n", pvfile); - fprintf(stderr, "debug2: Using verify tool: %s\n", verify_bin); - - if (ignore != NULL) { - fprintf(stderr, "debug2: Using ignore directives: %s\n", ignore); - } else { - fprintf(stderr, "debug2: No ignore directives found.\n"); - } - } - - /* now that we have read in the config file we can show the info */ - if (info == TRUE) { - show_info(query_var); - exit(EXIT_SUCCESS); - } - - /* we need to download the file first and check it went ok */ - if (download == TRUE) { - retval = dvl(); - - if (retval != 0) - exit(EXIT_FAILURE); - } - - /* open pvfile */ - if ((pv = fopen(pvfile, "r")) == NULL) { - errx(EXIT_FAILURE, "Unable to open: %s", pvfile); - } - - /* check for an old vulnerabilities file if we're being verbose */ - if ((verbose >= 1) && (download == FALSE)) - old_pvfile(); - - /* check the #FORMAT from the pkg-vulnerabilities file */ - pv_format(pv); - - rewind(pv); - - /* check the hashes */ - retval = check_hash(pvfile); - - if (retval != 0) { - errx(EXIT_FAILURE, "Hash mismatch."); - } else { - if (verbose >= 2) - fprintf(stderr, "debug2: Hash match.\n"); - } - - /* do signature checking - if required */ - if (verify_sig == TRUE) { - retval = check_sig(pvfile); - - if (retval != 0) { - errx(EXIT_FAILURE, "Signature verification failure."); - } - } - - /* - * this is for -p: - * check a specific installed package for vulnerabilities - * if we find that it's not installed, just exit silently - */ - if ((pkg_installed == TRUE) && (check_one == TRUE)) { - if ((checkforpkg(pkgname)) != NULL) { - if (verbose >= 3) - fprintf(stderr, "debug3: Package found to be installed (-p): %s\n", pkgname); - } else { - if (verbose >= 3) - fprintf(stderr, "debug3: Package not found to be installed (-p): %s\n", pkgname); - exit(EXIT_SUCCESS); - } - } - - /* - * this is for -n: - * check a specific package for vulnerabilities - * here we don't care if it's installed or not - */ - if ((pkg_installed == FALSE) && (check_one == TRUE)) { - if (verbose >= 3) - fprintf(stderr, "debug3: Looking for package (-n): %s\n", pkgname); - } - - rewind(pv); - - /* check a package for vulnerabilities */ - if (bulk == FALSE) { - retval = checkforvuln(pv, pkgname, type, pkg_type, check_one); - - if (retval != 0) - vuln_found = TRUE; - } else { - check_one = TRUE; - - if ((bf = fopen(bulk_file, "r")) == NULL) { - errx(EXIT_FAILURE, "Unable to open: %s", bulk_file); - } - - bpkg = safe_calloc(MAXLINELEN, sizeof(char)); - - while ((bpkg_ptr = fgets(bpkg, MAXLINELEN, bf)) != NULL) { - - /* what we're not interested in */ - if ((bpkg[0] == '#') || (bpkg[0] == '\n')) - continue; - - bpkg = trim_r(bpkg); - - retval = checkforvuln(pv, bpkg, type, pkg_type, check_one); - if (retval != 0) - vuln_found = TRUE; - } - - free(bpkg); - - /* bail if ferror is set */ - if (ferror(bf) != 0) - errx(EXIT_FAILURE, "Unable to read: %s", bulk_file); - - fclose(bf); - } - - fclose(pv); - - if ((verbose >= 1) && (vuln_found == FALSE)) - fprintf(stderr, "No vulnerable packages found.\n"); - - if (vuln_found == FALSE) { - return EXIT_SUCCESS; - } else { - return EXIT_FAILURE; - } -} - -/* end main() */ - -/* - * check a given pattern/package for a hit in the pkg-vulnerabilities file - */ -static int -checkforvuln(FILE *vuln_file, char *package, Boolean type, char *pkg_type, Boolean check_one) -{ - Boolean vuln_found = FALSE; - - char *line = NULL; - char *line_tmp = NULL; - char *pv_token = NULL; - char *pv_entry[] = {NULL, NULL, NULL}; - - int line_count = 0; - int i = 0; - int retval = -1; - int vuln_count = 0; - - line = safe_calloc(MAXLINELEN, sizeof(char)); - - while (fgets(line, MAXLINELEN, vuln_file) != NULL) { - - ++line_count; - - /* what we're not interested in */ - if ((line[0] == '#') || - (line[0] == '\n') || - (strncmp(line, "-----BEGIN", 10) == 0) || - (strncmp(line, "Hash:", 5) == 0)) - continue; - - /* effective EOF */ - if (strncmp(line, "Version:", 8) == 0) - break; - - i = 0; - - line_tmp = trim_r(line); - - do { - pv_token = strsep(&line_tmp, " \t"); - - /* - * pv_entry[0] = pattern - * pv_entry[1] = type - * pv_entry[2] = URL - */ - - /* loop processing all tokens into pv_entry[] */ - if ((pv_token != NULL) && - (pv_token[0] != '\0') && - (pv_token[0] != ' ')) { - /* three tokens make a valid entry */ - pv_entry[i] = pv_token; - ++i; - } - } while ((pv_token != NULL) && (i <= 2)); - - /* look for invalid (short) entries */ - if (i < 3) { - errx(EXIT_FAILURE, "Invalid pkg-vulnerabilities entry rejected on line %i.", line_count); - } - - /* if doing type checking, ignore what we don't want to see */ - if (type == TRUE) { - if (strcmp(pv_entry[1], pkg_type) != 0) - continue; - } - - /* deal with URLs that we're ignorning */ - if (ignore != NULL) { - retval = ap_ignore(pv_entry); - - /* if we got an ignore hit then stop here */ - if (retval == 1) - continue; - } - - if (check_one == TRUE) { - - /* - * if we're checking for just one package (i.e. - * check_one) regardless if it's installed or not - * (i.e. -n and -p) then use pkg_match - * to see if we have a hit using pattern - * matching. - */ - - if ((pkg_match(pv_entry[0], package)) == 1) - vuln_found = TRUE; - } else { - - /* - * if we're not checking for a specific package - * then run checkforpkg to see if the - * pattern in pv_entry[0] is installed. - */ - - package = checkforpkg(pv_entry[0]); - if (package != NULL) - vuln_found = TRUE; - } - - /* display the messages for all the vulnerable packages seen */ - if (vuln_found == TRUE) { - - /* EOL or vulnerable message and increment the count */ - retval = pv_message(pv_entry, package); - vuln_count = vuln_count + retval; - - /* reset the found flag */ - vuln_found = FALSE; - } - } - - /* bail if ferror is set */ - if (ferror(vuln_file) != 0) - errx(EXIT_FAILURE, "Unable to read specified pkg-vulnerabilities file: %s", pvfile); - - rewind(vuln_file); - free(line); - - return vuln_count; -} - -/* - * wrap calloc in some common error checking - */ -static void * -safe_calloc(size_t number, size_t size) -{ - void *ptr; - - ptr = calloc(number, size); - - if (ptr == NULL) { - errx(EXIT_FAILURE, "Unable to allocate memory at line: %d.", __LINE__); - } - - return ptr; -} - -/* - * strip any trailing characters we don't want from a string - */ -static char * -trim_r(char *trimmer) -{ - int i = 0; - - for (i = (strlen(trimmer) - 1); i > 0; --i) { - if (STRIP(trimmer[i])) { - trimmer[i] = '\0'; - } else { - i = 0; - } - } - - return trimmer; -} - -/* - * clean a valid line from the configuration file - */ -static char * -clean_conf(char *conf_line) -{ - size_t len = 0; - char *token = NULL; - char *cp; - - if (((cp = strchr(conf_line, '\n')) == NULL) || - ((cp = strchr(conf_line, '=')) == NULL)) { - /* no newline or no '=' */ - errx(EXIT_FAILURE, "Malformed entry in audit-packages.conf file."); - } - - /* split the line up and get what we need */ - token = strchr(conf_line, '='); - - /* remove any leading characters we don't want */ - while (STRIP(*token)) { - token++; - } - - /* remove any trailing characters we don't want */ - token = trim_r(token); - - len = strlen(token); - - /* look for entries with no associated value */ - if (len == 0) { - token = NULL; - } - - return token; -} - -/* - * read in our values from a configuration file - */ -static int -get_confvalues(void) -{ - FILE *conf; - char *line_ptr = NULL; - char *line = NULL; - char *retval = NULL; - Boolean f_ignore = FALSE; - Boolean f_verify_bin = FALSE; - Boolean f_set_pvfile = FALSE; - - if ((conf = fopen(conf_file, "r")) == NULL) { - if (verbose >= 2) - fprintf(stderr, "debug2: No configuration file found.\n"); - return 0; - } else { - if (verbose >= 1) - fprintf(stderr, "Using configuration file: %s\n", conf_file); - } - - line = safe_calloc(MAXLINELEN, sizeof(char)); - - while ((line_ptr = fgets(line, MAXLINELEN, conf)) != NULL) { - - /* what we're not interested in */ - if ((line[0] == '#') || (line[0] == '\n')) - continue; - - if ((strncmp(line, "IGNORE_URLS", 11) == 0) && - (f_ignore == FALSE)) { - retval = clean_conf(line); - if (retval != NULL) { - ignore = safe_strdup(retval); - f_ignore = TRUE; - } - } - else if ((strncmp(line, "GPG", 3) == 0) && - (f_verify_bin == FALSE)) { - retval = clean_conf(line); - if (retval != NULL) { - verify_bin = safe_strdup(retval); - f_verify_bin = TRUE; - } - } - else if ((strncmp(line, "PKGVULNDIR", 9) == 0) && - (f_set_pvfile == FALSE)) { - retval = clean_conf(line); - if (retval != NULL) { - set_pvfile(retval); - f_set_pvfile = TRUE; - } - } - - retval = NULL; - } - - /* bail if eof has not been set or ferror is set */ - if ((feof(conf) == 0) || (ferror(conf) != 0)) - errx(EXIT_FAILURE, "Unable to read specified configuration file: %s", conf_file); - - free(line); - fclose(conf); - - return 0; -} - -/* - * check to see if a package exists - */ -static char * -checkforpkg(const char *package) -{ - char *retval = NULL; - - retval = find_best_matching_installed_pkg(package); - - if (retval == NULL && !ispkgpattern(package)) { - char *pattern; - - if (asprintf(&pattern, "%s-[0-9]*", package) == -1) - errx(EXIT_FAILURE, "asprintf failed"); - - retval = find_best_matching_installed_pkg(pattern); - free(pattern); - } - - return retval; -} - -/* - * usage message for this program - */ -static void -usage(void) -{ - fprintf(stderr, "Usage: %s [-deqsVv] [-c config_file] [-F file] [-g file] [-h file] [-K pkg_dbdir] [-n package] [-p package] [-Q varname ] [-t type]\n", program_name); - fprintf(stderr, "\t-d : Run the download-vulnerability-list script before anything else.\n"); - fprintf(stderr, "\t-e : Check for end-of-life (eol) packages.\n"); - fprintf(stderr, "\t-q : Be quiet and just dump the detected vulnerable package names.\n"); - fprintf(stderr, "\t-s : Verify the signature of the pkg-vulnerabilities file.\n"); - fprintf(stderr, "\t-V : Display version and exit.\n"); - fprintf(stderr, "\t-v : Be more verbose. Specify multiple -v flags to increase verbosity.\n"); - fprintf(stderr, "\t-c : Specify a custom configuration file to use.\n"); - fprintf(stderr, "\t-F : Check all packages listed in a file for vulnerabilities.\n"); - fprintf(stderr, "\t-g : Compute the hash of a file.\n"); - fprintf(stderr, "\t-h : Check the hash of a file against the internally stored value.\n"); - fprintf(stderr, "\t-K : Use pkg_dbdir as PKG_DBDIR.\n"); - fprintf(stderr, "\t-n : Check a specific package for vulnerabilities.\n"); - fprintf(stderr, "\t-p : Check a specific installed package for vulnerabilities.\n"); - fprintf(stderr, "\t-Q : Display the current value of varname and exit.\n"); - fprintf(stderr, "\t-t : Only check for a specific type of vulnerability.\n"); - exit(EXIT_SUCCESS); -} - -/* - * we need to download the file first - */ -static int -dvl(void) -{ - int retval = -1; - - /* execute download-vulnerability-list */ - retval = fexec(DVL_BIN, NULL); - - if (retval != 0) { - errx(EXIT_FAILURE, "Failure running: %s", DVL_BIN); - } - - return retval; -} - -/* - * check for an old vulnerabilities file if we're being verbose - */ -static void -old_pvfile(void) -{ - float t_diff; - int long t_current; - time_t t_pvfile; - struct stat pvstat; - struct timeval now_time = {0, 0}; - - /* we already know it exists */ - stat(pvfile, &pvstat); - - if ((gettimeofday(&now_time, NULL)) != 0) { - warnx("Unable to get current time. You pkg-vulnerabilities file may be out of date."); - } else { - /* difference between the file and now */ - t_current = now_time.tv_sec; - t_pvfile = pvstat.st_ctime; - t_diff = (((((float) t_current - (float) t_pvfile) / 60) / 60) / 24); - - if (t_diff >= 7) - fprintf(stderr, "%s more than a week old, continuing...\n", pvfile); - - if (verbose >= 2) - fprintf(stderr, "debug2: pkg-vulnerabilities file %.2f day(s) old.\n", t_diff); - } -} - -/* - * get the #FORMAT from the pkg-vulnerabilities file - */ -static void -pv_format(FILE * pv) -{ - char *line = NULL; - char *line_ptr; - - int major = 0; - int minor = 0; - int teeny = 0; - int format_found = 0; - - if (verbose >= 3) - fprintf(stderr, "debug3: File format required: #FORMAT %i.%i.%i\n", FORMAT[0], FORMAT[1], FORMAT[2]); - - line = safe_calloc(MAXLINELEN, sizeof(char)); - - while ((line_ptr = fgets(line, MAXLINELEN, pv)) != NULL) { - - /* this time round this is all we're interested in */ - if (strncmp(line, "#FORMAT", 6) == 0) { - - sscanf(line, "#FORMAT %i.%i.%i", - &major, &minor, &teeny); - - if (line[strlen(line) - 1] == '\n') - line[strlen(line) - 1] = '\0'; - - format_found = 1; - - if (verbose >= 3) - fprintf(stderr, "debug3: File format detected: %s\n", line); - - break; - } - } - - /* compare the #FORMAT with what we expect to see */ - if (format_found == 1) { - if ((major < FORMAT[0]) || - (minor < FORMAT[1]) || - (teeny < FORMAT[2])) { - errx(EXIT_FAILURE, "Your pkg-vulnerabilites file is out of date.\nPlease update audit-packages and run download-vulnerability-list again."); - } - } else { - errx(EXIT_FAILURE, "No file format version found in: %s.\nPlease update audit-packages and run download-vulnerability-list again.", pvfile); - } - - free(line); -} - -/* - * extract the stored hash in the pkg-vulnerabilities file - */ -static char * -get_hash(char *hash_input) -{ - char *line = NULL; - char *hash = NULL; - char *line_ptr = NULL; - - int hash_found = 0; - - FILE *hash_in; - - if ((hash_in = fopen(hash_input, "r")) == NULL) { - errx(EXIT_FAILURE, "Unable to open: %s", hash_input); - } - - line = safe_calloc(MAXLINELEN, sizeof(char)); - - while ((line_ptr = fgets(line, MAXLINELEN, hash_in)) != NULL) { - if (strncmp(line, "#CHECKSUM SHA512", 16) == 0) { - - hash = safe_calloc(SHA512_DIGEST_STRING_LENGTH, sizeof(char)); - sscanf(line, "#CHECKSUM SHA512 %129s", hash); - hash_found = 1; - - break; - } - } - - if (hash_found == 0) { - errx(EXIT_FAILURE, "No hash found in: %s\nPlease update audit-packages and run download-vulnerability-list again.", pvfile); - } - - fclose(hash_in); - free(line); - - return hash; -} - -/* - * check the internally stored hash against the computed hash (-h <file>) - */ -static int -check_hash(char *hash_input) -{ - int retval = -1; - char *hash_stored = NULL; - char *hash_generated = NULL; - - hash_generated = gen_hash(hash_input); - - /* if gen_hash() failed then return now */ - if (hash_generated == NULL) - return retval; - - if (verbose >= 2) - fprintf(stderr, "debug2: Hash generated: %s\n", hash_generated); - - hash_stored = get_hash(hash_input); - - /* if get_hash() failed then return now */ - if (hash_stored == NULL) - return retval; - - if (verbose >= 2) - fprintf(stderr, "debug2: Hash stored: %s\n", hash_stored); - - /* do the hash comparison */ - if (strncmp(hash_generated, hash_stored, SHA512_DIGEST_STRING_LENGTH) == 0) { - retval = 0; - } else { - retval = -1; - } - - return retval; -} - -/* - * do the hash calculation on specified input - */ -static char * -gen_hash(char *hash_input) -{ - char *hash_result = NULL; - char *hash_calc = NULL; - char *line = NULL; - char *line_ptr; - - int j = 0; - int i = 0; - - FILE *hash_in; - SHA512_CTX hash_ctx; - - if ((hash_in = fopen(hash_input, "r")) == NULL) { - errx(EXIT_FAILURE, "Unable to open: %s", hash_input); - } - - SHA512_Init(&hash_ctx); - - line = safe_calloc(MAXLINELEN, sizeof(char)); - - while ((line_ptr = fgets(line, MAXLINELEN, hash_in)) != NULL) { - - /* what we're not interested in */ - if ((strncmp(line, "# $NetBSD:", 10) == 0) || - (line[0] == '\n') || - (strncmp(line, "-----BEGIN", 10) == 0) || - (strncmp(line, "Hash:", 5) == 0) || - (strncmp(line, "#CHECKSUM", 9) == 0 )) - continue; - - /* effective EOF */ - if (strncmp(line, "Version:", 8) == 0) - break; - - SHA512_Update(&hash_ctx, (unsigned char *)line, strlen(line)); - } - - /* get the hash_result into a human readable string */ - hash_calc = safe_calloc(SHA512_DIGEST_STRING_LENGTH, sizeof(char)); - hash_result = safe_calloc(SHA512_DIGEST_LENGTH, sizeof(char)); - - SHA512_Final((unsigned char *)hash_result, &hash_ctx); - - for (i = 0; i < SHA512_DIGEST_LENGTH; ++i) { - sprintf(&hash_calc[j], "%02x", hash_result[i] & 0xFF); - j = j + 2; - } - - fclose(hash_in); - free(hash_result); - free(line); - - return hash_calc; -} - -/* - * do signature checking - if required - */ -static int -check_sig(char *sig_input) -{ - int retval = -1; - - if (verbose >= 3) - fprintf(stderr, "debug3: Attempting to verify signature.\n"); - - /* execute our verification tool */ - retval = fexec(verify_bin, "--verify", "--batch", "--no-options", sig_input, NULL); - - return retval; -} - -/* - * print the messages for eol and vulnerable packages - */ -static int -pv_message(char *pv_entry[], char *package) -{ - int retval = 0; - - /* deal with eol'ed packages */ - if (strcmp(pv_entry[1], "eol") == 0) { - if (eol == TRUE) { - if (quiet == FALSE) { - fprintf(stdout, "Package %s has reached end-of-life (eol), see %s/eol-packages\n", pv_entry[0], EOL_URL); - } else { - fprintf(stdout, "%s\n", pv_entry[0]); - } - } - } else { - /* return that we found a vulnerable package */ - retval = 1; - - /* Just make sure we display _something_ useful here */ - if (package == NULL) - package = pv_entry[0]; - - if (quiet == FALSE) { - fprintf(stdout, "Package %s has a %s vulnerability, see: %s\n", package, pv_entry[1], pv_entry[2]); - } else { - fprintf(stdout, "%s\n", package); - } - } - - return retval; -} - -/* - * deal with URLs that we're ignorning - */ -static int -ap_ignore(char *pv_entry[]) -{ - char *ignore_tmp = NULL; - char *ig_token = NULL; - - int retval = 0; - int ignore_hit = 0; - - ignore_tmp = safe_strdup(ignore); - - while ((ig_token = strsep(&ignore_tmp, " ")) != NULL) { - - /* ignore empty tokens as well */ - if (ig_token[0] != '\0') { - /* see we have an IGNORE_URLS hit */ - if (strcmp(pv_entry[2], ig_token) == 0) { - ignore_hit = 1; - break; - } - } - } - - /* if we're seen an IGNORE_URLS then don't bother going on */ - if (ignore_hit == 1) { - if (verbose >= 1) { - fprintf(stderr, "Ignoring vulnerability for %s with pattern: %s\n", pv_entry[2], pv_entry[0]); - } - - /* return that we got an ignore hit */ - retval = 1; - } - - return retval; -} - -/* - * at the moment we really don't need to clean anything up - */ -void -cleanup(int signo) -{ -} - -/* - * print what the current settings are - */ -static void -show_info(char *varname) -{ - if (strncmp(varname, "GPG", 3) == 0) { - fprintf(stdout, "%s\n", verify_bin); - } - else if (strncmp(varname, "PKGVULNDIR", 9) == 0) { - fprintf(stdout, "%s\n", pvdir); - } - else if (strncmp(varname, "IGNORE_URLS", 11) == 0) { - fprintf(stdout, "%s\n", ignore); - } -} - -/* - * set the location for the pkg-vulnerabilities file - */ -static void -set_pvfile(const char *vuln_dir) -{ - char *pvloc = NULL; - size_t retval; - const char pvname[] = "/pkg-vulnerabilities"; - - pvloc = safe_calloc(MAXPATHLEN, sizeof(char)); - retval = strlcpy(pvloc, vuln_dir, MAXPATHLEN); - retval = strlcat(pvloc, pvname, MAXPATHLEN); - - pvdir = safe_strdup(vuln_dir); - pvfile = safe_strdup(pvloc); - - free(pvloc); -} - -/* - * duplicate a string and check the return value - */ -static char * -safe_strdup(const char *dupe) -{ - char *retval; - - if ((retval = strdup(dupe)) == NULL) { - errx(EXIT_FAILURE, "Unable to allocate memory at line: %d.", __LINE__); - } - - return retval; -} diff --git a/pkgtools/pkg_install/files/audit-packages/audit-packages.cat1.in b/pkgtools/pkg_install/files/audit-packages/audit-packages.cat1.in deleted file mode 100644 index bb64ac594c6..00000000000 --- a/pkgtools/pkg_install/files/audit-packages/audit-packages.cat1.in +++ /dev/null @@ -1,199 +0,0 @@ -AUDIT-PACKAGES(1) NetBSD General Commands Manual AUDIT-PACKAGES(1) - -NNAAMMEE - aauuddiitt--ppaacckkaaggeess, ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt -- show vulnerabilities in - installed packages - -SSYYNNOOPPSSIISS - aauuddiitt--ppaacckkaaggeess [--ddeeqqssVVvv] [--cc _c_o_n_f_i_g___f_i_l_e] [--gg _f_i_l_e] [--hh _f_i_l_e] - [--KK _p_k_g___d_b_d_i_r] [--nn _p_a_c_k_a_g_e] [--pp _p_a_c_k_a_g_e] [--QQ _v_a_r_n_a_m_e] - [--tt _t_y_p_e] - ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt [--hhss] [--cc _c_o_n_f_i_g___f_i_l_e] - -DDEESSCCRRIIPPTTIIOONN - The aauuddiitt--ppaacckkaaggeess program compares the installed packages with the - _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file and reports any known security issues to stan- - dard output. This output contains the name and version of the package, - the type of vulnerability, and an URL for further information for each - vulnerable package. - - The following flags are supported: - - --cc _c_o_n_f_i_g___f_i_l_e Specify a custom _c_o_n_f_i_g___f_i_l_e configuration file to use. - - --dd Attempt to download the vulnerabilities file using the - ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt script before scanning the - installed packages for vulnerabilities. - - --ee Check for end-of-life (eol) packages. - - --gg _f_i_l_e Compute the SHA512 hash on _f_i_l_e. - - --hh _f_i_l_e Check the SHA512 hash of a _f_i_l_e against the internally - stored value. - - --KK _p_k_g___d_b_d_i_r Use package database directory _p_k_g___d_b_d_i_r. - - --nn _p_a_c_k_a_g_e Check only the package _p_a_c_k_a_g_e for vulnerabilities. - - --pp _p_a_c_k_a_g_e Check only the installed package _p_a_c_k_a_g_e for vulnera- - bilities. - - --QQ _v_a_r_n_a_m_e Display the current value of _v_a_r_n_a_m_e and exit. Cur- - rently supported _v_a_r_n_a_m_e are GPG, PKGVULNDIR, and - IGNORE_URLS. - - --qq Be ``quiet'' in emitting report headers and such, just - dump the raw info (basically, assume a non-human read- - ing). - - --ss Verify the signature of the current _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s - file. The key used to sign the file is available from: - _f_t_p_:_/_/_f_t_p_._n_e_t_b_s_d_._o_r_g_/_p_u_b_/_N_e_t_B_S_D_/_s_e_c_u_r_i_t_y_/_P_G_P_/_p_k_g_s_r_c_-_s_e_c_u_r_i_t_y_@_N_e_t_B_S_D_._o_r_g_._a_s_c - - In order for this to function correctly the above key - must be added to the gpg keyring of the user who runs - aauuddiitt--ppaacckkaaggeess --ss and/or ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt - --ss. In addition to this the gpg binary must be - installed on your system. The path to the gpg binary - can be set in audit-packages.conf(5). - - The requirement for GnuPG may go away in the future - when a suitable replacement is implemented. - - --tt _t_y_p_e Only check for the specified _t_y_p_e of vulnerability. - - --VV Display the version number and exit. - - --vv Be more verbose. Specify multiple --vv flags to increase - verbosity. Currently a maximum level of three is sup- - ported. - - The ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt program downloads the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s - file from _f_t_p_._N_e_t_B_S_D_._o_r_g using ftp(1) by default. This vulnerabilities - file documents all known security issues in pkgsrc packages and is kept - up-to-date by the NetBSD pkgsrc-security team. - - The following flags are supported: - - --cc _c_o_n_f_i_g___f_i_l_e Specify a custom _c_o_n_f_i_g___f_i_l_e configuration file to use. - - --hh Display program usage. - - --ss Verify the signature of the current _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s - file. In order for this to function correctly you will - need to add the pkgsrc Security Team key to your gpg - keyring and trust it. The key is available from: - _f_t_p_:_/_/_f_t_p_._n_e_t_b_s_d_._o_r_g_/_p_u_b_/_N_e_t_B_S_D_/_s_e_c_u_r_i_t_y_/_P_G_P_/_p_k_g_s_r_c_-_s_e_c_u_r_i_t_y_@_N_e_t_B_S_D_._o_r_g_._a_s_c - In addition to this the gpg binary must be installed on - your system. The path to the gpg binary can be set in - audit-packages.conf(5). - - By default ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt will download a compressed version - of _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s from ftp.netbsd.org. The default file downloaded - is compressed using gzip(1). The compression tool used can set in - audit-packages.conf(5). Currently only gzcat(1) and bzcat(1) are sup- - ported. - - aauuddiitt--ppaacckkaaggeess and/or ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt need not be run by the - root user. They will function as an unpriveleged user just so long as - the user chosen has permmission to write the downloded _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_e_s - file to the location specified in audit-packages.conf(5). - - Each line lists the package and vulnerable versions, the type of exploit, - and an Internet address for further information: - - <package pattern> <type> <url> - - The type of exploit can be any text, although some common types of - exploits listed are: - ++oo cross-site-html - ++oo cross-site-scripting - ++oo denial-of-service - ++oo eol - ++oo file-permissions - ++oo local-access - ++oo local-code-execution - ++oo local-file-read - ++oo local-file-removal - ++oo local-file-write - ++oo local-root-file-view - ++oo local-root-shell - ++oo local-symlink-race - ++oo local-user-file-view - ++oo local-user-shell - ++oo privacy-leak - ++oo remote-code-execution - ++oo remote-command-inject - ++oo remote-file-creation - ++oo remote-file-read - ++oo remote-file-view - ++oo remote-file-write - ++oo remote-key-theft - ++oo remote-root-access - ++oo remote-root-shell - ++oo remote-script-inject - ++oo remote-server-admin - ++oo remote-use-of-secret - ++oo remote-user-access - ++oo remote-user-file-view - ++oo remote-user-shell - ++oo unknown - ++oo weak-authentication - ++oo weak-encryption - ++oo weak-ssl-authentication - - The type _e_o_l implies that the package is no longer maintained by the - software vendor but is provided by the pkgsrc team for your convenience - only. It may contain any number of the above mentioned vulnerabilities. - Any packages of type eol are not reported by default. Run aauuddiitt--ppaacckkaaggeess - --ee to also report on eol packages. - - By default, the vulnerabilities file is stored in the PKG_DBDIR direc- - tory. On a standard installation this will be set to @pkgdbdir@. If you - have installed pkgsrc on a supported platform this will be what ever you - specifed when bootstrapping pkgsrc i.e., ----ppkkggddbbddiirr <_p_k_g_d_b_d_i_r>. The path - to the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file can be set in audit-packages.conf(5). - -EEXXIITT SSTTAATTUUSS - The aauuddiitt--ppaacckkaaggeess utility exits 0 on success, and >0 if an error occurs. - -FFIILLEESS - @pkgdbdir@/pkg-vulnerabilities Vulnerabilities database. - - @sysconfdir@/audit-packages.conf aauuddiitt--ppaacckkaaggeess configuration file. - - ftp://ftp.netbsd.org/pub/NetBSD/security/PGP/pkgsrc-security@NetBSD.org.asc - Key used to sign the vulnerabilities - file. - -EEXXAAMMPPLLEESS - The ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt command can be run via cron(8) to update - the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file daily. aauuddiitt--ppaacckkaaggeess can be run via - cron(8) (or with NetBSD's _/_e_t_c_/_s_e_c_u_r_i_t_y_._l_o_c_a_l daily security script). - - The ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt command can be forced to use IPv4 with - the following setting in @sysconfdir@/audit-packages.conf: - - FETCH_ARGS="-4" - - The ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt command can be forced to use http to - download the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file with the following setting in - @sysconfdir@/audit-packages.conf: - - FETCH_PROTO="http" - -SSEEEE AALLSSOO - pkg_info(1), audit-packages.conf(5), mk.conf(5), pkgsrc(7), - - _D_o_c_u_m_e_n_t_a_t_i_o_n _o_n _t_h_e _N_e_t_B_S_D _P_a_c_k_a_g_e _S_y_s_t_e_m. - -HHIISSTTOORRYY - The aauuddiitt--ppaacckkaaggeess and ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt commands were origi- - nally implemented and added to NetBSD's pkgsrc by Alistair Crooks on - September 19, 2000. During April 2007 aauuddiitt--ppaacckkaaggeess was re-written by - Adrian Portelli and support was added for compressed files and checking - signatures on downloaded files. The original idea came from Roland - Dowdeswell and Bill Sommerfeld. - -NetBSD 3.1 August 10, 2007 NetBSD 3.1 diff --git a/pkgtools/pkg_install/files/audit-packages/audit-packages.conf.5.in b/pkgtools/pkg_install/files/audit-packages/audit-packages.conf.5.in deleted file mode 100644 index 6dae8043373..00000000000 --- a/pkgtools/pkg_install/files/audit-packages/audit-packages.conf.5.in +++ /dev/null @@ -1,126 +0,0 @@ -.\" $NetBSD: audit-packages.conf.5.in,v 1.4 2007/09/17 22:40:27 adrianp Exp $ -.\" -.\" Copyright (c) 2007 Adrian Portelli. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by Adrian Portelli -.\" for the NetBSD project. -.\" 4. The name of the author may not be used to endorse or promote -.\" products derived from this software without specific prior written -.\" permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS -.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -.\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd July 07, 2007 -.Os -.Dt audit-packages.conf 5 -.Sh NAME -.Nm audit-packages.conf -.Nd audit-packages and download-vulnerability-list configuration file. -.Sh DESCRIPTION -The -.Nm -file contains the configuration information for -.Xr download-vulnerability-list 8 -and -.Xr audit-packages 8 . -.Pp -These variables can be defined in the -.Xr audit-packages.conf 8 -file. -.Pp -.Bl -tag -width COMPRESS_TYPE -.It Ev GPG -The full path to the location of the binary used to verify the signature -on the downloaded -.Pa pkg-vulnerabilities -file. Currently only GnuPG is supported. -.Pp -The default is "@prefix@/bin/gpg". -.It Ev PKGVULNDIR -Specifies the directory containing the -.Pa pkg-vulnerabilities -file. -.Pp -The default is "@pkgdbdir@". -.It Ev COMPRESS_TYPE -Specifies which type of compressed -.Pa pkg-vulnerabilities -file to download. You can also specify COMPRESS_TYPE="" to use -and uncompressed version of the file. If you change this from the -default you must specify a COMPRESS_TOOL. The -currently accepted options are gzip and bzip2. -.It Ev COMPRESS_TOOL -The full path to the location of the binary used to -decompress the downloaded -.Pa pkg-vulnerabilities -file. -.Pp -The default is "@gzcat@". -.It Ev FETCH_CMD -Specifies the client used to download the -.Pa pkg-vulnerabilities -file. Currently known tools include curl, ftp, wget and fetch. -.Pp -The default is @ftp@. -.It Ev FETCH_PRE_ARGS -Specifies optional arguments for the -.Pa download-vulnerability-list -client. These options appear before FETCH_CMD. -.It Ev FETCH_ARGS -Specifies optional arguments for the client used to download the -.Pa pkg-vulnerabilities -file. -.It Ev FETCH_PROTO -Specifies the protocol to use when fetching the -.Pa pkg-vulnerabilities -file. -Currently supports only http and ftp. -.Pp -The default is "ftp". -.It Ev IGNORE_URLS -A list of vulnerability URLs to be ignored. -This allows for ignoring certain URLs that are attached to a -vulnerability. -.El -.Sh FILES -@sysconfdir@/audit-packages.conf -.Sh SEE ALSO -.Xr pkg_info 1 , -.Xr mk.conf 5 , -.Xr pkgsrc 7 , -.Xr audit-packages 8 and -.%T "Documentation on the NetBSD Package System" -.Sh HISTORY -The -.Nm audit-packages -and -.Nm download-vulnerability-list -commands were originally implemented and added to -.Nx Ap s -pkgsrc by -.An Alistair Crooks -on September 19, 2000. During April 2007 -.Nm audit-packages -was re-written by Adrian Portelli and support was added for compressed -files and checking signatures on downloaded files. The original idea -came from Roland Dowdeswell and Bill Sommerfeld. diff --git a/pkgtools/pkg_install/files/audit-packages/audit-packages.conf.cat5.in b/pkgtools/pkg_install/files/audit-packages/audit-packages.conf.cat5.in deleted file mode 100644 index f1de23a7a70..00000000000 --- a/pkgtools/pkg_install/files/audit-packages/audit-packages.conf.cat5.in +++ /dev/null @@ -1,75 +0,0 @@ -audit-packages.conf(5) NetBSD File Formats Manual audit-packages.conf(5) - -NNAAMMEE - aauuddiitt--ppaacckkaaggeess..ccoonnff -- audit-packages and download-vulnerability-list - configuration file. - -DDEESSCCRRIIPPTTIIOONN - The aauuddiitt--ppaacckkaaggeess..ccoonnff file contains the configuration information for - download-vulnerability-list(8) and audit-packages(8). - - These variables can be defined in the audit-packages.conf(8) file. - - GPG The full path to the location of the binary used to verify - the signature on the downloaded _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file. - Currently only GnuPG is supported. - - The default is "@prefix@/bin/gpg". - - PKGVULNDIR Specifies the directory containing the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s - file. - - The default is "@pkgdbdir@". - - COMPRESS_TYPE Specifies which type of compressed _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s - file to download. You can also specify COMPRESS_TYPE="" - to use and uncompressed version of the file. If you - change this from the default you must specify a COM- - PRESS_TOOL. The currently accepted options are gzip and - bzip2. - - COMPRESS_TOOL The full path to the location of the binary used to decom- - press the downloaded _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file. - - The default is "@gzcat@". - - FETCH_CMD Specifies the client used to download the - _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file. Currently known tools include - curl, ftp, wget and fetch. - - The default is @ftp@. - - FETCH_PRE_ARGS - Specifies optional arguments for the - _d_o_w_n_l_o_a_d_-_v_u_l_n_e_r_a_b_i_l_i_t_y_-_l_i_s_t client. These options appear - before FETCH_CMD. - - FETCH_ARGS Specifies optional arguments for the client used to down- - load the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file. - - FETCH_PROTO Specifies the protocol to use when fetching the - _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file. Currently supports only http - and ftp. - - The default is "ftp". - - IGNORE_URLS A list of vulnerability URLs to be ignored. This allows - for ignoring certain URLs that are attached to a vulnera- - bility. - -FFIILLEESS - @sysconfdir@/audit-packages.conf - -SSEEEE AALLSSOO - pkg_info(1), mk.conf(5), pkgsrc(7), audit-packages(8) and _D_o_c_u_m_e_n_t_a_t_i_o_n - _o_n _t_h_e _N_e_t_B_S_D _P_a_c_k_a_g_e _S_y_s_t_e_m - -HHIISSTTOORRYY - The aauuddiitt--ppaacckkaaggeess and ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt commands were origi- - nally implemented and added to NetBSD's pkgsrc by Alistair Crooks on - September 19, 2000. During April 2007 aauuddiitt--ppaacckkaaggeess was re-written by - Adrian Portelli and support was added for compressed files and checking - signatures on downloaded files. The original idea came from Roland - Dowdeswell and Bill Sommerfeld. - -NetBSD 3.1 July 07, 2007 NetBSD 3.1 diff --git a/pkgtools/pkg_install/files/audit-packages/audit-packages.conf.in b/pkgtools/pkg_install/files/audit-packages/audit-packages.conf.in deleted file mode 100644 index 599ca85e5f2..00000000000 --- a/pkgtools/pkg_install/files/audit-packages/audit-packages.conf.in +++ /dev/null @@ -1,87 +0,0 @@ -# $NetBSD: audit-packages.conf.in,v 1.2 2007/09/17 22:40:27 adrianp Exp $ - -# -# sample configuration file for audit-packages(8) and -# download-vulnerability-list(8) -# - -# GPG -# -# Specifies the full path to the gpg tool that will be used for verifying -# the signature on the downloaded pkg-vulnerabilities file. -# -# Used by: audit-packages download-vulnerability-list -# Supported: /path/to/gpg -# Default: GPG="@prefix@/bin/gpg" - -# PKGVULNDIR -# -# Specifies the directory the pkg-vulnerabilities file is located in. -# -# Used by: audit-packages download-vulnerability-list -# Supported: /path/to/pkg-vulnerabilities/ -# Default: PKGVULNDIR="@pkgdbdir@" - -# COMPRESS_TYPE -# -# Specifies which type of compressed pkg-vulnerabilities file to -# download. You can also specify COMPRESS_TYPE="" to use -# and uncompressed version of the file. -# -# If you change this from the default you must specify a COMPRESS_TOOL. -# -# Used by: download-vulnerability-list -# Supported: gzip bzip2 (none) -# Default: COMPRESS_TYPE="gzip" - -# COMPRESS_TOOL -# -# Specifies which tool will be used when dealing with the compressed -# pkg-vulnerabilities file. -# -# Used by: download-vulnerability-list -# Supported: Any local binary that can decompress the -# pkg-vulnerabilities file to stdout -# Default: COMPRESS_TOOL="@gzcat@" - -# FETCH_CMD -# -# Specifies the tool that will be used to fetch the pkg-vulnerabilities -# file. -# -# Used by: download-vulnerability-list -# Supported: /path/to/curl /path/to/ftp /path/to/wget /path/to/fetch -# Default: FETCH_CMD=@ftp@ - -# FETCH_PRE_ARGS -# -# Specifies optional arguments for the download-vulnerability-list client. -# These options appear before ${FETCH_CMD}. -# -# Used by: download-vulnerability-list -# Supported: Any valid arguments for FETCH_CMD -# Default: FETCH_PRE_ARGS= - -# FETCH_ARGS -# -# Specifies optional arguments for the download-vulnerability-list client. -# -# Used by: download-vulnerability-list -# Supported: Any valid arguments for FETCH_CMD -# Default: FETCH_ARGS= - -# FETCH_PROTO -# -# Specifies the protocol to use when fetching the pkg-vulnerabilities file. -# -# Used by: download-vulnerability-list -# Supported: ftp http -# Default: FETCH_PROTO="ftp" - -# IGNORE_URLS -# -# A list of vulnerability URLs to be ignored. -# -# Used by: audit-packages -# Supported: Valid URL(s) from pkg-vulnerabilities -# Default: IGNORE_URLS= diff --git a/pkgtools/pkg_install/files/audit-packages/download-vulnerability-list.1.in b/pkgtools/pkg_install/files/audit-packages/download-vulnerability-list.1.in deleted file mode 100644 index 7b6e0f0d806..00000000000 --- a/pkgtools/pkg_install/files/audit-packages/download-vulnerability-list.1.in +++ /dev/null @@ -1,336 +0,0 @@ -.\" $NetBSD: download-vulnerability-list.1.in,v 1.2 2007/07/16 09:57:57 joerg Exp $ -.\" -.\" Copyright (c) 2003 Jeremy C. Reed. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by Jeremy C. Reed -.\" for the NetBSD project. -.\" 4. The name of the author may not be used to endorse or promote -.\" products derived from this software without specific prior written -.\" permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS -.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -.\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd July 07, 2007 -.Os -.Dt AUDIT-PACKAGES 1 -.Sh NAME -.Nm audit-packages , -.Nm download-vulnerability-list -.Nd show vulnerabilities in installed packages -.Sh SYNOPSIS -.Nm -.Op Fl desVv -.Op Fl c Ar config_file -.Op Fl g Ar file -.Op Fl h Ar file -.Op Fl K Ar pkg_dbdir -.Op Fl n Ar package -.Op Fl p Ar package -.Op Fl Q Ar varname -.Op Fl t Ar type -.Nm download-vulnerability-list -.Op Fl hs -.Op Fl c Ar config_file -.Sh DESCRIPTION -The -.Nm -program compares the installed packages with the -.Pa pkg-vulnerabilities -file and reports any known security issues to standard output. -This output contains the name and version of the package, the -type of vulnerability, and an URL for further information for each -vulnerable package. -.Pp -The following flags are supported: -.Bl -tag -width Ar -.It Fl d -Attempt to download the vulnerabilities -file using the -.Pa download-vulnerability-list -script before scanning the installed packages for vulnerabilities. -.It Fl e -Check for end-of-life (eol) packages. -.It Fl s -Verify the signature of the current -.Pa pkg-vulnerabilities -file. The key used to sign the file is available from: -.Pa ftp.netbsd.org/pub/NetBSD/security/PGP/pkgsrc-security@NetBSD.org.asc -.Pp -In order for this to function correctly the above key must be -added to the gpg keyring of the user who runs -.Pa audit-packages -s -and/or -.Pa download-vulnerability-list -s . -In addition to this the gpg binary must be installed on your system. -The path to the gpg binary can be set in -.Xr audit-packages.conf 5 . -.Pp -The requirement for GnuPG may go away in the future when a suitable -replacement is implemented. -.It Fl V -Display the version number and exit. -.It Fl v -Be more verbose. Specify multiple -v flags to increase verbosity. -Currently a maximum level of three is supported. -.It Fl c Ar conf_file -Specify a custom -.Ar conf_file -configuration file to use. -.It Fl g Ar file -Compute the SHA512 hash on -.Ar file . -.It Fl h Ar file -Check the SHA512 hash of a -.Ar file -against the internally stored value. -.It Fl K Ar pkg_dbdir -Use package database directory -.Ar pkg_dbdir . -.It Fl n Ar package -Check only the package -.Ar package -for vulnerabilities. -.It Fl p Ar package -Check only the installed package -.Ar package -for vulnerabilities. -.It Fl Q Ar varname -Display the current value of -.Ar varname -and exit. Currently supported -.Ar varname -are GPG, PKGVULNDIR and IGNORE_URLS. -.It Fl t Ar type -Only check for the specified -.Ar type -of vulnerability. -.El -.Pp -The -.Nm download-vulnerability-list -program downloads the -.Pa pkg-vulnerabilities -file from -.Pa ftp.NetBSD.org -using -.Xr ftp 1 -by default. This vulnerabilities file documents all known security issues in -pkgsrc packages and is kept up-to-date by the -.Nx -pkgsrc-security team. -.Pp -The following flags are supported: -.Bl -tag -width Ar -.It Fl h -Display program usage. -.It Fl s -Verify the signature of the current -.Pa pkg-vulnerabilities -file. In order for this to function correctly you will need to add the -pkgsrc Security Team key to your gpg keyring and trust it. The key is -available from: -.Pa ftp.netbsd.org/pub/NetBSD/security/PGP/pkgsrc-security@NetBSD.org.asc -In addition to this the gpg binary must be installed on your system. -The path to the gpg binary can be set in -.Xr audit-packages.conf 5 . -.It Fl c Ar conf_file -Specify a custom -.Ar conf_file -configuration file to use. -.El -.Pp -By default -.Nm download-vulnerability-list -will download a compressed version of -.Pa pkg-vulnerabilities -from ftp.netbsd.org. The default file downloaded is compressed using -.Xr gzip 1 . -The compression tool used can set in -.Xr audit-packages.conf 5 . -Currently only -.Xr gzcat 1 -and -.Xr bzcat 1 -are supported. -.Pp -Each line lists the package and vulnerable versions, the type of exploit, -and an Internet address for further information: -.Bl -item -.It -.Aq package pattern -.Aq type -.Aq url -.El -.Pp -The type of exploit can be any text, although -some common types of exploits listed are: -.Bl -bullet -compact -offset indent -.It -cross-site-html -.It -cross-site-scripting -.It -denial-of-service -.It -eol -.It -file-permissions -.It -local-access -.It -local-code-execution -.It -local-file-read -.It -local-file-removal -.It -local-file-write -.It -local-root-file-view -.It -local-root-shell -.It -local-symlink-race -.It -local-user-file-view -.It -local-user-shell -.It -privacy-leak -.It -remote-code-execution -.It -remote-command-inject -.It -remote-file-creation -.It -remote-file-read -.It -remote-file-view -.It -remote-file-write -.It -remote-key-theft -.It -remote-root-access -.It -remote-root-shell -.It -remote-script-inject -.It -remote-server-admin -.It -remote-use-of-secret -.It -remote-user-access -.It -remote-user-file-view -.It -remote-user-shell -.It -unknown -.It -weak-authentication -.It -weak-encryption -.It -weak-ssl-authentication -.El -.Pp -The type -.Pa eol -implies that the package is no longer maintained by the software vendor but -is provided by the pkgsrc team for your convenience only. It may contain any -number of the above mentioned vulnerabilities. Any packages of type eol -are not reported by default. Run -.Nm Fl e -to also report on eol packages. -.Pp -By default, the vulnerabilities file is stored in the -PKG_DBDIR -directory. On a standard installation this will be set to @pkgdbdir@. -If you have installed pkgsrc on a supported platform this will be what -ever you specifed when bootstrapping pkgsrc i.e. --pkgdbdir <pkgdbdir>. -The path to the -.Pa pkg-vulnerabilities -file can be set in -.Xr audit-packages.conf 5 . -.Sh EXIT STATUS -.Ex -std audit-packages -.Sh FILES -@pkgdbdir@/pkg-vulnerabilities -.Pp -@sysconfdir@/audit-packages.conf -.Sh EXAMPLES -The -.Nm download-vulnerability-list -command can be run via -.Xr cron 8 -to update the -.Pa pkg-vulnerabilities -file daily. -And -.Nm -can be run via -.Xr cron 8 -(or with -.Nx Ap s -.Pa /etc/security.local -daily security script). -.Pp -The -.Nm download-vulnerability-list -command can be forced to use IPv4 with the following setting in -@sysconfdir@/audit-packages.conf: -.Pp -FETCH_ARGS="-4" -.Pp -The -.Nm download-vulnerability-list -command can be forced to use http to download the -.Pa pkg-vulnerabilities -file with the following setting in -@sysconfdir@/audit-packages.conf: -.Pp -FETCH_PROTO="http" -.Sh SEE ALSO -.Xr pkg_info 1 , -.Xr audit-packages.conf 5 , -.Xr mk.conf 5 , -.Xr pkgsrc 7 , -.%T "Documentation on the NetBSD Package System" -.Sh HISTORY -The -.Nm -and -.Nm download-vulnerability-list -commands were originally implemented and added to -.Nx Ap s -pkgsrc by -.An Alistair Crooks -on September 19, 2000. During April 2007 -.Nm -was re-written by Adrian Portelli -and support was added for compressed files and checking signatures on downloaded -files. -The original idea came from Roland Dowdeswell and Bill Sommerfeld. diff --git a/pkgtools/pkg_install/files/audit-packages/download-vulnerability-list.cat1.in b/pkgtools/pkg_install/files/audit-packages/download-vulnerability-list.cat1.in deleted file mode 100644 index b0473d8c40c..00000000000 --- a/pkgtools/pkg_install/files/audit-packages/download-vulnerability-list.cat1.in +++ /dev/null @@ -1,183 +0,0 @@ -AUDIT-PACKAGES(1) NetBSD General Commands Manual AUDIT-PACKAGES(1) - -NNAAMMEE - aauuddiitt--ppaacckkaaggeess, ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt -- show vulnerabilities in - installed packages - -SSYYNNOOPPSSIISS - aauuddiitt--ppaacckkaaggeess [--ddeessVVvv] [--cc _c_o_n_f_i_g___f_i_l_e] [--gg _f_i_l_e] [--hh _f_i_l_e] - [--KK _p_k_g___d_b_d_i_r] [--nn _p_a_c_k_a_g_e] [--pp _p_a_c_k_a_g_e] [--QQ _v_a_r_n_a_m_e] - [--tt _t_y_p_e] - ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt [--hhss] [--cc _c_o_n_f_i_g___f_i_l_e] - -DDEESSCCRRIIPPTTIIOONN - The aauuddiitt--ppaacckkaaggeess program compares the installed packages with the - _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file and reports any known security issues to stan- - dard output. This output contains the name and version of the package, - the type of vulnerability, and an URL for further information for each - vulnerable package. - - The following flags are supported: - - --dd Attempt to download the vulnerabilities file using the - _d_o_w_n_l_o_a_d_-_v_u_l_n_e_r_a_b_i_l_i_t_y_-_l_i_s_t script before scanning the - installed packages for vulnerabilities. - - --ee Check for end-of-life (eol) packages. - - --ss Verify the signature of the current _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s - file. The key used to sign the file is available from: - _f_t_p_._n_e_t_b_s_d_._o_r_g_/_p_u_b_/_N_e_t_B_S_D_/_s_e_c_u_r_i_t_y_/_P_G_P_/_p_k_g_s_r_c_-_s_e_c_u_r_i_t_y_@_N_e_t_B_S_D_._o_r_g_._a_s_c - - In order for this to function correctly the above key must - be added to the gpg keyring of the user who runs - _a_u_d_i_t_-_p_a_c_k_a_g_e_s _-_s and/or _d_o_w_n_l_o_a_d_-_v_u_l_n_e_r_a_b_i_l_i_t_y_-_l_i_s_t _-_s. - In addition to this the gpg binary must be installed on - your system. The path to the gpg binary can be set in - audit-packages.conf(5). - - The requirement for GnuPG may go away in the future when a - suitable replacement is implemented. - - --VV Display the version number and exit. - - --vv Be more verbose. Specify multiple -v flags to increase ver- - bosity. Currently a maximum level of three is supported. - - --cc _c_o_n_f___f_i_l_e Specify a custom _c_o_n_f___f_i_l_e configuration file to use. - - --gg _f_i_l_e Compute the SHA512 hash on _f_i_l_e. - - --hh _f_i_l_e Check the SHA512 hash of a _f_i_l_e against the internally - stored value. - - --KK _p_k_g___d_b_d_i_r Use package database directory _p_k_g___d_b_d_i_r. - - --nn _p_a_c_k_a_g_e Check only the package _p_a_c_k_a_g_e for vulnerabilities. - - --pp _p_a_c_k_a_g_e Check only the installed package _p_a_c_k_a_g_e for vulnerabili- - ties. - - --QQ _v_a_r_n_a_m_e Display the current value of _v_a_r_n_a_m_e and exit. Currently - supported _v_a_r_n_a_m_e are GPG, PKGVULNDIR and IGNORE_URLS. - - --tt _t_y_p_e Only check for the specified _t_y_p_e of vulnerability. - - The ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt program downloads the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s - file from _f_t_p_._N_e_t_B_S_D_._o_r_g using ftp(1) by default. This vulnerabilities - file documents all known security issues in pkgsrc packages and is kept - up-to-date by the NetBSD pkgsrc-security team. - - The following flags are supported: - - --hh Display program usage. - - --ss Verify the signature of the current _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s - file. In order for this to function correctly you will - need to add the pkgsrc Security Team key to your gpg - keyring and trust it. The key is available from: - _f_t_p_._n_e_t_b_s_d_._o_r_g_/_p_u_b_/_N_e_t_B_S_D_/_s_e_c_u_r_i_t_y_/_P_G_P_/_p_k_g_s_r_c_-_s_e_c_u_r_i_t_y_@_N_e_t_B_S_D_._o_r_g_._a_s_c - In addition to this the gpg binary must be installed on - your system. The path to the gpg binary can be set in - audit-packages.conf(5). - - --cc _c_o_n_f___f_i_l_e Specify a custom _c_o_n_f___f_i_l_e configuration file to use. - - By default ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt will download a compressed version - of _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s from ftp.netbsd.org. The default file downloaded - is compressed using gzip(1). The compression tool used can set in - audit-packages.conf(5). Currently only gzcat(1) and bzcat(1) are sup- - ported. - - Each line lists the package and vulnerable versions, the type of exploit, - and an Internet address for further information: - - <package pattern> <type> <url> - - The type of exploit can be any text, although some common types of - exploits listed are: - ·· cross-site-html - ·· cross-site-scripting - ·· denial-of-service - ·· eol - ·· file-permissions - ·· local-access - ·· local-code-execution - ·· local-file-read - ·· local-file-removal - ·· local-file-write - ·· local-root-file-view - ·· local-root-shell - ·· local-symlink-race - ·· local-user-file-view - ·· local-user-shell - ·· privacy-leak - ·· remote-code-execution - ·· remote-command-inject - ·· remote-file-creation - ·· remote-file-read - ·· remote-file-view - ·· remote-file-write - ·· remote-key-theft - ·· remote-root-access - ·· remote-root-shell - ·· remote-script-inject - ·· remote-server-admin - ·· remote-use-of-secret - ·· remote-user-access - ·· remote-user-file-view - ·· remote-user-shell - ·· unknown - ·· weak-authentication - ·· weak-encryption - ·· weak-ssl-authentication - - The type _e_o_l implies that the package is no longer maintained by the - software vendor but is provided by the pkgsrc team for your convenience - only. It may contain any number of the above mentioned vulnerabilities. - Any packages of type eol are not reported by default. Run aauuddiitt--ppaacckkaaggeess - --ee to also report on eol packages. - - By default, the vulnerabilities file is stored in the PKG_DBDIR direc- - tory. On a standard installation this will be set to @pkgdbdir@. If you - have installed pkgsrc on a supported platform this will be what ever you - specifed when bootstrapping pkgsrc i.e. --pkgdbdir <pkgdbdir>. The path - to the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file can be set in audit-packages.conf(5). - -EEXXIITT SSTTAATTUUSS - The aauuddiitt--ppaacckkaaggeess utility exits 0 on success, and >0 if an error occurs. - -FFIILLEESS - @pkgdbdir@/pkg-vulnerabilities - - @sysconfdir@/audit-packages.conf - -EEXXAAMMPPLLEESS - The ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt command can be run via cron(8) to update - the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file daily. And aauuddiitt--ppaacckkaaggeess can be run via - cron(8) (or with NetBSD's _/_e_t_c_/_s_e_c_u_r_i_t_y_._l_o_c_a_l daily security script). - - The ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt command can be forced to use IPv4 with - the following setting in @sysconfdir@/audit-packages.conf: - - FETCH_ARGS="-4" - - The ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt command can be forced to use http to - download the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file with the following setting in - @sysconfdir@/audit-packages.conf: - - FETCH_PROTO="http" - -SSEEEE AALLSSOO - pkg_info(1), audit-packages.conf(5), mk.conf(5), pkgsrc(7), _D_o_c_u_m_e_n_t_a_t_i_o_n - _o_n _t_h_e _N_e_t_B_S_D _P_a_c_k_a_g_e _S_y_s_t_e_m - -HHIISSTTOORRYY - The aauuddiitt--ppaacckkaaggeess and ddoowwnnllooaadd--vvuullnneerraabbiilliittyy--lliisstt commands were origi- - nally implemented and added to NetBSD's pkgsrc by Alistair Crooks on - September 19, 2000. During April 2007 aauuddiitt--ppaacckkaaggeess was re-written by - Adrian Portelli and support was added for compressed files and checking - signatures on downloaded files. The original idea came from Roland - Dowdeswell and Bill Sommerfeld. - -NetBSD 4.0 July 07, 2007 NetBSD 4.0 diff --git a/pkgtools/pkg_install/files/audit-packages/download-vulnerability-list.sh.in b/pkgtools/pkg_install/files/audit-packages/download-vulnerability-list.sh.in deleted file mode 100644 index 608dd7ae5d1..00000000000 --- a/pkgtools/pkg_install/files/audit-packages/download-vulnerability-list.sh.in +++ /dev/null @@ -1,217 +0,0 @@ -#!/bin/sh - -# $NetBSD: download-vulnerability-list.sh.in,v 1.5 2008/03/13 08:37:43 wiz Exp $ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by Alistair Crooks -# for the NetBSD project. -# 4. The name of the author may not be used to endorse or promote -# products derived from this software without specific prior written -# permission. -# -# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS -# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -: ${PKGVULNDIR="@pkgdbdir@"} -: ${COMPRESS_TYPE="gzip"} -: ${FETCH_PRE_ARGS=""} -: ${FETCH_CMD=@ftp@} -: ${FETCH_ARGS=""} -: ${FETCH_PROTO=ftp} - -prefix=@prefix@ -AP=@exec_prefix@/sbin/audit-packages -NEW_VUL_LIST=pkg-vulnerabilities.$$ -EXIST_VUL_LIST=pkg-vulnerabilities -FETCH_PATH="ftp.NetBSD.org/pub/NetBSD/packages/vulns" -_CONF_FILE="@sysconfdir@/audit-packages.conf" -COMPRESS_TOOL="" - -usage() -{ - argv0="${1##*/}" - cat <<EOF -$2 -Usage: $argv0 [-s] [-c config-file] - -s : Verify the signature on the downloaded file. - -c : Specify a custom configuration file to use. -EOF - exit 1 -} - -verify=no -custom_conf=no -conf_found=no -neednew=no - -while [ $# -gt 0 ]; do - case "$1" in - -s) - verify=yes - ;; - -c) - custom_conf=yes - local_conf="$2" - shift - ;; - *) - usage "$0" "Unknown option $1" - esac - shift -done - -# generic conf file handler -if [ -r ${_CONF_FILE} ]; then - conf_found=yes -fi - -# see if the user wants us to use a custom config file -if [ "x${custom_conf}" = "xyes" ]; then - if [ -r ${local_conf} ]; then - conf_found=yes - _CONF_FILE=${local_conf} - fi -fi - -# only do the following if we have found a config file to use -if [ "x${conf_found}" = "xyes" ]; then - if [ -r ${_CONF_FILE} ]; then - echo "Reading settings from ${_CONF_FILE}" - . ${_CONF_FILE} - fi -fi - -# setup the compression type -case "${COMPRESS_TYPE}" in -bzip2) COMPRESS_EXTN=.bz2 - compressed=yes - ;; -gzip) COMPRESS_EXTN=.gz - compressed=yes - ;; -none) COMPRESS_EXTN="" - compressed=no - ;; -*) echo "***ERROR*** Unknown COMPRESS_TYPE specified - Only bzip2 and gzip are currently supported." - exit 1 - ;; -esac - -# setup the compression tool and arguments -if [ "x${compressed}" = "xyes" ]; then - if [ "x${COMPRESS_TYPE}" = "xgzip" -a "x${COMPRESS_TOOL}" = "x" ]; then - COMPRESS_TOOL="@gzcat@" - fi - - if [ "x${COMPRESS_TYPE}" != "xgzip" -a "x${COMPRESS_TOOL}" = "x" ]; then - echo "***ERROR*** A non-default COMPRESS_TYPE has been specified without a COMPRESS_TOOL" - exit 1 - fi -fi - -VUL_SOURCE="${FETCH_PROTO}://${FETCH_PATH}/pkg-vulnerabilities${COMPRESS_EXTN}" - -if [ ! -d ${PKGVULNDIR}/. ]; then - echo "Creating ${PKGVULNDIR}" - - /bin/mkdir ${PKGVULNDIR} - if [ ! -d ${PKGVULNDIR} ]; then - echo "***ERROR*** Can't create: ${PKGVULNDIR}" - exit 1 - fi -fi - -echo "audit-packages" > ${PKGVULNDIR}/.cookie - -if [ -f ${PKGVULNDIR}/.cookie ]; then - rm -f ${PKGVULNDIR}/.cookie -else - echo "***ERROR*** Can't write to: ${PKGVULNDIR}" - exit 1 -fi - -if [ ! "x${FETCH_PROTO}" = "xhttp" -a ! "x${FETCH_PROTO}" = "xftp" ]; then - echo "***ERROR*** Unknown FETCH_PROTO specified - Only http and ftp are currently supported." - exit 1 -fi - -cd ${PKGVULNDIR} -utility=`basename "${FETCH_CMD}"` -case "${utility}" in -curl|fetch|ftp) ${FETCH_PRE_ARGS} ${FETCH_CMD} ${FETCH_ARGS} \ - -o ${NEW_VUL_LIST}${COMPRESS_EXTN} ${VUL_SOURCE} ;; -wget) ${FETCH_PRE_ARGS} ${FETCH_CMD} ${FETCH_ARGS} \ - -O ${NEW_VUL_LIST}${COMPRESS_EXTN} ${VUL_SOURCE} ;; -*) echo "Unknown fetch command - please use send-pr to send in support for your fetch command" 1>&2 - exit 1 - ;; -esac - -# see if we got a file -if [ ! -f "${NEW_VUL_LIST}${COMPRESS_EXTN}" ]; then - echo "***ERROR*** Download of vulnerabilities file failed" 1>&2 - exit 1 -fi - -# decompress the downloaded file and delete the download -if [ "x${compressed}" = "xyes" ]; then - ${COMPRESS_TOOL} ${NEW_VUL_LIST}${COMPRESS_EXTN} > ${NEW_VUL_LIST} - /bin/rm -f ${NEW_VUL_LIST}${COMPRESS_EXTN} -fi - -# compare the old and new files to see if there's a difference -if [ -f ${EXIST_VUL_LIST} ]; then - exist_hash=`${AP} -g ${EXIST_VUL_LIST}` - new_hash=`${AP} -g ${NEW_VUL_LIST}` - - if [ "x${exist_hash}" != "x${new_hash}" ]; then - neednew=yes - else - echo "No change from existing package vulnerabilities file" - /bin/rm -f ${NEW_VUL_LIST} - exit 0 - fi -else - neednew=yes -fi - -# check the hash and/or sig on the new file -if [ "x${verify}" = "xyes" ]; then - ${AP} -s -h ${NEW_VUL_LIST} -else - ${AP} -h ${NEW_VUL_LIST} -fi - -ec=$?; - -if [ $ec -ne 0 ]; then - echo "***ERROR*** Failed to verify the newly downloaded vulnerabilities file" 1>&2 - /bin/rm -f ${NEW_VUL_LIST} - exit 1 -fi - -# move the new file into position -echo "Package vulnerabilities file has been updated" -/bin/chmod a+r ${NEW_VUL_LIST} -/bin/mv -f ${NEW_VUL_LIST} ${EXIST_VUL_LIST} - -exit 0 diff --git a/pkgtools/pkg_install/files/configure b/pkgtools/pkg_install/files/configure index 7fb6f8fe2d1..98bff3ce3dd 100755 --- a/pkgtools/pkg_install/files/configure +++ b/pkgtools/pkg_install/files/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.62 for pkg_install 20070804. +# Generated by GNU Autoconf 2.63 for pkg_install 20090201. # # Report bugs to <joerg@NetBSD.org>. # @@ -596,8 +596,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='pkg_install' PACKAGE_TARNAME='pkg_install' -PACKAGE_VERSION='20070804' -PACKAGE_STRING='pkg_install 20070804' +PACKAGE_VERSION='20090201' +PACKAGE_STRING='pkg_install 20090201' PACKAGE_BUGREPORT='joerg@NetBSD.org' ac_unique_file="lib/plist.c" @@ -637,98 +637,94 @@ ac_includes_default="\ # include <unistd.h> #endif" -ac_subst_vars='SHELL -PATH_SEPARATOR -PACKAGE_NAME -PACKAGE_TARNAME -PACKAGE_VERSION -PACKAGE_STRING -PACKAGE_BUGREPORT -exec_prefix -prefix -program_transform_name -bindir -sbindir -libexecdir -datarootdir -datadir -sysconfdir -sharedstatedir -localstatedir -includedir -oldincludedir -docdir -infodir -htmldir -dvidir -pdfdir -psdir -libdir -localedir -mandir -DEFS -ECHO_C -ECHO_N -ECHO_T -LIBS -build_alias -host_alias -target_alias -build -build_cpu -build_vendor -build_os -host -host_cpu -host_vendor -host_os -CANONICAL_HOST -INCLUDES -SET_MAKE -CC -CFLAGS -LDFLAGS -CPPFLAGS -ac_ct_CC -EXEEXT -OBJEXT -INSTALL_PROGRAM -INSTALL_SCRIPT -INSTALL_DATA -LN_S -RANLIB -AR -CHMOD -CMP -CP -ENV -FIND -GREP -LN -MKDIR -RMDIR -RM -SED -SORT -TOUCH -AUTOCONF -AUTOHEADER -pkgdbdir -ftp -tar -pax -bootstrap -CPP -EGREP +ac_subst_vars='LTLIBOBJS LIBOBJS -LTLIBOBJS' +EGREP +CPP +bootstrap +ssl_support +pkgdbdir +AUTOHEADER +AUTOCONF +TOUCH +SORT +SED +RM +RMDIR +MKDIR +LN +GREP +FIND +ENV +CP +CMP +CHMOD +AR +RANLIB +LN_S +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +SET_MAKE +INCLUDES +CANONICAL_HOST +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_pkgdbdir -with_ftp -with_tar -with_pax +with_ssl enable_bootstrap ' ac_precious_vars='build_alias @@ -1162,9 +1158,9 @@ fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; - fatal) { $as_echo "$as_me: error: Unrecognized options: $ac_unrecognized_opts" >&2 + fatal) { $as_echo "$as_me: error: unrecognized options: $ac_unrecognized_opts" >&2 { (exit 1); exit 1; }; } ;; - *) $as_echo "$as_me: WARNING: Unrecognized options: $ac_unrecognized_opts" >&2 ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi @@ -1217,7 +1213,7 @@ test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - { $as_echo "$as_me: error: Working directory cannot be determined" >&2 + { $as_echo "$as_me: error: working directory cannot be determined" >&2 { (exit 1); exit 1; }; } test "X$ac_ls_di" = "X$ac_pwd_ls_di" || { $as_echo "$as_me: error: pwd does not report name of working directory" >&2 @@ -1292,7 +1288,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures pkg_install 20070804 to adapt to many kinds of systems. +\`configure' configures pkg_install 20090201 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1357,7 +1353,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pkg_install 20070804:";; + short | recursive ) echo "Configuration of pkg_install 20090201:";; esac cat <<\_ACEOF @@ -1371,9 +1367,7 @@ Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pkgdbdir=DIR Where to put the pkg database (/var/db/pkg) - --with-ftp=path Path to tnftp (PREFIX/bin/ftp) - --with-tar=path Path to pax-as-tar (PREFIX/bin/tar) - --with-pax=path Path to pax (PREFIX/bin/pax) + --with-ssl Enable OpenSSL based signature support Some influential environment variables: CC C compiler command @@ -1451,8 +1445,8 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pkg_install configure 20070804 -generated by GNU Autoconf 2.62 +pkg_install configure 20090201 +generated by GNU Autoconf 2.63 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. @@ -1465,8 +1459,8 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by pkg_install $as_me 20070804, which was -generated by GNU Autoconf 2.62. Invocation command line was +It was created by pkg_install $as_me 20090201, which was +generated by GNU Autoconf 2.63. Invocation command line was $ $0 $@ @@ -1589,8 +1583,8 @@ _ASBOX case $ac_val in #( *${as_nl}*) case $ac_var in #( - *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 -$as_echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( @@ -1793,6 +1787,8 @@ $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi done if $ac_cache_corrupted; then + { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { $as_echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 @@ -2072,12 +2068,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC @@ -2276,12 +2268,8 @@ done else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC @@ -2291,11 +2279,13 @@ fi fi -test -z "$CC" && { { $as_echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +test -z "$CC" && { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 $as_echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + { (exit 1); exit 1; }; }; } # Provide some information about the compiler. $as_echo "$as_me:$LINENO: checking for C compiler version" >&5 @@ -2425,11 +2415,13 @@ if test -z "$ac_file"; then $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 +{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 $as_echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } + { (exit 77); exit 77; }; }; } fi ac_exeext=$ac_cv_exeext @@ -2457,13 +2449,15 @@ $as_echo "$ac_try_echo") >&5 if test "$cross_compiling" = maybe; then cross_compiling=yes else - { { $as_echo "$as_me:$LINENO: error: cannot run C compiled programs. + { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + { (exit 1); exit 1; }; }; } fi fi fi @@ -2506,11 +2500,13 @@ for ac_file in conftest.exe conftest conftest.*; do esac done else - { { $as_echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link + { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + { (exit 1); exit 1; }; }; } fi rm -f conftest$ac_cv_exeext @@ -2564,11 +2560,13 @@ else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 +{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + { (exit 1); exit 1; }; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext @@ -3102,12 +3100,8 @@ fi else case $cross_compiling:$ac_tool_warned in yes:) -{ $as_echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&5 -$as_echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools -whose name does not start with the host triplet. If you think this -configuration is useful to you, please write to autoconf@gnu.org." >&2;} +{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB @@ -3691,31 +3685,11 @@ fi -# Check whether --with-ftp was given. -if test "${with_ftp+set}" = set; then - withval=$with_ftp; ftp="$with_ftp" -else - ftp='$(prefix)/bin/ftp' -fi - - - - -# Check whether --with-tar was given. -if test "${with_tar+set}" = set; then - withval=$with_tar; tar="$with_tar" +# Check whether --with-ssl was given. +if test "${with_ssl+set}" = set; then + withval=$with_ssl; ssl_support=yes else - tar='$(prefix)/bin/tar' -fi - - - - -# Check whether --with-pax was given. -if test "${with_pax+set}" = set; then - withval=$with_pax; pax="$with_pax" -else - pax='$(prefix)/bin/pax' + ssl_support= fi @@ -3796,7 +3770,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_db___db185_open" >&5 $as_echo "$ac_cv_lib_db___db185_open" >&6; } -if test $ac_cv_lib_db___db185_open = yes; then +if test "x$ac_cv_lib_db___db185_open" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBDB 1 _ACEOF @@ -4203,11 +4177,13 @@ rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else - { { $as_echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check + { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 $as_echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + { (exit 1); exit 1; }; }; } fi ac_ext=c @@ -4590,8 +4566,9 @@ ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test `eval 'as_val=${'$as_ac_Header'} - $as_echo "$as_val"'` = yes; then +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -4767,8 +4744,9 @@ ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$ac_res" >&6; } fi -if test `eval 'as_val=${'$as_ac_Header'} - $as_echo "$as_val"'` = yes; then +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -4919,8 +4897,9 @@ ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$ac_res" >&6; } fi -if test `eval 'as_val=${'$as_ac_Header'} - $as_echo "$as_val"'` = yes; then +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -5086,8 +5065,9 @@ ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$ac_res" >&6; } fi -if test `eval 'as_val=${'$as_ac_Header'} - $as_echo "$as_val"'` = yes; then +as_val=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -5193,109 +5173,9 @@ ac_res=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } -if test `eval 'as_val=${'$as_ac_var'} - $as_echo "$as_val"'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - - - -for ac_func in getrlimit setrlimit -do -as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 -$as_echo_n "checking for $ac_func... " >&6; } -if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then - $as_echo_n "(cached) " >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func. - For example, HP-UX 11i <limits.h> declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer <limits.h> to <assert.h> if __STDC__ is defined, since - <limits.h> exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include <limits.h> -#else -# include <assert.h> -#endif - -#undef $ac_func - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$ac_func || defined __stub___$ac_func -choke me -#endif - -int -main () -{ -return $ac_func (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (ac_try="$ac_link" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" -$as_echo "$ac_try_echo") >&5 - (eval "$ac_link") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { - test -z "$ac_c_werror_flag" || - test ! -s conftest.err - } && test -s conftest$ac_exeext && { - test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext - }; then - eval "$as_ac_var=yes" -else - $as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - eval "$as_ac_var=no" -fi - -rm -rf conftest.dSYM -rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ - conftest$ac_exeext conftest.$ac_ext -fi -ac_res=`eval 'as_val=${'$as_ac_var'} +as_val=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` - { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -if test `eval 'as_val=${'$as_ac_var'} - $as_echo "$as_val"'` = yes; then + if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF @@ -5542,7 +5422,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_socket_socket" >&5 $as_echo "$ac_cv_lib_socket_socket" >&6; } -if test $ac_cv_lib_socket_socket = yes; then +if test "x$ac_cv_lib_socket_socket" = x""yes; then LIBS="-lsocket -lnsl $LIBS" fi @@ -6215,11 +6095,13 @@ done case $ac_lo in ?*) ac_cv_sizeof_int=$ac_lo;; '') if test "$ac_cv_type_int" = yes; then - { { $as_echo "$as_me:$LINENO: error: cannot compute sizeof (int) + { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: cannot compute sizeof (int) See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot compute sizeof (int) See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } + { (exit 77); exit 77; }; }; } else ac_cv_sizeof_int=0 fi ;; @@ -6295,11 +6177,13 @@ sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) if test "$ac_cv_type_int" = yes; then - { { $as_echo "$as_me:$LINENO: error: cannot compute sizeof (int) + { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: cannot compute sizeof (int) See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot compute sizeof (int) See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } + { (exit 77); exit 77; }; }; } else ac_cv_sizeof_int=0 fi @@ -6570,11 +6454,13 @@ done case $ac_lo in ?*) ac_cv_sizeof_long=$ac_lo;; '') if test "$ac_cv_type_long" = yes; then - { { $as_echo "$as_me:$LINENO: error: cannot compute sizeof (long) + { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: cannot compute sizeof (long) See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot compute sizeof (long) See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } + { (exit 77); exit 77; }; }; } else ac_cv_sizeof_long=0 fi ;; @@ -6650,11 +6536,13 @@ sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) if test "$ac_cv_type_long" = yes; then - { { $as_echo "$as_me:$LINENO: error: cannot compute sizeof (long) + { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: cannot compute sizeof (long) See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot compute sizeof (long) See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } + { (exit 77); exit 77; }; }; } else ac_cv_sizeof_long=0 fi @@ -6925,11 +6813,13 @@ done case $ac_lo in ?*) ac_cv_sizeof_long_long=$ac_lo;; '') if test "$ac_cv_type_long_long" = yes; then - { { $as_echo "$as_me:$LINENO: error: cannot compute sizeof (long long) + { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: cannot compute sizeof (long long) See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot compute sizeof (long long) See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } + { (exit 77); exit 77; }; }; } else ac_cv_sizeof_long_long=0 fi ;; @@ -7005,11 +6895,13 @@ sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) if test "$ac_cv_type_long_long" = yes; then - { { $as_echo "$as_me:$LINENO: error: cannot compute sizeof (long long) + { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ { $as_echo "$as_me:$LINENO: error: cannot compute sizeof (long long) See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot compute sizeof (long long) See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } + { (exit 77); exit 77; }; }; } else ac_cv_sizeof_long_long=0 fi @@ -7043,7 +6935,7 @@ esac -ac_config_files="$ac_config_files Makefile add/Makefile admin/Makefile audit-packages/Makefile audit-packages/audit-packages.1 audit-packages/audit-packages.cat1 audit-packages/audit-packages.conf audit-packages/audit-packages.conf.5 audit-packages/audit-packages.conf.cat5 audit-packages/download-vulnerability-list.1 audit-packages/download-vulnerability-list.cat1 audit-packages/download-vulnerability-list.sh bpm/bpm.sh create/Makefile delete/Makefile info/Makefile lib/Makefile view/Makefile view/linkfarm.sh view/pkg_view.sh" +ac_config_files="$ac_config_files Makefile add/Makefile admin/Makefile bpm/bpm.sh create/Makefile delete/Makefile info/Makefile lib/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -7072,8 +6964,8 @@ _ACEOF case $ac_val in #( *${as_nl}*) case $ac_var in #( - *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5 -$as_echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;; + *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( @@ -7464,8 +7356,8 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by pkg_install $as_me 20070804, which was -generated by GNU Autoconf 2.62. Invocation command line was +This file was extended by pkg_install $as_me 20090201, which was +generated by GNU Autoconf 2.63. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -7478,6 +7370,15 @@ on `(hostname || uname -n) 2>/dev/null | sed 1q` _ACEOF +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" @@ -7490,16 +7391,17 @@ ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. -Usage: $0 [OPTIONS] [FILE]... +Usage: $0 [OPTION]... [FILE]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit - -q, --quiet do not print progress messages + -q, --quiet, --silent + do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] + --file=FILE[:TEMPLATE] instantiate the configuration file FILE - --header=FILE[:TEMPLATE] + --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: @@ -7513,8 +7415,8 @@ Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ -pkg_install config.status 20070804 -configured by $0, generated by GNU Autoconf 2.62, +pkg_install config.status 20090201 +configured by $0, generated by GNU Autoconf 2.63, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2008 Free Software Foundation, Inc. @@ -7633,23 +7535,11 @@ do "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "add/Makefile") CONFIG_FILES="$CONFIG_FILES add/Makefile" ;; "admin/Makefile") CONFIG_FILES="$CONFIG_FILES admin/Makefile" ;; - "audit-packages/Makefile") CONFIG_FILES="$CONFIG_FILES audit-packages/Makefile" ;; - "audit-packages/audit-packages.1") CONFIG_FILES="$CONFIG_FILES audit-packages/audit-packages.1" ;; - "audit-packages/audit-packages.cat1") CONFIG_FILES="$CONFIG_FILES audit-packages/audit-packages.cat1" ;; - "audit-packages/audit-packages.conf") CONFIG_FILES="$CONFIG_FILES audit-packages/audit-packages.conf" ;; - "audit-packages/audit-packages.conf.5") CONFIG_FILES="$CONFIG_FILES audit-packages/audit-packages.conf.5" ;; - "audit-packages/audit-packages.conf.cat5") CONFIG_FILES="$CONFIG_FILES audit-packages/audit-packages.conf.cat5" ;; - "audit-packages/download-vulnerability-list.1") CONFIG_FILES="$CONFIG_FILES audit-packages/download-vulnerability-list.1" ;; - "audit-packages/download-vulnerability-list.cat1") CONFIG_FILES="$CONFIG_FILES audit-packages/download-vulnerability-list.cat1" ;; - "audit-packages/download-vulnerability-list.sh") CONFIG_FILES="$CONFIG_FILES audit-packages/download-vulnerability-list.sh" ;; "bpm/bpm.sh") CONFIG_FILES="$CONFIG_FILES bpm/bpm.sh" ;; "create/Makefile") CONFIG_FILES="$CONFIG_FILES create/Makefile" ;; "delete/Makefile") CONFIG_FILES="$CONFIG_FILES delete/Makefile" ;; "info/Makefile") CONFIG_FILES="$CONFIG_FILES info/Makefile" ;; "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; - "view/Makefile") CONFIG_FILES="$CONFIG_FILES view/Makefile" ;; - "view/linkfarm.sh") CONFIG_FILES="$CONFIG_FILES view/linkfarm.sh" ;; - "view/pkg_view.sh") CONFIG_FILES="$CONFIG_FILES view/pkg_view.sh" ;; *) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 $as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;} @@ -7730,7 +7620,8 @@ for ac_last_try in false false false false false :; do $as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` = $ac_delim_num; then + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 @@ -7935,9 +7826,9 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 } split(mac1, mac2, "(") #) macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". - prefix = substr(line, 1, index(line, defundef) - 1) print prefix "define", macro P[macro] D[macro] next } else { @@ -7945,7 +7836,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { - print "/*", line, "*/" + print "/*", prefix defundef, macro, "*/" next } } @@ -7969,8 +7860,8 @@ do esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) { { $as_echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5 -$as_echo "$as_me: error: Invalid tag $ac_tag." >&2;} + :L* | :C*:*) { { $as_echo "$as_me:$LINENO: error: invalid tag $ac_tag" >&5 +$as_echo "$as_me: error: invalid tag $ac_tag" >&2;} { (exit 1); exit 1; }; };; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; @@ -8293,7 +8184,7 @@ if test "$no_create" != yes; then $ac_cs_success || { (exit 1); exit 1; } fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then - { $as_echo "$as_me:$LINENO: WARNING: Unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: Unrecognized options: $ac_unrecognized_opts" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi diff --git a/pkgtools/pkg_install/files/configure.ac b/pkgtools/pkg_install/files/configure.ac index 8881e5e568b..9262635829c 100644 --- a/pkgtools/pkg_install/files/configure.ac +++ b/pkgtools/pkg_install/files/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.52) -AC_INIT([pkg_install], [20070804], [joerg@NetBSD.org]) +AC_INIT([pkg_install], [20090201], [joerg@NetBSD.org]) AC_CONFIG_SRCDIR([lib/plist.c]) AC_CONFIG_HEADER(lib/config.h) @@ -43,23 +43,11 @@ AC_ARG_WITH(pkgdbdir, [ pkgdbdir="/var/db/pkg" ]) AC_SUBST(pkgdbdir) -AC_ARG_WITH(ftp, -[ --with-ftp=path Path to tnftp (PREFIX/bin/ftp)], -[ ftp="$with_ftp" ], -[ ftp='$(prefix)/bin/ftp' ]) -AC_SUBST(ftp) - -AC_ARG_WITH(tar, -[ --with-tar=path Path to pax-as-tar (PREFIX/bin/tar)], -[ tar="$with_tar" ], -[ tar='$(prefix)/bin/tar' ]) -AC_SUBST(tar) - -AC_ARG_WITH(pax, -[ --with-pax=path Path to pax (PREFIX/bin/pax)], -[ pax="$with_pax" ], -[ pax='$(prefix)/bin/pax' ]) -AC_SUBST(pax) +AC_ARG_WITH(ssl, +[ --with-ssl Enable OpenSSL based signature support], +[ ssl_support=yes ], +[ ssl_support= ]) +AC_SUBST(ssl_support) AC_ARG_ENABLE([bootstrap], [AS_HELP_STRING([--enable-bootstrap], [build minimal version of pkg_install])], @@ -85,7 +73,6 @@ AC_CHECK_HEADERS([sys/cdefs.h sys/file.h sys/ioctl.h sys/param.h \ # Checks for library functions. AC_CHECK_FUNCS([chflags dbopen __db185_open tgetent vfork]) -AC_CHECK_FUNCS([getrlimit setrlimit]) AC_SEARCH_LIBS([gethostbyname], [nsl]) AC_SEARCH_LIBS([socket], @@ -159,14 +146,7 @@ AH_BOTTOM( #endif ) -AC_CONFIG_FILES([Makefile add/Makefile admin/Makefile - audit-packages/Makefile audit-packages/audit-packages.1 \ - audit-packages/audit-packages.cat1 audit-packages/audit-packages.conf \ - audit-packages/audit-packages.conf.5 \ - audit-packages/audit-packages.conf.cat5 \ - audit-packages/download-vulnerability-list.1 \ - audit-packages/download-vulnerability-list.cat1 \ - audit-packages/download-vulnerability-list.sh bpm/bpm.sh \ - create/Makefile delete/Makefile info/Makefile lib/Makefile \ - view/Makefile view/linkfarm.sh view/pkg_view.sh]) +AC_CONFIG_FILES([Makefile add/Makefile admin/Makefile bpm/bpm.sh \ + create/Makefile delete/Makefile info/Makefile \ + lib/Makefile]) AC_OUTPUT diff --git a/pkgtools/pkg_install/files/create/build.c b/pkgtools/pkg_install/files/create/build.c index 4cc1a405e21..0ebb692f3f1 100644 --- a/pkgtools/pkg_install/files/create/build.c +++ b/pkgtools/pkg_install/files/create/build.c @@ -1,4 +1,4 @@ -/* $NetBSD: build.c,v 1.8 2008/04/23 16:58:07 joerg Exp $ */ +/* $NetBSD: build.c,v 1.9 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,13 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -#if 0 -static const char *rcsid = "from FreeBSD Id: perform.c,v 1.38 1997/10/13 15:03:51 jkh Exp"; -#else -__RCSID("$NetBSD: build.c,v 1.8 2008/04/23 16:58:07 joerg Exp $"); -#endif -#endif +__RCSID("$NetBSD: build.c,v 1.9 2009/02/02 12:35:01 joerg Exp $"); /*- * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>. @@ -251,8 +245,7 @@ make_dist(const char *pkg, const char *suffix, const package_t *plist) else archive_write_set_compression_none(archive); - if (asprintf(&archive_name, "%s.%s", pkg, suffix) == -1) - err(2, "cannot compute output name"); + archive_name = xasprintf("%s.%s", pkg, suffix); if (archive_write_open_file(archive, archive_name)) errx(2, "cannot create archive: %s", archive_error_string(archive)); diff --git a/pkgtools/pkg_install/files/create/main.c b/pkgtools/pkg_install/files/create/main.c index f5d69fe59f3..aa316d80229 100644 --- a/pkgtools/pkg_install/files/create/main.c +++ b/pkgtools/pkg_install/files/create/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.11 2007/08/03 13:15:59 joerg Exp $ */ +/* $NetBSD: main.c,v 1.12 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,13 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -#if 0 -static const char *rcsid = "from FreeBSD Id: main.c,v 1.17 1997/10/08 07:46:23 charnier Exp"; -#else -__RCSID("$NetBSD: main.c,v 1.11 2007/08/03 13:15:59 joerg Exp $"); -#endif -#endif +__RCSID("$NetBSD: main.c,v 1.12 2009/02/02 12:35:01 joerg Exp $"); /* * FreeBSD install - a package for the installation and maintainance diff --git a/pkgtools/pkg_install/files/create/perform.c b/pkgtools/pkg_install/files/create/perform.c index 6cb63435da9..5389f7e1d61 100644 --- a/pkgtools/pkg_install/files/create/perform.c +++ b/pkgtools/pkg_install/files/create/perform.c @@ -1,4 +1,4 @@ -/* $NetBSD: perform.c,v 1.22 2008/09/17 15:21:30 joerg Exp $ */ +/* $NetBSD: perform.c,v 1.23 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,13 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -#if 0 -static const char *rcsid = "from FreeBSD Id: perform.c,v 1.38 1997/10/13 15:03:51 jkh Exp"; -#else -__RCSID("$NetBSD: perform.c,v 1.22 2008/09/17 15:21:30 joerg Exp $"); -#endif -#endif +__RCSID("$NetBSD: perform.c,v 1.23 2009/02/02 12:35:01 joerg Exp $"); /* * FreeBSD install - a package for the installation and maintainance @@ -91,13 +85,45 @@ register_depends(package_t *plist, char *deps, int build_only) } /* + * Expect "fname" to point at a file, and read it into + * the buffer returned. + */ +static char * +fileGetContents(char *fname) +{ + char *contents; + struct stat sb; + int fd; + + if (stat(fname, &sb) == FAIL) { + cleanup(0); + errx(2, "can't stat '%s'", fname); + } + + contents = xmalloc((size_t) (sb.st_size) + 1); + fd = open(fname, O_RDONLY, 0); + if (fd == FAIL) { + cleanup(0); + errx(2, "unable to open '%s' for reading", fname); + } + if (read(fd, contents, (size_t) sb.st_size) != (size_t) sb.st_size) { + cleanup(0); + errx(2, "short read on '%s' - did not get %lld bytes", + fname, (long long) sb.st_size); + } + close(fd); + contents[(size_t) sb.st_size] = '\0'; + return contents; +} + +/* * Get a string parameter as a file spec or as a "contents follow -" spec */ static void get_dash_string(char **s) { if (**s == '-') - *s = strdup(*s + 1); + *s = xstrdup(*s + 1); else *s = fileGetContents(*s); } @@ -114,8 +140,7 @@ pkg_perform(const char *pkg) /* Break the package name into base and desired suffix (if any) */ if ((cp = strrchr(pkg, '.')) != NULL) { - if ((allocated_pkg = malloc(cp - pkg + 1)) == NULL) - err(2, "malloc failed"); + allocated_pkg = xmalloc(cp - pkg + 1); memcpy(allocated_pkg, pkg, cp - pkg); allocated_pkg[cp - pkg] = '\0'; suffix = cp + 1; @@ -140,6 +165,7 @@ pkg_perform(const char *pkg) if (!pkg_in) errx(2, "unable to open contents file '%s' for input", Contents); } + plist.head = plist.tail = NULL; /* If a SrcDir override is set, add it now */ diff --git a/pkgtools/pkg_install/files/create/pkg_create.1 b/pkgtools/pkg_install/files/create/pkg_create.1 index 1bb2ffbaf72..16a3af95c74 100644 --- a/pkgtools/pkg_install/files/create/pkg_create.1 +++ b/pkgtools/pkg_install/files/create/pkg_create.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: pkg_create.1,v 1.15 2008/01/04 14:24:38 rillig Exp $ +.\" $NetBSD: pkg_create.1,v 1.16 2009/02/02 12:35:01 joerg Exp $ .\" .\" FreeBSD install - a package for the installation and maintenance .\" of non-core utilities. @@ -24,7 +24,7 @@ .\" [jkh] Took John's changes back and made some additional extensions for .\" better integration with FreeBSD's new ports collection. .\" -.Dd August 10, 2007 +.Dd July 28, 2008 .Dt PKG_CREATE 1 .Os .Sh NAME @@ -514,13 +514,3 @@ refined it for .Nx wildcard dependency processing, pkgdb, pkg size recording etc. .El -.Sh BUGS -Hard links between files in a distribution must be bracketed by -.Cm @cwd -directives in order to be preserved as hard links when the package is -extracted. -They additionally must not end up being split between -.Cm tar -invocations due to exec argument-space limitations (this depends on the -value returned by -.Fn sysconf _SC_ARG_MAX ) . diff --git a/pkgtools/pkg_install/files/create/pkg_create.cat1 b/pkgtools/pkg_install/files/create/pkg_create.cat1 index 0825cd1bc44..5d6f23d23d8 100644 --- a/pkgtools/pkg_install/files/create/pkg_create.cat1 +++ b/pkgtools/pkg_install/files/create/pkg_create.cat1 @@ -289,11 +289,4 @@ AAUUTTHHOORRSS NetBSD wildcard dependency processing, pkgdb, pkg size recording etc. -BBUUGGSS - Hard links between files in a distribution must be bracketed by @@ccwwdd - directives in order to be preserved as hard links when the package is - extracted. They additionally must not end up being split between ttaarr - invocations due to exec argument-space limitations (this depends on the - value returned by ssyyssccoonnff(___S_C___A_R_G___M_A_X)). - -NetBSD 4.0 August 10, 2007 NetBSD 4.0 +NetBSD 4.0 July 28, 2008 NetBSD 4.0 diff --git a/pkgtools/pkg_install/files/create/pl.c b/pkgtools/pkg_install/files/create/pl.c index 6323bdba9fc..7218167f520 100644 --- a/pkgtools/pkg_install/files/create/pl.c +++ b/pkgtools/pkg_install/files/create/pl.c @@ -1,4 +1,4 @@ -/* $NetBSD: pl.c,v 1.11 2008/09/16 13:32:58 joerg Exp $ */ +/* $NetBSD: pl.c,v 1.12 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,13 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -#if 0 -static const char *rcsid = "from FreeBSD Id: pl.c,v 1.11 1997/10/08 07:46:35 charnier Exp"; -#else -__RCSID("$NetBSD: pl.c,v 1.11 2008/09/16 13:32:58 joerg Exp $"); -#endif -#endif +__RCSID("$NetBSD: pl.c,v 1.12 2009/02/02 12:35:01 joerg Exp $"); /* * FreeBSD install - a package for the installation and maintainance @@ -98,22 +92,18 @@ reorder(package_t *pkg, int dirc) char **dirv; int i; - if ((dirv = (char **) calloc(dirc, sizeof(char *))) == (char **) NULL) { - warn("No directory re-ordering will be done"); - } else { - for (p = pkg->head, i = 0; p; p = p->next) { - if (p->type == PLIST_DIR_RM) { - dirv[i++] = p->name; - } - } - qsort(dirv, dirc, sizeof(char *), dircmp); - for (p = pkg->head, i = 0; p; p = p->next) { - if (p->type == PLIST_DIR_RM) { - p->name = dirv[i++]; - } - } - (void) free(dirv); + dirv = xcalloc(dirc, sizeof(char *)); + + for (p = pkg->head, i = 0; p; p = p->next) { + if (p->type == PLIST_DIR_RM) + dirv[i++] = p->name; + } + qsort(dirv, dirc, sizeof(char *), dircmp); + for (p = pkg->head, i = 0; p; p = p->next) { + if (p->type == PLIST_DIR_RM) + p->name = dirv[i++]; } + free(dirv); } /* @@ -169,17 +159,11 @@ check_list(package_t *pkg, const char *PkgName) p->name); s = pkgdb_retrieve(t); -#ifdef PKGDB_DEBUG - fprintf(stderr, "pkgdb_retrieve(\"%s\")=\"%s\"\n", t, s); /* pkgdb-debug - HF */ -#endif if (s && PlistOnly) warnx("Overwriting %s - " "pkg %s bogus/conflicting?", t, s); else { pkgdb_store(t, PkgName); -#ifdef PKGDB_DEBUG - fprintf(stderr, "pkgdb_store(\"%s\", \"%s\")\n", t, PkgName); /* pkgdb-debug - HF */ -#endif } } @@ -210,7 +194,7 @@ check_list(package_t *pkg, const char *PkgName) } target[SymlinkHeaderLen + cc] = 0x0; tmp = new_plist_entry(); - tmp->name = strdup(target); + tmp->name = xstrdup(target); tmp->type = PLIST_COMMENT; tmp->next = p->next; tmp->prev = p; @@ -231,7 +215,7 @@ check_list(package_t *pkg, const char *PkgName) sizeof(buf)); if (MD5File(name, &buf[ChecksumHeaderLen]) != (char *) NULL) { tmp = new_plist_entry(); - tmp->name = strdup(buf); + tmp->name = xstrdup(buf); tmp->type = PLIST_COMMENT; /* PLIST_MD5 - HF */ tmp->next = p->next; tmp->prev = p; diff --git a/pkgtools/pkg_install/files/create/util.c b/pkgtools/pkg_install/files/create/util.c index 351bb0e8cf0..d17b1fed763 100644 --- a/pkgtools/pkg_install/files/create/util.c +++ b/pkgtools/pkg_install/files/create/util.c @@ -95,13 +95,10 @@ make_memory_file(const char *archive_name, void *data, size_t len, { struct memory_file *file; - if ((file = malloc(sizeof(*file))) == NULL) - err(2, "malloc failed"); - + file = xmalloc(sizeof(*file)); file->name = archive_name; file->owner = owner; file->group = group; - file->data = data; file->len = len; @@ -126,9 +123,7 @@ load_memory_file(const char *disk_name, struct memory_file *file; int fd; - if ((file = malloc(sizeof(*file))) == NULL) - err(2, "malloc failed"); - + file = xmalloc(sizeof(*file)); file->name = archive_name; file->owner = owner; file->group = group; @@ -144,9 +139,9 @@ load_memory_file(const char *disk_name, if ((file->st.st_mode & S_IFMT) != S_IFREG) errx(1, "meta data file %s is not regular file", disk_name); - if (file->st.st_size > SSIZE_MAX || - (file->data = malloc(file->st.st_size)) == NULL) - errx(2, "cannot allocate memory for file %s", disk_name); + if (file->st.st_size > SSIZE_MAX) + errx(2, "meta data file too large: %s", disk_name); + file->data = xmalloc(file->st.st_size); if (read(fd, file->data, file->st.st_size) != file->st.st_size) err(2, "cannot read file into memory %s", disk_name); diff --git a/pkgtools/pkg_install/files/delete/delete.h b/pkgtools/pkg_install/files/delete/delete.h index 116025d8557..02d3ea3dda6 100644 --- a/pkgtools/pkg_install/files/delete/delete.h +++ b/pkgtools/pkg_install/files/delete/delete.h @@ -1,4 +1,4 @@ -/* $NetBSD: delete.h,v 1.5 2007/07/30 07:16:21 joerg Exp $ */ +/* $NetBSD: delete.h,v 1.6 2009/02/02 12:35:01 joerg Exp $ */ /* from FreeBSD Id: delete.h,v 1.4 1997/02/22 16:09:35 peter Exp */ @@ -25,6 +25,7 @@ #ifndef _INST_DELETE_H_INCLUDE #define _INST_DELETE_H_INCLUDE +extern char *Destdir; extern char *Prefix; extern char *ProgramPath; extern Boolean NoDeleteFiles; diff --git a/pkgtools/pkg_install/files/delete/main.c b/pkgtools/pkg_install/files/delete/main.c index 94a3c0bbe70..3ab5fb19c1a 100644 --- a/pkgtools/pkg_install/files/delete/main.c +++ b/pkgtools/pkg_install/files/delete/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.21 2007/09/08 09:58:14 rillig Exp $ */ +/* $NetBSD: main.c,v 1.22 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,13 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -#if 0 -static char *rcsid = "from FreeBSD Id: main.c,v 1.11 1997/10/08 07:46:48 charnier Exp"; -#else -__RCSID("$NetBSD: main.c,v 1.21 2007/09/08 09:58:14 rillig Exp $"); -#endif -#endif +__RCSID("$NetBSD: main.c,v 1.22 2009/02/02 12:35:01 joerg Exp $"); /* * @@ -42,8 +36,10 @@ __RCSID("$NetBSD: main.c,v 1.21 2007/09/08 09:58:14 rillig Exp $"); #include "lib.h" #include "delete.h" -static char Options[] = "DdFfhK:NnOp:RrVv"; +static char Options[] = "DdFfhK:NnOp:P:RrVv"; +char *Destdir = NULL; +char *Pkgdb = NULL; char *Prefix = NULL; char *ProgramPath = NULL; Boolean NoDeleteFiles = FALSE; @@ -58,7 +54,7 @@ lpkg_head_t pkgs; static void usage(void) { - fprintf(stderr, "usage: pkg_delete [-DdFfNnORrVv] [-K pkg_dbdir] [-p prefix] pkg-name ...\n"); + fprintf(stderr, "usage: pkg_delete [-DdFfNnORrVv] [-K pkg_dbdir] [-P destdir] [-p prefix] pkg-name ...\n"); exit(1); } @@ -92,7 +88,7 @@ main(int argc, char **argv) break; case 'K': - _pkgdb_setPKGDB_DIR(optarg); + Pkgdb = xstrdup(optarg); break; case 'N': @@ -109,6 +105,10 @@ main(int argc, char **argv) OnlyDeleteFromPkgDB = TRUE; break; + case 'P': + Destdir = optarg; + break; + case 'p': Prefix = optarg; break; @@ -141,6 +141,19 @@ main(int argc, char **argv) TAILQ_INIT(&pkgs); + if (Pkgdb == NULL) + Pkgdb = xstrdup(_pkgdb_getPKGDB_DIR()); + + if (Destdir != NULL) { + char *pkgdbdir; + + pkgdbdir = xasprintf("%s/%s", Destdir, Pkgdb); + _pkgdb_setPKGDB_DIR(pkgdbdir); + free(pkgdbdir); + } else { + _pkgdb_setPKGDB_DIR(Pkgdb); + } + /* Get all the remaining package names, if any */ if (File2Pkg && !pkgdb_open(ReadOnly)) { err(EXIT_FAILURE, "cannot open pkgdb"); @@ -167,11 +180,8 @@ main(int argc, char **argv) errx(EXIT_FAILURE, "error expanding '%s' ('%s' nonexistent?)", *argv, _pkgdb_getPKGDB_DIR()); } } else { - const char *dbdir; - - dbdir = _pkgdb_getPKGDB_DIR(); - if (**argv == '/' && strncmp(*argv, dbdir, strlen(dbdir)) == 0) { - *argv += strlen(dbdir) + 1; + if (**argv == '/' && strncmp(*argv, Pkgdb, strlen(Pkgdb)) == 0) { + *argv += strlen(Pkgdb) + 1; if ((*argv)[strlen(*argv) - 1] == '/') { (*argv)[strlen(*argv) - 1] = 0; } diff --git a/pkgtools/pkg_install/files/delete/perform.c b/pkgtools/pkg_install/files/delete/perform.c index 26896527cfb..58ec8e0e3b3 100644 --- a/pkgtools/pkg_install/files/delete/perform.c +++ b/pkgtools/pkg_install/files/delete/perform.c @@ -1,4 +1,4 @@ -/* $NetBSD: perform.c,v 1.24 2008/09/17 15:21:30 joerg Exp $ */ +/* $NetBSD: perform.c,v 1.25 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,13 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -#if 0 -static const char *rcsid = "from FreeBSD Id: perform.c,v 1.15 1997/10/13 15:03:52 jkh Exp"; -#else -__RCSID("$NetBSD: perform.c,v 1.24 2008/09/17 15:21:30 joerg Exp $"); -#endif -#endif +__RCSID("$NetBSD: perform.c,v 1.25 2009/02/02 12:35:01 joerg Exp $"); /* * FreeBSD install - a package for the installation and maintainance @@ -81,13 +75,12 @@ typedef enum { static int require_find_recursive_up(lpkg_t *); static int require_find_recursive_down(lpkg_t *, package_t *); static int require_find(char *, rec_find_t); -static int require_delete(char *, int); +static int require_delete(int); static void require_print(void); static int undepend(const char *, void *); static char LogDir[MaxPathSize]; static char linebuf[MaxPathSize]; -static char pkgdir[MaxPathSize]; static package_t Plist; @@ -95,13 +88,19 @@ static lpkg_head_t lpfindq; static lpkg_head_t lpdelq; static void -sanity_check(char *pkg) +sanity_check(const char *pkg) { - if (!fexists(CONTENTS_FNAME)) { + char *fname; + + fname = pkgdb_pkg_file(pkg, CONTENTS_FNAME); + + if (!fexists(fname)) { cleanup(0); errx(2, "installed package %s has no %s file!", pkg, CONTENTS_FNAME); } + + free(fname); } void @@ -120,32 +119,25 @@ cleanup(int sig) static int undepend(const char *deppkgname, void *vp) { - char *pkg2delname = vp; - char fname[MaxPathSize], ftmp[MaxPathSize]; - char fbuf[MaxPathSize]; - FILE *fp, *fpwr; - int s; - - (void) snprintf(fname, sizeof(fname), "%s/%s/%s", - _pkgdb_getPKGDB_DIR(), deppkgname, REQUIRED_BY_FNAME); - fp = fopen(fname, "r"); - if (fp == NULL) { + char *fname, *fname_tmp; + char fbuf[MaxPathSize]; + const char *pkg2delname = vp; + FILE *fp, *fpwr; + + fname = pkgdb_pkg_file(deppkgname, REQUIRED_BY_FNAME); + fname_tmp = pkgdb_pkg_file(deppkgname, REQUIRED_BY_FNAME_TMP); + + if ((fp = fopen(fname, "r")) == NULL) { warnx("couldn't open dependency file `%s'", fname); + free(fname); + free(fname_tmp); return 0; } - (void) snprintf(ftmp, sizeof(ftmp), "%s.XXXXXX", fname); - s = mkstemp(ftmp); - if (s == -1) { - fclose(fp); - warnx("couldn't open temp file `%s'", ftmp); - return 0; - } - fpwr = fdopen(s, "w"); - if (fpwr == NULL) { - close(s); + if ((fpwr = fopen(fname_tmp, "w")) == NULL) { fclose(fp); - warnx("couldn't fdopen temp file `%s'", ftmp); - remove(ftmp); + warnx("couldn't open temporary file `%s'", fname_tmp); + free(fname); + free(fname_tmp); return 0; } while (fgets(fbuf, sizeof(fbuf), fp) != NULL) { @@ -155,20 +147,19 @@ undepend(const char *deppkgname, void *vp) fputs(fbuf, fpwr), putc('\n', fpwr); } (void) fclose(fp); - if (fchmod(s, 0644) == FAIL) { - warnx("error changing permission of temp file `%s'", ftmp); - fclose(fpwr); - remove(ftmp); - return 0; - } if (fclose(fpwr) == EOF) { - warnx("error closing temp file `%s'", ftmp); - remove(ftmp); + warnx("error closing temporary file `%s'", fname_tmp); + remove(fname_tmp); + free(fname); + free(fname_tmp); return 0; } - if (rename(ftmp, fname) == -1) - warn("error renaming `%s' to `%s'", ftmp, fname); - remove(ftmp); /* just in case */ + if (rename(fname_tmp, fname) == -1) + warn("error renaming `%s' to `%s'", fname_tmp, fname); + remove(fname_tmp); /* just in case */ + + free(fname); + free(fname_tmp); return 0; } @@ -180,18 +171,16 @@ undepend(const char *deppkgname, void *vp) static int unview(const char *pkgname) { - char fname[MaxPathSize], ftmp[MaxPathSize]; + const char *dbdir; + char *fname, *fname_tmp; char fbuf[MaxPathSize]; - char dbdir[MaxPathSize]; FILE *fp, *fpwr; - int s; + int rv; int cc; - (void) snprintf(dbdir, sizeof(dbdir), "%s", _pkgdb_getPKGDB_DIR()); + dbdir = _pkgdb_getPKGDB_DIR(); - /* Get the depot directory. */ - (void) snprintf(fname, sizeof(fname), "%s/%s/%s", - dbdir, pkgname, DEPOT_FNAME); + fname = pkgdb_pkg_file(pkgname, DEPOT_FNAME); if ((fp = fopen(fname, "r")) == NULL) { warnx("unable to open `%s' file", fname); return -1; @@ -199,33 +188,32 @@ unview(const char *pkgname) if (fgets(fbuf, sizeof(fbuf), fp) == NULL) { (void) fclose(fp); warnx("empty depot file `%s'", fname); + free(fname); return -1; } if (fbuf[cc = strlen(fbuf) - 1] == '\n') { fbuf[cc] = 0; } fclose(fp); + free(fname); /* * Copy the contents of the +VIEWS file into a temp file, but * skip copying the name of the current view's package dbdir. */ - (void) snprintf(fname, sizeof(fname), "%s/%s", fbuf, VIEWS_FNAME); + fname = pkgdb_pkg_file(pkgname, VIEWS_FNAME); + fname_tmp = pkgdb_pkg_file(pkgname, VIEWS_FNAME_TMP); if ((fp = fopen(fname, "r")) == NULL) { warnx("unable to open `%s' file", fname); + free(fname); + free(fname_tmp); return -1; } - (void) snprintf(ftmp, sizeof(ftmp), "%s.XXXXXX", fname); - if ((s = mkstemp(ftmp)) == -1) { - (void) fclose(fp); - warnx("unable to open `%s' temp file", ftmp); - return -1; - } - if ((fpwr = fdopen(s, "w")) == NULL) { - (void) close(s); - (void) remove(ftmp); + if ((fpwr = fopen(fname_tmp, "w")) == NULL) { (void) fclose(fp); - warnx("unable to fdopen `%s' temp file", ftmp); + warnx("unable to fopen `%s' temporary file", fname_tmp); + free(fname); + free(fname_tmp); return -1; } while (fgets(fbuf, sizeof(fbuf), fp) != NULL) { @@ -238,45 +226,36 @@ unview(const char *pkgname) } } (void) fclose(fp); - if (fchmod(s, 0644) == FAIL) { - (void) fclose(fpwr); - (void) remove(ftmp); - warnx("unable to change permissions of `%s' temp file", ftmp); - return -1; - } + if (fclose(fpwr) == EOF) { - (void) remove(ftmp); - warnx("unable to close `%s' temp file", ftmp); + remove(fname_tmp); + warnx("unable to close `%s' temp file", fname_tmp); + free(fname); + free(fname_tmp); return -1; } /* Rename the temp file to the +VIEWS file */ - if (rename(ftmp, fname) == -1) { - (void) remove(ftmp); - warnx("unable to rename `%s' to `%s'", ftmp, fname); - return -1; - } - return 0; + if ((rv = rename(fname_tmp, fname)) == -1) + warnx("unable to rename `%s' to `%s'", fname_tmp, fname); + + remove(fname_tmp); + free(fname); + free(fname_tmp); + + return rv; } /* * Delete from directory 'home' all packages on lpkg_list. * If tryall is set, ignore errors from pkg_delete(1). */ -int -require_delete(char *home, int tryall) +static int +require_delete(int tryall) { char *best_installed; lpkg_t *lpp; int rv, fail; - int oldcwd; - - /* save cwd */ - oldcwd = open(".", O_RDONLY, 0); - if (oldcwd == -1) - err(EXIT_FAILURE, "cannot open \".\""); - - (void) snprintf(pkgdir, sizeof(pkgdir), "%s", _pkgdb_getPKGDB_DIR()); best_installed = NULL; @@ -287,38 +266,15 @@ require_delete(char *home, int tryall) free(best_installed); best_installed = NULL; - /* go to the db dir */ - if (chdir(pkgdir) == FAIL) { - warnx("unable to change directory to %s, deinstall failed (1)", - pkgdir); - fail = 1; - break; - } - /* look to see if package was already deleted */ - if (ispkgpattern(lpp->lp_name)) { - - best_installed = find_best_matching_installed_pkg(lpp->lp_name); - if (best_installed == NULL) { - warnx("%s appears to have been deleted", lpp->lp_name); - continue; - } - } else { - if (!fexists(lpp->lp_name)) { - warnx("%s appears to have been deleted", lpp->lp_name); - continue; - } - } - - /* return home for execution of command */ - if (chdir(home) == FAIL) { - warnx("unable to change directory to %s, deinstall failed (2)", home); - fail = 1; - break; + best_installed = find_best_matching_installed_pkg(lpp->lp_name); + if (best_installed == NULL) { + warnx("%s appears to have been deleted", lpp->lp_name); + continue; } if (Verbose) - printf("deinstalling %s\n", best_installed ? best_installed : lpp->lp_name); + printf("deinstalling %s\n", best_installed); /* delete the package */ if (Fake) @@ -333,12 +289,12 @@ require_delete(char *home, int tryall) NoDeleteFiles ? "-N" : "", CleanDirs ? "-d" : "", Fake ? "-n" : "", - best_installed ? best_installed : lpp->lp_name, NULL); + best_installed, NULL); /* check for delete failure */ if (rv && !tryall) { fail = 1; - warnx("had problem removing %s%s", best_installed?best_installed:lpp->lp_name, + warnx("had problem removing %s%s", best_installed, Force ? ", continuing" : ""); if (!Force) break; @@ -353,13 +309,6 @@ require_delete(char *home, int tryall) free_lpkg(lpp); } - /* return to the log dir */ - if (fchdir(oldcwd) == FAIL) { - warnx("unable to change to previous directory, deinstall failed"); - fail = 1; - } - close(oldcwd); - return (fail); } @@ -370,6 +319,7 @@ require_delete(char *home, int tryall) int require_find_recursive_up(lpkg_t *thislpp) { + char *fname; lpkg_head_t reqq; lpkg_t *lpp = NULL; FILE *cfile; @@ -383,25 +333,23 @@ require_find_recursive_up(lpkg_t *thislpp) TAILQ_INIT(&reqq); - (void) snprintf(pkgdir, sizeof(pkgdir), "%s/%s", - _pkgdb_getPKGDB_DIR(), thislpp->lp_name); - - /* change to package's dir */ - if (chdir(pkgdir) == FAIL) { - warnx("unable to change directory to %s! deinstall failed", pkgdir); - return (1); - } + fname = pkgdb_pkg_file(thislpp->lp_name, REQUIRED_BY_FNAME); /* terminate recursion if no required by's */ - if (isemptyfile(REQUIRED_BY_FNAME)) + if (isemptyfile(fname)) { + free(fname); return (0); + } /* get packages that directly require us */ - cfile = fopen(REQUIRED_BY_FNAME, "r"); + cfile = fopen(fname, "r"); if (!cfile) { - warnx("cannot open requirements file `%s'", REQUIRED_BY_FNAME); + warnx("cannot open requirements file `%s'", fname); + free(fname); return (1); } + free(fname); + while (fgets(linebuf, sizeof(linebuf), cfile)) { if ((nl = strrchr(linebuf, '\n'))) *nl = 0; @@ -488,45 +436,32 @@ require_find_recursive_down(lpkg_t *thislpp, package_t *plist) while ((lpp = TAILQ_FIRST(&reqq))) { FILE *cfile; package_t rPlist; + char *best_installed, *fname; /* remove a direct req from our queue */ TAILQ_REMOVE(&reqq, lpp, lp_link); /* prepare for recursion */ - chdir(_pkgdb_getPKGDB_DIR()); - if (ispkgpattern(lpp->lp_name)) { - char *best_installed; + best_installed = find_best_matching_installed_pkg(lpp->lp_name); - best_installed = find_best_matching_installed_pkg(lpp->lp_name); - - if (best_installed == NULL) { - warnx("cannot remove dependency for pkg-pattern %s", lpp->lp_name); - fail = 1; - goto fail; - } - if (chdir(best_installed) == -1) { - warnx("can't chdir to %s", best_installed); - free(best_installed); - fail = 1; - goto fail; - } - sanity_check(best_installed); - free(best_installed); - } else { - if (chdir(lpp->lp_name) == -1) { - warnx("cannot remove dependency from %s", lpp->lp_name); - fail = 1; - goto fail; - } - sanity_check(lpp->lp_name); + if (best_installed == NULL) { + warnx("cannot remove dependency for pkg-pattern %s", + lpp->lp_name); + fail = 1; + goto fail; } + sanity_check(best_installed); - cfile = fopen(CONTENTS_FNAME, "r"); + fname = pkgdb_pkg_file(best_installed, CONTENTS_FNAME); + free(best_installed); + cfile = fopen(fname, "r"); if (!cfile) { - warn("unable to open '%s' file", CONTENTS_FNAME); + warn("unable to open '%s' file", fname); + free(fname); fail = 1; goto fail; } + free(fname); read_plist(&rPlist, cfile); fclose(cfile); /* If we have a prefix, replace the first @cwd. */ @@ -612,11 +547,10 @@ require_print(void) static int pkg_do(char *pkg) { + char *pkgdir, *fname; plist_t *p; FILE *cfile; FILE *fp; - char home[MaxPathSize]; - char view[MaxPathSize]; int cc; Boolean is_depoted_pkg = FALSE; @@ -624,15 +558,16 @@ pkg_do(char *pkg) if (Plist.head) free_plist(&Plist); - (void) snprintf(LogDir, sizeof(LogDir), "%s/%s", - _pkgdb_getPKGDB_DIR(), pkg); - if (!fexists(LogDir) || !(isdir(LogDir) || islinktodir(LogDir))) { + pkgdir = xasprintf("%s/%s", _pkgdb_getPKGDB_DIR(), pkg); + if (!fexists(pkgdir) || !(isdir(pkgdir) || islinktodir(pkgdir))) { /* Check if the given package name matches something * with 'pkg-[0-9]*' */ lpkg_head_t trypkgs; lpkg_t *lpp; int qlen = 0; + free(pkgdir); + TAILQ_INIT(&trypkgs); switch (add_installed_pkgs_by_basename(pkg, &trypkgs)) { @@ -666,28 +601,31 @@ pkg_do(char *pkg) return 0; } + free(pkgdir); setenv(PKG_REFCOUNT_DBDIR_VNAME, pkgdb_refcount_dir(), 1); - if (!getcwd(home, MaxPathSize)) { - cleanup(0); - errx(2, "unable to get current working directory!"); - } - if (chdir(LogDir) == FAIL) { - warnx("unable to change directory to %s! deinstall failed", LogDir); - return 1; - } - if (!fexists(CONTENTS_FNAME)) { - warnx("package '%s' is not installed, %s missing", pkg, CONTENTS_FNAME); - if (!Force) + fname = pkgdb_pkg_file(pkg, CONTENTS_FNAME); + if (!fexists(fname)) { + warnx("package '%s' is not installed, %s missing", pkg, fname); + if (!Force) { + free(fname); return 1; + } } - if (fexists(PRESERVE_FNAME)) { + free(fname); + + fname = pkgdb_pkg_file(pkg, PRESERVE_FNAME); + if (fexists(fname)) { printf("Package `%s' is marked as not for deletion\n", pkg); if (Force <= (NoDeleteFiles ? 0 : 1)) { + free(fname); return 1; } printf("Deleting anyway\n"); } - if (!isemptyfile(REQUIRED_BY_FNAME)) { + free(fname); + + fname = pkgdb_pkg_file(pkg, REQUIRED_BY_FNAME); + if (!isemptyfile(fname)) { /* This package is required by others. Either nuke * them (-r), or stop. */ if (!Recurse_up) @@ -696,22 +634,31 @@ pkg_do(char *pkg) printf("Building list of packages that require `%s'" " to deinstall\n", pkg); if (require_find(pkg, FIND_UP)) { - if (!Force || Recurse_up) + if (!Force || Recurse_up) { + free(fname); return (1); + } } - chdir(LogDir); /* CWD was changed by require_find() */ if (!Recurse_up) { require_print(); - if (!Force) + if (!Force) { + free(fname); return 1; + } } else - require_delete(home, 0); + require_delete(0); } - if (!isemptyfile(VIEWS_FNAME)) { + free(fname); + + fname = pkgdb_pkg_file(pkg, VIEWS_FNAME); + if (!isemptyfile(fname)) { + char view[MaxPathSize]; + /* This package has instances in other views */ /* Delete them from the views */ - if ((fp = fopen(VIEWS_FNAME, "r")) == NULL) { - warnx("unable to open '%s' file", VIEWS_FNAME); + if ((fp = fopen(fname, "r")) == NULL) { + warnx("unable to open '%s' file", fname); + free(fname); return 1; } while (fgets(view, sizeof(view), fp) != NULL) { @@ -726,17 +673,23 @@ pkg_do(char *pkg) pkg, NULL) != 0) { warnx("unable to delete package %s from view %s", pkg, view); (void) fclose(fp); + free(fname); return 1; } } (void) fclose(fp); } - sanity_check(LogDir); - cfile = fopen(CONTENTS_FNAME, "r"); - if (!cfile) { - warnx("unable to open '%s' file", CONTENTS_FNAME); + free(fname); + + sanity_check(pkg); + fname = pkgdb_pkg_file(pkg, CONTENTS_FNAME); + if ((cfile = fopen(fname, "r")) == NULL) { + warnx("unable to open '%s' file", fname); + free(fname); return 1; } + free(fname); + read_plist(&Plist, cfile); fclose(cfile); p = find_plist(&Plist, PLIST_CWD); @@ -749,48 +702,60 @@ pkg_do(char *pkg) warnx("package '%s' doesn't have a prefix", pkg); return 1; } + if (Destdir != NULL) + setenv(PKG_DESTDIR_VNAME, Destdir, 1); setenv(PKG_PREFIX_VNAME, p->name, 1); setenv(PKG_METADATA_DIR_VNAME, LogDir, 1); /* * Ensure that we don't do VIEW-DEINSTALL action for old packages * or for the package in its depot directory. */ - if (!NoDeInstall && fexists(DEINSTALL_FNAME) && fexists(DEPOT_FNAME)) { + fname = pkgdb_pkg_file(pkg, DEINSTALL_FNAME); + if (!NoDeInstall && fexists(fname)) { + const char *target, *text; + char *fname2; + + fname2 = pkgdb_pkg_file(pkg, DEPOT_FNAME); + if (fexists(fname2)) { + target = "VIEW-DEINSTALL"; + text = "view deinstall"; + } else { + target = "DEINSTALL"; + text = "deinstall"; + } + free(fname2); + if (Fake) { - printf("Would execute view de-install script at this point (arg: VIEW-DEINSTALL).\n"); + printf("Would execute %s script at this point " + "(arg: %s).\n", text, target); } else { - (void) fexec(CHMOD_CMD, "+x", DEINSTALL_FNAME, NULL); /* make sure */ - if (fexec("./" DEINSTALL_FNAME, pkg, "VIEW-DEINSTALL", NULL)) { - warnx("view deinstall script returned error status"); + pkgdir = xasprintf("%s/%s", _pkgdb_getPKGDB_DIR(), pkg); + if (chmod(fname, 0555)) + warn("chmod of %s failed", fname); + if (fcexec(pkgdir, fname, pkg, target, NULL)) { + warnx("%s script returned error status", text); if (!Force) { + free(pkgdir); return 1; } } + free(pkgdir); } } - if (!NoDeInstall && fexists(DEINSTALL_FNAME) && !fexists(DEPOT_FNAME)) { - if (Fake) - printf("Would execute de-install script at this point (arg: DEINSTALL).\n"); - else { - (void) fexec(CHMOD_CMD, "+x", DEINSTALL_FNAME, NULL); /* make sure */ - if (fexec("./" DEINSTALL_FNAME, pkg, "DEINSTALL", NULL)) { - warnx("deinstall script returned error status"); - if (!Force) - return 1; - } - } - } + free(fname); + if (!Fake) { /* Some packages aren't packed right, so we need to just ignore delete_package()'s status. Ugh! :-( */ - if (delete_package(FALSE, CleanDirs, &Plist, NoDeleteFiles) == FAIL) + if (delete_package(FALSE, CleanDirs, &Plist, NoDeleteFiles, Destdir) == FAIL) warnx("couldn't entirely delete package `%s'\n", pkg); - } - else { /* Fake means Verbose */ + } else { /* Fake means Verbose */ printf("Attempting to delete package `%s'\n", pkg); } - if (!isemptyfile(DEPOT_FNAME)) { + fname = pkgdb_pkg_file(pkg, DEPOT_FNAME); + if (!isemptyfile(fname)) { if (Verbose) - printf("Attempting to remove the %s registration on package `%s'\n", VIEWS_FNAME, pkg); + printf("Attempting to remove the %s registration" + " on package `%s'\n", fname, pkg); if (!Fake) (void) unview(pkg); } @@ -798,7 +763,7 @@ pkg_do(char *pkg) * If this isn't a package in a view, then remove this package * from the +REQUIRED_BY list of the packages this depends on. */ - if (!fexists(DEPOT_FNAME)) { + if (!fexists(fname)) { for (p = Plist.head; p; p = p->next) { if (p->type != PLIST_PKGDEP) continue; @@ -808,6 +773,7 @@ pkg_do(char *pkg) match_installed_pkgs(p->name, undepend, pkg); } } + free(fname); if (Recurse_down) { /* Also remove the packages further down, now that there's * (most likely) nothing left which requires them. */ @@ -816,46 +782,68 @@ pkg_do(char *pkg) if (require_find(pkg, FIND_DOWN)) return (1); - require_delete(home, 1); - } - if (!NoDeInstall && fexists(DEINSTALL_FNAME) && !fexists(DEPOT_FNAME)) { - if (Fake) - printf("Would execute post-de-install script at this point (arg: POST-DEINSTALL).\n"); - else { - (void) fexec(CHMOD_CMD, "+x", DEINSTALL_FNAME, NULL); /* make sure */ - if (fexec("./" DEINSTALL_FNAME, pkg, "POST-DEINSTALL", NULL)) { - warnx("post-deinstall script returned error status"); - if (!Force) - return 1; + require_delete(1); + } + + fname = pkgdb_pkg_file(pkg, DEINSTALL_FNAME); + if (!NoDeInstall && fexists(fname)) { + char *fname2; + + fname2 = pkgdb_pkg_file(pkg, DEPOT_FNAME); + if (!fexists(fname2)) { + if (Fake) + printf("Would execute post-de-install script at this point (arg: POST-DEINSTALL).\n"); + else { + pkgdir = xasprintf("%s/%s", _pkgdb_getPKGDB_DIR(), pkg); + if (chmod(fname, 0555)) + warn("chmod of %s failed", fname); + if (fcexec(pkgdir, fname, pkg, "POST-DEINSTALL", NULL)) { + warnx("post-deinstall script returned error status"); + if (!Force) { + free(pkgdir); + free(fname); + free(fname2); + return 1; + } + } + free(pkgdir); } } + free(fname2); } - if (fexists(VIEWS_FNAME)) + free(fname); + + fname = pkgdb_pkg_file(pkg, VIEWS_FNAME); + if (fexists(fname)) is_depoted_pkg = TRUE; + free(fname); /* Change out of LogDir before we remove it. * Do not fail here, as the package is not yet completely deleted! */ - if (chdir(home) == FAIL) - warnx("Oops - removed current working directory. Oh, well."); if (!Fake) { /* Finally nuke the +-files and the pkgdb-dir (/var/db/pkg/foo) */ - (void) remove_files(LogDir, "+*"); - if (isemptydir(LogDir)) - (void)rmdir(LogDir); + pkgdir = xasprintf("%s/%s", _pkgdb_getPKGDB_DIR(), pkg); + (void) remove_files(pkgdir, "+*"); + if (isemptydir(pkgdir)) + (void)rmdir(pkgdir); else if (is_depoted_pkg) - warnx("%s is not empty", LogDir); + warnx("%s is not empty", pkgdir); else if (Force) { - if (fexec(REMOVE_CMD, "-rf", LogDir, NULL) != 0) { - warnx("couldn't remove log entry in %s", LogDir); + if (recursive_remove(pkgdir, 1)) { + warn("Couldn't remove log entry in %s", pkgdir); + free(pkgdir); return 1; } else { - warnx("log entry forcefully removed in %s", LogDir); + warnx("log entry forcefully removed in %s", pkgdir); + free(pkgdir); return 0; } } else { - warnx("couldn't remove log entry in %s", LogDir); + warnx("couldn't remove log entry in %s", pkgdir); + free(pkgdir); return 1; } + free(pkgdir); } return 0; } diff --git a/pkgtools/pkg_install/files/delete/pkg_delete.1 b/pkgtools/pkg_install/files/delete/pkg_delete.1 index b3e0698edf0..27051ebebd4 100644 --- a/pkgtools/pkg_install/files/delete/pkg_delete.1 +++ b/pkgtools/pkg_install/files/delete/pkg_delete.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: pkg_delete.1,v 1.16 2007/08/10 22:29:49 gdt Exp $ +.\" $NetBSD: pkg_delete.1,v 1.17 2009/02/02 12:35:01 joerg Exp $ .\" .\" FreeBSD install - a package for the installation and maintenance .\" of non-core utilities. @@ -17,7 +17,7 @@ .\" .\" from FreeBSD: @(#)pkg_delete.1 .\" -.Dd March 2, 2007 +.Dd July 30, 2008 .Dt PKG_DELETE 1 .Os .Sh NAME @@ -30,6 +30,7 @@ .Op Fl K Ar pkg_dbdir .Ek .Bk -words +.Op Fl P Ar destdir .Op Fl p Ar prefix .Ek .Ar pkg-name ... @@ -133,6 +134,11 @@ would be taken if it were. .It Fl O Only delete the package's entries from the package database, do not touch the package or its files itself. +.It Fl p Ar destdir +Prefix all file and directory names with +.Ar destdir . +For packages without install scripts this has the same behavior as +using chroot. .It Fl p Ar prefix Set .Ar prefix @@ -256,6 +262,13 @@ meta-data files, and with the .Ev PKG_REFCOUNT_DBDIR environment variable set to the location of the package reference counts database directory. +If the +.Fl P +flag was given to +.Nm , +.Ev PKG_DESTDIR +will be set to +.Ar destdir . .Sh ENVIRONMENT .Bl -tag -width PKG_DBDIR .It Ev PKG_DBDIR diff --git a/pkgtools/pkg_install/files/delete/pkg_delete.cat1 b/pkgtools/pkg_install/files/delete/pkg_delete.cat1 index 91c2c00298f..309432c83fc 100644 --- a/pkgtools/pkg_install/files/delete/pkg_delete.cat1 +++ b/pkgtools/pkg_install/files/delete/pkg_delete.cat1 @@ -5,7 +5,8 @@ NNAAMMEE age distributions SSYYNNOOPPSSIISS - ppkkgg__ddeelleettee [--DDddFFffNNnnOORRrrVVvv] [--KK _p_k_g___d_b_d_i_r] [--pp _p_r_e_f_i_x] _p_k_g_-_n_a_m_e _._._. + ppkkgg__ddeelleettee [--DDddFFffNNnnOORRrrVVvv] [--KK _p_k_g___d_b_d_i_r] [--PP _d_e_s_t_d_i_r] [--pp _p_r_e_f_i_x] + _p_k_g_-_n_a_m_e _._._. DDEESSCCRRIIPPTTIIOONN The ppkkgg__ddeelleettee command is used to delete packages that have been previ- @@ -72,6 +73,11 @@ OOPPTTIIOONNSS --OO Only delete the package's entries from the package database, do not touch the package or its files itself. + --pp _d_e_s_t_d_i_r + Prefix all file and directory names with _d_e_s_t_d_i_r. For packages + without install scripts this has the same behavior as using + chroot. + --pp _p_r_e_f_i_x Set _p_r_e_f_i_x as the directory in which to delete files from any installed packages which do not explicitly set theirs. For most @@ -136,7 +142,8 @@ TTEECCHHNNIICCAALL DDEETTAAIILLSS The scripts are also called with the PKG_METADATA_DIR environment vari- able set to the location of the _+_* meta-data files, and with the PKG_REFCOUNT_DBDIR environment variable set to the location of the pack- - age reference counts database directory. + age reference counts database directory. If the --PP flag was given to + ppkkgg__ddeelleettee, PKG_DESTDIR will be set to _d_e_s_t_d_i_r. EENNVVIIRROONNMMEENNTT PKG_DBDIR If the --KK flag isn't given, then PKG_DBDIR is the location of @@ -162,4 +169,4 @@ AAUUTTHHOORRSS NetBSD wildcard dependency processing, pkgdb, recursive "down" delete, etc. -NetBSD 4.0 March 2, 2007 NetBSD 4.0 +NetBSD 4.0 July 30, 2008 NetBSD 4.0 diff --git a/pkgtools/pkg_install/files/info/Makefile.in b/pkgtools/pkg_install/files/info/Makefile.in index 967ead0f550..e2f1d4a4733 100644 --- a/pkgtools/pkg_install/files/info/Makefile.in +++ b/pkgtools/pkg_install/files/info/Makefile.in @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.in,v 1.16 2008/04/26 17:40:01 joerg Exp $ +# $NetBSD: Makefile.in,v 1.17 2009/02/02 12:35:01 joerg Exp $ srcdir= @srcdir@ @@ -16,7 +16,7 @@ BOOTSTRAP= @bootstrap@ CC= @CC@ CCLD= $(CC) .if empty(BOOTSTRAP) -LIBS= -linstall -larchive -lbz2 -lfetch -lz @LIBS@ +LIBS= -linstall -larchive -lfetch -lbz2 -lz @LIBS@ CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -I../lib .else LIBS= -linstall @LIBS@ diff --git a/pkgtools/pkg_install/files/info/main.c b/pkgtools/pkg_install/files/info/main.c index b6a17261a13..88376fa2b54 100644 --- a/pkgtools/pkg_install/files/info/main.c +++ b/pkgtools/pkg_install/files/info/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.22 2007/11/05 09:39:38 joerg Exp $ */ +/* $NetBSD: main.c,v 1.23 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,13 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -#if 0 -static char *rcsid = "from FreeBSD Id: main.c,v 1.14 1997/10/08 07:47:26 charnier Exp"; -#else -__RCSID("$NetBSD: main.c,v 1.22 2007/11/05 09:39:38 joerg Exp $"); -#endif -#endif +__RCSID("$NetBSD: main.c,v 1.23 2009/02/02 12:35:01 joerg Exp $"); /* * @@ -271,11 +265,9 @@ main(int argc, char **argv) s = pkgdb_retrieve(CheckPkg); - if (s) { - CheckPkg = strdup(s); - } else { + if (s == NULL) errx(EXIT_FAILURE, "No matching pkg for %s.", CheckPkg); - } + CheckPkg = xstrdup(s); pkgdb_close(); } diff --git a/pkgtools/pkg_install/files/info/perform.c b/pkgtools/pkg_install/files/info/perform.c index cdf4b563f6b..a64c3f807b3 100644 --- a/pkgtools/pkg_install/files/info/perform.c +++ b/pkgtools/pkg_install/files/info/perform.c @@ -1,4 +1,4 @@ -/* $NetBSD: perform.c,v 1.48 2008/04/26 17:40:01 joerg Exp $ */ +/* $NetBSD: perform.c,v 1.49 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -13,13 +13,7 @@ #if HAVE_SYS_WAIT_H #include <sys/wait.h> #endif -#ifndef lint -#if 0 -static const char *rcsid = "from FreeBSD Id: perform.c,v 1.23 1997/10/13 15:03:53 jkh Exp"; -#else -__RCSID("$NetBSD: perform.c,v 1.48 2008/04/26 17:40:01 joerg Exp $"); -#endif -#endif +__RCSID("$NetBSD: perform.c,v 1.49 2009/02/02 12:35:01 joerg Exp $"); /*- * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. @@ -126,7 +120,7 @@ static const struct pkg_meta_desc { int entry_mask; int required_file; } pkg_meta_descriptors[] = { - { offsetof(struct pkg_meta, meta_contents), CONTENTS_FNAME , + { offsetof(struct pkg_meta, meta_contents), CONTENTS_FNAME, LOAD_CONTENTS, 1}, { offsetof(struct pkg_meta, meta_comment), COMMENT_FNAME, LOAD_COMMENT, 1 }, @@ -174,10 +168,10 @@ free_pkg_meta(struct pkg_meta *meta) #ifndef BOOTSTRAP static struct pkg_meta * -read_meta_data_from_archive(struct archive *archive) +read_meta_data_from_archive(struct archive *archive, + struct archive_entry *entry) { struct pkg_meta *meta; - struct archive_entry *entry; const char *fname; const struct pkg_meta_desc *descr, *last_descr; char **target; @@ -186,13 +180,14 @@ read_meta_data_from_archive(struct archive *archive) found_required = 0; - if ((meta = malloc(sizeof(*meta))) == NULL) - err(2, "cannot allocate meta data header"); - - memset(meta, 0, sizeof(*meta)); + meta = xcalloc(1, sizeof(*meta)); last_descr = 0; + if (entry != NULL) + goto has_entry; + while ((r = archive_read_next_header(archive, &entry)) == ARCHIVE_OK) { +has_entry: fname = archive_entry_pathname(entry); for (descr = pkg_meta_descriptors; descr->entry_filename; @@ -223,8 +218,7 @@ read_meta_data_from_archive(struct archive *archive) size = archive_entry_size(entry); if (size > SSIZE_MAX - 1) errx(2, "package meta data too large to process"); - if ((*target = malloc(size + 1)) == NULL) - err(2, "cannot allocate meta data"); + *target = xmalloc(size + 1); if (archive_read_data(archive, *target, size) != size) errx(2, "cannot read package meta data"); (*target)[size] = '\0'; @@ -236,7 +230,7 @@ read_meta_data_from_archive(struct archive *archive) } if (found_required != 0) { free_pkg_meta(meta); - return NULL; + meta = NULL; } archive_read_finish(archive); @@ -255,10 +249,7 @@ read_meta_data_from_pkgdb(const char *pkg) int fd; struct stat st; - if ((meta = malloc(sizeof(*meta))) == NULL) - err(2, "cannot allocate meta data header"); - - memset(meta, 0, sizeof(*meta)); + meta = xcalloc(1, sizeof(*meta)); for (descr = pkg_meta_descriptors; descr->entry_filename; ++descr) { if ((descr->entry_mask & desired_meta_data) == 0) @@ -281,8 +272,7 @@ read_meta_data_from_pkgdb(const char *pkg) errx(1, "meta data is not regular file"); if (st.st_size > SSIZE_MAX - 1) err(2, "meta data file too large to process"); - if ((*target = malloc(st.st_size + 1)) == NULL) - err(2, "cannot allocate meta data"); + *target = xmalloc(st.st_size + 1); if (read(fd, *target, st.st_size) != st.st_size) err(2, "cannot read meta data"); (*target)[st.st_size] = '\0'; @@ -302,30 +292,38 @@ pkg_do(const char *pkg) int code = 0; const char *binpkgfile = NULL; - if (IS_URL(pkg)) { -#ifdef BOOTSTRAP - errx(2, "Remote access not supported during bootstrap"); -#else - struct archive *archive; - void *remote_archive_cookie; - - archive = open_remote_archive(pkg, &remote_archive_cookie); - - meta = read_meta_data_from_archive(archive); - close_remote_archive(remote_archive_cookie); -#endif - } else if (fexists(pkg) && isfile(pkg)) { + if (IS_URL(pkg) || (fexists(pkg) && isfile(pkg))) { #ifdef BOOTSTRAP errx(2, "Binary packages not supported during bootstrap"); #else struct archive *archive; - void *remote_archive_cookie; - - archive = open_local_archive(pkg, &remote_archive_cookie); - - meta = read_meta_data_from_archive(archive); - close_local_archive(remote_archive_cookie); - binpkgfile = pkg; + void *archive_cookie; +# ifdef HAVE_SSL + void *signature_cookie; +# endif + struct archive_entry *entry; + char *pkgname; + + archive = open_archive(pkg, &archive_cookie); + if (archive == NULL) { + warnx("can't find package `%s', skipped", pkg); + return -1; + } + pkgname = NULL; + entry = NULL; +# ifdef HAVE_SSL + pkg_verify_signature(&archive, &entry, &pkgname, + &signature_cookie); +# endif + free(pkgname); + + meta = read_meta_data_from_archive(archive, entry); + close_archive(archive_cookie); +# ifdef HAVE_SSL + pkg_free_signature(signature_cookie); +# endif + if (!IS_URL(pkg)) + binpkgfile = pkg; #endif } else { /* @@ -373,7 +371,6 @@ pkg_do(const char *pkg) package_t plist; /* Read the contents list */ - plist.head = plist.tail = NULL; parse_plist(&plist, meta->meta_contents); /* Start showing the package contents */ @@ -500,8 +497,7 @@ CheckForPkg(const char *pkgname) if (arg.got_match == 0 && !ispkgpattern(pkgname)) { char *pattern; - if (asprintf(&pattern, "%s-[0-9]*", pkgname) == -1) - errx(EXIT_FAILURE, "asprintf failed"); + pattern = xasprintf("%s-[0-9]*", pkgname); arg.pattern = pattern; arg.got_match = 0; @@ -536,9 +532,7 @@ CheckForBestPkg(const char *pkgname) if (ispkgpattern(pkgname)) return 1; - if (asprintf(&pattern, "%s-[0-9]*", pkgname) == -1) - errx(EXIT_FAILURE, "asprintf failed"); - + pattern = xasprintf("%s-[0-9]*", pkgname); best_match = find_best_matching_installed_pkg(pattern); free(pattern); } diff --git a/pkgtools/pkg_install/files/info/show.c b/pkgtools/pkg_install/files/info/show.c index c2591554edd..b95cee60b1b 100644 --- a/pkgtools/pkg_install/files/info/show.c +++ b/pkgtools/pkg_install/files/info/show.c @@ -1,4 +1,4 @@ -/* $NetBSD: show.c,v 1.22 2008/04/29 05:46:08 martin Exp $ */ +/* $NetBSD: show.c,v 1.23 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,13 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -#if 0 -static const char *rcsid = "from FreeBSD Id: show.c,v 1.11 1997/10/08 07:47:38 charnier Exp"; -#else -__RCSID("$NetBSD: show.c,v 1.22 2008/04/29 05:46:08 martin Exp $"); -#endif -#endif +__RCSID("$NetBSD: show.c,v 1.23 2009/02/02 12:35:01 joerg Exp $"); /* * FreeBSD install - a package for the installation and maintainance diff --git a/pkgtools/pkg_install/files/lib/Makefile.in b/pkgtools/pkg_install/files/lib/Makefile.in index e513a89a7d4..3e361d51df9 100644 --- a/pkgtools/pkg_install/files/lib/Makefile.in +++ b/pkgtools/pkg_install/files/lib/Makefile.in @@ -1,26 +1,25 @@ -# $NetBSD: Makefile.in,v 1.23 2008/04/26 17:40:01 joerg Exp $ +# $NetBSD: Makefile.in,v 1.24 2009/02/02 12:35:01 joerg Exp $ srcdir= @srcdir@ pkgdbdir= @pkgdbdir@ mandir= @mandir@ datarootdir= @datarootdir@ +sysconfdir= @sysconfdir@ cat5dir= $(mandir)/cat5 cat7dir= $(mandir)/cat7 man5dir= $(mandir)/man5 man7dir= $(mandir)/man7 -tar= @tar@ -ftp= @ftp@ - BOOTSTRAP= @bootstrap@ +SSL_SUPPORT= @ssl_support@ RANLIB= @RANLIB@ AR= @AR@ CC= @CC@ CPPFLAGS= @CPPFLAGS@ -I. -I$(srcdir) -DEFS= @DEFS@ -DDEF_LOG_DIR=\"$(pkgdbdir)\" -DTAR_CMD=\"$(tar)\" -DFTP_CMD=\"$(ftp)\" +DEFS= @DEFS@ -DDEF_LOG_DIR=\"$(pkgdbdir)\" CFLAGS= @CFLAGS@ INSTALL= @INSTALL@ @@ -28,9 +27,11 @@ INSTALL= @INSTALL@ LIB= libinstall.a OBJS= automatic.o conflicts.o decompress.o dewey.o fexec.o file.o \ - ftpio.o global.o iterate.o lpkg.o opattern.o \ - path.o pen.o pexec.o pkgdb.o plist.o \ - str.o var.o version.o vulnerabilities-file.o + gpgsig.o global.o iterate.o lpkg.o opattern.o \ + parse-config.o path.o pkgdb.o plist.o remove.o \ + str.o var.o version.o vulnerabilities-file.o xwrapper.o + +CPPFLAGS+= -DSYSCONFDIR=\"$(sysconfdir)\" .if !empty(BOOTSTRAP) CPPFLAGS+= -DBOOTSTRAP @@ -38,6 +39,11 @@ CPPFLAGS+= -DBOOTSTRAP OBJS+= pkg_io.o .endif +.if !empty(SSL_SUPPORT) +CPPFLAGS+= -DHAVE_SSL +OBJS+= pkg_signature.o pkcs7.o +.endif + all: $(LIB) .c.o: @@ -57,5 +63,7 @@ install: $(INSTALL) -m 755 -d ${DESTDIR}$(cat7dir) $(INSTALL) -m 444 pkg_summary.5 ${DESTDIR}$(man5dir)/pkg_summary.5 $(INSTALL) -m 444 pkg_summary.cat5 ${DESTDIR}$(cat5dir)/pkg_summary.0 + $(INSTALL) -m 444 pkg_install.conf.5 ${DESTDIR}$(man5dir)/pkg_install.conf.5 + $(INSTALL) -m 444 pkg_install.conf.cat5 ${DESTDIR}$(cat5dir)/pkg_install.conf.0 $(INSTALL) -m 444 pkgsrc.7 ${DESTDIR}$(man7dir)/pkgsrc.7 $(INSTALL) -m 444 pkgsrc.cat7 ${DESTDIR}$(cat7dir)/pkgsrc.0 diff --git a/pkgtools/pkg_install/files/lib/automatic.c b/pkgtools/pkg_install/files/lib/automatic.c index 865f9ecdd43..3d991dd3333 100644 --- a/pkgtools/pkg_install/files/lib/automatic.c +++ b/pkgtools/pkg_install/files/lib/automatic.c @@ -1,4 +1,4 @@ -/* $NetBSD: automatic.c,v 1.4 2007/08/15 02:08:40 joerg Exp $ */ +/* $NetBSD: automatic.c,v 1.5 2009/02/02 12:35:01 joerg Exp $ */ /*- * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -39,9 +39,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -__RCSID("$NetBSD: automatic.c,v 1.4 2007/08/15 02:08:40 joerg Exp $"); -#endif +__RCSID("$NetBSD: automatic.c,v 1.5 2009/02/02 12:35:01 joerg Exp $"); #if HAVE_ASSERT_H #include <assert.h> diff --git a/pkgtools/pkg_install/files/lib/config.h.in b/pkgtools/pkg_install/files/lib/config.h.in index 3a32b2fda26..7ee4d522d24 100644 --- a/pkgtools/pkg_install/files/lib/config.h.in +++ b/pkgtools/pkg_install/files/lib/config.h.in @@ -36,9 +36,6 @@ /* Define to 1 if you have the <fnmatch.h> header file. */ #undef HAVE_FNMATCH_H -/* Define to 1 if you have the `getrlimit' function. */ -#undef HAVE_GETRLIMIT - /* Define to 1 if you have the <glob.h> header file. */ #undef HAVE_GLOB_H @@ -66,9 +63,6 @@ /* Define to 1 if you have the <regex.h> header file. */ #undef HAVE_REGEX_H -/* Define to 1 if you have the `setrlimit' function. */ -#undef HAVE_SETRLIMIT - /* Define to 1 if you have the <signal.h> header file. */ #undef HAVE_SIGNAL_H diff --git a/pkgtools/pkg_install/files/lib/conflicts.c b/pkgtools/pkg_install/files/lib/conflicts.c index 0be50f3b1cc..f77679ae473 100644 --- a/pkgtools/pkg_install/files/lib/conflicts.c +++ b/pkgtools/pkg_install/files/lib/conflicts.c @@ -1,3 +1,34 @@ +/* $NetBSD: conflicts.c,v 1.8 2009/02/02 12:35:01 joerg Exp $ */ + +/*- + * Copyright (c) 2007 Roland Illig <rillig@NetBSD.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + /* * XXX: Reading the +CONTENTS files of all installed packages is * rather slow. Since this check is necessary to avoid conflicting @@ -13,6 +44,12 @@ #include <nbcompat.h> +#if HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> +#endif + +__RCSID("$NetBSD: conflicts.c,v 1.8 2009/02/02 12:35:01 joerg Exp $"); + #if HAVE_ERR_H #include <err.h> #endif @@ -30,21 +67,11 @@ */ struct package_conflict { const char *pkgname; + const char *skip_pkgname; char **conflicting_pkgname; char **conflicting_pattern; }; -static void * -nonnull(void *p) -{ - - if (p == NULL) { - err(EXIT_FAILURE, "NullPointerException"); - /* NOTREACHED */ - } - return p; -} - static FILE * fopen_contents(const char *pkgname, const char *mode) { @@ -70,6 +97,10 @@ check_package_conflict(const char *pkgname, void *v) FILE *f; int rv; + if (conflict->skip_pkgname != NULL && + strcmp(conflict->skip_pkgname, pkgname) == 0) + return 0; + rv = 0; f = fopen_contents(pkgname, "r"); @@ -81,8 +112,8 @@ check_package_conflict(const char *pkgname, void *v) continue; if (pkg_match(p->name, conflict->pkgname) == 1) { - *(conflict->conflicting_pkgname) = nonnull(strdup(pkgname)); - *(conflict->conflicting_pattern) = nonnull(strdup(p->name)); + *(conflict->conflicting_pkgname) = xstrdup(pkgname); + *(conflict->conflicting_pattern) = xstrdup(p->name); rv = 1 /* nonzero, stop iterating */; break; } @@ -100,12 +131,14 @@ check_package_conflict(const char *pkgname, void *v) * variables are set to NULL. */ int -some_installed_package_conflicts_with(const char *pkgname, char **inst_pkgname, char **inst_pattern) +some_installed_package_conflicts_with(const char *pkgname, + const char *skip_pkgname, char **inst_pkgname, char **inst_pattern) { struct package_conflict cfl; int rv; cfl.pkgname = pkgname; + cfl.skip_pkgname = skip_pkgname; *inst_pkgname = NULL; *inst_pattern = NULL; cfl.conflicting_pkgname = inst_pkgname; diff --git a/pkgtools/pkg_install/files/lib/decompress.c b/pkgtools/pkg_install/files/lib/decompress.c index 79448def1d2..820f988691a 100644 --- a/pkgtools/pkg_install/files/lib/decompress.c +++ b/pkgtools/pkg_install/files/lib/decompress.c @@ -1,3 +1,5 @@ +/* $NetBSD: decompress.c,v 1.2 2009/02/02 12:35:01 joerg Exp $ */ + /*- * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. * All rights reserved. @@ -37,7 +39,7 @@ #include <sys/cdefs.h> #endif -__RCSID("$NetBSD: decompress.c,v 1.1 2008/02/19 15:16:24 joerg Exp $"); +__RCSID("$NetBSD: decompress.c,v 1.2 2009/02/02 12:35:01 joerg Exp $"); #ifdef BOOTSTRAP #include "lib.h" @@ -71,8 +73,7 @@ decompress_bzip2(const char *in, size_t in_len, char **out, size_t *out_len) *out_len = in_len * 10; else *out_len = in_len; - if ((*out = malloc(*out_len + 1)) == NULL) - err(EXIT_FAILURE, "malloc failed"); + *out = xmalloc(*out_len + 1); stream.next_in = (char *)in; stream.avail_in = in_len; @@ -92,9 +93,7 @@ decompress_bzip2(const char *in, size_t in_len, char **out, size_t *out_len) if (BZ2_bzDecompressEnd(&stream) != Z_OK) errx(EXIT_FAILURE, "inflateEnd failed"); output_produced = *out_len - stream.avail_out; - *out = realloc(*out, output_produced + 1); - if (*out == NULL) - err(EXIT_FAILURE, "realloc failed"); + *out = xrealloc(*out, output_produced + 1); *out_len = output_produced; (*out)[*out_len] = '\0'; return; @@ -104,7 +103,7 @@ decompress_bzip2(const char *in, size_t in_len, char **out, size_t *out_len) *out_len *= 2; else errx(EXIT_FAILURE, "input too large"); - *out = realloc(*out, *out_len + 1); + *out = xrealloc(*out, *out_len + 1); stream.next_out = *out + output_produced; stream.avail_out = *out_len - output_produced; break; @@ -124,8 +123,7 @@ decompress_zlib(const char *in, size_t in_len, char **out, size_t *out_len) *out_len = in_len * 10; else *out_len = in_len; - if ((*out = malloc(*out_len + 1)) == NULL) - err(EXIT_FAILURE, "malloc failed"); + *out = xmalloc(*out_len + 1); stream.next_in = (unsigned char *)in; stream.avail_in = in_len; @@ -145,9 +143,7 @@ decompress_zlib(const char *in, size_t in_len, char **out, size_t *out_len) if (inflateEnd(&stream) != Z_OK) errx(EXIT_FAILURE, "inflateEnd failed"); output_produced = *out_len - stream.avail_out; - *out = realloc(*out, output_produced + 1); - if (*out == NULL) - err(EXIT_FAILURE, "realloc failed"); + *out = xrealloc(*out, output_produced + 1); *out_len = output_produced; (*out)[*out_len] = '\0'; return; @@ -159,7 +155,7 @@ decompress_zlib(const char *in, size_t in_len, char **out, size_t *out_len) errx(EXIT_FAILURE, "input too large"); else *out_len = SSIZE_MAX - 1; - *out = realloc(*out, *out_len + 1); + *out = xrealloc(*out, *out_len + 1); stream.next_out = (unsigned char *)*out + output_produced; stream.avail_out = *out_len - output_produced; break; diff --git a/pkgtools/pkg_install/files/lib/dewey.c b/pkgtools/pkg_install/files/lib/dewey.c index a133b414535..98240c7221d 100644 --- a/pkgtools/pkg_install/files/lib/dewey.c +++ b/pkgtools/pkg_install/files/lib/dewey.c @@ -1,4 +1,4 @@ -/* $NetBSD: dewey.c,v 1.9 2008/12/14 10:18:16 rillig Exp $ */ +/* $NetBSD: dewey.c,v 1.10 2009/02/02 12:35:01 joerg Exp $ */ /* * Copyright © 2002 Alistair G. Crooks. All rights reserved. diff --git a/pkgtools/pkg_install/files/lib/fexec.c b/pkgtools/pkg_install/files/lib/fexec.c index 8e0f31426d2..5789bd4933c 100644 --- a/pkgtools/pkg_install/files/lib/fexec.c +++ b/pkgtools/pkg_install/files/lib/fexec.c @@ -1,3 +1,5 @@ +/* $NetBSD: fexec.c,v 1.11 2009/02/02 12:35:01 joerg Exp $ */ + /*- * Copyright (c) 2003 The NetBSD Foundation, Inc. * All rights reserved. @@ -57,9 +59,7 @@ #include "lib.h" -#ifndef lint -__RCSID("$NetBSD: fexec.c,v 1.10 2008/04/29 05:46:08 martin Exp $"); -#endif +__RCSID("$NetBSD: fexec.c,v 1.11 2009/02/02 12:35:01 joerg Exp $"); static int vfcexec(const char *, int, const char *, va_list); @@ -106,8 +106,7 @@ vfcexec(const char *path, int skipempty, const char *arg, va_list ap) int retval; argv_size = 16; - if ((argv = malloc(argv_size * sizeof(*argv))) == NULL) - err(EXIT_FAILURE, "vfcexec: malloc failed"); + argv = xcalloc(argv_size, sizeof(*argv)); argv[0] = arg; argc = 1; @@ -115,9 +114,7 @@ vfcexec(const char *path, int skipempty, const char *arg, va_list ap) do { if (argc == argv_size) { argv_size *= 2; - argv = realloc(argv, argv_size * sizeof(*argv)); - if (argv == NULL) - err(EXIT_FAILURE, "vfcexec: realloc failed"); + argv = xrealloc(argv, argv_size * sizeof(*argv)); } arg = va_arg(ap, const char *); if (skipempty && arg && strlen(arg) == 0) diff --git a/pkgtools/pkg_install/files/lib/file.c b/pkgtools/pkg_install/files/lib/file.c index 47146a31cac..5ee81b935a4 100644 --- a/pkgtools/pkg_install/files/lib/file.c +++ b/pkgtools/pkg_install/files/lib/file.c @@ -1,4 +1,4 @@ -/* $NetBSD: file.c,v 1.25 2008/04/26 17:40:01 joerg Exp $ */ +/* $NetBSD: file.c,v 1.26 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -13,13 +13,7 @@ #if HAVE_SYS_QUEUE_H #include <sys/queue.h> #endif -#ifndef lint -#if 0 -static const char *rcsid = "from FreeBSD Id: file.c,v 1.29 1997/10/08 07:47:54 charnier Exp"; -#else -__RCSID("$NetBSD: file.c,v 1.25 2008/04/26 17:40:01 joerg Exp $"); -#endif -#endif +__RCSID("$NetBSD: file.c,v 1.26 2009/02/02 12:35:01 joerg Exp $"); /* * FreeBSD install - a package for the installation and maintainance @@ -190,6 +184,7 @@ typedef struct url_t { /* A table of valid leading strings for URLs */ static const url_t urls[] = { + {"file://", 7}, {"ftp://", 6}, {"http://", 7}, {NULL} @@ -218,263 +213,6 @@ URLlength(const char *fname) } /* - * Returns the host part of a URL - */ -const char * -fileURLHost(const char *fname, char *where, int max) -{ - const char *ret; - int i; - - assert(where != NULL); - assert(max > 0); - - if ((i = URLlength(fname)) < 0) { /* invalid URL? */ - errx(EXIT_FAILURE, "fileURLhost called with a bad URL: `%s'", fname); - } - fname += i; - /* Do we have a place to stick our work? */ - ret = where; - while (*fname && *fname != '/' && --max) - *where++ = *fname++; - *where = '\0'; - - return ret; -} - -/* - * Returns the filename part of a URL - */ -const char * -fileURLFilename(const char *fname, char *where, int max) -{ - const char *ret; - int i; - - assert(where != NULL); - assert(max > 0); - - if ((i = URLlength(fname)) < 0) { /* invalid URL? */ - errx(EXIT_FAILURE, "fileURLFilename called with a bad URL: `%s'", fname); - } - fname += i; - /* Do we have a place to stick our work? */ - ret = where; - while (*fname && *fname != '/') - ++fname; - if (*fname == '/') { - while (*fname && --max) - *where++ = *fname++; - } - *where = '\0'; - - return ret; -} - -/* - * Try and fetch a file by URL, returning the directory name for where - * it's unpacked, if successful. To be handed to leave_playpen() later. - */ -char * -fileGetURL(const char *spec) -{ - char host[MAXHOSTNAMELEN], file[MaxPathSize]; - const char *cp; - char *rp; - char pen[MaxPathSize]; - int rc; - - rp = NULL; - if (!IS_URL(spec)) { - errx(EXIT_FAILURE, "fileGetURL was called with non-URL arg '%s'", spec); - } - - /* Some sanity checks on the URL */ - cp = fileURLHost(spec, host, MAXHOSTNAMELEN); - if (!*cp) { - warnx("URL `%s' has bad host part!", spec); - return NULL; - } - cp = fileURLFilename(spec, file, MaxPathSize); - if (!*cp) { - warnx("URL `%s' has bad filename part!", spec); - return NULL; - } - - if (Verbose) - printf("Trying to fetch %s.\n", spec); - - pen[0] = '\0'; - rp = make_playpen(pen, sizeof(pen), 0); - if (rp == NULL) { - printf("Error: Unable to construct a new playpen for FTP!\n"); - return NULL; - } - - rp = strdup(pen); - rc = unpackURL(spec, pen); - if (rc < 0) { - leave_playpen(rp); /* Don't leave dir hang around! */ - - printf("Error on unpackURL('%s', '%s')\n", spec, pen); - return NULL; - } - return rp; -} - -static char * -resolvepattern1(const char *name) -{ - static char tmp[MaxPathSize]; - char *cp; - - if (IS_URL(name)) { - /* some package depends on a wildcard pkg */ - int rc; - - rc = expandURL(tmp, name); - if (rc < 0) { - return NULL; - } - if (Verbose) - printf("'%s' expanded to '%s'\n", name, tmp); - return tmp; /* return expanded URL w/ corrent pkg */ - } - else if (ispkgpattern(name)) { - cp = find_best_matching_file(dirname_of(name), basename_of(name), 1, 0); - if (cp) { - snprintf(tmp, sizeof(tmp), "%s/%s", dirname_of(name), cp); - free(cp); - return tmp; - } - } else { - if (isfile(name)) { - strlcpy(tmp, name, sizeof(tmp)); - return tmp; - } - } - - return NULL; -} - -static char * -resolvepattern(const char *name) -{ - char tmp[MaxPathSize]; - char *cp; - const char *suf; - - cp = resolvepattern1(name); - if (cp != NULL) - return cp; - - if (ispkgpattern(name)) - return NULL; - - suf = suffix_of(name); - if (!strcmp(suf, "tbz") || !strcmp(suf, "tgz")) - return NULL; - - /* add suffix and try */ - snprintf(tmp, sizeof(tmp), "%s.tbz", name); - cp = resolvepattern1(tmp); - if (cp != NULL) - return cp; - snprintf(tmp, sizeof(tmp), "%s.tgz", name); - cp = resolvepattern1(tmp); - if (cp != NULL) - return cp; - - /* add version number wildcard and try */ - snprintf(tmp, sizeof(tmp), "%s-[0-9]*", name); - return resolvepattern1(tmp); -} - -/* - * Look for filename/pattern "fname" in - * Returns a full path/URL where the pkg can be found - */ -char * -fileFindByPath(const char *fname) -{ - char tmp[MaxPathSize]; - struct path *path; - - /* - * 1. if fname is an absolute pathname or a URL, - * just use it. - */ - if (IS_FULLPATH(fname) || IS_URL(fname)) - return resolvepattern(fname); - - /* - * 2. otherwise, use PKG_PATH. - */ - TAILQ_FOREACH(path, &PkgPath, pl_entry) { - char *cp; - const char *cp2 = path->pl_path; - - if (Verbose) - printf("trying PKG_PATH %s\n", cp2); - - if (IS_FULLPATH(cp2) || IS_URL(cp2)) { - snprintf(tmp, sizeof(tmp), "%s/%s", cp2, fname); - } - else { - char cwdtmp[MaxPathSize]; - if (getcwd(cwdtmp, sizeof(cwdtmp)) == NULL) - errx(EXIT_FAILURE, "getcwd"); - snprintf(tmp, sizeof(tmp), "%s/%s/%s", cwdtmp, cp2, fname); - } - cp = resolvepattern(tmp); - if (cp) - return cp; - } - -#if 0 - /* - * 3. finally, search current directory. - */ - snprintf(tmp, sizeof(tmp), "./%s", fname); - return resolvepattern(tmp); -#else - return NULL; -#endif -} - -/* - * Expect "fname" to point at a file, and read it into - * the buffer returned. - */ -char * -fileGetContents(char *fname) -{ - char *contents; - struct stat sb; - int fd; - - if (stat(fname, &sb) == FAIL) { - cleanup(0); - errx(2, "can't stat '%s'", fname); - } - - contents = (char *) malloc((size_t) (sb.st_size) + 1); - fd = open(fname, O_RDONLY, 0); - if (fd == FAIL) { - cleanup(0); - errx(2, "unable to open '%s' for reading", fname); - } - if (read(fd, contents, (size_t) sb.st_size) != (size_t) sb.st_size) { - cleanup(0); - errx(2, "short read on '%s' - did not get %lld bytes", - fname, (long long) sb.st_size); - } - close(fd); - contents[(size_t) sb.st_size] = '\0'; - return contents; -} - -/* * Takes a filename and package name, returning (in "try") the canonical * "preserve" name for it. */ @@ -509,97 +247,6 @@ make_preserve_name(char *try, size_t max, char *name, char *file) return TRUE; } -/* - * Write the contents of "str" to a file - */ -void -write_file(char *name, char *str) -{ - size_t len; - FILE *fp; - - if ((fp = fopen(name, "w")) == (FILE *) NULL) { - cleanup(0); - errx(2, "cannot fopen '%s' for writing", name); - } - len = strlen(str); - if (fwrite(str, 1, len, fp) != len) { - cleanup(0); - errx(2, "short fwrite on '%s', tried to write %ld bytes", - name, (long) len); - } - if (fclose(fp)) { - cleanup(0); - errx(2, "failure to fclose '%s'", name); - } -} - -void -copy_file(char *dir, char *fname, char *to) -{ - char fpath[MaxPathSize]; - - (void) snprintf(fpath, sizeof(fpath), "%s%s%s", - (fname[0] != '/') ? dir : "", - (fname[0] != '/') ? "/" : "", - fname); - if (fexec("cp", "-r", fpath, to, NULL)) { - cleanup(0); - errx(2, "could not perform 'cp -r %s %s'", fpath, to); - } -} - -void -move_file(char *dir, char *fname, char *to) -{ - char fpath[MaxPathSize]; - - (void) snprintf(fpath, sizeof(fpath), "%s%s%s", - (fname[0] != '/') ? dir : "", - (fname[0] != '/') ? "/" : "", - fname); - if (fexec("mv", fpath, to, NULL)) { - cleanup(0); - errx(2, "could not perform 'mv %s %s'", fpath, to); - } -} - -void -move_files(const char *dir, const char *pattern, const char *to) -{ - char fpath[MaxPathSize]; - glob_t globbed; - size_t i; - - (void) snprintf(fpath, sizeof(fpath), "%s/%s", dir, pattern); - if ((i=glob(fpath, GLOB_NOSORT, NULL, &globbed)) != 0) { - switch(i) { - case GLOB_NOMATCH: - warn("no files matching ``%s'' found", fpath); - break; - case GLOB_ABORTED: - warn("globbing aborted"); - break; - case GLOB_NOSPACE: - warn("out-of-memory during globbing"); - break; - default: - warn("unknown error during globbing"); - break; - } - return; - } - - /* Moving globbed files -- we just use mv(1) to do the job */ - for (i=0; i<globbed.gl_pathc; i++) - if (fexec("mv", globbed.gl_pathv[i], to, NULL)) { - cleanup(0); - errx(2, "could not perform 'mv %s %s'", globbed.gl_pathv[i], to); - } - - return; -} - void remove_files(const char *path, const char *pattern) { @@ -635,74 +282,6 @@ remove_files(const char *path, const char *pattern) } /* - * Unpack a tar file - */ -int -unpack(const char *pkg, const lfile_head_t *filesp) -{ - const char *decompress_cmd = NULL; - const char *suf; - int count = 0; - lfile_t *lfp; - char **up_argv; - int up_argc = 7; - int i = 0; - int result; - - if (filesp != NULL) - TAILQ_FOREACH(lfp, filesp, lf_link) - count++; - up_argc += count; - up_argv = malloc((count + up_argc + 1) * sizeof(char *)); - if (!IS_STDIN(pkg)) { - suf = suffix_of(pkg); - if (!strcmp(suf, "tbz") || !strcmp(suf, "bz2")) - decompress_cmd = BZIP2_CMD; - else if (!strcmp(suf, "tgz") || !strcmp(suf, "gz")) - decompress_cmd = GZIP_CMD; - else if (!strcmp(suf, "tar")) - ; /* do nothing */ - else - errx(EXIT_FAILURE, "don't know how to decompress %s, sorry", pkg); - } else - decompress_cmd = GZIP_CMD; - - up_argv[i] = (char *)strrchr(TAR_CMD, '/'); - if (up_argv[i] == NULL) - up_argv[i] = TAR_CMD; - else - up_argv[i]++; /* skip / character */ - if (count > 0) - up_argv[++i] = "--fast-read"; - if (decompress_cmd != NULL) { - up_argv[++i] = "--use-compress-program"; - up_argv[++i] = (char *)decompress_cmd; - } - up_argv[++i] = "-xpf"; - up_argv[++i] = (char *)pkg; - if (count > 0) - TAILQ_FOREACH(lfp, filesp, lf_link) - up_argv[++i] = lfp->lf_name; - up_argv[++i] = NULL; - - if (Verbose) { - printf("running: %s", TAR_CMD); - for (i = 1; up_argv[i] != NULL; i++) - printf(" %s", up_argv[i]); - printf("\n"); - } - - result = pfcexec(NULL, TAR_CMD, (const char **)up_argv); - free(up_argv); - if (result != 0) { - warnx("extract of %s failed", pkg); - return 1; - } - - return 0; -} - -/* * Using fmt, replace all instances of: * * %F With the parameter "name" @@ -712,60 +291,84 @@ unpack(const char *pkg, const lfile_head_t *filesp) * * Check that no overflows can occur. */ -void -format_cmd(char *buf, size_t size, char *fmt, char *dir, char *name) +int +format_cmd(char *buf, size_t size, const char *fmt, const char *dir, const char *name) { - char scratch[MaxPathSize * 2]; - char *bufp; + size_t remaining, quoted; + char *bufp, *tmp; char *cp; - for (bufp = buf; (int) (bufp - buf) < size && *fmt;) { - if (*fmt == '%') { - if (*++fmt != 'D' && name == NULL) { - cleanup(0); - errx(2, "no last file available for '%s' command", buf); + for (bufp = buf, remaining = size; remaining > 1 && *fmt;) { + if (*fmt != '%') { + *bufp++ = *fmt++; + --remaining; + continue; + } + + if (*++fmt != 'D' && name == NULL) { + warnx("no last file available for '%s' command", buf); + return -1; + } + switch (*fmt) { + case 'F': + quoted = shquote(name, bufp, remaining); + if (quoted >= remaining) { + warnx("overflow during quoting"); + return -1; + } + bufp += quoted; + remaining -= quoted; + break; + + case 'D': + quoted = shquote(dir, bufp, remaining); + if (quoted >= remaining) { + warnx("overflow during quoting"); + return -1; } - switch (*fmt) { - case 'F': - strlcpy(bufp, name, size - (int) (bufp - buf)); - bufp += strlen(bufp); - break; - - case 'D': - strlcpy(bufp, dir, size - (int) (bufp - buf)); - bufp += strlen(bufp); - break; - - case 'B': - (void) snprintf(scratch, sizeof(scratch), "%s/%s", dir, name); - if ((cp = strrchr(scratch, '/')) == (char *) NULL) { - cp = scratch; - } - *cp = '\0'; - strlcpy(bufp, scratch, size - (int) (bufp - buf)); - bufp += strlen(bufp); - break; - - case 'f': - (void) snprintf(scratch, sizeof(scratch), "%s/%s", dir, name); - if ((cp = strrchr(scratch, '/')) == (char *) NULL) { - cp = scratch; - } else { - cp++; - } - strlcpy(bufp, cp, size - (int) (bufp - buf)); - bufp += strlen(bufp); - break; - - default: - *bufp++ = '%'; - *bufp++ = *fmt; - break; + bufp += quoted; + remaining -= quoted; + break; + + case 'B': + tmp = xasprintf("%s/%s", dir, name); + cp = strrchr(tmp, '/'); + *cp = '\0'; + quoted = shquote(tmp, bufp, remaining); + free(tmp); + if (quoted >= remaining) { + warnx("overflow during quoting"); + return -1; } - ++fmt; - } else { - *bufp++ = *fmt++; + bufp += quoted; + remaining -= quoted; + break; + + case 'f': + tmp = xasprintf("%s/%s", dir, name); + cp = strrchr(tmp, '/') + 1; + quoted = shquote(cp, bufp, remaining); + free(tmp); + if (quoted >= remaining) { + warnx("overflow during quoting"); + return -1; + } + bufp += quoted; + remaining -= quoted; + break; + + default: + if (remaining == 1) { + warnx("overflow during quoting"); + return -1; + } + *bufp++ = '%'; + *bufp++ = *fmt; + remaining -= 2; + break; } + ++fmt; } *bufp = '\0'; + return 0; } diff --git a/pkgtools/pkg_install/files/lib/ftpio.c b/pkgtools/pkg_install/files/lib/ftpio.c deleted file mode 100644 index 4e0c23cf17b..00000000000 --- a/pkgtools/pkg_install/files/lib/ftpio.c +++ /dev/null @@ -1,1252 +0,0 @@ -/* $NetBSD: ftpio.c,v 1.29 2008/04/29 05:46:08 martin Exp $ */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include <nbcompat.h> -#if HAVE_SYS_CDEFS_H -#include <sys/cdefs.h> -#endif -#ifndef lint -__RCSID("$NetBSD: ftpio.c,v 1.29 2008/04/29 05:46:08 martin Exp $"); -#endif - -/*- - * Copyright (c) 1999-2008 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Hubert Feyrer <hubert@feyrer.de> and Thomas Klausner. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#if HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#if HAVE_SYS_TIME_H -#include <sys/time.h> -#endif -#if HAVE_SYS_POLL_H -#include <sys/poll.h> -#endif -#if HAVE_SYS_WAIT_H -#include <sys/wait.h> -#endif -#if HAVE_SIGNAL_H -#include <signal.h> -#endif -#if HAVE_ASSERT_H -#include <assert.h> -#endif -#if HAVE_CTYPE_H -#include <ctype.h> -#endif -#if HAVE_ERR_H -#include <err.h> -#endif -#if HAVE_ERRNO_H -#include <errno.h> -#endif -#if HAVE_FCNTL_H -#include <fcntl.h> -#endif -#if HAVE_NETDB_H -#include <netdb.h> -#endif -#if HAVE_REGEX_H -#include <regex.h> -#endif -#if HAVE_STRING_H -#include <string.h> -#endif -#if HAVE_STDIO_H -#include <stdio.h> -#endif -#if HAVE_STDLIB_H -#include <stdlib.h> -#endif -#if HAVE_TERMCAP_H -#include <termcap.h> -#endif -#if HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include "../lib/lib.h" - -/* - * Names of environment variables used to pass things to - * subprocesses, for connection caching. - */ -#define PKG_FTPIO_COMMAND "PKG_FTPIO_COMMAND" -#define PKG_FTPIO_ANSWER "PKG_FTPIO_ANSWER" -#define PKG_FTPIO_CNT "PKG_FTPIO_CNT" -#define PKG_FTPIO_CURRENTHOST "PKG_FTPIO_CURRENTHOST" -#define PKG_FTPIO_CURRENTDIR "PKG_FTPIO_CURRENTDIR" - -#undef STANDALONE /* define for standalone debugging */ - -/* File descriptors */ -typedef struct { - int command; - int answer; -} fds; - - -static int needclose=0; -static int ftp_started=0; -static fds ftpio; -static int ftp_pid; -static char term[1024]; -static char bold_on[1024]; -static char bold_off[1024]; - -static char *ftp_expand_URL(const char *, char *); -static int hexvalue(char); -static char *http_expand_URL(const char *, char *); -static int http_extract_fn(char *, char *, size_t); -static void URL_decode(char *); - -/* - * expect "str" (a regular expression) on file descriptor "fd", storing - * the FTP return code of the command in the integer "ftprc". The "str" - * string is expected to match some FTP return codes after a '\n', e.g. - * "\n(550|226).*\n" - */ -static int -expect(int fd, const char *str, int *ftprc) -{ - int rc; - char buf[256]; - regex_t rstr; - int done; - struct pollfd set[1]; - int retval; - regmatch_t match; - int verbose_expect=0; - - if (regcomp(&rstr, str, REG_EXTENDED) != 0) - err(EXIT_FAILURE, "expect: regcomp() failed"); - - memset(buf, '\n', sizeof(buf)); - - done=0; - retval=0; - set[0].fd = fd; - set[0].events = POLLIN; - while(!done) { - rc = poll(set, 1, 60*60*1000); /* seconds until next message from tar */ - switch (rc) { - case -1: - if (errno == EINTR) - break; - warn("expect: poll() failed (probably ftp died because of bad args)"); - done = 1; - retval = -1; - break; - case 0: - warnx("expect: poll() timeout"); - /* need to send ftp coprocess SIGINT to make it stop - * downloading into dir that we'll blow away in a second */ - kill(ftp_pid, SIGINT); - - /* Wait until ftp coprocess is responsive again - * XXX Entering recursion here! - */ - rc = ftp_cmd("cd .\n", "\n(550|250).*\n"); - if (rc != 250) { - /* now we have a really good reason to bail out ;) */ - } - /* ftp is at command prompt again, and will wait for our - * next command. If we were downloading, we can now safely - * continue and remove the dir that the tar command was - * expanding to */ - - done = 1; /* hope that's ok */ - retval = -1; - break; - default: - if (set[0].revents & POLLHUP) { - done = 1; - retval = -1; - break; - } - - rc = read(fd, &buf[sizeof(buf) - 1], 1); - if (rc <= 0) { - done = 1; - retval = -1; - break; - } - - if (verbose_expect) - putchar(buf[sizeof(buf)-1]); - - if (regexec(&rstr, buf, 1, &match, 0) == 0) { - if (ftprc && isdigit((unsigned char)buf[match.rm_so+1])) - *ftprc = atoi(buf+match.rm_so+1); - - done=1; - retval=0; - } - - memmove(buf, buf+1, sizeof(buf)-1); /* yes, this is non-performant */ - break; - } - } - - return retval; -} - -/* - * send a certain ftp-command "cmd" to our FTP coprocess, and wait for - * "expectstr" to be returned. Return numeric FTP return code or -1 - * in case of an error (usually expect() timeout) - */ -int -ftp_cmd(const char *cmd, const char *expectstr) -{ - int rc=0, verbose_ftp=0; - int len; - - if (Verbose) - verbose_ftp=1; - - if (verbose_ftp) - fprintf(stderr, "\n%sftp> %s%s", bold_on, cmd, bold_off); - - fflush(stdout); - len = write(ftpio.command, cmd, strlen(cmd)); - if (len == strlen(cmd)) { - if (expectstr) { - /* set "rc" to the FTP error code: */ - if (expect(ftpio.answer, expectstr, &rc) == -1) - rc = -1; /* some error occurred */ - } - } else { - if (Verbose) - warn("short write"); - } - - return rc; -} - - -/* - * Really fire up FTP coprocess - */ -static int -setupCoproc(const char *base) -{ - int command_pipe[2]; - int answer_pipe[2]; - int rc1, rc2; - char buf[20]; - char *argv0 = (char *)strrchr(FTP_CMD, '/'); - if (argv0 == NULL) - argv0 = FTP_CMD; - else - argv0++; - - rc1 = pipe(command_pipe); - rc2 = pipe(answer_pipe); - - if(rc1==-1 || rc2==-1) { - warn("setupCoproc: pipe() failed"); - return -1; - } - - if (command_pipe[0] == -1 || command_pipe[1] == -1 || - answer_pipe[0] == -1 || answer_pipe[1] == -1 ) { - warn("setupCoproc: pipe() returned bogus descriptor"); - return -1; - } - - rc1 = fork(); - switch (rc1) { - case -1: - /* Error */ - - warn("setupCoproc: fork() failed"); - return -1; - break; - - case 0: - /* Child */ - - (void) close(command_pipe[1]); - rc1 = dup2(command_pipe[0], 0); - if (rc1 == -1) { - err(EXIT_FAILURE, "setupCoproc: dup2 failed (command_pipe[0])"); - } - (void) close(command_pipe[0]); - - (void) close(answer_pipe[0]); - rc1 = dup2(answer_pipe[1], 1); - if (rc1 == -1) { - err(EXIT_FAILURE, "setupCoproc: dup2 failed (answer_pipe[1])"); - } - (void) close(answer_pipe[1]); - - setbuf(stdout, NULL); - - if (Verbose) - fprintf(stderr, "%sftp -detv %s%s\n", bold_on, base, bold_off); - rc1 = execlp(FTP_CMD, argv0, "-detv", base, NULL); - warn("setupCoproc: execlp() failed"); - exit(1); - break; - default: - /* Parent */ - (void) close(command_pipe[0]); - (void) close(answer_pipe[1]); - - (void) snprintf(buf, sizeof(buf), "%d", command_pipe[1]); - setenv(PKG_FTPIO_COMMAND, buf, 1); - (void) snprintf(buf, sizeof(buf), "%d", answer_pipe[0]); - setenv(PKG_FTPIO_ANSWER, buf, 1); - - ftpio.command = command_pipe[1]; - ftpio.answer = answer_pipe[0]; - ftp_pid = rc1; /* to ^C transfers */ - - fcntl(ftpio.command, F_SETFL, O_NONBLOCK); - fcntl(ftpio.answer , F_SETFL, O_NONBLOCK); - - break; - } - - return 0; -} - - -/* - * Dummy signal handler to detect if the ftp(1) coprocess or - * and of the processes of the tar/gzip pipeline dies. - */ -static void -sigchld_handler (int n) -{ - /* Make poll(2) return EINTR */ -} - - -/* - * SIGPIPE only happens when there's something wrong with the FTP - * coprocess. In that case, set mark to not try to close shut down - * the coprocess. - */ -static void -sigpipe_handler(int n) -{ - /* aparently our ftp companion died */ - if (Verbose) - fprintf(stderr, "SIGPIPE!\n"); - needclose = 0; -} - - -/* - * Close the FTP coprocess' current connection, but - * keep the process itself alive. - */ -void -ftp_stop(void) -{ -#if defined(__svr4__) && defined(__sun__) - char env[BUFSIZ]; -#endif - const char *tmp1, *tmp2; - - if (!ftp_started) - return; - - tmp1=getenv(PKG_FTPIO_COMMAND); - tmp2=getenv(PKG_FTPIO_ANSWER); - - /* (Only) the last one closes the link */ - if (tmp1 != NULL && tmp2 != NULL) { - if (needclose) - ftp_cmd("close\n", "\n(221 .*|Not connected.)\n"); - - (void) close(ftpio.command); - (void) close(ftpio.answer); - } - -#if defined(__svr4__) && defined(__sun__) - (void) snprintf(env, sizeof(env), "%s=", PKG_FTPIO_COMMAND); - putenv(env); - (void) snprintf(env, sizeof(env), "%s=", PKG_FTPIO_ANSWER); - putenv(env); -#else - unsetenv(PKG_FTPIO_COMMAND); - unsetenv(PKG_FTPIO_ANSWER); -#endif -} - - -/* - * (Start and re-)Connect the FTP coprocess to some host/dir. - * If the requested host/dir is different than the one that the - * coprocess is currently at, close first. - */ -int -ftp_start(const char *base) -{ - const char *tmp1, *tmp2; - char *p; - int rc; - char newHost[MAXHOSTNAMELEN]; - const char *newDir; - const char *currentHost=getenv(PKG_FTPIO_CURRENTHOST); - const char *currentDir=getenv(PKG_FTPIO_CURRENTDIR); - int urllen; - - /* talk to termcap for bold on/off escape sequences */ - if (getenv("TERM") != NULL && tgetent(term, getenv("TERM")) > 0) { - p = bold_on; tgetstr("md", &p); - p = bold_off; tgetstr("me", &p); - } else { - bold_on[0] = '\0'; - bold_off[0] = '\0'; - } - - fileURLHost(base, newHost, sizeof(newHost)); - urllen = URLlength(base); - if (urllen < 0 || !(newDir = strchr(base + URLlength(base), '/'))) - errx(EXIT_FAILURE, "ftp_start: bad URL '%s'", base); - newDir++; - if (currentHost - && currentDir - && ( strcmp(newHost, currentHost) != 0 - || strcmp(newDir, currentDir) != 0)) { /* could handle new dir case better here, w/o reconnect */ - if (Verbose) { - printf("ftp_start: new host or dir, stopping previous connect...\n"); - printf("currentHost='%s', newHost='%s'\n", currentHost, newHost); - printf("currentDir='%s', newDir='%s'\n", currentDir, newDir); - } - - ftp_stop(); - - if (Verbose) - printf("ftp stopped\n"); - } - setenv(PKG_FTPIO_CURRENTHOST, newHost, 1); /* need to update this in the environment */ - setenv(PKG_FTPIO_CURRENTDIR, newDir, 1); /* for subprocesses to have this available */ - - tmp1=getenv(PKG_FTPIO_COMMAND); - tmp2=getenv(PKG_FTPIO_ANSWER); - if(tmp1==NULL || tmp2==NULL || *tmp1=='\0' || *tmp2=='\0') { - /* no FTP coprocess running yet */ - - if (Verbose) - printf("Spawning FTP coprocess\n"); - - rc = setupCoproc(base); - if (rc == -1) { - warnx("setupCoproc() failed"); - return -1; - } - - needclose=1; - signal(SIGPIPE, sigpipe_handler); - signal(SIGCHLD, sigchld_handler); - - if ((expect(ftpio.answer, "\n(221|250|221|550).*\n", &rc) != 0) - || rc != 250) { - warnx("expect1 failed, rc=%d", rc); - return -1; - } - - /* nbftp now issues a CWD for each part of the path - * and will return a code for each of them. No idea how to - * deal with that other than to issue a 'prompt off' to - * get something that we can wait for and that does NOT - * look like a CWD command's output */ - rc = ftp_cmd("prompt off\n", "\n(Interactive mode off|221).*\n"); - if ((rc == 221) || (rc == -1)) { - /* something is wrong */ - ftp_started=1; /* not really, but for ftp_stop() */ - ftp_stop(); - warnx("prompt failed - wrong dir?"); - return -1; - } - - ftp_started=1; - } else { - /* get FDs of our coprocess */ - - ftpio.command = dup(atoi(tmp1)); - if (ftpio.command == -1 ) { - warnx("command dup() failed, increase 'descriptors' limit"); - return -1; - } - ftpio.answer = dup(atoi(tmp2)); - if (ftpio.answer == -1 ) { - warnx("answer dup() failed, increase 'descriptors' limit"); - return -1; - } - - if (Verbose) - printf("Reusing FDs %s/%s for communication to FTP coprocess\n", tmp1, tmp2); - - fcntl(ftpio.command, F_SETFL, O_NONBLOCK); - fcntl(ftpio.answer , F_SETFL, O_NONBLOCK); - } - - return 0; -} - - -/* - * Expand the given wildcard URL "wildcardurl" if possible, and store the - * expanded value into "expandedurl". return 0 if successful, -1 else. - */ -int -expandURL(char *expandedurl, const char *wildcardurl) -{ - char *pattern; - char *bestmatch; - char base[MaxPathSize]; - - pattern=strrchr(wildcardurl, '/'); - if (pattern == NULL){ - warnx("expandURL: no '/' in URL %s?!", wildcardurl); - return -1; - } - if (pattern-strchr(wildcardurl, '/') < 2) { - /* only one or two slashes in total */ - warnx("expandURL: not enough '/' in URL %s", wildcardurl); - return -1; - } - (void) snprintf(base, sizeof(base), "%.*s/", - (int)(pattern-wildcardurl), wildcardurl); - pattern++; - - if (strncmp(wildcardurl, "ftp://", 6) == 0) - bestmatch=ftp_expand_URL(base, pattern); - else if (strncmp(wildcardurl, "http://", 7) == 0) - bestmatch=http_expand_URL(base, pattern); - else { - warnx("expandURL: unknown protocol in URL `%s'", wildcardurl); - return -1; - } - - /* no match found */ - if (bestmatch == NULL) - return -1; - - snprintf(expandedurl, MaxPathSize, "%s%s", base, bestmatch); - if (Verbose) - printf("best match: '%s'\n", expandedurl); - - return 0; -} - -/* for a given wildcard ftp:// URL, find the best matching pkg */ -static char * -ftp_expand_URL(const char *base, char *pattern) -{ - char *s, buf[MaxPathSize]; - char tmpname[MaxPathSize]; - char best[MaxPathSize]; - char s_best[MaxPathSize]; - int rc, got_list, tfd, retry_tbz; - - retry_tbz = 0; - best[0]='\0'; - s_best[0]='\0'; - - rc = ftp_start(base); - if (rc == -1) { - warnx("ftp_start() failed"); - return NULL; - } - - strlcpy(tmpname, "/var/tmp/pkg.XXXXXX", sizeof(tmpname)); - tfd=mkstemp(tmpname); - if (tfd == -1) { - warnx("Cannot generate temp file for ftp(1)'s nlist output"); - return NULL; - } - close(tfd); /* We don't need the file descriptor, but will use - the file in a second */ - - s=strpbrk(pattern, "<>[]?*{"); /* Could leave out "[]?*" here; - * ftp(1) is not that stupid */ - if (!s) { - /* This should only happen when getting here with (only) a package - * name specified to pkg_add, and PKG_PATH containing some URL. - */ - (void) snprintf(buf, sizeof(buf), "nlist %s %s\n", pattern, tmpname); - } else { - /* replace possible version(wildcard) given with "-*". - * we can't use the pkg wildcards here as dewey compare - * and alternates won't be handled by ftp(1); sort - * out later, using pkg_match() */ - if (retry_tbz) { -retry_with_tbz: - (void) snprintf(buf, sizeof(buf), "nlist %.*s*.tbz %s\n", - (int)(s-pattern), pattern, tmpname); - retry_tbz = 0; - } else { - (void) snprintf(buf, sizeof(buf), "nlist %.*s*.tgz %s\n", - (int)(s-pattern), pattern, tmpname); - retry_tbz = 1; - } - } - - rc = ftp_cmd(buf, "\n(550|450|226).*\n"); /* catch errors */ - if (rc != 226) - got_list = 0; - else - got_list = 1; - - /* Sync - don't remove */ - rc = ftp_cmd("cd .\n", "\n(550|250|257).*\n"); - if (rc != 250) { - warnx("chdir failed!"); - unlink(tmpname); /* remove clutter */ - return NULL; - } - - if (got_list == 1 && access(tmpname, R_OK)==0) { - FILE *f; - char filename[MaxPathSize]; - - f=fopen(tmpname, "r"); - if (f == NULL) { - warn("fopen"); - unlink(tmpname); /* remove clutter */ - return NULL; - } - /* The following loop is basically the same as the readdir() loop - * in findmatchingname() */ - while (fgets(filename, sizeof(filename), f)) { - - /* - * We need to strip off any .t[bg]z etc. - * suffix here - */ - - char s_filename[MaxPathSize]; - char s_pattern[MaxPathSize]; - - filename[strlen(filename)-1] = '\0'; - - strip_txz(s_filename, NULL, filename); - strip_txz(s_pattern, NULL, pattern); - - if (pkg_order(s_pattern, s_filename, - s_best[0] != '\0' ? s_best : NULL) == 1) { - strlcpy(s_best, s_filename, sizeof(s_best)); - strlcpy(best, filename, sizeof(best)); - } - } - (void) fclose(f); - } - - if (retry_tbz) - goto retry_with_tbz; - - if (best[0] == '\0' && Verbose) - warnx("nothing appropriate found"); - - unlink(tmpname); - - if (best[0] == '\0') - return NULL; - - return strdup(best); -} - -/* for a given wildcard http:// URL, find the best matching pkg */ -static char * -http_expand_URL(const char *base, char *pattern) -{ - char best[MaxPathSize]; - char s_best[MaxPathSize]; - char line[BUFSIZ]; - char filename[MaxPathSize]; - FILE *fp; - int pipefds[2]; - int state; - pid_t pid; - - *best = '\0'; - *s_best = '\0'; - - /* Set up a pipe for getting the file list */ - if (pipe(pipefds) == -1) { - warnx("cannot create pipe"); - return NULL; - } - if ((pid = fork()) == -1) { - warnx("cannot fork ftp process"); - return NULL; - } - if (pid == 0) { /* The child */ - if (dup2(pipefds[1], STDOUT_FILENO) == -1) { - warnx("dup2 failed before starting ftp"); - _exit(2); - } - close(pipefds[0]); - close(pipefds[1]); - /* get URL contents to stdout and thus to parent, - * silently */ - execlp("ftp", "ftp", "-V", "-o", "-", base, NULL); - warnx("failed to execute ftp"); - _exit(2); - } - - /* parent */ - close(pipefds[1]); - - if ((fp=fdopen(pipefds[0], "r")) == NULL) - warn("can't fdopen pipe end"); - else { - char s_pattern[MaxPathSize]; - int len, offset; - - /* strip of .t[bg]z for comparison */ - strip_txz(s_pattern, NULL, pattern); - - /* initialize http_extract_fn internal state */ - http_extract_fn(NULL, NULL, 0); - - /* read line from HTTP output and extract filenames */ - while (fgets(line, sizeof(line), fp) != NULL) { - len = offset = 0; - while ((len=http_extract_fn(line+offset, filename, - sizeof(filename))) > 0) { - char s_filename[MaxPathSize]; - - offset += len; - strip_txz(s_filename, NULL, filename); - - if (pkg_order(s_pattern, s_filename, - *s_best != '\0' ? s_best : NULL) == 1) { - strlcpy(best, filename, sizeof(best)); - strlcpy(s_best, s_filename, sizeof(best)); - } - } - } - - } - - fclose(fp); - - /* wait for child to exit */ - if (waitpid(pid, &state, 0) < 0) { - /* error has been reported by child */ - return NULL; - } - - if (best[0] == '\0') { - if (Verbose) - warnx("nothing appropriate found"); - return NULL; - } - - return strdup(best); - -} - -enum http_states { - ST_NONE, - ST_LT, ST_LTA, ST_TAGA, ST_H, ST_R, ST_E, ST_F, ST_HREF, - ST_TAG, ST_TAGAX -}; - -/* return any hrefs found */ -static int -http_extract_fn(char *input, char *outbuf, size_t outbuflen) -{ - /* partial copied hrefs from previous calls are saved here */ - static char tempbuf[MaxPathSize]; - /* fill state of tempbuf */ - static int tempbuffill = 0; - /* parsing state information */ - static enum http_states state; - /* currently in double quotes (in parsing) */ - static int dqflag; - char p; - int offset, found; - - if (outbuf == NULL) { - /* init */ - dqflag = tempbuffill = 0; - state = ST_NONE; - return 0; - } - - offset = 0; - found = 0; - while ((p=input[offset++]) != '\0') { - /* handle anything that's inside double quotes */ - if (dqflag) { - /* incomplete href */ - if (state == ST_HREF) { - /* check if space left in output - * buffer */ - if (tempbuffill >= sizeof(tempbuf)) { - warnx("href starting with `%.*s'" - " too long", 60, tempbuf); - /* ignore remainder */ - tempbuffill = 0; - /* need space before "href" - * can start again (invalidly, - * of course, but we don't - * care) */ - state = ST_TAGAX; - } - - /* href complete */ - if (p == '\"') { - /* complete */ - dqflag = 0; - tempbuf[tempbuffill++] = '\0'; - /* need space before "href" - * can start again (invalidly, - * of course, but we don't - * care) */ - state = ST_TAGAX; - found = 1; - break; - } else { - /* copy one more char */ - tempbuf[tempbuffill++] = p; - } - } else { - /* leaving double quotes */ - if (p == '\"') - dqflag = 0; - } - continue; - } - - /* - * entering double quotes? (only relevant inside a tag) - */ - if (state != ST_NONE && p == '\"') { - dqflag = 1; - continue; - } - - /* other cases */ - switch (state) { - case ST_NONE: - /* plain text, not in markup */ - if (p == '<') - state = ST_LT; - break; - case ST_LT: - /* in tag -- "<" already found */ - if (p == '>') - state = ST_NONE; - else if (p == 'a' || p == 'A') - state = ST_LTA; - else if (!isspace((unsigned char)p)) - state = ST_TAG; - break; - case ST_LTA: - /* in tag -- "<a" already found */ - if (p == '>') - state = ST_NONE; - else if (isspace((unsigned char)p)) - state = ST_TAGA; - else - state = ST_TAG; - break; - case ST_TAG: - /* in tag, but not "<a" -- disregard */ - if (p == '>') - state = ST_NONE; - break; - case ST_TAGA: - /* in a-tag -- "<a " already found */ - if (p == '>') - state = ST_NONE; - else if (p == 'h' || p == 'H') - state = ST_H; - else if (!isspace((unsigned char)p)) - state = ST_TAGAX; - break; - case ST_TAGAX: - /* in unknown keyword in a-tag */ - if (p == '>') - state = ST_NONE; - else if (isspace((unsigned char)p)) - state = ST_TAGA; - break; - case ST_H: - /* in a-tag -- "<a h" already found */ - if (p == '>') - state = ST_NONE; - else if (p == 'r' || p == 'R') - state = ST_R; - else if (isspace((unsigned char)p)) - state = ST_TAGA; - else - state = ST_TAGAX; - break; - case ST_R: - /* in a-tag -- "<a hr" already found */ - if (p == '>') - state = ST_NONE; - else if (p == 'e' || p == 'E') - state = ST_E; - else if (isspace((unsigned char)p)) - state = ST_TAGA; - else - state = ST_TAGAX; - break; - case ST_E: - /* in a-tag -- "<a hre" already found */ - if (p == '>') - state = ST_NONE; - else if (p == 'f' || p == 'F') - state = ST_F; - else if (isspace((unsigned char)p)) - state = ST_TAGA; - else - state = ST_TAGAX; - break; - case ST_F: - /* in a-tag -- "<a href" already found */ - if (p == '>') - state = ST_NONE; - else if (p == '=') - state = ST_HREF; - else if (!isspace((unsigned char)p)) - state = ST_TAGAX; - break; - case ST_HREF: - /* in a-tag -- "<a href=" already found */ - /* XXX: handle missing double quotes? */ - if (p == '>') - state = ST_NONE; - /* skip spaces before URL */ - else if (!isspace((unsigned char)p)) - state = ST_TAGA; - break; - /* no default case by purpose */ - } - } - - if (p == '\0') - return -1; - - if (found) { - char *q; - - URL_decode(tempbuf); - - /* strip path (XXX) */ - if ((q=strrchr(tempbuf, '/')) == NULL) - q = tempbuf; - - (void)strlcpy(outbuf, q, outbuflen); - tempbuffill = 0; - } - - return offset; -} - - -static int -hexvalue(char p) -{ - if (p >= '0' && p <= '9') - return (p-'0'); - else if (p >= 'a' && p <= 'f') - return (p-'a'+10); - else if (p >= 'A' && p <= 'F') - return (p-'A'+10); - else - return -1; -} - -/* fetch and extract URL url into directory path */ -static int -http_fetch(const char *url, const char *path) -{ - int pipefds[2]; - int stateftp, state; - pid_t pidftp, pid; - - /* Set up a pipe for passing the fetched contents. */ - if (pipe(pipefds) == -1) { - warn("cannot create pipe"); - return -1; - } - /* fork ftp child */ - if ((pidftp = fork()) == -1) { - warn("cannot fork process for ftp"); - return -1; - } - if (pidftp == 0) { - /* child */ - if (dup2(pipefds[1], STDOUT_FILENO) == -1) { - warn("dup2 failed before executing ftp"); - _exit(2); - } - close(pipefds[0]); - close(pipefds[1]); - execlp(FTP_CMD, FTP_CMD, "-o", "-", url, NULL); - warnx("failed to execute ftp"); - _exit(2); - } - - /* fork unpack child */ - if ((pid = fork()) == -1) { - warn("cannot fork unpack process"); - return -1; - } - if (pid == 0) { - /* child */ - if (dup2(pipefds[0], STDIN_FILENO) == -1) { - warn("dup2 failed before unpack"); - _exit(2); - } - close(pipefds[0]); - close(pipefds[1]); - if ((path != NULL) && (chdir(path) < 0)) - _exit(127); - - if (unpack("-", NULL) != 0) { - warnx("unpack failed"); - _exit(2); - } - - _exit(0); - } - - close(pipefds[0]); - close(pipefds[1]); - - /* wait for unpack to exit */ - while (waitpid(pid, &state, 0) < 0) { - if (errno != EINTR) { - (void)waitpid(pidftp, &stateftp, 0); - return -1; - } - } - while (waitpid(pidftp, &stateftp, 0) < 0) { - if (errno != EINTR) { - return -1; - } - } - - if (!WIFEXITED(state) || !WIFEXITED(stateftp)) - return -1; - - if (WEXITSTATUS(state) != 0 || WEXITSTATUS(stateftp) != 0) - return -1; - - return 0; -} - -static void -URL_decode(char *URL) -{ - char *in, *out; - - in = out = URL; - - while (*in != '\0') { - if (in[0] == '%' && in[1] != '\0' && in[2] != '\0') { - /* URL-decode character */ - if (hexvalue(in[1]) != -1 && hexvalue(in[2]) != -1) { - *out++ = hexvalue(in[1])*16+hexvalue(in[2]); - } - /* skip invalid encoded signs too */ - in += 3; - } - else - *out++ = *in++; - } - - *out = '\0'; - - return; -} -/* - * extract the given (expanded) URL "url" to the given directory "dir" - * return -1 on error, 0 else; - */ -int -unpackURL(const char *url, const char *dir) -{ - char *pkg; - int rc; - char base[MaxPathSize]; - char pkg_path[MaxPathSize]; - - { - /* Verify if the URL is really ok */ - char expnd[MaxPathSize]; - - rc=expandURL(expnd, url); - if (rc == -1) { - warnx("unpackURL: verification expandURL failed"); - return -1; - } - if (strcmp(expnd, url) != 0) { - warnx("unpackURL: verification expandURL failed, '%s'!='%s'", - expnd, url); - return -1; - } - } - - pkg=strrchr(url, '/'); - if (pkg == NULL){ - warnx("unpackURL: no '/' in URL %s?!", url); - return -1; - } - (void) snprintf(base, sizeof(base), "%.*s/", (int)(pkg-url), url); - (void) snprintf(pkg_path, sizeof(pkg_path), "%.*s", - (int)(pkg-url), url); /* no trailing '/' */ - pkg++; - - /* Leave a hint for any depending pkgs that may need it */ - if (getenv("PKG_PATH") == NULL) { - setenv("PKG_PATH", pkg_path, 1); -#if 0 - path_create(pkg_path); /* XXX */ -#endif - if (Verbose) - printf("setenv PKG_PATH='%s'\n", pkg_path); - } - - if (strncmp(url, "http://", 7) == 0) - return http_fetch(url, dir); - - rc = ftp_start(base); - if (rc == -1) { - warnx("ftp_start() failed"); - return -1; /* error */ - } - - { - char cmd[1024]; - const char *decompress_cmd = NULL; - const char *suf; - - if (Verbose) - printf("unpackURL '%s' to '%s'\n", url, dir); - - suf = suffix_of(pkg); - if (!strcmp(suf, "tbz") || !strcmp(suf, "bz2")) - decompress_cmd = BZIP2_CMD; - else if (!strcmp(suf, "tgz") || !strcmp(suf, "gz")) - decompress_cmd = GZIP_CMD; - else if (!strcmp(suf, "tar")) - ; /* do nothing */ - else - errx(EXIT_FAILURE, "don't know how to decompress %s, sorry", pkg); - - /* yes, this is gross, but needed for borken ftp(1) */ - (void) snprintf(cmd, sizeof(cmd), "get %s \"| ( cd %s; " TAR_CMD " %s %s -vvxp -f - | tee %s )\"\n", - pkg, dir, - decompress_cmd != NULL ? "--use-compress-program" : "", - decompress_cmd != NULL ? decompress_cmd : "", - Verbose ? "/dev/stderr" : "/dev/null"); - - rc = ftp_cmd(cmd, "\n(226|550).*\n"); - if (rc != 226) { - warnx("Cannot fetch file (%d!=226)!", rc); - return -1; - } - } - - return 0; -} - - -#ifdef STANDALONE -static void -usage(void) -{ - errx(EXIT_FAILURE, "Usage: foo [-v] ftp://-pattern"); -} - - -int -main(int argc, char *argv[]) -{ - int rc, ch; - char *argv0 = argv[0]; - - while ((ch = getopt(argc, argv, "v")) != -1) { - switch (ch) { - case 'v': - Verbose=1; - break; - default: - usage(); - } - } - argc -= optind; - argv += optind; - - if (argc<1) - usage(); - - while(argv[0] != NULL) { - char newurl[MaxPathSize]; - - printf("Expand %s:\n", argv[0]); - rc = expandURL(newurl, argv[0]); - if (rc==-1) - warnx("Cannot expand %s", argv[0]); - else - printf("Expanded URL: %s\n", newurl); - - /* test out connection caching */ - if (1) { - char *s, buf[MaxPathSize]; - - if ((s=getenv(PKG_FTPIO_CNT)) && atoi(s)>0){ - (void) snprintf(buf, sizeof(buf),"%d", atoi(s)-1); - setenv(PKG_FTPIO_CNT, buf, 1); - - printf("%s>>> %s -v %s\n", s, argv0, argv[0]); - fexec(argv0, "-v", argv[0], NULL); - } - } - - printf("\n\n\n"); - argv++; - } - - ftp_stop(); - - return 0; -} - -void -cleanup(int i) -{ -} -#endif /* STANDALONE */ diff --git a/pkgtools/pkg_install/files/lib/global.c b/pkgtools/pkg_install/files/lib/global.c index e76cc3c160b..608b9278ac7 100644 --- a/pkgtools/pkg_install/files/lib/global.c +++ b/pkgtools/pkg_install/files/lib/global.c @@ -1,4 +1,4 @@ -/* $NetBSD: global.c,v 1.4 2003/09/23 07:13:53 grant Exp $ */ +/* $NetBSD: global.c,v 1.5 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,13 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -#if 0 -static const char *rcsid = "from FreeBSD Id: global.c,v 1.6 1997/10/08 07:47:58 charnier Exp"; -#else -__RCSID("$NetBSD: global.c,v 1.4 2003/09/23 07:13:53 grant Exp $"); -#endif -#endif +__RCSID("$NetBSD: global.c,v 1.5 2009/02/02 12:35:01 joerg Exp $"); /* * FreeBSD install - a package for the installation and maintainance diff --git a/pkgtools/pkg_install/files/lib/gpgsig.c b/pkgtools/pkg_install/files/lib/gpgsig.c new file mode 100644 index 00000000000..e01c50d91ae --- /dev/null +++ b/pkgtools/pkg_install/files/lib/gpgsig.c @@ -0,0 +1,252 @@ +/* $NetBSD: gpgsig.c,v 1.2 2009/02/02 12:35:01 joerg Exp $ */ +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include <nbcompat.h> +#if HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> +#endif + +__RCSID("$NetBSD: gpgsig.c,v 1.2 2009/02/02 12:35:01 joerg Exp $"); + +/*- + * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/wait.h> +#ifndef NETBSD +#include <nbcompat/err.h> +#else +#include <err.h> +#endif +#ifndef NETBSD +#include <nbcompat/stdlib.h> +#else +#include <stdlib.h> +#endif + +#include "lib.h" + +#ifndef __UNCONST +#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) +#endif + +static void +verify_signature(const char *input, size_t input_len, const char *keyring, + const char *detached_signature) +{ + const char *argv[8], **argvp; + pid_t child; + int fd[2], status; + + if (pipe(fd) == -1) + err(EXIT_FAILURE, "cannot create input pipes"); + + child = vfork(); + if (child == -1) + err(EXIT_FAILURE, "cannot fork GPG process"); + if (child == 0) { + close(fd[1]); + close(STDIN_FILENO); + if (dup2(fd[0], STDIN_FILENO) == -1) { + static const char err_msg[] = + "cannot redirect stdin of GPG process\n"; + write(STDERR_FILENO, err_msg, sizeof(err_msg) - 1); + _exit(255); + } + close(fd[0]); + argvp = argv; + *argvp++ = gpg_cmd; + *argvp++ = "--verify"; + if (keyring != NULL) { + *argvp++ = "--no-default-keyring"; + *argvp++ = "--keyring"; + *argvp++ = keyring; + } + + if (detached_signature != NULL) + *argvp++ = detached_signature; + *argvp++ = "-"; + + *argvp = NULL; + + execvp(gpg_cmd, __UNCONST(argv)); + _exit(255); + } + close(fd[0]); + if (write(fd[1], input, input_len) != input_len) + errx(EXIT_FAILURE, "Short read from GPG"); + close(fd[1]); + waitpid(child, &status, 0); + if (status) + errx(EXIT_FAILURE, "GPG could not verify the signature"); +} + +int +inline_gpg_verify(const char *content, size_t len, const char *keyring) +{ + verify_signature(content, len, keyring, NULL); + + return 0; +} + +int +detached_gpg_verify(const char *content, size_t len, + const char *signature, size_t signature_len, const char *keyring) +{ + int fd; + const char *tmpdir; + char *tempsig; + ssize_t ret; + + if (gpg_cmd == NULL) { + warnx("GPG variable not set, failing signature check"); + return -1; + } + + if ((tmpdir = getenv("TMPDIR")) == NULL) + tmpdir = "/tmp"; + tempsig = xasprintf("%s/pkg_install.XXXXXX", tmpdir); + + fd = mkstemp(tempsig); + if (fd == -1) { + warnx("Creating temporary file for GPG signature failed"); + return -1; + } + + while (signature_len) { + ret = write(fd, signature, signature_len); + if (ret == -1) + err(EXIT_FAILURE, "Write to GPG failed"); + if (ret == 0) + errx(EXIT_FAILURE, "Short write to GPG"); + signature_len -= ret; + signature += ret; + } + + verify_signature(content, len, keyring, tempsig); + + unlink(tempsig); + close(fd); + free(tempsig); + + return 0; +} + +int +detached_gpg_sign(const char *content, size_t len, char **sig, size_t *sig_len, + const char *keyring, const char *user) +{ + const char *argv[12], **argvp; + pid_t child; + int fd_in[2], fd_out[2], status; + size_t allocated; + ssize_t ret; + + if (gpg_cmd == NULL) + errx(EXIT_FAILURE, "GPG variable not set"); + + if (pipe(fd_in) == -1) + err(EXIT_FAILURE, "cannot create input pipes"); + if (pipe(fd_out) == -1) + err(EXIT_FAILURE, "cannot create output pipes"); + + child = fork(); + if (child == -1) + err(EXIT_FAILURE, "cannot fork GPG process"); + if (child == 0) { + close(fd_in[1]); + close(STDIN_FILENO); + if (dup2(fd_in[0], STDIN_FILENO) == -1) { + static const char err_msg[] = + "cannot redirect stdin of GPG process\n"; + write(STDERR_FILENO, err_msg, sizeof(err_msg) - 1); + _exit(255); + } + close(fd_in[0]); + + close(fd_out[0]); + close(STDOUT_FILENO); + if (dup2(fd_out[1], STDOUT_FILENO) == -1) { + static const char err_msg[] = + "cannot redirect stdout of GPG process\n"; + write(STDERR_FILENO, err_msg, sizeof(err_msg) - 1); + _exit(255); + } + close(fd_out[1]); + + argvp = argv; + *argvp++ = gpg_cmd; + *argvp++ = "--detach-sign"; + *argvp++ = "--armor"; + *argvp++ = "--output"; + *argvp++ = "-"; + if (user != NULL) { + *argvp++ = "--local-user"; + *argvp++ = user; + } + if (keyring != NULL) { + *argvp++ = "--no-default-keyring"; + *argvp++ = "--secret-keyring"; + *argvp++ = keyring; + } + + *argvp++ = "-"; + *argvp = NULL; + + execvp(gpg_cmd, __UNCONST(argv)); + _exit(255); + } + close(fd_in[0]); + if (write(fd_in[1], content, len) != len) + errx(EXIT_FAILURE, "Short read from GPG"); + close(fd_in[1]); + + allocated = 1024; + *sig = xmalloc(allocated); + *sig_len = 0; + + close(fd_out[1]); + + while ((ret = read(fd_out[0], *sig + *sig_len, + allocated - *sig_len)) > 0) { + *sig_len += ret; + if (*sig_len == allocated) { + allocated *= 2; + *sig = xrealloc(*sig, allocated); + } + } + + close(fd_out[0]); + + waitpid(child, &status, 0); + if (status) + errx(EXIT_FAILURE, "GPG could not create signature"); + + return 0; +} diff --git a/pkgtools/pkg_install/files/lib/iterate.c b/pkgtools/pkg_install/files/lib/iterate.c index 36ddc996789..1ab3b74428d 100644 --- a/pkgtools/pkg_install/files/lib/iterate.c +++ b/pkgtools/pkg_install/files/lib/iterate.c @@ -1,3 +1,5 @@ +/* $NetBSD: iterate.c,v 1.6 2009/02/02 12:35:01 joerg Exp $ */ + /*- * Copyright (c) 2007 Joerg Sonnenberger <joerg@NetBSD.org>. * All rights reserved. @@ -280,8 +282,7 @@ match_best_installed(const char *pkg, void *cookie) case 1: /* Current package is better, remember it. */ free(arg->best_current_match); - if ((arg->best_current_match = strdup(pkg)) == NULL) - return -1; + arg->best_current_match = xstrdup(pkg); break; } return 0; @@ -367,8 +368,7 @@ match_best_file(const char *filename, void *cookie) warnx("filename %s does not contain a recognized suffix", filename); return -1; } - if ((filtered_filename = malloc(len - 4 + 1)) == NULL) - err(EXIT_FAILURE, "malloc failed"); + filtered_filename = xmalloc(len - 4 + 1); memcpy(filtered_filename, filename, len - 4); filtered_filename[len - 4] = '\0'; active_filename = filtered_filename; @@ -390,12 +390,11 @@ match_best_file(const char *filename, void *cookie) /* Current package is better, remember it. */ free(arg->best_current_match); free(arg->best_current_match_filtered); - if ((arg->best_current_match = strdup(filename)) == NULL) - err(EXIT_FAILURE, "strdup failed"); + arg->best_current_match = xstrdup(filename); if (filtered_filename != NULL) arg->best_current_match_filtered = filtered_filename; - else if ((arg->best_current_match_filtered = strdup(active_filename)) == NULL) - err(EXIT_FAILURE, "strdup failed"); + else + arg->best_current_match_filtered = xstrdup(active_filename); return 0; default: errx(EXIT_FAILURE, "Invalid error from pkg_order"); @@ -450,8 +449,7 @@ match_file_and_call(const char *filename, void *cookie) warnx("filename %s does not contain a recognized suffix", filename); return -1; } - if ((filtered_filename = malloc(len - 4 + 1)) == NULL) - err(EXIT_FAILURE, "malloc failed"); + filtered_filename = xmalloc(len - 4 + 1); memcpy(filtered_filename, filename, len - 4); filtered_filename[len - 4] = '\0'; active_filename = filtered_filename; diff --git a/pkgtools/pkg_install/files/lib/lib.h b/pkgtools/pkg_install/files/lib/lib.h index b803b6746e1..2098752e7d0 100644 --- a/pkgtools/pkg_install/files/lib/lib.h +++ b/pkgtools/pkg_install/files/lib/lib.h @@ -1,4 +1,4 @@ -/* $NetBSD: lib.h,v 1.45 2008/09/17 15:21:30 joerg Exp $ */ +/* $NetBSD: lib.h,v 1.46 2009/02/02 12:35:01 joerg Exp $ */ /* from FreeBSD Id: lib.h,v 1.25 1997/10/08 07:48:03 charnier Exp */ @@ -86,55 +86,16 @@ #define DEF_UMASK 022 #endif -/* Usually "rm", but often "echo" during debugging! */ -#define REMOVE_CMD "rm" - -/* Usually "rm", but often "echo" during debugging! */ -#define RMDIR_CMD "rmdir" - -/* Define tar as a string, in case it's called gtar or something */ -#ifndef TAR_CMD -#define TAR_CMD "tar" -#endif - -/* Define pax as a string, used to copy files from staging area */ -#ifndef PAX_CMD -#define PAX_CMD "pax" -#endif - -/* Define gzip and bzip2, used to unpack binary packages */ -#ifndef GZIP_CMD -#define GZIP_CMD "gzip" -#endif - -#ifndef BZIP2_CMD -#define BZIP2_CMD "bzip2" -#endif - -/* Define ftp as a string, in case the ftp client is called something else */ -#ifndef FTP_CMD -#define FTP_CMD "ftp" -#endif - -#ifndef CHOWN_CMD -#define CHOWN_CMD "chown" -#endif - -#ifndef CHMOD_CMD -#define CHMOD_CMD "chmod" -#endif - -#ifndef CHGRP_CMD -#define CHGRP_CMD "chgrp" -#endif - -/* some operating systems don't have this */ -#ifndef MAXPATHLEN -#define MAXPATHLEN 1024 +#ifndef PATH_MAX +# ifdef MAXPATHLEN +# define PATH_MAX MAXPATHLEN +# else +# define PATH_MAX 1024 +# endif #endif enum { - MaxPathSize = MAXPATHLEN + MaxPathSize = PATH_MAX }; /* The names of our "special" files */ @@ -144,6 +105,7 @@ enum { #define INSTALL_FNAME "+INSTALL" #define DEINSTALL_FNAME "+DEINSTALL" #define REQUIRED_BY_FNAME "+REQUIRED_BY" +#define REQUIRED_BY_FNAME_TMP "+REQUIRED_BY.tmp" #define DISPLAY_FNAME "+DISPLAY" #define MTREE_FNAME "+MTREE_DIRS" #define BUILD_VERSION_FNAME "+BUILD_VERSION" @@ -153,22 +115,21 @@ enum { #define SIZE_ALL_FNAME "+SIZE_ALL" #define PRESERVE_FNAME "+PRESERVE" #define VIEWS_FNAME "+VIEWS" +#define VIEWS_FNAME_TMP "+VIEWS.tmp" #define DEPOT_FNAME "+DEPOT" /* The names of special variables */ #define AUTOMATIC_VARNAME "automatic" -/* - * files which we expect to be in every package, passed to - * tar --fast-read. - */ -#define ALL_FNAMES CONTENTS_FNAME" "COMMENT_FNAME" "DESC_FNAME" "MTREE_FNAME" "BUILD_VERSION_FNAME" "BUILD_INFO_FNAME" "SIZE_PKG_FNAME" "SIZE_ALL_FNAME - -#define CMD_CHAR '@' /* prefix for extended PLIST cmd */ +/* Prefix for extended PLIST cmd */ +#define CMD_CHAR '@' /* The name of the "prefix" environment variable given to scripts */ #define PKG_PREFIX_VNAME "PKG_PREFIX" +/* The name of the "destdir" environment variable given to scripts */ +#define PKG_DESTDIR_VNAME "PKG_DESTDIR" + /* * The name of the "metadatadir" environment variable given to scripts. * This variable holds the location of the +-files for this package. @@ -260,7 +221,7 @@ typedef struct _lfile_t { TAILQ_HEAD(_lfile_head_t, _lfile_t); typedef struct _lfile_head_t lfile_head_t; #define LFILE_ADD(lfhead,lfp,str) do { \ - lfp = malloc(sizeof(lfile_t)); \ + lfp = xmalloc(sizeof(lfile_t)); \ lfp->lf_name = str; \ TAILQ_INSERT_TAIL(lfhead,lfp,lf_link); \ } while(0) @@ -273,14 +234,6 @@ typedef struct _lpkg_t { TAILQ_HEAD(_lpkg_head_t, _lpkg_t); typedef struct _lpkg_head_t lpkg_head_t; -/* This structure describes a pipe to a child process */ -typedef struct { - int fds[2]; /* pipe, 0=child stdin, 1=parent output */ - FILE *fp; /* output from parent process */ - pid_t pid; /* process id of child process */ - void (*cleanup)(void); /* called on non-zero child exit status */ -} pipe_to_system_t; - struct pkg_vulnerabilities { size_t entries; char **vulnerability; @@ -296,25 +249,17 @@ struct pkg_vulnerabilities { #define IS_FULLPATH(str) ((str) != NULL && (str)[0] == '/') /* Conflict handling (conflicts.c) */ -int some_installed_package_conflicts_with(const char *, char **, char **); +int some_installed_package_conflicts_with(const char *, const char *, char **, char **); /* Prototypes */ /* Misc */ void cleanup(int); -char *make_playpen(char *, size_t, size_t); -char *where_playpen(void); -void leave_playpen(char *); -uint64_t min_free(const char *); -void save_dirs(char **, char **); -void restore_dirs(char *, char *); void show_version(void); int fexec(const char *, ...); int fexec_skipempty(const char *, ...); int fcexec(const char *, const char *, ...); int pfcexec(const char *, const char *, const char **); -pipe_to_system_t *pipe_to_system_begin(const char *, char *const *, void (*)(void)); -int pipe_to_system_end(pipe_to_system_t *); /* variables file handling */ @@ -335,7 +280,7 @@ const char *suffix_of(const char *); int pkg_match(const char *, const char *); int pkg_order(const char *, const char *, const char *); int ispkgpattern(const char *); -void strip_txz(char *, char *, const char *); +int quick_pkg_match(const char *, const char *); /* Iterator functions */ int iterate_pkg_generic_src(int (*)(const char *, void *), void *, @@ -361,35 +306,20 @@ Boolean isfile(const char *); Boolean isbrokenlink(const char *); Boolean isempty(const char *); int URLlength(const char *); -char *fileGetURL(const char *); -const char *fileURLFilename(const char *, char *, int); -const char *fileURLHost(const char *, char *, int); -char *fileFindByPath(const char *); -char *fileGetContents(char *); Boolean make_preserve_name(char *, size_t, char *, char *); -void write_file(char *, char *); -void copy_file(char *, char *, char *); -void move_file(char *, char *, char *); -void move_files(const char *, const char *, const char *); void remove_files(const char *, const char *); int delete_hierarchy(char *, Boolean, Boolean); -int unpack(const char *, const lfile_head_t *); -void format_cmd(char *, size_t, char *, char *, char *); +int format_cmd(char *, size_t, const char *, const char *, const char *); -/* ftpio.c: FTP handling */ -int expandURL(char *, const char *); -int unpackURL(const char *, const char *); -int ftp_cmd(const char *, const char *); -int ftp_start(const char *); -void ftp_stop(void); +int recursive_remove(const char *, int); /* pkg_io.c: Local and remote archive handling */ struct archive; +struct archive_entry; -struct archive *open_remote_archive(const char *, void **); -void close_remote_archive(void *); -struct archive *open_local_archive(const char *, void **); -void close_local_archive(void *); +struct archive *open_archive(const char *, void **); +void close_archive(void *); +struct archive *find_archive(const char *, void **); /* Packing list */ plist_t *new_plist_entry(void); @@ -404,11 +334,11 @@ void add_plist(package_t *, pl_ent_t, const char *); void add_plist_top(package_t *, pl_ent_t, const char *); void delete_plist(package_t *, Boolean, pl_ent_t, char *); void write_plist(package_t *, FILE *, char *); -void stringify_plist(package_t *, char **, size_t *, char *); +void stringify_plist(package_t *, char **, size_t *, const char *); void parse_plist(package_t *, const char *); void read_plist(package_t *, FILE *); void append_plist(package_t *, FILE *); -int delete_package(Boolean, Boolean, package_t *, Boolean); +int delete_package(Boolean, Boolean, package_t *, Boolean, const char *); /* Package Database */ int pkgdb_open(int); @@ -438,11 +368,66 @@ struct pkg_vulnerabilities *parse_pkg_vulnerabilities(const char *, size_t, int) /* Read pkg_vulnerabilities from file */ struct pkg_vulnerabilities *read_pkg_vulnerabilities(const char *, int, int); void free_pkg_vulnerabilities(struct pkg_vulnerabilities *); +int audit_package(struct pkg_vulnerabilities *, const char *, const char *, + int, int); + +/* Parse configuration file */ +void pkg_install_config(void); +/* Print configuration variable */ +void pkg_install_show_variable(const char *); + +#ifdef HAVE_SSL +/* Package signature creation and validation */ +int pkg_verify_signature(struct archive **, struct archive_entry **, char **, + void **); +int pkg_full_signature_check(struct archive *); +void pkg_free_signature(void *); +void pkg_sign_x509(const char *, const char *, const char *, const char *); +#endif + +void pkg_sign_gpg(const char *, const char *); + +#ifdef HAVE_SSL +/* PKCS7 signing/verification */ +int easy_pkcs7_verify(const char *, size_t, const char *, size_t, + const char *, int); +int easy_pkcs7_sign(const char *, size_t, char **, size_t *, const char *, + const char *); +#endif + +int inline_gpg_verify(const char *, size_t, const char *); +int detached_gpg_verify(const char *, size_t, const char *, size_t, + const char *); +int detached_gpg_sign(const char *, size_t, char **, size_t *, const char *, + const char *); + +char *xstrdup(const char *); +void *xrealloc(void *, size_t); +void *xcalloc(size_t, size_t); +void *xmalloc(size_t); +char *xasprintf(const char *, ...); /* Externs */ extern Boolean Verbose; extern Boolean Fake; extern Boolean Force; +extern const char *cert_chain_file; +extern const char *certs_packages; +extern const char *certs_pkg_vulnerabilities; +extern const char *check_vulnerabilities; +extern const char *config_file; +extern const char *verified_installation; extern const char *gpg_cmd; +extern const char *gpg_keyring_pkgvuln; +extern const char *gpg_keyring_sign; +extern const char *gpg_keyring_verify; +extern const char *gpg_sign_as; +extern char fetch_flags[]; + +extern const char *pkg_vulnerabilities_dir; +extern const char *pkg_vulnerabilities_file; +extern const char *pkg_vulnerabilities_url; +extern const char *ignore_advisories; +extern const char tnf_vulnerability_base[]; #endif /* _INST_LIB_LIB_H_ */ diff --git a/pkgtools/pkg_install/files/lib/lpkg.c b/pkgtools/pkg_install/files/lib/lpkg.c index 58325d03568..6607467a518 100644 --- a/pkgtools/pkg_install/files/lib/lpkg.c +++ b/pkgtools/pkg_install/files/lib/lpkg.c @@ -1,4 +1,4 @@ -/* $NetBSD: lpkg.c,v 1.5 2003/09/23 07:13:53 grant Exp $ */ +/* $NetBSD: lpkg.c,v 1.6 2009/02/02 12:35:01 joerg Exp $ */ /* * Copyright (c) 1999 Christian E. Hopps @@ -46,10 +46,8 @@ alloc_lpkg(const char *pkgname) { lpkg_t *lpp; - if ((lpp = malloc(sizeof(*lpp))) == 0) - err(EXIT_FAILURE, "cannot allocate recursion data"); - if ((lpp->lp_name = strdup(pkgname)) == 0) - err(EXIT_FAILURE, "cannot allocate recursion data"); + lpp = xmalloc(sizeof(*lpp)); + lpp->lp_name = xstrdup(pkgname); return (lpp); } diff --git a/pkgtools/pkg_install/files/lib/opattern.c b/pkgtools/pkg_install/files/lib/opattern.c index cd0bb186119..3861f3250ae 100644 --- a/pkgtools/pkg_install/files/lib/opattern.c +++ b/pkgtools/pkg_install/files/lib/opattern.c @@ -1,4 +1,4 @@ -/* $NetBSD: opattern.c,v 1.4 2007/10/14 23:24:24 rillig Exp $ */ +/* $NetBSD: opattern.c,v 1.5 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,13 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -#if 0 -static const char *rcsid = "Id: str.c,v 1.5 1997/10/08 07:48:21 charnier Exp"; -#else -__RCSID("$NetBSD: opattern.c,v 1.4 2007/10/14 23:24:24 rillig Exp $"); -#endif -#endif +__RCSID("$NetBSD: opattern.c,v 1.5 2009/02/02 12:35:01 joerg Exp $"); /* * FreeBSD install - a package for the installation and maintainance @@ -119,11 +113,35 @@ simple_match(const char *pattern, const char *pkg) } /* + * Performs a fast check if pattern can ever match pkg. + * Returns 1 if a match is possible and 0 otherwise. + */ +int +quick_pkg_match(const char *pattern, const char *pkg) +{ +#define simple(x) (isalnum((unsigned char)(x)) || (x) == '-') + if (!simple(pattern[0])) + return 1; + if (pattern[0] != pkg[0]) + return 0; + + if (!simple(pattern[1])) + return 1; + if (pattern[1] != pkg[1]) + return 0; + return 1; +#undef simple +} + +/* * Match pkg against pattern, return 1 if matching, 0 else */ int pkg_match(const char *pattern, const char *pkg) { + if (!quick_pkg_match(pattern, pkg)) + return 0; + if (strchr(pattern, '{') != (char *) NULL) { /* emulate csh-type alternates */ return alternate_match(pattern, pkg); @@ -154,8 +172,7 @@ pkg_match(const char *pattern, const char *pkg) char *pattern_ver; int retval; - if (asprintf(&pattern_ver, "%s-[0-9]*", pattern) == -1) - errx(EXIT_FAILURE, "Out of memory"); + pattern_ver = xasprintf("%s-[0-9]*", pattern); retval = glob_match(pattern_ver, pkg); free(pattern_ver); return retval; diff --git a/pkgtools/pkg_install/files/admin/config.c b/pkgtools/pkg_install/files/lib/parse-config.c index 073642fbc10..66e9ac6f41f 100644 --- a/pkgtools/pkg_install/files/admin/config.c +++ b/pkgtools/pkg_install/files/lib/parse-config.c @@ -1,4 +1,4 @@ -/* $NetBSD: config.c,v 1.5 2008/04/07 13:25:32 joerg Exp $ */ +/* $NetBSD: parse-config.c,v 1.2 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,9 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -__RCSID("$NetBSD: config.c,v 1.5 2008/04/07 13:25:32 joerg Exp $"); -#endif +__RCSID("$NetBSD: parse-config.c,v 1.2 2009/02/02 12:35:01 joerg Exp $"); /*- * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. @@ -47,31 +45,58 @@ __RCSID("$NetBSD: config.c,v 1.5 2008/04/07 13:25:32 joerg Exp $"); #include <string.h> #endif -#include "admin.h" #include "lib.h" +const char *config_file = SYSCONFDIR"/pkg_install.conf"; + +char fetch_flags[10]; +static const char *active_ftp; +static const char *verbose_netio; +static const char *ignore_proxy; +const char *cert_chain_file; +const char *certs_packages; +const char *certs_pkg_vulnerabilities; +const char *check_vulnerabilities; +const char *verified_installation; +const char *gpg_cmd; +const char *gpg_keyring_pkgvuln; +const char *gpg_keyring_sign; +const char *gpg_keyring_verify; +const char *gpg_sign_as; const char *pkg_vulnerabilities_dir; const char *pkg_vulnerabilities_file; const char *pkg_vulnerabilities_url; const char *ignore_advisories = NULL; + const char tnf_vulnerability_base[] = "ftp://ftp.NetBSD.org/pub/NetBSD/packages/vulns"; static struct config_variable { const char *name; const char **var; } config_variables[] = { + { "ACTIVE_FTP", &active_ftp }, + { "CERTIFICATE_ANCHOR_PKGS", &certs_packages }, + { "CERTIFICATE_ANCHOR_PKGVULN", &certs_pkg_vulnerabilities }, + { "CERTIFICATE_CHAIN", &cert_chain_file }, + { "CHECK_VULNERABILITIES", &check_vulnerabilities }, { "GPG", &gpg_cmd }, + { "GPG_KEYRING_PKGVULN", &gpg_keyring_pkgvuln }, + { "GPG_KEYRING_SIGN", &gpg_keyring_sign }, + { "GPG_KEYRING_VERIFY", &gpg_keyring_verify }, + { "GPG_SIGN_AS", &gpg_sign_as }, + { "IGNORE_PROXY", &ignore_proxy }, + { "IGNORE_URL", &ignore_advisories }, { "PKGVULNDIR", &pkg_vulnerabilities_dir }, { "PKGVULNURL", &pkg_vulnerabilities_url }, - { "IGNORE_URL", &ignore_advisories }, + { "VERBOSE_NETIO", &verbose_netio }, + { "VERIFIED_INSTALLATION", &verified_installation }, { NULL, NULL } }; void -pkg_install_config(const char *config_file) +pkg_install_config(void) { char *value; - int ret; struct config_variable *var; for (var = config_variables; var->name != NULL; ++var) { @@ -82,17 +107,22 @@ pkg_install_config(const char *config_file) if (pkg_vulnerabilities_dir == NULL) pkg_vulnerabilities_dir = _pkgdb_getPKGDB_DIR(); - ret = asprintf(&value, "%s/pkg-vulnerabilities", pkg_vulnerabilities_dir); - pkg_vulnerabilities_file = value; - if (ret == -1) - err(EXIT_FAILURE, "asprintf failed"); + pkg_vulnerabilities_file = xasprintf("%s/pkg-vulnerabilities", + pkg_vulnerabilities_dir); if (pkg_vulnerabilities_url == NULL) { - ret = asprintf(&value, "%s/pkg-vulnerabilities.gz", + pkg_vulnerabilities_url = xasprintf("%s/pkg-vulnerabilities.gz", tnf_vulnerability_base); - pkg_vulnerabilities_url = value; - if (ret == -1) - err(EXIT_FAILURE, "asprintf failed"); } + if (verified_installation == NULL) + verified_installation = "never"; + + if (check_vulnerabilities == NULL) + check_vulnerabilities = "never"; + + snprintf(fetch_flags, sizeof(fetch_flags), "%s%s%s", + (verbose_netio && *verbose_netio) ? "v" : "", + (active_ftp && *active_ftp) ? "" : "p", + (ignore_proxy && *ignore_proxy) ? "d" : ""); } void diff --git a/pkgtools/pkg_install/files/lib/path.c b/pkgtools/pkg_install/files/lib/path.c index 5ef484ebffd..982510bc577 100644 --- a/pkgtools/pkg_install/files/lib/path.c +++ b/pkgtools/pkg_install/files/lib/path.c @@ -1,4 +1,4 @@ -/* $NetBSD: path.c,v 1.6 2004/12/29 12:16:56 agc Exp $ */ +/* $NetBSD: path.c,v 1.7 2009/02/02 12:35:01 joerg Exp $ */ /*- * Copyright (c)2002 YAMAMOTO Takashi, @@ -33,9 +33,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -__RCSID("$NetBSD: path.c,v 1.6 2004/12/29 12:16:56 agc Exp $"); -#endif +__RCSID("$NetBSD: path.c,v 1.7 2009/02/02 12:35:01 joerg Exp $"); #if HAVE_ERR_H #include <err.h> @@ -113,29 +111,18 @@ path_new_entry(const char *cp, size_t len) { struct path *new; - new = malloc(sizeof(*new)); - if (new == NULL) - err(EXIT_FAILURE, "path_create"); + new = xmalloc(sizeof(*new)); if (!IS_FULLPATH(cp) && !IS_URL(cp)) { /* this is a relative path */ - size_t total; char cwd[MaxPathSize]; - size_t cwdlen; if (getcwd(cwd, sizeof(cwd)) == NULL) err(EXIT_FAILURE, "getcwd"); - cwdlen = strlen(cwd); - total = cwdlen + 1 + len + 1; - new->pl_path = malloc(total); - if (new->pl_path == NULL) - err(EXIT_FAILURE, "path_create"); - snprintf(new->pl_path, total, "%s/%*.*s", cwd, (int)len, (int)len, cp); + new->pl_path = xasprintf("%s/%*.*s", cwd, (int)len, (int)len, cp); } else { - new->pl_path = malloc(len + 1); - if (new->pl_path == NULL) - err(EXIT_FAILURE, "path_create"); + new->pl_path = xmalloc(len + 1); memcpy(new->pl_path, cp, len); new->pl_path[len] = '\0'; } @@ -183,9 +170,7 @@ path_setenv(const char *envname) TAILQ_FOREACH(p, &PkgPath, pl_entry) len += strlen(p->pl_path) + 1; - env = malloc(len); - if (env == NULL) - err(EXIT_FAILURE, "path_setenv"); + env = xmalloc(len); env0 = env; envend = env + len; diff --git a/pkgtools/pkg_install/files/lib/pen.c b/pkgtools/pkg_install/files/lib/pen.c deleted file mode 100644 index 65451e7e4e7..00000000000 --- a/pkgtools/pkg_install/files/lib/pen.c +++ /dev/null @@ -1,206 +0,0 @@ -/* $NetBSD: pen.c,v 1.24 2008/04/26 17:40:01 joerg Exp $ */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include <nbcompat.h> -#if HAVE_SYS_CDEFS_H -#include <sys/cdefs.h> -#endif -#ifndef lint -#if 0 -static const char *rcsid = "from FreeBSD Id: pen.c,v 1.25 1997/10/08 07:48:12 charnier Exp"; -#else -__RCSID("$NetBSD: pen.c,v 1.24 2008/04/26 17:40:01 joerg Exp $"); -#endif -#endif - -/* - * FreeBSD install - a package for the installation and maintainance - * of non-core utilities. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Jordan K. Hubbard - * 18 July 1993 - * - * Routines for managing the "play pen". - * - */ - -#if HAVE_ERR_H -#include <err.h> -#endif -#include "lib.h" -#if HAVE_SYS_SIGNAL_H -#include <sys/signal.h> -#endif - -/* For keeping track of where we are */ -static char Current[MaxPathSize]; -static char Previous[MaxPathSize]; -static int CurrentSet; /* rm -fr Current only if it's really set! */ - /* CurrentSet is set to 0 before strcpy()s - * to prevent rm'ing of a partial string - * when interrupted by ^C */ - -char * -where_playpen(void) -{ - return Current; -} - -/* - * Find a good place to play. - */ -static char * -find_play_pen(char *pen, size_t pensize, size_t sz) -{ - const char **cp; - struct stat sb; - char *r; - const char *tmpdir[] = { - "PKG_TMPDIR", - "TMPDIR", - "/var/tmp", - "/tmp", - "/usr/tmp", - NULL - }; - - if (pen == NULL) { - cleanup(0); - errx(2, "find_play_pen(): 'pen' variable is NULL\n" - "(this should not happen, please report!)"); - return NULL; - } - - if (pen[0] && (r = strrchr(pen, '/')) != NULL) { - *r = '\0'; - if (stat(pen, &sb) != FAIL && (min_free(pen) >= sz)) { - *r = '/'; - return pen; - } - } - - for (cp = tmpdir; *cp; cp++) { - const char *d = (**cp == '/') ? *cp : getenv(*cp); - - if (d == NULL || stat(d, &sb) == FAIL || min_free(d) < sz) - continue; - - (void)snprintf(pen, pensize, "%s/instmp.XXXXXX", d); - return pen; - } - - cleanup(0); - errx(2, "Can't find enough temporary space to extract the files.\n" - "Please set your PKG_TMPDIR environment variable to a location " - "with at least %zu bytes free", sz); - return NULL; -} - -/* - * Make a temporary directory to play in and chdir() to it, returning - * pathname of previous working directory. - */ -char * -make_playpen(char *pen, size_t pensize, size_t sz) -{ - if (!find_play_pen(pen, pensize, sz)) - return NULL; - - if (!mkdtemp(pen)) { - cleanup(0); - errx(2, "can't mkdtemp '%s'", pen); - } - - /* - * On at least NetBSD, the temporary directory may have a group - * that isn't in the group list of the current user. In that - * case, it is impossible to extract setgid binaries from the - * package, since chmod(2) doesn't allow to set the S_ISGID bit - * for a group that isn't yours. - */ - (void)chown(pen, -1, getegid()); - - if (Verbose) { - if (sz) - fprintf(stderr, - "Requested space: %lu bytes, free space: %lld bytes in %s\n", - (u_long) sz, (long long) min_free(pen), pen); - } - if (min_free(pen) < sz) { - rmdir(pen); - cleanup(0); - errx(2, "not enough free space to create '%s'.\n" - "Please set your PKG_TMPDIR environment variable to a location\n" - "with more space and\ntry the command again", pen); - } - if (Current[0]) - strlcpy(Previous, Current, sizeof(Previous)); - else if (!getcwd(Previous, MaxPathSize)) { - cleanup(0); - err(EXIT_FAILURE, "fatal error during execution: getcwd"); - } - if (chdir(pen) == FAIL) { - cleanup(0); - errx(2, "can't chdir to '%s'", pen); - } - CurrentSet = 0; strlcpy(Current, pen, sizeof(Current)); CurrentSet = 1; - - return Previous; -} - -/* - * Convenience routine for getting out of playpen - */ -void -leave_playpen(char *save) -{ - void (*oldsig) (int); - - /* Make us interruptable while we're cleaning up - just in case... */ - oldsig = signal(SIGINT, SIG_DFL); - if (Previous[0] && chdir(Previous) == FAIL) { - cleanup(0); - errx(2, "can't chdir back to '%s'", Previous); - } else if (CurrentSet && Current[0] && strcmp(Current, Previous)) { - if (strcmp(Current, "/") == 0) { - fprintf(stderr, "PANIC: About to rm -fr / (not doing so, aborting)\n"); - abort(); - } - if (fexec("rm", "-fr", Current, NULL)) - warnx("couldn't remove temporary dir '%s'", Current); - strlcpy(Current, Previous, sizeof(Current)); - } - if (save) - strlcpy(Previous, save, sizeof(Previous)); - else - Previous[0] = '\0'; - signal(SIGINT, oldsig); -} - -/* - * Return free disk space (in bytes) on given file system. - * Returns size in a uint64_t since off_t isn't 64 bits on all - * operating systems. - */ -uint64_t -min_free(const char *tmpdir) -{ - struct statvfs buf; - - if (statvfs(tmpdir, &buf) != 0) { - warn("statvfs"); - return 0; - } - return (uint64_t)buf.f_bavail * buf.f_bsize; -} diff --git a/pkgtools/pkg_install/files/lib/pexec.c b/pkgtools/pkg_install/files/lib/pexec.c deleted file mode 100644 index 1358aedb910..00000000000 --- a/pkgtools/pkg_install/files/lib/pexec.c +++ /dev/null @@ -1,110 +0,0 @@ -#if HAVE_CONFIG_H -#include "config.h" -#endif -#include <nbcompat.h> -#if HAVE_SYS_WAIT_H -#include <sys/wait.h> -#endif -#if HAVE_ERR_H -#include <err.h> -#endif -#if HAVE_ERRNO_H -#include <errno.h> -#endif -#if HAVE_STDLIB_H -#include <stdlib.h> -#endif -#if HAVE_UNISTD_H -#include <unistd.h> -#endif -#if HAVE_STDIO_H -#include <stdio.h> -#endif - -#include "lib.h" - -/* - * If the supplied callback is not NULL, then call it. - */ -static void call_callback(void (*callback)(void)) -{ - if (callback != NULL) { - callback(); - } -} - -/* - * create pipe, fork and exec file with arguments in argv - * child takes stdin from pipe, set up fp for parent to - * output to pipe, and return this information. - */ -pipe_to_system_t *pipe_to_system_begin(const char *file, char *const argv[], - void (*cleanup_callback)(void)) -{ - pipe_to_system_t *retval; - - retval = malloc(sizeof(pipe_to_system_t)); - if (retval == NULL) { - call_callback(cleanup_callback); - errx(2, "can't get pipe space"); - } - - retval->cleanup = cleanup_callback; - - if (pipe(retval->fds) == -1) { - call_callback(retval->cleanup); - errx(2, "cannot create pipe"); - } - - retval->pid = fork(); - if (retval->pid == -1) { - call_callback(retval->cleanup); - errx(2, "cannot fork process for %s", file); - } - - if (retval->pid == 0) { /* The child */ - if (retval->fds[0] != 0) { - dup2(retval->fds[0], 0); - close(retval->fds[0]); - } - close(retval->fds[1]); - execvp(file, argv); - warn("failed to execute %s command", file); - _exit(2); - } - - /* Meanwhile, back in the parent process ... */ - close(retval->fds[0]); - retval->fp = fdopen(retval->fds[1], "w"); - if (retval->fp == NULL) { - call_callback(retval->cleanup); - errx(2, "fdopen failed"); - } - return retval; -} - -/* - * close pipe and wait for child to exit. on non-zero exit status, - * call cleanup callback. return exit status. - */ -int pipe_to_system_end(pipe_to_system_t *to_pipe) -{ - int status; - int wait_ret; - - fclose(to_pipe->fp); - do { - wait_ret = waitpid(to_pipe->pid, &status, 0); - } while (wait_ret == -1 && errno == EINTR); - - if (wait_ret < 0) { - call_callback(to_pipe->cleanup); - errx(2, "waitpid returned failure"); - } - if (!WIFEXITED(status)) { - call_callback(to_pipe->cleanup); - errx(2, "waitpid: process terminated abnormally"); - } - free(to_pipe); - return WEXITSTATUS(status); -} diff --git a/pkgtools/pkg_install/files/lib/pkcs7.c b/pkgtools/pkg_install/files/lib/pkcs7.c new file mode 100644 index 00000000000..c5a1b7f7464 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/pkcs7.c @@ -0,0 +1,326 @@ +/* $NetBSD: pkcs7.c,v 1.2 2009/02/02 12:35:01 joerg Exp $ */ +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include <nbcompat.h> +#if HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> +#endif + +__RCSID("$NetBSD: pkcs7.c,v 1.2 2009/02/02 12:35:01 joerg Exp $"); + +/*- + * Copyright (c) 2004, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Love Hörnquist Åstrand <lha@it.su.se> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_ERR_H +#include <err.h> +#endif + +#include <openssl/pkcs7.h> +#include <openssl/evp.h> +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#include <openssl/pem.h> +#include <openssl/err.h> +#include <openssl/ui.h> + +#include "lib.h" + +#ifndef __UNCONST +#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) +#endif + +static const int pkg_key_usage = XKU_CODE_SIGN | XKU_SMIME; + +static int +check_ca(X509 *cert) +{ + if ((cert->ex_flags & EXFLAG_KUSAGE) != 0 && + (cert->ex_kusage & KU_KEY_CERT_SIGN) != KU_KEY_CERT_SIGN) + return 0; + if ((cert->ex_flags & EXFLAG_BCONS) != 0) + return (cert->ex_flags & EXFLAG_CA) == EXFLAG_CA; + if ((cert->ex_flags & (EXFLAG_V1|EXFLAG_SS)) == (EXFLAG_V1|EXFLAG_SS)) + return 1; + if ((cert->ex_flags & EXFLAG_KUSAGE) != 0) + return 1; + if ((cert->ex_flags & EXFLAG_NSCERT) != 0 && + (cert->ex_nscert & NS_ANY_CA) != 0) + return 1; + return 0; +} + +static STACK_OF(X509) * +file_to_certs(const char *file) +{ + unsigned long ret; + STACK_OF(X509) *certs; + FILE *f; + + if ((f = fopen(file, "r")) == NULL) { + warn("open failed %s", file); + return NULL; + } + + certs = sk_X509_new_null(); + for (;;) { + X509 *cert; + + cert = PEM_read_X509(f, NULL, NULL, NULL); + if (cert == NULL) { + ret = ERR_GET_REASON(ERR_peek_error()); + if (ret == PEM_R_NO_START_LINE) { + /* End of file reached. no error */ + ERR_clear_error(); + break; + } + sk_X509_free(certs); + warnx("Can't read certificate in file: %s", file); + return NULL; + } + sk_X509_insert(certs, cert, sk_X509_num(certs)); + } + + fclose(f); + + if (sk_X509_num(certs) == 0) { + sk_X509_free(certs); + certs = NULL; + warnx("No certificate found in file %s", file); + } + + return certs; +} + +int +easy_pkcs7_verify(const char *content, size_t len, + const char *signature, size_t signature_len, + const char *anchor, int is_pkg) +{ + STACK_OF(X509) *cert_chain, *signers; + X509_STORE *store; + BIO *sig, *in; + PKCS7 *p7; + int i, status; + X509_NAME *name; + char *subject; + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + status = -1; + + if (cert_chain_file) + cert_chain = file_to_certs(cert_chain_file); + else + cert_chain = NULL; + + store = X509_STORE_new(); + if (store == NULL) { + sk_X509_free(cert_chain); + warnx("Failed to create certificate store"); + return -1; + } + + X509_STORE_load_locations(store, anchor, NULL); + + in = BIO_new_mem_buf(__UNCONST(content), len); + sig = BIO_new_mem_buf(__UNCONST(signature), signature_len); + signers = NULL; + + p7 = PEM_read_bio_PKCS7(sig, NULL, NULL, NULL); + if (p7 == NULL) { + warnx("Failed to parse the signature"); + goto cleanup; + } + + if (PKCS7_verify(p7, cert_chain, store, in, NULL, 0) != 1) { + warnx("Failed to verify signature"); + goto cleanup; + } + + signers = PKCS7_get0_signers(p7, NULL, 0); + if (signers == NULL) { + warnx("Failed to get signers"); + goto cleanup; + } + + if (sk_X509_num(signers) == 0) { + warnx("No signers found"); + goto cleanup; + } + + for (i = 0; i < sk_X509_num(signers); i++) { + /* Compute ex_xkusage */ + X509_check_purpose(sk_X509_value(signers, i), -1, -1); + + if (check_ca(sk_X509_value(signers, i))) { + warnx("CA keys are not valid for signatures"); + goto cleanup; + } + if (is_pkg) { + if (sk_X509_value(signers, i)->ex_xkusage != pkg_key_usage) { + warnx("Certificate must have CODE SIGNING " + "and EMAIL PROTECTION property"); + goto cleanup; + } + } else { + if (sk_X509_value(signers, i)->ex_xkusage != 0) { + warnx("Certificate must not have any property"); + goto cleanup; + } + } + } + + printf("Sigature ok, signed by:\n"); + + for (i = 0; i < sk_X509_num(signers); i++) { + name = X509_get_subject_name(sk_X509_value(signers, i)); + subject = X509_NAME_oneline(name, NULL, 0); + + printf("\t%s\n", subject); + + OPENSSL_free(subject); + } + + status = 0; + +cleanup: + sk_X509_free(cert_chain); + sk_X509_free(signers); + X509_STORE_free(store); + + PKCS7_free(p7); + BIO_free(in); + BIO_free(sig); + + return status; +} + +static int +ssl_pass_cb(char *buf, int size, int rwflag, void *u) +{ + + if (UI_UTIL_read_pw_string(buf, size, "Passphrase: ", 0)) + return 0; + return strlen(buf); +} + +int +easy_pkcs7_sign(const char *content, size_t len, + char **signature, size_t *signature_len, + const char *key_file, const char *cert_file) +{ + FILE *f; + X509 *certificate; + STACK_OF(X509) *c, *cert_chain; + EVP_PKEY *private_key; + char *tmp_sig; + BIO *out, *in; + PKCS7 *p7; + int status; + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + status = -1; + private_key = NULL; + cert_chain = NULL; + in = NULL; + + c = file_to_certs(cert_file); + + if (sk_X509_num(c) != 1) { + warnx("More then one certificate in the certificate file"); + goto cleanup; + } + certificate = sk_X509_value(c, 0); + + /* Compute ex_kusage */ + X509_check_purpose(certificate, -1, 0); + + if (check_ca(certificate)) { + warnx("CA keys are not valid for signatures"); + goto cleanup; + } + + if (certificate->ex_xkusage != pkg_key_usage) { + warnx("Certificate must have CODE SIGNING " + "and EMAIL PROTECTION property"); + goto cleanup; + } + + if (cert_chain_file) + cert_chain = file_to_certs(cert_chain_file); + + if ((f = fopen(key_file, "r")) == NULL) { + warn("Failed to open private key file %s", key_file); + goto cleanup; + } + private_key = PEM_read_PrivateKey(f, NULL, ssl_pass_cb, NULL); + fclose(f); + if (private_key == NULL) { + warnx("Can't read private key: %s", key_file); + goto cleanup; + } + + if (X509_check_private_key(certificate, private_key) != 1) { + warnx("The private key %s doesn't match the certificate %s", + key_file, cert_file); + goto cleanup; + } + + in = BIO_new_mem_buf(__UNCONST(content), len); + + p7 = PKCS7_sign(certificate, private_key, cert_chain, in, + PKCS7_DETACHED|PKCS7_NOATTR|PKCS7_BINARY); + if (p7 == NULL) { + warnx("Failed to create signature structure"); + goto cleanup; + } + + out = BIO_new(BIO_s_mem()); + PEM_write_bio_PKCS7(out, p7); + *signature_len = BIO_get_mem_data(out, &tmp_sig); + *signature = xmalloc(*signature_len); + memcpy(*signature, tmp_sig, *signature_len); + BIO_free_all(out); + + PKCS7_free(p7); + + status = 0; + +cleanup: + sk_X509_free(c); + sk_X509_free(cert_chain); + EVP_PKEY_free(private_key); + BIO_free(in); + + return status; +} diff --git a/pkgtools/pkg_install/files/lib/pkg_install.conf.5 b/pkgtools/pkg_install/files/lib/pkg_install.conf.5 new file mode 100644 index 00000000000..15841f809b8 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/pkg_install.conf.5 @@ -0,0 +1,158 @@ +.\" $NetBSD: pkg_install.conf.5,v 1.2 2009/02/02 12:35:01 joerg Exp $ +.\" +.\" Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Thomas Klausner. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd January 8, 2009 +.Dt PKG_INSTALL.CONF 5 +.Os +.Sh NAME +.Nm pkg_install.conf +.Nd configuration file for package installation tools +.Sh DESCRIPTION +The file +.Nm +contains system defaults for the package installation tools +as a list of variable-value pairs. +Each line has the format +.Ev VARIABLE=VALUE . +If the value consists of more than one line, each line is prefixed with +.Ev VARIABLE= . +.Pp +The current value of a variable can be checked by running +.Dl Ic pkg_admin config-var VARIABLE +.Pp +The following variables are supported: +.Bl -tag -width indent +.It Dv ACTIVE_FTP +Force the use of active FTP. +.It Dv CERTIFICATE_ANCHOR_PKGS +Path to the file containing the certificates used for validating +binary packages. +A package is trusted when a certificate chain ends in one of the +certificates contained in this file. +The certificates must be PEM-encoded. +.It Dv CERTIFICATE_ANCHOR_PKGVULN +Analogous to +.Dv CERTIFICATE_ANCHOR_PKGS . +The +.Pa pkg-vulnerabilities +is trusted when a certificate chain ends in one of the certificates +contained in this file. +.It Dv CERTIFICATE_CHAIN +Path to a file containing additional certificates that can be used +for completing certicate chains when validating binary packages or +pkg-vulnerabilities files. +.Dv CHECK_VULNERABILITIES +Check for vulnerabilities when installing packages. +Supported values are: +.Bl -tag -width interactiveXX +.It Dv never +No check is performed. +.It Dv always +Passing the vulnerability check is required. +A missing pkg-vulnerabilities file is considered an error. +.It Dv interactive +The user is always asked to confirm installation of vulnerable packages. +.El +.It Dv GPG +Path to +.Xr gpg 1 , +which can be used to verify the signature in the +.Pa pkg-vulnerabilities +file when running +.Dl Ic pkg_admin check-pkg-vulnerabilities -s +or +.Dl Ic pkg_admin fetch-pkg-vulnerabilities -s +It can also be used to verify and sign binary packages. +.It Dv GPG_KEYRING_PKGVULN +Non-default keyring to use for verifying GPG signatures of +.Pa pkg-vulnerabilities . +.It Dv GPG_KEYRING_SIGN +Non-default keyring to use for signing packages with GPG. +.It Dv GPG_KEYRING_VERIFY +Non-default keyring to use for verifying GPG signature of packages. +.It Dv GPG_SIGN_AS +User-id to use for signing packages. +.It Dv IGNORE_PROXY +Use direct connections and ignore +.Ev FTP_PROXY +and +.Ev HTTP_PROXY . +.It Dv IGNORE_URL +One line per advisory which should be ignored when running +.Dl Ic pkg_admin audit +The URL from the +.Pa pkg-vulnerabilities +file should be used as value. +.It Dv PKGVULNDIR +Directory name in which the +.Pa pkg-vulnerabilities +file resides. +Default is +.Pa ${PKG_DBDIR} . +.It Dv PKGVULNURL +URL which is used for updating the local +.Pa pkg-vulnerabilities +file when running +.Dl Ic pkg_admin fetch-pkg-vulnerabilities +The default is +.Pa ftp://ftp.NetBSD.org/pub/NetBSD/packages/vulns/pkg-vulnerabilities.gz +.Em Note : +Usually, only the compression type should be changed. +Currently supported are uncompressed files and files compressed by +.Xr bzip2 1 +.Pq Pa .bz2 +or +.Xr gzip 1 +.Pq Pa .gz . +.It Dv VERBOSE_NETIO +Log details of network IO to stderr. +.It Dv VERIFIED_INSTALLATION +Set trust level used when installation. +Supported values are: +.Bl -tag -width interactiveXX +.It Dv never +No signature checks are performed. +.It Dv always +A valid signature is required. +If the binary package can not be verified, the installation is terminated +.It Dv trusted +A valid signature is required. +If the binary package can not be verified, the user is asked interactively. +.It Dv interactive +The user is always asked interactively when installing a package. +.El +.El +.Sh FILES +.Bl -tag +.It Pa @SYSCONFDIR@/pkg_install.conf +Default location for the file described in this manual page. +.El +.Sh SEE ALSO +.Xr pkg_add 1 , +.Xr pkg_admin 1 diff --git a/pkgtools/pkg_install/files/lib/pkg_install.conf.cat5 b/pkgtools/pkg_install/files/lib/pkg_install.conf.cat5 new file mode 100644 index 00000000000..fee89cf98a1 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/pkg_install.conf.cat5 @@ -0,0 +1,117 @@ +PKG_INSTALL.CONF(5) NetBSD File Formats Manual PKG_INSTALL.CONF(5) + +NNAAMMEE + ppkkgg__iinnssttaallll..ccoonnff -- configuration file for package installation tools + +DDEESSCCRRIIPPTTIIOONN + The file ppkkgg__iinnssttaallll..ccoonnff contains system defaults for the package + installation tools as a list of variable-value pairs. Each line has the + format VARIABLE=VALUE. If the value consists of more than one line, each + line is prefixed with VARIABLE=. + + The current value of a variable can be checked by running + ppkkgg__aaddmmiinn ccoonnffiigg--vvaarr VVAARRIIAABBLLEE + + The following variables are supported: + + ACTIVE_FTP + Force the use of active FTP. + + CERTIFICATE_ANCHOR_PKGS + Path to the file containing the certificates used for validating + binary packages. A package is trusted when a certificate chain + ends in one of the certificates contained in this file. The cer- + tificates must be PEM-encoded. + + CERTIFICATE_ANCHOR_PKGVULN + Analogous to CERTIFICATE_ANCHOR_PKGS. The _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s is + trusted when a certificate chain ends in one of the certificates + contained in this file. + + CERTIFICATE_CHAIN + Path to a file containing additional certificates that can be + used for completing certicate chains when validating binary pack- + ages or pkg-vulnerabilities files. CHECK_VULNERABILITIES Check + for vulnerabilities when installing packages. Supported values + are: + + never No check is performed. + + always Passing the vulnerability check is required. A + missing pkg-vulnerabilities file is considered an + error. + + interactive The user is always asked to confirm installation + of vulnerable packages. + + GPG Path to gpg(1), which can be used to verify the signature in the + _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file when running + ppkkgg__aaddmmiinn cchheecckk--ppkkgg--vvuullnneerraabbiilliittiieess --ss + or + ppkkgg__aaddmmiinn ffeettcchh--ppkkgg--vvuullnneerraabbiilliittiieess --ss + It can also be used to verify and sign binary packages. + + GPG_KEYRING_PKGVULN + Non-default keyring to use for verifying GPG signatures of + _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s. + + GPG_KEYRING_SIGN + Non-default keyring to use for signing packages with GPG. + + GPG_KEYRING_VERIFY + Non-default keyring to use for verifying GPG signature of pack- + ages. + + GPG_SIGN_AS + User-id to use for signing packages. + + IGNORE_PROXY + Use direct connections and ignore FTP_PROXY and HTTP_PROXY. + + IGNORE_URL + One line per advisory which should be ignored when running + ppkkgg__aaddmmiinn aauuddiitt + The URL from the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file should be used as + value. + + PKGVULNDIR + Directory name in which the _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file resides. + Default is _$_{_P_K_G___D_B_D_I_R_}. + + PKGVULNURL + URL which is used for updating the local _p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s file + when running + ppkkgg__aaddmmiinn ffeettcchh--ppkkgg--vvuullnneerraabbiilliittiieess + The default is + _f_t_p_:_/_/_f_t_p_._N_e_t_B_S_D_._o_r_g_/_p_u_b_/_N_e_t_B_S_D_/_p_a_c_k_a_g_e_s_/_v_u_l_n_s_/_p_k_g_-_v_u_l_n_e_r_a_b_i_l_i_t_i_e_s_._g_z + _N_o_t_e: Usually, only the compression type should be changed. Cur- + rently supported are uncompressed files and files compressed by + bzip2(1) (_._b_z_2) or gzip(1) (_._g_z). + + VERBOSE_NETIO + Log details of network IO to stderr. + + VERIFIED_INSTALLATION + Set trust level used when installation. Supported values are: + + never No signature checks are performed. + + always A valid signature is required. If the binary + package can not be verified, the installation is + terminated + + trusted A valid signature is required. If the binary + package can not be verified, the user is asked + interactively. + + interactive The user is always asked interactively when + installing a package. + +FFIILLEESS + @SYSCONFDIR@/pkg_install.conf Default location for the file described + in this manual page. + +SSEEEE AALLSSOO + pkg_add(1), pkg_admin(1) + +NetBSD 5.0 January 8, 2009 NetBSD 5.0 diff --git a/pkgtools/pkg_install/files/lib/pkg_io.c b/pkgtools/pkg_install/files/lib/pkg_io.c index e8496eb2c2f..abc973c8ed8 100644 --- a/pkgtools/pkg_install/files/lib/pkg_io.c +++ b/pkgtools/pkg_install/files/lib/pkg_io.c @@ -1,4 +1,4 @@ -/* $NetBSD: pkg_io.c,v 1.3 2008/04/26 17:40:01 joerg Exp $ */ +/* $NetBSD: pkg_io.c,v 1.4 2009/02/02 12:35:01 joerg Exp $ */ /*- * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. * All rights reserved. @@ -36,7 +36,7 @@ #include <sys/cdefs.h> #endif -__RCSID("$NetBSD: pkg_io.c,v 1.3 2008/04/26 17:40:01 joerg Exp $"); +__RCSID("$NetBSD: pkg_io.c,v 1.4 2009/02/02 12:35:01 joerg Exp $"); #include <archive.h> #include <archive_entry.h> @@ -52,7 +52,7 @@ __RCSID("$NetBSD: pkg_io.c,v 1.3 2008/04/26 17:40:01 joerg Exp $"); #include "lib.h" struct fetch_archive { - const char *url; + struct url *url; fetchIO *fetch; char buffer[32768]; }; @@ -62,7 +62,7 @@ fetch_archive_open(struct archive *a, void *client_data) { struct fetch_archive *f = client_data; - f->fetch = fetchGetURL(f->url, ""); + f->fetch = fetchGet(f->url, fetch_flags); if (f->fetch == NULL) return ENOENT; return 0; @@ -88,52 +88,194 @@ fetch_archive_close(struct archive *a, void *client_data) return 0; } -struct archive * -open_remote_archive(const char *url, void **cookie) +static struct archive * +open_archive_by_url(struct url *url, void **cookie) { struct fetch_archive *f; - struct archive *archive; + struct archive *a; - f = malloc(sizeof(*f)); - if (f == NULL) - err(2, "cannot allocate memory for remote archive"); + f = xmalloc(sizeof(*f)); f->url = url; - archive = archive_read_new(); - archive_read_support_compression_all(archive); - archive_read_support_format_all(archive); - if (archive_read_open(archive, f, fetch_archive_open, fetch_archive_read, - fetch_archive_close)) - errx(2, "cannot open archive: %s", archive_error_string(archive)); + a = archive_read_new(); + archive_read_support_compression_all(a); + archive_read_support_format_all(a); + if (archive_read_open(a, f, fetch_archive_open, fetch_archive_read, + fetch_archive_close)) { + archive_read_close(a); + free(f); + return NULL; + } *cookie = f; + return a; +} + +struct archive * +open_archive(const char *url, void **cookie) +{ + struct url *u; + struct archive *a; + + if (!IS_URL(url)) { + a = archive_read_new(); + archive_read_support_compression_all(a); + archive_read_support_format_all(a); + if (archive_read_open_filename(a, url, 1024)) { + archive_read_close(a); + return NULL; + } + *cookie = NULL; + return a; + } + + if ((u = fetchParseURL(url)) == NULL) + return NULL; - return archive; + a = open_archive_by_url(u, cookie); + + fetchFreeURL(u); + return a; } void -close_remote_archive(void *cookie) +close_archive(void *cookie) { free(cookie); } -struct archive * -open_local_archive(const char *path, void **cookie) +static int +strip_suffix(char *filename) { - struct archive *archive; + size_t len; - archive = archive_read_new(); - archive_read_support_compression_all(archive); - archive_read_support_format_all(archive); - if (archive_read_open_filename(archive, path, 1024)) - errx(2, "cannot open archive: %s", - archive_error_string(archive)); - *cookie = NULL; + len = strlen(filename); + if (len <= 4) + return 0; + if (strcmp(filename + len - 4, ".tgz") == 0 || + strcmp(filename + len - 4, ".tbz") == 0) { + filename[len - 4] = '\0'; + return 1; + } else + return 0; +} + +static int +find_best_package(struct url *url, const char *pattern, struct url **best_url) +{ + char *cur_match, *url_pattern, *best_match = NULL; + struct url_list ue; + size_t i; - return archive; + if (*best_url) { + if ((best_match = fetchUnquoteFilename(*best_url)) == NULL) + return -1; + } else + best_match = NULL; + + if (best_match && strip_suffix(best_match) == 0) { + free(best_match); + return -1; + } + + for (i = 0; pattern[i] != '\0'; ++i) { + if (!isalnum((unsigned char)(pattern[i])) && + (pattern[i]) != '-') + break; + } + url_pattern = xasprintf("%*.*s*", (int)i, (int)i, pattern); + + fetchInitURLList(&ue); + if (fetchList(&ue, url, url_pattern, fetch_flags)) { + char *base_url; + base_url = fetchStringifyURL(url); + warnx("Can't process %s%s: %s", base_url, url_pattern, + fetchLastErrString); + free(base_url); + free(url_pattern); + fetchFreeURLList(&ue); + return -1; + } + free(url_pattern); + + for (i = 0; i < ue.length; ++i) { + cur_match = fetchUnquoteFilename(ue.urls + i); + + if (cur_match == NULL) { + free(best_match); + fetchFreeURLList(&ue); + return -1; + } + if (strip_suffix(cur_match) == 0) { + free(cur_match); + continue; + } + if (pkg_order(pattern, cur_match, best_match) == 1) { + if (*best_url) + fetchFreeURL(*best_url); + *best_url = fetchCopyURL(ue.urls + i); + free(best_match); + best_match = cur_match; + cur_match = NULL; + if (*best_url == NULL) { + free(best_match); + return -1; + } + } + free(cur_match); + } + free(best_match); + fetchFreeURLList(&ue); + return 0; } -void -close_local_archive(void *cookie) +struct archive * +find_archive(const char *fname, void **cookie) { + struct archive *a; + struct path *path; + const char *cur_path; + struct url *url, *best_match; + char tmp[MaxPathSize]; + + best_match = NULL; + + a = open_archive(fname, cookie); + if (a != NULL) + return a; + + if (strchr(fname, '/') != NULL) { + const char *last_slash; + + last_slash = strrchr(fname, '/'); + snprintf(tmp, sizeof(tmp), "%s%.*s", + IS_URL(fname) ? "" : "file://", + (int)(last_slash - fname + 1), fname); + url = fetchParseURL(tmp); + if (url == NULL) + return NULL; + fname = last_slash + 1; /* XXX fetchUnquoteFilename */ + find_best_package(url, fname, &best_match); + fetchFreeURL(url); + } else { + TAILQ_FOREACH(path, &PkgPath, pl_entry) { + cur_path = path->pl_path; + if (!IS_URL(cur_path)) { + snprintf(tmp, sizeof(tmp), "file://%s", cur_path); + cur_path = tmp; + } + url = fetchParseURL(cur_path); + if (url == NULL) + continue; + find_best_package(url, fname, &best_match); + /* XXX Check return value and complain */ + fetchFreeURL(url); + } + } + + if (best_match == NULL) + return NULL; + a = open_archive_by_url(best_match, cookie); + fetchFreeURL(best_match); + return a; } diff --git a/pkgtools/pkg_install/files/lib/pkg_signature.c b/pkgtools/pkg_install/files/lib/pkg_signature.c new file mode 100644 index 00000000000..3f4bb1f039c --- /dev/null +++ b/pkgtools/pkg_install/files/lib/pkg_signature.c @@ -0,0 +1,686 @@ +/* $NetBSD: pkg_signature.c,v 1.2 2009/02/02 12:35:01 joerg Exp $ */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include <nbcompat.h> +#if HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> +#endif +__RCSID("$NetBSD: pkg_signature.c,v 1.2 2009/02/02 12:35:01 joerg Exp $"); + +/*- + * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif +#include <ctype.h> +#if HAVE_ERR_H +#include <err.h> +#endif +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#ifndef NETBSD +#include <nbcompat/sha2.h> +#else +#include <sha2.h> +#endif +#include <signal.h> +#ifdef NETBSD +#include <unistd.h> +#else +#include <nbcompat/unistd.h> +#endif + +#include <archive.h> +#include <archive_entry.h> + +#include "lib.h" + +#define HASH_FNAME "+PKG_HASH" +#define SIGNATURE_FNAME "+PKG_SIGNATURE" +#define GPG_SIGNATURE_FNAME "+PKG_GPG_SIGNATURE" + +struct signature_archive { + struct archive *archive; + off_t pkg_size; + size_t sign_block_len, sign_block_number, sign_cur_block; + char **sign_blocks; + unsigned char *sign_buf; +}; + +static void +hash_block(unsigned char *buf, size_t buf_len, + char hash[SHA512_DIGEST_STRING_LENGTH]) +{ + unsigned char digest[SHA512_DIGEST_LENGTH]; + SHA512_CTX hash_ctx; + int i; + + SHA512_Init(&hash_ctx); + SHA512_Update(&hash_ctx, buf, buf_len); + SHA512_Final(digest, &hash_ctx); + for (i = 0; i < SHA512_DIGEST_LENGTH; ++i) { + unsigned char c; + + c = digest[i] / 16; + if (c < 10) + hash[2 * i] = '0' + c; + else + hash[2 * i] = 'a' - 10 + c; + + c = digest[i] % 16; + if (c < 10) + hash[2 * i + 1] = '0' + c; + else + hash[2 * i + 1] = 'a' - 10 + c; + } + hash[2 * i] = '\0'; +} + +static ssize_t +verify_signature_read_cb(struct archive *archive, void *cookie, const void **buf) +{ + struct signature_archive *state = cookie; + char hash[SHA512_DIGEST_STRING_LENGTH]; + ssize_t len, expected; + + if (state->sign_cur_block >= state->sign_block_number) + return 0; + + /* The following works for sign_block_len > 1 */ + if (state->sign_cur_block + 1 == state->sign_block_number) + expected = state->pkg_size % state->sign_block_len; + else + expected = state->sign_block_len; + + len = archive_read_data(state->archive, state->sign_buf, expected); + if (len != expected) { + warnx("Short read from package"); + return -1; + } + + hash_block(state->sign_buf, len, hash); + + if (strcmp(hash, state->sign_blocks[state->sign_cur_block]) != 0) { + warnx("Invalid signature of block %llu", + (unsigned long long)state->sign_cur_block); + return -1; + } + ++state->sign_cur_block; + *buf = state->sign_buf; + return len; +} + +static void +free_signature_int(struct signature_archive *state) +{ + size_t i; + + if (state->sign_blocks != NULL) { + for (i = 0; i < state->sign_block_number; ++i) + free(state->sign_blocks[i]); + } + free(state->sign_blocks); + free(state->sign_buf); + free(state); +} + +void +pkg_free_signature(void *cookie) +{ + struct signature_archive *state = cookie; + + if (state == NULL) + return; + + archive_read_finish(state->archive); + free_signature_int(state); +} + +static int +read_file_from_archive(struct archive *archive, struct archive_entry **entry, + const char *fname, char **content, size_t *len) +{ + int r; + + *content = NULL; + *len = 0; + +retry: + if (*entry == NULL && + (r = archive_read_next_header(archive, entry)) != ARCHIVE_OK) { + if (r == ARCHIVE_FATAL) + warnx("Cannot read from archive: %s", + archive_error_string(archive)); + return -1; + } + if (strcmp(archive_entry_pathname(*entry), "//") == 0) { + archive_read_data_skip(archive); + *entry = NULL; + goto retry; + } + + if (strcmp(fname, archive_entry_pathname(*entry)) != 0) + return -1; + + if (archive_entry_size(*entry) > SSIZE_MAX - 1) { + warnx("signature too large to process"); + return 1; + } + *len = archive_entry_size(*entry); + *content = xmalloc(*len + 1); + + if (archive_read_data(archive, *content, *len) != *len) { + warnx("cannot read complete %s from archive", fname); + free(*content); + *len = 0; + *content = NULL; + return 1; + } + (*content)[*len] = '\0'; + *entry = NULL; + + return 0; +} + +static int +parse_hash_file(const char *hash_file, char **pkgname, + struct signature_archive *state) +{ + static const char block1[] = "pkgsrc signature\n\nversion: 1\npkgname: "; + static const char block2[] = "algorithm: SHA512\nblock size: "; + static const char block3[] = "file size: "; + static const char block4[] = "end pkgsrc signature\n"; + char *next; + size_t i, len; + + *pkgname = NULL; + + if (strncmp(hash_file, block1, strlen(block1)) != 0) + goto cleanup; + hash_file += strlen(block1); + + len = strcspn(hash_file, "\n"); + *pkgname = xmalloc(len + 1); + memcpy(*pkgname, hash_file, len); + (*pkgname)[len] = '\0'; + for (i = 0; i < len; ++i) { + if (!isgraph((unsigned char)(*pkgname)[i])) + goto cleanup; + } + hash_file += len + 1; + + if (strncmp(hash_file, block2, strlen(block2)) != 0) + goto cleanup; + hash_file += strlen(block2); + + errno = 0; + if (!isdigit((unsigned char)*hash_file)) + goto cleanup; + state->sign_block_len = strtoul(hash_file, &next, 10); + hash_file = next; + + /* Assert sane minimum block size of 1KB */ + if (*hash_file++ != '\n' || errno == ERANGE || state->sign_block_len < 1024) + goto cleanup; + + if (strncmp(hash_file, block3, strlen(block3)) != 0) + goto cleanup; + hash_file += strlen(block3); + + errno = 0; + if (!isdigit((unsigned char)*hash_file)) + goto cleanup; + if (sizeof(off_t) >= sizeof(long long)) + state->pkg_size = strtoll(hash_file, &next, 10); + else + state->pkg_size = strtol(hash_file, &next, 10); + hash_file = next; + if (*hash_file++ != '\n' || errno == ERANGE || state->pkg_size < 1) + goto cleanup; + + if (*hash_file++ != '\n') + goto cleanup; + + if (state->pkg_size / state->sign_block_len > SSIZE_MAX) + goto cleanup; + state->sign_block_number = (state->pkg_size + + state->sign_block_len - 1) / state->sign_block_len; + + state->sign_buf = xmalloc(state->sign_block_len); + state->sign_blocks = xcalloc(state->sign_block_number, sizeof(char *)); + + for (i = 0; i < state->sign_block_number; ++i) { + len = strspn(hash_file, "01234567889abcdef"); + if (len != SHA512_DIGEST_LENGTH * 2 || hash_file[len] != '\n') + goto cleanup_hashes; + state->sign_blocks[i] = xmalloc(len + 1); + memcpy(state->sign_blocks[i], hash_file, len); + state->sign_blocks[i][len] = '\0'; + hash_file += len + 1; + } + + if (strcmp(hash_file, block4) != 0) + goto cleanup_hashes; + + return 0; + +cleanup_hashes: + for (i = 0; i < state->sign_block_number; ++i) + free(state->sign_blocks[i]); + free(state->sign_blocks); + state->sign_blocks = NULL; + +cleanup: + warnx("Unknown format of hash file"); + free(*pkgname); + *pkgname = NULL; + return -1; +} + +int +pkg_verify_signature(struct archive **archive, struct archive_entry **entry, + char **pkgname, void **cookie) +{ + struct signature_archive *state; + struct archive_entry *my_entry; + struct archive *a; + char *hash_file, *signature_file; + size_t hash_len, signature_len; + int r, has_sig; + + *pkgname = NULL; + *cookie = NULL; + + state = xmalloc(sizeof(*state)); + state->sign_blocks = NULL; + state->sign_buf = NULL; + state->archive = NULL; + + r = read_file_from_archive(*archive, entry, HASH_FNAME, + &hash_file, &hash_len); + if (r == -1) { + free(state); + goto no_valid_signature; + } else if (r == 1) { + free(state); + goto no_valid_signature; + } + + if (parse_hash_file(hash_file, pkgname, state)) + goto no_valid_signature; + + r = read_file_from_archive(*archive, entry, SIGNATURE_FNAME, + &signature_file, &signature_len); + if (r != 0) { + if (*entry != NULL) + r = read_file_from_archive(*archive, entry, + GPG_SIGNATURE_FNAME, + &signature_file, &signature_len); + if (r != 0) { + free(hash_file); + free(state); + goto no_valid_signature; + } + has_sig = !detached_gpg_verify(hash_file, hash_len, + signature_file, signature_len, gpg_keyring_verify); + + free(signature_file); + } else { + has_sig = !easy_pkcs7_verify(hash_file, hash_len, signature_file, + signature_len, certs_packages, 1); + + free(signature_file); + } + + r = archive_read_next_header(*archive, &my_entry); + if (r != ARCHIVE_OK) { + warnx("Cannot read inner package: %s", + archive_error_string(*archive)); + free_signature_int(state); + goto no_valid_signature; + } + + if (archive_entry_size(my_entry) != state->pkg_size) { + warnx("Package size doesn't match signature"); + free_signature_int(state); + goto no_valid_signature; + } + + state->archive = *archive; + + a = archive_read_new(); + archive_read_support_compression_all(a); + archive_read_support_format_all(a); + if (archive_read_open(a, state, NULL, verify_signature_read_cb, NULL)) { + warnx("Can't open signed package file"); + archive_read_finish(a); + free_signature_int(state); + goto no_valid_signature; + } + *archive = a; + *entry = NULL; + *cookie = state; + + return has_sig ? 0 : -1; + +no_valid_signature: + return -1; +} + +int +pkg_full_signature_check(struct archive *archive) +{ + struct archive_entry *entry = NULL; + char *pkgname; + void *cookie; + int r; + + if (pkg_verify_signature(&archive, &entry, &pkgname, &cookie)) + return -1; + if (pkgname == NULL) + return 0; + + /* XXX read PLIST and compare pkgname */ + while ((r = archive_read_next_header(archive, &entry)) == ARCHIVE_OK) + archive_read_data_skip(archive); + + pkg_free_signature(cookie); + free(pkgname); + return r == ARCHIVE_EOF ? 0 : -1; +} + +static char * +extract_pkgname(int fd) +{ + package_t plist; + plist_t *p; + struct archive *a; + struct archive_entry *entry; + char *buf; + ssize_t len; + int r; + + a = archive_read_new(); + archive_read_support_compression_all(a); + archive_read_support_format_all(a); + if (archive_read_open_fd(a, fd, 1024)) { + warnx("Cannot open binary package: %s", + archive_error_string(a)); + archive_read_finish(a); + return NULL; + } + + r = archive_read_next_header(a, &entry); + if (r != ARCHIVE_OK) { + warnx("Cannot extract package name: %s", + r == ARCHIVE_EOF ? "EOF" : archive_error_string(a)); + archive_read_finish(a); + return NULL; + } + if (strcmp(archive_entry_pathname(entry), "+CONTENTS") != 0) { + warnx("Invalid binary package, doesn't start with +CONTENTS"); + archive_read_finish(a); + return NULL; + } + if (archive_entry_size(entry) > SSIZE_MAX - 1) { + warnx("+CONTENTS too large to process"); + archive_read_finish(a); + return NULL; + } + + len = archive_entry_size(entry); + buf = xmalloc(len + 1); + + if (archive_read_data(a, buf, len) != len) { + warnx("Short read when extracing +CONTENTS"); + free(buf); + archive_read_finish(a); + return NULL; + } + buf[len] = '\0'; + + archive_read_finish(a); + + parse_plist(&plist, buf); + free(buf); + p = find_plist(&plist, PLIST_NAME); + if (p != NULL) { + buf = xstrdup(p->name); + } else { + warnx("Invalid PLIST: missing @name"); + buf = NULL; + } + free_plist(&plist); + + if (lseek(fd, 0, SEEK_SET) != 0) { + warn("Cannot seek in archive"); + free(buf); + return NULL; + } + + return buf; +} + +static const char hash_template[] = +"pkgsrc signature\n" +"\n" +"version: 1\n" +"pkgname: %s\n" +"algorithm: SHA512\n" +"block size: 65536\n" +"file size: %lld\n" +"\n"; + +static const char hash_trailer[] = "end pkgsrc signature\n"; + +void +pkg_sign_x509(const char *name, const char *output, const char *key_file, const char *cert_file) +{ + struct archive *pkg; + struct archive_entry *entry, *hash_entry, *sign_entry; + int fd; + struct stat sb; + char *hash_file, *signature_file, *tmp, *pkgname, hash[SHA512_DIGEST_STRING_LENGTH]; + unsigned char block[65536]; + off_t i, size; + size_t block_len, signature_len; + + if ((fd = open(name, O_RDONLY)) == -1) + err(EXIT_FAILURE, "Cannot open binary package %s", name); + if (fstat(fd, &sb) == -1) + err(EXIT_FAILURE, "Cannot stat %s", name); + + entry = archive_entry_new(); + archive_entry_copy_stat(entry, &sb); + + pkgname = extract_pkgname(fd); + hash_file = xasprintf(hash_template, pkgname, + (long long)archive_entry_size(entry)); + free(pkgname); + + for (i = 0; i < archive_entry_size(entry); i += block_len) { + if (i + sizeof(block) < archive_entry_size(entry)) + block_len = sizeof(block); + else + block_len = archive_entry_size(entry) % sizeof(block); + if (read(fd, block, block_len) != block_len) + err(2, "short read"); + hash_block(block, block_len, hash); + tmp = xasprintf("%s%s\n", hash_file, hash); + free(hash_file); + hash_file = tmp; + } + tmp = xasprintf("%s%s", hash_file, hash_trailer); + free(hash_file); + hash_file = tmp; + + if (easy_pkcs7_sign(hash_file, strlen(hash_file), &signature_file, + &signature_len, key_file, cert_file)) + err(EXIT_FAILURE, "Cannot sign hash file"); + + lseek(fd, 0, SEEK_SET); + + sign_entry = archive_entry_clone(entry); + hash_entry = archive_entry_clone(entry); + pkgname = strrchr(name, '/'); + archive_entry_set_pathname(entry, pkgname != NULL ? pkgname + 1 : name); + archive_entry_set_pathname(hash_entry, HASH_FNAME); + archive_entry_set_pathname(sign_entry, SIGNATURE_FNAME); + archive_entry_set_size(hash_entry, strlen(hash_file)); + archive_entry_set_size(sign_entry, signature_len); + + pkg = archive_write_new(); + archive_write_set_compression_none(pkg); + archive_write_set_format_ar_bsd(pkg); + archive_write_open_filename(pkg, output); + + archive_write_header(pkg, hash_entry); + archive_write_data(pkg, hash_file, strlen(hash_file)); + archive_write_finish_entry(pkg); + archive_entry_free(hash_entry); + + archive_write_header(pkg, sign_entry); + archive_write_data(pkg, signature_file, signature_len); + archive_write_finish_entry(pkg); + archive_entry_free(sign_entry); + + size = archive_entry_size(entry); + archive_write_header(pkg, entry); + + for (i = 0; i < size; i += block_len) { + if (i + sizeof(block) < size) + block_len = sizeof(block); + else + block_len = size % sizeof(block); + if (read(fd, block, block_len) != block_len) + err(2, "short read"); + archive_write_data(pkg, block, block_len); + } + archive_write_finish_entry(pkg); + archive_entry_free(entry); + + archive_write_finish(pkg); + + exit(0); +} + +void +pkg_sign_gpg(const char *name, const char *output) +{ + struct archive *pkg; + struct archive_entry *entry, *hash_entry, *sign_entry; + int fd; + struct stat sb; + char *hash_file, *signature_file, *tmp, *pkgname, hash[SHA512_DIGEST_STRING_LENGTH]; + unsigned char block[65536]; + off_t i, size; + size_t block_len, signature_len; + + if ((fd = open(name, O_RDONLY)) == -1) + err(EXIT_FAILURE, "Cannot open binary package %s", name); + if (fstat(fd, &sb) == -1) + err(EXIT_FAILURE, "Cannot stat %s", name); + + entry = archive_entry_new(); + archive_entry_copy_stat(entry, &sb); + + pkgname = extract_pkgname(fd); + hash_file = xasprintf(hash_template, pkgname, + (long long)archive_entry_size(entry)); + free(pkgname); + + for (i = 0; i < archive_entry_size(entry); i += block_len) { + if (i + sizeof(block) < archive_entry_size(entry)) + block_len = sizeof(block); + else + block_len = archive_entry_size(entry) % sizeof(block); + if (read(fd, block, block_len) != block_len) + err(2, "short read"); + hash_block(block, block_len, hash); + tmp = xasprintf("%s%s\n", hash_file, hash); + free(hash_file); + hash_file = tmp; + } + tmp = xasprintf("%s%s", hash_file, hash_trailer); + free(hash_file); + hash_file = tmp; + + if (detached_gpg_sign(hash_file, strlen(hash_file), &signature_file, + &signature_len, gpg_keyring_sign, gpg_sign_as)) + err(EXIT_FAILURE, "Cannot sign hash file"); + + lseek(fd, 0, SEEK_SET); + + sign_entry = archive_entry_clone(entry); + hash_entry = archive_entry_clone(entry); + pkgname = strrchr(name, '/'); + archive_entry_set_pathname(entry, pkgname != NULL ? pkgname + 1 : name); + archive_entry_set_pathname(hash_entry, HASH_FNAME); + archive_entry_set_pathname(sign_entry, GPG_SIGNATURE_FNAME); + archive_entry_set_size(hash_entry, strlen(hash_file)); + archive_entry_set_size(sign_entry, signature_len); + + pkg = archive_write_new(); + archive_write_set_compression_none(pkg); + archive_write_set_format_ar_bsd(pkg); + archive_write_open_filename(pkg, output); + + archive_write_header(pkg, hash_entry); + archive_write_data(pkg, hash_file, strlen(hash_file)); + archive_write_finish_entry(pkg); + archive_entry_free(hash_entry); + + archive_write_header(pkg, sign_entry); + archive_write_data(pkg, signature_file, signature_len); + archive_write_finish_entry(pkg); + archive_entry_free(sign_entry); + + size = archive_entry_size(entry); + archive_write_header(pkg, entry); + + for (i = 0; i < size; i += block_len) { + if (i + sizeof(block) < size) + block_len = sizeof(block); + else + block_len = size % sizeof(block); + if (read(fd, block, block_len) != block_len) + err(2, "short read"); + archive_write_data(pkg, block, block_len); + } + archive_write_finish_entry(pkg); + archive_entry_free(entry); + + archive_write_finish(pkg); + + exit(0); +} diff --git a/pkgtools/pkg_install/files/lib/pkgdb.c b/pkgtools/pkg_install/files/lib/pkgdb.c index afeefb13655..3270da9ada9 100644 --- a/pkgtools/pkg_install/files/lib/pkgdb.c +++ b/pkgtools/pkg_install/files/lib/pkgdb.c @@ -1,4 +1,4 @@ -/* $NetBSD: pkgdb.c,v 1.30 2008/04/29 05:46:08 martin Exp $ */ +/* $NetBSD: pkgdb.c,v 1.31 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,9 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -__RCSID("$NetBSD: pkgdb.c,v 1.30 2008/04/29 05:46:08 martin Exp $"); -#endif +__RCSID("$NetBSD: pkgdb.c,v 1.31 2009/02/02 12:35:01 joerg Exp $"); /*- * Copyright (c) 1999-2008 The NetBSD Foundation, Inc. @@ -341,10 +339,5 @@ _pkgdb_setPKGDB_DIR(const char *dir) char * pkgdb_pkg_file(const char *pkg, const char *file) { - char *buf; - - if (asprintf(&buf, "%s/%s/%s", _pkgdb_getPKGDB_DIR(), pkg, file) == -1) - err(EXIT_FAILURE, "asprintf failed"); - - return buf; + return xasprintf("%s/%s/%s", _pkgdb_getPKGDB_DIR(), pkg, file); } diff --git a/pkgtools/pkg_install/files/lib/plist.c b/pkgtools/pkg_install/files/lib/plist.c index 6701edda7cd..b55cd3f6239 100644 --- a/pkgtools/pkg_install/files/lib/plist.c +++ b/pkgtools/pkg_install/files/lib/plist.c @@ -1,4 +1,4 @@ -/* $NetBSD: plist.c,v 1.21 2008/09/17 15:21:30 joerg Exp $ */ +/* $NetBSD: plist.c,v 1.22 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,13 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -#if 0 -static const char *rcsid = "from FreeBSD Id: plist.c,v 1.24 1997/10/08 07:48:15 charnier Exp"; -#else -__RCSID("$NetBSD: plist.c,v 1.21 2008/09/17 15:21:30 joerg Exp $"); -#endif -#endif +__RCSID("$NetBSD: plist.c,v 1.22 2009/02/02 12:35:01 joerg Exp $"); /* * FreeBSD install - a package for the installation and maintainance @@ -118,7 +112,7 @@ add_plist(package_t *p, pl_ent_t type, const char *arg) plist_t *tmp; tmp = new_plist_entry(); - tmp->name = (arg == (char *) NULL) ? (char *) NULL : strdup(arg); + tmp->name = (arg == NULL) ? NULL : xstrdup(arg); tmp->type = type; if (!p->head) { p->head = p->tail = tmp; @@ -138,7 +132,7 @@ add_plist_top(package_t *p, pl_ent_t type, const char *arg) plist_t *tmp; tmp = new_plist_entry(); - tmp->name = (arg == (char *) NULL) ? (char *) NULL : strdup(arg); + tmp->name = (arg == NULL) ? NULL : xstrdup(arg); tmp->type = type; if (!p->head) { p->head = p->tail = tmp; @@ -239,13 +233,7 @@ delete_plist(package_t *pkg, Boolean all, pl_ent_t type, char *name) plist_t * new_plist_entry(void) { - plist_t *ret; - - if ((ret = (plist_t *) malloc(sizeof(plist_t))) == (plist_t *) NULL) { - err(EXIT_FAILURE, "can't allocate %ld bytes", (long) sizeof(plist_t)); - } - memset(ret, 0, sizeof(plist_t)); - return ret; + return xcalloc(1, sizeof(plist_t)); } /* @@ -290,9 +278,7 @@ plist_cmd(const char *s, char **arg) while (isspace((unsigned char)*sp)) ++sp; - *arg = strdup(sp); - if (*arg == NULL) - err(2, "strdup failed"); + *arg = xstrdup(sp); if (*sp) { sp2 = *arg + strlen(*arg) - 1; /* @@ -317,6 +303,9 @@ parse_plist(package_t *pkg, const char *buf) const char *eol, *next; size_t len; + pkg->head = NULL; + pkg->tail = NULL; + for (; *buf; buf = next) { /* Until add_plist can deal with trailing whitespace. */ if ((eol = strchr(buf, '\n')) != NULL) { @@ -333,9 +322,7 @@ parse_plist(package_t *pkg, const char *buf) if (len == 0) continue; - line = malloc(len + 1); - if (line == NULL) - err(2, "malloc failed"); + line = xmalloc(len + 1); memcpy(line, buf, len); line[len] = '\0'; @@ -439,7 +426,8 @@ write_plist(package_t *pkg, FILE * fp, char *realprefix) * Like write_plist, but compute memory string. */ void -stringify_plist(package_t *pkg, char **real_buf, size_t *real_len, char *realprefix) +stringify_plist(package_t *pkg, char **real_buf, size_t *real_len, + const char *realprefix) { plist_t *p; const cmd_t *cmdp; @@ -468,8 +456,7 @@ stringify_plist(package_t *pkg, char **real_buf, size_t *real_len, char *realpre } /* Pass Two: build actual string. */ - if ((buf = malloc(len + 1)) == NULL) - err(2, "malloc failed"); + buf = xmalloc(len + 1); *real_buf = buf; *real_len = len; ++len; @@ -517,7 +504,8 @@ do { \ * run it too in cases of failure. */ int -delete_package(Boolean ign_err, Boolean nukedirs, package_t *pkg, Boolean NoDeleteFiles) +delete_package(Boolean ign_err, Boolean nukedirs, package_t *pkg, + Boolean NoDeleteFiles, const char *destdir) { plist_t *p; char *Where = ".", *last_file = ""; @@ -550,6 +538,7 @@ delete_package(Boolean ign_err, Boolean nukedirs, package_t *pkg, Boolean NoDele if (NoDeleteFiles) break; format_cmd(tmp, sizeof(tmp), p->name, Where, last_file); + /* XXX cleanup(0); */ printf("Executing `%s'\n", tmp); if (!Fake && system(tmp)) { warnx("unexec command for `%s' failed", tmp); @@ -559,7 +548,9 @@ delete_package(Boolean ign_err, Boolean nukedirs, package_t *pkg, Boolean NoDele case PLIST_FILE: last_file = p->name; - (void) snprintf(tmp, sizeof(tmp), "%s/%s", Where, p->name); + (void) snprintf(tmp, sizeof(tmp), "%s%s%s/%s", + destdir ? destdir : "", destdir ? "/" : "", + Where, p->name); if (isdir(tmp)) { warnx("attempting to delete directory `%s' as a file\n" "this packing list is incorrect - ignoring delete request", tmp); @@ -577,7 +568,7 @@ delete_package(Boolean ign_err, Boolean nukedirs, package_t *pkg, Boolean NoDele Force ? "deleting anyway" : "not deleting", tmp); if (!Force) { fail = FAIL; - continue; + goto pkgdb_cleanup; } } } @@ -590,7 +581,7 @@ delete_package(Boolean ign_err, Boolean nukedirs, package_t *pkg, Boolean NoDele if ((cc = readlink(tmp, &buf[SymlinkHeaderLen], sizeof(buf) - SymlinkHeaderLen - 1)) < 0) { warn("can't readlink `%s'", tmp); - continue; + goto pkgdb_cleanup; } buf[SymlinkHeaderLen + cc] = 0x0; if (strcmp(buf, p->next->name) != 0) { @@ -600,7 +591,7 @@ delete_package(Boolean ign_err, Boolean nukedirs, package_t *pkg, Boolean NoDele buf, Force ? "deleting anyway" : "not deleting", tmp); if (!Force) { fail = FAIL; - continue; + goto pkgdb_cleanup; } } buf[SymlinkHeaderLen + cc] = 0x0; @@ -609,7 +600,7 @@ delete_package(Boolean ign_err, Boolean nukedirs, package_t *pkg, Boolean NoDele buf, Force ? "deleting anyway" : "not deleting", tmp); if (!Force) { fail = FAIL; - continue; + goto pkgdb_cleanup; } } } @@ -635,21 +626,12 @@ delete_package(Boolean ign_err, Boolean nukedirs, package_t *pkg, Boolean NoDele } } +pkgdb_cleanup: if (!Fake) { if (!restored) { -#ifdef PKGDB_DEBUG - printf("pkgdb_remove(\"%s\")\n", tmp); /* HF */ -#endif errno = 0; - if (pkgdb_remove(tmp)) { - if (errno) { - perror("pkgdb_remove"); - } - } else { -#ifdef PKGDB_DEBUG - printf("pkgdb_remove: ok\n"); -#endif - } + if (pkgdb_remove(tmp) && errno) + perror("pkgdb_remove"); } } } @@ -659,7 +641,9 @@ delete_package(Boolean ign_err, Boolean nukedirs, package_t *pkg, Boolean NoDele if (NoDeleteFiles) break; - (void) snprintf(tmp, sizeof(tmp), "%s/%s", Where, p->name); + (void) snprintf(tmp, sizeof(tmp), "%s%s%s/%s", + destdir ? destdir : "", destdir ? "/" : "", + Where, p->name); if (fexists(tmp)) { if (!isdir(tmp)) { warnx("cannot remove `%s' as a directory\n" @@ -686,14 +670,6 @@ delete_package(Boolean ign_err, Boolean nukedirs, package_t *pkg, Boolean NoDele return fail; } -#ifdef DEBUG -#define RMDIR(dir) fexec(RMDIR_CMD, dir, NULL) -#define REMOVE(dir,ie) fexec_skipemtpy(REMOVE_CMD, (ie) ? "-f " : "", dir, NULL) -#else -#define RMDIR rmdir -#define REMOVE(file,ie) (remove(file) && !(ie)) -#endif - /* * Selectively delete a hierarchy * Returns 1 on error, 0 else. @@ -710,13 +686,15 @@ delete_hierarchy(char *dir, Boolean ign_err, Boolean nukedirs) isdir(dir) ? "directory" : "file", dir); return !ign_err; } else if (nukedirs) { - if (fexec_skipempty(REMOVE_CMD, "-r", ign_err ? "-f" : "", dir, NULL)) + if (recursive_remove(dir, ign_err)) { + warn("Couldn't remove %s", dir); return 1; + } } else if (isdir(dir)) { - if (RMDIR(dir) && !ign_err) + if (rmdir(dir) && !ign_err) return 1; } else { - if (REMOVE(dir, ign_err)) + if (remove(dir) && !ign_err) return 1; } @@ -727,7 +705,7 @@ delete_hierarchy(char *dir, Boolean ign_err, Boolean nukedirs) *cp2 = '\0'; if (!isemptydir(dir)) return 0; - if (RMDIR(dir) && !ign_err) { + if (rmdir(dir) && !ign_err) { if (!fexists(dir)) warnx("directory `%s' doesn't really exist", dir); else diff --git a/pkgtools/pkg_install/files/lib/remove.c b/pkgtools/pkg_install/files/lib/remove.c new file mode 100644 index 00000000000..03249766e45 --- /dev/null +++ b/pkgtools/pkg_install/files/lib/remove.c @@ -0,0 +1,196 @@ +/* $NetBSD: remove.c,v 1.2 2009/02/02 12:35:01 joerg Exp $ */ + +/*- + * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <nbcompat.h> + +#if HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> +#endif + +__RCSID("$NetBSD: remove.c,v 1.2 2009/02/02 12:35:01 joerg Exp $"); + +#if HAVE_DIRENT_H +#include <dirent.h> +#endif +#if HAVE_ERR_H +#include <err.h> +#endif +#include <errno.h> +#if HAVE_FCNTL_H +#include <fcntl.h> +#endif +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "lib.h" + +static int +safe_fchdir(int cwd) +{ + int tmp_errno, rv; + + tmp_errno = errno; + rv = fchdir(cwd); + errno = tmp_errno; + + return rv; +} + +static int +long_remove(const char **path_ptr, int missing_ok, int *did_chdir) +{ + char tmp_path[PATH_MAX + 1]; + const char *slash, *path; + size_t i, len; + int rv; + + path = *path_ptr; + len = strlen(path); + *did_chdir = 0; + + while (len >= PATH_MAX) { + slash = path; + for (i = PATH_MAX - 1; i > 0; --i) { + if (path[i] == '/') + break; + } + if (i == 0) { + errno = ENAMETOOLONG; + return -1; /* Assumes PATH_MAX > NAME_MAX */ + } + memcpy(tmp_path, path, i); + tmp_path[i] = '\0'; + if (chdir(tmp_path)) + return -1; + *did_chdir = 1; + path += i + 1; + len -= i + 1; + } + + if (remove(path) == 0 || (errno == ENOENT && missing_ok)) + rv = 0; + else + rv = -1; + + *path_ptr = path; + + return rv; +} + +static int +recursive_remove_internal(const char *path, int missing_ok, int cwd) +{ + DIR *dir; + struct dirent *de; + const char *sub_path; + char *subdir; + int did_chdir, rv; + + /* + * If the argument is longer than PATH_MAX, long_remove + * will try to shorten it using chdir. So before returning, + * make sure to fchdir back to the original cwd. + */ + sub_path = path; + if (long_remove(&sub_path, missing_ok, &did_chdir) == 0) + rv = 0; + else if (errno != ENOTEMPTY) /* Other errors are terminal. */ + rv = -1; + else + rv = 1; + + if (rv != 1) { + if (did_chdir && safe_fchdir(cwd) == -1 && rv == 0) + rv = -1; + return rv; + } + + if ((dir = opendir(sub_path)) == NULL) { + if (errno == EMFILE) + warn("opendir failed"); + return -1; + } + + if (did_chdir && fchdir(cwd) == -1) + return -1; + + rv = 0; + + while ((de = readdir(dir)) != NULL) { + if (strcmp(de->d_name, ".") == 0) + continue; + if (strcmp(de->d_name, "..") == 0) + continue; + subdir = xasprintf("%s/%s", path, de->d_name); + rv = recursive_remove_internal(subdir, 1, cwd); + free(subdir); + } + + closedir(dir); + + safe_fchdir(cwd); + + rv |= long_remove(&path, missing_ok, &did_chdir); + + if (did_chdir && safe_fchdir(cwd) == -1 && rv == 0) + rv = -1; + + return rv; +} + +int +recursive_remove(const char *path, int missing_ok) +{ + int orig_cwd, rv; + + /* First try the easy case of regular file or empty directory. */ + if (remove(path) == 0 || (errno == ENOENT && missing_ok)) + return 0; + + /* + * If the path is too long, long_remove will use chdir to shorten it, + * so remember the current directory first. + */ + if ((orig_cwd = open(".", O_RDONLY)) == -1) + return -1; + + rv = recursive_remove_internal(path, missing_ok, orig_cwd); + + close(orig_cwd); + return rv; +} diff --git a/pkgtools/pkg_install/files/lib/str.c b/pkgtools/pkg_install/files/lib/str.c index dc76af31976..b190a1e8a77 100644 --- a/pkgtools/pkg_install/files/lib/str.c +++ b/pkgtools/pkg_install/files/lib/str.c @@ -1,4 +1,4 @@ -/* $NetBSD: str.c,v 1.25 2008/10/13 15:54:24 erh Exp $ */ +/* $NetBSD: str.c,v 1.26 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,13 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -#if 0 -static const char *rcsid = "Id: str.c,v 1.5 1997/10/08 07:48:21 charnier Exp"; -#else -__RCSID("$NetBSD: str.c,v 1.25 2008/10/13 15:54:24 erh Exp $"); -#endif -#endif +__RCSID("$NetBSD: str.c,v 1.26 2009/02/02 12:35:01 joerg Exp $"); /* * FreeBSD install - a package for the installation and maintainance @@ -106,44 +100,3 @@ ispkgpattern(const char *pkg) { return strpbrk(pkg, "<>[]?*{") != NULL; } - -/* - * Strip off any .tgz, .tbz or .t[bg]z suffix from fname, - * and copy into buffer "buf", the suffix is stored in "sfx" - * if "sfx" is not NULL. If no suffix is found, "sfx" is set - * to an empty string. - */ -void -strip_txz(char *buf, char *sfx, const char *fname) -{ - static const char *const suffixes[] = { - ".tgz", ".tbz", ".t[bg]z", 0}; - const char *const *suffixp; - size_t len; - - len = strlen(fname); - assert(len < PKG_PATTERN_MAX); - - if (sfx) - sfx[0] = '\0'; - - for (suffixp = suffixes; *suffixp; suffixp++) { - size_t suffixlen = strlen(*suffixp); - - if (memcmp(&fname[len - suffixlen], *suffixp, suffixlen)) - continue; - - /* matched! */ - memcpy(buf, fname, len - suffixlen); - buf[len - suffixlen] = 0; - if (sfx) { - if (suffixlen >= PKG_SUFFIX_MAX) - errx(EXIT_FAILURE, "too long suffix '%s'", fname); - memcpy(sfx, *suffixp, suffixlen+1); - } - return; - } - - /* not found */ - memcpy(buf, fname, len+1); -} diff --git a/pkgtools/pkg_install/files/lib/var.c b/pkgtools/pkg_install/files/lib/var.c index bc902bd6702..af93f456557 100644 --- a/pkgtools/pkg_install/files/lib/var.c +++ b/pkgtools/pkg_install/files/lib/var.c @@ -1,4 +1,4 @@ -/* $NetBSD: var.c,v 1.6 2008/02/02 16:21:46 joerg Exp $ */ +/* $NetBSD: var.c,v 1.7 2009/02/02 12:35:01 joerg Exp $ */ /*- * Copyright (c) 2005, 2008 The NetBSD Foundation, Inc. @@ -39,9 +39,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -__RCSID("$NetBSD: var.c,v 1.6 2008/02/02 16:21:46 joerg Exp $"); -#endif +__RCSID("$NetBSD: var.c,v 1.7 2009/02/02 12:35:01 joerg Exp $"); #if HAVE_SYS_STAT_H #include <sys/stat.h> @@ -128,11 +126,11 @@ var_get(const char *fname, const char *variable) thislen = line+len - p; if (value) { - value = realloc(value, valuelen+thislen+2); + value = xrealloc(value, valuelen+thislen+2); value[valuelen++] = '\n'; } else { - value = malloc(thislen+1); + value = xmalloc(thislen+1); } sprintf(value+valuelen, "%.*s", (int)thislen, p); valuelen += thislen; @@ -171,11 +169,11 @@ var_get_memory(const char *buf, const char *variable) thislen = buf + len - data; if (value) { - value = realloc(value, valuelen+thislen+2); + value = xrealloc(value, valuelen+thislen+2); value[valuelen++] = '\n'; } else { - value = malloc(thislen+1); + value = xmalloc(thislen+1); } sprintf(value + valuelen, "%.*s", (int)thislen, data); valuelen += thislen; @@ -214,9 +212,8 @@ var_set(const char *fname, const char *variable, const char *value) return 0; /* Nothing to do */ } - tmpname = malloc(strlen(fname)+8); - sprintf(tmpname, "%s.XXXXXX", fname); - if ((fd=mkstemp(tmpname)) < 0) { + tmpname = xasprintf("%s.XXXXXX", fname); + if ((fd = mkstemp(tmpname)) < 0) { free(tmpname); if (fp != NULL) fclose(fp); diff --git a/pkgtools/pkg_install/files/lib/version.c b/pkgtools/pkg_install/files/lib/version.c index effebae1c95..f7cb6ec51ad 100644 --- a/pkgtools/pkg_install/files/lib/version.c +++ b/pkgtools/pkg_install/files/lib/version.c @@ -1,4 +1,4 @@ -/* $NetBSD: version.c,v 1.5 2008/05/08 15:30:17 wiz Exp $ */ +/* $NetBSD: version.c,v 1.6 2009/02/02 12:35:01 joerg Exp $ */ #if HAVE_CONFIG_H #include "config.h" @@ -7,9 +7,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -#ifndef lint -__RCSID("$NetBSD: version.c,v 1.5 2008/05/08 15:30:17 wiz Exp $"); -#endif +__RCSID("$NetBSD: version.c,v 1.6 2009/02/02 12:35:01 joerg Exp $"); /* * Copyright (c) 2001 Thomas Klausner. All rights reserved. diff --git a/pkgtools/pkg_install/files/lib/version.h b/pkgtools/pkg_install/files/lib/version.h index 47e7475c966..4ce786660d8 100644 --- a/pkgtools/pkg_install/files/lib/version.h +++ b/pkgtools/pkg_install/files/lib/version.h @@ -1,4 +1,4 @@ -/* $NetBSD: version.h,v 1.107 2008/10/13 15:54:24 erh Exp $ */ +/* $NetBSD: version.h,v 1.108 2009/02/02 12:35:01 joerg Exp $ */ /* * Copyright (c) 2001 Thomas Klausner. All rights reserved. @@ -27,6 +27,6 @@ #ifndef _INST_LIB_VERSION_H_ #define _INST_LIB_VERSION_H_ -#define PKGTOOLS_VERSION "20081013" +#define PKGTOOLS_VERSION "20090201" #endif /* _INST_LIB_VERSION_H_ */ diff --git a/pkgtools/pkg_install/files/lib/vulnerabilities-file.c b/pkgtools/pkg_install/files/lib/vulnerabilities-file.c index e0195a41130..aca293bb5f5 100644 --- a/pkgtools/pkg_install/files/lib/vulnerabilities-file.c +++ b/pkgtools/pkg_install/files/lib/vulnerabilities-file.c @@ -1,3 +1,5 @@ +/* $NetBSD: vulnerabilities-file.c,v 1.4 2009/02/02 12:35:01 joerg Exp $ */ + /*- * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. * All rights reserved. @@ -36,7 +38,7 @@ #if HAVE_SYS_CDEFS_H #include <sys/cdefs.h> #endif -__RCSID("$NetBSD: vulnerabilities-file.c,v 1.3 2008/03/31 16:52:13 tron Exp $"); +__RCSID("$NetBSD: vulnerabilities-file.c,v 1.4 2009/02/02 12:35:01 joerg Exp $"); #if HAVE_SYS_STAT_H #include <sys/stat.h> @@ -64,47 +66,52 @@ __RCSID("$NetBSD: vulnerabilities-file.c,v 1.3 2008/03/31 16:52:13 tron Exp $"); #include "lib.h" -/* - * We explicitely initialize this to NULL to stop Mac OS X Leopard's linker - * from turning this into a common symbol which causes a link failure. - */ -const char *gpg_cmd = NULL; +static const char pgp_msg_start[] = "-----BEGIN PGP SIGNED MESSAGE-----\n"; +static const char pgp_msg_end[] = "-----BEGIN PGP SIGNATURE-----\n"; +static const char pkcs7_begin[] = "-----BEGIN PKCS7-----\n"; +static const char pkcs7_end[] = "-----END PKCS7-----\n"; static void -verify_signature(const char *input, size_t input_len) +verify_signature_pkcs7(const char *input) { - pid_t child; - int fd[2], status; - - if (gpg_cmd == NULL) - errx(EXIT_FAILURE, "GPG variable not set in configuration file"); - - if (pipe(fd) == -1) - err(EXIT_FAILURE, "cannot create input pipes"); - - child = vfork(); - if (child == -1) - err(EXIT_FAILURE, "cannot fork GPG process"); - if (child == 0) { - close(fd[1]); - close(STDIN_FILENO); - if (dup2(fd[0], STDIN_FILENO) == -1) { - static const char err_msg[] = - "cannot redirect stdin of GPG process\n"; - write(STDERR_FILENO, err_msg, sizeof(err_msg) - 1); - _exit(255); - } - close(fd[0]); - execlp(gpg_cmd, gpg_cmd, "--verify", "-", (char *)NULL); - _exit(255); +#ifdef HAVE_SSL + const char *begin_pkgvul, *end_pkgvul, *begin_sig, *end_sig; + + if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) { + begin_pkgvul = input + strlen(pgp_msg_start); + if ((end_pkgvul = strstr(begin_pkgvul, pgp_msg_end)) == NULL) + errx(EXIT_FAILURE, "Invalid PGP signature"); + if ((begin_sig = strstr(end_pkgvul, pkcs7_begin)) == NULL) + errx(EXIT_FAILURE, "No PKCS7 signature"); + } else { + begin_pkgvul = input; + if ((begin_sig = strstr(begin_pkgvul, pkcs7_begin)) == NULL) + errx(EXIT_FAILURE, "No PKCS7 signature"); + end_pkgvul = begin_sig; } - close(fd[0]); - if (write(fd[1], input, input_len) != input_len) - errx(EXIT_FAILURE, "Short read from GPG"); - close(fd[1]); - waitpid(child, &status, 0); - if (status) - errx(EXIT_FAILURE, "GPG could not verify the signature"); + if ((end_sig = strstr(begin_sig, pkcs7_end)) == NULL) + errx(EXIT_FAILURE, "Invalid PKCS7 signature"); + end_sig += strlen(pkcs7_end); + + if (easy_pkcs7_verify(begin_pkgvul, end_pkgvul - begin_pkgvul, + begin_sig, end_sig - begin_sig, certs_pkg_vulnerabilities, 0)) + errx(EXIT_FAILURE, "Unable to verify PKCS7 signature"); +#else + errx(EXIT_FAILURE, "OpenSSL support is not compiled in"); +#endif +} + +static void +verify_signature(const char *input, size_t input_len) +{ + if (gpg_cmd == NULL && certs_pkg_vulnerabilities == NULL) + errx(EXIT_FAILURE, + "At least GPG or CERTIFICATE_ANCHOR_PKGVULN " + "must be configured"); + if (gpg_cmd != NULL) + inline_gpg_verify(input, input_len, gpg_keyring_pkgvuln); + if (certs_pkg_vulnerabilities != NULL) + verify_signature_pkcs7(input); } static void * @@ -128,9 +135,27 @@ static const char * sha512_hash_finish(void *ctx) { static char hash[SHA512_DIGEST_STRING_LENGTH]; + unsigned char digest[SHA512_DIGEST_LENGTH]; SHA512_CTX *hash_ctx = ctx; + int i; + + SHA512_Final(digest, hash_ctx); + for (i = 0; i < SHA512_DIGEST_LENGTH; ++i) { + unsigned char c; - SHA512_End(hash_ctx, hash); + c = digest[i] / 16; + if (c < 10) + hash[2 * i] = '0' + c; + else + hash[2 * i] = 'a' - 10 + c; + + c = digest[i] % 16; + if (c < 10) + hash[2 * i + 1] = '0' + c; + else + hash[2 * i + 1] = 'a' - 10 + c; + } + hash[2 * i] = '\0'; return hash; } @@ -183,6 +208,7 @@ verify_hash(const char *input, const char *hash_line) const struct hash_algorithm *hash; void *ctx; const char *last_start, *next, *hash_value; + int in_pgp_msg; for (hash = hash_algorithms; hash->name != NULL; ++hash) { if (strncmp(hash_line, hash->name, hash->name_len)) @@ -211,19 +237,27 @@ verify_hash(const char *input, const char *hash_line) errx(EXIT_FAILURE, "Invalid #CHECKSUM"); ctx = (*hash->init)(); + if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) { + input += strlen(pgp_msg_start); + in_pgp_msg = 1; + } else { + in_pgp_msg = 0; + } for (last_start = input; *input != '\0'; input = next) { if ((next = strchr(input, '\n')) == NULL) errx(EXIT_FAILURE, "Missing newline in pkg-vulnerabilities"); ++next; + if (in_pgp_msg && strncmp(input, pgp_msg_end, strlen(pgp_msg_end)) == 0) + break; + if (!in_pgp_msg && strncmp(input, pkcs7_begin, strlen(pkcs7_begin)) == 0) + break; if (*input == '\n' || - strncmp(input, "-----BEGIN", 10) == 0 || strncmp(input, "Hash:", 5) == 0 || strncmp(input, "# $NetBSD", 9) == 0 || strncmp(input, "#CHECKSUM", 9) == 0) { (*hash->update)(ctx, last_start, input - last_start); last_start = next; - } else if (strncmp(input, "Version:", 8) == 0) - break; + } } (*hash->update)(ctx, last_start, input - last_start); hash_value = (*hash->finish)(ctx); @@ -280,27 +314,21 @@ add_vulnerability(struct pkg_vulnerabilities *pv, size_t *allocated, const char *allocated *= 2; else errx(EXIT_FAILURE, "Too many vulnerabilities"); - pv->vulnerability = realloc(pv->vulnerability, + pv->vulnerability = xrealloc(pv->vulnerability, sizeof(char *) * *allocated); - pv->classification = realloc(pv->classification, + pv->classification = xrealloc(pv->classification, sizeof(char *) * *allocated); - pv->advisory = realloc(pv->advisory, + pv->advisory = xrealloc(pv->advisory, sizeof(char *) * *allocated); - if (pv->vulnerability == NULL || - pv->classification == NULL || pv->advisory == NULL) - errx(EXIT_FAILURE, "realloc failed"); } - if ((pv->vulnerability[pv->entries] = malloc(len_pattern + 1)) == NULL) - errx(EXIT_FAILURE, "malloc failed"); + pv->vulnerability[pv->entries] = xmalloc(len_pattern + 1); memcpy(pv->vulnerability[pv->entries], start_pattern, len_pattern); pv->vulnerability[pv->entries][len_pattern] = '\0'; - if ((pv->classification[pv->entries] = malloc(len_class + 1)) == NULL) - errx(EXIT_FAILURE, "malloc failed"); + pv->classification[pv->entries] = xmalloc(len_class + 1); memcpy(pv->classification[pv->entries], start_class, len_class); pv->classification[pv->entries][len_class] = '\0'; - if ((pv->advisory[pv->entries] = malloc(len_url + 1)) == NULL) - errx(EXIT_FAILURE, "malloc failed"); + pv->advisory[pv->entries] = xmalloc(len_url + 1); memcpy(pv->advisory[pv->entries], start_url, len_url); pv->advisory[pv->entries][len_url] = '\0'; @@ -334,8 +362,7 @@ read_pkg_vulnerabilities(const char *path, int ignore_missing, int check_sum) input_len = (size_t)st.st_size; if (input_len < 4) err(EXIT_FAILURE, "Input too short for a pkg_vulnerability file"); - if ((input = malloc(input_len + 1)) == NULL) - err(EXIT_FAILURE, "malloc failed"); + input = xmalloc(input_len + 1); if ((bytes_read = read(fd, input, input_len)) == -1) err(1, "Failed to read input"); if (bytes_read != st.st_size) @@ -361,10 +388,9 @@ parse_pkg_vulnerabilities(const char *input, size_t input_len, int check_sum) char *end; const char *iter, *next; size_t allocated_vulns; + int in_pgp_msg; - pv = malloc(sizeof(*pv)); - if (pv == NULL) - err(EXIT_FAILURE, "malloc failed"); + pv = xmalloc(sizeof(*pv)); allocated_vulns = pv->entries = 0; pv->vulnerability = NULL; @@ -377,14 +403,20 @@ parse_pkg_vulnerabilities(const char *input, size_t input_len, int check_sum) if (check_sum) verify_signature(input, input_len); - for (iter = input; *iter; iter = next) { + if (strncmp(input, pgp_msg_start, strlen(pgp_msg_start)) == 0) { + iter = input + strlen(pgp_msg_start); + in_pgp_msg = 1; + } else { + iter = input; + in_pgp_msg = 0; + } + + for (; *iter; iter = next) { if ((next = strchr(iter, '\n')) == NULL) errx(EXIT_FAILURE, "Missing newline in pkg-vulnerabilities"); ++next; if (*iter == '\0' || *iter == '\n') continue; - if (strncmp(iter, "-----BEGIN", 10) == 0) - continue; if (strncmp(iter, "Hash:", 5) == 0) continue; if (strncmp(iter, "# $NetBSD", 9) == 0) @@ -430,7 +462,9 @@ parse_pkg_vulnerabilities(const char *input, size_t input_len, int check_sum) ++next; if (*iter == '\0' || *iter == '\n') continue; - if (strncmp(iter, "Version:", 5) == 0) + if (in_pgp_msg && strncmp(iter, pgp_msg_end, strlen(pgp_msg_end)) == 0) + break; + if (!in_pgp_msg && strncmp(iter, pkcs7_begin, strlen(pkcs7_begin)) == 0) break; if (*iter == '#' && (iter[1] == '\0' || iter[1] == '\n' || isspace((unsigned char)iter[1]))) @@ -456,15 +490,12 @@ parse_pkg_vulnerabilities(const char *input, size_t input_len, int check_sum) } if (pv->entries != allocated_vulns) { - pv->vulnerability = realloc(pv->vulnerability, + pv->vulnerability = xrealloc(pv->vulnerability, sizeof(char *) * pv->entries); - pv->classification = realloc(pv->classification, + pv->classification = xrealloc(pv->classification, sizeof(char *) * pv->entries); - pv->advisory = realloc(pv->advisory, + pv->advisory = xrealloc(pv->advisory, sizeof(char *) * pv->entries); - if (pv->vulnerability == NULL || - pv->classification == NULL || pv->advisory == NULL) - errx(EXIT_FAILURE, "realloc failed"); } return pv; @@ -485,3 +516,73 @@ free_pkg_vulnerabilities(struct pkg_vulnerabilities *pv) free(pv->advisory); free(pv); } + +static int +check_ignored_entry(struct pkg_vulnerabilities *pv, size_t i) +{ + const char *iter, *next; + size_t entry_len, url_len; + + if (ignore_advisories == NULL) + return 0; + + url_len = strlen(pv->advisory[i]); + + for (iter = ignore_advisories; *iter; iter = next) { + if ((next = strchr(iter, '\n')) == NULL) { + entry_len = strlen(iter); + next = iter + entry_len; + } else { + entry_len = next - iter; + ++next; + } + if (url_len != entry_len) + continue; + if (strncmp(pv->advisory[i], iter, entry_len) == 0) + return 1; + } + return 0; +} + +int +audit_package(struct pkg_vulnerabilities *pv, const char *pkgname, + const char *limit_vul_types, int check_eol, int output_type) +{ + FILE *output = output_type == 1 ? stdout : stderr; + size_t i; + int retval; + + retval = 0; + + for (i = 0; i < pv->entries; ++i) { + if (check_ignored_entry(pv, i)) + continue; + if (limit_vul_types != NULL && + strcmp(limit_vul_types, pv->classification[i])) + continue; + if (!pkg_match(pv->vulnerability[i], pkgname)) + continue; + if (strcmp("eol", pv->classification[i]) == 0) { + if (!check_eol) + continue; + if (output_type == 0) { + puts(pkgname); + continue; + } + fprintf(output, + "Package %s has reached end-of-life (eol), " + "see %s/eol-packages\n", pkgname, + tnf_vulnerability_base); + continue; + } + retval = 1; + if (output_type == 0) { + puts(pkgname); + } else { + fprintf(output, + "Package %s has a %s vulnerability, see %s\n", + pkgname, pv->classification[i], pv->advisory[i]); + } + } + return retval; +} diff --git a/pkgtools/pkg_install/files/lib/xwrapper.c b/pkgtools/pkg_install/files/lib/xwrapper.c new file mode 100644 index 00000000000..75f5fa3108f --- /dev/null +++ b/pkgtools/pkg_install/files/lib/xwrapper.c @@ -0,0 +1,102 @@ +/* $NetBSD: xwrapper.c,v 1.2 2009/02/02 12:35:01 joerg Exp $ */ + +/*- + * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif +#include <nbcompat.h> +#if HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> +#endif +__RCSID("$NetBSD: xwrapper.c,v 1.2 2009/02/02 12:35:01 joerg Exp $"); + +#if HAVE_ERR_H +#include <err.h> +#endif +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "lib.h" + +char * +xasprintf(const char *fmt, ...) +{ + va_list ap; + char *buf; + + va_start(ap, fmt); + if (vasprintf(&buf, fmt, ap) == -1) + err(1, "asprintf failed"); + va_end(ap); + return buf; +} + +void * +xmalloc(size_t len) +{ + void *ptr; + + if ((ptr = malloc(len)) == NULL) + err(1, "malloc failed"); + return ptr; +} + +void * +xcalloc(size_t len, size_t n) +{ + void *ptr; + + if ((ptr = calloc(len, n)) == NULL) + err(1, "calloc failed"); + return ptr; +} + +void * +xrealloc(void *buf, size_t len) +{ + void *ptr; + + if ((ptr = realloc(buf, len)) == NULL) + err(1, "realloc failed"); + return ptr; +} + +char * +xstrdup(const char *str) +{ + char *buf; + + if ((buf = strdup(str)) == NULL) + err(1, "strdup failed"); + return buf; +} |