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 (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
22 */
23
24#include <stdio.h>
25#include <strings.h>
26#include <ctype.h>
27#include <libgen.h>
28#include <libintl.h>
29#include <errno.h>
30#include <sys/stat.h>
31#include <kmfapiP.h>
32#include "util.h"
33
34#define	LIB_NSS_PATH	"/usr/lib/mps/libnss3.so"
35#define	LIB_NSPR_PATH	"/usr/lib/mps/libnspr4.so"
36
37static void
38show_policy(KMF_POLICY_RECORD *plc)
39{
40	int i;
41	if (plc == NULL)
42		return;
43
44	(void) printf("Name: %s\n", plc->name);
45
46	(void) printf(gettext("Ignore Date: %s\n"),
47	    plc->ignore_date ? gettext("true") : gettext("false"));
48
49	(void) printf(gettext("Ignore Unknown EKUs: %s\n"),
50	    plc->ignore_unknown_ekus ? gettext("true") : gettext("false"));
51
52	(void) printf(gettext("Ignore TA: %s\n"),
53	    plc->ignore_trust_anchor ? gettext("true") : gettext("false"));
54
55	(void) printf(gettext("Validity Adjusted Time: %s\n"),
56	    plc->validity_adjusttime ? plc->validity_adjusttime : "<null>");
57
58	if (plc->ta_name == NULL && plc->ta_serial == NULL) {
59		(void) printf(gettext("Trust Anchor Certificate: <null>\n"));
60	} else if (strcasecmp(plc->ta_name, "search") == 0) {
61		(void) printf(gettext("Trust Anchor Certificate: "
62		    "Search by Issuer\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	(void) printf(gettext("Mapper name: %s\n"),
165	    plc->mapper.mapname ? plc->mapper.mapname : "<null>");
166	(void) printf(gettext("Mapper pathname: %s\n"),
167	    plc->mapper.pathname ? plc->mapper.pathname : "<null>");
168	(void) printf(gettext("Mapper directory: %s\n"),
169	    plc->mapper.dir ? plc->mapper.dir : "<null>");
170	(void) printf(gettext("Mapper options: %s\n"),
171	    plc->mapper.options ? plc->mapper.options : "<null>");
172
173	(void) printf("\n");
174}
175
176void
177show_plugin(void)
178{
179	conf_entrylist_t *phead = NULL;
180	struct stat 	statbuf;
181
182	(void) printf(gettext("KMF plugin information:\n"));
183	(void) printf(gettext("-----------------------\n"));
184
185	/* List the built-in plugins */
186	(void) printf("pkcs11:kmf_pkcs11.so.1 (built-in)\n");
187	(void) printf("file:kmf_openssl.so.1 (built-in)\n");
188
189	/*
190	 * If the NSS libraries are not installed in the system,
191	 * then we will not show the nss plugin either.
192	 */
193	if (stat(LIB_NSS_PATH, &statbuf) == 0 &&
194	    stat(LIB_NSPR_PATH, &statbuf) == 0) {
195		(void) printf("nss:kmf_nss.so.1 (built-in)\n");
196	}
197
198	/* List non-default plugins, if there is any. */
199	if (get_entrylist(&phead) == KMF_OK) {
200		while (phead != NULL) {
201			(void) printf("%s:%s", phead->entry->keystore,
202			    phead->entry->modulepath);
203
204			if (phead->entry->option == NULL)
205				(void) printf("\n");
206			else
207				(void) printf(";option=%s\n",
208				    phead->entry->option);
209			phead = phead->next;
210		}
211		free_entrylist(phead);
212	}
213}
214
215
216int
217kc_list(int argc, char *argv[])
218{
219	int 		rv = KC_OK;
220	int		opt, found = 0;
221	extern int	optind_av;
222	extern char	*optarg_av;
223	char		*filename = NULL;
224	char		*policyname = NULL;
225	POLICY_LIST	*plclist = NULL, *pnode;
226	int		sanity_err = 0;
227	boolean_t	list_plugin = B_FALSE;
228
229	while ((opt = getopt_av(argc, argv, "i:(dbfile)p:(policy)m(plugin)"))
230	    != EOF) {
231		switch (opt) {
232		case 'i':
233			if (list_plugin)
234				rv = KC_ERR_USAGE;
235			else {
236				filename = get_string(optarg_av, &rv);
237				if (filename == NULL) {
238					(void) fprintf(stderr,
239					    gettext("Error dbfile input.\n"));
240				}
241			}
242			break;
243		case 'p':
244			if (list_plugin)
245				rv = KC_ERR_USAGE;
246			else {
247				policyname = get_string(optarg_av, &rv);
248				if (policyname == NULL) {
249					(void) fprintf(stderr,
250					    gettext("Error policy name.\n"));
251				}
252			}
253			break;
254		case 'm':
255			list_plugin = B_TRUE;
256			break;
257		default:
258			(void) fprintf(stderr,
259			    gettext("Error input option.\n"));
260			rv = KC_ERR_USAGE;
261			break;
262		}
263		if (rv != KC_OK)
264			goto out;
265	}
266
267	/* No additional args allowed. */
268	argc -= optind_av;
269	if (argc) {
270		(void) fprintf(stderr,
271		    gettext("Error input option\n"));
272		rv = KC_ERR_USAGE;
273		goto out;
274	}
275
276	if (list_plugin) {
277		show_plugin();
278		goto out;
279	}
280
281	if (filename == NULL) {
282		filename = strdup(KMF_DEFAULT_POLICY_FILE);
283		if (filename == NULL) {
284			rv = KC_ERR_MEMORY;
285			goto out;
286		}
287	}
288
289	/* Check the access permission of the policy DB */
290	if (access(filename, R_OK) < 0) {
291		int err = errno;
292		(void) fprintf(stderr,
293		    gettext("Cannot access \"%s\" for list - %s\n"), filename,
294		    strerror(err));
295		rv = KC_ERR_ACCESS;
296		goto out;
297	}
298
299	rv = load_policies(filename, &plclist);
300	if (rv != KMF_OK) {
301		goto out;
302	}
303
304	pnode = plclist;
305	while (pnode != NULL) {
306		if (policyname == NULL ||
307		    strcmp(policyname, pnode->plc.name) == 0) {
308			KMF_POLICY_RECORD *plc = &pnode->plc;
309
310			found++;
311			rv = kmf_verify_policy(plc);
312			if (rv != KMF_OK) {
313				(void) fprintf(stderr, gettext(
314				    "Policy Name: '%s' is invalid\n"),
315				    plc->name);
316				sanity_err++;
317			} else {
318				show_policy(&pnode->plc);
319			}
320		}
321		pnode = pnode->next;
322	}
323
324	free_policy_list(plclist);
325
326	if (!found) {
327		if (policyname)
328			(void) fprintf(stderr, gettext(
329			    "Cannot find policy '%s'\n"), policyname);
330		else
331			(void) fprintf(stderr, gettext("Cannot find "
332			    "any policies to display\n"));
333		rv = KC_ERR_FIND_POLICY;
334	} else if (sanity_err) {
335		rv = KC_ERR_VERIFY_POLICY;
336	}
337
338out:
339
340	if (filename != NULL)
341		free(filename);
342
343	if (policyname != NULL)
344		free(policyname);
345
346	return (rv);
347}
348