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