xref: /titanic_52/usr/src/cmd/cmd-crypto/kmfcfg/util.c (revision 99ebb4ca412cb0a19d77a3899a87c055b9c30fa8)
1*99ebb4caSwyllys /*
2*99ebb4caSwyllys  * CDDL HEADER START
3*99ebb4caSwyllys  *
4*99ebb4caSwyllys  * The contents of this file are subject to the terms of the
5*99ebb4caSwyllys  * Common Development and Distribution License (the "License").
6*99ebb4caSwyllys  * You may not use this file except in compliance with the License.
7*99ebb4caSwyllys  *
8*99ebb4caSwyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*99ebb4caSwyllys  * or http://www.opensolaris.org/os/licensing.
10*99ebb4caSwyllys  * See the License for the specific language governing permissions
11*99ebb4caSwyllys  * and limitations under the License.
12*99ebb4caSwyllys  *
13*99ebb4caSwyllys  * When distributing Covered Code, include this CDDL HEADER in each
14*99ebb4caSwyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*99ebb4caSwyllys  * If applicable, add the following below this CDDL HEADER, with the
16*99ebb4caSwyllys  * fields enclosed by brackets "[]" replaced with your own identifying
17*99ebb4caSwyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
18*99ebb4caSwyllys  *
19*99ebb4caSwyllys  * CDDL HEADER END
20*99ebb4caSwyllys  *
21*99ebb4caSwyllys  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
22*99ebb4caSwyllys  * Use is subject to license terms.
23*99ebb4caSwyllys  */
24*99ebb4caSwyllys 
25*99ebb4caSwyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
26*99ebb4caSwyllys 
27*99ebb4caSwyllys #include <stdio.h>
28*99ebb4caSwyllys #include <strings.h>
29*99ebb4caSwyllys #include <ctype.h>
30*99ebb4caSwyllys #include <libgen.h>
31*99ebb4caSwyllys #include <libintl.h>
32*99ebb4caSwyllys 
33*99ebb4caSwyllys #include <libxml/tree.h>
34*99ebb4caSwyllys #include <libxml/parser.h>
35*99ebb4caSwyllys 
36*99ebb4caSwyllys #include <kmfapiP.h>
37*99ebb4caSwyllys 
38*99ebb4caSwyllys #include "util.h"
39*99ebb4caSwyllys 
40*99ebb4caSwyllys /* Supporting structures and global variables for getopt_av(). */
41*99ebb4caSwyllys typedef struct	av_opts_s {
42*99ebb4caSwyllys 	int		shortnm;	/* short name character */
43*99ebb4caSwyllys 	char		*longnm;	/* long name string, NOT terminated */
44*99ebb4caSwyllys 	int		longnm_len;	/* length of long name string */
45*99ebb4caSwyllys 	boolean_t	has_arg;	/* takes optional argument */
46*99ebb4caSwyllys } av_opts;
47*99ebb4caSwyllys 
48*99ebb4caSwyllys static av_opts		*opts_av = NULL;
49*99ebb4caSwyllys static const char	*_save_optstr = NULL;
50*99ebb4caSwyllys static int		_save_numopts = 0;
51*99ebb4caSwyllys int			optind_av = 1;
52*99ebb4caSwyllys char			*optarg_av = NULL;
53*99ebb4caSwyllys 
54*99ebb4caSwyllys void
55*99ebb4caSwyllys free_policy_list(POLICY_LIST *plist)
56*99ebb4caSwyllys {
57*99ebb4caSwyllys 	POLICY_LIST *n = plist, *old;
58*99ebb4caSwyllys 
59*99ebb4caSwyllys 	if (plist == NULL)
60*99ebb4caSwyllys 		return;
61*99ebb4caSwyllys 
62*99ebb4caSwyllys 	while (n != NULL) {
63*99ebb4caSwyllys 		old = n;
64*99ebb4caSwyllys 		KMF_FreePolicyRecord(&n->plc);
65*99ebb4caSwyllys 		n = n->next;
66*99ebb4caSwyllys 		free(old);
67*99ebb4caSwyllys 	}
68*99ebb4caSwyllys 	plist = NULL;
69*99ebb4caSwyllys }
70*99ebb4caSwyllys 
71*99ebb4caSwyllys int
72*99ebb4caSwyllys load_policies(char *file, POLICY_LIST **policy_list)
73*99ebb4caSwyllys {
74*99ebb4caSwyllys 	int rv = KC_OK;
75*99ebb4caSwyllys 	KMF_RETURN kmfrv = KMF_OK;
76*99ebb4caSwyllys 	POLICY_LIST *newitem, *plist = NULL;
77*99ebb4caSwyllys 	xmlParserCtxtPtr ctxt;
78*99ebb4caSwyllys 	xmlDocPtr doc = NULL;
79*99ebb4caSwyllys 	xmlNodePtr cur, node;
80*99ebb4caSwyllys 
81*99ebb4caSwyllys 	/* Create a parser context */
82*99ebb4caSwyllys 	ctxt = xmlNewParserCtxt();
83*99ebb4caSwyllys 	if (ctxt == NULL)
84*99ebb4caSwyllys 		return (KMF_ERR_POLICY_DB_FORMAT);
85*99ebb4caSwyllys 
86*99ebb4caSwyllys 	/* Read the policy DB and verify it against the schema. */
87*99ebb4caSwyllys 	doc = xmlCtxtReadFile(ctxt, file, NULL,
88*99ebb4caSwyllys 	    XML_PARSE_DTDVALID | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
89*99ebb4caSwyllys 	if (doc == NULL || ctxt->valid == 0) {
90*99ebb4caSwyllys 		kmfrv = KMF_ERR_POLICY_DB_FORMAT;
91*99ebb4caSwyllys 		goto end;
92*99ebb4caSwyllys 	}
93*99ebb4caSwyllys 
94*99ebb4caSwyllys 	cur = xmlDocGetRootElement(doc);
95*99ebb4caSwyllys 	if (cur == NULL) {
96*99ebb4caSwyllys 		kmfrv = KMF_ERR_POLICY_DB_FORMAT;
97*99ebb4caSwyllys 		goto end;
98*99ebb4caSwyllys 	}
99*99ebb4caSwyllys 
100*99ebb4caSwyllys 	node = cur->xmlChildrenNode;
101*99ebb4caSwyllys 	while (node != NULL) {
102*99ebb4caSwyllys 		char *c;
103*99ebb4caSwyllys 		/*
104*99ebb4caSwyllys 		 * Search for the policy that matches the given name.
105*99ebb4caSwyllys 		 */
106*99ebb4caSwyllys 		if (!xmlStrcmp((const xmlChar *)node->name,
107*99ebb4caSwyllys 			(const xmlChar *)KMF_POLICY_ELEMENT)) {
108*99ebb4caSwyllys 			/* Check the name attribute */
109*99ebb4caSwyllys 			c = (char *)xmlGetProp(node,
110*99ebb4caSwyllys 				(const xmlChar *)KMF_POLICY_NAME_ATTR);
111*99ebb4caSwyllys 
112*99ebb4caSwyllys 			/* If a match, parse the rest of the data */
113*99ebb4caSwyllys 			if (c != NULL) {
114*99ebb4caSwyllys 				xmlFree(c);
115*99ebb4caSwyllys 				newitem = malloc(sizeof (POLICY_LIST));
116*99ebb4caSwyllys 				if (newitem != NULL) {
117*99ebb4caSwyllys 					(void) memset(newitem, 0,
118*99ebb4caSwyllys 						sizeof (POLICY_LIST));
119*99ebb4caSwyllys 					kmfrv = parsePolicyElement(node,
120*99ebb4caSwyllys 						&newitem->plc);
121*99ebb4caSwyllys 				} else {
122*99ebb4caSwyllys 					kmfrv = KMF_ERR_MEMORY;
123*99ebb4caSwyllys 					goto end;
124*99ebb4caSwyllys 				}
125*99ebb4caSwyllys 				/* add to linked list */
126*99ebb4caSwyllys 				if (plist == NULL) {
127*99ebb4caSwyllys 					plist = newitem;
128*99ebb4caSwyllys 				} else {
129*99ebb4caSwyllys 					POLICY_LIST *n = plist;
130*99ebb4caSwyllys 					while (n->next != NULL)
131*99ebb4caSwyllys 						n = n->next;
132*99ebb4caSwyllys 
133*99ebb4caSwyllys 					n->next = newitem;
134*99ebb4caSwyllys 					newitem->next = NULL;
135*99ebb4caSwyllys 				}
136*99ebb4caSwyllys 			}
137*99ebb4caSwyllys 		}
138*99ebb4caSwyllys 		node = node->next;
139*99ebb4caSwyllys 	}
140*99ebb4caSwyllys 
141*99ebb4caSwyllys end:
142*99ebb4caSwyllys 	if (ctxt != NULL)
143*99ebb4caSwyllys 		xmlFreeParserCtxt(ctxt);
144*99ebb4caSwyllys 
145*99ebb4caSwyllys 	if (doc != NULL)
146*99ebb4caSwyllys 		xmlFreeDoc(doc);
147*99ebb4caSwyllys 
148*99ebb4caSwyllys 	if (kmfrv != KMF_OK) {
149*99ebb4caSwyllys 		free_policy_list(plist);
150*99ebb4caSwyllys 		rv = KC_ERR_LOADDB;
151*99ebb4caSwyllys 	} else {
152*99ebb4caSwyllys 		*policy_list = plist;
153*99ebb4caSwyllys 	}
154*99ebb4caSwyllys 
155*99ebb4caSwyllys 	return (rv);
156*99ebb4caSwyllys }
157*99ebb4caSwyllys 
158*99ebb4caSwyllys /*
159*99ebb4caSwyllys  * Return 0 if there is any error in the input string.
160*99ebb4caSwyllys  */
161*99ebb4caSwyllys uint16_t
162*99ebb4caSwyllys parseKUlist(char *kustring)
163*99ebb4caSwyllys {
164*99ebb4caSwyllys 	uint16_t cur_bit;
165*99ebb4caSwyllys 	uint16_t kubits = 0;
166*99ebb4caSwyllys 	char *p;
167*99ebb4caSwyllys 
168*99ebb4caSwyllys 	p = strtok(kustring, ",");
169*99ebb4caSwyllys 	while (p != NULL) {
170*99ebb4caSwyllys 		cur_bit = KMF_StringToKeyUsage(p);
171*99ebb4caSwyllys 		if (cur_bit == 0) {
172*99ebb4caSwyllys 			kubits = 0;
173*99ebb4caSwyllys 			break;
174*99ebb4caSwyllys 		}
175*99ebb4caSwyllys 		kubits |= cur_bit;
176*99ebb4caSwyllys 		p = strtok(NULL, ",");
177*99ebb4caSwyllys 	}
178*99ebb4caSwyllys 
179*99ebb4caSwyllys 	return (kubits);
180*99ebb4caSwyllys }
181*99ebb4caSwyllys 
182*99ebb4caSwyllys static void
183*99ebb4caSwyllys addToEKUList(KMF_EKU_POLICY *ekus, KMF_OID *newoid)
184*99ebb4caSwyllys {
185*99ebb4caSwyllys 	if (newoid != NULL && ekus != NULL) {
186*99ebb4caSwyllys 		ekus->eku_count++;
187*99ebb4caSwyllys 		ekus->ekulist = realloc(
188*99ebb4caSwyllys 			ekus->ekulist,
189*99ebb4caSwyllys 			ekus->eku_count * sizeof (KMF_OID));
190*99ebb4caSwyllys 		if (ekus->ekulist != NULL) {
191*99ebb4caSwyllys 			ekus->ekulist[ekus->eku_count-1] = *newoid;
192*99ebb4caSwyllys 		}
193*99ebb4caSwyllys 	}
194*99ebb4caSwyllys }
195*99ebb4caSwyllys 
196*99ebb4caSwyllys int
197*99ebb4caSwyllys parseEKUNames(char *ekulist, KMF_POLICY_RECORD *plc)
198*99ebb4caSwyllys {
199*99ebb4caSwyllys 	int rv = KC_OK;
200*99ebb4caSwyllys 	char *p;
201*99ebb4caSwyllys 	KMF_OID *newoid;
202*99ebb4caSwyllys 	KMF_EKU_POLICY *ekus = &plc->eku_set;
203*99ebb4caSwyllys 
204*99ebb4caSwyllys 	if (ekulist == NULL || !strlen(ekulist))
205*99ebb4caSwyllys 		return (0);
206*99ebb4caSwyllys 
207*99ebb4caSwyllys 	/*
208*99ebb4caSwyllys 	 * The list should be comma separated list of EKU Names.
209*99ebb4caSwyllys 	 */
210*99ebb4caSwyllys 	p = strtok(ekulist, ",");
211*99ebb4caSwyllys 
212*99ebb4caSwyllys 	/* If no tokens found, then maybe its just a single EKU value */
213*99ebb4caSwyllys 	if (p == NULL) {
214*99ebb4caSwyllys 		newoid = kmf_ekuname2oid(ekulist);
215*99ebb4caSwyllys 		if (newoid != NULL) {
216*99ebb4caSwyllys 			addToEKUList(ekus, newoid);
217*99ebb4caSwyllys 			free(newoid);
218*99ebb4caSwyllys 		} else {
219*99ebb4caSwyllys 			rv = KC_ERR_USAGE;
220*99ebb4caSwyllys 		}
221*99ebb4caSwyllys 	}
222*99ebb4caSwyllys 
223*99ebb4caSwyllys 	while (p != NULL) {
224*99ebb4caSwyllys 		newoid = kmf_ekuname2oid(p);
225*99ebb4caSwyllys 		if (newoid != NULL) {
226*99ebb4caSwyllys 			addToEKUList(ekus, newoid);
227*99ebb4caSwyllys 			free(newoid);
228*99ebb4caSwyllys 		} else {
229*99ebb4caSwyllys 			rv = KC_ERR_USAGE;
230*99ebb4caSwyllys 			break;
231*99ebb4caSwyllys 		}
232*99ebb4caSwyllys 		p = strtok(NULL, ",");
233*99ebb4caSwyllys 	}
234*99ebb4caSwyllys 
235*99ebb4caSwyllys 	if (rv != KC_OK)
236*99ebb4caSwyllys 		KMF_FreeEKUPolicy(ekus);
237*99ebb4caSwyllys 
238*99ebb4caSwyllys 	return (rv);
239*99ebb4caSwyllys }
240*99ebb4caSwyllys 
241*99ebb4caSwyllys int
242*99ebb4caSwyllys parseEKUOIDs(char *ekulist, KMF_POLICY_RECORD *plc)
243*99ebb4caSwyllys {
244*99ebb4caSwyllys 	int rv = KC_OK;
245*99ebb4caSwyllys 	char *p;
246*99ebb4caSwyllys 	KMF_OID *newoid;
247*99ebb4caSwyllys 	KMF_EKU_POLICY *ekus = &plc->eku_set;
248*99ebb4caSwyllys 
249*99ebb4caSwyllys 	if (ekulist == NULL || !strlen(ekulist))
250*99ebb4caSwyllys 		return (0);
251*99ebb4caSwyllys 
252*99ebb4caSwyllys 	/*
253*99ebb4caSwyllys 	 * The list should be comma separated list of EKU Names.
254*99ebb4caSwyllys 	 */
255*99ebb4caSwyllys 	p = strtok(ekulist, ",");
256*99ebb4caSwyllys 	if (p == NULL) {
257*99ebb4caSwyllys 		newoid = kmf_string2oid(ekulist);
258*99ebb4caSwyllys 		if (newoid != NULL) {
259*99ebb4caSwyllys 			addToEKUList(ekus, newoid);
260*99ebb4caSwyllys 			free(newoid);
261*99ebb4caSwyllys 		} else {
262*99ebb4caSwyllys 			rv = KC_ERR_USAGE;
263*99ebb4caSwyllys 		}
264*99ebb4caSwyllys 	}
265*99ebb4caSwyllys 
266*99ebb4caSwyllys 	while (p != NULL && rv == 0) {
267*99ebb4caSwyllys 		newoid = kmf_string2oid(p);
268*99ebb4caSwyllys 		if (newoid != NULL) {
269*99ebb4caSwyllys 			addToEKUList(ekus, newoid);
270*99ebb4caSwyllys 			free(newoid);
271*99ebb4caSwyllys 		} else {
272*99ebb4caSwyllys 			rv = KC_ERR_USAGE;
273*99ebb4caSwyllys 			break;
274*99ebb4caSwyllys 		}
275*99ebb4caSwyllys 		p = strtok(NULL, ",");
276*99ebb4caSwyllys 	}
277*99ebb4caSwyllys 
278*99ebb4caSwyllys 	if (rv != KC_OK)
279*99ebb4caSwyllys 		KMF_FreeEKUPolicy(ekus);
280*99ebb4caSwyllys 
281*99ebb4caSwyllys 	return (rv);
282*99ebb4caSwyllys }
283*99ebb4caSwyllys 
284*99ebb4caSwyllys int
285*99ebb4caSwyllys get_boolean(char *arg)
286*99ebb4caSwyllys {
287*99ebb4caSwyllys 	if (arg == NULL)
288*99ebb4caSwyllys 		return (-1);
289*99ebb4caSwyllys 	if (strcasecmp(arg, "true") == 0)
290*99ebb4caSwyllys 		return (1);
291*99ebb4caSwyllys 	if (strcasecmp(arg, "false") == 0)
292*99ebb4caSwyllys 		return (0);
293*99ebb4caSwyllys 	return (-1);
294*99ebb4caSwyllys }
295*99ebb4caSwyllys 
296*99ebb4caSwyllys /*
297*99ebb4caSwyllys  * This function processes the input string.  It removes the beginning
298*99ebb4caSwyllys  * and ending blank's first, makes a copy of the resulting string and
299*99ebb4caSwyllys  * return it.
300*99ebb4caSwyllys  *
301*99ebb4caSwyllys  * This function returns NULL, if there is an error in the
302*99ebb4caSwyllys  * input string or when the system is out of memory.  The output
303*99ebb4caSwyllys  * "err_flag" argument will record the error code, if it is not NULL.
304*99ebb4caSwyllys  */
305*99ebb4caSwyllys char *
306*99ebb4caSwyllys get_string(char *str, int *err_flag)
307*99ebb4caSwyllys {
308*99ebb4caSwyllys 	char *p;
309*99ebb4caSwyllys 	int len, i;
310*99ebb4caSwyllys 	char *retstr = NULL;
311*99ebb4caSwyllys 
312*99ebb4caSwyllys 	if (str == NULL) {
313*99ebb4caSwyllys 		if (err_flag != NULL)
314*99ebb4caSwyllys 			*err_flag = KC_ERR_USAGE;
315*99ebb4caSwyllys 		return (NULL);
316*99ebb4caSwyllys 	}
317*99ebb4caSwyllys 
318*99ebb4caSwyllys 	/* Remove beginning whitespace */
319*99ebb4caSwyllys 	p = str;
320*99ebb4caSwyllys 	while (p != NULL && isspace(*p))
321*99ebb4caSwyllys 		p++;
322*99ebb4caSwyllys 
323*99ebb4caSwyllys 	if (p == NULL) {
324*99ebb4caSwyllys 		if (err_flag != NULL)
325*99ebb4caSwyllys 			*err_flag = KC_ERR_USAGE;
326*99ebb4caSwyllys 		return (NULL);
327*99ebb4caSwyllys 	}
328*99ebb4caSwyllys 
329*99ebb4caSwyllys 	/* Remove the trailing blanks */
330*99ebb4caSwyllys 	len = strlen(p);
331*99ebb4caSwyllys 	while (len > 0 && isspace(p[len-1]))
332*99ebb4caSwyllys 		len--;
333*99ebb4caSwyllys 
334*99ebb4caSwyllys 	if (len == 0) {
335*99ebb4caSwyllys 		if (err_flag != NULL)
336*99ebb4caSwyllys 			*err_flag = KC_ERR_USAGE;
337*99ebb4caSwyllys 		return (NULL);
338*99ebb4caSwyllys 	}
339*99ebb4caSwyllys 
340*99ebb4caSwyllys 	/* Check if there is any non-printable character */
341*99ebb4caSwyllys 	i = 0;
342*99ebb4caSwyllys 	while (i < len) {
343*99ebb4caSwyllys 		if (isprint(p[i]))
344*99ebb4caSwyllys 			i++;
345*99ebb4caSwyllys 		else {
346*99ebb4caSwyllys 			if (err_flag != NULL)
347*99ebb4caSwyllys 				*err_flag = KC_ERR_USAGE;
348*99ebb4caSwyllys 			return (NULL);
349*99ebb4caSwyllys 		}
350*99ebb4caSwyllys 	}
351*99ebb4caSwyllys 
352*99ebb4caSwyllys 	/* Make a copy of the string and return it */
353*99ebb4caSwyllys 	retstr = malloc(len + 1);
354*99ebb4caSwyllys 	if (retstr == NULL) {
355*99ebb4caSwyllys 		if (err_flag != NULL)
356*99ebb4caSwyllys 			*err_flag = KC_ERR_MEMORY;
357*99ebb4caSwyllys 		return (NULL);
358*99ebb4caSwyllys 	}
359*99ebb4caSwyllys 
360*99ebb4caSwyllys 	if (err_flag != NULL)
361*99ebb4caSwyllys 		*err_flag = KC_OK;
362*99ebb4caSwyllys 
363*99ebb4caSwyllys 	(void) strncpy(retstr, p, len);
364*99ebb4caSwyllys 	retstr[len] = '\0';
365*99ebb4caSwyllys 	return (retstr);
366*99ebb4caSwyllys }
367*99ebb4caSwyllys 
368*99ebb4caSwyllys /*
369*99ebb4caSwyllys  * Breaks out the getopt-style option string into a structure that can be
370*99ebb4caSwyllys  * traversed later for calls to getopt_av().  Option string is NOT altered,
371*99ebb4caSwyllys  * but the struct fields point to locations within option string.
372*99ebb4caSwyllys  */
373*99ebb4caSwyllys static int
374*99ebb4caSwyllys populate_opts(char *optstring)
375*99ebb4caSwyllys {
376*99ebb4caSwyllys 	int		i;
377*99ebb4caSwyllys 	av_opts		*temp;
378*99ebb4caSwyllys 	char		*marker;
379*99ebb4caSwyllys 
380*99ebb4caSwyllys 	if (optstring == NULL || *optstring == '\0')
381*99ebb4caSwyllys 		return (0);
382*99ebb4caSwyllys 
383*99ebb4caSwyllys 	/*
384*99ebb4caSwyllys 	 * This tries to imitate getopt(3c) Each option must conform to:
385*99ebb4caSwyllys 	 * <short name char> [ ':' ] [ '(' <long name string> ')' ]
386*99ebb4caSwyllys 	 * If long name is missing, the short name is used for long name.
387*99ebb4caSwyllys 	 */
388*99ebb4caSwyllys 	for (i = 0; *optstring != '\0'; i++) {
389*99ebb4caSwyllys 		if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
390*99ebb4caSwyllys 		    realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
391*99ebb4caSwyllys 			free(opts_av);
392*99ebb4caSwyllys 			opts_av = NULL;
393*99ebb4caSwyllys 			return (0);
394*99ebb4caSwyllys 		} else
395*99ebb4caSwyllys 			opts_av = (av_opts *)temp;
396*99ebb4caSwyllys 
397*99ebb4caSwyllys 		marker = optstring;		/* may need optstring later */
398*99ebb4caSwyllys 
399*99ebb4caSwyllys 		opts_av[i].shortnm = *marker++;	/* set short name */
400*99ebb4caSwyllys 
401*99ebb4caSwyllys 		if (*marker == ':') {		/* check for opt arg */
402*99ebb4caSwyllys 			marker++;
403*99ebb4caSwyllys 			opts_av[i].has_arg = B_TRUE;
404*99ebb4caSwyllys 		}
405*99ebb4caSwyllys 
406*99ebb4caSwyllys 		if (*marker == '(') {		/* check and set long name */
407*99ebb4caSwyllys 			marker++;
408*99ebb4caSwyllys 			opts_av[i].longnm = marker;
409*99ebb4caSwyllys 			opts_av[i].longnm_len = strcspn(marker, ")");
410*99ebb4caSwyllys 			optstring = marker + opts_av[i].longnm_len + 1;
411*99ebb4caSwyllys 		} else {
412*99ebb4caSwyllys 			/* use short name option character */
413*99ebb4caSwyllys 			opts_av[i].longnm = optstring;
414*99ebb4caSwyllys 			opts_av[i].longnm_len = 1;
415*99ebb4caSwyllys 			optstring = marker;
416*99ebb4caSwyllys 		}
417*99ebb4caSwyllys 	}
418*99ebb4caSwyllys 
419*99ebb4caSwyllys 	return (i);
420*99ebb4caSwyllys }
421*99ebb4caSwyllys 
422*99ebb4caSwyllys /*
423*99ebb4caSwyllys  * getopt_av() is very similar to getopt(3c) in that the takes an option
424*99ebb4caSwyllys  * string, compares command line arguments for matches, and returns a single
425*99ebb4caSwyllys  * letter option when a match is found.  However, getopt_av() differs from
426*99ebb4caSwyllys  * getopt(3c) by allowing both longname options and values be found
427*99ebb4caSwyllys  * on the command line.
428*99ebb4caSwyllys  */
429*99ebb4caSwyllys int
430*99ebb4caSwyllys getopt_av(int argc, char * const *argv, const char *optstring)
431*99ebb4caSwyllys {
432*99ebb4caSwyllys 	int	i;
433*99ebb4caSwyllys 	int	len;
434*99ebb4caSwyllys 
435*99ebb4caSwyllys 	if (optind_av >= argc)
436*99ebb4caSwyllys 		return (EOF);
437*99ebb4caSwyllys 
438*99ebb4caSwyllys 	/* First time or when optstring changes from previous one */
439*99ebb4caSwyllys 	if (_save_optstr != optstring) {
440*99ebb4caSwyllys 		if (opts_av != NULL)
441*99ebb4caSwyllys 		    free(opts_av);
442*99ebb4caSwyllys 		opts_av = NULL;
443*99ebb4caSwyllys 		_save_optstr = optstring;
444*99ebb4caSwyllys 		_save_numopts = populate_opts((char *)optstring);
445*99ebb4caSwyllys 	}
446*99ebb4caSwyllys 
447*99ebb4caSwyllys 	for (i = 0; i < _save_numopts; i++) {
448*99ebb4caSwyllys 		if (strcmp(argv[optind_av], "--") == 0) {
449*99ebb4caSwyllys 			optind_av++;
450*99ebb4caSwyllys 			break;
451*99ebb4caSwyllys 		}
452*99ebb4caSwyllys 
453*99ebb4caSwyllys 		len = strcspn(argv[optind_av], "=");
454*99ebb4caSwyllys 
455*99ebb4caSwyllys 		if (len == opts_av[i].longnm_len && strncmp(argv[optind_av],
456*99ebb4caSwyllys 		    opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
457*99ebb4caSwyllys 			/* matched */
458*99ebb4caSwyllys 			if (!opts_av[i].has_arg) {
459*99ebb4caSwyllys 				optind_av++;
460*99ebb4caSwyllys 				return (opts_av[i].shortnm);
461*99ebb4caSwyllys 			}
462*99ebb4caSwyllys 
463*99ebb4caSwyllys 			/* needs optarg */
464*99ebb4caSwyllys 			if (argv[optind_av][len] == '=') {
465*99ebb4caSwyllys 				optarg_av = &(argv[optind_av][len+1]);
466*99ebb4caSwyllys 				optind_av++;
467*99ebb4caSwyllys 				return (opts_av[i].shortnm);
468*99ebb4caSwyllys 			}
469*99ebb4caSwyllys 
470*99ebb4caSwyllys 			optarg_av = NULL;
471*99ebb4caSwyllys 			optind_av++;
472*99ebb4caSwyllys 			return ((int)'?');
473*99ebb4caSwyllys 		}
474*99ebb4caSwyllys 	}
475*99ebb4caSwyllys 
476*99ebb4caSwyllys 	return (EOF);
477*99ebb4caSwyllys }
478*99ebb4caSwyllys 
479*99ebb4caSwyllys void
480*99ebb4caSwyllys print_sanity_error(KMF_RETURN ret)
481*99ebb4caSwyllys {
482*99ebb4caSwyllys 	switch (ret) {
483*99ebb4caSwyllys 	case KMF_ERR_POLICY_NAME:
484*99ebb4caSwyllys 		(void) fprintf(stderr, gettext("Error in the policy name\n"));
485*99ebb4caSwyllys 		break;
486*99ebb4caSwyllys 	case KMF_ERR_TA_POLICY:
487*99ebb4caSwyllys 		(void) fprintf(stderr,
488*99ebb4caSwyllys 		    gettext("Error in trust anchor attributes\n"));
489*99ebb4caSwyllys 		break;
490*99ebb4caSwyllys 	case KMF_ERR_OCSP_POLICY:
491*99ebb4caSwyllys 		(void) fprintf(stderr,
492*99ebb4caSwyllys 		    gettext("Error in OCSP policy attributes\n"));
493*99ebb4caSwyllys 		break;
494*99ebb4caSwyllys 	default:
495*99ebb4caSwyllys 		break;
496*99ebb4caSwyllys 	}
497*99ebb4caSwyllys }
498