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 44 static int options; 45 static keystore_handle_t keystore = NULL; 46 47 static void usage(void); 48 static 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 58 int 59 main(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 212 void 213 quit(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 229 static void 230 trap(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 243 static void 244 usage(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