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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
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.
38 #include <smbsrv/string.h>
39 #include <smbsrv/libsmb.h>
40 #include <smbsrv/smb_privilege.h>
42 static char *smb_priv_getname(uint32_t id
);
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.
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.
52 static smb_privinfo_t priv_table
[] = {
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",
73 { 18, SE_RESTORE_NAME
, "Restore files and directories",
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 }
86 * smb_priv_presentable_num
88 * Returns number of presentable privileges
91 smb_priv_presentable_num()
96 for (i
= SE_MIN_LUID
; i
<= SE_MAX_LUID
; i
++)
97 if (priv_table
[i
].flags
== PF_PRESENTABLE
)
104 * smb_priv_presentable_ids
106 * Returns IDs of presentable privileges
107 * Returns 0 in case of invalid parameter and 1 on success.
110 smb_priv_presentable_ids(uint32_t *ids
, int num
)
114 if (ids
== NULL
|| num
<= 0)
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
;
125 * smb_priv_getbyvalue
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.
131 smb_priv_getbyvalue(uint32_t id
)
133 if (id
< SE_MIN_LUID
|| id
> SE_MAX_LUID
)
136 return (&priv_table
[id
]);
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.
147 smb_priv_getbyname(char *name
)
149 smb_privinfo_t
*entry
;
155 for (i
= SE_MIN_LUID
; i
<= SE_MAX_LUID
; ++i
) {
156 entry
= &priv_table
[i
];
158 if (smb_strcasecmp(name
, entry
->name
, 0) == 0)
168 * Returns the memory block size needed to keep a complete
169 * set of privileges in a smb_privset_t structure.
174 int pcnt
= SE_MAX_LUID
- SE_MIN_LUID
+ 1;
176 return (2 * sizeof (uint32_t) +
177 pcnt
* sizeof (smb_luid_attrs_t
));
181 * smb_privset_validate
183 * Validates the given privilege set structure
184 * Returns 1 if the structure is Ok, otherwise returns 0.
187 smb_privset_validate(smb_privset_t
*privset
)
196 count
= SE_MAX_LUID
- SE_MIN_LUID
+ 1;
198 if (privset
->priv_cnt
!= count
) {
202 for (i
= 0; i
< count
; i
++) {
203 if (privset
->priv
[i
].luid
.hi_part
!= 0) {
207 if (privset
->priv
[i
].luid
.lo_part
!=
219 * initialize all privileges in disable state.
222 smb_privset_init(smb_privset_t
*privset
)
230 count
= SE_MAX_LUID
- SE_MIN_LUID
+ 1;
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;
244 * Allocate memory and initialize all privileges in disable state.
245 * Returns pointer to allocated space or NULL if there is not
251 smb_privset_t
*privset
;
253 privset
= malloc(smb_privset_size());
257 smb_privset_init(privset
);
265 * Copy privleges information specified by 'src' to the
266 * buffer specified by dst.
269 smb_privset_copy(smb_privset_t
*dst
, smb_privset_t
*src
)
271 if (src
== 0 || dst
== 0)
274 (void) memcpy(dst
, src
, smb_privset_size());
280 * Enable the privileges that are enabled in src in dst
283 smb_privset_merge(smb_privset_t
*dst
, smb_privset_t
*src
)
287 if (src
== NULL
|| dst
== NULL
)
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
);
299 * This will free the memory allocated by the 'privset'.
302 smb_privset_free(smb_privset_t
*privset
)
308 smb_privset_enable(smb_privset_t
*privset
, uint32_t id
)
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
;
322 smb_privset_log(smb_privset_t
*privset
)
330 for (i
= 0, ecnt
= 0; i
< privset
->priv_cnt
; ++i
) {
331 if (privset
->priv
[i
].attrs
!= 0) {
336 syslog(LOG_DEBUG
, " Privilege Count: %d (Enable=%d)",
337 privset
->priv_cnt
, ecnt
);
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
));
349 smb_privset_query(smb_privset_t
*privset
, uint32_t id
)
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
)
369 smb_priv_getname(uint32_t id
)
371 if (id
< SE_MIN_LUID
|| id
> SE_MAX_LUID
)
372 return ("Unknown Privilege");
374 return (priv_table
[id
].name
);