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