xref: /titanic_52/usr/src/cmd/svr4pkg/pkgadm/listcert.c (revision 2bc987325e3ded1865bff043128661815c4690b9)
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 
28 #include <stdio.h>
29 #include <stdarg.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <unistd.h>
34 #include <signal.h>
35 #include <locale.h>
36 #include <sys/param.h>
37 #include <openssl/bio.h>
38 
39 #include <libinst.h>
40 #include <pkglib.h>
41 #include <pkgerr.h>
42 #include <keystore.h>
43 #include "pkgadm.h"
44 #include "pkgadm_msgs.h"
45 
46 /*
47  * Name:	listcert
48  * Desc:  Lists one or more certificates from the keystore
49  * Syntax:	listcert [-a app] [-f format] [-k keystore] \
50  *	[-n name] [-o outfile] [-P passarg] [-R altroot]
51  */
52 int
53 listcert(int argc, char **argv)
54 {
55 	int				i;
56 	char				keystore_file[MAXPATHLEN] = "";
57 	char				*keystore_base = NULL;
58 	char				*homedir;
59 	char				*passarg = NULL;
60 	char				*altroot = NULL;
61 	char				*prog = NULL;
62 	char				*format_str = NULL;
63 	keystore_encoding_format_t	format;
64 	char				*alias = NULL;
65 	char				*outfile_str = NULL;
66 	FILE				*outfile = NULL;
67 	int				ret = 1;
68 	PKG_ERR				*err = NULL;
69 	keystore_handle_t		keystore = NULL;
70 
71 	while ((i = getopt(argc, argv, ":a:f:k:n:o:P:R:")) != EOF) {
72 		switch (i) {
73 		case 'a':
74 			prog = optarg;
75 			break;
76 		case 'f':
77 			format_str = optarg;
78 			break;
79 		case 'k':
80 			keystore_base = optarg;
81 			break;
82 		case 'n':
83 			alias = optarg;
84 			break;
85 		case 'o':
86 			outfile_str = optarg;
87 			break;
88 		case 'P':
89 			passarg = optarg;
90 			break;
91 		case 'R':
92 			altroot = optarg;
93 			break;
94 		case ':':
95 			log_msg(LOG_MSG_ERR, MSG_MISSING_OPERAND, optopt);
96 			/* fallthrough intentional */
97 		case '?':
98 		default:
99 			log_msg(LOG_MSG_ERR, MSG_USAGE);
100 			goto cleanup;
101 		}
102 	}
103 
104 	/* should be no arguments left */
105 	if ((argc-optind) > 0) {
106 		log_msg(LOG_MSG_ERR, MSG_USAGE);
107 		goto cleanup;
108 	}
109 
110 	/* figure out format */
111 	if (format_str == NULL) {
112 		format = KEYSTORE_FORMAT_TEXT;
113 	} else {
114 		if (ci_streq(format_str, "text")) {
115 			format = KEYSTORE_FORMAT_TEXT;
116 		} else if (ci_streq(format_str, "pem")) {
117 			format = KEYSTORE_FORMAT_PEM;
118 		} else if (ci_streq(format_str, "der")) {
119 			format = KEYSTORE_FORMAT_DER;
120 		} else {
121 			log_msg(LOG_MSG_ERR, MSG_BAD_FORMAT, format_str);
122 			goto cleanup;
123 		}
124 	}
125 
126 	/* open output file */
127 	if (outfile_str == NULL) {
128 		outfile = stdout;
129 		outfile_str = "stdout";
130 	} else {
131 		if ((outfile = fopen(outfile_str, "w+")) == NULL) {
132 			log_msg(LOG_MSG_ERR, MSG_OPEN_WRITE, outfile_str);
133 			goto cleanup;
134 		}
135 	}
136 
137 	/* set up proper keystore */
138 	if (altroot != NULL) {
139 	    if (strlcpy(keystore_file, altroot, MAXPATHLEN) >= MAXPATHLEN) {
140 		log_msg(LOG_MSG_ERR, MSG_TOO_LONG, altroot);
141 		goto cleanup;
142 	    }
143 
144 	    if (strlcat(keystore_file, "/", MAXPATHLEN) >= MAXPATHLEN) {
145 		log_msg(LOG_MSG_ERR, MSG_TOO_LONG, altroot);
146 		goto cleanup;
147 	    }
148 	}
149 
150 	if (keystore_base == NULL) {
151 		if (geteuid() == 0 || altroot != NULL) {
152 				/*
153 				 * If we have an alternate
154 				 * root, then we have no choice but to use
155 				 * root's keystore on that alternate root,
156 				 * since there is no way to resolve a
157 				 * user's home dir given an alternate root
158 				 */
159 			if (strlcat(keystore_file, PKGSEC,
160 			    MAXPATHLEN) >= MAXPATHLEN) {
161 				log_msg(LOG_MSG_ERR, MSG_TOO_LONG,
162 				    keystore_file);
163 				goto cleanup;
164 			}
165 		} else {
166 			if ((homedir = getenv("HOME")) == NULL) {
167 				/*
168 				 * not superuser, but no home dir, so
169 				 * use superuser's keystore
170 				 */
171 				if (strlcat(keystore_file, PKGSEC,
172 				    MAXPATHLEN) >= MAXPATHLEN) {
173 					log_msg(LOG_MSG_ERR, MSG_TOO_LONG,
174 					    keystore_file);
175 					goto cleanup;
176 				}
177 			} else {
178 				if (strlcat(keystore_file, homedir,
179 				    MAXPATHLEN) >= MAXPATHLEN) {
180 					log_msg(LOG_MSG_ERR, MSG_TOO_LONG,
181 					    homedir);
182 					goto cleanup;
183 				}
184 				if (strlcat(keystore_file, "/.pkg/security",
185 				    MAXPATHLEN) >= MAXPATHLEN) {
186 					log_msg(LOG_MSG_ERR, MSG_TOO_LONG,
187 					    keystore_file);
188 					goto cleanup;
189 				}
190 			}
191 		}
192 	} else {
193 		if (strlcat(keystore_file, keystore_base,
194 		    MAXPATHLEN) >= MAXPATHLEN) {
195 		    log_msg(LOG_MSG_ERR, MSG_TOO_LONG,
196 			keystore_base);
197 		    goto cleanup;
198 		}
199 	}
200 	err = pkgerr_new();
201 
202 	/* now load the key store */
203 	log_msg(LOG_MSG_DEBUG, "Loading keystore <%s>", keystore_file);
204 
205 	set_passphrase_prompt(MSG_KEYSTORE_PASSPROMPT);
206 	set_passphrase_passarg(passarg);
207 	if (open_keystore(err, keystore_file, prog,
208 	    pkg_passphrase_cb, KEYSTORE_DFLT_FLAGS,
209 	    &keystore) != 0) {
210 		log_pkgerr(LOG_MSG_ERR, err);
211 		log_msg(LOG_MSG_ERR, MSG_PRINT, outfile_str);
212 		goto cleanup;
213 	}
214 
215 	/* list the certs */
216 	log_msg(LOG_MSG_DEBUG, "Listing certificates");
217 	if (print_certs(err, keystore, alias, format, outfile) != 0) {
218 		log_pkgerr(LOG_MSG_ERR, err);
219 	    log_msg(LOG_MSG_ERR, MSG_PRINT, outfile_str);
220 		goto cleanup;
221 	}
222 
223 	/* now close it out */
224 	log_msg(LOG_MSG_DEBUG, "Closing keystore");
225 	set_passphrase_prompt(MSG_KEYSTORE_PASSOUTPROMPT);
226 	set_passphrase_passarg(passarg);
227 	if (close_keystore(err, keystore, pkg_passphrase_cb) != 0) {
228 		log_pkgerr(LOG_MSG_ERR, err);
229 		log_msg(LOG_MSG_ERR, MSG_PRINT, outfile_str);
230 		goto cleanup;
231 	}
232 
233 	/* everything worked */
234 	ret = 0;
235 
236 	/* fallthrough intentional */
237 cleanup:
238 	if (outfile != NULL)
239 		(void) fclose(outfile);
240 
241 	if (err != NULL)
242 		pkgerr_free(err);
243 
244 	return (ret);
245 }
246