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