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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 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 }; 86 87 /* 88 * smb_priv_presentable_num 89 * 90 * Returns number of presentable privileges 91 */ 92 int 93 smb_priv_presentable_num() 94 { 95 int i, num; 96 97 num = 0; 98 for (i = SE_MIN_LUID; i <= SE_MAX_LUID; i++) 99 if (priv_table[i].flags == PF_PRESENTABLE) 100 num++; 101 102 return (num); 103 } 104 105 /* 106 * smb_priv_presentable_ids 107 * 108 * Returns IDs of presentable privileges 109 * Returns 0 in case of invalid parameter and 1 on success. 110 */ 111 int 112 smb_priv_presentable_ids(uint32_t *ids, int num) 113 { 114 int i, j; 115 116 if (ids == NULL || num <= 0) 117 return (0); 118 119 for (i = SE_MIN_LUID, j = 0; i <= SE_MAX_LUID; i++) 120 if (priv_table[i].flags == PF_PRESENTABLE) 121 ids[j++] = priv_table[i].id; 122 123 return (1); 124 } 125 126 /* 127 * smb_priv_getbyvalue 128 * 129 * Return the privilege info for the specified id (low part of the LUID). 130 * Returns a null pointer if id is out-of-range. 131 */ 132 smb_privinfo_t * 133 smb_priv_getbyvalue(uint32_t id) 134 { 135 if (id < SE_MIN_LUID || id > SE_MAX_LUID) 136 return (0); 137 138 return (&priv_table[id]); 139 } 140 141 142 /* 143 * smb_priv_getbyname 144 * 145 * Return the privilege info for the specified name. Returns a null 146 * pointer if we can't find a matching name in the table. 147 */ 148 smb_privinfo_t * 149 smb_priv_getbyname(char *name) 150 { 151 smb_privinfo_t *entry; 152 int i; 153 154 if (name == 0) 155 return (0); 156 157 for (i = SE_MIN_LUID; i <= SE_MAX_LUID; ++i) { 158 entry = &priv_table[i]; 159 160 if (utf8_strcasecmp(name, entry->name) == 0) 161 return (entry); 162 } 163 164 return (0); 165 } 166 167 /* 168 * smb_privset_size 169 * 170 * Returns the memory block size needed to keep a complete 171 * set of privileges in a smb_privset_t structure. 172 */ 173 int 174 smb_privset_size() 175 { 176 int pcnt = SE_MAX_LUID - SE_MIN_LUID + 1; 177 178 return (2 * sizeof (uint32_t) + 179 pcnt * sizeof (smb_luid_attrs_t)); 180 } 181 182 /* 183 * smb_privset_validate 184 * 185 * Validates the given privilege set structure 186 * Returns 1 if the structure is Ok, otherwise returns 0. 187 */ 188 int 189 smb_privset_validate(smb_privset_t *privset) 190 { 191 int count; 192 uint32_t i; 193 194 if (privset == 0) { 195 return (0); 196 } 197 198 count = SE_MAX_LUID - SE_MIN_LUID + 1; 199 200 if (privset->priv_cnt != count) { 201 return (0); 202 } 203 204 for (i = 0; i < count; i++) { 205 if (privset->priv[i].luid.hi_part != 0) { 206 return (0); 207 } 208 209 if (privset->priv[i].luid.lo_part != 210 i + SE_MIN_LUID) { 211 return (0); 212 } 213 } 214 215 return (1); 216 } 217 218 /* 219 * smb_privset_init 220 * 221 * initialize all privileges in disable state. 222 */ 223 void 224 smb_privset_init(smb_privset_t *privset) 225 { 226 int count; 227 uint32_t i; 228 229 if (privset == 0) 230 return; 231 232 count = SE_MAX_LUID - SE_MIN_LUID + 1; 233 234 privset->priv_cnt = count; 235 privset->control = 0; 236 for (i = 0; i < count; i++) { 237 privset->priv[i].luid.hi_part = 0; 238 privset->priv[i].luid.lo_part = i + SE_MIN_LUID; 239 privset->priv[i].attrs = 0; 240 } 241 } 242 243 /* 244 * smb_privset_new 245 * 246 * Allocate memory and initialize all privileges in disable state. 247 * Returns pointer to allocated space or NULL if there is not 248 * enough memory. 249 */ 250 smb_privset_t * 251 smb_privset_new() 252 { 253 smb_privset_t *privset; 254 255 privset = malloc(smb_privset_size()); 256 if (privset == NULL) 257 return (NULL); 258 259 smb_privset_init(privset); 260 261 return (privset); 262 } 263 264 /* 265 * smb_privset_copy 266 * 267 * Copy privleges information specified by 'src' to the 268 * buffer specified by dst. 269 */ 270 void 271 smb_privset_copy(smb_privset_t *dst, smb_privset_t *src) 272 { 273 if (src == 0 || dst == 0) 274 return; 275 276 (void) memcpy(dst, src, smb_privset_size()); 277 } 278 279 /* 280 * smb_privset_merge 281 * 282 * Enable the privileges that are enabled in src in dst 283 */ 284 void 285 smb_privset_merge(smb_privset_t *dst, smb_privset_t *src) 286 { 287 int i; 288 289 if (src == NULL || dst == NULL) 290 return; 291 292 for (i = 0; i < src->priv_cnt; i++) { 293 if (src->priv[i].attrs == SE_PRIVILEGE_ENABLED) 294 smb_privset_enable(dst, src->priv[i].luid.lo_part); 295 } 296 } 297 298 /* 299 * smb_privset_free 300 * 301 * This will free the memory allocated by the 'privset'. 302 */ 303 void 304 smb_privset_free(smb_privset_t *privset) 305 { 306 free(privset); 307 } 308 309 void 310 smb_privset_enable(smb_privset_t *privset, uint32_t id) 311 { 312 int i; 313 314 if (privset == NULL) 315 return; 316 317 for (i = 0; i < privset->priv_cnt; i++) { 318 if (privset->priv[i].luid.lo_part == id) 319 privset->priv[i].attrs = SE_PRIVILEGE_ENABLED; 320 } 321 } 322 323 void 324 smb_privset_log(smb_privset_t *privset) 325 { 326 smb_luid_t *luid; 327 int i, ecnt; 328 329 if (privset == NULL) 330 return; 331 332 for (i = 0, ecnt = 0; i < privset->priv_cnt; ++i) { 333 if (privset->priv[i].attrs != 0) { 334 ecnt++; 335 } 336 } 337 338 syslog(LOG_DEBUG, " Privilege Count: %d (Enable=%d)", 339 privset->priv_cnt, ecnt); 340 341 for (i = 0; i < privset->priv_cnt; ++i) { 342 if (privset->priv[i].attrs != 0) { 343 luid = &privset->priv[i].luid; 344 syslog(LOG_DEBUG, " %s", 345 smb_priv_getname(luid->lo_part)); 346 } 347 } 348 } 349 350 int 351 smb_privset_query(smb_privset_t *privset, uint32_t id) 352 { 353 int i; 354 355 if (privset == NULL) 356 return (0); 357 358 for (i = 0; privset->priv_cnt; i++) { 359 if (privset->priv[i].luid.lo_part == id) { 360 if (privset->priv[i].attrs == SE_PRIVILEGE_ENABLED) 361 return (1); 362 else 363 return (0); 364 } 365 } 366 367 return (0); 368 } 369 370 static char * 371 smb_priv_getname(uint32_t id) 372 { 373 if (id < SE_MIN_LUID || id > SE_MAX_LUID) 374 return ("Unknown Privilege"); 375 376 return (priv_table[id].name); 377 } 378