main.c revision 9781:ccf49524d5dc
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22/* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28/* All Rights Reserved */ 29 30 31#include <locale.h> 32#include <libintl.h> 33#include <stdio.h> 34#include <signal.h> 35#include <stdlib.h> 36#include <unistd.h> 37#include <string.h> 38#include <pkgtrans.h> 39#include <pkglib.h> 40#include <pkglocs.h> 41#include <libadm.h> 42#include <libinst.h> 43 44static int options; 45static keystore_handle_t keystore = NULL; 46 47static void usage(void); 48static void trap(int signo); 49 50#define PASSWD_CMDLINE \ 51 "## WARNING: USING <%s> MAKES PASSWORD " \ 52 "VISIBLE TO ALL USERS." 53 54#define PASSPHRASE_PROMPT "Enter keystore password:" 55#define KEYSTORE_OPEN "Retrieving signing certificates from keystore <%s>" 56#define PARAM_LEN "Parameter <%s> too long" 57 58int 59main(int argc, char *argv[]) 60{ 61 int c; 62 void (*func)(); 63 extern char *optarg; 64 extern int optind; 65 char *keystore_alias = NULL; 66 char *keystore_file = NULL; 67 boolean_t create_sig = B_FALSE; 68 char *homedir = NULL; 69 PKG_ERR *err; 70 int ret, len, homelen; 71 72 (void) setlocale(LC_ALL, ""); 73 74#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 75#define TEXT_DOMAIN "SYS_TEST" 76#endif 77 (void) textdomain(TEXT_DOMAIN); 78 79 (void) set_prog_name(argv[0]); 80 81 while ((c = getopt(argc, argv, "ga:P:k:snio?")) != EOF) { 82 switch (c) { 83 case 'n': 84 options |= PT_RENAME; 85 break; 86 87 case 'i': 88 options |= PT_INFO_ONLY; 89 break; 90 91 case 'o': 92 options |= PT_OVERWRITE; 93 break; 94 95 case 's': 96 options |= PT_ODTSTREAM; 97 break; 98 99 case 'g': 100 /* this should eventually be a PT_ option */ 101 create_sig = B_TRUE; 102 break; 103 104 case 'k': 105 keystore_file = optarg; 106 break; 107 108 case 'a': 109 keystore_alias = optarg; 110 break; 111 112 case 'P': 113 set_passphrase_passarg(optarg); 114 if (ci_strneq(optarg, "pass:", 5)) { 115 /* 116 * passwords on the command line are highly 117 * insecure. complain. 118 */ 119 logerr(gettext(PASSWD_CMDLINE), "pass:<pass>"); 120 } 121 break; 122 123 default: 124 usage(); 125 return (1); 126 } 127 } 128 func = signal(SIGINT, trap); 129 if (func != SIG_DFL) 130 (void) signal(SIGINT, func); 131 (void) signal(SIGHUP, trap); 132 (void) signal(SIGQUIT, trap); 133 (void) signal(SIGTERM, trap); 134 (void) signal(SIGPIPE, trap); 135#ifndef SUNOS41 136 (void) signal(SIGPWR, trap); 137#endif 138 139 if ((argc-optind) < 2) { 140 usage(); 141 return (1); 142 } 143 144 if (create_sig) { 145 sec_init(); 146 err = pkgerr_new(); 147 148 /* figure out which keystore to use */ 149 if (keystore_file == NULL) { 150 if (geteuid() == 0) { 151 /* we are superuser, so use their keystore */ 152 keystore_file = PKGSEC; 153 } else { 154 if ((homedir = getenv("HOME")) == NULL) { 155 /* 156 * not superuser, but no home dir, so 157 * use superuser's keystore 158 */ 159 keystore_file = PKGSEC; 160 } else { 161 /* $HOME/.pkg/security\0 */ 162 homelen = strlen(homedir) + 15; 163 keystore_file = 164 malloc(strlen(homedir) + 15); 165 if (((len = snprintf(keystore_file, 166 homelen, "%s/%s", homedir, 167 ".pkg/security")) < 0) || 168 (len >= homelen)) { 169 logerr(gettext(PARAM_LEN), 170 "$HOME"); 171 quit(1); 172 } 173 } 174 } 175 } 176 177 logerr(gettext(KEYSTORE_OPEN), keystore_file); 178 179 set_passphrase_prompt(gettext(PASSPHRASE_PROMPT)); 180 181 /* open keystore for reading */ 182 if (open_keystore(err, keystore_file, get_prog_name(), 183 pkg_passphrase_cb, KEYSTORE_DFLT_FLAGS, &keystore) != 0) { 184 pkgerr(err); 185 pkgerr_free(err); 186 quit(1); 187 } 188 189 } else { 190 /* no signature, so don't use a keystore */ 191 keystore = NULL; 192 } 193 194 ret = pkgtrans(flex_device(argv[optind], 1), 195 flex_device(argv[optind+1], 1), &argv[optind+2], options, 196 keystore, keystore_alias); 197 198 if (create_sig) { 199 /* close keystore */ 200 if (close_keystore(err, keystore, NULL) != 0) { 201 pkgerr(err); 202 pkgerr_free(err); 203 quit(1); 204 } 205 keystore = NULL; 206 } 207 208 quit(ret); 209 /*NOTREACHED*/ 210} 211 212void 213quit(int retcode) 214{ 215 PKG_ERR *err; 216 217 err = pkgerr_new(); 218 (void) signal(SIGINT, SIG_IGN); 219 (void) signal(SIGHUP, SIG_IGN); 220 (void) ds_close(1); 221 (void) pkghead(NULL); 222 if (keystore != NULL) { 223 (void) close_keystore(err, keystore, NULL); 224 pkgerr_free(err); 225 } 226 exit(retcode); 227} 228 229static void 230trap(int signo) 231{ 232 (void) signal(SIGINT, SIG_IGN); 233 (void) signal(SIGHUP, SIG_IGN); 234 235 if (signo == SIGINT) { 236 progerr(gettext("aborted at user request.\n")); 237 quit(3); 238 } 239 progerr(gettext("aborted by signal %d\n"), signo); 240 quit(1); 241} 242 243static void 244usage(void) 245{ 246 (void) fprintf(stderr, 247 gettext("usage: %s [-ionsg] [-k keystore] " \ 248 "[-a alias] [-P password] srcdev dstdev [pkg [pkg...]]\n"), 249 get_prog_name()); 250} 251