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 * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 32 */ 33 34 #include <locale.h> 35 #include <libintl.h> 36 #include <stdio.h> 37 #include <signal.h> 38 #include <stdlib.h> 39 #include <unistd.h> 40 #include <string.h> 41 #include <pkgtrans.h> 42 #include <pkglib.h> 43 #include <pkglocs.h> 44 #include <libadm.h> 45 #include <libinst.h> 46 #include <messages.h> 47 48 static int options; 49 static keystore_handle_t keystore = NULL; 50 51 static void usage(void); 52 static void trap(int signo); 53 54 #define KEYSTORE_OPEN "Retrieving signing certificates from keystore <%s>" 55 56 int 57 main(int argc, char *argv[]) 58 { 59 int c; 60 void (*func)(); 61 extern char *optarg; 62 extern int optind; 63 char *keystore_alias = NULL; 64 char *keystore_file = NULL; 65 boolean_t create_sig = B_FALSE; 66 char *homedir = NULL; 67 PKG_ERR *err; 68 int ret, len; 69 70 (void) setlocale(LC_ALL, ""); 71 72 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 73 #define TEXT_DOMAIN "SYS_TEST" 74 #endif 75 (void) textdomain(TEXT_DOMAIN); 76 77 (void) set_prog_name(argv[0]); 78 79 while ((c = getopt(argc, argv, "ga:P:k:snio?")) != EOF) { 80 switch (c) { 81 case 'n': 82 options |= PT_RENAME; 83 break; 84 85 case 'i': 86 options |= PT_INFO_ONLY; 87 break; 88 89 case 'o': 90 options |= PT_OVERWRITE; 91 break; 92 93 case 's': 94 options |= PT_ODTSTREAM; 95 break; 96 97 case 'g': 98 /* this should eventually be a PT_ option */ 99 create_sig = B_TRUE; 100 break; 101 102 case 'k': 103 keystore_file = optarg; 104 break; 105 106 case 'a': 107 keystore_alias = optarg; 108 break; 109 110 case 'P': 111 set_passphrase_passarg(optarg); 112 if (ci_strneq(optarg, "pass:", 5)) { 113 /* 114 * passwords on the command line are highly 115 * insecure. complain. 116 */ 117 logerr(PASSWD_CMDLINE, "pass:<pass>"); 118 } 119 break; 120 121 default: 122 usage(); 123 return (1); 124 } 125 } 126 func = signal(SIGINT, trap); 127 if (func != SIG_DFL) 128 (void) signal(SIGINT, func); 129 (void) signal(SIGHUP, trap); 130 (void) signal(SIGQUIT, trap); 131 (void) signal(SIGTERM, trap); 132 (void) signal(SIGPIPE, trap); 133 (void) signal(SIGPWR, trap); 134 135 if ((argc-optind) < 2) { 136 usage(); 137 return (1); 138 } 139 140 if (create_sig) { 141 sec_init(); 142 err = pkgerr_new(); 143 144 /* figure out which keystore to use */ 145 if (keystore_file == NULL) { 146 if (geteuid() == 0) { 147 /* we are superuser, so use their keystore */ 148 keystore_file = PKGSEC; 149 150 } else if ((homedir = getenv("HOME")) == NULL) { 151 /* 152 * not superuser, but no home dir, so 153 * use superuser's keystore 154 */ 155 keystore_file = PKGSEC; 156 157 } else if (asprintf(&keystore_file, "%s/.pkg/security", 158 homedir) < 0) { 159 logerr(ERR_MEM); 160 quit(1); 161 } 162 } 163 164 logerr(gettext(KEYSTORE_OPEN), keystore_file); 165 166 set_passphrase_prompt(MSG_PASSPROMPT); 167 168 /* open keystore for reading */ 169 if (open_keystore(err, keystore_file, get_prog_name(), 170 pkg_passphrase_cb, KEYSTORE_DFLT_FLAGS, &keystore) != 0) { 171 pkgerr(err); 172 pkgerr_free(err); 173 quit(1); 174 } 175 176 } else { 177 /* no signature, so don't use a keystore */ 178 keystore = NULL; 179 } 180 181 ret = pkgtrans(flex_device(argv[optind], 1), 182 flex_device(argv[optind+1], 1), &argv[optind+2], options, 183 keystore, keystore_alias); 184 185 if (create_sig) { 186 /* close keystore */ 187 if (close_keystore(err, keystore, NULL) != 0) { 188 pkgerr(err); 189 pkgerr_free(err); 190 quit(1); 191 } 192 keystore = NULL; 193 } 194 195 quit(ret); 196 /*NOTREACHED*/ 197 } 198 199 void 200 quit(int retcode) 201 { 202 PKG_ERR *err; 203 204 err = pkgerr_new(); 205 (void) signal(SIGINT, SIG_IGN); 206 (void) signal(SIGHUP, SIG_IGN); 207 (void) ds_close(1); 208 (void) pkghead(NULL); 209 if (keystore != NULL) { 210 (void) close_keystore(err, keystore, NULL); 211 pkgerr_free(err); 212 } 213 exit(retcode); 214 } 215 216 static void 217 trap(int signo) 218 { 219 (void) signal(SIGINT, SIG_IGN); 220 (void) signal(SIGHUP, SIG_IGN); 221 222 if (signo == SIGINT) { 223 progerr(gettext("aborted at user request.\n")); 224 quit(3); 225 } 226 progerr(gettext("aborted by signal %d\n"), signo); 227 quit(1); 228 } 229 230 static void 231 usage(void) 232 { 233 (void) fprintf(stderr, 234 gettext("usage: %s [-ionsg] [-k keystore] " \ 235 "[-a alias] [-P password] srcdev dstdev [pkg [pkg...]]\n"), 236 get_prog_name()); 237 } 238