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