xref: /titanic_44/usr/src/lib/libdladm/common/secobj.c (revision a9489f613f667faf21ee68381b627b28ddb22188)
10ba2cbe9Sxc151355 /*
20ba2cbe9Sxc151355  * CDDL HEADER START
30ba2cbe9Sxc151355  *
40ba2cbe9Sxc151355  * The contents of this file are subject to the terms of the
50ba2cbe9Sxc151355  * Common Development and Distribution License (the "License").
60ba2cbe9Sxc151355  * You may not use this file except in compliance with the License.
70ba2cbe9Sxc151355  *
80ba2cbe9Sxc151355  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90ba2cbe9Sxc151355  * or http://www.opensolaris.org/os/licensing.
100ba2cbe9Sxc151355  * See the License for the specific language governing permissions
110ba2cbe9Sxc151355  * and limitations under the License.
120ba2cbe9Sxc151355  *
130ba2cbe9Sxc151355  * When distributing Covered Code, include this CDDL HEADER in each
140ba2cbe9Sxc151355  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150ba2cbe9Sxc151355  * If applicable, add the following below this CDDL HEADER, with the
160ba2cbe9Sxc151355  * fields enclosed by brackets "[]" replaced with your own identifying
170ba2cbe9Sxc151355  * information: Portions Copyright [yyyy] [name of copyright owner]
180ba2cbe9Sxc151355  *
190ba2cbe9Sxc151355  * CDDL HEADER END
200ba2cbe9Sxc151355  */
210ba2cbe9Sxc151355 /*
22d62bc4baSyz147064  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230ba2cbe9Sxc151355  * Use is subject to license terms.
240ba2cbe9Sxc151355  */
250ba2cbe9Sxc151355 
260ba2cbe9Sxc151355 #include <unistd.h>
270ba2cbe9Sxc151355 #include <stdlib.h>
280ba2cbe9Sxc151355 #include <strings.h>
290ba2cbe9Sxc151355 #include <errno.h>
300ba2cbe9Sxc151355 #include <ctype.h>
310ba2cbe9Sxc151355 #include <fcntl.h>
320ba2cbe9Sxc151355 #include <sys/stat.h>
330ba2cbe9Sxc151355 #include <sys/dld.h>
340ba2cbe9Sxc151355 #include <libinetutil.h>
35f595a68aSyz147064 #include <libdllink.h>
360ba2cbe9Sxc151355 #include <libdladm_impl.h>
370ba2cbe9Sxc151355 
380ba2cbe9Sxc151355 static dladm_status_t	i_dladm_set_secobj_db(const char *,
390ba2cbe9Sxc151355 			    dladm_secobj_class_t, uint8_t *, uint_t);
400ba2cbe9Sxc151355 static dladm_status_t	i_dladm_get_secobj_db(const char *,
410ba2cbe9Sxc151355 			    dladm_secobj_class_t *, uint8_t *, uint_t *);
420ba2cbe9Sxc151355 static dladm_status_t	i_dladm_unset_secobj_db(const char *);
430ba2cbe9Sxc151355 static dladm_status_t	i_dladm_walk_secobj_db(void *,
440ba2cbe9Sxc151355 			    boolean_t (*)(void *, const char *));
450ba2cbe9Sxc151355 
460ba2cbe9Sxc151355 typedef struct secobj_class_info {
470ba2cbe9Sxc151355 	const char		*sc_name;
480ba2cbe9Sxc151355 	dld_secobj_class_t	sc_dldclass;
490ba2cbe9Sxc151355 } secobj_class_info_t;
500ba2cbe9Sxc151355 
510ba2cbe9Sxc151355 static secobj_class_info_t secobj_class_table[] = {
52a399b765Szf162725 	{"wep",	DLD_SECOBJ_CLASS_WEP},
53a399b765Szf162725 	{"wpa",	DLD_SECOBJ_CLASS_WPA}
540ba2cbe9Sxc151355 };
550ba2cbe9Sxc151355 
56eae72b5bSSebastien Roy #define	SECOBJ_MAXBUFSZ	65536
570ba2cbe9Sxc151355 #define	NSECOBJCLASS \
580ba2cbe9Sxc151355 	(sizeof (secobj_class_table) / sizeof (secobj_class_info_t))
590ba2cbe9Sxc151355 
600ba2cbe9Sxc151355 static boolean_t
610ba2cbe9Sxc151355 dladm_check_secobjclass(dladm_secobj_class_t class)
620ba2cbe9Sxc151355 {
630ba2cbe9Sxc151355 	return (class >= 0 && class < NSECOBJCLASS);
640ba2cbe9Sxc151355 }
650ba2cbe9Sxc151355 
660ba2cbe9Sxc151355 dladm_status_t
670ba2cbe9Sxc151355 dladm_str2secobjclass(const char *str, dladm_secobj_class_t *class)
680ba2cbe9Sxc151355 {
690ba2cbe9Sxc151355 	int			i;
700ba2cbe9Sxc151355 	secobj_class_info_t	*sp;
710ba2cbe9Sxc151355 
720ba2cbe9Sxc151355 	for (i = 0; i < NSECOBJCLASS; i++) {
730ba2cbe9Sxc151355 		sp = &secobj_class_table[i];
740ba2cbe9Sxc151355 		if (strcasecmp(str, sp->sc_name) == 0) {
750ba2cbe9Sxc151355 			*class = i;
760ba2cbe9Sxc151355 			return (DLADM_STATUS_OK);
770ba2cbe9Sxc151355 		}
780ba2cbe9Sxc151355 	}
790ba2cbe9Sxc151355 	return (DLADM_STATUS_BADARG);
800ba2cbe9Sxc151355 }
810ba2cbe9Sxc151355 
820ba2cbe9Sxc151355 const char *
830ba2cbe9Sxc151355 dladm_secobjclass2str(dladm_secobj_class_t class, char *buf)
840ba2cbe9Sxc151355 {
850ba2cbe9Sxc151355 	const char		*s;
860ba2cbe9Sxc151355 
870ba2cbe9Sxc151355 	if (!dladm_check_secobjclass(class))
880ba2cbe9Sxc151355 		s = "";
890ba2cbe9Sxc151355 	else
900ba2cbe9Sxc151355 		s = secobj_class_table[class].sc_name;
910ba2cbe9Sxc151355 
920ba2cbe9Sxc151355 	(void) snprintf(buf, DLADM_STRSIZE, "%s", s);
930ba2cbe9Sxc151355 	return (buf);
940ba2cbe9Sxc151355 }
950ba2cbe9Sxc151355 
960ba2cbe9Sxc151355 static boolean_t
970ba2cbe9Sxc151355 dladm_convert_secobjclass(dladm_secobj_class_t class,
980ba2cbe9Sxc151355     dld_secobj_class_t *dldclass)
990ba2cbe9Sxc151355 {
1000ba2cbe9Sxc151355 	if (!dladm_check_secobjclass(class))
1010ba2cbe9Sxc151355 		return (B_FALSE);
1020ba2cbe9Sxc151355 
1030ba2cbe9Sxc151355 	*dldclass = secobj_class_table[class].sc_dldclass;
1040ba2cbe9Sxc151355 	return (B_TRUE);
1050ba2cbe9Sxc151355 }
1060ba2cbe9Sxc151355 
1070ba2cbe9Sxc151355 static boolean_t
1080ba2cbe9Sxc151355 dladm_convert_dldsecobjclass(dld_secobj_class_t dldclass,
1090ba2cbe9Sxc151355     dladm_secobj_class_t *class)
1100ba2cbe9Sxc151355 {
1110ba2cbe9Sxc151355 	int			i;
1120ba2cbe9Sxc151355 	secobj_class_info_t	*sp;
1130ba2cbe9Sxc151355 
1140ba2cbe9Sxc151355 	for (i = 0; i < NSECOBJCLASS; i++) {
1150ba2cbe9Sxc151355 		sp = &secobj_class_table[i];
1160ba2cbe9Sxc151355 		if (dldclass == sp->sc_dldclass) {
1170ba2cbe9Sxc151355 			*class = i;
1180ba2cbe9Sxc151355 			return (B_TRUE);
1190ba2cbe9Sxc151355 		}
1200ba2cbe9Sxc151355 	}
1210ba2cbe9Sxc151355 	return (B_FALSE);
1220ba2cbe9Sxc151355 }
1230ba2cbe9Sxc151355 
1240ba2cbe9Sxc151355 dladm_status_t
1250ba2cbe9Sxc151355 dladm_set_secobj(const char *obj_name, dladm_secobj_class_t class,
1260ba2cbe9Sxc151355     uint8_t *obj_val, uint_t obj_len, uint_t flags)
1270ba2cbe9Sxc151355 {
1280ba2cbe9Sxc151355 	int			fd;
1290ba2cbe9Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
1300ba2cbe9Sxc151355 	dld_ioc_secobj_set_t	secobj_set;
1310ba2cbe9Sxc151355 	dld_secobj_t		*objp;
1320ba2cbe9Sxc151355 
133*a9489f61SAnurag S. Maskey 	if (!dladm_valid_secobj_name(obj_name))
134*a9489f61SAnurag S. Maskey 		return (DLADM_STATUS_BADARG);
135*a9489f61SAnurag S. Maskey 
1360ba2cbe9Sxc151355 	if (!dladm_check_secobjclass(class) || flags == 0 ||
1370ba2cbe9Sxc151355 	    obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
1380ba2cbe9Sxc151355 	    obj_val == NULL || obj_len == 0 || obj_len > DLD_SECOBJ_VAL_MAX)
1390ba2cbe9Sxc151355 		return (DLADM_STATUS_BADARG);
1400ba2cbe9Sxc151355 
141d62bc4baSyz147064 	if ((flags & DLADM_OPT_ACTIVE) == 0)
1420ba2cbe9Sxc151355 		goto persist;
1430ba2cbe9Sxc151355 
1440ba2cbe9Sxc151355 	bzero(&secobj_set, sizeof (secobj_set));
1450ba2cbe9Sxc151355 	objp = &secobj_set.ss_obj;
1460ba2cbe9Sxc151355 	if (!dladm_convert_secobjclass(class, &objp->so_class))
1470ba2cbe9Sxc151355 		return (DLADM_STATUS_BADARG);
1480ba2cbe9Sxc151355 
1490ba2cbe9Sxc151355 	(void) strlcpy(objp->so_name, obj_name, DLD_SECOBJ_NAME_MAX);
1500ba2cbe9Sxc151355 	bcopy(obj_val, objp->so_val, obj_len);
1510ba2cbe9Sxc151355 	objp->so_len = obj_len;
1520ba2cbe9Sxc151355 
1530ba2cbe9Sxc151355 	if ((flags & DLADM_OPT_CREATE) != 0)
1540ba2cbe9Sxc151355 		secobj_set.ss_flags = DLD_SECOBJ_OPT_CREATE;
1550ba2cbe9Sxc151355 
1560ba2cbe9Sxc151355 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
1570ba2cbe9Sxc151355 		return (dladm_errno2status(errno));
1580ba2cbe9Sxc151355 
159eae72b5bSSebastien Roy 	if (ioctl(fd, DLDIOC_SECOBJ_SET, &secobj_set) < 0)
1600ba2cbe9Sxc151355 		status = dladm_errno2status(errno);
1610ba2cbe9Sxc151355 
1620ba2cbe9Sxc151355 	(void) close(fd);
163a399b765Szf162725 
1640ba2cbe9Sxc151355 	if (status != DLADM_STATUS_OK)
1650ba2cbe9Sxc151355 		return (status);
1660ba2cbe9Sxc151355 
1670ba2cbe9Sxc151355 persist:
1680ba2cbe9Sxc151355 	if ((flags & DLADM_OPT_PERSIST) != 0) {
1690ba2cbe9Sxc151355 		status = i_dladm_set_secobj_db(obj_name, class,
1700ba2cbe9Sxc151355 		    obj_val, obj_len);
1710ba2cbe9Sxc151355 	}
1720ba2cbe9Sxc151355 	return (status);
1730ba2cbe9Sxc151355 }
1740ba2cbe9Sxc151355 
1750ba2cbe9Sxc151355 dladm_status_t
1760ba2cbe9Sxc151355 dladm_get_secobj(const char *obj_name, dladm_secobj_class_t *classp,
1770ba2cbe9Sxc151355     uint8_t *obj_val, uint_t *obj_lenp, uint_t flags)
1780ba2cbe9Sxc151355 {
1790ba2cbe9Sxc151355 	int			fd;
1800ba2cbe9Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
1810ba2cbe9Sxc151355 	dld_ioc_secobj_get_t	secobj_get;
1820ba2cbe9Sxc151355 	dld_secobj_t		*objp;
1830ba2cbe9Sxc151355 
1840ba2cbe9Sxc151355 	if (obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
1850ba2cbe9Sxc151355 	    obj_val == NULL || obj_lenp == NULL || *obj_lenp == 0 ||
1860ba2cbe9Sxc151355 	    *obj_lenp > DLD_SECOBJ_VAL_MAX)
1870ba2cbe9Sxc151355 		return (DLADM_STATUS_BADARG);
1880ba2cbe9Sxc151355 
1890ba2cbe9Sxc151355 	if ((flags & DLADM_OPT_PERSIST) != 0) {
1900ba2cbe9Sxc151355 		return (i_dladm_get_secobj_db(obj_name, classp,
1910ba2cbe9Sxc151355 		    obj_val, obj_lenp));
1920ba2cbe9Sxc151355 	}
1930ba2cbe9Sxc151355 
1940ba2cbe9Sxc151355 	bzero(&secobj_get, sizeof (secobj_get));
1950ba2cbe9Sxc151355 	objp = &secobj_get.sg_obj;
1960ba2cbe9Sxc151355 	(void) strlcpy(objp->so_name, obj_name, DLD_SECOBJ_NAME_MAX);
1970ba2cbe9Sxc151355 
1980ba2cbe9Sxc151355 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
1990ba2cbe9Sxc151355 		return (dladm_errno2status(errno));
2000ba2cbe9Sxc151355 
201eae72b5bSSebastien Roy 	secobj_get.sg_size = sizeof (secobj_get);
202eae72b5bSSebastien Roy 	if (ioctl(fd, DLDIOC_SECOBJ_GET, &secobj_get) < 0)
2030ba2cbe9Sxc151355 		status = dladm_errno2status(errno);
2040ba2cbe9Sxc151355 
2050ba2cbe9Sxc151355 	(void) close(fd);
2060ba2cbe9Sxc151355 	if (objp->so_len > *obj_lenp)
2070ba2cbe9Sxc151355 		return (DLADM_STATUS_TOOSMALL);
2080ba2cbe9Sxc151355 
2090ba2cbe9Sxc151355 	if (!dladm_convert_dldsecobjclass(objp->so_class, classp))
2100ba2cbe9Sxc151355 		return (DLADM_STATUS_FAILED);
2110ba2cbe9Sxc151355 
2120ba2cbe9Sxc151355 	*obj_lenp = objp->so_len;
2130ba2cbe9Sxc151355 	bcopy(objp->so_val, obj_val, *obj_lenp);
2140ba2cbe9Sxc151355 	return (status);
2150ba2cbe9Sxc151355 }
2160ba2cbe9Sxc151355 
2170ba2cbe9Sxc151355 dladm_status_t
2180ba2cbe9Sxc151355 dladm_unset_secobj(const char *obj_name, uint_t flags)
2190ba2cbe9Sxc151355 {
2200ba2cbe9Sxc151355 	int			fd;
2210ba2cbe9Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
2220ba2cbe9Sxc151355 	dld_ioc_secobj_unset_t	secobj_unset;
2230ba2cbe9Sxc151355 
2240ba2cbe9Sxc151355 	if (obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
2250ba2cbe9Sxc151355 	    flags == 0)
2260ba2cbe9Sxc151355 		return (DLADM_STATUS_BADARG);
2270ba2cbe9Sxc151355 
228d62bc4baSyz147064 	if ((flags & DLADM_OPT_ACTIVE) == 0)
2290ba2cbe9Sxc151355 		goto persist;
2300ba2cbe9Sxc151355 
2310ba2cbe9Sxc151355 	bzero(&secobj_unset, sizeof (secobj_unset));
2320ba2cbe9Sxc151355 	(void) strlcpy(secobj_unset.su_name, obj_name, DLD_SECOBJ_NAME_MAX);
2330ba2cbe9Sxc151355 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
2340ba2cbe9Sxc151355 		return (dladm_errno2status(errno));
2350ba2cbe9Sxc151355 
236eae72b5bSSebastien Roy 	if (ioctl(fd, DLDIOC_SECOBJ_UNSET, &secobj_unset) < 0)
2370ba2cbe9Sxc151355 		status = dladm_errno2status(errno);
2380ba2cbe9Sxc151355 
2390ba2cbe9Sxc151355 	(void) close(fd);
2400ba2cbe9Sxc151355 	if (status != DLADM_STATUS_OK)
2410ba2cbe9Sxc151355 		return (status);
2420ba2cbe9Sxc151355 
2430ba2cbe9Sxc151355 persist:
2440ba2cbe9Sxc151355 	if ((flags & DLADM_OPT_PERSIST) != 0)
2450ba2cbe9Sxc151355 		status = i_dladm_unset_secobj_db(obj_name);
2460ba2cbe9Sxc151355 
2470ba2cbe9Sxc151355 	return (status);
2480ba2cbe9Sxc151355 }
2490ba2cbe9Sxc151355 
2500ba2cbe9Sxc151355 dladm_status_t
2510ba2cbe9Sxc151355 dladm_walk_secobj(void *arg, boolean_t (*func)(void *, const char *),
2520ba2cbe9Sxc151355     uint_t flags)
2530ba2cbe9Sxc151355 {
2540ba2cbe9Sxc151355 	int			fd = -1;
2550ba2cbe9Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
2560ba2cbe9Sxc151355 	dld_ioc_secobj_get_t	*secobj_getp;
2570ba2cbe9Sxc151355 	dld_secobj_t		*objp;
258eae72b5bSSebastien Roy 	size_t			secobj_bufsz;
2590ba2cbe9Sxc151355 
2600ba2cbe9Sxc151355 	if ((flags & DLADM_OPT_PERSIST) != 0)
2610ba2cbe9Sxc151355 		return (i_dladm_walk_secobj_db(arg, func));
2620ba2cbe9Sxc151355 
263eae72b5bSSebastien Roy 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
264eae72b5bSSebastien Roy 		return (dladm_errno2status(errno));
2650ba2cbe9Sxc151355 
266eae72b5bSSebastien Roy 	/* Start with enough room for 10 objects, increase if necessary. */
267eae72b5bSSebastien Roy 	secobj_bufsz = sizeof (*secobj_getp) + (10 * sizeof (*objp));
268eae72b5bSSebastien Roy 	secobj_getp = calloc(1, secobj_bufsz);
269eae72b5bSSebastien Roy 	if (secobj_getp == NULL) {
2700ba2cbe9Sxc151355 		status = dladm_errno2status(errno);
2710ba2cbe9Sxc151355 		goto done;
2720ba2cbe9Sxc151355 	}
273eae72b5bSSebastien Roy 
274eae72b5bSSebastien Roy tryagain:
275eae72b5bSSebastien Roy 	secobj_getp->sg_size = secobj_bufsz;
276eae72b5bSSebastien Roy 	if (ioctl(fd, DLDIOC_SECOBJ_GET, secobj_getp) < 0) {
277eae72b5bSSebastien Roy 		if (errno == ENOSPC) {
278eae72b5bSSebastien Roy 			/* Increase the buffer size and try again. */
279eae72b5bSSebastien Roy 			secobj_bufsz *= 2;
280eae72b5bSSebastien Roy 			if (secobj_bufsz > SECOBJ_MAXBUFSZ) {
281eae72b5bSSebastien Roy 				status = dladm_errno2status(errno);
282eae72b5bSSebastien Roy 				goto done;
283eae72b5bSSebastien Roy 			}
284eae72b5bSSebastien Roy 			secobj_getp = realloc(secobj_getp, secobj_bufsz);
285eae72b5bSSebastien Roy 			if (secobj_getp == NULL) {
286eae72b5bSSebastien Roy 				status = dladm_errno2status(errno);
287eae72b5bSSebastien Roy 				goto done;
288eae72b5bSSebastien Roy 			}
289eae72b5bSSebastien Roy 			bzero(secobj_getp, secobj_bufsz);
290eae72b5bSSebastien Roy 			goto tryagain;
291eae72b5bSSebastien Roy 		}
2920ba2cbe9Sxc151355 		status = dladm_errno2status(errno);
2930ba2cbe9Sxc151355 		goto done;
2940ba2cbe9Sxc151355 	}
2950ba2cbe9Sxc151355 
2960ba2cbe9Sxc151355 	objp = (dld_secobj_t *)(secobj_getp + 1);
2970ba2cbe9Sxc151355 	while (secobj_getp->sg_count > 0) {
2980ba2cbe9Sxc151355 		if (!func(arg, objp->so_name))
2990ba2cbe9Sxc151355 			goto done;
3000ba2cbe9Sxc151355 		secobj_getp->sg_count--;
3010ba2cbe9Sxc151355 		objp++;
3020ba2cbe9Sxc151355 	}
3030ba2cbe9Sxc151355 done:
3040ba2cbe9Sxc151355 	(void) close(fd);
3050ba2cbe9Sxc151355 	free(secobj_getp);
3060ba2cbe9Sxc151355 	return (status);
3070ba2cbe9Sxc151355 }
3080ba2cbe9Sxc151355 
3090ba2cbe9Sxc151355 /*
3100ba2cbe9Sxc151355  * Data structures used for implementing persistent secure objects
3110ba2cbe9Sxc151355  */
3120ba2cbe9Sxc151355 typedef struct secobj_info {
3130ba2cbe9Sxc151355 	const char		*si_name;
3140ba2cbe9Sxc151355 	dladm_secobj_class_t	*si_classp;
3150ba2cbe9Sxc151355 	uint8_t			*si_val;
3160ba2cbe9Sxc151355 	uint_t			*si_lenp;
3170ba2cbe9Sxc151355 } secobj_info_t;
3180ba2cbe9Sxc151355 
3190ba2cbe9Sxc151355 typedef struct secobj_name {
3200ba2cbe9Sxc151355 	char			*sn_name;
3210ba2cbe9Sxc151355 	struct secobj_name	*sn_next;
3220ba2cbe9Sxc151355 } secobj_name_t;
3230ba2cbe9Sxc151355 
3240ba2cbe9Sxc151355 typedef struct secobj_db_state	secobj_db_state_t;
3250ba2cbe9Sxc151355 
3260ba2cbe9Sxc151355 typedef boolean_t (*secobj_db_op_t)(struct secobj_db_state *, char *,
3270ba2cbe9Sxc151355     secobj_info_t *, dladm_status_t *);
3280ba2cbe9Sxc151355 
3290ba2cbe9Sxc151355 struct secobj_db_state {
3300ba2cbe9Sxc151355 	secobj_db_op_t		ss_op;
3310ba2cbe9Sxc151355 	secobj_info_t		ss_info;
3320ba2cbe9Sxc151355 	secobj_name_t		**ss_namelist;
3330ba2cbe9Sxc151355 };
3340ba2cbe9Sxc151355 
3350ba2cbe9Sxc151355 /*
3360ba2cbe9Sxc151355  * Update or generate a secobj entry using the info in ssp->ss_info.
3370ba2cbe9Sxc151355  */
3380ba2cbe9Sxc151355 /* ARGSUSED */
3390ba2cbe9Sxc151355 static boolean_t
3400ba2cbe9Sxc151355 process_secobj_set(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
3410ba2cbe9Sxc151355     dladm_status_t *statusp)
3420ba2cbe9Sxc151355 {
3430ba2cbe9Sxc151355 	char	tmpbuf[MAXLINELEN];
3440ba2cbe9Sxc151355 	char	classbuf[DLADM_STRSIZE];
3450ba2cbe9Sxc151355 	char	*ptr = tmpbuf, *lim = tmpbuf + MAXLINELEN;
3460ba2cbe9Sxc151355 	int	i;
3470ba2cbe9Sxc151355 
3480ba2cbe9Sxc151355 	sip = &ssp->ss_info;
3490ba2cbe9Sxc151355 
3500ba2cbe9Sxc151355 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", sip->si_name);
3510ba2cbe9Sxc151355 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t",
3520ba2cbe9Sxc151355 	    dladm_secobjclass2str(*sip->si_classp, classbuf));
3530ba2cbe9Sxc151355 
3540ba2cbe9Sxc151355 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "0x");
3550ba2cbe9Sxc151355 	for (i = 0; i < *sip->si_lenp; i++) {
3560ba2cbe9Sxc151355 		ptr += snprintf(ptr, BUFLEN(lim, ptr), "%02x",
3570ba2cbe9Sxc151355 		    sip->si_val[i] & 0xff);
3580ba2cbe9Sxc151355 	}
3590ba2cbe9Sxc151355 	if (ptr > lim) {
3600ba2cbe9Sxc151355 		*statusp = DLADM_STATUS_TOOSMALL;
3610ba2cbe9Sxc151355 		return (B_FALSE);
3620ba2cbe9Sxc151355 	}
3630ba2cbe9Sxc151355 	(void) snprintf(buf, MAXLINELEN, "%s\n", tmpbuf);
3640ba2cbe9Sxc151355 	return (B_FALSE);
3650ba2cbe9Sxc151355 }
3660ba2cbe9Sxc151355 
3670ba2cbe9Sxc151355 /* ARGSUSED */
3680ba2cbe9Sxc151355 static boolean_t
3690ba2cbe9Sxc151355 process_secobj_get(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
3700ba2cbe9Sxc151355     dladm_status_t *statusp)
3710ba2cbe9Sxc151355 {
3720ba2cbe9Sxc151355 	if (*sip->si_lenp > *ssp->ss_info.si_lenp) {
3730ba2cbe9Sxc151355 		*statusp = DLADM_STATUS_TOOSMALL;
3740ba2cbe9Sxc151355 		return (B_FALSE);
3750ba2cbe9Sxc151355 	}
3760ba2cbe9Sxc151355 	bcopy(sip->si_val, ssp->ss_info.si_val, *sip->si_lenp);
3770ba2cbe9Sxc151355 	*ssp->ss_info.si_lenp = *sip->si_lenp;
3780ba2cbe9Sxc151355 	*ssp->ss_info.si_classp = *sip->si_classp;
3790ba2cbe9Sxc151355 	return (B_FALSE);
3800ba2cbe9Sxc151355 }
3810ba2cbe9Sxc151355 
3820ba2cbe9Sxc151355 /* ARGSUSED */
3830ba2cbe9Sxc151355 static boolean_t
3840ba2cbe9Sxc151355 process_secobj_unset(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
3850ba2cbe9Sxc151355     dladm_status_t *statusp)
3860ba2cbe9Sxc151355 {
3870ba2cbe9Sxc151355 	/*
3880ba2cbe9Sxc151355 	 * Delete line.
3890ba2cbe9Sxc151355 	 */
3900ba2cbe9Sxc151355 	buf[0] = '\0';
3910ba2cbe9Sxc151355 	return (B_FALSE);
3920ba2cbe9Sxc151355 }
3930ba2cbe9Sxc151355 
3940ba2cbe9Sxc151355 /* ARGSUSED */
3950ba2cbe9Sxc151355 static boolean_t
3960ba2cbe9Sxc151355 process_secobj_walk(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
3970ba2cbe9Sxc151355     dladm_status_t *statusp)
3980ba2cbe9Sxc151355 {
3990ba2cbe9Sxc151355 	secobj_name_t	*snp;
4000ba2cbe9Sxc151355 
4010ba2cbe9Sxc151355 	if ((snp = malloc(sizeof (*snp))) == NULL)
4020ba2cbe9Sxc151355 		return (B_TRUE);
4030ba2cbe9Sxc151355 
4040ba2cbe9Sxc151355 	if ((snp->sn_name = strdup(sip->si_name)) == NULL) {
4050ba2cbe9Sxc151355 		free(snp);
4060ba2cbe9Sxc151355 		return (B_TRUE);
4070ba2cbe9Sxc151355 	}
4080ba2cbe9Sxc151355 
4090ba2cbe9Sxc151355 	snp->sn_next = NULL;
4100ba2cbe9Sxc151355 	*ssp->ss_namelist = snp;
4110ba2cbe9Sxc151355 	ssp->ss_namelist = &snp->sn_next;
4120ba2cbe9Sxc151355 	return (B_TRUE);
4130ba2cbe9Sxc151355 }
4140ba2cbe9Sxc151355 
4150ba2cbe9Sxc151355 /* ARGSUSED */
4160ba2cbe9Sxc151355 static boolean_t
4170ba2cbe9Sxc151355 process_secobj_init(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
4180ba2cbe9Sxc151355     dladm_status_t *statusp)
4190ba2cbe9Sxc151355 {
4200ba2cbe9Sxc151355 	*statusp = dladm_set_secobj(sip->si_name, *sip->si_classp, sip->si_val,
421d62bc4baSyz147064 	    *sip->si_lenp, DLADM_OPT_ACTIVE | DLADM_OPT_CREATE);
4220ba2cbe9Sxc151355 	return (B_TRUE);
4230ba2cbe9Sxc151355 }
4240ba2cbe9Sxc151355 
4250ba2cbe9Sxc151355 static int
4260ba2cbe9Sxc151355 parse_secobj_val(char *buf, secobj_info_t *sip)
4270ba2cbe9Sxc151355 {
4280ba2cbe9Sxc151355 	if (strncmp(buf, "0x", 2) != 0)
4290ba2cbe9Sxc151355 		return (EINVAL);
4300ba2cbe9Sxc151355 
4310ba2cbe9Sxc151355 	return (hexascii_to_octet(buf + 2, strlen(buf) - 2,
4320ba2cbe9Sxc151355 	    sip->si_val, sip->si_lenp));
4330ba2cbe9Sxc151355 }
4340ba2cbe9Sxc151355 
4350ba2cbe9Sxc151355 static boolean_t
4360ba2cbe9Sxc151355 process_secobj_line(secobj_db_state_t *ssp, char *buf,
4370ba2cbe9Sxc151355     dladm_status_t *statusp)
4380ba2cbe9Sxc151355 {
4390ba2cbe9Sxc151355 	secobj_info_t		sinfo;
4400ba2cbe9Sxc151355 	dladm_secobj_class_t	class;
4410ba2cbe9Sxc151355 	uint8_t			val[DLADM_SECOBJ_VAL_MAX];
4420ba2cbe9Sxc151355 	uint_t			vlen;
4430ba2cbe9Sxc151355 	int			i, len, nlen;
4440ba2cbe9Sxc151355 	char			*str, *lasts;
4450ba2cbe9Sxc151355 
4460ba2cbe9Sxc151355 	/*
4470ba2cbe9Sxc151355 	 * Skip leading spaces, blank lines, and comments.
4480ba2cbe9Sxc151355 	 */
4490ba2cbe9Sxc151355 	len = strlen(buf);
4500ba2cbe9Sxc151355 	for (i = 0; i < len; i++) {
4510ba2cbe9Sxc151355 		if (!isspace(buf[i]))
4520ba2cbe9Sxc151355 			break;
4530ba2cbe9Sxc151355 	}
4540ba2cbe9Sxc151355 	if (i == len || buf[i] == '#')
4550ba2cbe9Sxc151355 		return (B_TRUE);
4560ba2cbe9Sxc151355 
4570ba2cbe9Sxc151355 	str = buf + i;
4580ba2cbe9Sxc151355 	if (ssp->ss_info.si_name != NULL) {
4590ba2cbe9Sxc151355 		/*
4600ba2cbe9Sxc151355 		 * Skip objects we're not interested in.
4610ba2cbe9Sxc151355 		 */
4620ba2cbe9Sxc151355 		nlen = strlen(ssp->ss_info.si_name);
4630ba2cbe9Sxc151355 		if (strncmp(str, ssp->ss_info.si_name, nlen) != 0 ||
4640ba2cbe9Sxc151355 		    !isspace(str[nlen]))
4650ba2cbe9Sxc151355 			return (B_TRUE);
4660ba2cbe9Sxc151355 
4670ba2cbe9Sxc151355 		sinfo.si_name = ssp->ss_info.si_name;
4680ba2cbe9Sxc151355 	} else {
4690ba2cbe9Sxc151355 		/*
4700ba2cbe9Sxc151355 		 * If an object is not specified, find the object name
4710ba2cbe9Sxc151355 		 * and assign it to sinfo.si_name.
4720ba2cbe9Sxc151355 		 */
4730ba2cbe9Sxc151355 		if (strtok_r(str, " \n\t", &lasts) == NULL)
4740ba2cbe9Sxc151355 			goto fail;
4750ba2cbe9Sxc151355 
4760ba2cbe9Sxc151355 		nlen = strlen(str);
4770ba2cbe9Sxc151355 		sinfo.si_name = str;
4780ba2cbe9Sxc151355 	}
4790ba2cbe9Sxc151355 	str += nlen + 1;
4800ba2cbe9Sxc151355 	if (str >= buf + len)
4810ba2cbe9Sxc151355 		goto fail;
4820ba2cbe9Sxc151355 
4830ba2cbe9Sxc151355 	/*
4840ba2cbe9Sxc151355 	 * Find the class name.
4850ba2cbe9Sxc151355 	 */
4860ba2cbe9Sxc151355 	if ((str = strtok_r(str, " \n\t", &lasts)) == NULL)
4870ba2cbe9Sxc151355 		goto fail;
4880ba2cbe9Sxc151355 
4890ba2cbe9Sxc151355 	*statusp = dladm_str2secobjclass(str, &class);
4900ba2cbe9Sxc151355 	if (*statusp != DLADM_STATUS_OK)
4910ba2cbe9Sxc151355 		goto fail;
4920ba2cbe9Sxc151355 
4930ba2cbe9Sxc151355 	/*
4940ba2cbe9Sxc151355 	 * Find the object value.
4950ba2cbe9Sxc151355 	 */
4960ba2cbe9Sxc151355 	if ((str = strtok_r(NULL, " \n\t", &lasts)) == NULL)
4970ba2cbe9Sxc151355 		goto fail;
4980ba2cbe9Sxc151355 
4990ba2cbe9Sxc151355 	vlen = DLADM_SECOBJ_VAL_MAX;
5000ba2cbe9Sxc151355 	sinfo.si_classp = &class;
5010ba2cbe9Sxc151355 	sinfo.si_val = val;
5020ba2cbe9Sxc151355 	sinfo.si_lenp = &vlen;
5030ba2cbe9Sxc151355 	if (parse_secobj_val(str, &sinfo) != 0)
5040ba2cbe9Sxc151355 		goto fail;
5050ba2cbe9Sxc151355 
5060ba2cbe9Sxc151355 	return ((*ssp->ss_op)(ssp, buf, &sinfo, statusp));
5070ba2cbe9Sxc151355 
5080ba2cbe9Sxc151355 fail:
5090ba2cbe9Sxc151355 	/*
5100ba2cbe9Sxc151355 	 * Delete corrupted line.
5110ba2cbe9Sxc151355 	 */
5120ba2cbe9Sxc151355 	buf[0] = '\0';
5130ba2cbe9Sxc151355 	return (B_TRUE);
5140ba2cbe9Sxc151355 }
5150ba2cbe9Sxc151355 
5160ba2cbe9Sxc151355 static dladm_status_t
5170ba2cbe9Sxc151355 process_secobj_db(void *arg, FILE *fp, FILE *nfp)
5180ba2cbe9Sxc151355 {
5190ba2cbe9Sxc151355 	secobj_db_state_t	*ssp = arg;
5200ba2cbe9Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
5210ba2cbe9Sxc151355 	char			buf[MAXLINELEN];
5220ba2cbe9Sxc151355 	boolean_t		cont = B_TRUE;
5230ba2cbe9Sxc151355 
5240ba2cbe9Sxc151355 	/*
5250ba2cbe9Sxc151355 	 * This loop processes each line of the configuration file.
5260ba2cbe9Sxc151355 	 * buf can potentially be modified by process_secobj_line().
5270ba2cbe9Sxc151355 	 * If this is a write operation and buf is not truncated, buf will
5280ba2cbe9Sxc151355 	 * be written to disk. process_secobj_line() will no longer be
5290ba2cbe9Sxc151355 	 * called after it returns B_FALSE; at which point the remainder
5300ba2cbe9Sxc151355 	 * of the file will continue to be read and, if necessary, written
5310ba2cbe9Sxc151355 	 * to disk as well.
5320ba2cbe9Sxc151355 	 */
5330ba2cbe9Sxc151355 	while (fgets(buf, MAXLINELEN, fp) != NULL) {
5340ba2cbe9Sxc151355 		if (cont)
5350ba2cbe9Sxc151355 			cont = process_secobj_line(ssp, buf, &status);
5360ba2cbe9Sxc151355 
5370ba2cbe9Sxc151355 		if (nfp != NULL && buf[0] != '\0' && fputs(buf, nfp) == EOF) {
5380ba2cbe9Sxc151355 			status = dladm_errno2status(errno);
5390ba2cbe9Sxc151355 			break;
5400ba2cbe9Sxc151355 		}
5410ba2cbe9Sxc151355 	}
5420ba2cbe9Sxc151355 	if (status != DLADM_STATUS_OK || !cont)
5430ba2cbe9Sxc151355 		return (status);
5440ba2cbe9Sxc151355 
5450ba2cbe9Sxc151355 	if (ssp->ss_op == process_secobj_set) {
5460ba2cbe9Sxc151355 		/*
5470ba2cbe9Sxc151355 		 * If the specified object is not found above, we add the
5480ba2cbe9Sxc151355 		 * object to the configuration file.
5490ba2cbe9Sxc151355 		 */
5500ba2cbe9Sxc151355 		(void) (*ssp->ss_op)(ssp, buf, NULL, &status);
5510ba2cbe9Sxc151355 		if (status == DLADM_STATUS_OK && fputs(buf, nfp) == EOF)
5520ba2cbe9Sxc151355 			status = dladm_errno2status(errno);
5530ba2cbe9Sxc151355 	}
5540ba2cbe9Sxc151355 
5550ba2cbe9Sxc151355 	if (ssp->ss_op == process_secobj_unset ||
5560ba2cbe9Sxc151355 	    ssp->ss_op == process_secobj_get)
5570ba2cbe9Sxc151355 		status = DLADM_STATUS_NOTFOUND;
5580ba2cbe9Sxc151355 
5590ba2cbe9Sxc151355 	return (status);
5600ba2cbe9Sxc151355 }
5610ba2cbe9Sxc151355 
5620ba2cbe9Sxc151355 #define	SECOBJ_RW_DB(statep, writeop) \
5630ba2cbe9Sxc151355 	(i_dladm_rw_db("/etc/dladm/secobj.conf", S_IRUSR | S_IWUSR, \
5640ba2cbe9Sxc151355 	process_secobj_db, (statep), (writeop)))
5650ba2cbe9Sxc151355 
5660ba2cbe9Sxc151355 static dladm_status_t
5670ba2cbe9Sxc151355 i_dladm_set_secobj_db(const char *obj_name, dladm_secobj_class_t class,
5680ba2cbe9Sxc151355     uint8_t *obj_val, uint_t obj_len)
5690ba2cbe9Sxc151355 {
5700ba2cbe9Sxc151355 	secobj_db_state_t	state;
5710ba2cbe9Sxc151355 
5720ba2cbe9Sxc151355 	state.ss_op = process_secobj_set;
5730ba2cbe9Sxc151355 	state.ss_info.si_name = obj_name;
5740ba2cbe9Sxc151355 	state.ss_info.si_classp = &class;
5750ba2cbe9Sxc151355 	state.ss_info.si_val = obj_val;
5760ba2cbe9Sxc151355 	state.ss_info.si_lenp = &obj_len;
5770ba2cbe9Sxc151355 	state.ss_namelist = NULL;
5780ba2cbe9Sxc151355 
5790ba2cbe9Sxc151355 	return (SECOBJ_RW_DB(&state, B_TRUE));
5800ba2cbe9Sxc151355 }
5810ba2cbe9Sxc151355 
5820ba2cbe9Sxc151355 static dladm_status_t
5830ba2cbe9Sxc151355 i_dladm_get_secobj_db(const char *obj_name, dladm_secobj_class_t *classp,
5840ba2cbe9Sxc151355     uint8_t *obj_val, uint_t *obj_lenp)
5850ba2cbe9Sxc151355 {
5860ba2cbe9Sxc151355 	secobj_db_state_t	state;
5870ba2cbe9Sxc151355 
5880ba2cbe9Sxc151355 	state.ss_op = process_secobj_get;
5890ba2cbe9Sxc151355 	state.ss_info.si_name = obj_name;
5900ba2cbe9Sxc151355 	state.ss_info.si_classp = classp;
5910ba2cbe9Sxc151355 	state.ss_info.si_val = obj_val;
5920ba2cbe9Sxc151355 	state.ss_info.si_lenp = obj_lenp;
5930ba2cbe9Sxc151355 	state.ss_namelist = NULL;
5940ba2cbe9Sxc151355 
5950ba2cbe9Sxc151355 	return (SECOBJ_RW_DB(&state, B_FALSE));
5960ba2cbe9Sxc151355 }
5970ba2cbe9Sxc151355 
5980ba2cbe9Sxc151355 static dladm_status_t
5990ba2cbe9Sxc151355 i_dladm_unset_secobj_db(const char *obj_name)
6000ba2cbe9Sxc151355 {
6010ba2cbe9Sxc151355 	secobj_db_state_t	state;
6020ba2cbe9Sxc151355 
6030ba2cbe9Sxc151355 	state.ss_op = process_secobj_unset;
6040ba2cbe9Sxc151355 	state.ss_info.si_name = obj_name;
6050ba2cbe9Sxc151355 	state.ss_info.si_classp = NULL;
6060ba2cbe9Sxc151355 	state.ss_info.si_val = NULL;
6070ba2cbe9Sxc151355 	state.ss_info.si_lenp = NULL;
6080ba2cbe9Sxc151355 	state.ss_namelist = NULL;
6090ba2cbe9Sxc151355 
6100ba2cbe9Sxc151355 	return (SECOBJ_RW_DB(&state, B_TRUE));
6110ba2cbe9Sxc151355 }
6120ba2cbe9Sxc151355 
6130ba2cbe9Sxc151355 static dladm_status_t
6140ba2cbe9Sxc151355 i_dladm_walk_secobj_db(void *arg, boolean_t (*func)(void *, const char *))
6150ba2cbe9Sxc151355 {
6160ba2cbe9Sxc151355 	secobj_db_state_t	state;
6170ba2cbe9Sxc151355 	secobj_name_t		*snp = NULL, *fsnp;
6180ba2cbe9Sxc151355 	dladm_status_t		status;
6190ba2cbe9Sxc151355 	boolean_t		cont = B_TRUE;
6200ba2cbe9Sxc151355 
6210ba2cbe9Sxc151355 	state.ss_op = process_secobj_walk;
6220ba2cbe9Sxc151355 	state.ss_info.si_name = NULL;
6230ba2cbe9Sxc151355 	state.ss_info.si_classp = NULL;
6240ba2cbe9Sxc151355 	state.ss_info.si_val = NULL;
6250ba2cbe9Sxc151355 	state.ss_info.si_lenp = NULL;
6260ba2cbe9Sxc151355 	state.ss_namelist = &snp;
6270ba2cbe9Sxc151355 
6280ba2cbe9Sxc151355 	status = SECOBJ_RW_DB(&state, B_FALSE);
6290ba2cbe9Sxc151355 	if (status != DLADM_STATUS_OK)
6300ba2cbe9Sxc151355 		return (status);
6310ba2cbe9Sxc151355 
6320ba2cbe9Sxc151355 	while (snp != NULL) {
6330ba2cbe9Sxc151355 		fsnp = snp;
6340ba2cbe9Sxc151355 		snp = snp->sn_next;
6350ba2cbe9Sxc151355 		if (cont)
6360ba2cbe9Sxc151355 			cont = func(arg, fsnp->sn_name);
6370ba2cbe9Sxc151355 		free(fsnp->sn_name);
6380ba2cbe9Sxc151355 		free(fsnp);
6390ba2cbe9Sxc151355 	}
6400ba2cbe9Sxc151355 	return (status);
6410ba2cbe9Sxc151355 }
6420ba2cbe9Sxc151355 
6430ba2cbe9Sxc151355 dladm_status_t
6440ba2cbe9Sxc151355 dladm_init_secobj(void)
6450ba2cbe9Sxc151355 {
6460ba2cbe9Sxc151355 	secobj_db_state_t	state;
6470ba2cbe9Sxc151355 
6480ba2cbe9Sxc151355 	state.ss_op = process_secobj_init;
6490ba2cbe9Sxc151355 	state.ss_info.si_name = NULL;
6500ba2cbe9Sxc151355 	state.ss_info.si_classp = NULL;
6510ba2cbe9Sxc151355 	state.ss_info.si_val = NULL;
6520ba2cbe9Sxc151355 	state.ss_info.si_lenp = NULL;
6530ba2cbe9Sxc151355 	state.ss_namelist = NULL;
6540ba2cbe9Sxc151355 
6550ba2cbe9Sxc151355 	return (SECOBJ_RW_DB(&state, B_FALSE));
6560ba2cbe9Sxc151355 }
657*a9489f61SAnurag S. Maskey 
658*a9489f61SAnurag S. Maskey boolean_t
659*a9489f61SAnurag S. Maskey dladm_valid_secobj_name(const char *secobj_name)
660*a9489f61SAnurag S. Maskey {
661*a9489f61SAnurag S. Maskey 	size_t len = strlen(secobj_name);
662*a9489f61SAnurag S. Maskey 	const char *cp;
663*a9489f61SAnurag S. Maskey 
664*a9489f61SAnurag S. Maskey 	if (len + 1 > DLADM_SECOBJ_NAME_MAX)
665*a9489f61SAnurag S. Maskey 		return (B_FALSE);
666*a9489f61SAnurag S. Maskey 
667*a9489f61SAnurag S. Maskey 	/*
668*a9489f61SAnurag S. Maskey 	 * The legal characters in a secobj name are:
669*a9489f61SAnurag S. Maskey 	 * alphanumeric (a-z, A-Z, 0-9), '.', '_', '-'.
670*a9489f61SAnurag S. Maskey 	 */
671*a9489f61SAnurag S. Maskey 	for (cp = secobj_name; *cp != '\0'; cp++) {
672*a9489f61SAnurag S. Maskey 		if (!isalnum(*cp) &&
673*a9489f61SAnurag S. Maskey 		    (*cp != '.') && (*cp != '_') && (*cp != '-'))
674*a9489f61SAnurag S. Maskey 			return (B_FALSE);
675*a9489f61SAnurag S. Maskey 	}
676*a9489f61SAnurag S. Maskey 
677*a9489f61SAnurag S. Maskey 	return (B_TRUE);
678*a9489f61SAnurag S. Maskey }
679