xref: /onnv-gate/usr/src/lib/smbsrv/libsmb/common/smb_privilege.c (revision 10966:37e5dcdf36d3)
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