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