summaryrefslogtreecommitdiff
path: root/source3/rpc_server
diff options
context:
space:
mode:
authorVolker Lendecke <vlendec@samba.org>2005-12-03 18:34:13 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:05:43 -0500
commit05ac2de0df78d22ad5afb42ea5c72ba17bef8395 (patch)
treef4968eaab779b3f09dfac41e34f6088f32c38463 /source3/rpc_server
parent678f13c761bea7b4dc4b96c4c1a7d65ee143181c (diff)
downloadsamba-05ac2de0df78d22ad5afb42ea5c72ba17bef8395.tar.gz
samba-05ac2de0df78d22ad5afb42ea5c72ba17bef8395.tar.bz2
samba-05ac2de0df78d22ad5afb42ea5c72ba17bef8395.zip
r12051: Merge across the lookup_name and lookup_sid work. Lets see how the build farm
reacts :-) Volker (This used to be commit 9f99d04a54588cd9d1a1ab163ebb304437f932f7)
Diffstat (limited to 'source3/rpc_server')
-rw-r--r--source3/rpc_server/srv_lsa_nt.c123
-rw-r--r--source3/rpc_server/srv_samr_nt.c144
2 files changed, 153 insertions, 114 deletions
diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c
index b56ae10914..78e9cd6211 100644
--- a/source3/rpc_server/srv_lsa_nt.c
+++ b/source3/rpc_server/srv_lsa_nt.c
@@ -135,67 +135,75 @@ static int init_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid)
init_lsa_rid2s
***************************************************************************/
-static void init_lsa_rid2s(DOM_R_REF *ref, DOM_RID2 *rid2,
- int num_entries, UNISTR2 *name,
- uint32 *mapped_count, BOOL endian)
+static int init_lsa_rid2s(TALLOC_CTX *mem_ctx,
+ DOM_R_REF *ref, DOM_RID2 *rid2,
+ int num_entries, UNISTR2 *name,
+ int flags)
{
- int i;
- int total = 0;
- *mapped_count = 0;
+ int mapped_count, i;
SMB_ASSERT(num_entries <= MAX_LOOKUP_SIDS);
+ mapped_count = 0;
+
become_root(); /* lookup_name can require root privs */
for (i = 0; i < num_entries; i++) {
BOOL status = False;
DOM_SID sid;
- uint32 rid = 0xffffffff;
- int dom_idx = -1;
- pstring full_name;
- fstring dom_name, user;
- enum SID_NAME_USE name_type = SID_NAME_UNKNOWN;
+ uint32 rid;
+ int dom_idx;
+ char *full_name, *domain;
+ enum SID_NAME_USE type = SID_NAME_UNKNOWN;
/* Split name into domain and user component */
- unistr2_to_ascii(full_name, &name[i], sizeof(full_name));
- split_domain_name(full_name, dom_name, user);
-
- /* Lookup name */
+ if (rpcstr_pull_unistr2_talloc(mem_ctx, &full_name,
+ &name[i]) < 0) {
+ DEBUG(0, ("pull_ucs2_talloc failed\n"));
+ return 0;
+ }
DEBUG(5, ("init_lsa_rid2s: looking up name %s\n", full_name));
- status = lookup_name(dom_name, user, &sid, &name_type);
-
- if((name_type == SID_NAME_UNKNOWN) && (lp_server_role() == ROLE_DOMAIN_MEMBER) && (strncmp(dom_name, full_name, strlen(dom_name)) != 0)) {
- DEBUG(5, ("init_lsa_rid2s: domain name not provided and local account not found, using member domain\n"));
- fstrcpy(dom_name, lp_workgroup());
- status = lookup_name(dom_name, user, &sid, &name_type);
- }
+ /* We can ignore the result of lookup_name, it will not touch
+ "type" if it's not successful */
- if (name_type == SID_NAME_WKN_GRP) {
- /* BUILTIN aliases are still aliases :-) */
- name_type = SID_NAME_ALIAS;
- }
+ lookup_name(mem_ctx, full_name, flags, &domain, NULL,
+ &sid, &type);
DEBUG(5, ("init_lsa_rid2s: %s\n", status ? "found" :
"not found"));
- if (status && name_type != SID_NAME_UNKNOWN) {
+ switch (type) {
+ case SID_NAME_USER:
+ case SID_NAME_DOM_GRP:
+ case SID_NAME_DOMAIN:
+ case SID_NAME_ALIAS:
+ case SID_NAME_WKN_GRP:
+ /* Leave these unchanged */
+ break;
+ default:
+ /* Don't hand out anything but the list above */
+ type = SID_NAME_UNKNOWN;
+ break;
+ }
+
+ rid = 0;
+ dom_idx = -1;
+
+ if (type != SID_NAME_UNKNOWN) {
sid_split_rid(&sid, &rid);
- dom_idx = init_dom_ref(ref, dom_name, &sid);
- (*mapped_count)++;
- } else {
- dom_idx = -1;
- rid = 0;
- name_type = SID_NAME_UNKNOWN;
+ dom_idx = init_dom_ref(ref, domain, &sid);
+ mapped_count++;
}
- init_dom_rid2(&rid2[total], rid, name_type, dom_idx);
- total++;
+ init_dom_rid2(&rid2[i], rid, type, dom_idx);
}
unbecome_root();
+
+ return mapped_count;
}
/***************************************************************************
@@ -250,42 +258,44 @@ static void init_lsa_trans_names(TALLOC_CTX *ctx, DOM_R_REF *ref, LSA_TRANS_NAME
DOM_SID find_sid = sid[i].sid;
uint32 rid = 0xffffffff;
int dom_idx = -1;
- fstring name, dom_name;
- enum SID_NAME_USE sid_name_use = (enum SID_NAME_USE)0;
+ char *name, *domain;
+ enum SID_NAME_USE type = SID_NAME_UNKNOWN;
- sid_to_string(name, &find_sid);
- DEBUG(5, ("init_lsa_trans_names: looking up sid %s\n", name));
+ DEBUG(5, ("init_lsa_trans_names: looking up sid %s\n",
+ sid_string_static(&find_sid)));
/* Lookup sid from winbindd */
- status = lookup_sid(&find_sid, dom_name, name, &sid_name_use);
+ status = lookup_sid(ctx, &find_sid, &domain, &name, &type);
DEBUG(5, ("init_lsa_trans_names: %s\n", status ? "found" :
"not found"));
if (!status) {
- sid_name_use = SID_NAME_UNKNOWN;
- memset(dom_name, '\0', sizeof(dom_name));
- sid_to_string(name, &find_sid);
+ type = SID_NAME_UNKNOWN;
+ domain = talloc_strdup(ctx, "");
+ name = talloc_strdup(ctx,
+ sid_string_static(&find_sid));
dom_idx = -1;
- DEBUG(10,("init_lsa_trans_names: added unknown user '%s' to "
- "referenced list.\n", name ));
+ DEBUG(10,("init_lsa_trans_names: added unknown user "
+ "'%s' to referenced list.\n", name ));
} else {
(*mapped_count)++;
/* Store domain sid in ref array */
if (find_sid.num_auths == 5) {
sid_split_rid(&find_sid, &rid);
}
- dom_idx = init_dom_ref(ref, dom_name, &find_sid);
+ dom_idx = init_dom_ref(ref, domain, &find_sid);
- DEBUG(10,("init_lsa_trans_names: added %s '%s\\%s' (%d) to referenced list.\n",
- sid_type_lookup(sid_name_use), dom_name, name, sid_name_use ));
+ DEBUG(10,("init_lsa_trans_names: added %s '%s\\%s' "
+ "(%d) to referenced list.\n",
+ sid_type_lookup(type), domain, name, type));
}
init_lsa_trans_name(&trn->name[total], &trn->uni_name[total],
- sid_name_use, name, dom_idx);
+ type, name, dom_idx);
total++;
}
@@ -697,12 +707,18 @@ NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP
DOM_R_REF *ref;
DOM_RID2 *rids;
uint32 mapped_count = 0;
+ int flags = 0;
if (num_entries > MAX_LOOKUP_SIDS) {
num_entries = MAX_LOOKUP_SIDS;
DEBUG(5,("_lsa_lookup_names: truncating name lookup list to %d\n", num_entries));
}
+ /* Probably the lookup_level is some sort of bitmask. */
+ if (q_u->lookup_level == 1) {
+ flags = LOOKUP_NAME_ALL;
+ }
+
ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF);
rids = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_RID2, num_entries);
@@ -720,10 +736,11 @@ NTSTATUS _lsa_lookup_names(pipes_struct *p,LSA_Q_LOOKUP_NAMES *q_u, LSA_R_LOOKUP
if (!ref || !rids)
return NT_STATUS_NO_MEMORY;
+ /* set up the LSA Lookup RIDs response */
+ mapped_count = init_lsa_rid2s(p->mem_ctx, ref, rids, num_entries,
+ names, flags);
done:
- /* set up the LSA Lookup RIDs response */
- init_lsa_rid2s(ref, rids, num_entries, names, &mapped_count, p->endian);
if (NT_STATUS_IS_OK(r_u->status)) {
if (mapped_count == 0)
r_u->status = NT_STATUS_NONE_MAPPED;
@@ -1109,15 +1126,13 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, prs_struct *ps, LSA_Q_ENUMPRIVS
NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA_R_GETSYSTEMACCOUNT *r_u)
{
struct lsa_info *info=NULL;
- fstring name, dom_name;
- enum SID_NAME_USE type;
/* find the connection policy handle. */
if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
return NT_STATUS_INVALID_HANDLE;
- if (!lookup_sid(&info->sid, dom_name, name, &type))
+ if (!lookup_sid(p->mem_ctx, &info->sid, NULL, NULL, NULL))
return NT_STATUS_ACCESS_DENIED;
/*
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index 635d870762..13f3a3284b 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -1366,9 +1366,7 @@ NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAM
NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LOOKUP_NAMES *r_u)
{
uint32 rid[MAX_SAM_ENTRIES];
- uint32 local_rid;
enum SID_NAME_USE type[MAX_SAM_ENTRIES];
- enum SID_NAME_USE local_type;
int i;
int num_rids = q_u->num_names2;
DOM_SID pol_sid;
@@ -1400,42 +1398,30 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
for (i = 0; i < num_rids; i++) {
fstring name;
- DOM_SID sid;
int ret;
r_u->status = NT_STATUS_NONE_MAPPED;
+ type[i] = SID_NAME_UNKNOWN;
rid [i] = 0xffffffff;
- type[i] = SID_NAME_UNKNOWN;
ret = rpcstr_pull(name, q_u->uni_name[i].buffer, sizeof(name), q_u->uni_name[i].uni_str_len*2, 0);
- /*
- * we are only looking for a name
- * the SID we get back can be outside
- * the scope of the pol_sid
- *
- * in clear: it prevents to reply to domain\group: yes
- * when only builtin\group exists.
- *
- * a cleaner code is to add the sid of the domain we're looking in
- * to the local_lookup_name function.
- */
-
- if ((ret > 0) && local_lookup_name(name, &sid, &local_type)) {
- sid_split_rid(&sid, &local_rid);
-
- if (sid_equal(&sid, &pol_sid)) {
- rid[i]=local_rid;
-
- /* Windows does not return WKN_GRP here, even
- * on lookups in builtin */
- type[i] = (local_type == SID_NAME_WKN_GRP) ?
- SID_NAME_ALIAS : local_type;
-
- r_u->status = NT_STATUS_OK;
+ if (ret <= 0) {
+ continue;
+ }
+
+ if (sid_check_is_builtin(&pol_sid)) {
+ if (lookup_builtin_name(name, &rid[i])) {
+ type[i] = SID_NAME_ALIAS;
}
- }
+ } else {
+ lookup_global_sam_name(name, &rid[i], &type[i]);
+ }
+
+ if (type[i] != SID_NAME_UNKNOWN) {
+ r_u->status = NT_STATUS_OK;
+ }
}
init_samr_r_lookup_names(p->mem_ctx, r_u, num_rids, rid, (uint32 *)type, r_u->status);
@@ -2247,6 +2233,41 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
return r_u->status;
}
+/* W2k3 seems to use the same check for all 3 objects that can be created via
+ * SAMR, if you try to create for example "Dialup" as an alias it says
+ * "NT_STATUS_USER_EXISTS". This is racy, but we can't really lock the user
+ * database. */
+
+static NTSTATUS can_create(TALLOC_CTX *mem_ctx, const char *new_name)
+{
+ enum SID_NAME_USE type;
+ BOOL result;
+
+ become_root();
+ /* Lookup in our local databases (only LOOKUP_NAME_ISOLATED set)
+ * whether the name already exists */
+ result = lookup_name(mem_ctx, new_name, LOOKUP_NAME_ISOLATED,
+ NULL, NULL, NULL, &type);
+ unbecome_root();
+
+ if (!result) {
+ return NT_STATUS_OK;
+ }
+
+ DEBUG(5, ("trying to create %s, exists as %s\n",
+ new_name, sid_type_lookup(type)));
+
+ if (type == SID_NAME_DOM_GRP) {
+ return NT_STATUS_GROUP_EXISTS;
+ }
+ if (type == SID_NAME_ALIAS) {
+ return NT_STATUS_ALIAS_EXISTS;
+ }
+
+ /* Yes, the default is NT_STATUS_USER_EXISTS */
+ return NT_STATUS_USER_EXISTS;
+}
+
/*******************************************************************
_samr_create_user
Create an account, can be either a normal user or a machine.
@@ -2294,19 +2315,11 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
rpcstr_pull(account, user_account.buffer, sizeof(account), user_account.uni_str_len*2, 0);
strlower_m(account);
- pdb_init_sam(&sam_pass);
-
- become_root();
- ret = pdb_getsampwnam(sam_pass, account);
- unbecome_root();
- if (ret == True) {
- /* this account exists: say so */
- pdb_free_sam(&sam_pass);
- return NT_STATUS_USER_EXISTS;
+ nt_status = can_create(p->mem_ctx, account);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
}
- pdb_free_sam(&sam_pass);
-
/*********************************************************************
* HEADS UP! If we have to create a new user account, we have to get
* a new RID from somewhere. This used to be done by the passdb
@@ -2776,7 +2789,7 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A
/* append the alias' RID to it */
if (!sid_append_rid(&sid, alias_rid))
- return NT_STATUS_NO_SUCH_USER;
+ return NT_STATUS_NO_SUCH_ALIAS;
/*check if access can be granted as requested by client. */
@@ -2793,12 +2806,21 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A
if ( !NT_STATUS_IS_OK(status) )
return status;
- /*
- * we should check if the rid really exist !!!
- * JFM.
- */
+ {
+ /* Check we actually have the requested alias */
+ enum SID_NAME_USE type;
+ BOOL result;
- /* associate the user's SID with the new handle. */
+ become_root();
+ result = lookup_sid(NULL, &sid, NULL, NULL, &type);
+ unbecome_root();
+
+ if (!result || (type != SID_NAME_ALIAS)) {
+ return NT_STATUS_NO_SUCH_ALIAS;
+ }
+ }
+
+ /* associate the alias SID with the new handle. */
if ((info = get_samr_info_by_sid(&sid)) == NULL)
return NT_STATUS_NO_MEMORY;
@@ -2814,12 +2836,11 @@ NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_A
/*******************************************************************
set_user_info_7
********************************************************************/
-static NTSTATUS set_user_info_7(const SAM_USER_INFO_7 *id7, SAM_ACCOUNT *pwd)
+static NTSTATUS set_user_info_7(TALLOC_CTX *mem_ctx,
+ const SAM_USER_INFO_7 *id7, SAM_ACCOUNT *pwd)
{
fstring new_name;
- SAM_ACCOUNT *check_acct = NULL;
NTSTATUS rc;
- BOOL check_rc;
if (id7 == NULL) {
DEBUG(5, ("set_user_info_7: NULL id7\n"));
@@ -2842,13 +2863,9 @@ static NTSTATUS set_user_info_7(const SAM_USER_INFO_7 *id7, SAM_ACCOUNT *pwd)
simply that the rename fails with a slightly different status
code (like UNSUCCESSFUL instead of ALREADY_EXISTS). */
- pdb_init_sam(&check_acct);
- check_rc = pdb_getsampwnam(check_acct, new_name);
- pdb_free_sam(&check_acct);
-
- if (check_rc == True) {
- /* this account exists: say so */
- return NT_STATUS_USER_EXISTS;
+ rc = can_create(mem_ctx, new_name);
+ if (!NT_STATUS_IS_OK(rc)) {
+ return rc;
}
rc = pdb_rename_sam_account(pwd, new_name);
@@ -3365,7 +3382,8 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
switch (switch_value) {
case 7:
- r_u->status = set_user_info_7(ctr->info.id7, pwd);
+ r_u->status = set_user_info_7(p->mem_ctx,
+ ctr->info.id7, pwd);
break;
case 16:
if (!set_user_info_16(ctr->info.id16, pwd))
@@ -4199,9 +4217,10 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
unistr2_to_ascii(name, &q_u->uni_acct_desc, sizeof(name)-1);
- /* check if group already exist */
- if ((grp=getgrnam(name)) != NULL)
- return NT_STATUS_GROUP_EXISTS;
+ r_u->status = can_create(p->mem_ctx, name);
+ if (!NT_STATUS_IS_OK(r_u->status)) {
+ return r_u->status;
+ }
se_priv_copy( &se_rights, &se_add_users );
can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights );
@@ -4289,6 +4308,11 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S
if (!sid_equal(&dom_sid, get_global_sam_sid()))
return NT_STATUS_ACCESS_DENIED;
+ r_u->status = can_create(p->mem_ctx, name);
+ if (!NT_STATUS_IS_OK(r_u->status)) {
+ return r_u->status;
+ }
+
unistr2_to_ascii(name, &q_u->uni_acct_desc, sizeof(name)-1);
se_priv_copy( &se_rights, &se_add_users );