dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-crypto / kmfcfg / util.c
blob41eb45e49dcba13e7e053bb4fdb57326a734c86b
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
21 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
25 #include <stdio.h>
26 #include <strings.h>
27 #include <ctype.h>
28 #include <libgen.h>
29 #include <libintl.h>
31 #include <libxml/tree.h>
32 #include <libxml/parser.h>
34 #include <kmfapiP.h>
35 #include "util.h"
38 /* Supporting structures and global variables for getopt_av(). */
39 typedef struct av_opts_s {
40 int shortnm; /* short name character */
41 char *longnm; /* long name string, NOT terminated */
42 int longnm_len; /* length of long name string */
43 boolean_t has_arg; /* takes optional argument */
44 } av_opts;
46 static av_opts *opts_av = NULL;
47 static const char *_save_optstr = NULL;
48 static int _save_numopts = 0;
49 int optind_av = 1;
50 char *optarg_av = NULL;
52 void
53 free_policy_list(POLICY_LIST *plist)
55 POLICY_LIST *n = plist, *old;
57 if (plist == NULL)
58 return;
60 while (n != NULL) {
61 old = n;
62 kmf_free_policy_record(&n->plc);
63 n = n->next;
64 free(old);
66 plist = NULL;
69 int
70 load_policies(char *file, POLICY_LIST **policy_list)
72 int rv = KC_OK;
73 KMF_RETURN kmfrv = KMF_OK;
74 POLICY_LIST *newitem, *plist = NULL;
75 xmlParserCtxtPtr ctxt;
76 xmlDocPtr doc = NULL;
77 xmlNodePtr cur, node;
79 /* Create a parser context */
80 ctxt = xmlNewParserCtxt();
81 if (ctxt == NULL)
82 return (KMF_ERR_POLICY_DB_FORMAT);
84 /* Read the policy DB and verify it against the schema. */
85 doc = xmlCtxtReadFile(ctxt, file, NULL,
86 XML_PARSE_DTDVALID | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
87 if (doc == NULL || ctxt->valid == 0) {
88 kmfrv = KMF_ERR_POLICY_DB_FORMAT;
89 goto end;
92 cur = xmlDocGetRootElement(doc);
93 if (cur == NULL) {
94 kmfrv = KMF_ERR_POLICY_DB_FORMAT;
95 goto end;
98 node = cur->xmlChildrenNode;
99 while (node != NULL) {
100 char *c;
102 * Search for the policy that matches the given name.
104 if (!xmlStrcmp((const xmlChar *)node->name,
105 (const xmlChar *)KMF_POLICY_ELEMENT)) {
106 /* Check the name attribute */
107 c = (char *)xmlGetProp(node,
108 (const xmlChar *)KMF_POLICY_NAME_ATTR);
110 /* If a match, parse the rest of the data */
111 if (c != NULL) {
112 xmlFree(c);
113 newitem = malloc(sizeof (POLICY_LIST));
114 if (newitem != NULL) {
115 (void) memset(newitem, 0,
116 sizeof (POLICY_LIST));
117 kmfrv = parsePolicyElement(node,
118 &newitem->plc);
119 } else {
120 kmfrv = KMF_ERR_MEMORY;
121 goto end;
123 /* add to linked list */
124 if (plist == NULL) {
125 plist = newitem;
126 } else {
127 POLICY_LIST *n = plist;
128 while (n->next != NULL)
129 n = n->next;
131 n->next = newitem;
132 newitem->next = NULL;
136 node = node->next;
139 end:
140 if (ctxt != NULL)
141 xmlFreeParserCtxt(ctxt);
143 if (doc != NULL)
144 xmlFreeDoc(doc);
146 if (kmfrv != KMF_OK) {
147 free_policy_list(plist);
148 rv = KC_ERR_LOADDB;
149 } else {
150 *policy_list = plist;
153 return (rv);
157 * Return 0 if there is any error in the input string.
159 uint16_t
160 parseKUlist(char *kustring)
162 uint16_t cur_bit;
163 uint16_t kubits = 0;
164 char *p;
166 p = strtok(kustring, ",");
167 while (p != NULL) {
168 cur_bit = kmf_string_to_ku(p);
169 if (cur_bit == 0) {
170 kubits = 0;
171 break;
173 kubits |= cur_bit;
174 p = strtok(NULL, ",");
177 return (kubits);
180 static void
181 addToEKUList(KMF_EKU_POLICY *ekus, KMF_OID *newoid)
183 if (newoid != NULL && ekus != NULL) {
184 ekus->eku_count++;
185 ekus->ekulist = reallocarray(ekus->ekulist, ekus->eku_count,
186 sizeof (KMF_OID));
187 if (ekus->ekulist != NULL) {
188 ekus->ekulist[ekus->eku_count-1] = *newoid;
194 parseEKUNames(char *ekulist, KMF_POLICY_RECORD *plc)
196 int rv = KC_OK;
197 char *p;
198 KMF_OID *newoid;
199 KMF_EKU_POLICY *ekus = &plc->eku_set;
201 if (ekulist == NULL || !strlen(ekulist))
202 return (0);
205 * The list should be comma separated list of EKU Names.
207 p = strtok(ekulist, ",");
209 /* If no tokens found, then maybe its just a single EKU value */
210 if (p == NULL) {
211 newoid = kmf_ekuname_to_oid(ekulist);
212 if (newoid != NULL) {
213 addToEKUList(ekus, newoid);
214 free(newoid);
215 } else {
216 rv = KC_ERR_USAGE;
220 while (p != NULL) {
221 newoid = kmf_ekuname_to_oid(p);
222 if (newoid != NULL) {
223 addToEKUList(ekus, newoid);
224 free(newoid);
225 } else {
226 rv = KC_ERR_USAGE;
227 break;
229 p = strtok(NULL, ",");
232 if (rv != KC_OK)
233 kmf_free_eku_policy(ekus);
235 return (rv);
239 parseEKUOIDs(char *ekulist, KMF_POLICY_RECORD *plc)
241 int rv = KC_OK;
242 char *p;
243 KMF_OID newoid = { 0, NULL };
244 KMF_EKU_POLICY *ekus = &plc->eku_set;
246 if (ekulist == NULL || !strlen(ekulist))
247 return (0);
250 * The list should be comma separated list of EKU Names.
252 p = strtok(ekulist, ",");
253 if (p == NULL) {
254 if (kmf_string_to_oid(ekulist, &newoid) == KMF_OK) {
255 addToEKUList(ekus, &newoid);
256 } else {
257 rv = KC_ERR_USAGE;
261 while (p != NULL && rv == 0) {
262 if (kmf_string_to_oid(p, &newoid) == KMF_OK) {
263 addToEKUList(ekus, &newoid);
264 } else {
265 rv = KC_ERR_USAGE;
266 break;
268 p = strtok(NULL, ",");
271 if (rv != KC_OK)
272 kmf_free_eku_policy(ekus);
274 return (rv);
278 get_boolean(char *arg)
280 if (arg == NULL)
281 return (-1);
282 if (strcasecmp(arg, "true") == 0)
283 return (1);
284 if (strcasecmp(arg, "false") == 0)
285 return (0);
286 return (-1);
290 * This function processes the input string. It removes the beginning
291 * and ending blank's first, makes a copy of the resulting string and
292 * return it.
294 * This function returns NULL, if there is an error in the
295 * input string or when the system is out of memory. The output
296 * "err_flag" argument will record the error code, if it is not NULL.
298 char *
299 get_string(char *str, int *err_flag)
301 char *p;
302 int len, i;
303 char *retstr = NULL;
305 if (str == NULL) {
306 if (err_flag != NULL)
307 *err_flag = KC_ERR_USAGE;
308 return (NULL);
311 /* Remove beginning whitespace */
312 p = str;
313 while (p != NULL && isspace(*p))
314 p++;
316 if (p == NULL) {
317 if (err_flag != NULL)
318 *err_flag = KC_ERR_USAGE;
319 return (NULL);
322 /* Remove the trailing blanks */
323 len = strlen(p);
324 while (len > 0 && isspace(p[len-1]))
325 len--;
327 if (len == 0) {
328 if (err_flag != NULL)
329 *err_flag = KC_ERR_USAGE;
330 return (NULL);
333 /* Check if there is any non-printable character */
334 i = 0;
335 while (i < len) {
336 if (isprint(p[i]))
337 i++;
338 else {
339 if (err_flag != NULL)
340 *err_flag = KC_ERR_USAGE;
341 return (NULL);
345 /* Make a copy of the string and return it */
346 retstr = malloc(len + 1);
347 if (retstr == NULL) {
348 if (err_flag != NULL)
349 *err_flag = KC_ERR_MEMORY;
350 return (NULL);
353 if (err_flag != NULL)
354 *err_flag = KC_OK;
356 (void) strncpy(retstr, p, len);
357 retstr[len] = '\0';
358 return (retstr);
362 * Breaks out the getopt-style option string into a structure that can be
363 * traversed later for calls to getopt_av(). Option string is NOT altered,
364 * but the struct fields point to locations within option string.
366 static int
367 populate_opts(char *optstring)
369 int i;
370 av_opts *temp;
371 char *marker;
373 if (optstring == NULL || *optstring == '\0')
374 return (0);
377 * This tries to imitate getopt(3c) Each option must conform to:
378 * <short name char> [ ':' ] [ '(' <long name string> ')' ]
379 * If long name is missing, the short name is used for long name.
381 for (i = 0; *optstring != '\0'; i++) {
382 if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
383 reallocarray(opts_av, i + 1, sizeof (av_opts)))) == NULL) {
384 free(opts_av);
385 opts_av = NULL;
386 return (0);
387 } else
388 opts_av = (av_opts *)temp;
390 marker = optstring; /* may need optstring later */
392 opts_av[i].shortnm = *marker++; /* set short name */
394 if (*marker == ':') { /* check for opt arg */
395 marker++;
396 opts_av[i].has_arg = B_TRUE;
399 if (*marker == '(') { /* check and set long name */
400 marker++;
401 opts_av[i].longnm = marker;
402 opts_av[i].longnm_len = strcspn(marker, ")");
403 optstring = marker + opts_av[i].longnm_len + 1;
404 } else {
405 /* use short name option character */
406 opts_av[i].longnm = optstring;
407 opts_av[i].longnm_len = 1;
408 optstring = marker;
412 return (i);
416 * getopt_av() is very similar to getopt(3c) in that the takes an option
417 * string, compares command line arguments for matches, and returns a single
418 * letter option when a match is found. However, getopt_av() differs from
419 * getopt(3c) by allowing both longname options and values be found
420 * on the command line.
423 getopt_av(int argc, char * const *argv, const char *optstring)
425 int i;
426 int len;
428 if (optind_av >= argc)
429 return (EOF);
431 /* First time or when optstring changes from previous one */
432 if (_save_optstr != optstring) {
433 free(opts_av);
434 opts_av = NULL;
435 _save_optstr = optstring;
436 _save_numopts = populate_opts((char *)optstring);
439 for (i = 0; i < _save_numopts; i++) {
440 if (strcmp(argv[optind_av], "--") == 0) {
441 optind_av++;
442 break;
445 len = strcspn(argv[optind_av], "=");
447 if (len == opts_av[i].longnm_len && strncmp(argv[optind_av],
448 opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
449 /* matched */
450 if (!opts_av[i].has_arg) {
451 optind_av++;
452 return (opts_av[i].shortnm);
455 /* needs optarg */
456 if (argv[optind_av][len] == '=') {
457 optarg_av = &(argv[optind_av][len+1]);
458 optind_av++;
459 return (opts_av[i].shortnm);
462 optarg_av = NULL;
463 optind_av++;
464 return ((int)'?');
468 return (EOF);
471 void
472 print_sanity_error(KMF_RETURN ret)
474 switch (ret) {
475 case KMF_ERR_POLICY_NAME:
476 (void) fprintf(stderr, gettext("Error in the policy name\n"));
477 break;
478 case KMF_ERR_TA_POLICY:
479 (void) fprintf(stderr,
480 gettext("Error in trust anchor attributes\n"));
481 break;
482 case KMF_ERR_OCSP_POLICY:
483 (void) fprintf(stderr,
484 gettext("Error in OCSP policy attributes\n"));
485 break;
486 default:
487 break;
492 conf_entry_t *
493 get_keystore_entry(char *kstore_name)
495 conf_entrylist_t *phead = NULL;
496 conf_entrylist_t *ptr;
497 conf_entry_t *rtn_entry = NULL;
499 if (kstore_name == NULL)
500 return (NULL);
502 if (get_entrylist(&phead) != KMF_OK)
503 return (NULL);
505 ptr = phead;
506 while (ptr != NULL) {
507 if (strcmp(ptr->entry->keystore, kstore_name) == 0)
508 break;
509 ptr = ptr->next;
512 if (ptr != NULL) /* found the entry */
513 rtn_entry = dup_entry(ptr->entry);
515 free_entrylist(phead);
516 return (rtn_entry);