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 38*8453SAnurag.Maskey@Sun.COM static dladm_status_t i_dladm_set_secobj_db(dladm_handle_t, const char *, 393147Sxc151355 dladm_secobj_class_t, uint8_t *, uint_t); 40*8453SAnurag.Maskey@Sun.COM static dladm_status_t i_dladm_get_secobj_db(dladm_handle_t, const char *, 413147Sxc151355 dladm_secobj_class_t *, uint8_t *, uint_t *); 42*8453SAnurag.Maskey@Sun.COM static dladm_status_t i_dladm_unset_secobj_db(dladm_handle_t, const char *); 43*8453SAnurag.Maskey@Sun.COM static dladm_status_t i_dladm_walk_secobj_db(dladm_handle_t, void *, 44*8453SAnurag.Maskey@Sun.COM boolean_t (*)(dladm_handle_t, void *, 45*8453SAnurag.Maskey@Sun.COM const char *)); 463147Sxc151355 473147Sxc151355 typedef struct secobj_class_info { 483147Sxc151355 const char *sc_name; 493147Sxc151355 dld_secobj_class_t sc_dldclass; 503147Sxc151355 } secobj_class_info_t; 513147Sxc151355 523147Sxc151355 static secobj_class_info_t secobj_class_table[] = { 534126Szf162725 {"wep", DLD_SECOBJ_CLASS_WEP}, 544126Szf162725 {"wpa", DLD_SECOBJ_CLASS_WPA} 553147Sxc151355 }; 563147Sxc151355 577408SSebastien.Roy@Sun.COM #define SECOBJ_MAXBUFSZ 65536 583147Sxc151355 #define NSECOBJCLASS \ 593147Sxc151355 (sizeof (secobj_class_table) / sizeof (secobj_class_info_t)) 603147Sxc151355 613147Sxc151355 static boolean_t 623147Sxc151355 dladm_check_secobjclass(dladm_secobj_class_t class) 633147Sxc151355 { 643147Sxc151355 return (class >= 0 && class < NSECOBJCLASS); 653147Sxc151355 } 663147Sxc151355 673147Sxc151355 dladm_status_t 683147Sxc151355 dladm_str2secobjclass(const char *str, dladm_secobj_class_t *class) 693147Sxc151355 { 703147Sxc151355 int i; 713147Sxc151355 secobj_class_info_t *sp; 723147Sxc151355 733147Sxc151355 for (i = 0; i < NSECOBJCLASS; i++) { 743147Sxc151355 sp = &secobj_class_table[i]; 753147Sxc151355 if (strcasecmp(str, sp->sc_name) == 0) { 763147Sxc151355 *class = i; 773147Sxc151355 return (DLADM_STATUS_OK); 783147Sxc151355 } 793147Sxc151355 } 803147Sxc151355 return (DLADM_STATUS_BADARG); 813147Sxc151355 } 823147Sxc151355 833147Sxc151355 const char * 843147Sxc151355 dladm_secobjclass2str(dladm_secobj_class_t class, char *buf) 853147Sxc151355 { 863147Sxc151355 const char *s; 873147Sxc151355 883147Sxc151355 if (!dladm_check_secobjclass(class)) 893147Sxc151355 s = ""; 903147Sxc151355 else 913147Sxc151355 s = secobj_class_table[class].sc_name; 923147Sxc151355 933147Sxc151355 (void) snprintf(buf, DLADM_STRSIZE, "%s", s); 943147Sxc151355 return (buf); 953147Sxc151355 } 963147Sxc151355 973147Sxc151355 static boolean_t 983147Sxc151355 dladm_convert_secobjclass(dladm_secobj_class_t class, 993147Sxc151355 dld_secobj_class_t *dldclass) 1003147Sxc151355 { 1013147Sxc151355 if (!dladm_check_secobjclass(class)) 1023147Sxc151355 return (B_FALSE); 1033147Sxc151355 1043147Sxc151355 *dldclass = secobj_class_table[class].sc_dldclass; 1053147Sxc151355 return (B_TRUE); 1063147Sxc151355 } 1073147Sxc151355 1083147Sxc151355 static boolean_t 1093147Sxc151355 dladm_convert_dldsecobjclass(dld_secobj_class_t dldclass, 1103147Sxc151355 dladm_secobj_class_t *class) 1113147Sxc151355 { 1123147Sxc151355 int i; 1133147Sxc151355 secobj_class_info_t *sp; 1143147Sxc151355 1153147Sxc151355 for (i = 0; i < NSECOBJCLASS; i++) { 1163147Sxc151355 sp = &secobj_class_table[i]; 1173147Sxc151355 if (dldclass == sp->sc_dldclass) { 1183147Sxc151355 *class = i; 1193147Sxc151355 return (B_TRUE); 1203147Sxc151355 } 1213147Sxc151355 } 1223147Sxc151355 return (B_FALSE); 1233147Sxc151355 } 1243147Sxc151355 1253147Sxc151355 dladm_status_t 126*8453SAnurag.Maskey@Sun.COM dladm_set_secobj(dladm_handle_t handle, const char *obj_name, 127*8453SAnurag.Maskey@Sun.COM dladm_secobj_class_t class, uint8_t *obj_val, uint_t obj_len, uint_t flags) 1283147Sxc151355 { 1293147Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 1303147Sxc151355 dld_ioc_secobj_set_t secobj_set; 1313147Sxc151355 dld_secobj_t *objp; 1323147Sxc151355 1338431SAnurag.Maskey@Sun.COM if (!dladm_valid_secobj_name(obj_name)) 1348431SAnurag.Maskey@Sun.COM return (DLADM_STATUS_BADARG); 1358431SAnurag.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 156*8453SAnurag.Maskey@Sun.COM if (ioctl(dladm_dld_fd(handle), DLDIOC_SECOBJ_SET, &secobj_set) < 0) 1573147Sxc151355 status = dladm_errno2status(errno); 1583147Sxc151355 1593147Sxc151355 if (status != DLADM_STATUS_OK) 1603147Sxc151355 return (status); 1613147Sxc151355 1623147Sxc151355 persist: 1633147Sxc151355 if ((flags & DLADM_OPT_PERSIST) != 0) { 164*8453SAnurag.Maskey@Sun.COM status = i_dladm_set_secobj_db(handle, obj_name, class, 1653147Sxc151355 obj_val, obj_len); 1663147Sxc151355 } 1673147Sxc151355 return (status); 1683147Sxc151355 } 1693147Sxc151355 1703147Sxc151355 dladm_status_t 171*8453SAnurag.Maskey@Sun.COM dladm_get_secobj(dladm_handle_t handle, const char *obj_name, 172*8453SAnurag.Maskey@Sun.COM dladm_secobj_class_t *classp, uint8_t *obj_val, uint_t *obj_lenp, 173*8453SAnurag.Maskey@Sun.COM uint_t flags) 1743147Sxc151355 { 1753147Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 1763147Sxc151355 dld_ioc_secobj_get_t secobj_get; 1773147Sxc151355 dld_secobj_t *objp; 1783147Sxc151355 1793147Sxc151355 if (obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX || 1803147Sxc151355 obj_val == NULL || obj_lenp == NULL || *obj_lenp == 0 || 1813147Sxc151355 *obj_lenp > DLD_SECOBJ_VAL_MAX) 1823147Sxc151355 return (DLADM_STATUS_BADARG); 1833147Sxc151355 1843147Sxc151355 if ((flags & DLADM_OPT_PERSIST) != 0) { 185*8453SAnurag.Maskey@Sun.COM return (i_dladm_get_secobj_db(handle, obj_name, classp, 1863147Sxc151355 obj_val, obj_lenp)); 1873147Sxc151355 } 1883147Sxc151355 1893147Sxc151355 bzero(&secobj_get, sizeof (secobj_get)); 1903147Sxc151355 objp = &secobj_get.sg_obj; 1913147Sxc151355 (void) strlcpy(objp->so_name, obj_name, DLD_SECOBJ_NAME_MAX); 1923147Sxc151355 1937408SSebastien.Roy@Sun.COM secobj_get.sg_size = sizeof (secobj_get); 194*8453SAnurag.Maskey@Sun.COM if (ioctl(dladm_dld_fd(handle), DLDIOC_SECOBJ_GET, &secobj_get) < 0) 1953147Sxc151355 status = dladm_errno2status(errno); 1963147Sxc151355 1973147Sxc151355 if (objp->so_len > *obj_lenp) 1983147Sxc151355 return (DLADM_STATUS_TOOSMALL); 1993147Sxc151355 2003147Sxc151355 if (!dladm_convert_dldsecobjclass(objp->so_class, classp)) 2013147Sxc151355 return (DLADM_STATUS_FAILED); 2023147Sxc151355 2033147Sxc151355 *obj_lenp = objp->so_len; 2043147Sxc151355 bcopy(objp->so_val, obj_val, *obj_lenp); 2053147Sxc151355 return (status); 2063147Sxc151355 } 2073147Sxc151355 2083147Sxc151355 dladm_status_t 209*8453SAnurag.Maskey@Sun.COM dladm_unset_secobj(dladm_handle_t handle, const char *obj_name, uint_t flags) 2103147Sxc151355 { 2113147Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 2123147Sxc151355 dld_ioc_secobj_unset_t secobj_unset; 2133147Sxc151355 2143147Sxc151355 if (obj_name == NULL || strlen(obj_name) > DLD_SECOBJ_NAME_MAX || 2153147Sxc151355 flags == 0) 2163147Sxc151355 return (DLADM_STATUS_BADARG); 2173147Sxc151355 2185895Syz147064 if ((flags & DLADM_OPT_ACTIVE) == 0) 2193147Sxc151355 goto persist; 2203147Sxc151355 2213147Sxc151355 bzero(&secobj_unset, sizeof (secobj_unset)); 2223147Sxc151355 (void) strlcpy(secobj_unset.su_name, obj_name, DLD_SECOBJ_NAME_MAX); 2233147Sxc151355 224*8453SAnurag.Maskey@Sun.COM if (ioctl(dladm_dld_fd(handle), DLDIOC_SECOBJ_UNSET, &secobj_unset) < 0) 2253147Sxc151355 status = dladm_errno2status(errno); 2263147Sxc151355 2273147Sxc151355 if (status != DLADM_STATUS_OK) 2283147Sxc151355 return (status); 2293147Sxc151355 2303147Sxc151355 persist: 2313147Sxc151355 if ((flags & DLADM_OPT_PERSIST) != 0) 232*8453SAnurag.Maskey@Sun.COM status = i_dladm_unset_secobj_db(handle, obj_name); 2333147Sxc151355 2343147Sxc151355 return (status); 2353147Sxc151355 } 2363147Sxc151355 2373147Sxc151355 dladm_status_t 238*8453SAnurag.Maskey@Sun.COM dladm_walk_secobj(dladm_handle_t handle, void *arg, 239*8453SAnurag.Maskey@Sun.COM boolean_t (*func)(dladm_handle_t, void *, const char *), uint_t flags) 2403147Sxc151355 { 2413147Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 2423147Sxc151355 dld_ioc_secobj_get_t *secobj_getp; 2433147Sxc151355 dld_secobj_t *objp; 2447408SSebastien.Roy@Sun.COM size_t secobj_bufsz; 2453147Sxc151355 2463147Sxc151355 if ((flags & DLADM_OPT_PERSIST) != 0) 247*8453SAnurag.Maskey@Sun.COM return (i_dladm_walk_secobj_db(handle, arg, func)); 2483147Sxc151355 2497408SSebastien.Roy@Sun.COM /* Start with enough room for 10 objects, increase if necessary. */ 2507408SSebastien.Roy@Sun.COM secobj_bufsz = sizeof (*secobj_getp) + (10 * sizeof (*objp)); 2517408SSebastien.Roy@Sun.COM secobj_getp = calloc(1, secobj_bufsz); 2527408SSebastien.Roy@Sun.COM if (secobj_getp == NULL) { 2533147Sxc151355 status = dladm_errno2status(errno); 2543147Sxc151355 goto done; 2553147Sxc151355 } 2567408SSebastien.Roy@Sun.COM 2577408SSebastien.Roy@Sun.COM tryagain: 2587408SSebastien.Roy@Sun.COM secobj_getp->sg_size = secobj_bufsz; 259*8453SAnurag.Maskey@Sun.COM if (ioctl(dladm_dld_fd(handle), DLDIOC_SECOBJ_GET, secobj_getp) < 0) { 2607408SSebastien.Roy@Sun.COM if (errno == ENOSPC) { 2617408SSebastien.Roy@Sun.COM /* Increase the buffer size and try again. */ 2627408SSebastien.Roy@Sun.COM secobj_bufsz *= 2; 2637408SSebastien.Roy@Sun.COM if (secobj_bufsz > SECOBJ_MAXBUFSZ) { 2647408SSebastien.Roy@Sun.COM status = dladm_errno2status(errno); 2657408SSebastien.Roy@Sun.COM goto done; 2667408SSebastien.Roy@Sun.COM } 2677408SSebastien.Roy@Sun.COM secobj_getp = realloc(secobj_getp, secobj_bufsz); 2687408SSebastien.Roy@Sun.COM if (secobj_getp == NULL) { 2697408SSebastien.Roy@Sun.COM status = dladm_errno2status(errno); 2707408SSebastien.Roy@Sun.COM goto done; 2717408SSebastien.Roy@Sun.COM } 2727408SSebastien.Roy@Sun.COM bzero(secobj_getp, secobj_bufsz); 2737408SSebastien.Roy@Sun.COM goto tryagain; 2747408SSebastien.Roy@Sun.COM } 2753147Sxc151355 status = dladm_errno2status(errno); 2763147Sxc151355 goto done; 2773147Sxc151355 } 2783147Sxc151355 2793147Sxc151355 objp = (dld_secobj_t *)(secobj_getp + 1); 2803147Sxc151355 while (secobj_getp->sg_count > 0) { 281*8453SAnurag.Maskey@Sun.COM if (!func(handle, arg, objp->so_name)) 2823147Sxc151355 goto done; 2833147Sxc151355 secobj_getp->sg_count--; 2843147Sxc151355 objp++; 2853147Sxc151355 } 2863147Sxc151355 done: 2873147Sxc151355 free(secobj_getp); 2883147Sxc151355 return (status); 2893147Sxc151355 } 2903147Sxc151355 2913147Sxc151355 /* 2923147Sxc151355 * Data structures used for implementing persistent secure objects 2933147Sxc151355 */ 2943147Sxc151355 typedef struct secobj_info { 2953147Sxc151355 const char *si_name; 2963147Sxc151355 dladm_secobj_class_t *si_classp; 2973147Sxc151355 uint8_t *si_val; 2983147Sxc151355 uint_t *si_lenp; 2993147Sxc151355 } secobj_info_t; 3003147Sxc151355 3013147Sxc151355 typedef struct secobj_name { 3023147Sxc151355 char *sn_name; 3033147Sxc151355 struct secobj_name *sn_next; 3043147Sxc151355 } secobj_name_t; 3053147Sxc151355 3063147Sxc151355 typedef struct secobj_db_state secobj_db_state_t; 3073147Sxc151355 308*8453SAnurag.Maskey@Sun.COM typedef boolean_t (*secobj_db_op_t)(dladm_handle_t, struct secobj_db_state *, 309*8453SAnurag.Maskey@Sun.COM char *, secobj_info_t *, dladm_status_t *); 3103147Sxc151355 3113147Sxc151355 struct secobj_db_state { 3123147Sxc151355 secobj_db_op_t ss_op; 3133147Sxc151355 secobj_info_t ss_info; 3143147Sxc151355 secobj_name_t **ss_namelist; 3153147Sxc151355 }; 3163147Sxc151355 3173147Sxc151355 /* 3183147Sxc151355 * Update or generate a secobj entry using the info in ssp->ss_info. 3193147Sxc151355 */ 3203147Sxc151355 /* ARGSUSED */ 3213147Sxc151355 static boolean_t 322*8453SAnurag.Maskey@Sun.COM process_secobj_set(dladm_handle_t handle, secobj_db_state_t *ssp, char *buf, 323*8453SAnurag.Maskey@Sun.COM secobj_info_t *sip, dladm_status_t *statusp) 3243147Sxc151355 { 3253147Sxc151355 char tmpbuf[MAXLINELEN]; 3263147Sxc151355 char classbuf[DLADM_STRSIZE]; 3273147Sxc151355 char *ptr = tmpbuf, *lim = tmpbuf + MAXLINELEN; 3283147Sxc151355 int i; 3293147Sxc151355 3303147Sxc151355 sip = &ssp->ss_info; 3313147Sxc151355 3323147Sxc151355 ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", sip->si_name); 3333147Sxc151355 ptr += snprintf(ptr, BUFLEN(lim, ptr), "%s\t", 3343147Sxc151355 dladm_secobjclass2str(*sip->si_classp, classbuf)); 3353147Sxc151355 3363147Sxc151355 ptr += snprintf(ptr, BUFLEN(lim, ptr), "0x"); 3373147Sxc151355 for (i = 0; i < *sip->si_lenp; i++) { 3383147Sxc151355 ptr += snprintf(ptr, BUFLEN(lim, ptr), "%02x", 3393147Sxc151355 sip->si_val[i] & 0xff); 3403147Sxc151355 } 3413147Sxc151355 if (ptr > lim) { 3423147Sxc151355 *statusp = DLADM_STATUS_TOOSMALL; 3433147Sxc151355 return (B_FALSE); 3443147Sxc151355 } 3453147Sxc151355 (void) snprintf(buf, MAXLINELEN, "%s\n", tmpbuf); 3463147Sxc151355 return (B_FALSE); 3473147Sxc151355 } 3483147Sxc151355 3493147Sxc151355 /* ARGSUSED */ 3503147Sxc151355 static boolean_t 351*8453SAnurag.Maskey@Sun.COM process_secobj_get(dladm_handle_t handle, secobj_db_state_t *ssp, char *buf, 352*8453SAnurag.Maskey@Sun.COM secobj_info_t *sip, dladm_status_t *statusp) 3533147Sxc151355 { 3543147Sxc151355 if (*sip->si_lenp > *ssp->ss_info.si_lenp) { 3553147Sxc151355 *statusp = DLADM_STATUS_TOOSMALL; 3563147Sxc151355 return (B_FALSE); 3573147Sxc151355 } 3583147Sxc151355 bcopy(sip->si_val, ssp->ss_info.si_val, *sip->si_lenp); 3593147Sxc151355 *ssp->ss_info.si_lenp = *sip->si_lenp; 3603147Sxc151355 *ssp->ss_info.si_classp = *sip->si_classp; 3613147Sxc151355 return (B_FALSE); 3623147Sxc151355 } 3633147Sxc151355 3643147Sxc151355 /* ARGSUSED */ 3653147Sxc151355 static boolean_t 366*8453SAnurag.Maskey@Sun.COM process_secobj_unset(dladm_handle_t handle, secobj_db_state_t *ssp, char *buf, 367*8453SAnurag.Maskey@Sun.COM secobj_info_t *sip, dladm_status_t *statusp) 3683147Sxc151355 { 3693147Sxc151355 /* 3703147Sxc151355 * Delete line. 3713147Sxc151355 */ 3723147Sxc151355 buf[0] = '\0'; 3733147Sxc151355 return (B_FALSE); 3743147Sxc151355 } 3753147Sxc151355 3763147Sxc151355 /* ARGSUSED */ 3773147Sxc151355 static boolean_t 378*8453SAnurag.Maskey@Sun.COM process_secobj_walk(dladm_handle_t handle, secobj_db_state_t *ssp, char *buf, 379*8453SAnurag.Maskey@Sun.COM secobj_info_t *sip, dladm_status_t *statusp) 3803147Sxc151355 { 3813147Sxc151355 secobj_name_t *snp; 3823147Sxc151355 3833147Sxc151355 if ((snp = malloc(sizeof (*snp))) == NULL) 3843147Sxc151355 return (B_TRUE); 3853147Sxc151355 3863147Sxc151355 if ((snp->sn_name = strdup(sip->si_name)) == NULL) { 3873147Sxc151355 free(snp); 3883147Sxc151355 return (B_TRUE); 3893147Sxc151355 } 3903147Sxc151355 3913147Sxc151355 snp->sn_next = NULL; 3923147Sxc151355 *ssp->ss_namelist = snp; 3933147Sxc151355 ssp->ss_namelist = &snp->sn_next; 3943147Sxc151355 return (B_TRUE); 3953147Sxc151355 } 3963147Sxc151355 3973147Sxc151355 /* ARGSUSED */ 3983147Sxc151355 static boolean_t 399*8453SAnurag.Maskey@Sun.COM process_secobj_init(dladm_handle_t handle, secobj_db_state_t *ssp, char *buf, 400*8453SAnurag.Maskey@Sun.COM secobj_info_t *sip, dladm_status_t *statusp) 4013147Sxc151355 { 402*8453SAnurag.Maskey@Sun.COM *statusp = dladm_set_secobj(handle, sip->si_name, *sip->si_classp, 403*8453SAnurag.Maskey@Sun.COM sip->si_val, *sip->si_lenp, 404*8453SAnurag.Maskey@Sun.COM DLADM_OPT_ACTIVE | DLADM_OPT_CREATE); 4053147Sxc151355 return (B_TRUE); 4063147Sxc151355 } 4073147Sxc151355 4083147Sxc151355 static int 4093147Sxc151355 parse_secobj_val(char *buf, secobj_info_t *sip) 4103147Sxc151355 { 4113147Sxc151355 if (strncmp(buf, "0x", 2) != 0) 4123147Sxc151355 return (EINVAL); 4133147Sxc151355 4143147Sxc151355 return (hexascii_to_octet(buf + 2, strlen(buf) - 2, 4153147Sxc151355 sip->si_val, sip->si_lenp)); 4163147Sxc151355 } 4173147Sxc151355 4183147Sxc151355 static boolean_t 419*8453SAnurag.Maskey@Sun.COM process_secobj_line(dladm_handle_t handle, secobj_db_state_t *ssp, char *buf, 4203147Sxc151355 dladm_status_t *statusp) 4213147Sxc151355 { 4223147Sxc151355 secobj_info_t sinfo; 4233147Sxc151355 dladm_secobj_class_t class; 4243147Sxc151355 uint8_t val[DLADM_SECOBJ_VAL_MAX]; 4253147Sxc151355 uint_t vlen; 4263147Sxc151355 int i, len, nlen; 4273147Sxc151355 char *str, *lasts; 4283147Sxc151355 4293147Sxc151355 /* 4303147Sxc151355 * Skip leading spaces, blank lines, and comments. 4313147Sxc151355 */ 4323147Sxc151355 len = strlen(buf); 4333147Sxc151355 for (i = 0; i < len; i++) { 4343147Sxc151355 if (!isspace(buf[i])) 4353147Sxc151355 break; 4363147Sxc151355 } 4373147Sxc151355 if (i == len || buf[i] == '#') 4383147Sxc151355 return (B_TRUE); 4393147Sxc151355 4403147Sxc151355 str = buf + i; 4413147Sxc151355 if (ssp->ss_info.si_name != NULL) { 4423147Sxc151355 /* 4433147Sxc151355 * Skip objects we're not interested in. 4443147Sxc151355 */ 4453147Sxc151355 nlen = strlen(ssp->ss_info.si_name); 4463147Sxc151355 if (strncmp(str, ssp->ss_info.si_name, nlen) != 0 || 4473147Sxc151355 !isspace(str[nlen])) 4483147Sxc151355 return (B_TRUE); 4493147Sxc151355 4503147Sxc151355 sinfo.si_name = ssp->ss_info.si_name; 4513147Sxc151355 } else { 4523147Sxc151355 /* 4533147Sxc151355 * If an object is not specified, find the object name 4543147Sxc151355 * and assign it to sinfo.si_name. 4553147Sxc151355 */ 4563147Sxc151355 if (strtok_r(str, " \n\t", &lasts) == NULL) 4573147Sxc151355 goto fail; 4583147Sxc151355 4593147Sxc151355 nlen = strlen(str); 4603147Sxc151355 sinfo.si_name = str; 4613147Sxc151355 } 4623147Sxc151355 str += nlen + 1; 4633147Sxc151355 if (str >= buf + len) 4643147Sxc151355 goto fail; 4653147Sxc151355 4663147Sxc151355 /* 4673147Sxc151355 * Find the class name. 4683147Sxc151355 */ 4693147Sxc151355 if ((str = strtok_r(str, " \n\t", &lasts)) == NULL) 4703147Sxc151355 goto fail; 4713147Sxc151355 4723147Sxc151355 *statusp = dladm_str2secobjclass(str, &class); 4733147Sxc151355 if (*statusp != DLADM_STATUS_OK) 4743147Sxc151355 goto fail; 4753147Sxc151355 4763147Sxc151355 /* 4773147Sxc151355 * Find the object value. 4783147Sxc151355 */ 4793147Sxc151355 if ((str = strtok_r(NULL, " \n\t", &lasts)) == NULL) 4803147Sxc151355 goto fail; 4813147Sxc151355 4823147Sxc151355 vlen = DLADM_SECOBJ_VAL_MAX; 4833147Sxc151355 sinfo.si_classp = &class; 4843147Sxc151355 sinfo.si_val = val; 4853147Sxc151355 sinfo.si_lenp = &vlen; 4863147Sxc151355 if (parse_secobj_val(str, &sinfo) != 0) 4873147Sxc151355 goto fail; 4883147Sxc151355 489*8453SAnurag.Maskey@Sun.COM return ((*ssp->ss_op)(handle, ssp, buf, &sinfo, statusp)); 4903147Sxc151355 4913147Sxc151355 fail: 4923147Sxc151355 /* 4933147Sxc151355 * Delete corrupted line. 4943147Sxc151355 */ 4953147Sxc151355 buf[0] = '\0'; 4963147Sxc151355 return (B_TRUE); 4973147Sxc151355 } 4983147Sxc151355 4993147Sxc151355 static dladm_status_t 500*8453SAnurag.Maskey@Sun.COM process_secobj_db(dladm_handle_t handle, void *arg, FILE *fp, FILE *nfp) 5013147Sxc151355 { 5023147Sxc151355 secobj_db_state_t *ssp = arg; 5033147Sxc151355 dladm_status_t status = DLADM_STATUS_OK; 5043147Sxc151355 char buf[MAXLINELEN]; 5053147Sxc151355 boolean_t cont = B_TRUE; 5063147Sxc151355 5073147Sxc151355 /* 5083147Sxc151355 * This loop processes each line of the configuration file. 5093147Sxc151355 * buf can potentially be modified by process_secobj_line(). 5103147Sxc151355 * If this is a write operation and buf is not truncated, buf will 5113147Sxc151355 * be written to disk. process_secobj_line() will no longer be 5123147Sxc151355 * called after it returns B_FALSE; at which point the remainder 5133147Sxc151355 * of the file will continue to be read and, if necessary, written 5143147Sxc151355 * to disk as well. 5153147Sxc151355 */ 5163147Sxc151355 while (fgets(buf, MAXLINELEN, fp) != NULL) { 5173147Sxc151355 if (cont) 518*8453SAnurag.Maskey@Sun.COM cont = process_secobj_line(handle, ssp, buf, &status); 5193147Sxc151355 5203147Sxc151355 if (nfp != NULL && buf[0] != '\0' && fputs(buf, nfp) == EOF) { 5213147Sxc151355 status = dladm_errno2status(errno); 5223147Sxc151355 break; 5233147Sxc151355 } 5243147Sxc151355 } 5253147Sxc151355 if (status != DLADM_STATUS_OK || !cont) 5263147Sxc151355 return (status); 5273147Sxc151355 5283147Sxc151355 if (ssp->ss_op == process_secobj_set) { 5293147Sxc151355 /* 5303147Sxc151355 * If the specified object is not found above, we add the 5313147Sxc151355 * object to the configuration file. 5323147Sxc151355 */ 533*8453SAnurag.Maskey@Sun.COM (void) (*ssp->ss_op)(handle, ssp, buf, NULL, &status); 5343147Sxc151355 if (status == DLADM_STATUS_OK && fputs(buf, nfp) == EOF) 5353147Sxc151355 status = dladm_errno2status(errno); 5363147Sxc151355 } 5373147Sxc151355 5383147Sxc151355 if (ssp->ss_op == process_secobj_unset || 5393147Sxc151355 ssp->ss_op == process_secobj_get) 5403147Sxc151355 status = DLADM_STATUS_NOTFOUND; 5413147Sxc151355 5423147Sxc151355 return (status); 5433147Sxc151355 } 5443147Sxc151355 545*8453SAnurag.Maskey@Sun.COM #define SECOBJ_RW_DB(handle, statep, writeop) \ 546*8453SAnurag.Maskey@Sun.COM (i_dladm_rw_db(handle, "/etc/dladm/secobj.conf", S_IRUSR | S_IWUSR, \ 5473147Sxc151355 process_secobj_db, (statep), (writeop))) 5483147Sxc151355 5493147Sxc151355 static dladm_status_t 550*8453SAnurag.Maskey@Sun.COM i_dladm_set_secobj_db(dladm_handle_t handle, const char *obj_name, 551*8453SAnurag.Maskey@Sun.COM dladm_secobj_class_t class, uint8_t *obj_val, uint_t obj_len) 5523147Sxc151355 { 5533147Sxc151355 secobj_db_state_t state; 5543147Sxc151355 5553147Sxc151355 state.ss_op = process_secobj_set; 5563147Sxc151355 state.ss_info.si_name = obj_name; 5573147Sxc151355 state.ss_info.si_classp = &class; 5583147Sxc151355 state.ss_info.si_val = obj_val; 5593147Sxc151355 state.ss_info.si_lenp = &obj_len; 5603147Sxc151355 state.ss_namelist = NULL; 5613147Sxc151355 562*8453SAnurag.Maskey@Sun.COM return (SECOBJ_RW_DB(handle, &state, B_TRUE)); 5633147Sxc151355 } 5643147Sxc151355 5653147Sxc151355 static dladm_status_t 566*8453SAnurag.Maskey@Sun.COM i_dladm_get_secobj_db(dladm_handle_t handle, const char *obj_name, 567*8453SAnurag.Maskey@Sun.COM dladm_secobj_class_t *classp, uint8_t *obj_val, uint_t *obj_lenp) 5683147Sxc151355 { 5693147Sxc151355 secobj_db_state_t state; 5703147Sxc151355 5713147Sxc151355 state.ss_op = process_secobj_get; 5723147Sxc151355 state.ss_info.si_name = obj_name; 5733147Sxc151355 state.ss_info.si_classp = classp; 5743147Sxc151355 state.ss_info.si_val = obj_val; 5753147Sxc151355 state.ss_info.si_lenp = obj_lenp; 5763147Sxc151355 state.ss_namelist = NULL; 5773147Sxc151355 578*8453SAnurag.Maskey@Sun.COM return (SECOBJ_RW_DB(handle, &state, B_FALSE)); 5793147Sxc151355 } 5803147Sxc151355 5813147Sxc151355 static dladm_status_t 582*8453SAnurag.Maskey@Sun.COM i_dladm_unset_secobj_db(dladm_handle_t handle, const char *obj_name) 5833147Sxc151355 { 5843147Sxc151355 secobj_db_state_t state; 5853147Sxc151355 5863147Sxc151355 state.ss_op = process_secobj_unset; 5873147Sxc151355 state.ss_info.si_name = obj_name; 5883147Sxc151355 state.ss_info.si_classp = NULL; 5893147Sxc151355 state.ss_info.si_val = NULL; 5903147Sxc151355 state.ss_info.si_lenp = NULL; 5913147Sxc151355 state.ss_namelist = NULL; 5923147Sxc151355 593*8453SAnurag.Maskey@Sun.COM return (SECOBJ_RW_DB(handle, &state, B_TRUE)); 5943147Sxc151355 } 5953147Sxc151355 5963147Sxc151355 static dladm_status_t 597*8453SAnurag.Maskey@Sun.COM i_dladm_walk_secobj_db(dladm_handle_t handle, void *arg, 598*8453SAnurag.Maskey@Sun.COM boolean_t (*func)(dladm_handle_t, void *, const char *)) 5993147Sxc151355 { 6003147Sxc151355 secobj_db_state_t state; 6013147Sxc151355 secobj_name_t *snp = NULL, *fsnp; 6023147Sxc151355 dladm_status_t status; 6033147Sxc151355 boolean_t cont = B_TRUE; 6043147Sxc151355 6053147Sxc151355 state.ss_op = process_secobj_walk; 6063147Sxc151355 state.ss_info.si_name = NULL; 6073147Sxc151355 state.ss_info.si_classp = NULL; 6083147Sxc151355 state.ss_info.si_val = NULL; 6093147Sxc151355 state.ss_info.si_lenp = NULL; 6103147Sxc151355 state.ss_namelist = &snp; 6113147Sxc151355 612*8453SAnurag.Maskey@Sun.COM status = SECOBJ_RW_DB(handle, &state, B_FALSE); 6133147Sxc151355 if (status != DLADM_STATUS_OK) 6143147Sxc151355 return (status); 6153147Sxc151355 6163147Sxc151355 while (snp != NULL) { 6173147Sxc151355 fsnp = snp; 6183147Sxc151355 snp = snp->sn_next; 6193147Sxc151355 if (cont) 620*8453SAnurag.Maskey@Sun.COM cont = func(handle, arg, fsnp->sn_name); 6213147Sxc151355 free(fsnp->sn_name); 6223147Sxc151355 free(fsnp); 6233147Sxc151355 } 6243147Sxc151355 return (status); 6253147Sxc151355 } 6263147Sxc151355 6273147Sxc151355 dladm_status_t 628*8453SAnurag.Maskey@Sun.COM dladm_init_secobj(dladm_handle_t handle) 6293147Sxc151355 { 6303147Sxc151355 secobj_db_state_t state; 6313147Sxc151355 6323147Sxc151355 state.ss_op = process_secobj_init; 6333147Sxc151355 state.ss_info.si_name = NULL; 6343147Sxc151355 state.ss_info.si_classp = NULL; 6353147Sxc151355 state.ss_info.si_val = NULL; 6363147Sxc151355 state.ss_info.si_lenp = NULL; 6373147Sxc151355 state.ss_namelist = NULL; 6383147Sxc151355 639*8453SAnurag.Maskey@Sun.COM return (SECOBJ_RW_DB(handle, &state, B_FALSE)); 6403147Sxc151355 } 6418431SAnurag.Maskey@Sun.COM 6428431SAnurag.Maskey@Sun.COM boolean_t 6438431SAnurag.Maskey@Sun.COM dladm_valid_secobj_name(const char *secobj_name) 6448431SAnurag.Maskey@Sun.COM { 6458431SAnurag.Maskey@Sun.COM size_t len = strlen(secobj_name); 6468431SAnurag.Maskey@Sun.COM const char *cp; 6478431SAnurag.Maskey@Sun.COM 6488431SAnurag.Maskey@Sun.COM if (len + 1 > DLADM_SECOBJ_NAME_MAX) 6498431SAnurag.Maskey@Sun.COM return (B_FALSE); 6508431SAnurag.Maskey@Sun.COM 6518431SAnurag.Maskey@Sun.COM /* 6528431SAnurag.Maskey@Sun.COM * The legal characters in a secobj name are: 6538431SAnurag.Maskey@Sun.COM * alphanumeric (a-z, A-Z, 0-9), '.', '_', '-'. 6548431SAnurag.Maskey@Sun.COM */ 6558431SAnurag.Maskey@Sun.COM for (cp = secobj_name; *cp != '\0'; cp++) { 6568431SAnurag.Maskey@Sun.COM if (!isalnum(*cp) && 6578431SAnurag.Maskey@Sun.COM (*cp != '.') && (*cp != '_') && (*cp != '-')) 6588431SAnurag.Maskey@Sun.COM return (B_FALSE); 6598431SAnurag.Maskey@Sun.COM } 6608431SAnurag.Maskey@Sun.COM 6618431SAnurag.Maskey@Sun.COM return (B_TRUE); 6628431SAnurag.Maskey@Sun.COM } 663