diff options
author | Jeremy Allison <jra@samba.org> | 2001-02-17 03:36:41 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2001-02-17 03:36:41 +0000 |
commit | b30c27e5d7f3d690af782d3b07cdd9827d36784a (patch) | |
tree | 21d41a4e2572379534f0a5a9184d0556bb2b3c1b | |
parent | 7fbdf1ebab1ae49b034708ff76c4aaeb1f3df990 (diff) | |
download | samba-b30c27e5d7f3d690af782d3b07cdd9827d36784a.tar.gz samba-b30c27e5d7f3d690af782d3b07cdd9827d36784a.tar.xz samba-b30c27e5d7f3d690af782d3b07cdd9827d36784a.zip |
Save, save, save as you go...
Jeremy.
-rw-r--r-- | source/rpc_server/srv_samr_nt.c | 452 |
1 files changed, 452 insertions, 0 deletions
diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c index 0bdc083e93d..374da7dcee4 100644 --- a/source/rpc_server/srv_samr_nt.c +++ b/source/rpc_server/srv_samr_nt.c @@ -997,3 +997,455 @@ uint32 _api_samr_open_user(pipe_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_US return r_u->status; } +/************************************************************************* + get_user_info_10 + *************************************************************************/ + +static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid) +{ + struct smb_passwd *smb_pass; + + if (!pdb_rid_is_user(user_rid)) + { + DEBUG(4,("RID 0x%x is not a user RID\n", user_rid)); + return False; + } + + become_root(); + smb_pass = getsmbpwrid(user_rid); + unbecome_root(); + + if (smb_pass == NULL) + { + DEBUG(4,("User 0x%x not found\n", user_rid)); + return False; + } + + DEBUG(3,("User:[%s]\n", smb_pass->smb_name)); + + init_sam_user_info10(id10, smb_pass->acct_ctrl); + + return True; +} + +/************************************************************************* + get_user_info_21 + *************************************************************************/ +static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid) +{ + NTTIME dummy_time; + struct sam_passwd *sam_pass; + LOGON_HRS hrs; + int i; + + if (!pdb_rid_is_user(user_rid)) + { + DEBUG(4,("RID 0x%x is not a user RID\n", user_rid)); + return False; + } + + become_root(); + sam_pass = getsam21pwrid(user_rid); + unbecome_root(); + + if (sam_pass == NULL) + { + DEBUG(4,("User 0x%x not found\n", user_rid)); + return False; + } + + DEBUG(3,("User:[%s]\n", sam_pass->smb_name)); + + dummy_time.low = 0xffffffff; + dummy_time.high = 0x7fffffff; + + DEBUG(5,("get_user_info_21 - TODO: convert unix times to NTTIMEs\n")); + + /* create a LOGON_HRS structure */ + hrs.len = sam_pass->hours_len; + SMB_ASSERT_ARRAY(hrs.hours, hrs.len); + for (i = 0; i < hrs.len; i++) + { + hrs.hours[i] = sam_pass->hours[i]; + } + + init_sam_user_info21(id21, + + &dummy_time, /* logon_time */ + &dummy_time, /* logoff_time */ + &dummy_time, /* kickoff_time */ + &dummy_time, /* pass_last_set_time */ + &dummy_time, /* pass_can_change_time */ + &dummy_time, /* pass_must_change_time */ + + sam_pass->smb_name, /* user_name */ + sam_pass->full_name, /* full_name */ + sam_pass->home_dir, /* home_dir */ + sam_pass->dir_drive, /* dir_drive */ + sam_pass->logon_script, /* logon_script */ + sam_pass->profile_path, /* profile_path */ + sam_pass->acct_desc, /* description */ + sam_pass->workstations, /* workstations user can log in from */ + sam_pass->unknown_str, /* don't know, yet */ + sam_pass->munged_dial, /* dialin info. contains dialin path and tel no */ + + sam_pass->user_rid, /* RID user_id */ + sam_pass->group_rid, /* RID group_id */ + sam_pass->acct_ctrl, + + sam_pass->unknown_3, /* unknown_3 */ + sam_pass->logon_divs, /* divisions per week */ + &hrs, /* logon hours */ + sam_pass->unknown_5, + sam_pass->unknown_6); + + return True; +} + +/******************************************************************* + _samr_query_userinfo + ********************************************************************/ + +uint32 _samr_query_userinfo(pipe_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_R_QUERY_USERINFO *r_u) +{ +#if 0 + SAM_USER_INFO_11 id11; +#endif + SAM_USER_INFO_10 id10; + SAM_USER_INFO_21 id21; + void *info = NULL; + uint32 rid = 0x0; + + r_u->status = NT_STATUS_NO_PROBLEMO; + + DEBUG(5,("_samr_query_userinfo: %d\n", __LINE__)); + + /* search for the handle */ + if (find_lsa_policy_by_hnd(&q_u->pol) == -1) + return NT_STATUS_INVALID_HANDLE; + + /* find the user's rid */ + if ((rid = get_lsa_policy_samr_rid(&q_u->pol)) == 0xffffffff) + return NT_STATUS_OBJECT_TYPE_MISMATCH; + + DEBUG(5,("_samr_query_userinfo: rid:0x%x\n", rid)); + + /* ok! user info levels (there are lots: see MSDEV help), off we go... */ + + switch (q_u->switch_value) { + case 0x10: + info = (void*)&id10; + r_u->status = get_user_info_10(&id10, rid) ? 0 : NT_STATUS_NO_SUCH_USER; + break; +#if 0 +/* whoops - got this wrong. i think. or don't understand what's happening. */ + case 0x11: + { + NTTIME expire; + info = (void*)&id11; + + expire.low = 0xffffffff; + expire.high = 0x7fffffff; + + make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080); + + break; + } +#endif + case 21: + info = (void*)&id21; + r_u->status = get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER; + break; + + default: + r_u->status = NT_STATUS_INVALID_INFO_CLASS; + break; + } + + init_samr_r_query_userinfo(r_u, q_u->switch_value, info, r_u->status); + + DEBUG(5,("_samr_query_userinfo: %d\n", __LINE__)); + + return r_u->status; +} + +/******************************************************************* + samr_reply_query_usergroups + ********************************************************************/ + +uint32 _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, SAMR_R_QUERY_USERGROUPS *r_u) +{ + struct sam_passwd *sam_pass; + DOM_GID *gids = NULL; + int num_groups = 0; + pstring groups; + uint32 rid; + prs_struct *rdata = &p->out_data.rdata; + + r_u->status = NT_STATUS_NO_PROBLEMO; + + DEBUG(5,("_samr_query_usergroups: %d\n", __LINE__)); + + /* find the policy handle. open a policy on it. */ + if (find_lsa_policy_by_hnd(&q_u->pol) == -1) + return NT_STATUS_INVALID_HANDLE; + + /* find the user's rid */ + if ((rid = get_lsa_policy_samr_rid(&q_u->pol)) == 0xffffffff) + return NT_STATUS_OBJECT_TYPE_MISMATCH; + + become_root(); + sam_pass = getsam21pwrid(rid); + unbecome_root(); + + if (sam_pass == NULL) + return NT_STATUS_NO_SUCH_USER; + + get_domain_user_groups(groups, sam_pass->smb_name); + gids = NULL; + num_groups = make_dom_gids(prs_get_mem_context(rdata), groups, &gids); + + /* construct the response. lkclXXXX: gids are not copied! */ + init_samr_r_query_usergroups(r_u, num_groups, gids, r_u->status); + + DEBUG(5,("_samr_query_usergroups: %d\n", __LINE__)); + + return r_u->status; +} + +/******************************************************************* + _samr_query_dom_info + ********************************************************************/ + +uint32 _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SAMR_R_QUERY_DOMAIN_INFO *r_u) +{ + SAM_UNK_CTR ctr; + uint16 switch_value = 0; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(ctr); + + r_u->status = NT_STATUS_NO_PROBLEMO; + + DEBUG(5,("_samr_query_dom_info: %d\n", __LINE__)); + + /* find the policy handle. open a policy on it. */ + if (find_lsa_policy_by_hnd(&q_u.domain_pol) == -1) + return NT_STATUS_INVALID_HANDLE; + + switch (q_u.switch_value) { + case 0x01: + switch_value = 0x1; + init_unk_info1(&ctr.info.inf1); + break; + case 0x02: + switch_value = 0x2; + init_unk_info2(&ctr.info.inf2, global_myworkgroup, global_myname); + break; + case 0x03: + switch_value = 0x3; + init_unk_info3(&ctr.info.inf3); + break; + case 0x06: + switch_value = 0x6; + init_unk_info6(&ctr.info.inf6); + break; + case 0x07: + switch_value = 0x7; + init_unk_info7(&ctr.info.inf7); + break; + case 0x0c: + switch_value = 0xc; + init_unk_info12(&ctr.info.inf12); + break; + default: + status = NT_STATUS_INVALID_INFO_CLASS; + break; + } + + init_samr_r_query_dom_info(prs_get_mem_context(rdata), &r_u, switch_value, &ctr, status); + + DEBUG(5,("_samr_query_dom_info: %d\n", __LINE__)); + + return r_u->status; +} + +/******************************************************************* + _api_samr_create_user + ********************************************************************/ + +uint32 _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREATE_USER *r_u) +{ + struct sam_passwd *sam_pass; + fstring mach_acct; + pstring err_str; + pstring msg_str; + int local_flags=0; + DOM_SID sid; + pstring add_script; + POLICY_HND dom_pol = q_u->pol; + UNISTR2 user_account = q_u->uni_mach_acct; + uint32 acb_info = q_u->acb_info; + uint32 access_mask = q_u->access_mask; + POLICY_HND *user_pol = &r_u->pol; + + /* find the policy handle. open a policy on it. */ + if (find_lsa_policy_by_hnd(&dom_pol) == -1) + return NT_STATUS_INVALID_HANDLE; + + /* find the machine account: tell the caller if it exists. + lkclXXXX i have *no* idea if this is a problem or not + or even if you are supposed to construct a different + reply if the account already exists... + */ + + fstrcpy(mach_acct, dos_unistrn2(user_account.buffer, user_account.uni_str_len)); + strlower(mach_acct); + + become_root(); + sam_pass = getsam21pwnam(mach_acct); + unbecome_root(); + if (sam_pass != NULL) { + /* machine account exists: say so */ + return NT_STATUS_USER_EXISTS; + } + + /* get a (unique) handle. open a policy on it. */ + if (!open_lsa_policy_hnd(user_pol)) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + + local_flags=LOCAL_ADD_USER|LOCAL_DISABLE_USER|LOCAL_SET_NO_PASSWORD; + local_flags|= (acb_info & ACB_WSTRUST) ? LOCAL_TRUST_ACCOUNT:0; + + /* + * NB. VERY IMPORTANT ! This call must be done as the current pipe user, + * *NOT* surrounded by a become_root()/unbecome_root() call. This ensures + * that only people with write access to the smbpasswd file will be able + * to create a user. JRA. + */ + + /* + * add the user in the /etc/passwd file or the unix authority system. + * We don't check if the smb_create_user() function succed or not for 2 reasons: + * a) local_password_change() checks for us if the /etc/passwd account really exists + * b) smb_create_user() would return an error if the account already exists + * and as it could return an error also if it can't create the account, it would be tricky. + * + * So we go the easy way, only check after if the account exists. + * JFM (2/3/2001), to clear any possible bad understanding (-: + */ + + pstrcpy(add_script, lp_adduser_script()); + + if(*add_script) + smb_create_user(mach_acct, NULL); + + /* add the user in the smbpasswd file or the Samba authority database */ + if (!local_password_change(mach_acct, local_flags, NULL, err_str, + sizeof(err_str), msg_str, sizeof(msg_str))) + { + DEBUG(0, ("%s\n", err_str)); + close_lsa_policy_hnd(user_pol); + return NT_STATUS_ACCESS_DENIED; + } + + become_root(); + sam_pass = getsam21pwnam(mach_acct); + unbecome_root(); + if (sam_pass == NULL) { + /* account doesn't exist: say so */ + close_lsa_policy_hnd(user_pol); + return NT_STATUS_ACCESS_DENIED; + } + + /* Get the domain SID stored in the domain policy */ + if(!get_lsa_policy_samr_sid(&dom_pol, &sid)) { + close_lsa_policy_hnd(user_pol); + return NT_STATUS_INVALID_HANDLE; + } + + /* append the user's RID to it */ + if(!sid_append_rid(&sid, sam_pass->user_rid)) { + close_lsa_policy_hnd(user_pol); + return NT_STATUS_NO_SUCH_USER; + } + + /* associate the RID with the (unique) handle. */ + if (!set_lsa_policy_samr_sid(user_pol, &sid)) { + /* oh, whoops. don't know what error message to return, here */ + close_lsa_policy_hnd(user_pol); + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + r_u->user_rid=sam_pass->user_rid; + r_u->unknown0 = 0x000703ff; + + return NT_STATUS_NO_PROBLEMO; +} + +/******************************************************************* + samr_reply_connect_anon + ********************************************************************/ + +uint32 _samr_connect_anon(pipes_struct *p, SAMR_Q_CONNECT_ANON *q_u, SAMR_R_CONNECT_ANON *r_u) +{ + /* set up the SAMR connect_anon response */ + + r_u->status = NT_STATUS_NO_PROBLEMO; + + /* get a (unique) handle. open a policy on it. */ + if (!open_lsa_policy_hnd(&r_u->connect_pol)) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + + /* associate the domain SID with the (unique) handle. */ + if (!set_lsa_policy_samr_pol_status(&r_u->connect_pol, q_u->unknown_0)) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + + close_lsa_policy_hnd(&r_u->connect_pol); + + return r_u->status; +} + +/******************************************************************* + samr_reply_connect + ********************************************************************/ + +uint32 _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u) +{ + DEBUG(5,("_samr_connect: %d\n", __LINE__)); + + r_u->status = NT_STATUS_NO_PROBLEMO; + + /* get a (unique) handle. open a policy on it. */ + if (!open_lsa_policy_hnd(&r_u->connect_pol)) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + + /* associate the domain SID with the (unique) handle. */ + if (!set_lsa_policy_samr_pol_status(&r_u->connect_pol, q_u->access_mask)) + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + + close_lsa_policy_hnd(&r_u.connect_pol); + + DEBUG(5,("_samr_connect: %d\n", __LINE__)); + + return r_u->status; +} + +/********************************************************************** + api_samr_lookup_domain + **********************************************************************/ + +uint32 _samr_lookup_domain(pipes_struct *p, SAMR_Q_LOOKUP_DOMAIN *q_u, SAMR_R_LOOKUP_DOMAIN *r_u) +{ + r_u->status = NT_STATUS_NO_PROBLEMO; + + if (find_lsa_policy_by_hnd(&q_u->connect_pol) == -1) + return NT_STATUS_INVALID_HANDLE; + + /* assume the domain name sent is our global_myname and + send global_sam_sid */ + init_samr_r_lookup_domain(r_u, &global_sam_sid, r_u->status); + + return r_u->status; +} + |