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
main(int argc,char * argv[])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
quit(int retcode)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
trap(int signo)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
usage(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