diff options
author | Simo Sorce <idra@samba.org> | 2004-03-01 16:10:28 +0000 |
---|---|---|
committer | Simo Sorce <idra@samba.org> | 2004-03-01 16:10:28 +0000 |
commit | eebc94d84af736bb1fdd8e0c511237b0da978e7a (patch) | |
tree | 3d39c50ac039a7fc56d677b90e60421f7d6fc878 /source3/rpc_server | |
parent | f986f33aa13f8672e2154f29906f657c023777dc (diff) | |
download | samba-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.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 |
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. */ |