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
smb_priv_presentable_num()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
smb_priv_presentable_ids(uint32_t * ids,int num)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 *
smb_priv_getbyvalue(uint32_t id)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 *
smb_priv_getbyname(char * name)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
smb_privset_size()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
smb_privset_validate(smb_privset_t * privset)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
smb_privset_init(smb_privset_t * privset)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 *
smb_privset_new()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
smb_privset_copy(smb_privset_t * dst,smb_privset_t * src)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
smb_privset_merge(smb_privset_t * dst,smb_privset_t * src)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
smb_privset_free(smb_privset_t * privset)302 smb_privset_free(smb_privset_t *privset)
303 {
304 free(privset);
305 }
306
307 void
smb_privset_enable(smb_privset_t * privset,uint32_t id)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
smb_privset_log(smb_privset_t * privset)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
smb_privset_query(smb_privset_t * privset,uint32_t id)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 *
smb_priv_getname(uint32_t id)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