1da6c28aaSamw /* 2da6c28aaSamw * CDDL HEADER START 3da6c28aaSamw * 4da6c28aaSamw * The contents of this file are subject to the terms of the 5da6c28aaSamw * Common Development and Distribution License (the "License"). 6da6c28aaSamw * You may not use this file except in compliance with the License. 7da6c28aaSamw * 8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9da6c28aaSamw * or http://www.opensolaris.org/os/licensing. 10da6c28aaSamw * See the License for the specific language governing permissions 11da6c28aaSamw * and limitations under the License. 12da6c28aaSamw * 13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each 14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the 16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying 17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner] 18da6c28aaSamw * 19da6c28aaSamw * CDDL HEADER END 20da6c28aaSamw */ 21da6c28aaSamw /* 22*bbf6f00cSJordan Brown * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23da6c28aaSamw * Use is subject to license terms. 24da6c28aaSamw */ 25da6c28aaSamw 26da6c28aaSamw /* 27da6c28aaSamw * This module provides the interface to the built-in privilege names 28da6c28aaSamw * and id's. NT privileges are known on the network using strings. Each 29da6c28aaSamw * system assigns locally unique identifiers (LUID) for use within the 30da6c28aaSamw * system. Each built-in privilege also has a display-name, which is a 31da6c28aaSamw * short description of the privilege. The functions here provide an 32da6c28aaSamw * interface to map between LUIDs, names and display names. 33da6c28aaSamw */ 34da6c28aaSamw 35da6c28aaSamw #include <string.h> 36da6c28aaSamw #include <syslog.h> 37da6c28aaSamw 38da6c28aaSamw #include <smbsrv/string.h> 39da6c28aaSamw #include <smbsrv/libsmb.h> 40da6c28aaSamw #include <smbsrv/smb_privilege.h> 41da6c28aaSamw 42da6c28aaSamw static char *smb_priv_getname(uint32_t id); 43da6c28aaSamw 44da6c28aaSamw /* 45da6c28aaSamw * Table of built-in privilege id's, names and display strings. This 46da6c28aaSamw * table matches the response from an NT4.0 PDC LSARPC service. 47da6c28aaSamw * Requests for values 0 and 1 return STATUS_NO_SUCH_PRIVILEGE. 48da6c28aaSamw * 49da6c28aaSamw * SE_UNSOLICITED_INPUT_NAME/SeUnsolicitedInputPrivilege is defined in 50da6c28aaSamw * winnt.h but doesn't appear in the list reported by the NT4.0 LSA. 51da6c28aaSamw */ 52da6c28aaSamw static smb_privinfo_t priv_table[] = { 53da6c28aaSamw { 0, "", "", 0 }, 54da6c28aaSamw { 1, "", "", 0 }, 55da6c28aaSamw { 2, SE_CREATE_TOKEN_NAME, "Create a token object", 0 }, 56da6c28aaSamw { 3, SE_ASSIGNPRIMARYTOKEN_NAME, "Replace a process level token", 0 }, 57da6c28aaSamw { 4, SE_LOCK_MEMORY_NAME, "Lock pages in memory", 0 }, 58da6c28aaSamw { 5, SE_INCREASE_QUOTA_NAME, "Increase quotas", 0 }, 59da6c28aaSamw { 6, SE_MACHINE_ACCOUNT_NAME, "Add workstations to domain", 0 }, 60da6c28aaSamw { 7, SE_TCB_NAME, "Act as part of the operating system", 0 }, 61da6c28aaSamw { 8, SE_SECURITY_NAME, "Manage auditing and security log", 0 }, 62da6c28aaSamw { 9, SE_TAKE_OWNERSHIP_NAME, 63da6c28aaSamw "Take ownership of files or other objects", PF_PRESENTABLE }, 64da6c28aaSamw { 10, SE_LOAD_DRIVER_NAME, "Load and unload device drivers", 0 }, 65da6c28aaSamw { 11, SE_SYSTEM_PROFILE_NAME, "Profile system performance", 0 }, 66da6c28aaSamw { 12, SE_SYSTEMTIME_NAME, "Change the system time", 0 }, 67da6c28aaSamw { 13, SE_PROF_SINGLE_PROCESS_NAME, "Profile single process", 0 }, 68da6c28aaSamw { 14, SE_INC_BASE_PRIORITY_NAME, "Increase scheduling priority", 0 }, 69da6c28aaSamw { 15, SE_CREATE_PAGEFILE_NAME, "Create a pagefile", 0 }, 70da6c28aaSamw { 16, SE_CREATE_PERMANENT_NAME, "Create permanent shared objects", 0 }, 71da6c28aaSamw { 17, SE_BACKUP_NAME, "Back up files and directories", 72da6c28aaSamw PF_PRESENTABLE }, 73da6c28aaSamw { 18, SE_RESTORE_NAME, "Restore files and directories", 74da6c28aaSamw PF_PRESENTABLE }, 75da6c28aaSamw { 19, SE_SHUTDOWN_NAME, "Shut down the system", 0 }, 76da6c28aaSamw { 20, SE_DEBUG_NAME, "Debug programs", 0 }, 77da6c28aaSamw { 21, SE_AUDIT_NAME, "Generate security audits", 0 }, 78da6c28aaSamw { 22, SE_SYSTEM_ENVIRONMENT_NAME, 79da6c28aaSamw "Modify firmware environment values", 0 }, 80da6c28aaSamw { 23, SE_CHANGE_NOTIFY_NAME, "Bypass traverse checking", 0 }, 81da6c28aaSamw { 24, SE_REMOTE_SHUTDOWN_NAME, 82da6c28aaSamw "Force shutdown from a remote system", 0 } 83da6c28aaSamw }; 84da6c28aaSamw 85da6c28aaSamw /* 86da6c28aaSamw * smb_priv_presentable_num 87da6c28aaSamw * 88da6c28aaSamw * Returns number of presentable privileges 89da6c28aaSamw */ 90da6c28aaSamw int 91da6c28aaSamw smb_priv_presentable_num() 92da6c28aaSamw { 93da6c28aaSamw int i, num; 94da6c28aaSamw 95da6c28aaSamw num = 0; 96dc20a302Sas200622 for (i = SE_MIN_LUID; i <= SE_MAX_LUID; i++) 97da6c28aaSamw if (priv_table[i].flags == PF_PRESENTABLE) 98da6c28aaSamw num++; 99da6c28aaSamw 100da6c28aaSamw return (num); 101da6c28aaSamw } 102da6c28aaSamw 103da6c28aaSamw /* 104da6c28aaSamw * smb_priv_presentable_ids 105da6c28aaSamw * 106da6c28aaSamw * Returns IDs of presentable privileges 107da6c28aaSamw * Returns 0 in case of invalid parameter and 1 on success. 108da6c28aaSamw */ 109da6c28aaSamw int 110da6c28aaSamw smb_priv_presentable_ids(uint32_t *ids, int num) 111da6c28aaSamw { 112da6c28aaSamw int i, j; 113da6c28aaSamw 114da6c28aaSamw if (ids == NULL || num <= 0) 115da6c28aaSamw return (0); 116da6c28aaSamw 117dc20a302Sas200622 for (i = SE_MIN_LUID, j = 0; i <= SE_MAX_LUID; i++) 118da6c28aaSamw if (priv_table[i].flags == PF_PRESENTABLE) 119da6c28aaSamw ids[j++] = priv_table[i].id; 120da6c28aaSamw 121da6c28aaSamw return (1); 122da6c28aaSamw } 123da6c28aaSamw 124da6c28aaSamw /* 125da6c28aaSamw * smb_priv_getbyvalue 126da6c28aaSamw * 127da6c28aaSamw * Return the privilege info for the specified id (low part of the LUID). 128da6c28aaSamw * Returns a null pointer if id is out-of-range. 129da6c28aaSamw */ 130da6c28aaSamw smb_privinfo_t * 131da6c28aaSamw smb_priv_getbyvalue(uint32_t id) 132da6c28aaSamw { 133dc20a302Sas200622 if (id < SE_MIN_LUID || id > SE_MAX_LUID) 134da6c28aaSamw return (0); 135da6c28aaSamw 136da6c28aaSamw return (&priv_table[id]); 137da6c28aaSamw } 138da6c28aaSamw 139da6c28aaSamw 140da6c28aaSamw /* 141da6c28aaSamw * smb_priv_getbyname 142da6c28aaSamw * 143da6c28aaSamw * Return the privilege info for the specified name. Returns a null 144da6c28aaSamw * pointer if we can't find a matching name in the table. 145da6c28aaSamw */ 146da6c28aaSamw smb_privinfo_t * 147da6c28aaSamw smb_priv_getbyname(char *name) 148da6c28aaSamw { 149da6c28aaSamw smb_privinfo_t *entry; 150da6c28aaSamw int i; 151da6c28aaSamw 152da6c28aaSamw if (name == 0) 153da6c28aaSamw return (0); 154da6c28aaSamw 155dc20a302Sas200622 for (i = SE_MIN_LUID; i <= SE_MAX_LUID; ++i) { 156da6c28aaSamw entry = &priv_table[i]; 157da6c28aaSamw 158*bbf6f00cSJordan Brown if (smb_strcasecmp(name, entry->name, 0) == 0) 159da6c28aaSamw return (entry); 160da6c28aaSamw } 161da6c28aaSamw 162da6c28aaSamw return (0); 163da6c28aaSamw } 164da6c28aaSamw 165da6c28aaSamw /* 166da6c28aaSamw * smb_privset_size 167da6c28aaSamw * 168da6c28aaSamw * Returns the memory block size needed to keep a complete 169da6c28aaSamw * set of privileges in a smb_privset_t structure. 170da6c28aaSamw */ 171da6c28aaSamw int 172da6c28aaSamw smb_privset_size() 173da6c28aaSamw { 174dc20a302Sas200622 int pcnt = SE_MAX_LUID - SE_MIN_LUID + 1; 175da6c28aaSamw 176da6c28aaSamw return (2 * sizeof (uint32_t) + 177da6c28aaSamw pcnt * sizeof (smb_luid_attrs_t)); 178da6c28aaSamw } 179da6c28aaSamw 180da6c28aaSamw /* 181da6c28aaSamw * smb_privset_validate 182da6c28aaSamw * 183da6c28aaSamw * Validates the given privilege set structure 184da6c28aaSamw * Returns 1 if the structure is Ok, otherwise returns 0. 185da6c28aaSamw */ 186da6c28aaSamw int 187da6c28aaSamw smb_privset_validate(smb_privset_t *privset) 188da6c28aaSamw { 189da6c28aaSamw int count; 190da6c28aaSamw uint32_t i; 191da6c28aaSamw 192da6c28aaSamw if (privset == 0) { 193da6c28aaSamw return (0); 194da6c28aaSamw } 195da6c28aaSamw 196dc20a302Sas200622 count = SE_MAX_LUID - SE_MIN_LUID + 1; 197da6c28aaSamw 198da6c28aaSamw if (privset->priv_cnt != count) { 199da6c28aaSamw return (0); 200da6c28aaSamw } 201da6c28aaSamw 202da6c28aaSamw for (i = 0; i < count; i++) { 203da6c28aaSamw if (privset->priv[i].luid.hi_part != 0) { 204da6c28aaSamw return (0); 205da6c28aaSamw } 206da6c28aaSamw 207da6c28aaSamw if (privset->priv[i].luid.lo_part != 208dc20a302Sas200622 i + SE_MIN_LUID) { 209da6c28aaSamw return (0); 210da6c28aaSamw } 211da6c28aaSamw } 212da6c28aaSamw 213da6c28aaSamw return (1); 214da6c28aaSamw } 215da6c28aaSamw 216da6c28aaSamw /* 217da6c28aaSamw * smb_privset_init 218da6c28aaSamw * 219da6c28aaSamw * initialize all privileges in disable state. 220da6c28aaSamw */ 221da6c28aaSamw void 222da6c28aaSamw smb_privset_init(smb_privset_t *privset) 223da6c28aaSamw { 224da6c28aaSamw int count; 225da6c28aaSamw uint32_t i; 226da6c28aaSamw 227da6c28aaSamw if (privset == 0) 228da6c28aaSamw return; 229da6c28aaSamw 230dc20a302Sas200622 count = SE_MAX_LUID - SE_MIN_LUID + 1; 231da6c28aaSamw 232da6c28aaSamw privset->priv_cnt = count; 233da6c28aaSamw privset->control = 0; 234da6c28aaSamw for (i = 0; i < count; i++) { 235da6c28aaSamw privset->priv[i].luid.hi_part = 0; 236dc20a302Sas200622 privset->priv[i].luid.lo_part = i + SE_MIN_LUID; 237da6c28aaSamw privset->priv[i].attrs = 0; 238da6c28aaSamw } 239da6c28aaSamw } 240da6c28aaSamw 241da6c28aaSamw /* 242da6c28aaSamw * smb_privset_new 243da6c28aaSamw * 244da6c28aaSamw * Allocate memory and initialize all privileges in disable state. 245da6c28aaSamw * Returns pointer to allocated space or NULL if there is not 246da6c28aaSamw * enough memory. 247da6c28aaSamw */ 248da6c28aaSamw smb_privset_t * 249da6c28aaSamw smb_privset_new() 250da6c28aaSamw { 251da6c28aaSamw smb_privset_t *privset; 252da6c28aaSamw 253da6c28aaSamw privset = malloc(smb_privset_size()); 254da6c28aaSamw if (privset == NULL) 255da6c28aaSamw return (NULL); 256da6c28aaSamw 257da6c28aaSamw smb_privset_init(privset); 258da6c28aaSamw 259da6c28aaSamw return (privset); 260da6c28aaSamw } 261da6c28aaSamw 262da6c28aaSamw /* 263da6c28aaSamw * smb_privset_copy 264da6c28aaSamw * 265da6c28aaSamw * Copy privleges information specified by 'src' to the 266da6c28aaSamw * buffer specified by dst. 267da6c28aaSamw */ 268da6c28aaSamw void 269da6c28aaSamw smb_privset_copy(smb_privset_t *dst, smb_privset_t *src) 270da6c28aaSamw { 271da6c28aaSamw if (src == 0 || dst == 0) 272da6c28aaSamw return; 273da6c28aaSamw 274da6c28aaSamw (void) memcpy(dst, src, smb_privset_size()); 275da6c28aaSamw } 276da6c28aaSamw 277da6c28aaSamw /* 278dc20a302Sas200622 * smb_privset_merge 279dc20a302Sas200622 * 280dc20a302Sas200622 * Enable the privileges that are enabled in src in dst 281dc20a302Sas200622 */ 282dc20a302Sas200622 void 283dc20a302Sas200622 smb_privset_merge(smb_privset_t *dst, smb_privset_t *src) 284dc20a302Sas200622 { 285dc20a302Sas200622 int i; 286dc20a302Sas200622 287dc20a302Sas200622 if (src == NULL || dst == NULL) 288dc20a302Sas200622 return; 289dc20a302Sas200622 290dc20a302Sas200622 for (i = 0; i < src->priv_cnt; i++) { 291dc20a302Sas200622 if (src->priv[i].attrs == SE_PRIVILEGE_ENABLED) 292dc20a302Sas200622 smb_privset_enable(dst, src->priv[i].luid.lo_part); 293dc20a302Sas200622 } 294dc20a302Sas200622 } 295dc20a302Sas200622 296dc20a302Sas200622 /* 297da6c28aaSamw * smb_privset_free 298da6c28aaSamw * 299da6c28aaSamw * This will free the memory allocated by the 'privset'. 300da6c28aaSamw */ 301da6c28aaSamw void 302da6c28aaSamw smb_privset_free(smb_privset_t *privset) 303da6c28aaSamw { 304da6c28aaSamw free(privset); 305da6c28aaSamw } 306da6c28aaSamw 307da6c28aaSamw void 308da6c28aaSamw smb_privset_enable(smb_privset_t *privset, uint32_t id) 309da6c28aaSamw { 310da6c28aaSamw int i; 311da6c28aaSamw 312da6c28aaSamw if (privset == NULL) 313da6c28aaSamw return; 314da6c28aaSamw 315da6c28aaSamw for (i = 0; i < privset->priv_cnt; i++) { 316da6c28aaSamw if (privset->priv[i].luid.lo_part == id) 317da6c28aaSamw privset->priv[i].attrs = SE_PRIVILEGE_ENABLED; 318da6c28aaSamw } 319da6c28aaSamw } 320da6c28aaSamw 321da6c28aaSamw void 322da6c28aaSamw smb_privset_log(smb_privset_t *privset) 323da6c28aaSamw { 324da6c28aaSamw smb_luid_t *luid; 325da6c28aaSamw int i, ecnt; 326da6c28aaSamw 327da6c28aaSamw if (privset == NULL) 328da6c28aaSamw return; 329da6c28aaSamw 330da6c28aaSamw for (i = 0, ecnt = 0; i < privset->priv_cnt; ++i) { 331da6c28aaSamw if (privset->priv[i].attrs != 0) { 332da6c28aaSamw ecnt++; 333da6c28aaSamw } 334da6c28aaSamw } 335da6c28aaSamw 336da6c28aaSamw syslog(LOG_DEBUG, " Privilege Count: %d (Enable=%d)", 337da6c28aaSamw privset->priv_cnt, ecnt); 338da6c28aaSamw 339da6c28aaSamw for (i = 0; i < privset->priv_cnt; ++i) { 340da6c28aaSamw if (privset->priv[i].attrs != 0) { 341da6c28aaSamw luid = &privset->priv[i].luid; 342da6c28aaSamw syslog(LOG_DEBUG, " %s", 343da6c28aaSamw smb_priv_getname(luid->lo_part)); 344da6c28aaSamw } 345da6c28aaSamw } 346da6c28aaSamw } 347da6c28aaSamw 348da6c28aaSamw int 349da6c28aaSamw smb_privset_query(smb_privset_t *privset, uint32_t id) 350da6c28aaSamw { 351da6c28aaSamw int i; 352da6c28aaSamw 353da6c28aaSamw if (privset == NULL) 354da6c28aaSamw return (0); 355da6c28aaSamw 356da6c28aaSamw for (i = 0; privset->priv_cnt; i++) { 357da6c28aaSamw if (privset->priv[i].luid.lo_part == id) { 358da6c28aaSamw if (privset->priv[i].attrs == SE_PRIVILEGE_ENABLED) 359da6c28aaSamw return (1); 360da6c28aaSamw else 361da6c28aaSamw return (0); 362da6c28aaSamw } 363da6c28aaSamw } 364da6c28aaSamw 365da6c28aaSamw return (0); 366da6c28aaSamw } 367da6c28aaSamw 368da6c28aaSamw static char * 369da6c28aaSamw smb_priv_getname(uint32_t id) 370da6c28aaSamw { 371dc20a302Sas200622 if (id < SE_MIN_LUID || id > SE_MAX_LUID) 372da6c28aaSamw return ("Unknown Privilege"); 373da6c28aaSamw 374da6c28aaSamw return (priv_table[id].name); 375da6c28aaSamw } 376