13147Sxc151355 /*
23147Sxc151355  * CDDL HEADER START
33147Sxc151355  *
43147Sxc151355  * The contents of this file are subject to the terms of the
53147Sxc151355  * Common Development and Distribution License (the "License").
63147Sxc151355  * You may not use this file except in compliance with the License.
73147Sxc151355  *
83147Sxc151355  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93147Sxc151355  * or http://www.opensolaris.org/os/licensing.
103147Sxc151355  * See the License for the specific language governing permissions
113147Sxc151355  * and limitations under the License.
123147Sxc151355  *
133147Sxc151355  * When distributing Covered Code, include this CDDL HEADER in each
143147Sxc151355  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153147Sxc151355  * If applicable, add the following below this CDDL HEADER, with the
163147Sxc151355  * fields enclosed by brackets "[]" replaced with your own identifying
173147Sxc151355  * information: Portions Copyright [yyyy] [name of copyright owner]
183147Sxc151355  *
193147Sxc151355  * CDDL HEADER END
203147Sxc151355  */
213147Sxc151355 /*
225895Syz147064  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
233147Sxc151355  * Use is subject to license terms.
243147Sxc151355  */
253147Sxc151355 
263147Sxc151355 #include <unistd.h>
273147Sxc151355 #include <stdlib.h>
283147Sxc151355 #include <strings.h>
293147Sxc151355 #include <errno.h>
303147Sxc151355 #include <ctype.h>
313147Sxc151355 #include <fcntl.h>
323147Sxc151355 #include <sys/stat.h>
333147Sxc151355 #include <sys/dld.h>
343147Sxc151355 #include <libinetutil.h>
353871Syz147064 #include <libdllink.h>
363147Sxc151355 #include <libdladm_impl.h>
373147Sxc151355 
383147Sxc151355 static dladm_status_t	i_dladm_set_secobj_db(const char *,
393147Sxc151355 			    dladm_secobj_class_t, uint8_t *, uint_t);
403147Sxc151355 static dladm_status_t	i_dladm_get_secobj_db(const char *,
413147Sxc151355 			    dladm_secobj_class_t *, uint8_t *, uint_t *);
423147Sxc151355 static dladm_status_t	i_dladm_unset_secobj_db(const char *);
433147Sxc151355 static dladm_status_t	i_dladm_walk_secobj_db(void *,
443147Sxc151355 			    boolean_t (*)(void *, const char *));
453147Sxc151355 
463147Sxc151355 typedef struct secobj_class_info {
473147Sxc151355 	const char		*sc_name;
483147Sxc151355 	dld_secobj_class_t	sc_dldclass;
493147Sxc151355 } secobj_class_info_t;
503147Sxc151355 
513147Sxc151355 static secobj_class_info_t secobj_class_table[] = {
524126Szf162725 	{"wep",	DLD_SECOBJ_CLASS_WEP},
534126Szf162725 	{"wpa",	DLD_SECOBJ_CLASS_WPA}
543147Sxc151355 };
553147Sxc151355 
567408SSebastien.Roy@Sun.COM #define	SECOBJ_MAXBUFSZ	65536
573147Sxc151355 #define	NSECOBJCLASS \
583147Sxc151355 	(sizeof (secobj_class_table) / sizeof (secobj_class_info_t))
593147Sxc151355 
603147Sxc151355 static boolean_t
613147Sxc151355 dladm_check_secobjclass(dladm_secobj_class_t class)
623147Sxc151355 {
633147Sxc151355 	return (class >= 0 && class < NSECOBJCLASS);
643147Sxc151355 }
653147Sxc151355 
663147Sxc151355 dladm_status_t
673147Sxc151355 dladm_str2secobjclass(const char *str, dladm_secobj_class_t *class)
683147Sxc151355 {
693147Sxc151355 	int			i;
703147Sxc151355 	secobj_class_info_t	*sp;
713147Sxc151355 
723147Sxc151355 	for (i = 0; i < NSECOBJCLASS; i++) {
733147Sxc151355 		sp = &secobj_class_table[i];
743147Sxc151355 		if (strcasecmp(str, sp->sc_name) == 0) {
753147Sxc151355 			*class = i;
763147Sxc151355 			return (DLADM_STATUS_OK);
773147Sxc151355 		}
783147Sxc151355 	}
793147Sxc151355 	return (DLADM_STATUS_BADARG);
803147Sxc151355 }
813147Sxc151355 
823147Sxc151355 const char *
833147Sxc151355 dladm_secobjclass2str(dladm_secobj_class_t class, char *buf)
843147Sxc151355 {
853147Sxc151355 	const char		*s;
863147Sxc151355 
873147Sxc151355 	if (!dladm_check_secobjclass(class))
883147Sxc151355 		s = "";
893147Sxc151355 	else
903147Sxc151355 		s = secobj_class_table[class].sc_name;
913147Sxc151355 
923147Sxc151355 	(void) snprintf(buf, DLADM_STRSIZE, "%s", s);
933147Sxc151355 	return (buf);
943147Sxc151355 }
953147Sxc151355 
963147Sxc151355 static boolean_t
973147Sxc151355 dladm_convert_secobjclass(dladm_secobj_class_t class,
983147Sxc151355     dld_secobj_class_t *dldclass)
993147Sxc151355 {
1003147Sxc151355 	if (!dladm_check_secobjclass(class))
1013147Sxc151355 		return (B_FALSE);
1023147Sxc151355 
1033147Sxc151355 	*dldclass = secobj_class_table[class].sc_dldclass;
1043147Sxc151355 	return (B_TRUE);
1053147Sxc151355 }
1063147Sxc151355 
1073147Sxc151355 static boolean_t
1083147Sxc151355 dladm_convert_dldsecobjclass(dld_secobj_class_t dldclass,
1093147Sxc151355     dladm_secobj_class_t *class)
1103147Sxc151355 {
1113147Sxc151355 	int			i;
1123147Sxc151355 	secobj_class_info_t	*sp;
1133147Sxc151355 
1143147Sxc151355 	for (i = 0; i < NSECOBJCLASS; i++) {
1153147Sxc151355 		sp = &secobj_class_table[i];
1163147Sxc151355 		if (dldclass == sp->sc_dldclass) {
1173147Sxc151355 			*class = i;
1183147Sxc151355 			return (B_TRUE);
1193147Sxc151355 		}
1203147Sxc151355 	}
1213147Sxc151355 	return (B_FALSE);
1223147Sxc151355 }
1233147Sxc151355 
1243147Sxc151355 dladm_status_t
1253147Sxc151355 dladm_set_secobj(const char *obj_name, dladm_secobj_class_t class,
1263147Sxc151355     uint8_t *obj_val, uint_t obj_len, uint_t flags)
1273147Sxc151355 {
1283147Sxc151355 	int			fd;
1293147Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
1303147Sxc151355 	dld_ioc_secobj_set_t	secobj_set;
1313147Sxc151355 	dld_secobj_t		*objp;
1323147Sxc151355 
133*8431SAnurag.Maskey@Sun.COM 	if (!dladm_valid_secobj_name(obj_name))
134*8431SAnurag.Maskey@Sun.COM 		return (DLADM_STATUS_BADARG);
135*8431SAnurag.Maskey@Sun.COM 
1363147Sxc151355 	if (!dladm_check_secobjclass(class) || flags == 0 ||
1373147Sxc151355 	    obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
1383147Sxc151355 	    obj_val == NULL || obj_len == 0 || obj_len > DLD_SECOBJ_VAL_MAX)
1393147Sxc151355 		return (DLADM_STATUS_BADARG);
1403147Sxc151355 
1415895Syz147064 	if ((flags & DLADM_OPT_ACTIVE) == 0)
1423147Sxc151355 		goto persist;
1433147Sxc151355 
1443147Sxc151355 	bzero(&secobj_set, sizeof (secobj_set));
1453147Sxc151355 	objp = &secobj_set.ss_obj;
1463147Sxc151355 	if (!dladm_convert_secobjclass(class, &objp->so_class))
1473147Sxc151355 		return (DLADM_STATUS_BADARG);
1483147Sxc151355 
1493147Sxc151355 	(void) strlcpy(objp->so_name, obj_name, DLD_SECOBJ_NAME_MAX);
1503147Sxc151355 	bcopy(obj_val, objp->so_val, obj_len);
1513147Sxc151355 	objp->so_len = obj_len;
1523147Sxc151355 
1533147Sxc151355 	if ((flags & DLADM_OPT_CREATE) != 0)
1543147Sxc151355 		secobj_set.ss_flags = DLD_SECOBJ_OPT_CREATE;
1553147Sxc151355 
1563147Sxc151355 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
1573147Sxc151355 		return (dladm_errno2status(errno));
1583147Sxc151355 
1597408SSebastien.Roy@Sun.COM 	if (ioctl(fd, DLDIOC_SECOBJ_SET, &secobj_set) < 0)
1603147Sxc151355 		status = dladm_errno2status(errno);
1613147Sxc151355 
1623147Sxc151355 	(void) close(fd);
1634126Szf162725 
1643147Sxc151355 	if (status != DLADM_STATUS_OK)
1653147Sxc151355 		return (status);
1663147Sxc151355 
1673147Sxc151355 persist:
1683147Sxc151355 	if ((flags & DLADM_OPT_PERSIST) != 0) {
1693147Sxc151355 		status = i_dladm_set_secobj_db(obj_name, class,
1703147Sxc151355 		    obj_val, obj_len);
1713147Sxc151355 	}
1723147Sxc151355 	return (status);
1733147Sxc151355 }
1743147Sxc151355 
1753147Sxc151355 dladm_status_t
1763147Sxc151355 dladm_get_secobj(const char *obj_name, dladm_secobj_class_t *classp,
1773147Sxc151355     uint8_t *obj_val, uint_t *obj_lenp, uint_t flags)
1783147Sxc151355 {
1793147Sxc151355 	int			fd;
1803147Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
1813147Sxc151355 	dld_ioc_secobj_get_t	secobj_get;
1823147Sxc151355 	dld_secobj_t		*objp;
1833147Sxc151355 
1843147Sxc151355 	if (obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
1853147Sxc151355 	    obj_val == NULL || obj_lenp == NULL || *obj_lenp == 0 ||
1863147Sxc151355 	    *obj_lenp > DLD_SECOBJ_VAL_MAX)
1873147Sxc151355 		return (DLADM_STATUS_BADARG);
1883147Sxc151355 
1893147Sxc151355 	if ((flags & DLADM_OPT_PERSIST) != 0) {
1903147Sxc151355 		return (i_dladm_get_secobj_db(obj_name, classp,
1913147Sxc151355 		    obj_val, obj_lenp));
1923147Sxc151355 	}
1933147Sxc151355 
1943147Sxc151355 	bzero(&secobj_get, sizeof (secobj_get));
1953147Sxc151355 	objp = &secobj_get.sg_obj;
1963147Sxc151355 	(void) strlcpy(objp->so_name, obj_name, DLD_SECOBJ_NAME_MAX);
1973147Sxc151355 
1983147Sxc151355 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
1993147Sxc151355 		return (dladm_errno2status(errno));
2003147Sxc151355 
2017408SSebastien.Roy@Sun.COM 	secobj_get.sg_size = sizeof (secobj_get);
2027408SSebastien.Roy@Sun.COM 	if (ioctl(fd, DLDIOC_SECOBJ_GET, &secobj_get) < 0)
2033147Sxc151355 		status = dladm_errno2status(errno);
2043147Sxc151355 
2053147Sxc151355 	(void) close(fd);
2063147Sxc151355 	if (objp->so_len > *obj_lenp)
2073147Sxc151355 		return (DLADM_STATUS_TOOSMALL);
2083147Sxc151355 
2093147Sxc151355 	if (!dladm_convert_dldsecobjclass(objp->so_class, classp))
2103147Sxc151355 		return (DLADM_STATUS_FAILED);
2113147Sxc151355 
2123147Sxc151355 	*obj_lenp = objp->so_len;
2133147Sxc151355 	bcopy(objp->so_val, obj_val, *obj_lenp);
2143147Sxc151355 	return (status);
2153147Sxc151355 }
2163147Sxc151355 
2173147Sxc151355 dladm_status_t
2183147Sxc151355 dladm_unset_secobj(const char *obj_name, uint_t flags)
2193147Sxc151355 {
2203147Sxc151355 	int			fd;
2213147Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
2223147Sxc151355 	dld_ioc_secobj_unset_t	secobj_unset;
2233147Sxc151355 
2243147Sxc151355 	if (obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
2253147Sxc151355 	    flags == 0)
2263147Sxc151355 		return (DLADM_STATUS_BADARG);
2273147Sxc151355 
2285895Syz147064 	if ((flags & DLADM_OPT_ACTIVE) == 0)
2293147Sxc151355 		goto persist;
2303147Sxc151355 
2313147Sxc151355 	bzero(&secobj_unset, sizeof (secobj_unset));
2323147Sxc151355 	(void) strlcpy(secobj_unset.su_name, obj_name, DLD_SECOBJ_NAME_MAX);
2333147Sxc151355 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
2343147Sxc151355 		return (dladm_errno2status(errno));
2353147Sxc151355 
2367408SSebastien.Roy@Sun.COM 	if (ioctl(fd, DLDIOC_SECOBJ_UNSET, &secobj_unset) < 0)
2373147Sxc151355 		status = dladm_errno2status(errno);
2383147Sxc151355 
2393147Sxc151355 	(void) close(fd);
2403147Sxc151355 	if (status != DLADM_STATUS_OK)
2413147Sxc151355 		return (status);
2423147Sxc151355 
2433147Sxc151355 persist:
2443147Sxc151355 	if ((flags & DLADM_OPT_PERSIST) != 0)
2453147Sxc151355 		status = i_dladm_unset_secobj_db(obj_name);
2463147Sxc151355 
2473147Sxc151355 	return (status);
2483147Sxc151355 }
2493147Sxc151355 
2503147Sxc151355 dladm_status_t
2513147Sxc151355 dladm_walk_secobj(void *arg, boolean_t (*func)(void *, const char *),
2523147Sxc151355     uint_t flags)
2533147Sxc151355 {
2543147Sxc151355 	int			fd = -1;
2553147Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
2563147Sxc151355 	dld_ioc_secobj_get_t	*secobj_getp;
2573147Sxc151355 	dld_secobj_t		*objp;
2587408SSebastien.Roy@Sun.COM 	size_t			secobj_bufsz;
2593147Sxc151355 
2603147Sxc151355 	if ((flags & DLADM_OPT_PERSIST) != 0)
2613147Sxc151355 		return (i_dladm_walk_secobj_db(arg, func));
2623147Sxc151355 
2637408SSebastien.Roy@Sun.COM 	if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
2647408SSebastien.Roy@Sun.COM 		return (dladm_errno2status(errno));
2653147Sxc151355 
2667408SSebastien.Roy@Sun.COM 	/* Start with enough room for 10 objects, increase if necessary. */
2677408SSebastien.Roy@Sun.COM 	secobj_bufsz = sizeof (*secobj_getp) + (10 * sizeof (*objp));
2687408SSebastien.Roy@Sun.COM 	secobj_getp = calloc(1, secobj_bufsz);
2697408SSebastien.Roy@Sun.COM 	if (secobj_getp == NULL) {
2703147Sxc151355 		status = dladm_errno2status(errno);
2713147Sxc151355 		goto done;
2723147Sxc151355 	}
2737408SSebastien.Roy@Sun.COM 
2747408SSebastien.Roy@Sun.COM tryagain:
2757408SSebastien.Roy@Sun.COM 	secobj_getp->sg_size = secobj_bufsz;
2767408SSebastien.Roy@Sun.COM 	if (ioctl(fd, DLDIOC_SECOBJ_GET, secobj_getp) < 0) {
2777408SSebastien.Roy@Sun.COM 		if (errno == ENOSPC) {
2787408SSebastien.Roy@Sun.COM 			/* Increase the buffer size and try again. */
2797408SSebastien.Roy@Sun.COM 			secobj_bufsz *= 2;
2807408SSebastien.Roy@Sun.COM 			if (secobj_bufsz > SECOBJ_MAXBUFSZ) {
2817408SSebastien.Roy@Sun.COM 				status = dladm_errno2status(errno);
2827408SSebastien.Roy@Sun.COM 				goto done;
2837408SSebastien.Roy@Sun.COM 			}
2847408SSebastien.Roy@Sun.COM 			secobj_getp = realloc(secobj_getp, secobj_bufsz);
2857408SSebastien.Roy@Sun.COM 			if (secobj_getp == NULL) {
2867408SSebastien.Roy@Sun.COM 				status = dladm_errno2status(errno);
2877408SSebastien.Roy@Sun.COM 				goto done;
2887408SSebastien.Roy@Sun.COM 			}
2897408SSebastien.Roy@Sun.COM 			bzero(secobj_getp, secobj_bufsz);
2907408SSebastien.Roy@Sun.COM 			goto tryagain;
2917408SSebastien.Roy@Sun.COM 		}
2923147Sxc151355 		status = dladm_errno2status(errno);
2933147Sxc151355 		goto done;
2943147Sxc151355 	}
2953147Sxc151355 
2963147Sxc151355 	objp = (dld_secobj_t *)(secobj_getp + 1);
2973147Sxc151355 	while (secobj_getp->sg_count > 0) {
2983147Sxc151355 		if (!func(arg, objp->so_name))
2993147Sxc151355 			goto done;
3003147Sxc151355 		secobj_getp->sg_count--;
3013147Sxc151355 		objp++;
3023147Sxc151355 	}
3033147Sxc151355 done:
3043147Sxc151355 	(void) close(fd);
3053147Sxc151355 	free(secobj_getp);
3063147Sxc151355 	return (status);
3073147Sxc151355 }
3083147Sxc151355 
3093147Sxc151355 /*
3103147Sxc151355  * Data structures used for implementing persistent secure objects
3113147Sxc151355  */
3123147Sxc151355 typedef struct secobj_info {
3133147Sxc151355 	const char		*si_name;
3143147Sxc151355 	dladm_secobj_class_t	*si_classp;
3153147Sxc151355 	uint8_t			*si_val;
3163147Sxc151355 	uint_t			*si_lenp;
3173147Sxc151355 } secobj_info_t;
3183147Sxc151355 
3193147Sxc151355 typedef struct secobj_name {
3203147Sxc151355 	char			*sn_name;
3213147Sxc151355 	struct secobj_name	*sn_next;
3223147Sxc151355 } secobj_name_t;
3233147Sxc151355 
3243147Sxc151355 typedef struct secobj_db_state	secobj_db_state_t;
3253147Sxc151355 
3263147Sxc151355 typedef boolean_t (*secobj_db_op_t)(struct secobj_db_state *, char *,
3273147Sxc151355     secobj_info_t *, dladm_status_t *);
3283147Sxc151355 
3293147Sxc151355 struct secobj_db_state {
3303147Sxc151355 	secobj_db_op_t		ss_op;
3313147Sxc151355 	secobj_info_t		ss_info;
3323147Sxc151355 	secobj_name_t		**ss_namelist;
3333147Sxc151355 };
3343147Sxc151355 
3353147Sxc151355 /*
3363147Sxc151355  * Update or generate a secobj entry using the info in ssp->ss_info.
3373147Sxc151355  */
3383147Sxc151355 /* ARGSUSED */
3393147Sxc151355 static boolean_t
3403147Sxc151355 process_secobj_set(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
3413147Sxc151355     dladm_status_t *statusp)
3423147Sxc151355 {
3433147Sxc151355 	char	tmpbuf[MAXLINELEN];
3443147Sxc151355 	char	classbuf[DLADM_STRSIZE];
3453147Sxc151355 	char	*ptr = tmpbuf, *lim = tmpbuf + MAXLINELEN;
3463147Sxc151355 	int	i;
3473147Sxc151355 
3483147Sxc151355 	sip = &ssp->ss_info;
3493147Sxc151355 
3503147Sxc151355 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", sip->si_name);
3513147Sxc151355 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t",
3523147Sxc151355 	    dladm_secobjclass2str(*sip->si_classp, classbuf));
3533147Sxc151355 
3543147Sxc151355 	ptr += snprintf(ptr, BUFLEN(lim, ptr), "0x");
3553147Sxc151355 	for (i = 0; i < *sip->si_lenp; i++) {
3563147Sxc151355 		ptr += snprintf(ptr, BUFLEN(lim, ptr), "%02x",
3573147Sxc151355 		    sip->si_val[i] & 0xff);
3583147Sxc151355 	}
3593147Sxc151355 	if (ptr > lim) {
3603147Sxc151355 		*statusp = DLADM_STATUS_TOOSMALL;
3613147Sxc151355 		return (B_FALSE);
3623147Sxc151355 	}
3633147Sxc151355 	(void) snprintf(buf, MAXLINELEN, "%s\n", tmpbuf);
3643147Sxc151355 	return (B_FALSE);
3653147Sxc151355 }
3663147Sxc151355 
3673147Sxc151355 /* ARGSUSED */
3683147Sxc151355 static boolean_t
3693147Sxc151355 process_secobj_get(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
3703147Sxc151355     dladm_status_t *statusp)
3713147Sxc151355 {
3723147Sxc151355 	if (*sip->si_lenp > *ssp->ss_info.si_lenp) {
3733147Sxc151355 		*statusp = DLADM_STATUS_TOOSMALL;
3743147Sxc151355 		return (B_FALSE);
3753147Sxc151355 	}
3763147Sxc151355 	bcopy(sip->si_val, ssp->ss_info.si_val, *sip->si_lenp);
3773147Sxc151355 	*ssp->ss_info.si_lenp = *sip->si_lenp;
3783147Sxc151355 	*ssp->ss_info.si_classp = *sip->si_classp;
3793147Sxc151355 	return (B_FALSE);
3803147Sxc151355 }
3813147Sxc151355 
3823147Sxc151355 /* ARGSUSED */
3833147Sxc151355 static boolean_t
3843147Sxc151355 process_secobj_unset(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
3853147Sxc151355     dladm_status_t *statusp)
3863147Sxc151355 {
3873147Sxc151355 	/*
3883147Sxc151355 	 * Delete line.
3893147Sxc151355 	 */
3903147Sxc151355 	buf[0] = '\0';
3913147Sxc151355 	return (B_FALSE);
3923147Sxc151355 }
3933147Sxc151355 
3943147Sxc151355 /* ARGSUSED */
3953147Sxc151355 static boolean_t
3963147Sxc151355 process_secobj_walk(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
3973147Sxc151355     dladm_status_t *statusp)
3983147Sxc151355 {
3993147Sxc151355 	secobj_name_t	*snp;
4003147Sxc151355 
4013147Sxc151355 	if ((snp = malloc(sizeof (*snp))) == NULL)
4023147Sxc151355 		return (B_TRUE);
4033147Sxc151355 
4043147Sxc151355 	if ((snp->sn_name = strdup(sip->si_name)) == NULL) {
4053147Sxc151355 		free(snp);
4063147Sxc151355 		return (B_TRUE);
4073147Sxc151355 	}
4083147Sxc151355 
4093147Sxc151355 	snp->sn_next = NULL;
4103147Sxc151355 	*ssp->ss_namelist = snp;
4113147Sxc151355 	ssp->ss_namelist = &snp->sn_next;
4123147Sxc151355 	return (B_TRUE);
4133147Sxc151355 }
4143147Sxc151355 
4153147Sxc151355 /* ARGSUSED */
4163147Sxc151355 static boolean_t
4173147Sxc151355 process_secobj_init(secobj_db_state_t *ssp, char *buf, secobj_info_t *sip,
4183147Sxc151355     dladm_status_t *statusp)
4193147Sxc151355 {
4203147Sxc151355 	*statusp = dladm_set_secobj(sip->si_name, *sip->si_classp, sip->si_val,
4215895Syz147064 	    *sip->si_lenp, DLADM_OPT_ACTIVE | DLADM_OPT_CREATE);
4223147Sxc151355 	return (B_TRUE);
4233147Sxc151355 }
4243147Sxc151355 
4253147Sxc151355 static int
4263147Sxc151355 parse_secobj_val(char *buf, secobj_info_t *sip)
4273147Sxc151355 {
4283147Sxc151355 	if (strncmp(buf, "0x", 2) != 0)
4293147Sxc151355 		return (EINVAL);
4303147Sxc151355 
4313147Sxc151355 	return (hexascii_to_octet(buf + 2, strlen(buf) - 2,
4323147Sxc151355 	    sip->si_val, sip->si_lenp));
4333147Sxc151355 }
4343147Sxc151355 
4353147Sxc151355 static boolean_t
4363147Sxc151355 process_secobj_line(secobj_db_state_t *ssp, char *buf,
4373147Sxc151355     dladm_status_t *statusp)
4383147Sxc151355 {
4393147Sxc151355 	secobj_info_t		sinfo;
4403147Sxc151355 	dladm_secobj_class_t	class;
4413147Sxc151355 	uint8_t			val[DLADM_SECOBJ_VAL_MAX];
4423147Sxc151355 	uint_t			vlen;
4433147Sxc151355 	int			i, len, nlen;
4443147Sxc151355 	char			*str, *lasts;
4453147Sxc151355 
4463147Sxc151355 	/*
4473147Sxc151355 	 * Skip leading spaces, blank lines, and comments.
4483147Sxc151355 	 */
4493147Sxc151355 	len = strlen(buf);
4503147Sxc151355 	for (i = 0; i < len; i++) {
4513147Sxc151355 		if (!isspace(buf[i]))
4523147Sxc151355 			break;
4533147Sxc151355 	}
4543147Sxc151355 	if (i == len || buf[i] == '#')
4553147Sxc151355 		return (B_TRUE);
4563147Sxc151355 
4573147Sxc151355 	str = buf + i;
4583147Sxc151355 	if (ssp->ss_info.si_name != NULL) {
4593147Sxc151355 		/*
4603147Sxc151355 		 * Skip objects we're not interested in.
4613147Sxc151355 		 */
4623147Sxc151355 		nlen = strlen(ssp->ss_info.si_name);
4633147Sxc151355 		if (strncmp(str, ssp->ss_info.si_name, nlen) != 0 ||
4643147Sxc151355 		    !isspace(str[nlen]))
4653147Sxc151355 			return (B_TRUE);
4663147Sxc151355 
4673147Sxc151355 		sinfo.si_name = ssp->ss_info.si_name;
4683147Sxc151355 	} else {
4693147Sxc151355 		/*
4703147Sxc151355 		 * If an object is not specified, find the object name
4713147Sxc151355 		 * and assign it to sinfo.si_name.
4723147Sxc151355 		 */
4733147Sxc151355 		if (strtok_r(str, " \n\t", &lasts) == NULL)
4743147Sxc151355 			goto fail;
4753147Sxc151355 
4763147Sxc151355 		nlen = strlen(str);
4773147Sxc151355 		sinfo.si_name = str;
4783147Sxc151355 	}
4793147Sxc151355 	str += nlen + 1;
4803147Sxc151355 	if (str >= buf + len)
4813147Sxc151355 		goto fail;
4823147Sxc151355 
4833147Sxc151355 	/*
4843147Sxc151355 	 * Find the class name.
4853147Sxc151355 	 */
4863147Sxc151355 	if ((str = strtok_r(str, " \n\t", &lasts)) == NULL)
4873147Sxc151355 		goto fail;
4883147Sxc151355 
4893147Sxc151355 	*statusp = dladm_str2secobjclass(str, &class);
4903147Sxc151355 	if (*statusp != DLADM_STATUS_OK)
4913147Sxc151355 		goto fail;
4923147Sxc151355 
4933147Sxc151355 	/*
4943147Sxc151355 	 * Find the object value.
4953147Sxc151355 	 */
4963147Sxc151355 	if ((str = strtok_r(NULL, " \n\t", &lasts)) == NULL)
4973147Sxc151355 		goto fail;
4983147Sxc151355 
4993147Sxc151355 	vlen = DLADM_SECOBJ_VAL_MAX;
5003147Sxc151355 	sinfo.si_classp = &class;
5013147Sxc151355 	sinfo.si_val = val;
5023147Sxc151355 	sinfo.si_lenp = &vlen;
5033147Sxc151355 	if (parse_secobj_val(str, &sinfo) != 0)
5043147Sxc151355 		goto fail;
5053147Sxc151355 
5063147Sxc151355 	return ((*ssp->ss_op)(ssp, buf, &sinfo, statusp));
5073147Sxc151355 
5083147Sxc151355 fail:
5093147Sxc151355 	/*
5103147Sxc151355 	 * Delete corrupted line.
5113147Sxc151355 	 */
5123147Sxc151355 	buf[0] = '\0';
5133147Sxc151355 	return (B_TRUE);
5143147Sxc151355 }
5153147Sxc151355 
5163147Sxc151355 static dladm_status_t
5173147Sxc151355 process_secobj_db(void *arg, FILE *fp, FILE *nfp)
5183147Sxc151355 {
5193147Sxc151355 	secobj_db_state_t	*ssp = arg;
5203147Sxc151355 	dladm_status_t		status = DLADM_STATUS_OK;
5213147Sxc151355 	char			buf[MAXLINELEN];
5223147Sxc151355 	boolean_t		cont = B_TRUE;
5233147Sxc151355 
5243147Sxc151355 	/*
5253147Sxc151355 	 * This loop processes each line of the configuration file.
5263147Sxc151355 	 * buf can potentially be modified by process_secobj_line().
5273147Sxc151355 	 * If this is a write operation and buf is not truncated, buf will
5283147Sxc151355 	 * be written to disk. process_secobj_line() will no longer be
5293147Sxc151355 	 * called after it returns B_FALSE; at which point the remainder
5303147Sxc151355 	 * of the file will continue to be read and, if necessary, written
5313147Sxc151355 	 * to disk as well.
5323147Sxc151355 	 */
5333147Sxc151355 	while (fgets(buf, MAXLINELEN, fp) != NULL) {
5343147Sxc151355 		if (cont)
5353147Sxc151355 			cont = process_secobj_line(ssp, buf, &status);
5363147Sxc151355 
5373147Sxc151355 		if (nfp != NULL && buf[0] != '\0' && fputs(buf, nfp) == EOF) {
5383147Sxc151355 			status = dladm_errno2status(errno);
5393147Sxc151355 			break;
5403147Sxc151355 		}
5413147Sxc151355 	}
5423147Sxc151355 	if (status != DLADM_STATUS_OK || !cont)
5433147Sxc151355 		return (status);
5443147Sxc151355 
5453147Sxc151355 	if (ssp->ss_op == process_secobj_set) {
5463147Sxc151355 		/*
5473147Sxc151355 		 * If the specified object is not found above, we add the
5483147Sxc151355 		 * object to the configuration file.
5493147Sxc151355 		 */
5503147Sxc151355 		(void) (*ssp->ss_op)(ssp, buf, NULL, &status);
5513147Sxc151355 		if (status == DLADM_STATUS_OK && fputs(buf, nfp) == EOF)
5523147Sxc151355 			status = dladm_errno2status(errno);
5533147Sxc151355 	}
5543147Sxc151355 
5553147Sxc151355 	if (ssp->ss_op == process_secobj_unset ||
5563147Sxc151355 	    ssp->ss_op == process_secobj_get)
5573147Sxc151355 		status = DLADM_STATUS_NOTFOUND;
5583147Sxc151355 
5593147Sxc151355 	return (status);
5603147Sxc151355 }
5613147Sxc151355 
5623147Sxc151355 #define	SECOBJ_RW_DB(statep, writeop) \
5633147Sxc151355 	(i_dladm_rw_db("/etc/dladm/secobj.conf", S_IRUSR | S_IWUSR, \
5643147Sxc151355 	process_secobj_db, (statep), (writeop)))
5653147Sxc151355 
5663147Sxc151355 static dladm_status_t
5673147Sxc151355 i_dladm_set_secobj_db(const char *obj_name, dladm_secobj_class_t class,
5683147Sxc151355     uint8_t *obj_val, uint_t obj_len)
5693147Sxc151355 {
5703147Sxc151355 	secobj_db_state_t	state;
5713147Sxc151355 
5723147Sxc151355 	state.ss_op = process_secobj_set;
5733147Sxc151355 	state.ss_info.si_name = obj_name;
5743147Sxc151355 	state.ss_info.si_classp = &class;
5753147Sxc151355 	state.ss_info.si_val = obj_val;
5763147Sxc151355 	state.ss_info.si_lenp = &obj_len;
5773147Sxc151355 	state.ss_namelist = NULL;
5783147Sxc151355 
5793147Sxc151355 	return (SECOBJ_RW_DB(&state, B_TRUE));
5803147Sxc151355 }
5813147Sxc151355 
5823147Sxc151355 static dladm_status_t
5833147Sxc151355 i_dladm_get_secobj_db(const char *obj_name, dladm_secobj_class_t *classp,
5843147Sxc151355     uint8_t *obj_val, uint_t *obj_lenp)
5853147Sxc151355 {
5863147Sxc151355 	secobj_db_state_t	state;
5873147Sxc151355 
5883147Sxc151355 	state.ss_op = process_secobj_get;
5893147Sxc151355 	state.ss_info.si_name = obj_name;
5903147Sxc151355 	state.ss_info.si_classp = classp;
5913147Sxc151355 	state.ss_info.si_val = obj_val;
5923147Sxc151355 	state.ss_info.si_lenp = obj_lenp;
5933147Sxc151355 	state.ss_namelist = NULL;
5943147Sxc151355 
5953147Sxc151355 	return (SECOBJ_RW_DB(&state, B_FALSE));
5963147Sxc151355 }
5973147Sxc151355 
5983147Sxc151355 static dladm_status_t
5993147Sxc151355 i_dladm_unset_secobj_db(const char *obj_name)
6003147Sxc151355 {
6013147Sxc151355 	secobj_db_state_t	state;
6023147Sxc151355 
6033147Sxc151355 	state.ss_op = process_secobj_unset;
6043147Sxc151355 	state.ss_info.si_name = obj_name;
6053147Sxc151355 	state.ss_info.si_classp = NULL;
6063147Sxc151355 	state.ss_info.si_val = NULL;
6073147Sxc151355 	state.ss_info.si_lenp = NULL;
6083147Sxc151355 	state.ss_namelist = NULL;
6093147Sxc151355 
6103147Sxc151355 	return (SECOBJ_RW_DB(&state, B_TRUE));
6113147Sxc151355 }
6123147Sxc151355 
6133147Sxc151355 static dladm_status_t
6143147Sxc151355 i_dladm_walk_secobj_db(void *arg, boolean_t (*func)(void *, const char *))
6153147Sxc151355 {
6163147Sxc151355 	secobj_db_state_t	state;
6173147Sxc151355 	secobj_name_t		*snp = NULL, *fsnp;
6183147Sxc151355 	dladm_status_t		status;
6193147Sxc151355 	boolean_t		cont = B_TRUE;
6203147Sxc151355 
6213147Sxc151355 	state.ss_op = process_secobj_walk;
6223147Sxc151355 	state.ss_info.si_name = NULL;
6233147Sxc151355 	state.ss_info.si_classp = NULL;
6243147Sxc151355 	state.ss_info.si_val = NULL;
6253147Sxc151355 	state.ss_info.si_lenp = NULL;
6263147Sxc151355 	state.ss_namelist = &snp;
6273147Sxc151355 
6283147Sxc151355 	status = SECOBJ_RW_DB(&state, B_FALSE);
6293147Sxc151355 	if (status != DLADM_STATUS_OK)
6303147Sxc151355 		return (status);
6313147Sxc151355 
6323147Sxc151355 	while (snp != NULL) {
6333147Sxc151355 		fsnp = snp;
6343147Sxc151355 		snp = snp->sn_next;
6353147Sxc151355 		if (cont)
6363147Sxc151355 			cont = func(arg, fsnp->sn_name);
6373147Sxc151355 		free(fsnp->sn_name);
6383147Sxc151355 		free(fsnp);
6393147Sxc151355 	}
6403147Sxc151355 	return (status);
6413147Sxc151355 }
6423147Sxc151355 
6433147Sxc151355 dladm_status_t
6443147Sxc151355 dladm_init_secobj(void)
6453147Sxc151355 {
6463147Sxc151355 	secobj_db_state_t	state;
6473147Sxc151355 
6483147Sxc151355 	state.ss_op = process_secobj_init;
6493147Sxc151355 	state.ss_info.si_name = NULL;
6503147Sxc151355 	state.ss_info.si_classp = NULL;
6513147Sxc151355 	state.ss_info.si_val = NULL;
6523147Sxc151355 	state.ss_info.si_lenp = NULL;
6533147Sxc151355 	state.ss_namelist = NULL;
6543147Sxc151355 
6553147Sxc151355 	return (SECOBJ_RW_DB(&state, B_FALSE));
6563147Sxc151355 }
657*8431SAnurag.Maskey@Sun.COM 
658*8431SAnurag.Maskey@Sun.COM boolean_t
659*8431SAnurag.Maskey@Sun.COM dladm_valid_secobj_name(const char *secobj_name)
660*8431SAnurag.Maskey@Sun.COM {
661*8431SAnurag.Maskey@Sun.COM 	size_t len = strlen(secobj_name);
662*8431SAnurag.Maskey@Sun.COM 	const char *cp;
663*8431SAnurag.Maskey@Sun.COM 
664*8431SAnurag.Maskey@Sun.COM 	if (len + 1 > DLADM_SECOBJ_NAME_MAX)
665*8431SAnurag.Maskey@Sun.COM 		return (B_FALSE);
666*8431SAnurag.Maskey@Sun.COM 
667*8431SAnurag.Maskey@Sun.COM 	/*
668*8431SAnurag.Maskey@Sun.COM 	 * The legal characters in a secobj name are:
669*8431SAnurag.Maskey@Sun.COM 	 * alphanumeric (a-z, A-Z, 0-9), '.', '_', '-'.
670*8431SAnurag.Maskey@Sun.COM 	 */
671*8431SAnurag.Maskey@Sun.COM 	for (cp = secobj_name; *cp != '\0'; cp++) {
672*8431SAnurag.Maskey@Sun.COM 		if (!isalnum(*cp) &&
673*8431SAnurag.Maskey@Sun.COM 		    (*cp != '.') && (*cp != '_') && (*cp != '-'))
674*8431SAnurag.Maskey@Sun.COM 			return (B_FALSE);
675*8431SAnurag.Maskey@Sun.COM 	}
676*8431SAnurag.Maskey@Sun.COM 
677*8431SAnurag.Maskey@Sun.COM 	return (B_TRUE);
678*8431SAnurag.Maskey@Sun.COM }
679