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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <strings.h>
31 #include <time.h>
32 #include <unistd.h>
33 #include <locale.h>
34 #include <sys/types.h>
35 #include <zone.h>
36 #include <sys/stat.h>
37 #include "cryptoadm.h"
38
39 static int err; /* To store errno which may be overwritten by gettext() */
40 static int build_entrylist(entry_t *, entrylist_t **);
41 static entry_t *dup_entry(entry_t *);
42 static mechlist_t *dup_mechlist(mechlist_t *);
43 static entry_t *getent(char *, entrylist_t *);
44 static int interpret(char *, entry_t **);
45 static int parse_sup_dis_list(char *, entry_t *);
46
47
48 /*
49 * Duplicate the mechanism list. A null pointer is returned if the storage
50 * space available is insufficient or the input argument is NULL.
51 */
52 static mechlist_t *
53 dup_mechlist(mechlist_t *plist)
54 {
55 mechlist_t *pres = NULL;
56 mechlist_t *pcur;
57 mechlist_t *ptmp;
58 int rc = SUCCESS;
59
60 while (plist != NULL) {
61 if (!(ptmp = create_mech(plist->name))) {
62 rc = FAILURE;
63 break;
64 }
65
161 return (NULL);
162 }
163 }
164
165 return (pent2);
166 }
167
168
169 /*
170 * This routine parses the disabledlist or the supportedlist of an entry
171 * in the kcf.conf configuration file.
172 *
173 * Arguments:
174 * buf: an input argument which is a char string with the format of
175 * "disabledlist=m1,m2,..." or "supportedlist=m1,m2,..."
176 * pent: the entry for the disabledlist. This is an IN/OUT argument.
177 *
178 * Return value: SUCCESS or FAILURE.
179 */
180 static int
181 parse_sup_dis_list(char *buf, entry_t *pent)
182 {
183 mechlist_t *pmech = NULL;
184 mechlist_t *phead = NULL;
185 char *next_token;
186 char *value;
187 int count;
188 int supflag = B_FALSE;
189 int disflag = B_FALSE;
190 int rc = SUCCESS;
191
192 if (strncmp(buf, EF_SUPPORTED, strlen(EF_SUPPORTED)) == 0) {
193 supflag = B_TRUE;
194 } else if (strncmp(buf, EF_DISABLED, strlen(EF_DISABLED)) == 0) {
195 disflag = B_TRUE;
196 } else {
197 /* should not come here */
198 return (FAILURE);
199 }
200
201 if (value = strpbrk(buf, SEP_EQUAL)) {
202 value++; /* get rid of = */
203 } else {
204 cryptodebug("failed to parse the kcf.conf file.");
205 return (FAILURE);
206 }
207
208 if ((next_token = strtok(value, SEP_COMMA)) == NULL) {
209 cryptodebug("failed to parse the kcf.conf file.");
210 return (FAILURE);
211 }
212
213 if ((pmech = create_mech(next_token)) == NULL) {
214 return (FAILURE);
215 }
216
217 if (supflag) {
218 pent->suplist = phead = pmech;
219 } else if (disflag) {
220 pent->dislist = phead = pmech;
221 }
222
223 count = 1;
224 while (next_token) {
225 if (next_token = strtok(NULL, SEP_COMMA)) {
226 if ((pmech = create_mech(next_token)) == NULL) {
227 rc = FAILURE;
228 break;
229 }
230 count++;
231 phead->next = pmech;
232 phead = phead->next;
233 }
234 }
235
236 if (rc == SUCCESS) {
237 if (supflag) {
238 pent->sup_count = count;
239 } else if (disflag) {
240 pent->dis_count = count;
241 }
242 } else {
243 free_mechlist(phead);
244 }
245
246 return (rc);
247 }
248
249
250 /*
251 * Convert a char string containing a line about a provider
252 * from kcf.conf into an entry_t structure.
253 *
254 * See ent2str(), the reverse of this function, for the format of
255 * kcf.conf lines.
256 */
257 static int
258 interpret(char *buf, entry_t **ppent)
259 {
260 entry_t *pent = NULL;
261 char *token1;
262 char *token2;
263 char *token3;
264 int rc;
265
266 /* Get provider name */
267 if ((token1 = strtok(buf, SEP_COLON)) == NULL) { /* buf is NULL */
268 return (FAILURE);
269 };
270
271 pent = create_entry(token1);
272 if (pent == NULL) {
273 cryptodebug("out of memory.");
274 return (FAILURE);
275 }
276
277 if ((token2 = strtok(NULL, SEP_SEMICOLON)) == NULL) {
278 /* The entry contains a provider name only */
279 free_entry(pent);
280 return (FAILURE);
281 }
282
283 if (strncmp(token2, EF_UNLOAD, strlen(EF_UNLOAD)) == 0) {
284 pent->load = B_FALSE; /* cryptoadm unload */
285 if ((token2 = strtok(NULL, SEP_SEMICOLON)) == NULL) {
286 /* The entry contains a provider name:unload only */
287 free_entry(pent);
288 return (FAILURE);
289 }
290 }
291
292 /* need to get token3 first to satisfy nested strtok invocations */
293 token3 = strtok(NULL, SEP_SEMICOLON); /* optional */
294
295 /* parse supportedlist (or disabledlist if no supportedlist) */
296 if ((token2 != NULL) && ((rc = parse_sup_dis_list(token2, pent)) !=
297 SUCCESS)) {
298 free_entry(pent);
299 return (rc);
300 }
301
302 /* parse disabledlist (if there's a supportedlist) */
303 if ((token3 != NULL) && ((rc = parse_sup_dis_list(token3, pent)) !=
304 SUCCESS)) {
305 free_entry(pent);
306 return (rc);
307 }
308
309 *ppent = pent;
310 return (SUCCESS);
311 }
312
313
314 /*
315 * Add an entry about a provider from kcf.conf to the end of an entry list.
316 * If the entry list pplist is NULL, create the linked list with pent as the
317 * first element.
318 */
319 static int
320 build_entrylist(entry_t *pent, entrylist_t **pplist)
321 {
322 entrylist_t *pentlist;
323 entrylist_t *pcur = NULL;
324
325 pentlist = malloc(sizeof (entrylist_t));
326 if (pentlist == NULL) {
327 cryptodebug("out of memory.");
397 /*
398 * Free elements in a entrylist_t linked list,
399 * which lists providers in kcf.conf.
400 */
401 void
402 free_entrylist(entrylist_t *entrylist)
403 {
404 entrylist_t *pnext;
405
406 while (entrylist != NULL) {
407 pnext = entrylist->next;
408 free_entry(entrylist->pent);
409 entrylist = pnext;
410 }
411 }
412
413
414 /*
415 * Convert an entry to a string. This routine builds a string for the entry
416 * to be inserted in the kcf.conf file. Based on the content of each entry,
417 * the result string can be one of these 6 forms:
418 * - name:supportedlist=m1,m2,...,mj
419 * - name:disabledlist=m1,m2,...,mj
420 * - name:supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
421 *
422 * - name:unload;supportedlist=m1,m2,...,mj
423 * - name:unload;disabledlist=m1,m2,...,mj
424 * - name:unload;supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
425 *
426 * Note that the caller is responsible for freeing the returned string
427 * (with free_entry()).
428 * See interpret() for the reverse of this function: converting a string
429 * to an entry_t.
430 */
431 char *
432 ent2str(entry_t *pent)
433 {
434 char *buf;
435 mechlist_t *pcur = NULL;
436 boolean_t semicolon_separator = B_FALSE;
437
438
439 if (pent == NULL) {
440 return (NULL);
441 }
|
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 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <strings.h>
31 #include <time.h>
32 #include <unistd.h>
33 #include <locale.h>
34 #include <sys/types.h>
35 #include <zone.h>
36 #include <sys/stat.h>
37 #include "cryptoadm.h"
38
39 static int err; /* To store errno which may be overwritten by gettext() */
40 static int build_entrylist(entry_t *, entrylist_t **);
41 static entry_t *dup_entry(entry_t *);
42 static mechlist_t *dup_mechlist(mechlist_t *);
43 static entry_t *getent(char *, entrylist_t *);
44 static int interpret(char *, entry_t **);
45 static int parse_sup_dis_list(const char *buf, entry_t *pent);
46
47
48 /*
49 * Duplicate the mechanism list. A null pointer is returned if the storage
50 * space available is insufficient or the input argument is NULL.
51 */
52 static mechlist_t *
53 dup_mechlist(mechlist_t *plist)
54 {
55 mechlist_t *pres = NULL;
56 mechlist_t *pcur;
57 mechlist_t *ptmp;
58 int rc = SUCCESS;
59
60 while (plist != NULL) {
61 if (!(ptmp = create_mech(plist->name))) {
62 rc = FAILURE;
63 break;
64 }
65
161 return (NULL);
162 }
163 }
164
165 return (pent2);
166 }
167
168
169 /*
170 * This routine parses the disabledlist or the supportedlist of an entry
171 * in the kcf.conf configuration file.
172 *
173 * Arguments:
174 * buf: an input argument which is a char string with the format of
175 * "disabledlist=m1,m2,..." or "supportedlist=m1,m2,..."
176 * pent: the entry for the disabledlist. This is an IN/OUT argument.
177 *
178 * Return value: SUCCESS or FAILURE.
179 */
180 static int
181 parse_sup_dis_list(const char *buf, entry_t *pent)
182 {
183 mechlist_t *pmech = NULL;
184 mechlist_t *phead = NULL;
185 char *next_token;
186 char *value;
187 int count;
188 int supflag = B_FALSE;
189 int disflag = B_FALSE;
190 int rc = SUCCESS;
191
192 if (strncmp(buf, EF_SUPPORTED, strlen(EF_SUPPORTED)) == 0) {
193 supflag = B_TRUE;
194 } else if (strncmp(buf, EF_DISABLED, strlen(EF_DISABLED)) == 0) {
195 disflag = B_TRUE;
196 } else {
197 /* should not come here */
198 return (FAILURE);
199 }
200
201 if (value = strpbrk(buf, SEP_EQUAL)) {
202 value++; /* get rid of = */
203 } else {
204 cryptodebug("failed to parse the kcf.conf file.");
205 return (FAILURE);
206 }
207
208 if ((next_token = strtok(value, SEP_COMMA)) == NULL) {
209 cryptodebug("failed to parse the kcf.conf file.");
210 return (FAILURE);
211 }
212
213 if ((pmech = create_mech(next_token)) == NULL) {
214 return (FAILURE);
215 }
216
217 if (supflag) {
218 if (pent->suplist != NULL) {
219 cryptodebug("multiple supportedlist entries "
220 "for a mechanism in file kcf.conf.");
221 return (FAILURE);
222 } else {
223 pent->suplist = phead = pmech;
224 }
225 } else if (disflag) {
226 if (pent->dislist != NULL) {
227 cryptodebug("multiple disabledlist entries "
228 "for a mechanism in file kcf.conf.");
229 return (FAILURE);
230 } else {
231 pent->dislist = phead = pmech;
232 }
233 }
234
235 count = 1;
236 while (next_token) {
237 if (next_token = strtok(NULL, SEP_COMMA)) {
238 if ((pmech = create_mech(next_token)) == NULL) {
239 rc = FAILURE;
240 break;
241 }
242 count++;
243 phead->next = pmech;
244 phead = phead->next;
245 }
246 }
247
248 if (rc == SUCCESS) {
249 if (supflag) {
250 pent->sup_count = count;
251 } else if (disflag) {
252 pent->dis_count = count;
253 }
254 } else {
255 free_mechlist(phead);
256 }
257
258 return (rc);
259 }
260
261
262 /*
263 * Convert a char string containing a line about a provider
264 * from kcf.conf into an entry_t structure.
265 *
266 * Note: the input string, buf, may be modified by this function.
267 *
268 * See ent2str(), the reverse of this function, for the format of
269 * kcf.conf lines.
270 */
271 static int
272 interpret(char *buf, entry_t **ppent)
273 {
274 entry_t *pent = NULL;
275 char *token1;
276 char *token2;
277 char *token3;
278 int rc;
279
280 /* Get provider name */
281 if ((token1 = strtok(buf, SEP_COLON)) == NULL) { /* buf is NULL */
282 return (FAILURE);
283 };
284
285 pent = create_entry(token1);
286 if (pent == NULL) {
287 cryptodebug("out of memory.");
288 return (FAILURE);
289 }
290
291 if ((token2 = strtok(NULL, SEP_SEMICOLON)) == NULL) {
292 /* The entry contains a provider name only */
293 free_entry(pent);
294 return (FAILURE);
295 }
296
297 if (strncmp(token2, EF_UNLOAD, strlen(EF_UNLOAD)) == 0) {
298 pent->load = B_FALSE; /* cryptoadm unload */
299 token2 = strtok(NULL, SEP_SEMICOLON);
300 /*
301 * If token2 is NULL, the entry contains a
302 * provider name:unload only
303 */
304 }
305
306 if (token2 != NULL) {
307 /*
308 * Either supportedlist or disabledlist or both are present.
309 * Need to call strtok() to get token3 first, as function
310 * parse_sup_dis_list() makes strtok() calls on the
311 * token2 substring.
312 */
313 token3 = strtok(NULL, SEP_SEMICOLON); /* optional */
314
315 /* parse supportedlist (or disabledlist if no supportedlist) */
316 if ((rc = parse_sup_dis_list(token2, pent)) != SUCCESS) {
317 free_entry(pent);
318 return (rc);
319 }
320
321 /* parse disabledlist (if there's a supportedlist) */
322 if ((token3 != NULL) && ((rc = parse_sup_dis_list(token3,
323 pent)) != SUCCESS)) {
324 free_entry(pent);
325 return (rc);
326 }
327 }
328
329 *ppent = pent;
330 return (SUCCESS);
331 }
332
333
334 /*
335 * Add an entry about a provider from kcf.conf to the end of an entry list.
336 * If the entry list pplist is NULL, create the linked list with pent as the
337 * first element.
338 */
339 static int
340 build_entrylist(entry_t *pent, entrylist_t **pplist)
341 {
342 entrylist_t *pentlist;
343 entrylist_t *pcur = NULL;
344
345 pentlist = malloc(sizeof (entrylist_t));
346 if (pentlist == NULL) {
347 cryptodebug("out of memory.");
417 /*
418 * Free elements in a entrylist_t linked list,
419 * which lists providers in kcf.conf.
420 */
421 void
422 free_entrylist(entrylist_t *entrylist)
423 {
424 entrylist_t *pnext;
425
426 while (entrylist != NULL) {
427 pnext = entrylist->next;
428 free_entry(entrylist->pent);
429 entrylist = pnext;
430 }
431 }
432
433
434 /*
435 * Convert an entry to a string. This routine builds a string for the entry
436 * to be inserted in the kcf.conf file. Based on the content of each entry,
437 * the result string can be one of these 7 forms:
438 * - name:supportedlist=m1,m2,...,mj
439 * - name:disabledlist=m1,m2,...,mj
440 * - name:supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
441 *
442 * - name:unload
443 * - name:unload;supportedlist=m1,m2,...,mj
444 * - name:unload;disabledlist=m1,m2,...,mj
445 * - name:unload;supportedlist=m1,...,mj;disabledlist=m1,m2,...,mk
446 *
447 * Note that the caller is responsible for freeing the returned string
448 * (with free_entry()).
449 * See interpret() for the reverse of this function: converting a string
450 * to an entry_t.
451 */
452 char *
453 ent2str(entry_t *pent)
454 {
455 char *buf;
456 mechlist_t *pcur = NULL;
457 boolean_t semicolon_separator = B_FALSE;
458
459
460 if (pent == NULL) {
461 return (NULL);
462 }
|