15331Samw /*
25331Samw * CDDL HEADER START
35331Samw *
45331Samw * The contents of this file are subject to the terms of the
55331Samw * Common Development and Distribution License (the "License").
65331Samw * You may not use this file except in compliance with the License.
75331Samw *
85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw * or http://www.opensolaris.org/os/licensing.
105331Samw * See the License for the specific language governing permissions
115331Samw * and limitations under the License.
125331Samw *
135331Samw * When distributing Covered Code, include this CDDL HEADER in each
145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw * If applicable, add the following below this CDDL HEADER, with the
165331Samw * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw *
195331Samw * CDDL HEADER END
205331Samw */
215331Samw /*
22*10966SJordan.Brown@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
235331Samw * Use is subject to license terms.
245331Samw */
255331Samw
265331Samw /*
275331Samw * This module provides the interface to the built-in privilege names
285331Samw * and id's. NT privileges are known on the network using strings. Each
295331Samw * system assigns locally unique identifiers (LUID) for use within the
305331Samw * system. Each built-in privilege also has a display-name, which is a
315331Samw * short description of the privilege. The functions here provide an
325331Samw * interface to map between LUIDs, names and display names.
335331Samw */
345331Samw
355331Samw #include <string.h>
365331Samw #include <syslog.h>
375331Samw
385331Samw #include <smbsrv/string.h>
395331Samw #include <smbsrv/libsmb.h>
405331Samw #include <smbsrv/smb_privilege.h>
415331Samw
425331Samw static char *smb_priv_getname(uint32_t id);
435331Samw
445331Samw /*
455331Samw * Table of built-in privilege id's, names and display strings. This
465331Samw * table matches the response from an NT4.0 PDC LSARPC service.
475331Samw * Requests for values 0 and 1 return STATUS_NO_SUCH_PRIVILEGE.
485331Samw *
495331Samw * SE_UNSOLICITED_INPUT_NAME/SeUnsolicitedInputPrivilege is defined in
505331Samw * winnt.h but doesn't appear in the list reported by the NT4.0 LSA.
515331Samw */
525331Samw static smb_privinfo_t priv_table[] = {
535331Samw { 0, "", "", 0 },
545331Samw { 1, "", "", 0 },
555331Samw { 2, SE_CREATE_TOKEN_NAME, "Create a token object", 0 },
565331Samw { 3, SE_ASSIGNPRIMARYTOKEN_NAME, "Replace a process level token", 0 },
575331Samw { 4, SE_LOCK_MEMORY_NAME, "Lock pages in memory", 0 },
585331Samw { 5, SE_INCREASE_QUOTA_NAME, "Increase quotas", 0 },
595331Samw { 6, SE_MACHINE_ACCOUNT_NAME, "Add workstations to domain", 0 },
605331Samw { 7, SE_TCB_NAME, "Act as part of the operating system", 0 },
615331Samw { 8, SE_SECURITY_NAME, "Manage auditing and security log", 0 },
625331Samw { 9, SE_TAKE_OWNERSHIP_NAME,
635331Samw "Take ownership of files or other objects", PF_PRESENTABLE },
645331Samw { 10, SE_LOAD_DRIVER_NAME, "Load and unload device drivers", 0 },
655331Samw { 11, SE_SYSTEM_PROFILE_NAME, "Profile system performance", 0 },
665331Samw { 12, SE_SYSTEMTIME_NAME, "Change the system time", 0 },
675331Samw { 13, SE_PROF_SINGLE_PROCESS_NAME, "Profile single process", 0 },
685331Samw { 14, SE_INC_BASE_PRIORITY_NAME, "Increase scheduling priority", 0 },
695331Samw { 15, SE_CREATE_PAGEFILE_NAME, "Create a pagefile", 0 },
705331Samw { 16, SE_CREATE_PERMANENT_NAME, "Create permanent shared objects", 0 },
715331Samw { 17, SE_BACKUP_NAME, "Back up files and directories",
725331Samw PF_PRESENTABLE },
735331Samw { 18, SE_RESTORE_NAME, "Restore files and directories",
745331Samw PF_PRESENTABLE },
755331Samw { 19, SE_SHUTDOWN_NAME, "Shut down the system", 0 },
765331Samw { 20, SE_DEBUG_NAME, "Debug programs", 0 },
775331Samw { 21, SE_AUDIT_NAME, "Generate security audits", 0 },
785331Samw { 22, SE_SYSTEM_ENVIRONMENT_NAME,
795331Samw "Modify firmware environment values", 0 },
805331Samw { 23, SE_CHANGE_NOTIFY_NAME, "Bypass traverse checking", 0 },
815331Samw { 24, SE_REMOTE_SHUTDOWN_NAME,
825331Samw "Force shutdown from a remote system", 0 }
835331Samw };
845331Samw
855331Samw /*
865331Samw * smb_priv_presentable_num
875331Samw *
885331Samw * Returns number of presentable privileges
895331Samw */
905331Samw int
smb_priv_presentable_num()915331Samw smb_priv_presentable_num()
925331Samw {
935331Samw int i, num;
945331Samw
955331Samw num = 0;
965772Sas200622 for (i = SE_MIN_LUID; i <= SE_MAX_LUID; i++)
975331Samw if (priv_table[i].flags == PF_PRESENTABLE)
985331Samw num++;
995331Samw
1005331Samw return (num);
1015331Samw }
1025331Samw
1035331Samw /*
1045331Samw * smb_priv_presentable_ids
1055331Samw *
1065331Samw * Returns IDs of presentable privileges
1075331Samw * Returns 0 in case of invalid parameter and 1 on success.
1085331Samw */
1095331Samw int
smb_priv_presentable_ids(uint32_t * ids,int num)1105331Samw smb_priv_presentable_ids(uint32_t *ids, int num)
1115331Samw {
1125331Samw int i, j;
1135331Samw
1145331Samw if (ids == NULL || num <= 0)
1155331Samw return (0);
1165331Samw
1175772Sas200622 for (i = SE_MIN_LUID, j = 0; i <= SE_MAX_LUID; i++)
1185331Samw if (priv_table[i].flags == PF_PRESENTABLE)
1195331Samw ids[j++] = priv_table[i].id;
1205331Samw
1215331Samw return (1);
1225331Samw }
1235331Samw
1245331Samw /*
1255331Samw * smb_priv_getbyvalue
1265331Samw *
1275331Samw * Return the privilege info for the specified id (low part of the LUID).
1285331Samw * Returns a null pointer if id is out-of-range.
1295331Samw */
1305331Samw smb_privinfo_t *
smb_priv_getbyvalue(uint32_t id)1315331Samw smb_priv_getbyvalue(uint32_t id)
1325331Samw {
1335772Sas200622 if (id < SE_MIN_LUID || id > SE_MAX_LUID)
1345331Samw return (0);
1355331Samw
1365331Samw return (&priv_table[id]);
1375331Samw }
1385331Samw
1395331Samw
1405331Samw /*
1415331Samw * smb_priv_getbyname
1425331Samw *
1435331Samw * Return the privilege info for the specified name. Returns a null
1445331Samw * pointer if we can't find a matching name in the table.
1455331Samw */
1465331Samw smb_privinfo_t *
smb_priv_getbyname(char * name)1475331Samw smb_priv_getbyname(char *name)
1485331Samw {
1495331Samw smb_privinfo_t *entry;
1505331Samw int i;
1515331Samw
1525331Samw if (name == 0)
1535331Samw return (0);
1545331Samw
1555772Sas200622 for (i = SE_MIN_LUID; i <= SE_MAX_LUID; ++i) {
1565331Samw entry = &priv_table[i];
1575331Samw
158*10966SJordan.Brown@Sun.COM if (smb_strcasecmp(name, entry->name, 0) == 0)
1595331Samw return (entry);
1605331Samw }
1615331Samw
1625331Samw return (0);
1635331Samw }
1645331Samw
1655331Samw /*
1665331Samw * smb_privset_size
1675331Samw *
1685331Samw * Returns the memory block size needed to keep a complete
1695331Samw * set of privileges in a smb_privset_t structure.
1705331Samw */
1715331Samw int
smb_privset_size()1725331Samw smb_privset_size()
1735331Samw {
1745772Sas200622 int pcnt = SE_MAX_LUID - SE_MIN_LUID + 1;
1755331Samw
1765331Samw return (2 * sizeof (uint32_t) +
1775331Samw pcnt * sizeof (smb_luid_attrs_t));
1785331Samw }
1795331Samw
1805331Samw /*
1815331Samw * smb_privset_validate
1825331Samw *
1835331Samw * Validates the given privilege set structure
1845331Samw * Returns 1 if the structure is Ok, otherwise returns 0.
1855331Samw */
1865331Samw int
smb_privset_validate(smb_privset_t * privset)1875331Samw smb_privset_validate(smb_privset_t *privset)
1885331Samw {
1895331Samw int count;
1905331Samw uint32_t i;
1915331Samw
1925331Samw if (privset == 0) {
1935331Samw return (0);
1945331Samw }
1955331Samw
1965772Sas200622 count = SE_MAX_LUID - SE_MIN_LUID + 1;
1975331Samw
1985331Samw if (privset->priv_cnt != count) {
1995331Samw return (0);
2005331Samw }
2015331Samw
2025331Samw for (i = 0; i < count; i++) {
2035331Samw if (privset->priv[i].luid.hi_part != 0) {
2045331Samw return (0);
2055331Samw }
2065331Samw
2075331Samw if (privset->priv[i].luid.lo_part !=
2085772Sas200622 i + SE_MIN_LUID) {
2095331Samw return (0);
2105331Samw }
2115331Samw }
2125331Samw
2135331Samw return (1);
2145331Samw }
2155331Samw
2165331Samw /*
2175331Samw * smb_privset_init
2185331Samw *
2195331Samw * initialize all privileges in disable state.
2205331Samw */
2215331Samw void
smb_privset_init(smb_privset_t * privset)2225331Samw smb_privset_init(smb_privset_t *privset)
2235331Samw {
2245331Samw int count;
2255331Samw uint32_t i;
2265331Samw
2275331Samw if (privset == 0)
2285331Samw return;
2295331Samw
2305772Sas200622 count = SE_MAX_LUID - SE_MIN_LUID + 1;
2315331Samw
2325331Samw privset->priv_cnt = count;
2335331Samw privset->control = 0;
2345331Samw for (i = 0; i < count; i++) {
2355331Samw privset->priv[i].luid.hi_part = 0;
2365772Sas200622 privset->priv[i].luid.lo_part = i + SE_MIN_LUID;
2375331Samw privset->priv[i].attrs = 0;
2385331Samw }
2395331Samw }
2405331Samw
2415331Samw /*
2425331Samw * smb_privset_new
2435331Samw *
2445331Samw * Allocate memory and initialize all privileges in disable state.
2455331Samw * Returns pointer to allocated space or NULL if there is not
2465331Samw * enough memory.
2475331Samw */
2485331Samw smb_privset_t *
smb_privset_new()2495331Samw smb_privset_new()
2505331Samw {
2515331Samw smb_privset_t *privset;
2525331Samw
2535331Samw privset = malloc(smb_privset_size());
2545331Samw if (privset == NULL)
2555331Samw return (NULL);
2565331Samw
2575331Samw smb_privset_init(privset);
2585331Samw
2595331Samw return (privset);
2605331Samw }
2615331Samw
2625331Samw /*
2635331Samw * smb_privset_copy
2645331Samw *
2655331Samw * Copy privleges information specified by 'src' to the
2665331Samw * buffer specified by dst.
2675331Samw */
2685331Samw void
smb_privset_copy(smb_privset_t * dst,smb_privset_t * src)2695331Samw smb_privset_copy(smb_privset_t *dst, smb_privset_t *src)
2705331Samw {
2715331Samw if (src == 0 || dst == 0)
2725331Samw return;
2735331Samw
2745331Samw (void) memcpy(dst, src, smb_privset_size());
2755331Samw }
2765331Samw
2775331Samw /*
2785772Sas200622 * smb_privset_merge
2795772Sas200622 *
2805772Sas200622 * Enable the privileges that are enabled in src in dst
2815772Sas200622 */
2825772Sas200622 void
smb_privset_merge(smb_privset_t * dst,smb_privset_t * src)2835772Sas200622 smb_privset_merge(smb_privset_t *dst, smb_privset_t *src)
2845772Sas200622 {
2855772Sas200622 int i;
2865772Sas200622
2875772Sas200622 if (src == NULL || dst == NULL)
2885772Sas200622 return;
2895772Sas200622
2905772Sas200622 for (i = 0; i < src->priv_cnt; i++) {
2915772Sas200622 if (src->priv[i].attrs == SE_PRIVILEGE_ENABLED)
2925772Sas200622 smb_privset_enable(dst, src->priv[i].luid.lo_part);
2935772Sas200622 }
2945772Sas200622 }
2955772Sas200622
2965772Sas200622 /*
2975331Samw * smb_privset_free
2985331Samw *
2995331Samw * This will free the memory allocated by the 'privset'.
3005331Samw */
3015331Samw void
smb_privset_free(smb_privset_t * privset)3025331Samw smb_privset_free(smb_privset_t *privset)
3035331Samw {
3045331Samw free(privset);
3055331Samw }
3065331Samw
3075331Samw void
smb_privset_enable(smb_privset_t * privset,uint32_t id)3085331Samw smb_privset_enable(smb_privset_t *privset, uint32_t id)
3095331Samw {
3105331Samw int i;
3115331Samw
3125331Samw if (privset == NULL)
3135331Samw return;
3145331Samw
3155331Samw for (i = 0; i < privset->priv_cnt; i++) {
3165331Samw if (privset->priv[i].luid.lo_part == id)
3175331Samw privset->priv[i].attrs = SE_PRIVILEGE_ENABLED;
3185331Samw }
3195331Samw }
3205331Samw
3215331Samw void
smb_privset_log(smb_privset_t * privset)3225331Samw smb_privset_log(smb_privset_t *privset)
3235331Samw {
3245331Samw smb_luid_t *luid;
3255331Samw int i, ecnt;
3265331Samw
3275331Samw if (privset == NULL)
3285331Samw return;
3295331Samw
3305331Samw for (i = 0, ecnt = 0; i < privset->priv_cnt; ++i) {
3315331Samw if (privset->priv[i].attrs != 0) {
3325331Samw ecnt++;
3335331Samw }
3345331Samw }
3355331Samw
3365331Samw syslog(LOG_DEBUG, " Privilege Count: %d (Enable=%d)",
3375331Samw privset->priv_cnt, ecnt);
3385331Samw
3395331Samw for (i = 0; i < privset->priv_cnt; ++i) {
3405331Samw if (privset->priv[i].attrs != 0) {
3415331Samw luid = &privset->priv[i].luid;
3425331Samw syslog(LOG_DEBUG, " %s",
3435331Samw smb_priv_getname(luid->lo_part));
3445331Samw }
3455331Samw }
3465331Samw }
3475331Samw
3485331Samw int
smb_privset_query(smb_privset_t * privset,uint32_t id)3495331Samw smb_privset_query(smb_privset_t *privset, uint32_t id)
3505331Samw {
3515331Samw int i;
3525331Samw
3535331Samw if (privset == NULL)
3545331Samw return (0);
3555331Samw
3565331Samw for (i = 0; privset->priv_cnt; i++) {
3575331Samw if (privset->priv[i].luid.lo_part == id) {
3585331Samw if (privset->priv[i].attrs == SE_PRIVILEGE_ENABLED)
3595331Samw return (1);
3605331Samw else
3615331Samw return (0);
3625331Samw }
3635331Samw }
3645331Samw
3655331Samw return (0);
3665331Samw }
3675331Samw
3685331Samw static char *
smb_priv_getname(uint32_t id)3695331Samw smb_priv_getname(uint32_t id)
3705331Samw {
3715772Sas200622 if (id < SE_MIN_LUID || id > SE_MAX_LUID)
3725331Samw return ("Unknown Privilege");
3735331Samw
3745331Samw return (priv_table[id].name);
3755331Samw }
376