diff options
-rw-r--r-- | source3/Makefile.in | 2 | ||||
-rw-r--r-- | source3/auth/auth_util.c | 22 | ||||
-rw-r--r-- | source3/groupdb/mapping.c | 11 | ||||
-rw-r--r-- | source3/include/auth.h | 1 | ||||
-rw-r--r-- | source3/include/includes.h | 4 | ||||
-rw-r--r-- | source3/include/passdb.h | 20 | ||||
-rw-r--r-- | source3/include/privileges.h | 47 | ||||
-rw-r--r-- | source3/include/smb.h | 3 | ||||
-rw-r--r-- | source3/lib/privileges.c | 79 | ||||
-rw-r--r-- | source3/param/loadparm.c | 2 | ||||
-rw-r--r-- | source3/passdb/pdb_interface.c | 157 | ||||
-rw-r--r-- | source3/passdb/pdb_tdb.c | 353 | ||||
-rw-r--r-- | source3/rpc_server/srv_lsa_nt.c | 4 | ||||
-rw-r--r-- | source3/rpc_server/srv_pipe_hnd.c | 2 | ||||
-rw-r--r-- | source3/rpc_server/srv_samr_nt.c | 72 | ||||
-rw-r--r-- | source3/rpc_server/srv_srvsvc_nt.c | 70 | ||||
-rw-r--r-- | source3/sam/gums.c | 63 | ||||
-rw-r--r-- | source3/smbd/chgpasswd.c | 2 | ||||
-rw-r--r-- | source3/smbd/conn.c | 8 | ||||
-rw-r--r-- | source3/smbd/password.c | 6 | ||||
-rw-r--r-- | source3/smbd/sec_ctx.c | 27 | ||||
-rw-r--r-- | source3/smbd/service.c | 4 | ||||
-rw-r--r-- | source3/smbd/uid.c | 18 | ||||
-rw-r--r-- | source3/utils/net.c | 1 |
24 files changed, 838 insertions, 140 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 25a0e45f05..5792b00264 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -514,7 +514,7 @@ NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_ads_cldap.o utils/net_help.o \ utils/net_rap.o utils/net_rpc.o utils/net_rpc_samsync.o \ utils/net_rpc_join.o utils/net_time.o utils/net_lookup.o \ utils/net_cache.o utils/net_groupmap.o utils/net_idmap.o \ - utils/net_status.o + utils/net_status.o utils/net_privileges.o NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \ $(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 4a23593936..018d3b1851 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -827,6 +827,23 @@ static NTSTATUS add_user_groups(auth_serversupplied_info **server_info, } /*************************************************************************** +Fill a server_info struct from a SAM_ACCOUNT with its privileges +***************************************************************************/ + +static NTSTATUS add_privileges(auth_serversupplied_info **server_info) +{ + PRIVILEGE_SET *privs = NULL; + + init_privilege(&privs); + if (!pdb_get_privilege_set((*server_info)->ptok, privs)) + return NT_STATUS_UNSUCCESSFUL; + + (*server_info)->privs = privs; + + return NT_STATUS_OK; +} + +/*************************************************************************** Make (and fill) a user_info struct from a SAM_ACCOUNT ***************************************************************************/ @@ -860,6 +877,11 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, return nt_status; } + if (!NT_STATUS_IS_OK(nt_status = add_privileges(server_info))) { + free_server_info(server_info); + return nt_status; + } + (*server_info)->sam_fill_level = SAM_FILL_ALL; DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n", pdb_get_username(sampass), diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c index c153ff258d..ef0708b888 100644 --- a/source3/groupdb/mapping.c +++ b/source3/groupdb/mapping.c @@ -29,17 +29,6 @@ static TDB_CONTEXT *tdb; /* used for driver files */ #define GROUP_PREFIX "UNIXGROUP/" #define ALIASMEM_PREFIX "ALIASMEMBERS/" -PRIVS privs[] = { - {SE_PRIV_NONE, "no_privs", "No privilege" }, /* this one MUST be first */ - {SE_PRIV_ADD_MACHINES, "SeMachineAccountPrivilege", "Add workstations to the domain" }, - {SE_PRIV_SEC_PRIV, "SeSecurityPrivilege", "Manage the audit logs" }, - {SE_PRIV_TAKE_OWNER, "SeTakeOwnershipPrivilege", "Take ownership of file" }, - {SE_PRIV_ADD_USERS, "SaAddUsers", "Add users to the domain - Samba" }, - {SE_PRIV_PRINT_OPERATOR, "SaPrintOp", "Add or remove printers - Samba" }, - {SE_PRIV_ALL, "SaAllPrivs", "all privileges" } -}; - - /**************************************************************************** dump the mapping group mapping to a text file ****************************************************************************/ diff --git a/source3/include/auth.h b/source3/include/auth.h index ecf4d539d8..27cdc1e3f5 100644 --- a/source3/include/auth.h +++ b/source3/include/auth.h @@ -86,6 +86,7 @@ typedef struct auth_serversupplied_info /* NT group information taken from the info3 structure */ NT_USER_TOKEN *ptok; + PRIVILEGE_SET *privs; DATA_BLOB nt_session_key; DATA_BLOB lm_session_key; diff --git a/source3/include/includes.h b/source3/include/includes.h index db060907e4..a594e309df 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -783,6 +783,8 @@ extern int errno; #include "version.h" +#include "privileges.h" + #include "smb.h" #include "nameserv.h" @@ -791,8 +793,6 @@ extern int errno; #include "byteorder.h" -#include "privileges.h" - #include "rpc_creds.h" #include "mapping.h" diff --git a/source3/include/passdb.h b/source3/include/passdb.h index 668bbcc2de..d471eb53f3 100644 --- a/source3/include/passdb.h +++ b/source3/include/passdb.h @@ -362,6 +362,16 @@ typedef struct pdb_context NTSTATUS (*pdb_update_trust_passwd)(struct pdb_context *context, SAM_TRUST_PASSWD* trust); NTSTATUS (*pdb_delete_trust_passwd)(struct pdb_context *context, SAM_TRUST_PASSWD* trust); + + /* privileges functions */ + + NTSTATUS (*pdb_add_sid_to_privilege)(struct pdb_context *context, const char *priv_name, const DOM_SID *sid); + + NTSTATUS (*pdb_remove_sid_from_privilege)(struct pdb_context *context, const char *priv_name, const DOM_SID *sid); + + NTSTATUS (*pdb_get_privilege_set)(struct pdb_context *context, NT_USER_TOKEN *token, PRIVILEGE_SET *privs); + + NTSTATUS (*pdb_get_privilege_entry)(struct pdb_context *context, const char *privname, char **sid_list); void (*free_fn)(struct pdb_context **); @@ -467,6 +477,16 @@ typedef struct pdb_methods NTSTATUS (*delete_trust_passwd)(struct pdb_methods *methods, const SAM_TRUST_PASSWD* trust); + /* privileges functions */ + + NTSTATUS (*add_sid_to_privilege)(struct pdb_methods *methods, const char *priv_name, const DOM_SID *sid); + + NTSTATUS (*remove_sid_from_privilege)(struct pdb_methods *methods, const char *priv_name, const DOM_SID *sid); + + NTSTATUS (*get_privilege_set)(struct pdb_methods *methods, NT_USER_TOKEN *token, PRIVILEGE_SET *privs); + + NTSTATUS (*get_privilege_entry)(struct pdb_methods *methods, const char *privname, char **sid_list); + } PDB_METHODS; typedef NTSTATUS (*pdb_init_function)(struct pdb_context *, diff --git a/source3/include/privileges.h b/source3/include/privileges.h index b7e1b44c2a..289afa234e 100644 --- a/source3/include/privileges.h +++ b/source3/include/privileges.h @@ -23,15 +23,39 @@ #ifndef PRIVILEGES_H #define PRIVILEGES_H -#define PRIV_ALL_INDEX 5 +#define PRIV_ALL_INDEX 30 -#define SE_PRIV_NONE 0x0000 -#define SE_PRIV_ADD_MACHINES 0x0006 -#define SE_PRIV_SEC_PRIV 0x0008 -#define SE_PRIV_TAKE_OWNER 0x0009 -#define SE_PRIV_ADD_USERS 0xff01 -#define SE_PRIV_PRINT_OPERATOR 0xff03 -#define SE_PRIV_ALL 0xffff +#define SE_NONE 0 +#define SE_ASSIGN_PRIMARY_TOKEN 1 +#define SE_CREATE_TOKEN 2 +#define SE_LOCK_MEMORY 3 +#define SE_INCREASE_QUOTA 4 +#define SE_UNSOLICITED_INPUT 5 +#define SE_MACHINE_ACCOUNT 6 +#define SE_TCB 7 +#define SE_SECURITY 8 +#define SE_TAKE_OWNERSHIP 9 +#define SE_LOAD_DRIVER 10 +#define SE_SYSTEM_PROFILE 11 +#define SE_SYSTEM_TIME 12 +#define SE_PROF_SINGLE_PROCESS 13 +#define SE_INC_BASE_PRIORITY 14 +#define SE_CREATE_PAGEFILE 15 +#define SE_CREATE_PERMANENT 16 +#define SE_BACKUP 17 +#define SE_RESTORE 18 +#define SE_SHUTDOWN 19 +#define SE_DEBUG 20 +#define SE_AUDIT 21 +#define SE_SYSTEM_ENVIRONMENT 22 +#define SE_CHANGE_NOTIFY 23 +#define SE_REMOTE_SHUTDOWN 24 +#define SE_UNDOCK 25 +#define SE_SYNC_AGENT 26 +#define SE_ENABLE_DELEGATION 27 +#define SE_PRINT_OPERATOR 28 +#define SE_ADD_USERS 29 +#define SE_ALL_PRIVS 0xffff #define PR_NONE 0x0000 #define PR_LOG_ON_LOCALLY 0x0001 @@ -39,6 +63,11 @@ #define PR_LOG_ON_BATCH_JOB 0x0004 #define PR_LOG_ON_SERVICE 0x0010 +#ifndef _BOOL +typedef int BOOL; +#define _BOOL /* So we don't typedef BOOL again in vfs.h */ +#endif + typedef struct LUID { uint32 low; @@ -49,7 +78,7 @@ typedef struct LUID_ATTR { LUID luid; uint32 attr; -} LUID_ATTR ; +} LUID_ATTR; typedef struct privilege_set { diff --git a/source3/include/smb.h b/source3/include/smb.h index 5cd5e71f74..ab6f4c70d6 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -500,6 +500,7 @@ typedef struct connection_struct int ngroups; gid_t *groups; NT_USER_TOKEN *nt_user_token; + PRIVILEGE_SET *privs; time_t lastused; BOOL used; @@ -519,6 +520,7 @@ struct current_user int ngroups; gid_t *groups; NT_USER_TOKEN *nt_user_token; + PRIVILEGE_SET *privs; }; /* Defines for the sent_oplock_break field above. */ @@ -1546,6 +1548,7 @@ typedef struct user_struct gid_t *groups; NT_USER_TOKEN *nt_user_token; + PRIVILEGE_SET *privs; DATA_BLOB session_key; diff --git a/source3/lib/privileges.c b/source3/lib/privileges.c index b9d4df301d..4bcf5e3b36 100644 --- a/source3/lib/privileges.c +++ b/source3/lib/privileges.c @@ -26,6 +26,43 @@ #define ALLOC_CHECK(ptr, err, label, str) do { if ((ptr) == NULL) { DEBUG(0, ("%s: out of memory!\n", str)); err = NT_STATUS_NO_MEMORY; goto label; } } while(0) #define NTSTATUS_CHECK(err, label, str1, str2) do { if (!NT_STATUS_IS_OK(err)) { DEBUG(0, ("%s: %s failed!\n", str1, str2)); } } while(0) + +PRIVS privs[] = { + {SE_NONE, "no_privs", "No privilege"}, /* this one MUST be first */ + {SE_CREATE_TOKEN, "SeCreateTokenPrivilege", "Create Token"}, + {SE_ASSIGN_PRIMARY_TOKEN, "SeAssignPrimaryTokenPrivilege", "Assign Primary Token"}, + {SE_LOCK_MEMORY, "SeLockMemoryPrivilege", "Lock Memory"}, + {SE_INCREASE_QUOTA, "SeIncreaseQuotaPrivilege", "Increase Quota"}, + {SE_UNSOLICITED_INPUT, "eUnsolicitedInputPrivilege", "Unsolicited Input"}, + {SE_MACHINE_ACCOUNT, "SeMachineAccountPrivilege", "Can add Machine Accounts to the Domain"}, + {SE_TCB, "SeTcbPrivilege", "TCB"}, + {SE_SECURITY, "SeSecurityPrivilege", "Security Privilege"}, + {SE_TAKE_OWNERSHIP, "SeTakeOwnershipPrivilege", "Take Ownership Privilege"}, + {SE_LOAD_DRIVER, "SeLocalDriverPrivilege", "Local Driver Privilege"}, + {SE_SYSTEM_PROFILE, "SeSystemProfilePrivilege", "System Profile Privilege"}, + {SE_SYSTEM_TIME, "SeSystemtimePrivilege", "System Time"}, + {SE_PROF_SINGLE_PROCESS, "SeProfileSingleProcessPrivilege", "Profile Single Process Privilege"}, + {SE_INC_BASE_PRIORITY, "SeIncreaseBasePriorityPrivilege", "Increase Base Priority Privilege"}, + {SE_CREATE_PAGEFILE, "SeCreatePagefilePrivilege", "Create Pagefile Privilege"}, + {SE_CREATE_PERMANENT, "SeCreatePermanentPrivilege", "Create Permanent"}, + {SE_BACKUP, "SeBackupPrivilege", "Backup Privilege"}, + {SE_RESTORE, "SeRestorePrivilege", "Restore Privilege"}, + {SE_SHUTDOWN, "SeShutdownPrivilege", "Shutdown Privilege"}, + {SE_DEBUG, "SeDebugPrivilege", "Debug Privilege"}, + {SE_AUDIT, "SeAuditPrivilege", "Audit"}, + {SE_SYSTEM_ENVIRONMENT, "SeSystemEnvironmentPrivilege", "System Environment Privilege"}, + {SE_CHANGE_NOTIFY, "SeChangeNotifyPrivilege", "Change Notify"}, + {SE_REMOTE_SHUTDOWN, "SeRemoteShutdownPrivilege", "Remote Shutdown Privilege"}, + {SE_UNDOCK, "SeUndockPrivilege", "Undock"}, + {SE_SYNC_AGENT, "SeSynchronizationAgentPrivilege", "Synchronization Agent"}, + {SE_ENABLE_DELEGATION, "SeEnableDelegationPrivilege", "Enable Delegation"}, + {SE_PRINT_OPERATOR, "SePrintOperatorPrivilege", "Printer Operator"}, + {SE_ADD_USERS, "SeAddUsersPrivilege", "Add Users"}, + {SE_ALL_PRIVS, "SeAllPrivileges", "All Privileges"} +}; + + + /**************************************************************************** Check if a user is a mapped group. @@ -170,6 +207,27 @@ done: return ret; } +NTSTATUS add_privilege_by_name(PRIVILEGE_SET *priv_set, const char *name) +{ + int e; + + for (e = 0; privs[e].se_priv != SE_ALL_PRIVS; e++) { + if (StrCaseCmp(privs[e].priv, name) == 0) { + LUID_ATTR la; + + la.attr = 0; + la.luid.high = 0; + la.luid.low = privs[e].se_priv; + + return add_privilege(priv_set, la); + } + } + + DEBUG(1, ("add_privilege_by_name: No Such Privilege Found (%s)\n", name)); + + return NT_STATUS_UNSUCCESSFUL; +} + /**************************************************************************** add all the privileges to a privilege array ****************************************************************************/ @@ -182,15 +240,15 @@ NTSTATUS add_all_privilege(PRIVILEGE_SET *priv_set) set.luid.high = 0; /* TODO: set a proper list of privileges */ - set.luid.low = SE_PRIV_ADD_USERS; + set.luid.low = SE_ADD_USERS; result = add_privilege(priv_set, set); NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege"); - set.luid.low = SE_PRIV_ADD_MACHINES; + set.luid.low = SE_MACHINE_ACCOUNT; result = add_privilege(priv_set, set); NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege"); - set.luid.low = SE_PRIV_PRINT_OPERATOR; + set.luid.low = SE_PRINT_OPERATOR; result = add_privilege(priv_set, set); NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege"); @@ -329,7 +387,7 @@ NTSTATUS dup_priv_set(PRIVILEGE_SET *new_priv_set, PRIVILEGE_SET *priv_set) old_set = priv_set->set; - new_set = (LUID_ATTR *)talloc(new_priv_set->mem_ctx, (priv_set->count - 1) * (sizeof(LUID_ATTR))); + new_set = (LUID_ATTR *)talloc(new_priv_set->mem_ctx, (priv_set->count) * (sizeof(LUID_ATTR))); ALLOC_CHECK(new_set, ret, done, "dup_priv_set"); for (i=0; i < priv_set->count; i++) { @@ -348,3 +406,16 @@ NTSTATUS dup_priv_set(PRIVILEGE_SET *new_priv_set, PRIVILEGE_SET *priv_set) done: return ret; } + + +NTSTATUS user_has_privilege(struct current_user *user, uint32 privilege) +{ + LUID_ATTR set; + + set.attr = 0; + set.luid.high = 0; + set.luid.low = privilege; + + return check_priv_in_privilege(user->privs, set); +} + diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index ae9d3ae945..58f4919465 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -3857,7 +3857,7 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults, if (iServiceIndex >= 0) bRetval = service_ok(iServiceIndex); - if (lp_config_backend()) { + if (*(lp_config_backend())) { modconf_init(lp_config_backend()); modconf_load(do_section, do_parameter); } diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index 2005885c45..180db58c2d 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -587,6 +587,86 @@ static NTSTATUS context_delete_trust_passwd(struct pdb_context *context, return trust->methods->delete_trust_passwd(trust->methods, trust); } +static NTSTATUS context_add_sid_to_privilege(struct pdb_context *context, const char *priv_name, const DOM_SID *sid) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + struct pdb_methods *curmethods; + if ((!context)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + curmethods = context->pdb_methods; + while (curmethods){ + if (NT_STATUS_IS_OK(ret = curmethods->add_sid_to_privilege(curmethods, priv_name, sid))) { + return ret; + } + curmethods = curmethods->next; + } + + return ret; +} + +static NTSTATUS context_remove_sid_from_privilege(struct pdb_context *context, const char *priv_name, const DOM_SID *sid) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + struct pdb_methods *curmethods; + if ((!context)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + curmethods = context->pdb_methods; + while (curmethods){ + if (NT_STATUS_IS_OK(ret = curmethods->remove_sid_from_privilege(curmethods, priv_name, sid))) { + return ret; + } + curmethods = curmethods->next; + } + + return ret; +} + +static NTSTATUS context_get_privilege_set(struct pdb_context *context, NT_USER_TOKEN *token, PRIVILEGE_SET *privset) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + struct pdb_methods *curmethods; + if ((!context)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + curmethods = context->pdb_methods; + while (curmethods){ + if (NT_STATUS_IS_OK(ret = curmethods->get_privilege_set(curmethods, token, privset))) { + return ret; + } + curmethods = curmethods->next; + } + + return ret; +} + +static NTSTATUS context_get_privilege_entry(struct pdb_context *context, const char *privname, char **sid_list) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + struct pdb_methods *curmethods; + if ((!context)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + curmethods = context->pdb_methods; + while (curmethods){ + if (NT_STATUS_IS_OK(ret = curmethods->get_privilege_entry(curmethods, privname, sid_list))) { + return ret; + } + curmethods = curmethods->next; + } + + return ret; +} + /****************************************************************** Free and cleanup a pdb context, any associated data and anything that the attached modules might have associated. @@ -711,6 +791,10 @@ static NTSTATUS make_pdb_context(struct pdb_context **context) (*context)->pdb_add_trust_passwd = context_add_trust_passwd; (*context)->pdb_update_trust_passwd = context_update_trust_passwd; (*context)->pdb_delete_trust_passwd = context_delete_trust_passwd; + (*context)->pdb_add_sid_to_privilege = context_add_sid_to_privilege; + (*context)->pdb_remove_sid_from_privilege = context_remove_sid_from_privilege; + (*context)->pdb_get_privilege_set = context_get_privilege_set; + (*context)->pdb_get_privilege_entry = context_get_privilege_entry; (*context)->free_fn = free_pdb_context; @@ -1072,6 +1156,54 @@ BOOL pdb_enum_alias_memberships(const DOM_SID *sid, aliases, num)); } +BOOL pdb_add_sid_to_privilege(char *priv_name, DOM_SID *sid) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context-> + pdb_add_sid_to_privilege(pdb_context, priv_name, sid)); +} + +BOOL pdb_remove_sid_from_privilege(char *priv_name, DOM_SID *sid) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context-> + pdb_remove_sid_from_privilege(pdb_context, priv_name, sid)); +} + +BOOL pdb_get_privilege_set(NT_USER_TOKEN *token, PRIVILEGE_SET *privset) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context-> + pdb_get_privilege_set(pdb_context, token, privset)); +} + +BOOL pdb_get_privilege_entry(const char *privname, char **sid_list) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context-> + pdb_get_privilege_entry(pdb_context, privname, sid_list)); +} + /*************************************************************** Initialize the static context (at smbd startup etc). @@ -1155,6 +1287,26 @@ static NTSTATUS pdb_default_delete_trust_passwd(struct pdb_methods *methods, con return NT_STATUS_NOT_IMPLEMENTED; } +static NTSTATUS pdb_default_add_sid_to_privilege(struct pdb_methods *methods, const char *priv_name, const DOM_SID *sid) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS pdb_default_remove_sid_from_privilege(struct pdb_methods *methods, const char *priv_name, const DOM_SID *sid) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS pdb_default_get_privilege_set(struct pdb_methods *methods, NT_USER_TOKEN *token, PRIVILEGE_SET *privset) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +static NTSTATUS pdb_default_get_privilege_entry(struct pdb_methods *methods, const char *privname, char **sid_list) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) { @@ -1193,5 +1345,10 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) (*methods)->update_trust_passwd = pdb_default_update_trust_passwd; (*methods)->delete_trust_passwd = pdb_default_delete_trust_passwd; + (*methods)->add_sid_to_privilege = pdb_default_add_sid_to_privilege; + (*methods)->remove_sid_from_privilege = pdb_default_remove_sid_from_privilege; + (*methods)->get_privilege_set = pdb_default_get_privilege_set; + (*methods)->get_privilege_entry = pdb_default_get_privilege_entry; + return NT_STATUS_OK; } diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index f54463e158..39de791b07 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -42,6 +42,7 @@ static int tdbsam_debug_level = DBGC_ALL; #define PASSDB_FILE_NAME "passdb.tdb" #define USERPREFIX "USER_" #define RIDPREFIX "RID_" +#define PRIVPREFIX "PRIV_" #define tdbsamver_t int32 struct tdbsam_privates { @@ -895,6 +896,354 @@ static NTSTATUS tdbsam_delete_trust_passwd(struct pdb_methods *methods, const SA } +/*************************************************************************** + Add sid to privilege +****************************************************************************/ + +static NTSTATUS tdbsam_add_sid_to_privilege(struct pdb_methods *my_methods, const char *priv_name, const DOM_SID *sid) +{ + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data; + TDB_CONTEXT *pwd_tdb = NULL; + TDB_DATA key, data; + fstring keystr; + fstring name; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + fstring sid_str; + char *sid_list = NULL, *s = NULL; + size_t str_size; + int flag; + + /* invalidate the existing TDB iterator if it is open */ + + if (tdb_state->passwd_tdb) { + tdb_close(tdb_state->passwd_tdb); + tdb_state->passwd_tdb = NULL; + } + + /* open the account TDB passwd*/ + + pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR | O_CREAT); + + if (!pwd_tdb) { + DEBUG(0, ("tdb_add_sid_to_privilege: Unable to open TDB passwd (%s)!\n", + tdb_state->tdbsam_location)); + return NT_STATUS_UNSUCCESSFUL; + } + + /* setup the PRIV index key */ + fstrcpy(name, priv_name); + strlower_m(name); + + slprintf(keystr, sizeof(keystr)-1, "%s%s", PRIVPREFIX, name); + key.dptr = keystr; + key.dsize = strlen(keystr) + 1; + + /* check if the privilege already exist in the database */ + + /* get the record */ + data = tdb_fetch (pwd_tdb, key); + + if (data.dptr) { + /* check the list is not empty */ + if (*(data.dptr)) { + sid_list = strdup(data.dptr); + if (!sid_list) { + DEBUG(0, ("tdbsam_add_sid_to_privilege: Out of Memory!\n")); + goto done; + } + } + SAFE_FREE(data.dptr); + + flag = TDB_MODIFY; + } else { + /* if privilege does not exist create one */ + flag = TDB_INSERT; + } + + /* add the given sid */ + sid_to_string(sid_str, sid); + + if (sid_list) { + str_size = strlen(sid_list) + strlen(sid_str) + 2; + s = realloc(sid_list, str_size); + if (!s) { + DEBUG(0, ("tdbsam_add_sid_to_privilege: Out of Memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + sid_list = s; + s = &sid_list[strlen(sid_list)]; + snprintf(s, strlen(sid_str) + 2, ",%s", sid_str); + + } else { + sid_list = strdup(sid_str); + if (!sid_list) { + DEBUG(0, ("tdbsam_add_sid_to_privilege: Out of Memory!\n")); + ret = NT_STATUS_NO_MEMORY; + goto done; + } + + } + + /* copy the PRIVILEGE struct into a BYTE buffer for storage */ + data.dsize = strlen(sid_list) + 1; + data.dptr = sid_list; + + /* add the account */ + if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) { + DEBUG(0, ("Unable to modify passwd TDB!")); + DEBUGADD(0, (" Error: %s", tdb_errorstr(pwd_tdb))); + DEBUGADD(0, (" occured while storing the main record (%s)\n", keystr)); + goto done; + } + + ret = NT_STATUS_OK; + +done: + /* cleanup */ + tdb_close (pwd_tdb); + SAFE_FREE(sid_list); + + return (ret); +} + +/*************************************************************************** + Reomve sid to privilege +****************************************************************************/ + +static NTSTATUS tdbsam_remove_sid_from_privilege(struct pdb_methods *my_methods, const char *priv_name, const DOM_SID *sid) +{ + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data; + TDB_CONTEXT *pwd_tdb = NULL; + TDB_DATA key, data; + fstring keystr; + fstring name; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + fstring sid_str; + char *sid_list = NULL, *s = NULL; + + /* invalidate the existing TDB iterator if it is open */ + + if (tdb_state->passwd_tdb) { + tdb_close(tdb_state->passwd_tdb); + tdb_state->passwd_tdb = NULL; + } + + /* open the account TDB passwd*/ + + pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDWR | O_CREAT); + + if (!pwd_tdb) { + DEBUG(0, ("tdbsam_remove_sid_from_privilege: Unable to open TDB passwd (%s)!\n", + tdb_state->tdbsam_location)); + return NT_STATUS_UNSUCCESSFUL; + } + + /* setup the PRIV index key */ + fstrcpy(name, priv_name); + strlower_m(name); + + slprintf(keystr, sizeof(keystr)-1, "%s%s", PRIVPREFIX, name); + key.dptr = keystr; + key.dsize = strlen(keystr) + 1; + + /* check if the privilege already exist in the database */ + + /* get the record */ + data = tdb_fetch (pwd_tdb, key); + + /* if privilege does not exist, just leave */ + if (!data.dptr) { + ret = NT_STATUS_OK; + goto done; + } + + if (data.dptr) { + sid_list = strdup(data.dptr); + if (!sid_list) { + DEBUG(0, ("tdbsam_remove_sid_from_privilege: Out of Memory!\n")); + goto done; + } + SAFE_FREE(data.dptr); + } + + /* remove the given sid */ + sid_to_string(sid_str, sid); + + s = strstr(sid_list, sid_str); + if (s) { + char *p; + p = strstr(s, ","); + if (p) { + size_t l = strlen(sid_list) + 1 - (s - sid_list); + memmove(s, ++p, l); + } else { + if (s != sid_list) + s--; + *s = '\0'; + } + } else { + /* sid not found */ + ret = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* copy the PRIVILEGE struct into a BYTE buffer for storage */ + data.dsize = strlen(sid_list) + 1; + data.dptr = sid_list; + + /* add the account */ + if (tdb_store(pwd_tdb, key, data, TDB_MODIFY) != TDB_SUCCESS) { + DEBUG(0, ("Unable to modify passwd TDB!")); + DEBUGADD(0, (" Error: %s", tdb_errorstr(pwd_tdb))); + DEBUGADD(0, (" occured while storing the main record (%s)\n", keystr)); + goto done; + } + + ret = NT_STATUS_OK; + +done: + /* cleanup */ + tdb_close (pwd_tdb); + SAFE_FREE(sid_list); + + return (ret); +} + +/*************************************************************************** + get the privilege list for the given token +****************************************************************************/ + +struct priv_traverse { + char **sid_list; + PRIVILEGE_SET *privset; +}; + +static int tdbsam_traverse_privilege(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state) +{ + struct priv_traverse *pt = (struct priv_traverse *)state; + int prefixlen = strlen(PRIVPREFIX); + + if (strncmp(key.dptr, PRIVPREFIX, prefixlen) == 0) { + + /* add to privilege_set if any of the sid in the token + * is contained in the privilege */ + int i; + + for(i=0; pt->sid_list[i] != NULL; i++) { + char *c, *s; + int len; + + s = data.dptr; + while (c = strchr(s, ',')) { + len = MAX((c - s), strlen(pt->sid_list[i])); + if (strncmp(s, pt->sid_list[i], len) == 0) { + DEBUG(10, ("sid [%s] found in users sid list\n", pt->sid_list[i])); + DEBUG(10, ("adding privilege [%s] to the users privilege list\n", &(key.dptr[prefixlen]))); + add_privilege_by_name(pt->privset, &(key.dptr[prefixlen])); + return 0; + } + s = c + 1; + } + len = MAX(strlen(s), strlen(pt->sid_list[i])); + if (strncmp(s, pt->sid_list[i], len) == 0) { + DEBUG(10, ("sid [%s] found in users sid list\n", pt->sid_list[i])); + DEBUG(10, ("adding privilege [%s] to the users privilege list\n", &(key.dptr[prefixlen]))); + add_privilege_by_name(pt->privset, &(key.dptr[prefixlen])); + return 0; + } + } + } + + return 0; +} + +static NTSTATUS tdbsam_get_privilege_set(struct pdb_methods *my_methods, NT_USER_TOKEN *token, PRIVILEGE_SET *privset) +{ + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + TDB_CONTEXT *pwd_tdb = NULL; + struct priv_traverse pt; + fstring sid_str; + char **sid_list; + int i; + + if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY ))) + return NT_STATUS_UNSUCCESSFUL; + + sid_list = (char **)malloc(sizeof(char *) * (token->num_sids + 1)); + for (i = 0; i < token->num_sids; i++) { + sid_to_string(sid_str, &token->user_sids[i]); + sid_list[i] = strdup(sid_str); + if ( ! sid_list[i]) { + ret = NT_STATUS_NO_MEMORY; + goto done; + } + } + sid_list[i] = NULL; + + pt.sid_list = sid_list; + pt.privset = privset; + tdb_traverse(pwd_tdb, tdbsam_traverse_privilege, &pt); + + ret = NT_STATUS_OK; + +done: + i = 0; + while (sid_list[i]) { + free(sid_list[i]); + i++; + } + free(sid_list); + + tdb_close(pwd_tdb); + + return ret; +} + +static NTSTATUS tdbsam_get_privilege_entry(struct pdb_methods *my_methods, const char *privname, char **sid_list) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + TDB_CONTEXT *pwd_tdb = NULL; + TDB_DATA key, data; + fstring name; + fstring keystr; + + struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data; + + if (!(pwd_tdb = tdbsam_tdbopen(tdb_state->tdbsam_location, O_RDONLY))) + return ret; + + /* setup the PRIV index key */ + fstrcpy(name, privname); + strlower_m(name); + + slprintf(keystr, sizeof(keystr)-1, "%s%s", PRIVPREFIX, name); + key.dptr = keystr; + key.dsize = strlen(keystr) + 1; + + data = tdb_fetch(pwd_tdb, key); + if (!data.dptr) + goto done; + + *sid_list = strdup(data.dptr); + SAFE_FREE(data.dptr); + + if (!*sid_list) + goto done; + + ret = NT_STATUS_OK; +done: + tdb_close(pwd_tdb); + return ret; +} + + + + + + + static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) { NTSTATUS nt_status; @@ -919,6 +1268,10 @@ static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_meth (*pdb_method)->add_trust_passwd = tdbsam_add_trust_passwd; (*pdb_method)->update_trust_passwd = tdbsam_update_trust_passwd; (*pdb_method)->delete_trust_passwd = tdbsam_delete_trust_passwd; + (*pdb_method)->add_sid_to_privilege = tdbsam_add_sid_to_privilege; + (*pdb_method)->remove_sid_from_privilege = tdbsam_remove_sid_from_privilege; + (*pdb_method)->get_privilege_set = tdbsam_get_privilege_set; + (*pdb_method)->get_privilege_entry = tdbsam_get_privilege_entry; tdb_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct tdbsam_privates)); diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index aa933f9d0d..1e3c6c2a9d 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -819,10 +819,10 @@ NTSTATUS _lsa_priv_get_dispname(pipes_struct *p, LSA_Q_PRIV_GET_DISPNAME *q_u, L DEBUG(10,("_lsa_priv_get_dispname: %s", name_asc)); - while (privs[i].se_priv!=SE_PRIV_ALL && strcmp(name_asc, privs[i].priv)) + while (privs[i].se_priv!=SE_ALL_PRIVS && strcmp(name_asc, privs[i].priv)) i++; - if (privs[i].se_priv!=SE_PRIV_ALL) { + if (privs[i].se_priv!=SE_ALL_PRIVS) { DEBUG(10,(": %s\n", privs[i].description)); init_unistr2(&r_u->desc, privs[i].description, UNI_FLAGS_NONE); init_uni_hdr(&r_u->hdr_desc, &r_u->desc); diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 514c22d471..64ca8388d7 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -344,6 +344,8 @@ static void *make_internal_rpc_pipe_p(char *pipe_name, if (vuser) { p->session_key = data_blob(vuser->session_key.data, vuser->session_key.length); p->pipe_user.nt_user_token = dup_nt_token(vuser->nt_user_token); + init_privilege(&p->pipe_user.privs); + dup_priv_set(p->pipe_user.privs, vuser->privs); } /* diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index b50d44d9e3..1959674f0a 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -40,6 +40,7 @@ extern rid_name domain_group_rids[]; extern rid_name domain_alias_rids[]; extern rid_name builtin_alias_rids[]; +extern PRIVS privs[]; typedef struct _disp_info { BOOL user_dbloaded; @@ -2137,7 +2138,15 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA return NT_STATUS_INVALID_HANDLE; if (!NT_STATUS_IS_OK(nt_status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_CREATE_USER, "_samr_create_user"))) { - return nt_status; + if (NT_STATUS_IS_OK(user_has_privilege(&(p->pipe_user), SE_MACHINE_ACCOUNT))) { + DEBUG(3, ("_samr_create_user: User should be denied access but was overridden by %s\n", privs[SE_MACHINE_ACCOUNT].priv)); + } else { + if (NT_STATUS_IS_OK(user_has_privilege(&(p->pipe_user), SE_ADD_USERS))) { + DEBUG(3, ("_samr_create_user: User should be denied access but was overridden by %s\n", privs[SE_ADD_USERS].priv)); + } else { + return nt_status; + } + } } if (!(acb_info == ACB_NORMAL || acb_info == ACB_DOMTRUST || acb_info == ACB_WSTRUST || acb_info == ACB_SVRTRUST)) { @@ -2200,6 +2209,33 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA /* the passdb lookup has failed; check to see if we need to run the add user/machine script */ + + /* + * we can't check both the ending $ and the acb_info. + * + * UserManager creates trust accounts (ending in $, + * normal that hidden accounts) with the acb_info equals to ACB_NORMAL. + * JFM, 11/29/2001 + */ + if (account[strlen(account)-1] == '$') { + if (NT_STATUS_IS_OK(user_has_privilege(&(p->pipe_user), SE_MACHINE_ACCOUNT)) || geteuid() == 0) { + DEBUG(3, ("user [%s] has been granted Add Machines privilege!\n", p->user_name)); + become_root(); + pstrcpy(add_script, lp_addmachine_script()); + } else { + DEBUG(3, ("user [%s] doesn't have Add Machines privilege!\n", p->user_name)); + return NT_STATUS_ACCESS_DENIED; + } + } else { + if (NT_STATUS_IS_OK(user_has_privilege(&(p->pipe_user), SE_ADD_USERS)) || geteuid() == 0) { + DEBUG(3, ("user [%s] has been granted Add Users privilege!\n", p->user_name)); + become_root(); + pstrcpy(add_script, lp_adduser_script()); + } else { + DEBUG(3, ("user [%s] doesn't have Add Users privilege!\n", p->user_name)); + return NT_STATUS_ACCESS_DENIED; + } + } pw = Get_Pwnam(account); @@ -2215,17 +2251,6 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA *********************************************************************/ if ( !pw ) { - /* - * we can't check both the ending $ and the acb_info. - * - * UserManager creates trust accounts (ending in $, - * normal that hidden accounts) with the acb_info equals to ACB_NORMAL. - * JFM, 11/29/2001 - */ - if (account[strlen(account)-1] == '$') - pstrcpy(add_script, lp_addmachine_script()); - else - pstrcpy(add_script, lp_adduser_script()); if (*add_script) { int add_ret; @@ -2235,7 +2260,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA } else /* no add user script -- ask winbindd to do it */ { - if ( !winbind_create_user( account, &new_rid ) ) { + if (!winbind_create_user(account, &new_rid)) { DEBUG(3,("_samr_create_user: winbind_create_user(%s) failed\n", account)); } @@ -2246,15 +2271,16 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA /* implicit call to getpwnam() next. we have a valid SID coming out of this call */ if ( !NT_STATUS_IS_OK(nt_status = pdb_init_sam_new(&sam_pass, account, new_rid)) ) - return nt_status; + goto done; pdb_set_acct_ctrl(sam_pass, acb_info, PDB_CHANGED); if (!pdb_add_sam_account(sam_pass)) { pdb_free_sam(&sam_pass); - DEBUG(0, ("could not add user/computer %s to passdb. Check permissions?\n", + DEBUG(0, ("could not add user/computer %s to passdb !?\n", account)); - return NT_STATUS_ACCESS_DENIED; + nt_status = NT_STATUS_ACCESS_DENIED; + goto done; } /* Get the user's SID */ @@ -2265,13 +2291,14 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA if (!NT_STATUS_IS_OK(nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, "_samr_create_user"))) { - return nt_status; + goto done; } /* associate the user's SID with the new handle. */ if ((info = get_samr_info_by_sid(&sid)) == NULL) { pdb_free_sam(&sam_pass); - return NT_STATUS_NO_MEMORY; + nt_status = NT_STATUS_NO_MEMORY; + goto done; } ZERO_STRUCTP(info); @@ -2281,7 +2308,8 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA /* get a (unique) handle. open a policy on it. */ if (!create_policy_hnd(p, user_pol, free_samr_info, (void *)info)) { pdb_free_sam(&sam_pass); - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + goto done; } r_u->user_rid=pdb_get_user_rid(sam_pass); @@ -2290,7 +2318,11 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA pdb_free_sam(&sam_pass); - return NT_STATUS_OK; + nt_status = NT_STATUS_OK; + +done: + unbecome_root(); + return nt_status; } /******************************************************************* diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index 40d3a43bef..7487e106bc 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -1405,10 +1405,7 @@ WERROR _srv_net_share_get_info(pipes_struct *p, SRV_Q_NET_SHARE_GET_INFO *q_u, S static char *valid_share_pathname(char *dos_pathname) { - pstring saved_pathname; - pstring unix_pathname; char *ptr; - int ret; /* Convert any '\' paths to '/' */ unix_format(dos_pathname); @@ -1423,21 +1420,29 @@ static char *valid_share_pathname(char *dos_pathname) if (*ptr != '/') return NULL; + return ptr; +} + +static BOOL exist_share_pathname(char *unix_pathname) +{ + pstring saved_pathname; + int ret; + /* Can we cd to it ? */ /* First save our current directory. */ if (getcwd(saved_pathname, sizeof(saved_pathname)) == NULL) return False; - pstrcpy(unix_pathname, ptr); - ret = chdir(unix_pathname); /* We *MUST* be able to chdir back. Abort if we can't. */ if (chdir(saved_pathname) == -1) smb_panic("valid_share_pathname: Unable to restore current directory.\n"); - return (ret != -1) ? ptr : NULL; + if (ret == -1) return False; + + return True; } /******************************************************************* @@ -1454,7 +1459,7 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S int type; int snum; int ret; - char *ptr; + char *path; SEC_DESC *psd = NULL; DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__)); @@ -1549,12 +1554,12 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S return WERR_ACCESS_DENIED; /* Check if the pathname is valid. */ - if (!(ptr = valid_share_pathname( pathname ))) + if (!(path = valid_share_pathname( pathname ))) return WERR_OBJECT_PATH_INVALID; /* Ensure share name, pathname and comment don't contain '"' characters. */ string_replace(share_name, '"', ' '); - string_replace(ptr, '"', ' '); + string_replace(path, '"', ' '); string_replace(comment, '"', ' '); DEBUG(10,("_srv_net_share_set_info: change share command = %s\n", @@ -1562,12 +1567,12 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S /* Only call modify function if something changed. */ - if (strcmp(ptr, lp_pathname(snum)) || strcmp(comment, lp_comment(snum)) ) { + if (strcmp(path, lp_pathname(snum)) || strcmp(comment, lp_comment(snum)) ) { if (!lp_change_share_cmd() || !*lp_change_share_cmd()) return WERR_ACCESS_DENIED; slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\"", - lp_change_share_cmd(), dyn_CONFIGFILE, share_name, ptr, comment); + lp_change_share_cmd(), dyn_CONFIGFILE, share_name, path, comment); DEBUG(10,("_srv_net_share_set_info: Running [%s]\n", command )); if ((ret = smbrun(command, NULL)) != 0) { @@ -1575,6 +1580,12 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S return WERR_ACCESS_DENIED; } + /* Check if the new share pathname exist, if not return an error */ + if (!exist_share_pathname(path)) { + DEBUG(1, ("_srv_net_share_set_info: change share command was ok but path (%s) has not been created!\n", path)); + return WERR_OBJECT_PATH_INVALID; + } + /* Tell everyone we updated smb.conf. */ message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL); @@ -1615,7 +1626,7 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S int type; int snum; int ret; - char *ptr; + char *path; SEC_DESC *psd = NULL; DEBUG(5,("_srv_net_share_add: %d\n", __LINE__)); @@ -1689,16 +1700,16 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S return WERR_ACCESS_DENIED; /* Check if the pathname is valid. */ - if (!(ptr = valid_share_pathname( pathname ))) + if (!(path = valid_share_pathname( pathname ))) return WERR_OBJECT_PATH_INVALID; /* Ensure share name, pathname and comment don't contain '"' characters. */ string_replace(share_name, '"', ' '); - string_replace(ptr, '"', ' '); + string_replace(path, '"', ' '); string_replace(comment, '"', ' '); slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\"", - lp_add_share_cmd(), dyn_CONFIGFILE, share_name, ptr, comment); + lp_add_share_cmd(), dyn_CONFIGFILE, share_name, path, comment); DEBUG(10,("_srv_net_share_add: Running [%s]\n", command )); if ((ret = smbrun(command, NULL)) != 0) { @@ -1706,10 +1717,33 @@ WERROR _srv_net_share_add(pipes_struct *p, SRV_Q_NET_SHARE_ADD *q_u, SRV_R_NET_S return WERR_ACCESS_DENIED; } + /* Check if the new share pathname exist, if not try to delete the + * share and return an error */ + if (!exist_share_pathname(path)) { + DEBUG(1, ("_srv_net_share_add: add share command was ok but path (%s) has not been created!\n", path)); + DEBUG(1, ("_srv_net_share_add: trying to rollback and delete the share\n")); + + if (!lp_delete_share_cmd() || !*lp_delete_share_cmd()) { + DEBUG(1, ("_srv_net_share_add: Error! delete share command is not defined! Please check share (%s) in the config file\n", share_name)); + return WERR_OBJECT_PATH_INVALID; + } + + slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", + lp_delete_share_cmd(), dyn_CONFIGFILE, share_name); + + DEBUG(10,("_srv_net_share_add: Running [%s]\n", command )); + if ((ret = smbrun(command, NULL)) != 0) { + DEBUG(0,("_srv_net_share_add: Running [%s] returned (%d)\n", command, ret )); + DEBUG(1, ("_srv_net_share_add: Error! delete share command failed! Please check share (%s) in the config file\n", share_name)); + } + + return WERR_OBJECT_PATH_INVALID; + } + if (psd) { - if (!set_share_security(p->mem_ctx, share_name, psd)) - DEBUG(0,("_srv_net_share_add: Failed to add security info to share %s.\n", - share_name )); + if (!set_share_security(p->mem_ctx, share_name, psd)) { + DEBUG(0,("_srv_net_share_add: Failed to add security info to share %s.\n", share_name )); + } } /* Tell everyone we updated smb.conf. */ diff --git a/source3/sam/gums.c b/source3/sam/gums.c index 91009f8b5d..b719153584 100644 --- a/source3/sam/gums.c +++ b/source3/sam/gums.c @@ -26,71 +26,8 @@ #define GMV_MAJOR 0 #define GMV_MINOR 1 -#define PRIV_NONE 0 -#define PRIV_CREATE_TOKEN 1 -#define PRIV_ASSIGNPRIMARYTOKEN 2 -#define PRIV_LOCK_MEMORY 3 -#define PRIV_INCREASE_QUOTA 4 -#define PRIV_MACHINE_ACCOUNT 5 -#define PRIV_TCB 6 -#define PRIV_SECURITY 7 -#define PRIV_TAKE_OWNERSHIP 8 -#define PRIV_LOAD_DRIVER 9 -#define PRIV_SYSTEM_PROFILE 10 -#define PRIV_SYSTEMTIME 11 -#define PRIV_PROF_SINGLE_PROCESS 12 -#define PRIV_INC_BASE_PRIORITY 13 -#define PRIV_CREATE_PAGEFILE 14 -#define PRIV_CREATE_PERMANENT 15 -#define PRIV_BACKUP 16 -#define PRIV_RESTORE 17 -#define PRIV_SHUTDOWN 18 -#define PRIV_DEBUG 19 -#define PRIV_AUDIT 20 -#define PRIV_SYSTEM_ENVIRONMENT 21 -#define PRIV_CHANGE_NOTIFY 22 -#define PRIV_REMOTE_SHUTDOWN 23 -#define PRIV_UNDOCK 24 -#define PRIV_SYNC_AGENT 25 -#define PRIV_ENABLE_DELEGATION 26 -#define PRIV_ALL 255 - - static GUMS_FUNCTIONS *gums_backend = NULL; -#if 0 -static PRIVS gums_privs[] = { - {PRIV_NONE, "no_privs", "No privilege"}, /* this one MUST be first */ - {PRIV_CREATE_TOKEN, "SeCreateToken", "Create Token"}, - {PRIV_ASSIGNPRIMARYTOKEN, "SeAssignPrimaryToken", "Assign Primary Token"}, - {PRIV_LOCK_MEMORY, "SeLockMemory", "Lock Memory"}, - {PRIV_INCREASE_QUOTA, "SeIncreaseQuotaPrivilege", "Increase Quota Privilege"}, - {PRIV_MACHINE_ACCOUNT, "SeMachineAccount", "Machine Account"}, - {PRIV_TCB, "SeTCB", "TCB"}, - {PRIV_SECURITY, "SeSecurityPrivilege", "Security Privilege"}, - {PRIV_TAKE_OWNERSHIP, "SeTakeOwnershipPrivilege", "Take Ownership Privilege"}, - {PRIV_LOAD_DRIVER, "SeLocalDriverPrivilege", "Local Driver Privilege"}, - {PRIV_SYSTEM_PROFILE, "SeSystemProfilePrivilege", "System Profile Privilege"}, - {PRIV_SYSTEMTIME, "SeSystemtimePrivilege", "System Time"}, - {PRIV_PROF_SINGLE_PROCESS, "SeProfileSingleProcessPrivilege", "Profile Single Process Privilege"}, - {PRIV_INC_BASE_PRIORITY, "SeIncreaseBasePriorityPrivilege", "Increase Base Priority Privilege"}, - {PRIV_CREATE_PAGEFILE, "SeCreatePagefilePrivilege", "Create Pagefile Privilege"}, - {PRIV_CREATE_PERMANENT, "SeCreatePermanent", "Create Permanent"}, - {PRIV_BACKUP, "SeBackupPrivilege", "Backup Privilege"}, - {PRIV_RESTORE, "SeRestorePrivilege", "Restore Privilege"}, - {PRIV_SHUTDOWN, "SeShutdownPrivilege", "Shutdown Privilege"}, - {PRIV_DEBUG, "SeDebugPrivilege", "Debug Privilege"}, - {PRIV_AUDIT, "SeAudit", "Audit"}, - {PRIV_SYSTEM_ENVIRONMENT, "SeSystemEnvironmentPrivilege", "System Environment Privilege"}, - {PRIV_CHANGE_NOTIFY, "SeChangeNotify", "Change Notify"}, - {PRIV_REMOTE_SHUTDOWN, "SeRemoteShutdownPrivilege", "Remote Shutdown Privilege"}, - {PRIV_UNDOCK, "SeUndock", "Undock"}, - {PRIV_SYNC_AGENT, "SeSynchronizationAgent", "Synchronization Agent"}, - {PRIV_ENABLE_DELEGATION, "SeEnableDelegation", "Enable Delegation"}, - {PRIV_ALL, "SaAllPrivs", "All Privileges"} -}; -#endif - static struct gums_init_function_entry *backends = NULL; static void lazy_initialize_gums(void) diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index e3df8a11d0..8e4df1a464 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -991,7 +991,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw if (!push_sec_ctx()) return NT_STATUS_UNSUCCESSFUL; - set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL); + set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL, NULL); set_re_uid(); } diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 9bac0acdb9..0805f8e690 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -249,6 +249,14 @@ void conn_free(connection_struct *conn) conn->ngroups = 0; } + if (conn->nt_user_token) { + delete_nt_token(&(conn->nt_user_token)); + } + + if (conn->privs) { + destroy_privilege(&(conn->privs)); + } + free_namearray(conn->veto_list); free_namearray(conn->hide_list); free_namearray(conn->veto_oplock_list); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 10c6aadb1f..8438f2a593 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -87,6 +87,7 @@ void invalidate_vuid(uint16 vuid) SAFE_FREE(vuser->groups); delete_nt_token(&vuser->nt_user_token); + destroy_privilege(&vuser->privs); SAFE_FREE(vuser); num_validated_vuids--; } @@ -234,6 +235,11 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, return UID_FIELD_INVALID; } + if (server_info->privs) { + init_privilege(&(vuser->privs)); + dup_priv_set(vuser->privs, server_info->privs); + } + /* use this to keep tabs on all our info from the authentication */ vuser->server_info = server_info; diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 8a85792ead..9244f34394 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -28,6 +28,7 @@ struct sec_ctx { int ngroups; gid_t *groups; NT_USER_TOKEN *token; + PRIVILEGE_SET *privs; }; /* A stack of security contexts. We include the current context as being @@ -256,6 +257,10 @@ BOOL push_sec_ctx(void) (unsigned int)ctx_p->uid, (unsigned int)ctx_p->gid, sec_ctx_stack_ndx )); ctx_p->token = dup_nt_token(sec_ctx_stack[sec_ctx_stack_ndx-1].token); + if (! ctx_p->token) { + DEBUG(0, ("Out of memory in push_sec_ctx()\n")); + return False; + } ctx_p->ngroups = sys_getgroups(0, NULL); @@ -271,6 +276,14 @@ BOOL push_sec_ctx(void) ctx_p->groups = NULL; } + init_privilege(&ctx_p->privs); + if (! NT_STATUS_IS_OK(dup_priv_set(ctx_p->privs, sec_ctx_stack[sec_ctx_stack_ndx-1].privs))) { + DEBUG(0, ("Out of memory in push_sec_ctx()\n")); + delete_nt_token(&ctx_p->token); + destroy_privilege(&ctx_p->privs); + return False; + } + return True; } @@ -278,7 +291,7 @@ BOOL push_sec_ctx(void) Set the current security context to a given user. ****************************************************************************/ -void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN *token) +void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN *token, PRIVILEGE_SET *privs) { struct sec_ctx *ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; @@ -303,9 +316,14 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN smb_panic("DUPLICATE_TOKEN"); delete_nt_token(&ctx_p->token); + if (ctx_p->privs) + reset_privilege(ctx_p->privs); + else + init_privilege(&ctx_p->privs); ctx_p->groups = memdup(groups, sizeof(gid_t) * ngroups); ctx_p->token = dup_nt_token(token); + dup_priv_set(ctx_p->privs, privs); become_id(uid, gid); @@ -319,6 +337,7 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN current_user.ngroups = ngroups; current_user.groups = groups; current_user.nt_user_token = ctx_p->token; + current_user.privs = ctx_p->privs; } /**************************************************************************** @@ -329,7 +348,7 @@ void set_root_sec_ctx(void) { /* May need to worry about supplementary groups at some stage */ - set_sec_ctx(0, 0, 0, NULL, NULL); + set_sec_ctx(0, 0, 0, NULL, NULL, NULL); } /**************************************************************************** @@ -359,6 +378,7 @@ BOOL pop_sec_ctx(void) ctx_p->ngroups = 0; delete_nt_token(&ctx_p->token); + destroy_privilege(&ctx_p->privs); /* Pop back previous user */ @@ -381,6 +401,7 @@ BOOL pop_sec_ctx(void) current_user.ngroups = prev_ctx_p->ngroups; current_user.groups = prev_ctx_p->groups; current_user.nt_user_token = prev_ctx_p->token; + current_user.privs = prev_ctx_p->privs; DEBUG(3, ("pop_sec_ctx (%u, %u) - sec_ctx_stack_ndx = %d\n", (unsigned int)geteuid(), (unsigned int)getegid(), sec_ctx_stack_ndx)); @@ -413,6 +434,7 @@ void init_sec_ctx(void) get_current_groups(ctx_p->gid, &ctx_p->ngroups, &ctx_p->groups); ctx_p->token = NULL; /* Maps to guest user. */ + ctx_p->privs = NULL; /* Initialise current_user global */ @@ -427,4 +449,5 @@ void init_sec_ctx(void) current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; current_user.nt_user_token = NULL; + current_user.privs = NULL; } diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 78b610ae37..caa2872f04 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -371,6 +371,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, string_set(&conn->dirpath,""); string_set(&conn->user,user); conn->nt_user_token = NULL; + conn->privs = NULL; conn->read_only = lp_readonly(conn->service); conn->admin_user = False; @@ -479,6 +480,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, conn->nt_user_token = create_nt_token(conn->uid, conn->gid, conn->ngroups, conn->groups, guest); + + init_privilege(&(conn->privs)); + pdb_get_privilege_set(conn->nt_user_token, conn->privs); } /* diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 3859298055..d43bf301e8 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -44,7 +44,7 @@ BOOL change_to_guest(void) initgroups(pass->pw_name, pass->pw_gid); #endif - set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL); + set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL, NULL); current_user.conn = NULL; current_user.vuid = UID_FIELD_INVALID; @@ -161,8 +161,9 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) gid_t gid; uid_t uid; char group_c; - BOOL must_free_token = False; + BOOL must_free_token_priv = False; NT_USER_TOKEN *token = NULL; + PRIVILEGE_SET *privs = NULL; if (!conn) { DEBUG(2,("change_to_user: Connection not open\n")); @@ -195,12 +196,14 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) current_user.groups = conn->groups; current_user.ngroups = conn->ngroups; token = conn->nt_user_token; + privs = conn->privs; } else if ((vuser) && check_user_ok(conn, vuser, snum)) { uid = conn->admin_user ? 0 : vuser->uid; gid = vuser->gid; current_user.ngroups = vuser->n_groups; current_user.groups = vuser->groups; token = vuser->nt_user_token; + privs = vuser->privs; } else { DEBUG(2,("change_to_user: Invalid vuid used %d or vuid not permitted access to share.\n",vuid)); return False; @@ -248,17 +251,20 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid) DEBUG(1, ("change_to_user: create_nt_token failed!\n")); return False; } - must_free_token = True; + pdb_get_privilege_set(token, privs); + must_free_token_priv = True; } - set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups, token); + set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups, token, privs); /* * Free the new token (as set_sec_ctx copies it). */ - if (must_free_token) + if (must_free_token_priv) { delete_nt_token(&token); + destroy_privilege(&privs); + } current_user.conn = conn; current_user.vuid = vuid; @@ -299,7 +305,7 @@ BOOL become_authenticated_pipe_user(pipes_struct *p) return False; set_sec_ctx(p->pipe_user.uid, p->pipe_user.gid, - p->pipe_user.ngroups, p->pipe_user.groups, p->pipe_user.nt_user_token); + p->pipe_user.ngroups, p->pipe_user.groups, p->pipe_user.nt_user_token, p->pipe_user.privs); return True; } diff --git a/source3/utils/net.c b/source3/utils/net.c index 8004ced43e..fcc8b4abe1 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -648,6 +648,7 @@ static struct functable net_func[] = { #ifdef WITH_FAKE_KASERVER {"AFSKEY", net_afskey}, #endif + {"PRIV", net_priv}, {"HELP", net_help}, {NULL, NULL} |