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 /*
22*11767SAnurag.Maskey@Sun.COM * Copyright 2010 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>
349107Sjames.d.carlson@sun.com #include <sys/dld_ioc.h>
353147Sxc151355 #include <libinetutil.h>
363871Syz147064 #include <libdllink.h>
373147Sxc151355 #include <libdladm_impl.h>
383147Sxc151355
398453SAnurag.Maskey@Sun.COM static dladm_status_t i_dladm_set_secobj_db(dladm_handle_t, const char *,
403147Sxc151355 dladm_secobj_class_t, uint8_t *, uint_t);
418453SAnurag.Maskey@Sun.COM static dladm_status_t i_dladm_get_secobj_db(dladm_handle_t, const char *,
423147Sxc151355 dladm_secobj_class_t *, uint8_t *, uint_t *);
438453SAnurag.Maskey@Sun.COM static dladm_status_t i_dladm_unset_secobj_db(dladm_handle_t, const char *);
448453SAnurag.Maskey@Sun.COM static dladm_status_t i_dladm_walk_secobj_db(dladm_handle_t, void *,
458453SAnurag.Maskey@Sun.COM boolean_t (*)(dladm_handle_t, void *,
468453SAnurag.Maskey@Sun.COM const char *));
473147Sxc151355
483147Sxc151355 typedef struct secobj_class_info {
493147Sxc151355 const char *sc_name;
503147Sxc151355 dld_secobj_class_t sc_dldclass;
513147Sxc151355 } secobj_class_info_t;
523147Sxc151355
533147Sxc151355 static secobj_class_info_t secobj_class_table[] = {
544126Szf162725 {"wep", DLD_SECOBJ_CLASS_WEP},
554126Szf162725 {"wpa", DLD_SECOBJ_CLASS_WPA}
563147Sxc151355 };
573147Sxc151355
587408SSebastien.Roy@Sun.COM #define SECOBJ_MAXBUFSZ 65536
593147Sxc151355 #define NSECOBJCLASS \
603147Sxc151355 (sizeof (secobj_class_table) / sizeof (secobj_class_info_t))
613147Sxc151355
623147Sxc151355 static boolean_t
dladm_check_secobjclass(dladm_secobj_class_t class)633147Sxc151355 dladm_check_secobjclass(dladm_secobj_class_t class)
643147Sxc151355 {
653147Sxc151355 return (class >= 0 && class < NSECOBJCLASS);
663147Sxc151355 }
673147Sxc151355
683147Sxc151355 dladm_status_t
dladm_str2secobjclass(const char * str,dladm_secobj_class_t * class)693147Sxc151355 dladm_str2secobjclass(const char *str, dladm_secobj_class_t *class)
703147Sxc151355 {
713147Sxc151355 int i;
723147Sxc151355 secobj_class_info_t *sp;
733147Sxc151355
743147Sxc151355 for (i = 0; i < NSECOBJCLASS; i++) {
753147Sxc151355 sp = &secobj_class_table[i];
763147Sxc151355 if (strcasecmp(str, sp->sc_name) == 0) {
773147Sxc151355 *class = i;
783147Sxc151355 return (DLADM_STATUS_OK);
793147Sxc151355 }
803147Sxc151355 }
813147Sxc151355 return (DLADM_STATUS_BADARG);
823147Sxc151355 }
833147Sxc151355
843147Sxc151355 const char *
dladm_secobjclass2str(dladm_secobj_class_t class,char * buf)853147Sxc151355 dladm_secobjclass2str(dladm_secobj_class_t class, char *buf)
863147Sxc151355 {
873147Sxc151355 const char *s;
883147Sxc151355
893147Sxc151355 if (!dladm_check_secobjclass(class))
903147Sxc151355 s = "";
913147Sxc151355 else
923147Sxc151355 s = secobj_class_table[class].sc_name;
933147Sxc151355
943147Sxc151355 (void) snprintf(buf, DLADM_STRSIZE, "%s", s);
953147Sxc151355 return (buf);
963147Sxc151355 }
973147Sxc151355
983147Sxc151355 static boolean_t
dladm_convert_secobjclass(dladm_secobj_class_t class,dld_secobj_class_t * dldclass)993147Sxc151355 dladm_convert_secobjclass(dladm_secobj_class_t class,
1003147Sxc151355 dld_secobj_class_t *dldclass)
1013147Sxc151355 {
1023147Sxc151355 if (!dladm_check_secobjclass(class))
1033147Sxc151355 return (B_FALSE);
1043147Sxc151355
1053147Sxc151355 *dldclass = secobj_class_table[class].sc_dldclass;
1063147Sxc151355 return (B_TRUE);
1073147Sxc151355 }
1083147Sxc151355
1093147Sxc151355 static boolean_t
dladm_convert_dldsecobjclass(dld_secobj_class_t dldclass,dladm_secobj_class_t * class)1103147Sxc151355 dladm_convert_dldsecobjclass(dld_secobj_class_t dldclass,
1113147Sxc151355 dladm_secobj_class_t *class)
1123147Sxc151355 {
1133147Sxc151355 int i;
1143147Sxc151355 secobj_class_info_t *sp;
1153147Sxc151355
1163147Sxc151355 for (i = 0; i < NSECOBJCLASS; i++) {
1173147Sxc151355 sp = &secobj_class_table[i];
1183147Sxc151355 if (dldclass == sp->sc_dldclass) {
1193147Sxc151355 *class = i;
1203147Sxc151355 return (B_TRUE);
1213147Sxc151355 }
1223147Sxc151355 }
1233147Sxc151355 return (B_FALSE);
1243147Sxc151355 }
1253147Sxc151355
1263147Sxc151355 dladm_status_t
dladm_set_secobj(dladm_handle_t handle,const char * obj_name,dladm_secobj_class_t class,uint8_t * obj_val,uint_t obj_len,uint_t flags)1278453SAnurag.Maskey@Sun.COM dladm_set_secobj(dladm_handle_t handle, const char *obj_name,
1288453SAnurag.Maskey@Sun.COM dladm_secobj_class_t class, uint8_t *obj_val, uint_t obj_len, uint_t flags)
1293147Sxc151355 {
1303147Sxc151355 dladm_status_t status = DLADM_STATUS_OK;
1313147Sxc151355 dld_ioc_secobj_set_t secobj_set;
1323147Sxc151355 dld_secobj_t *objp;
1333147Sxc151355
1348431SAnurag.Maskey@Sun.COM if (!dladm_valid_secobj_name(obj_name))
1358431SAnurag.Maskey@Sun.COM return (DLADM_STATUS_BADARG);
1368431SAnurag.Maskey@Sun.COM
1373147Sxc151355 if (!dladm_check_secobjclass(class) || flags == 0 ||
1383147Sxc151355 obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
1393147Sxc151355 obj_val == NULL || obj_len == 0 || obj_len > DLD_SECOBJ_VAL_MAX)
1403147Sxc151355 return (DLADM_STATUS_BADARG);
1413147Sxc151355
1425895Syz147064 if ((flags & DLADM_OPT_ACTIVE) == 0)
1433147Sxc151355 goto persist;
1443147Sxc151355
1453147Sxc151355 bzero(&secobj_set, sizeof (secobj_set));
1463147Sxc151355 objp = &secobj_set.ss_obj;
1473147Sxc151355 if (!dladm_convert_secobjclass(class, &objp->so_class))
1483147Sxc151355 return (DLADM_STATUS_BADARG);
1493147Sxc151355
1503147Sxc151355 (void) strlcpy(objp->so_name, obj_name, DLD_SECOBJ_NAME_MAX);
1513147Sxc151355 bcopy(obj_val, objp->so_val, obj_len);
1523147Sxc151355 objp->so_len = obj_len;
1533147Sxc151355
1543147Sxc151355 if ((flags & DLADM_OPT_CREATE) != 0)
1553147Sxc151355 secobj_set.ss_flags = DLD_SECOBJ_OPT_CREATE;
1563147Sxc151355
1578453SAnurag.Maskey@Sun.COM if (ioctl(dladm_dld_fd(handle), DLDIOC_SECOBJ_SET, &secobj_set) < 0)
1583147Sxc151355 status = dladm_errno2status(errno);
1593147Sxc151355
1603147Sxc151355 if (status != DLADM_STATUS_OK)
1613147Sxc151355 return (status);
1623147Sxc151355
1633147Sxc151355 persist:
1643147Sxc151355 if ((flags & DLADM_OPT_PERSIST) != 0) {
1658453SAnurag.Maskey@Sun.COM status = i_dladm_set_secobj_db(handle, obj_name, class,
1663147Sxc151355 obj_val, obj_len);
1673147Sxc151355 }
1683147Sxc151355 return (status);
1693147Sxc151355 }
1703147Sxc151355
1713147Sxc151355 dladm_status_t
dladm_get_secobj(dladm_handle_t handle,const char * obj_name,dladm_secobj_class_t * classp,uint8_t * obj_val,uint_t * obj_lenp,uint_t flags)1728453SAnurag.Maskey@Sun.COM dladm_get_secobj(dladm_handle_t handle, const char *obj_name,
1738453SAnurag.Maskey@Sun.COM dladm_secobj_class_t *classp, uint8_t *obj_val, uint_t *obj_lenp,
1748453SAnurag.Maskey@Sun.COM uint_t flags)
1753147Sxc151355 {
1763147Sxc151355 dladm_status_t status = DLADM_STATUS_OK;
1773147Sxc151355 dld_ioc_secobj_get_t secobj_get;
1783147Sxc151355 dld_secobj_t *objp;
1793147Sxc151355
1803147Sxc151355 if (obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
1813147Sxc151355 obj_val == NULL || obj_lenp == NULL || *obj_lenp == 0 ||
1823147Sxc151355 *obj_lenp > DLD_SECOBJ_VAL_MAX)
1833147Sxc151355 return (DLADM_STATUS_BADARG);
1843147Sxc151355
1853147Sxc151355 if ((flags & DLADM_OPT_PERSIST) != 0) {
1868453SAnurag.Maskey@Sun.COM return (i_dladm_get_secobj_db(handle, obj_name, classp,
1873147Sxc151355 obj_val, obj_lenp));
1883147Sxc151355 }
1893147Sxc151355
1903147Sxc151355 bzero(&secobj_get, sizeof (secobj_get));
1913147Sxc151355 objp = &secobj_get.sg_obj;
1923147Sxc151355 (void) strlcpy(objp->so_name, obj_name, DLD_SECOBJ_NAME_MAX);
1933147Sxc151355
1947408SSebastien.Roy@Sun.COM secobj_get.sg_size = sizeof (secobj_get);
1958453SAnurag.Maskey@Sun.COM if (ioctl(dladm_dld_fd(handle), DLDIOC_SECOBJ_GET, &secobj_get) < 0)
1963147Sxc151355 status = dladm_errno2status(errno);
1973147Sxc151355
1983147Sxc151355 if (objp->so_len > *obj_lenp)
1993147Sxc151355 return (DLADM_STATUS_TOOSMALL);
2003147Sxc151355
2013147Sxc151355 if (!dladm_convert_dldsecobjclass(objp->so_class, classp))
2023147Sxc151355 return (DLADM_STATUS_FAILED);
2033147Sxc151355
2043147Sxc151355 *obj_lenp = objp->so_len;
2053147Sxc151355 bcopy(objp->so_val, obj_val, *obj_lenp);
2063147Sxc151355 return (status);
2073147Sxc151355 }
2083147Sxc151355
2093147Sxc151355 dladm_status_t
dladm_unset_secobj(dladm_handle_t handle,const char * obj_name,uint_t flags)2108453SAnurag.Maskey@Sun.COM dladm_unset_secobj(dladm_handle_t handle, const char *obj_name, uint_t flags)
2113147Sxc151355 {
2123147Sxc151355 dladm_status_t status = DLADM_STATUS_OK;
2133147Sxc151355 dld_ioc_secobj_unset_t secobj_unset;
2143147Sxc151355
2153147Sxc151355 if (obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX ||
2163147Sxc151355 flags == 0)
2173147Sxc151355 return (DLADM_STATUS_BADARG);
2183147Sxc151355
2195895Syz147064 if ((flags & DLADM_OPT_ACTIVE) == 0)
2203147Sxc151355 goto persist;
2213147Sxc151355
2223147Sxc151355 bzero(&secobj_unset, sizeof (secobj_unset));
2233147Sxc151355 (void) strlcpy(secobj_unset.su_name, obj_name, DLD_SECOBJ_NAME_MAX);
2243147Sxc151355
2258453SAnurag.Maskey@Sun.COM if (ioctl(dladm_dld_fd(handle), DLDIOC_SECOBJ_UNSET, &secobj_unset) < 0)
2263147Sxc151355 status = dladm_errno2status(errno);
2273147Sxc151355
2283147Sxc151355 if (status != DLADM_STATUS_OK)
2293147Sxc151355 return (status);
2303147Sxc151355
2313147Sxc151355 persist:
2323147Sxc151355 if ((flags & DLADM_OPT_PERSIST) != 0)
2338453SAnurag.Maskey@Sun.COM status = i_dladm_unset_secobj_db(handle, obj_name);
2343147Sxc151355
2353147Sxc151355 return (status);
2363147Sxc151355 }
2373147Sxc151355
2383147Sxc151355 dladm_status_t
dladm_walk_secobj(dladm_handle_t handle,void * arg,boolean_t (* func)(dladm_handle_t,void *,const char *),uint_t flags)2398453SAnurag.Maskey@Sun.COM dladm_walk_secobj(dladm_handle_t handle, void *arg,
2408453SAnurag.Maskey@Sun.COM boolean_t (*func)(dladm_handle_t, void *, const char *), uint_t flags)
2413147Sxc151355 {
2423147Sxc151355 dladm_status_t status = DLADM_STATUS_OK;
2433147Sxc151355 dld_ioc_secobj_get_t *secobj_getp;
2443147Sxc151355 dld_secobj_t *objp;
2457408SSebastien.Roy@Sun.COM size_t secobj_bufsz;
2463147Sxc151355
2473147Sxc151355 if ((flags & DLADM_OPT_PERSIST) != 0)
2488453SAnurag.Maskey@Sun.COM return (i_dladm_walk_secobj_db(handle, arg, func));
2493147Sxc151355
2507408SSebastien.Roy@Sun.COM /* Start with enough room for 10 objects, increase if necessary. */
2517408SSebastien.Roy@Sun.COM secobj_bufsz = sizeof (*secobj_getp) + (10 * sizeof (*objp));
2527408SSebastien.Roy@Sun.COM secobj_getp = calloc(1, secobj_bufsz);
2537408SSebastien.Roy@Sun.COM if (secobj_getp == NULL) {
2543147Sxc151355 status = dladm_errno2status(errno);
2553147Sxc151355 goto done;
2563147Sxc151355 }
2577408SSebastien.Roy@Sun.COM
2587408SSebastien.Roy@Sun.COM tryagain:
2597408SSebastien.Roy@Sun.COM secobj_getp->sg_size = secobj_bufsz;
2608453SAnurag.Maskey@Sun.COM if (ioctl(dladm_dld_fd(handle), DLDIOC_SECOBJ_GET, secobj_getp) < 0) {
2617408SSebastien.Roy@Sun.COM if (errno == ENOSPC) {
2627408SSebastien.Roy@Sun.COM /* Increase the buffer size and try again. */
2637408SSebastien.Roy@Sun.COM secobj_bufsz *= 2;
2647408SSebastien.Roy@Sun.COM if (secobj_bufsz > SECOBJ_MAXBUFSZ) {
2657408SSebastien.Roy@Sun.COM status = dladm_errno2status(errno);
2667408SSebastien.Roy@Sun.COM goto done;
2677408SSebastien.Roy@Sun.COM }
2687408SSebastien.Roy@Sun.COM secobj_getp = realloc(secobj_getp, secobj_bufsz);
2697408SSebastien.Roy@Sun.COM if (secobj_getp == NULL) {
2707408SSebastien.Roy@Sun.COM status = dladm_errno2status(errno);
2717408SSebastien.Roy@Sun.COM goto done;
2727408SSebastien.Roy@Sun.COM }
2737408SSebastien.Roy@Sun.COM bzero(secobj_getp, secobj_bufsz);
2747408SSebastien.Roy@Sun.COM goto tryagain;
2757408SSebastien.Roy@Sun.COM }
2763147Sxc151355 status = dladm_errno2status(errno);
2773147Sxc151355 goto done;
2783147Sxc151355 }
2793147Sxc151355
2803147Sxc151355 objp = (dld_secobj_t *)(secobj_getp + 1);
2813147Sxc151355 while (secobj_getp->sg_count > 0) {
2828453SAnurag.Maskey@Sun.COM if (!func(handle, arg, objp->so_name))
2833147Sxc151355 goto done;
2843147Sxc151355 secobj_getp->sg_count--;
2853147Sxc151355 objp++;
2863147Sxc151355 }
2873147Sxc151355 done:
2883147Sxc151355 free(secobj_getp);
2893147Sxc151355 return (status);
2903147Sxc151355 }
2913147Sxc151355
2923147Sxc151355 /*
2933147Sxc151355 * Data structures used for implementing persistent secure objects
2943147Sxc151355 */
2953147Sxc151355 typedef struct secobj_info {
2963147Sxc151355 const char *si_name;
2973147Sxc151355 dladm_secobj_class_t *si_classp;
2983147Sxc151355 uint8_t *si_val;
2993147Sxc151355 uint_t *si_lenp;
3003147Sxc151355 } secobj_info_t;
3013147Sxc151355
3023147Sxc151355 typedef struct secobj_name {
3033147Sxc151355 char *sn_name;
3043147Sxc151355 struct secobj_name *sn_next;
3053147Sxc151355 } secobj_name_t;
3063147Sxc151355
3073147Sxc151355 typedef struct secobj_db_state secobj_db_state_t;
3083147Sxc151355
3098453SAnurag.Maskey@Sun.COM typedef boolean_t (*secobj_db_op_t)(dladm_handle_t, struct secobj_db_state *,
3108453SAnurag.Maskey@Sun.COM char *, secobj_info_t *, dladm_status_t *);
3113147Sxc151355
3123147Sxc151355 struct secobj_db_state {
3133147Sxc151355 secobj_db_op_t ss_op;
3143147Sxc151355 secobj_info_t ss_info;
3153147Sxc151355 secobj_name_t **ss_namelist;
3163147Sxc151355 };
3173147Sxc151355
3183147Sxc151355 /*
3193147Sxc151355 * Update or generate a secobj entry using the info in ssp->ss_info.
3203147Sxc151355 */
3213147Sxc151355 /* ARGSUSED */
3223147Sxc151355 static boolean_t
process_secobj_set(dladm_handle_t handle,secobj_db_state_t * ssp,char * buf,secobj_info_t * sip,dladm_status_t * statusp)3238453SAnurag.Maskey@Sun.COM process_secobj_set(dladm_handle_t handle, secobj_db_state_t *ssp, char *buf,
3248453SAnurag.Maskey@Sun.COM secobj_info_t *sip, dladm_status_t *statusp)
3253147Sxc151355 {
3263147Sxc151355 char tmpbuf[MAXLINELEN];
3273147Sxc151355 char classbuf[DLADM_STRSIZE];
3283147Sxc151355 char *ptr = tmpbuf, *lim = tmpbuf + MAXLINELEN;
3293147Sxc151355 int i;
3303147Sxc151355
3313147Sxc151355 sip = &ssp->ss_info;
3323147Sxc151355
3333147Sxc151355 ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", sip->si_name);
3343147Sxc151355 ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t",
3353147Sxc151355 dladm_secobjclass2str(*sip->si_classp, classbuf));
3363147Sxc151355
3373147Sxc151355 ptr += snprintf(ptr, BUFLEN(lim, ptr), "0x");
3383147Sxc151355 for (i = 0; i < *sip->si_lenp; i++) {
3393147Sxc151355 ptr += snprintf(ptr, BUFLEN(lim, ptr), "%02x",
3403147Sxc151355 sip->si_val[i] & 0xff);
3413147Sxc151355 }
3423147Sxc151355 if (ptr > lim) {
3433147Sxc151355 *statusp = DLADM_STATUS_TOOSMALL;
3443147Sxc151355 return (B_FALSE);
3453147Sxc151355 }
3463147Sxc151355 (void) snprintf(buf, MAXLINELEN, "%s\n", tmpbuf);
3473147Sxc151355 return (B_FALSE);
3483147Sxc151355 }
3493147Sxc151355
3503147Sxc151355 /* ARGSUSED */
3513147Sxc151355 static boolean_t
process_secobj_get(dladm_handle_t handle,secobj_db_state_t * ssp,char * buf,secobj_info_t * sip,dladm_status_t * statusp)3528453SAnurag.Maskey@Sun.COM process_secobj_get(dladm_handle_t handle, secobj_db_state_t *ssp, char *buf,
3538453SAnurag.Maskey@Sun.COM secobj_info_t *sip, dladm_status_t *statusp)
3543147Sxc151355 {
3553147Sxc151355 if (*sip->si_lenp > *ssp->ss_info.si_lenp) {
3563147Sxc151355 *statusp = DLADM_STATUS_TOOSMALL;
3573147Sxc151355 return (B_FALSE);
3583147Sxc151355 }
3593147Sxc151355 bcopy(sip->si_val, ssp->ss_info.si_val, *sip->si_lenp);
3603147Sxc151355 *ssp->ss_info.si_lenp = *sip->si_lenp;
3613147Sxc151355 *ssp->ss_info.si_classp = *sip->si_classp;
3623147Sxc151355 return (B_FALSE);
3633147Sxc151355 }
3643147Sxc151355
3653147Sxc151355 /* ARGSUSED */
3663147Sxc151355 static boolean_t
process_secobj_unset(dladm_handle_t handle,secobj_db_state_t * ssp,char * buf,secobj_info_t * sip,dladm_status_t * statusp)3678453SAnurag.Maskey@Sun.COM process_secobj_unset(dladm_handle_t handle, secobj_db_state_t *ssp, char *buf,
3688453SAnurag.Maskey@Sun.COM secobj_info_t *sip, dladm_status_t *statusp)
3693147Sxc151355 {
3703147Sxc151355 /*
3713147Sxc151355 * Delete line.
3723147Sxc151355 */
3733147Sxc151355 buf[0] = '\0';
3743147Sxc151355 return (B_FALSE);
3753147Sxc151355 }
3763147Sxc151355
3773147Sxc151355 /* ARGSUSED */
3783147Sxc151355 static boolean_t
process_secobj_walk(dladm_handle_t handle,secobj_db_state_t * ssp,char * buf,secobj_info_t * sip,dladm_status_t * statusp)3798453SAnurag.Maskey@Sun.COM process_secobj_walk(dladm_handle_t handle, secobj_db_state_t *ssp, char *buf,
3808453SAnurag.Maskey@Sun.COM secobj_info_t *sip, dladm_status_t *statusp)
3813147Sxc151355 {
3823147Sxc151355 secobj_name_t *snp;
3833147Sxc151355
3843147Sxc151355 if ((snp = malloc(sizeof (*snp))) == NULL)
3853147Sxc151355 return (B_TRUE);
3863147Sxc151355
3873147Sxc151355 if ((snp->sn_name = strdup(sip->si_name)) == NULL) {
3883147Sxc151355 free(snp);
3893147Sxc151355 return (B_TRUE);
3903147Sxc151355 }
3913147Sxc151355
3923147Sxc151355 snp->sn_next = NULL;
3933147Sxc151355 *ssp->ss_namelist = snp;
3943147Sxc151355 ssp->ss_namelist = &snp->sn_next;
3953147Sxc151355 return (B_TRUE);
3963147Sxc151355 }
3973147Sxc151355
3983147Sxc151355 /* ARGSUSED */
3993147Sxc151355 static boolean_t
process_secobj_init(dladm_handle_t handle,secobj_db_state_t * ssp,char * buf,secobj_info_t * sip,dladm_status_t * statusp)4008453SAnurag.Maskey@Sun.COM process_secobj_init(dladm_handle_t handle, secobj_db_state_t *ssp, char *buf,
4018453SAnurag.Maskey@Sun.COM secobj_info_t *sip, dladm_status_t *statusp)
4023147Sxc151355 {
4038453SAnurag.Maskey@Sun.COM *statusp = dladm_set_secobj(handle, sip->si_name, *sip->si_classp,
4048453SAnurag.Maskey@Sun.COM sip->si_val, *sip->si_lenp,
4058453SAnurag.Maskey@Sun.COM DLADM_OPT_ACTIVE | DLADM_OPT_CREATE);
4063147Sxc151355 return (B_TRUE);
4073147Sxc151355 }
4083147Sxc151355
4093147Sxc151355 static int
parse_secobj_val(char * buf,secobj_info_t * sip)4103147Sxc151355 parse_secobj_val(char *buf, secobj_info_t *sip)
4113147Sxc151355 {
4123147Sxc151355 if (strncmp(buf, "0x", 2) != 0)
4133147Sxc151355 return (EINVAL);
4143147Sxc151355
4153147Sxc151355 return (hexascii_to_octet(buf + 2, strlen(buf) - 2,
4163147Sxc151355 sip->si_val, sip->si_lenp));
4173147Sxc151355 }
4183147Sxc151355
4193147Sxc151355 static boolean_t
process_secobj_line(dladm_handle_t handle,secobj_db_state_t * ssp,char * buf,dladm_status_t * statusp)4208453SAnurag.Maskey@Sun.COM process_secobj_line(dladm_handle_t handle, secobj_db_state_t *ssp, char *buf,
4213147Sxc151355 dladm_status_t *statusp)
4223147Sxc151355 {
4233147Sxc151355 secobj_info_t sinfo;
4243147Sxc151355 dladm_secobj_class_t class;
4253147Sxc151355 uint8_t val[DLADM_SECOBJ_VAL_MAX];
4263147Sxc151355 uint_t vlen;
4273147Sxc151355 int i, len, nlen;
4283147Sxc151355 char *str, *lasts;
4293147Sxc151355
4303147Sxc151355 /*
4313147Sxc151355 * Skip leading spaces, blank lines, and comments.
4323147Sxc151355 */
4333147Sxc151355 len = strlen(buf);
4343147Sxc151355 for (i = 0; i < len; i++) {
4353147Sxc151355 if (!isspace(buf[i]))
4363147Sxc151355 break;
4373147Sxc151355 }
4383147Sxc151355 if (i == len || buf[i] == '#')
4393147Sxc151355 return (B_TRUE);
4403147Sxc151355
4413147Sxc151355 str = buf + i;
4423147Sxc151355 if (ssp->ss_info.si_name != NULL) {
4433147Sxc151355 /*
4443147Sxc151355 * Skip objects we're not interested in.
4453147Sxc151355 */
4463147Sxc151355 nlen = strlen(ssp->ss_info.si_name);
4473147Sxc151355 if (strncmp(str, ssp->ss_info.si_name, nlen) != 0 ||
4483147Sxc151355 !isspace(str[nlen]))
4493147Sxc151355 return (B_TRUE);
4503147Sxc151355
4513147Sxc151355 sinfo.si_name = ssp->ss_info.si_name;
4523147Sxc151355 } else {
4533147Sxc151355 /*
4543147Sxc151355 * If an object is not specified, find the object name
4553147Sxc151355 * and assign it to sinfo.si_name.
4563147Sxc151355 */
4573147Sxc151355 if (strtok_r(str, " \n\t", &lasts) == NULL)
4583147Sxc151355 goto fail;
4593147Sxc151355
4603147Sxc151355 nlen = strlen(str);
4613147Sxc151355 sinfo.si_name = str;
4623147Sxc151355 }
4633147Sxc151355 str += nlen + 1;
4643147Sxc151355 if (str >= buf + len)
4653147Sxc151355 goto fail;
4663147Sxc151355
4673147Sxc151355 /*
4683147Sxc151355 * Find the class name.
4693147Sxc151355 */
4703147Sxc151355 if ((str = strtok_r(str, " \n\t", &lasts)) == NULL)
4713147Sxc151355 goto fail;
4723147Sxc151355
4733147Sxc151355 *statusp = dladm_str2secobjclass(str, &class);
4743147Sxc151355 if (*statusp != DLADM_STATUS_OK)
4753147Sxc151355 goto fail;
4763147Sxc151355
4773147Sxc151355 /*
4783147Sxc151355 * Find the object value.
4793147Sxc151355 */
4803147Sxc151355 if ((str = strtok_r(NULL, " \n\t", &lasts)) == NULL)
4813147Sxc151355 goto fail;
4823147Sxc151355
4833147Sxc151355 vlen = DLADM_SECOBJ_VAL_MAX;
4843147Sxc151355 sinfo.si_classp = &class;
4853147Sxc151355 sinfo.si_val = val;
4863147Sxc151355 sinfo.si_lenp = &vlen;
4873147Sxc151355 if (parse_secobj_val(str, &sinfo) != 0)
4883147Sxc151355 goto fail;
4893147Sxc151355
4908453SAnurag.Maskey@Sun.COM return ((*ssp->ss_op)(handle, ssp, buf, &sinfo, statusp));
4913147Sxc151355
4923147Sxc151355 fail:
4933147Sxc151355 /*
4943147Sxc151355 * Delete corrupted line.
4953147Sxc151355 */
4963147Sxc151355 buf[0] = '\0';
4973147Sxc151355 return (B_TRUE);
4983147Sxc151355 }
4993147Sxc151355
5003147Sxc151355 static dladm_status_t
process_secobj_db(dladm_handle_t handle,void * arg,FILE * fp,FILE * nfp)5018453SAnurag.Maskey@Sun.COM process_secobj_db(dladm_handle_t handle, void *arg, FILE *fp, FILE *nfp)
5023147Sxc151355 {
5033147Sxc151355 secobj_db_state_t *ssp = arg;
5043147Sxc151355 dladm_status_t status = DLADM_STATUS_OK;
5053147Sxc151355 char buf[MAXLINELEN];
5063147Sxc151355 boolean_t cont = B_TRUE;
5073147Sxc151355
5083147Sxc151355 /*
5093147Sxc151355 * This loop processes each line of the configuration file.
5103147Sxc151355 * buf can potentially be modified by process_secobj_line().
5113147Sxc151355 * If this is a write operation and buf is not truncated, buf will
5123147Sxc151355 * be written to disk. process_secobj_line() will no longer be
5133147Sxc151355 * called after it returns B_FALSE; at which point the remainder
5143147Sxc151355 * of the file will continue to be read and, if necessary, written
5153147Sxc151355 * to disk as well.
5163147Sxc151355 */
5173147Sxc151355 while (fgets(buf, MAXLINELEN, fp) != NULL) {
5183147Sxc151355 if (cont)
5198453SAnurag.Maskey@Sun.COM cont = process_secobj_line(handle, ssp, buf, &status);
5203147Sxc151355
5213147Sxc151355 if (nfp != NULL && buf[0] != '\0' && fputs(buf, nfp) == EOF) {
5223147Sxc151355 status = dladm_errno2status(errno);
5233147Sxc151355 break;
5243147Sxc151355 }
5253147Sxc151355 }
5263147Sxc151355 if (status != DLADM_STATUS_OK || !cont)
5273147Sxc151355 return (status);
5283147Sxc151355
5293147Sxc151355 if (ssp->ss_op == process_secobj_set) {
5303147Sxc151355 /*
5313147Sxc151355 * If the specified object is not found above, we add the
5323147Sxc151355 * object to the configuration file.
5333147Sxc151355 */
5348453SAnurag.Maskey@Sun.COM (void) (*ssp->ss_op)(handle, ssp, buf, NULL, &status);
5353147Sxc151355 if (status == DLADM_STATUS_OK && fputs(buf, nfp) == EOF)
5363147Sxc151355 status = dladm_errno2status(errno);
5373147Sxc151355 }
5383147Sxc151355
5393147Sxc151355 if (ssp->ss_op == process_secobj_unset ||
5403147Sxc151355 ssp->ss_op == process_secobj_get)
5413147Sxc151355 status = DLADM_STATUS_NOTFOUND;
5423147Sxc151355
5433147Sxc151355 return (status);
5443147Sxc151355 }
5453147Sxc151355
546*11767SAnurag.Maskey@Sun.COM #define SECOBJ_RW_DB(handle, statep, writeop) \
547*11767SAnurag.Maskey@Sun.COM (i_dladm_rw_db(handle, "/etc/dladm/secobj.conf", \
548*11767SAnurag.Maskey@Sun.COM S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, \
5493147Sxc151355 process_secobj_db, (statep), (writeop)))
5503147Sxc151355
5513147Sxc151355 static dladm_status_t
i_dladm_set_secobj_db(dladm_handle_t handle,const char * obj_name,dladm_secobj_class_t class,uint8_t * obj_val,uint_t obj_len)5528453SAnurag.Maskey@Sun.COM i_dladm_set_secobj_db(dladm_handle_t handle, const char *obj_name,
5538453SAnurag.Maskey@Sun.COM dladm_secobj_class_t class, uint8_t *obj_val, uint_t obj_len)
5543147Sxc151355 {
5553147Sxc151355 secobj_db_state_t state;
5563147Sxc151355
5573147Sxc151355 state.ss_op = process_secobj_set;
5583147Sxc151355 state.ss_info.si_name = obj_name;
5593147Sxc151355 state.ss_info.si_classp = &class;
5603147Sxc151355 state.ss_info.si_val = obj_val;
5613147Sxc151355 state.ss_info.si_lenp = &obj_len;
5623147Sxc151355 state.ss_namelist = NULL;
5633147Sxc151355
5648453SAnurag.Maskey@Sun.COM return (SECOBJ_RW_DB(handle, &state, B_TRUE));
5653147Sxc151355 }
5663147Sxc151355
5673147Sxc151355 static dladm_status_t
i_dladm_get_secobj_db(dladm_handle_t handle,const char * obj_name,dladm_secobj_class_t * classp,uint8_t * obj_val,uint_t * obj_lenp)5688453SAnurag.Maskey@Sun.COM i_dladm_get_secobj_db(dladm_handle_t handle, const char *obj_name,
5698453SAnurag.Maskey@Sun.COM dladm_secobj_class_t *classp, uint8_t *obj_val, uint_t *obj_lenp)
5703147Sxc151355 {
5713147Sxc151355 secobj_db_state_t state;
5723147Sxc151355
5733147Sxc151355 state.ss_op = process_secobj_get;
5743147Sxc151355 state.ss_info.si_name = obj_name;
5753147Sxc151355 state.ss_info.si_classp = classp;
5763147Sxc151355 state.ss_info.si_val = obj_val;
5773147Sxc151355 state.ss_info.si_lenp = obj_lenp;
5783147Sxc151355 state.ss_namelist = NULL;
5793147Sxc151355
5808453SAnurag.Maskey@Sun.COM return (SECOBJ_RW_DB(handle, &state, B_FALSE));
5813147Sxc151355 }
5823147Sxc151355
5833147Sxc151355 static dladm_status_t
i_dladm_unset_secobj_db(dladm_handle_t handle,const char * obj_name)5848453SAnurag.Maskey@Sun.COM i_dladm_unset_secobj_db(dladm_handle_t handle, const char *obj_name)
5853147Sxc151355 {
5863147Sxc151355 secobj_db_state_t state;
5873147Sxc151355
5883147Sxc151355 state.ss_op = process_secobj_unset;
5893147Sxc151355 state.ss_info.si_name = obj_name;
5903147Sxc151355 state.ss_info.si_classp = NULL;
5913147Sxc151355 state.ss_info.si_val = NULL;
5923147Sxc151355 state.ss_info.si_lenp = NULL;
5933147Sxc151355 state.ss_namelist = NULL;
5943147Sxc151355
5958453SAnurag.Maskey@Sun.COM return (SECOBJ_RW_DB(handle, &state, B_TRUE));
5963147Sxc151355 }
5973147Sxc151355
5983147Sxc151355 static dladm_status_t
i_dladm_walk_secobj_db(dladm_handle_t handle,void * arg,boolean_t (* func)(dladm_handle_t,void *,const char *))5998453SAnurag.Maskey@Sun.COM i_dladm_walk_secobj_db(dladm_handle_t handle, void *arg,
6008453SAnurag.Maskey@Sun.COM boolean_t (*func)(dladm_handle_t, void *, const char *))
6013147Sxc151355 {
6023147Sxc151355 secobj_db_state_t state;
6033147Sxc151355 secobj_name_t *snp = NULL, *fsnp;
6043147Sxc151355 dladm_status_t status;
6053147Sxc151355 boolean_t cont = B_TRUE;
6063147Sxc151355
6073147Sxc151355 state.ss_op = process_secobj_walk;
6083147Sxc151355 state.ss_info.si_name = NULL;
6093147Sxc151355 state.ss_info.si_classp = NULL;
6103147Sxc151355 state.ss_info.si_val = NULL;
6113147Sxc151355 state.ss_info.si_lenp = NULL;
6123147Sxc151355 state.ss_namelist = &snp;
6133147Sxc151355
6148453SAnurag.Maskey@Sun.COM status = SECOBJ_RW_DB(handle, &state, B_FALSE);
6153147Sxc151355 if (status != DLADM_STATUS_OK)
6163147Sxc151355 return (status);
6173147Sxc151355
6183147Sxc151355 while (snp != NULL) {
6193147Sxc151355 fsnp = snp;
6203147Sxc151355 snp = snp->sn_next;
6213147Sxc151355 if (cont)
6228453SAnurag.Maskey@Sun.COM cont = func(handle, arg, fsnp->sn_name);
6233147Sxc151355 free(fsnp->sn_name);
6243147Sxc151355 free(fsnp);
6253147Sxc151355 }
6263147Sxc151355 return (status);
6273147Sxc151355 }
6283147Sxc151355
6293147Sxc151355 dladm_status_t
dladm_init_secobj(dladm_handle_t handle)6308453SAnurag.Maskey@Sun.COM dladm_init_secobj(dladm_handle_t handle)
6313147Sxc151355 {
6323147Sxc151355 secobj_db_state_t state;
6333147Sxc151355
6343147Sxc151355 state.ss_op = process_secobj_init;
6353147Sxc151355 state.ss_info.si_name = NULL;
6363147Sxc151355 state.ss_info.si_classp = NULL;
6373147Sxc151355 state.ss_info.si_val = NULL;
6383147Sxc151355 state.ss_info.si_lenp = NULL;
6393147Sxc151355 state.ss_namelist = NULL;
6403147Sxc151355
6418453SAnurag.Maskey@Sun.COM return (SECOBJ_RW_DB(handle, &state, B_FALSE));
6423147Sxc151355 }
6438431SAnurag.Maskey@Sun.COM
6448431SAnurag.Maskey@Sun.COM boolean_t
dladm_valid_secobj_name(const char * secobj_name)6458431SAnurag.Maskey@Sun.COM dladm_valid_secobj_name(const char *secobj_name)
6468431SAnurag.Maskey@Sun.COM {
6478431SAnurag.Maskey@Sun.COM size_t len = strlen(secobj_name);
6488431SAnurag.Maskey@Sun.COM const char *cp;
6498431SAnurag.Maskey@Sun.COM
6508431SAnurag.Maskey@Sun.COM if (len + 1 > DLADM_SECOBJ_NAME_MAX)
6518431SAnurag.Maskey@Sun.COM return (B_FALSE);
6528431SAnurag.Maskey@Sun.COM
6538431SAnurag.Maskey@Sun.COM /*
6548431SAnurag.Maskey@Sun.COM * The legal characters in a secobj name are:
6558431SAnurag.Maskey@Sun.COM * alphanumeric (a-z, A-Z, 0-9), '.', '_', '-'.
6568431SAnurag.Maskey@Sun.COM */
6578431SAnurag.Maskey@Sun.COM for (cp = secobj_name; *cp != '\0'; cp++) {
6588431SAnurag.Maskey@Sun.COM if (!isalnum(*cp) &&
6598431SAnurag.Maskey@Sun.COM (*cp != '.') && (*cp != '_') && (*cp != '-'))
6608431SAnurag.Maskey@Sun.COM return (B_FALSE);
6618431SAnurag.Maskey@Sun.COM }
6628431SAnurag.Maskey@Sun.COM
6638431SAnurag.Maskey@Sun.COM return (B_TRUE);
6648431SAnurag.Maskey@Sun.COM }
665