summaryrefslogtreecommitdiff
path: root/source3/rpc_server
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2004-03-01 16:10:28 +0000
committerSimo Sorce <idra@samba.org>2004-03-01 16:10:28 +0000
commiteebc94d84af736bb1fdd8e0c511237b0da978e7a (patch)
tree3d39c50ac039a7fc56d677b90e60421f7d6fc878 /source3/rpc_server
parentf986f33aa13f8672e2154f29906f657c023777dc (diff)
downloadsamba-eebc94d84af736bb1fdd8e0c511237b0da978e7a.tar.gz
samba-eebc94d84af736bb1fdd8e0c511237b0da978e7a.tar.bz2
samba-eebc94d84af736bb1fdd8e0c511237b0da978e7a.zip
Ok here it is my latest work on privileges
This patch add privilege support for samba Currently it is implemented only for tdbsam backend but estending it to other sam backends is straightforward. I must make a big thank to JFM for his teachings on the matter and the functions at the base of this work. At thye moment only samr_create_user honours SeAddUsersPrivilege and SeMachineAccountPrivilege to permit any user to add machines and/or users to the server. The command "net priv" has been provided to manipulate the privileges database. There are still many things to do (like support in "net rpc vampire") but the working core is here. Feel free to comment/extend on this work. Of course I will deny that any bug may affect this code :-) Simo. This patch adds also my patch about add share command enhancements. (This used to be commit 7a78c3605e203bd8e0d7ae244605f076a5d0b0bc)
Diffstat (limited to 'source3/rpc_server')
-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
4 files changed, 108 insertions, 40 deletions
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. */