summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/Makefile.in2
-rw-r--r--source3/auth/auth_util.c22
-rw-r--r--source3/groupdb/mapping.c11
-rw-r--r--source3/include/auth.h1
-rw-r--r--source3/include/includes.h4
-rw-r--r--source3/include/passdb.h20
-rw-r--r--source3/include/privileges.h47
-rw-r--r--source3/include/smb.h3
-rw-r--r--source3/lib/privileges.c79
-rw-r--r--source3/param/loadparm.c2
-rw-r--r--source3/passdb/pdb_interface.c157
-rw-r--r--source3/passdb/pdb_tdb.c353
-rw-r--r--source3/rpc_server/srv_lsa_nt.c4
-rw-r--r--source3/rpc_server/srv_pipe_hnd.c2
-rw-r--r--source3/rpc_server/srv_samr_nt.c72
-rw-r--r--source3/rpc_server/srv_srvsvc_nt.c70
-rw-r--r--source3/sam/gums.c63
-rw-r--r--source3/smbd/chgpasswd.c2
-rw-r--r--source3/smbd/conn.c8
-rw-r--r--source3/smbd/password.c6
-rw-r--r--source3/smbd/sec_ctx.c27
-rw-r--r--source3/smbd/service.c4
-rw-r--r--source3/smbd/uid.c18
-rw-r--r--source3/utils/net.c1
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}