xref: /titanic_41/usr/src/lib/libcryptoutil/common/config_parsing.c (revision 6dfee4834394825da35b977ca71cdc965bc7b6a4)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <errno.h>
31 #include <strings.h>
32 #include <locale.h>
33 #include <stdlib.h>
34 #include "cryptoutil.h"
35 
36 static int uef_interpret(char *, uentry_t **);
37 static int parse_policylist(char *, uentry_t *);
38 
39 /*
40  * Retrieve the user-level provider info from the pkcs11.conf file.
41  * If successful, the result is returned from the ppliblist argument.
42  * This function returns SUCCESS if successfully done; otherwise it returns
43  * FAILURE.
44  */
45 int
46 get_pkcs11conf_info(uentrylist_t **ppliblist)
47 {
48 	FILE *pfile;
49 	char buffer[BUFSIZ];
50 	size_t len;
51 	uentry_t *pent;
52 	uentrylist_t *pentlist;
53 	uentrylist_t *pcur;
54 	int rc = SUCCESS;
55 
56 	*ppliblist = NULL;
57 	if ((pfile = fopen(_PATH_PKCS11_CONF, "r")) == NULL) {
58 		cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_PKCS11_CONF);
59 		return (FAILURE);
60 	}
61 
62 	while (fgets(buffer, BUFSIZ, pfile) != NULL) {
63 		if (buffer[0] == '#' || buffer[0] == ' ' ||
64 		    buffer[0] == '\n'|| buffer[0] == '\t') {
65 			continue;   /* ignore comment lines */
66 		}
67 
68 		len = strlen(buffer);
69 		if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */
70 			len--;
71 		}
72 		buffer[len] = '\0';
73 
74 		if ((rc = uef_interpret(buffer,  &pent)) != SUCCESS) {
75 			break;
76 		}
77 
78 		/* append pent into ppliblist */
79 		pentlist = malloc(sizeof (uentrylist_t));
80 		if (pentlist == NULL) {
81 			cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
82 			    _PATH_PKCS11_CONF);
83 			free_uentry(pent);
84 			rc = FAILURE;
85 			break;
86 		}
87 		pentlist->puent = pent;
88 		pentlist->next = NULL;
89 
90 		if (*ppliblist == NULL) {
91 			*ppliblist = pcur = pentlist;
92 		} else {
93 			pcur->next = pentlist;
94 			pcur = pcur->next;
95 		}
96 	}
97 
98 	(void) fclose(pfile);
99 
100 	if (rc != SUCCESS) {
101 		free_uentrylist(*ppliblist);
102 		*ppliblist = NULL;
103 	}
104 
105 	return (rc);
106 }
107 
108 
109 /*
110  * This routine converts a char string into a uentry_t structure
111  * The input string "buf" should be one of the following:
112  *	library_name
113  *	library_name:NO_RANDOM
114  *	library_name:disabledlist=m1,m2,...,mk
115  *	library_name:disabledlist=m1,m2,...,mk;NO_RANDOM
116  *	library_name:enabledlist=
117  *	library_name:enabledlist=;NO_RANDOM
118  *	library_name:enabledlist=m1,m2,...,mk
119  *	library_name:enabledlist=m1,m2,...,mk;NO_RANDOM
120  *	metaslot:status=enabled;enabledlist=m1,m2,....;slot=<slot-description>;\
121  *	token=<token-label>
122  *
123  * Note:
124  *	The mechanisms m1,..mk are in hex form. For example, "0x00000210"
125  *	for CKM_MD5.
126  *
127  *	For the metaslot entry, "enabledlist", "slot", "auto_key_migrate"
128  * 	or "token" is optional
129  */
130 static int
131 uef_interpret(char *buf, uentry_t **ppent)
132 {
133 	uentry_t *pent;
134 	char	*token1;
135 	char	*token2;
136 	char	*lasts;
137 	int	rc;
138 
139 	*ppent = NULL;
140 	if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL) {
141 		/* buf is NULL */
142 		return (FAILURE);
143 	};
144 
145 	pent = calloc(sizeof (uentry_t), 1);
146 	if (pent == NULL) {
147 		cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
148 		    _PATH_PKCS11_CONF);
149 		return (FAILURE);
150 	}
151 	(void) strlcpy(pent->name, token1, sizeof (pent->name));
152 	/*
153 	 * in case metaslot_auto_key_migrate is not specified, it should
154 	 * be default to true
155 	 */
156 	pent->flag_metaslot_auto_key_migrate = B_TRUE;
157 
158 	while ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) != NULL) {
159 		if ((rc = parse_policylist(token2, pent)) != SUCCESS) {
160 			free_uentry(pent);
161 			return (rc);
162 		}
163 	}
164 
165 	*ppent = pent;
166 	return (SUCCESS);
167 }
168 
169 
170 /*
171  * This routine parses the policy list and stored the result in the argument
172  * pent.
173  *
174  * 	Arg buf: input only, its format should be one of the following:
175  *     		enabledlist=
176  *		enabledlist=m1,m2,...,mk
177  *		disabledlist=m1,m2,...,mk
178  *		NO_RANDOM
179  *		metaslot_status=enabled|disabled
180  *		metaslot_token=<token-label>
181  *		metaslot_slot=<slot-description.
182  *
183  *	Arg pent: input/output
184  *
185  *      return: SUCCESS or FAILURE
186  */
187 static int
188 parse_policylist(char *buf, uentry_t *pent)
189 {
190 	umechlist_t *phead = NULL;
191 	umechlist_t *pcur = NULL;
192 	umechlist_t *pmech;
193 	char *next_token;
194 	char *value;
195 	char *lasts;
196 	int count = 0;
197 	int rc = SUCCESS;
198 
199 	if (pent == NULL) {
200 		return (FAILURE);
201 	}
202 
203 	if (strncmp(buf, EF_DISABLED, sizeof (EF_DISABLED) - 1) == 0) {
204 		pent->flag_enabledlist = B_FALSE;
205 	} else if (strncmp(buf, EF_ENABLED, sizeof (EF_ENABLED) - 1) == 0) {
206 		pent->flag_enabledlist = B_TRUE;
207 	} else if (strncmp(buf, EF_NORANDOM, sizeof (EF_NORANDOM) - 1) == 0) {
208 		pent->flag_norandom = B_TRUE;
209 		return (rc);
210 	} else if (strncmp(buf, METASLOT_TOKEN,
211 	    sizeof (METASLOT_TOKEN) - 1) == 0) {
212 		if (value = strpbrk(buf, SEP_EQUAL)) {
213 			value++; /* get rid of = */
214 			(void) strlcpy((char *)pent->metaslot_ks_token, value,
215 			    TOKEN_LABEL_SIZE);
216 			return (SUCCESS);
217 		} else {
218 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
219 			    _PATH_PKCS11_CONF);
220 			return (FAILURE);
221 		}
222 	} else if (strncmp(buf, METASLOT_SLOT,
223 	    sizeof (METASLOT_SLOT) - 1) == 0) {
224 		if (value = strpbrk(buf, SEP_EQUAL)) {
225 			value++; /* get rid of = */
226 			(void) strlcpy((char *)pent->metaslot_ks_slot, value,
227 			    SLOT_DESCRIPTION_SIZE);
228 			return (SUCCESS);
229 		} else {
230 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
231 			    _PATH_PKCS11_CONF);
232 			return (FAILURE);
233 		}
234 	} else if (strncmp(buf, METASLOT_STATUS,
235 	    sizeof (METASLOT_STATUS) - 1) == 0) {
236 		if (value = strpbrk(buf, SEP_EQUAL)) {
237 			value++; /* get rid of = */
238 			if (strcmp(value, METASLOT_DISABLED) == 0) {
239 				pent->flag_metaslot_enabled = B_FALSE;
240 			} else if (strcmp(value, METASLOT_ENABLED) == 0) {
241 				pent->flag_metaslot_enabled = B_TRUE;
242 			} else {
243 				cryptoerror(LOG_ERR, "failed to parse %s.\n",
244 				    _PATH_PKCS11_CONF);
245 				return (FAILURE);
246 			}
247 			return (SUCCESS);
248 		} else {
249 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
250 			    _PATH_PKCS11_CONF);
251 			return (FAILURE);
252 		}
253 	} else if (strncmp(buf, METASLOT_AUTO_KEY_MIGRATE,
254 	    sizeof (METASLOT_AUTO_KEY_MIGRATE) - 1) == 0) {
255 		if (value = strpbrk(buf, SEP_EQUAL)) {
256 			value++; /* get rid of = */
257 			if (strcmp(value, METASLOT_DISABLED) == 0) {
258 				pent->flag_metaslot_auto_key_migrate = B_FALSE;
259 			} else if (strcmp(value, METASLOT_ENABLED) == 0) {
260 				pent->flag_metaslot_auto_key_migrate = B_TRUE;
261 			} else {
262 				cryptoerror(LOG_ERR, "failed to parse %s.\n",
263 				    _PATH_PKCS11_CONF);
264 				return (FAILURE);
265 			}
266 			return (SUCCESS);
267 		} else {
268 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
269 			    _PATH_PKCS11_CONF);
270 			return (FAILURE);
271 		}
272 	} else {
273 		cryptoerror(LOG_ERR, "failed to parse %s.\n",
274 		    _PATH_PKCS11_CONF);
275 		return (FAILURE);
276 	}
277 
278 	if (value = strpbrk(buf, SEP_EQUAL)) {
279 		value++; /* get rid of = */
280 	}
281 
282 	if ((next_token = strtok_r(value, SEP_COMMA, &lasts)) == NULL) {
283 		if (pent->flag_enabledlist) {
284 			return (SUCCESS);
285 		} else {
286 			cryptoerror(LOG_ERR, "failed to parse %s.\n",
287 			    _PATH_PKCS11_CONF);
288 			return (FAILURE);
289 		}
290 	}
291 
292 	while (next_token) {
293 		if ((pmech = create_umech(next_token)) == NULL) {
294 			cryptoerror(LOG_ERR, "parsing %s, out of memory.\n",
295 			    _PATH_PKCS11_CONF);
296 			rc = FAILURE;
297 			break;
298 		}
299 
300 		if (phead == NULL) {
301 			phead = pcur = pmech;
302 		} else {
303 			pcur->next = pmech;
304 			pcur = pcur->next;
305 		}
306 		count++;
307 		next_token = strtok_r(NULL, SEP_COMMA, &lasts);
308 	}
309 
310 	if (rc == SUCCESS) {
311 		pent->policylist = phead;
312 		pent->count = count;
313 	} else {
314 		free_umechlist(phead);
315 	}
316 
317 	return (rc);
318 }
319 
320 
321 /*
322  * Create one item of type umechlist_t with the mechanism name.  A NULL is
323  * returned when the input name is NULL or the heap memory is insufficient.
324  */
325 umechlist_t *
326 create_umech(char *name)
327 {
328 	umechlist_t *pmech = NULL;
329 
330 	if (name == NULL) {
331 		return (NULL);
332 	}
333 
334 	if ((pmech = malloc(sizeof (umechlist_t))) != NULL) {
335 		(void) strlcpy(pmech->name, name, sizeof (pmech->name));
336 		pmech->next = NULL;
337 	}
338 
339 	return (pmech);
340 }
341 
342 
343 void
344 free_umechlist(umechlist_t *plist)
345 {
346 	umechlist_t *pnext;
347 
348 	while (plist != NULL) {
349 		pnext = plist->next;
350 		free(plist);
351 		plist = pnext;
352 	}
353 }
354 
355 
356 void
357 free_uentry(uentry_t  *pent)
358 {
359 	if (pent == NULL) {
360 		return;
361 	} else {
362 		free_umechlist(pent->policylist);
363 		free(pent);
364 	}
365 }
366 
367 
368 void
369 free_uentrylist(uentrylist_t *entrylist)
370 {
371 	uentrylist_t *pnext;
372 
373 	while (entrylist != NULL) {
374 		pnext = entrylist->next;
375 		free_uentry(entrylist->puent);
376 		free(entrylist);
377 		entrylist = pnext;
378 	}
379 }
380