xref: /illumos-gate/usr/src/lib/libdladm/common/secobj.c (revision a9489f613f667faf21ee68381b627b28ddb22188)
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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <strings.h>
29 #include <errno.h>
30 #include <ctype.h>
31 #include <fcntl.h>
32 #include <sys/stat.h>
33 #include <sys/dld.h>
34 #include <libinetutil.h>
35 #include <libdllink.h>
36 #include <libdladm_impl.h>
37 
38 static dladm_status_t	i_dladm_set_secobj_db(const char *,
39 			    dladm_secobj_class_t, uint8_t *, uint_t);
40 static dladm_status_t	i_dladm_get_secobj_db(const char *,
41 			    dladm_secobj_class_t *, uint8_t *, uint_t *);
42 static dladm_status_t	i_dladm_unset_secobj_db(const char *);
43 static dladm_status_t	i_dladm_walk_secobj_db(void *,
44 			    boolean_t (*)(void *, const char *));
45 
46 typedef struct secobj_class_info {
47 	const char		*sc_name;
48 	dld_secobj_class_t	sc_dldclass;
49 } secobj_class_info_t;
50 
51 static secobj_class_info_t secobj_class_table[] = {
52 	{"wep",	DLD_SECOBJ_CLASS_WEP},
53 	{"wpa",	DLD_SECOBJ_CLASS_WPA}
54 };
55 
56 #define	SECOBJ_MAXBUFSZ	65536
57 #define	NSECOBJCLASS \
58 	(sizeof (secobj_class_table) / sizeof (secobj_class_info_t))
59 
60 static boolean_t
61 dladm_check_secobjclass(dladm_secobj_class_t class)
62 {
63 	return (class >= 0 && class < NSECOBJCLASS);
64 }
65 
66 dladm_status_t
67 dladm_str2secobjclass(const char *str, dladm_secobj_class_t *class)
68 {
69 	int			i;
70 	secobj_class_info_t	*sp;
71 
72 	for (i = 0; i < NSECOBJCLASS; i++) {
73 		sp = &secobj_class_table[i];
74 		if (strcasecmp(str, sp->sc_name) == 0) {
75 			*class = i;
76 			return (DLADM_STATUS_OK);
77 		}
78 	}
79 	return (DLADM_STATUS_BADARG);
80 }
81 
82 const char *
83 dladm_secobjclass2str(dladm_secobj_class_t class, char *buf)
84 {
85 	const char		*s;
86 
87 	if (!dladm_check_secobjclass(class))
88 		s = "";
89 	else
90 		s = secobj_class_table[class].sc_name;
91 
92 	(void) snprintf(buf, DLADM_STRSIZE, "%s", s);
93 	return (buf);
94 }
95 
96 static boolean_t
97 dladm_convert_secobjclass(dladm_secobj_class_t class,
98     dld_secobj_class_t *dldclass)
99 {
100 	if (!dladm_check_secobjclass(class))
101 		return (B_FALSE);
102 
103 	*dldclass = secobj_class_table[class].sc_dldclass;
104 	return (B_TRUE);
105 }
106 
107 static boolean_t
108 dladm_convert_dldsecobjclass(dld_secobj_class_t dldclass,
109     dladm_secobj_class_t *class)
110 {
111 	int			i;
112 	secobj_class_info_t	*sp;
113 
114 	for (i = 0; i < NSECOBJCLASS; i++) {
115 		sp = &secobj_class_table[i];
116 		if (dldclass == sp->sc_dldclass) {
117 			*class = i;
118 			return (B_TRUE);
119 		}
120 	}
121 	return (B_FALSE);
122 }
123 
124 dladm_status_t
125 dladm_set_secobj(const char *obj_name, dladm_secobj_class_t class,
126     uint8_t *obj_val, uint_t obj_len, uint_t flags)
127 {
128 	int			fd;
129 	dladm_status_t		status = DLADM_STATUS_OK;
130 	dld_ioc_secobj_set_t	secobj_set;
131 	dld_secobj_t		*objp;
132 
133 	if (!dladm_valid_secobj_name(obj_name))
134 		return (DLADM_STATUS_BADARG);
135 
136 	if (!dladm_check_secobjclass(class) || flags == 0 ||
137 	    obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
138 	    obj_val == NULL || obj_len == 0 || obj_len > DLD_SECOBJ_VAL_MAX)
139 		return (DLADM_STATUS_BADARG);
140 
141 	if ((flags & DLADM_OPT_ACTIVE) == 0)
142 		goto persist;
143 
144 	bzero(&secobj_set, sizeof (secobj_set));
145 	objp = &secobj_set.ss_obj;
146 	if (!dladm_convert_secobjclass(class, &objp->so_class))
147 		return (DLADM_STATUS_BADARG);
148 
149 	(void) strlcpy(objp->so_name, obj_name, DLD_SECOBJ_NAME_MAX);
150 	bcopy(obj_val, objp->so_val, obj_len);
151 	objp->so_len = obj_len;
152 
153 	if ((flags & DLADM_OPT_CREATE) != 0)
154 		secobj_set.ss_flags = DLD_SECOBJ_OPT_CREATE;
155 
156 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
157 		return (dladm_errno2status(errno));
158 
159 	if (ioctl(fd, DLDIOC_SECOBJ_SET, &secobj_set) < 0)
160 		status = dladm_errno2status(errno);
161 
162 	(void) close(fd);
163 
164 	if (status != DLADM_STATUS_OK)
165 		return (status);
166 
167 persist:
168 	if ((flags & DLADM_OPT_PERSIST) != 0) {
169 		status = i_dladm_set_secobj_db(obj_name, class,
170 		    obj_val, obj_len);
171 	}
172 	return (status);
173 }
174 
175 dladm_status_t
176 dladm_get_secobj(const char *obj_name, dladm_secobj_class_t *classp,
177     uint8_t *obj_val, uint_t *obj_lenp, uint_t flags)
178 {
179 	int			fd;
180 	dladm_status_t		status = DLADM_STATUS_OK;
181 	dld_ioc_secobj_get_t	secobj_get;
182 	dld_secobj_t		*objp;
183 
184 	if (obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
185 	    obj_val == NULL || obj_lenp == NULL || *obj_lenp == 0 ||
186 	    *obj_lenp > DLD_SECOBJ_VAL_MAX)
187 		return (DLADM_STATUS_BADARG);
188 
189 	if ((flags & DLADM_OPT_PERSIST) != 0) {
190 		return (i_dladm_get_secobj_db(obj_name, classp,
191 		    obj_val, obj_lenp));
192 	}
193 
194 	bzero(&secobj_get, sizeof (secobj_get));
195 	objp = &secobj_get.sg_obj;
196 	(void) strlcpy(objp->so_name, obj_name, DLD_SECOBJ_NAME_MAX);
197 
198 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
199 		return (dladm_errno2status(errno));
200 
201 	secobj_get.sg_size = sizeof (secobj_get);
202 	if (ioctl(fd, DLDIOC_SECOBJ_GET, &secobj_get) < 0)
203 		status = dladm_errno2status(errno);
204 
205 	(void) close(fd);
206 	if (objp->so_len > *obj_lenp)
207 		return (DLADM_STATUS_TOOSMALL);
208 
209 	if (!dladm_convert_dldsecobjclass(objp->so_class, classp))
210 		return (DLADM_STATUS_FAILED);
211 
212 	*obj_lenp = objp->so_len;
213 	bcopy(objp->so_val, obj_val, *obj_lenp);
214 	return (status);
215 }
216 
217 dladm_status_t
218 dladm_unset_secobj(const char *obj_name, uint_t flags)
219 {
220 	int			fd;
221 	dladm_status_t		status = DLADM_STATUS_OK;
222 	dld_ioc_secobj_unset_t	secobj_unset;
223 
224 	if (obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
225 	    flags == 0)
226 		return (DLADM_STATUS_BADARG);
227 
228 	if ((flags & DLADM_OPT_ACTIVE) == 0)
229 		goto persist;
230 
231 	bzero(&secobj_unset, sizeof (secobj_unset));
232 	(void) strlcpy(secobj_unset.su_name, obj_name, DLD_SECOBJ_NAME_MAX);
233 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
234 		return (dladm_errno2status(errno));
235 
236 	if (ioctl(fd, DLDIOC_SECOBJ_UNSET, &secobj_unset) < 0)
237 		status = dladm_errno2status(errno);
238 
239 	(void) close(fd);
240 	if (status != DLADM_STATUS_OK)
241 		return (status);
242 
243 persist:
244 	if ((flags & DLADM_OPT_PERSIST) != 0)
245 		status = i_dladm_unset_secobj_db(obj_name);
246 
247 	return (status);
248 }
249 
250 dladm_status_t
251 dladm_walk_secobj(void *arg, boolean_t (*func)(void *, const char *),
252     uint_t flags)
253 {
254 	int			fd = -1;
255 	dladm_status_t		status = DLADM_STATUS_OK;
256 	dld_ioc_secobj_get_t	*secobj_getp;
257 	dld_secobj_t		*objp;
258 	size_t			secobj_bufsz;
259 
260 	if ((flags & DLADM_OPT_PERSIST) != 0)
261 		return (i_dladm_walk_secobj_db(arg, func));
262 
263 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
264 		return (dladm_errno2status(errno));
265 
266 	/* Start with enough room for 10 objects, increase if necessary. */
267 	secobj_bufsz = sizeof (*secobj_getp) + (10 * sizeof (*objp));
268 	secobj_getp = calloc(1, secobj_bufsz);
269 	if (secobj_getp == NULL) {
270 		status = dladm_errno2status(errno);
271 		goto done;
272 	}
273 
274 tryagain:
275 	secobj_getp->sg_size = secobj_bufsz;
276 	if (ioctl(fd, DLDIOC_SECOBJ_GET, secobj_getp) < 0) {
277 		if (errno == ENOSPC) {
278 			/* Increase the buffer size and try again. */
279 			secobj_bufsz *= 2;
280 			if (secobj_bufsz > SECOBJ_MAXBUFSZ) {
281 				status = dladm_errno2status(errno);
282 				goto done;
283 			}
284 			secobj_getp = realloc(secobj_getp, secobj_bufsz);
285 			if (secobj_getp == NULL) {
286 				status = dladm_errno2status(errno);
287 				goto done;
288 			}
289 			bzero(secobj_getp, secobj_bufsz);
290 			goto tryagain;
291 		}
292 		status = dladm_errno2status(errno);
293 		goto done;
294 	}
295 
296 	objp = (dld_secobj_t *)(secobj_getp + 1);
297 	while (secobj_getp->sg_count > 0) {
298 		if (!func(arg, objp->so_name))
299 			goto done;
300 		secobj_getp->sg_count--;
301 		objp++;
302 	}
303 done:
304 	(void) close(fd);
305 	free(secobj_getp);
306 	return (status);
307 }
308 
309 /*
310  * Data structures used for implementing persistent secure objects
311  */
312 typedef struct secobj_info {
313 	const char		*si_name;
314 	dladm_secobj_class_t	*si_classp;
315 	uint8_t			*si_val;
316 	uint_t			*si_lenp;
317 } secobj_info_t;
318 
319 typedef struct secobj_name {
320 	char			*sn_name;
321 	struct secobj_name	*sn_next;
322 } secobj_name_t;
323 
324 typedef struct secobj_db_state	secobj_db_state_t;
325 
326 typedef boolean_t (*secobj_db_op_t)(struct secobj_db_state *, char *,
327     secobj_info_t *, dladm_status_t *);
328 
329 struct secobj_db_state {
330 	secobj_db_op_t		ss_op;
331 	secobj_info_t		ss_info;
332 	secobj_name_t		**ss_namelist;
333 };
334 
335 /*
336  * Update or generate a secobj entry using the info in ssp->ss_info.
337  */
338 /* ARGSUSED */
339 static boolean_t
340 process_secobj_set(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
341     dladm_status_t *statusp)
342 {
343 	char	tmpbuf[MAXLINELEN];
344 	char	classbuf[DLADM_STRSIZE];
345 	char	*ptr = tmpbuf, *lim = tmpbuf + MAXLINELEN;
346 	int	i;
347 
348 	sip = &ssp->ss_info;
349 
350 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", sip->si_name);
351 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t",
352 	    dladm_secobjclass2str(*sip->si_classp, classbuf));
353 
354 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "0x");
355 	for (i = 0; i < *sip->si_lenp; i++) {
356 		ptr += snprintf(ptr, BUFLEN(lim, ptr), "%02x",
357 		    sip->si_val[i] & 0xff);
358 	}
359 	if (ptr > lim) {
360 		*statusp = DLADM_STATUS_TOOSMALL;
361 		return (B_FALSE);
362 	}
363 	(void) snprintf(buf, MAXLINELEN, "%s\n", tmpbuf);
364 	return (B_FALSE);
365 }
366 
367 /* ARGSUSED */
368 static boolean_t
369 process_secobj_get(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
370     dladm_status_t *statusp)
371 {
372 	if (*sip->si_lenp > *ssp->ss_info.si_lenp) {
373 		*statusp = DLADM_STATUS_TOOSMALL;
374 		return (B_FALSE);
375 	}
376 	bcopy(sip->si_val, ssp->ss_info.si_val, *sip->si_lenp);
377 	*ssp->ss_info.si_lenp = *sip->si_lenp;
378 	*ssp->ss_info.si_classp = *sip->si_classp;
379 	return (B_FALSE);
380 }
381 
382 /* ARGSUSED */
383 static boolean_t
384 process_secobj_unset(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
385     dladm_status_t *statusp)
386 {
387 	/*
388 	 * Delete line.
389 	 */
390 	buf[0] = '\0';
391 	return (B_FALSE);
392 }
393 
394 /* ARGSUSED */
395 static boolean_t
396 process_secobj_walk(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
397     dladm_status_t *statusp)
398 {
399 	secobj_name_t	*snp;
400 
401 	if ((snp = malloc(sizeof (*snp))) == NULL)
402 		return (B_TRUE);
403 
404 	if ((snp->sn_name = strdup(sip->si_name)) == NULL) {
405 		free(snp);
406 		return (B_TRUE);
407 	}
408 
409 	snp->sn_next = NULL;
410 	*ssp->ss_namelist = snp;
411 	ssp->ss_namelist = &snp->sn_next;
412 	return (B_TRUE);
413 }
414 
415 /* ARGSUSED */
416 static boolean_t
417 process_secobj_init(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
418     dladm_status_t *statusp)
419 {
420 	*statusp = dladm_set_secobj(sip->si_name, *sip->si_classp, sip->si_val,
421 	    *sip->si_lenp, DLADM_OPT_ACTIVE | DLADM_OPT_CREATE);
422 	return (B_TRUE);
423 }
424 
425 static int
426 parse_secobj_val(char *buf, secobj_info_t *sip)
427 {
428 	if (strncmp(buf, "0x", 2) != 0)
429 		return (EINVAL);
430 
431 	return (hexascii_to_octet(buf + 2, strlen(buf) - 2,
432 	    sip->si_val, sip->si_lenp));
433 }
434 
435 static boolean_t
436 process_secobj_line(secobj_db_state_t *ssp, char *buf,
437     dladm_status_t *statusp)
438 {
439 	secobj_info_t		sinfo;
440 	dladm_secobj_class_t	class;
441 	uint8_t			val[DLADM_SECOBJ_VAL_MAX];
442 	uint_t			vlen;
443 	int			i, len, nlen;
444 	char			*str, *lasts;
445 
446 	/*
447 	 * Skip leading spaces, blank lines, and comments.
448 	 */
449 	len = strlen(buf);
450 	for (i = 0; i < len; i++) {
451 		if (!isspace(buf[i]))
452 			break;
453 	}
454 	if (i == len || buf[i] == '#')
455 		return (B_TRUE);
456 
457 	str = buf + i;
458 	if (ssp->ss_info.si_name != NULL) {
459 		/*
460 		 * Skip objects we're not interested in.
461 		 */
462 		nlen = strlen(ssp->ss_info.si_name);
463 		if (strncmp(str, ssp->ss_info.si_name, nlen) != 0 ||
464 		    !isspace(str[nlen]))
465 			return (B_TRUE);
466 
467 		sinfo.si_name = ssp->ss_info.si_name;
468 	} else {
469 		/*
470 		 * If an object is not specified, find the object name
471 		 * and assign it to sinfo.si_name.
472 		 */
473 		if (strtok_r(str, " \n\t", &lasts) == NULL)
474 			goto fail;
475 
476 		nlen = strlen(str);
477 		sinfo.si_name = str;
478 	}
479 	str += nlen + 1;
480 	if (str >= buf + len)
481 		goto fail;
482 
483 	/*
484 	 * Find the class name.
485 	 */
486 	if ((str = strtok_r(str, " \n\t", &lasts)) == NULL)
487 		goto fail;
488 
489 	*statusp = dladm_str2secobjclass(str, &class);
490 	if (*statusp != DLADM_STATUS_OK)
491 		goto fail;
492 
493 	/*
494 	 * Find the object value.
495 	 */
496 	if ((str = strtok_r(NULL, " \n\t", &lasts)) == NULL)
497 		goto fail;
498 
499 	vlen = DLADM_SECOBJ_VAL_MAX;
500 	sinfo.si_classp = &class;
501 	sinfo.si_val = val;
502 	sinfo.si_lenp = &vlen;
503 	if (parse_secobj_val(str, &sinfo) != 0)
504 		goto fail;
505 
506 	return ((*ssp->ss_op)(ssp, buf, &sinfo, statusp));
507 
508 fail:
509 	/*
510 	 * Delete corrupted line.
511 	 */
512 	buf[0] = '\0';
513 	return (B_TRUE);
514 }
515 
516 static dladm_status_t
517 process_secobj_db(void *arg, FILE *fp, FILE *nfp)
518 {
519 	secobj_db_state_t	*ssp = arg;
520 	dladm_status_t		status = DLADM_STATUS_OK;
521 	char			buf[MAXLINELEN];
522 	boolean_t		cont = B_TRUE;
523 
524 	/*
525 	 * This loop processes each line of the configuration file.
526 	 * buf can potentially be modified by process_secobj_line().
527 	 * If this is a write operation and buf is not truncated, buf will
528 	 * be written to disk. process_secobj_line() will no longer be
529 	 * called after it returns B_FALSE; at which point the remainder
530 	 * of the file will continue to be read and, if necessary, written
531 	 * to disk as well.
532 	 */
533 	while (fgets(buf, MAXLINELEN, fp) != NULL) {
534 		if (cont)
535 			cont = process_secobj_line(ssp, buf, &status);
536 
537 		if (nfp != NULL && buf[0] != '\0' && fputs(buf, nfp) == EOF) {
538 			status = dladm_errno2status(errno);
539 			break;
540 		}
541 	}
542 	if (status != DLADM_STATUS_OK || !cont)
543 		return (status);
544 
545 	if (ssp->ss_op == process_secobj_set) {
546 		/*
547 		 * If the specified object is not found above, we add the
548 		 * object to the configuration file.
549 		 */
550 		(void) (*ssp->ss_op)(ssp, buf, NULL, &status);
551 		if (status == DLADM_STATUS_OK && fputs(buf, nfp) == EOF)
552 			status = dladm_errno2status(errno);
553 	}
554 
555 	if (ssp->ss_op == process_secobj_unset ||
556 	    ssp->ss_op == process_secobj_get)
557 		status = DLADM_STATUS_NOTFOUND;
558 
559 	return (status);
560 }
561 
562 #define	SECOBJ_RW_DB(statep, writeop) \
563 	(i_dladm_rw_db("/etc/dladm/secobj.conf", S_IRUSR | S_IWUSR, \
564 	process_secobj_db, (statep), (writeop)))
565 
566 static dladm_status_t
567 i_dladm_set_secobj_db(const char *obj_name, dladm_secobj_class_t class,
568     uint8_t *obj_val, uint_t obj_len)
569 {
570 	secobj_db_state_t	state;
571 
572 	state.ss_op = process_secobj_set;
573 	state.ss_info.si_name = obj_name;
574 	state.ss_info.si_classp = &class;
575 	state.ss_info.si_val = obj_val;
576 	state.ss_info.si_lenp = &obj_len;
577 	state.ss_namelist = NULL;
578 
579 	return (SECOBJ_RW_DB(&state, B_TRUE));
580 }
581 
582 static dladm_status_t
583 i_dladm_get_secobj_db(const char *obj_name, dladm_secobj_class_t *classp,
584     uint8_t *obj_val, uint_t *obj_lenp)
585 {
586 	secobj_db_state_t	state;
587 
588 	state.ss_op = process_secobj_get;
589 	state.ss_info.si_name = obj_name;
590 	state.ss_info.si_classp = classp;
591 	state.ss_info.si_val = obj_val;
592 	state.ss_info.si_lenp = obj_lenp;
593 	state.ss_namelist = NULL;
594 
595 	return (SECOBJ_RW_DB(&state, B_FALSE));
596 }
597 
598 static dladm_status_t
599 i_dladm_unset_secobj_db(const char *obj_name)
600 {
601 	secobj_db_state_t	state;
602 
603 	state.ss_op = process_secobj_unset;
604 	state.ss_info.si_name = obj_name;
605 	state.ss_info.si_classp = NULL;
606 	state.ss_info.si_val = NULL;
607 	state.ss_info.si_lenp = NULL;
608 	state.ss_namelist = NULL;
609 
610 	return (SECOBJ_RW_DB(&state, B_TRUE));
611 }
612 
613 static dladm_status_t
614 i_dladm_walk_secobj_db(void *arg, boolean_t (*func)(void *, const char *))
615 {
616 	secobj_db_state_t	state;
617 	secobj_name_t		*snp = NULL, *fsnp;
618 	dladm_status_t		status;
619 	boolean_t		cont = B_TRUE;
620 
621 	state.ss_op = process_secobj_walk;
622 	state.ss_info.si_name = NULL;
623 	state.ss_info.si_classp = NULL;
624 	state.ss_info.si_val = NULL;
625 	state.ss_info.si_lenp = NULL;
626 	state.ss_namelist = &snp;
627 
628 	status = SECOBJ_RW_DB(&state, B_FALSE);
629 	if (status != DLADM_STATUS_OK)
630 		return (status);
631 
632 	while (snp != NULL) {
633 		fsnp = snp;
634 		snp = snp->sn_next;
635 		if (cont)
636 			cont = func(arg, fsnp->sn_name);
637 		free(fsnp->sn_name);
638 		free(fsnp);
639 	}
640 	return (status);
641 }
642 
643 dladm_status_t
644 dladm_init_secobj(void)
645 {
646 	secobj_db_state_t	state;
647 
648 	state.ss_op = process_secobj_init;
649 	state.ss_info.si_name = NULL;
650 	state.ss_info.si_classp = NULL;
651 	state.ss_info.si_val = NULL;
652 	state.ss_info.si_lenp = NULL;
653 	state.ss_namelist = NULL;
654 
655 	return (SECOBJ_RW_DB(&state, B_FALSE));
656 }
657 
658 boolean_t
659 dladm_valid_secobj_name(const char *secobj_name)
660 {
661 	size_t len = strlen(secobj_name);
662 	const char *cp;
663 
664 	if (len + 1 > DLADM_SECOBJ_NAME_MAX)
665 		return (B_FALSE);
666 
667 	/*
668 	 * The legal characters in a secobj name are:
669 	 * alphanumeric (a-z, A-Z, 0-9), '.', '_', '-'.
670 	 */
671 	for (cp = secobj_name; *cp != '\0'; cp++) {
672 		if (!isalnum(*cp) &&
673 		    (*cp != '.') && (*cp != '_') && (*cp != '-'))
674 			return (B_FALSE);
675 	}
676 
677 	return (B_TRUE);
678 }
679