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