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  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
22  * Use is subject to license terms.
23  */
24 
25 #pragma ident	"%Z%%M%	%I%	%E% SMI"
26 
27 #include <stdio.h>
28 #include <strings.h>
29 #include <ctype.h>
30 #include <libgen.h>
31 #include <libintl.h>
32 #include <errno.h>
33 #include <sys/stat.h>
34 #include <kmfapiP.h>
35 #include "util.h"
36 
37 #define	LIB_NSS_PATH	"/usr/lib/mps/libnss3.so"
38 #define	LIB_NSPR_PATH	"/usr/lib/mps/libnspr4.so"
39 
40 static void
41 show_policy(KMF_POLICY_RECORD *plc)
42 {
43 	int i;
44 	if (plc == NULL)
45 		return;
46 
47 	(void) printf("Name: %s\n", plc->name);
48 
49 	(void) printf(gettext("Ignore Date: %s\n"),
50 	    plc->ignore_date ? gettext("true") : gettext("false"));
51 
52 	(void) printf(gettext("Ignore Unknown EKUs: %s\n"),
53 	    plc->ignore_unknown_ekus ? gettext("true") : gettext("false"));
54 
55 	(void) printf(gettext("Ignore TA: %s\n"),
56 	    plc->ignore_trust_anchor ? gettext("true") : gettext("false"));
57 
58 	(void) printf(gettext("Validity Adjusted Time: %s\n"),
59 	    plc->validity_adjusttime ? plc->validity_adjusttime : "<null>");
60 
61 	if (plc->ta_name == NULL && plc->ta_serial == NULL) {
62 		(void) printf(gettext("Trust Anchor Certificate: <null>\n"));
63 	} else {
64 		(void) printf(gettext("Trust Anchor Certificate:\n"));
65 		(void) printf(gettext("\tName: %s\n"),
66 		    plc->ta_name ? plc->ta_name : "<null>");
67 		(void) printf(gettext("\tSerial Number: %s\n"),
68 		    plc->ta_serial ? plc->ta_serial : "<null>");
69 	}
70 
71 	if (plc->ku_bits != 0) {
72 		(void) printf(gettext("Key Usage Bits: "));
73 		for (i = KULOWBIT; i <= KUHIGHBIT; i++) {
74 			char *s = kmf_ku_to_string(
75 			    (plc->ku_bits & (1<<i)));
76 			if (s != NULL) {
77 				(void) printf("%s ", s);
78 			}
79 		}
80 		(void) printf("\n");
81 	} else {
82 		(void) printf(gettext("Key Usage Bits: 0\n"));
83 	}
84 
85 	if (plc->eku_set.eku_count > 0) {
86 		(void) printf(gettext("Extended Key Usage Values:\n"));
87 		for (i = 0; i < plc->eku_set.eku_count; i++) {
88 			char *s = kmf_oid_to_ekuname(
89 			    &plc->eku_set.ekulist[i]);
90 			(void) printf("\t%s\t(%s)\n",
91 			    kmf_oid_to_string(&plc->eku_set.ekulist[i]),
92 			    s ? s : "unknown");
93 		}
94 	} else {
95 		(void) printf(gettext("Extended Key Usage Values: <null>\n"));
96 	}
97 
98 	(void) printf(gettext("Validation Policy Information:\n"));
99 
100 	if (plc->revocation & KMF_REVOCATION_METHOD_OCSP) {
101 		(void) printf(gettext("    OCSP:\n"));
102 
103 		(void) printf(gettext("\tResponder URI: %s\n"),
104 		    plc->VAL_OCSP_BASIC.responderURI ?
105 		    plc->VAL_OCSP_BASIC.responderURI : "<null>");
106 
107 		(void) printf(gettext("\tProxy: %s\n"),
108 		    plc->VAL_OCSP_BASIC.proxy ?
109 		    plc->VAL_OCSP_BASIC.proxy : "<null>");
110 
111 		(void) printf(gettext("\tUse ResponderURI from Certificate: "
112 		    "%s\n"), plc->VAL_OCSP_BASIC.uri_from_cert ?
113 		    gettext("true") : gettext("false"));
114 
115 		(void) printf(gettext("\tResponse lifetime: %s\n"),
116 		    plc->VAL_OCSP_BASIC.response_lifetime ?
117 		    plc->VAL_OCSP_BASIC.response_lifetime : "<null>");
118 
119 		(void) printf(gettext("\tIgnore Response signature: %s\n"),
120 		    plc->VAL_OCSP_BASIC.ignore_response_sign ?
121 		    gettext("true") : gettext("false"));
122 
123 		if (!plc->VAL_OCSP.has_resp_cert) {
124 			(void) printf(gettext("\tResponder Certificate:"
125 			    " <null>\n"));
126 		} else {
127 			(void) printf(gettext("\tResponder Certificate:\n"));
128 			(void) printf(gettext("\t\tName: %s\n"),
129 			    plc->VAL_OCSP_RESP_CERT.name ?
130 			    plc->VAL_OCSP_RESP_CERT.name : "<null>");
131 			(void) printf(gettext("\t\tSerial: %s\n"),
132 			    plc->VAL_OCSP_RESP_CERT.serial ?
133 			    plc->VAL_OCSP_RESP_CERT.serial : "<null>");
134 		}
135 	}
136 
137 	if (plc->revocation & KMF_REVOCATION_METHOD_CRL) {
138 		(void) printf(gettext("    CRL:\n"));
139 
140 		(void) printf(gettext("\tBase filename: %s\n"),
141 		    plc->validation_info.crl_info.basefilename ?
142 		    plc->validation_info.crl_info.basefilename : "<null>");
143 
144 		(void) printf(gettext("\tDirectory: %s\n"),
145 		    plc->validation_info.crl_info.directory ?
146 		    plc->validation_info.crl_info.directory : "<null>");
147 
148 		(void) printf(gettext("\tDownload and cache CRL: %s\n"),
149 		    plc->validation_info.crl_info.get_crl_uri ?
150 		    gettext("true") : gettext("false"));
151 
152 		(void) printf(gettext("\tProxy: %s\n"),
153 		    plc->validation_info.crl_info.proxy ?
154 		    plc->validation_info.crl_info.proxy : "<null>");
155 
156 		(void) printf(gettext("\tIgnore CRL signature: %s\n"),
157 		    plc->validation_info.crl_info.ignore_crl_sign ?
158 		    gettext("true") : gettext("false"));
159 
160 		(void) printf(gettext("\tIgnore CRL validity date: %s\n"),
161 		    plc->validation_info.crl_info.ignore_crl_date ?
162 		    gettext("true") : gettext("false"));
163 	}
164 
165 	(void) printf("\n");
166 }
167 
168 void
169 show_plugin(void)
170 {
171 	conf_entrylist_t *phead = NULL;
172 	struct stat 	statbuf;
173 
174 	(void) printf(gettext("KMF plugin information:\n"));
175 	(void) printf(gettext("-----------------------\n"));
176 
177 	/* List the built-in plugins */
178 	(void) printf("pkcs11:kmf_pkcs11.so.1 (built-in)\n");
179 	(void) printf("file:kmf_openssl.so.1 (built-in)\n");
180 
181 	/*
182 	 * If the NSS libraries are not installed in the system,
183 	 * then we will not show the nss plugin either.
184 	 */
185 	if (stat(LIB_NSS_PATH, &statbuf) == 0 &&
186 	    stat(LIB_NSPR_PATH, &statbuf) == 0) {
187 		(void) printf("nss:kmf_nss.so.1 (built-in)\n");
188 	}
189 
190 	/* List non-default plugins, if there is any. */
191 	if (get_entrylist(&phead) == KMF_OK) {
192 		while (phead != NULL) {
193 			(void) printf("%s:%s", phead->entry->keystore,
194 			    phead->entry->modulepath);
195 
196 			if (phead->entry->option == NULL)
197 				(void) printf("\n");
198 			else
199 				(void) printf(";option=%s\n",
200 				    phead->entry->option);
201 			phead = phead->next;
202 		}
203 		free_entrylist(phead);
204 	}
205 }
206 
207 
208 int
209 kc_list(int argc, char *argv[])
210 {
211 	int 		rv = KC_OK;
212 	int		opt, found = 0;
213 	extern int	optind_av;
214 	extern char	*optarg_av;
215 	char		*filename = NULL;
216 	char		*policyname = NULL;
217 	POLICY_LIST	*plclist = NULL, *pnode;
218 	int		sanity_err = 0;
219 	boolean_t	list_plugin = B_FALSE;
220 
221 	while ((opt = getopt_av(argc, argv, "i:(dbfile)p:(policy)m(plugin)"))
222 	    != EOF) {
223 		switch (opt) {
224 		case 'i':
225 			if (list_plugin)
226 				rv = KC_ERR_USAGE;
227 			else {
228 				filename = get_string(optarg_av, &rv);
229 				if (filename == NULL) {
230 					(void) fprintf(stderr,
231 					    gettext("Error dbfile input.\n"));
232 				}
233 			}
234 			break;
235 		case 'p':
236 			if (list_plugin)
237 				rv = KC_ERR_USAGE;
238 			else {
239 				policyname = get_string(optarg_av, &rv);
240 				if (policyname == NULL) {
241 					(void) fprintf(stderr,
242 					    gettext("Error policy name.\n"));
243 				}
244 			}
245 			break;
246 		case 'm':
247 			list_plugin = B_TRUE;
248 			break;
249 		default:
250 			(void) fprintf(stderr,
251 			    gettext("Error input option.\n"));
252 			rv = KC_ERR_USAGE;
253 			break;
254 		}
255 		if (rv != KC_OK)
256 			goto out;
257 	}
258 
259 	/* No additional args allowed. */
260 	argc -= optind_av;
261 	if (argc) {
262 		(void) fprintf(stderr,
263 		    gettext("Error input option\n"));
264 		rv = KC_ERR_USAGE;
265 		goto out;
266 	}
267 
268 	if (list_plugin) {
269 		show_plugin();
270 		goto out;
271 	}
272 
273 	if (filename == NULL) {
274 		filename = strdup(KMF_DEFAULT_POLICY_FILE);
275 		if (filename == NULL) {
276 			rv = KC_ERR_MEMORY;
277 			goto out;
278 		}
279 	}
280 
281 	/* Check the access permission of the policy DB */
282 	if (access(filename, R_OK) < 0) {
283 		int err = errno;
284 		(void) fprintf(stderr,
285 		    gettext("Cannot access \"%s\" for list - %s\n"), filename,
286 		    strerror(err));
287 		rv = KC_ERR_ACCESS;
288 		goto out;
289 	}
290 
291 	rv = load_policies(filename, &plclist);
292 	if (rv != KMF_OK) {
293 		goto out;
294 	}
295 
296 	pnode = plclist;
297 	while (pnode != NULL) {
298 		if (policyname == NULL ||
299 		    strcmp(policyname, pnode->plc.name) == 0) {
300 			KMF_POLICY_RECORD *plc = &pnode->plc;
301 
302 			found++;
303 			rv = kmf_verify_policy(plc);
304 			if (rv != KMF_OK) {
305 				(void) fprintf(stderr, gettext(
306 				    "Policy Name: '%s' is invalid\n"),
307 				    plc->name);
308 				sanity_err++;
309 			} else {
310 				show_policy(&pnode->plc);
311 			}
312 		}
313 		pnode = pnode->next;
314 	}
315 
316 	free_policy_list(plclist);
317 
318 	if (!found) {
319 		if (policyname)
320 			(void) fprintf(stderr, gettext(
321 			    "Cannot find policy '%s'\n"), policyname);
322 		else
323 			(void) fprintf(stderr, gettext("Cannot find "
324 			    "any policies to display\n"));
325 		rv = KC_ERR_FIND_POLICY;
326 	} else if (sanity_err) {
327 		rv = KC_ERR_VERIFY_POLICY;
328 	}
329 
330 out:
331 
332 	if (filename != NULL)
333 		free(filename);
334 
335 	if (policyname != NULL)
336 		free(policyname);
337 
338 	return (rv);
339 }
340