diff options
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. */ |