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