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