/*
- * Unix SMB/Netbios implementation.
- * Version 1.9.
+ * Unix SMB/CIFS implementation.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
#include "includes.h"
-extern BOOL sam_logon_in_ssb;
-extern pstring samlogon_user;
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
extern pstring global_myname;
-extern DOM_SID global_sam_sid;
/*************************************************************************
init_net_r_req_chal:
DEBUG(3, ("sending sam synchronisation message\n"));
- message_send_all(tdb, MSG_SMB_SAM_SYNC, NULL, 0, False);
+ message_send_all(tdb, MSG_SMB_SAM_SYNC, NULL, 0, False, NULL);
tdb_close(tdb);
}
***********************************************************************************/
static void init_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
- DOM_CRED *srv_cred, NTSTATUS status)
+ DOM_CRED *srv_cred, NTSTATUS status)
{
DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__));
SAM_ACCOUNT *sampass = NULL;
const uint8 *pass;
BOOL ret;
+ uint32 acct_ctrl;
#if 0
/*
}
#endif /* 0 */
- if(!pdb_init_sam(&sampass))
+ if(!NT_STATUS_IS_OK(pdb_init_sam(&sampass)))
return False;
/* JRA. This is ok as it is only used for generating the challenge. */
return False;
}
- if (!(pdb_get_acct_ctrl(sampass) & ACB_DISABLED) && ((pass=pdb_get_nt_passwd(sampass)) != NULL)) {
+ acct_ctrl = pdb_get_acct_ctrl(sampass);
+ if (!(acct_ctrl & ACB_DISABLED) &&
+ ((acct_ctrl & ACB_DOMTRUST) ||
+ (acct_ctrl & ACB_WSTRUST) ||
+ (acct_ctrl & ACB_SVRTRUST)) &&
+ ((pass=pdb_get_nt_passwd(sampass)) != NULL)) {
memcpy(md4pw, pass, 16);
dump_data(5, md4pw, 16);
pdb_free_sam(&sampass);
NTSTATUS _net_req_chal(pipes_struct *p, NET_Q_REQ_CHAL *q_u, NET_R_REQ_CHAL *r_u)
{
NTSTATUS status = NT_STATUS_OK;
- fstring mach_acct;
-
- if (!get_valid_user_struct(p->vuid))
- return NT_STATUS_NO_SUCH_USER;
-
- rpcstr_pull(mach_acct,q_u->uni_logon_clnt.buffer,sizeof(fstring),q_u->uni_logon_clnt.uni_str_len*2,0);
-
- strlower(mach_acct);
- fstrcat(mach_acct, "$");
- if (get_md4pw((char *)p->dc.md4pw, mach_acct)) {
- /* copy the client credentials */
- memcpy(p->dc.clnt_chal.data , q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
- memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
+ rpcstr_pull(p->dc.remote_machine,q_u->uni_logon_clnt.buffer,sizeof(fstring),q_u->uni_logon_clnt.uni_str_len*2,0);
- /* create a server challenge for the client */
- /* Set these to random values. */
- generate_random_buffer(p->dc.srv_chal.data, 8, False);
-
- memcpy(p->dc.srv_cred.challenge.data, p->dc.srv_chal.data, 8);
-
- memset((char *)p->dc.sess_key, '\0', sizeof(p->dc.sess_key));
-
- /* from client / server challenges and md4 password, generate sess key */
- cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal,
- (char *)p->dc.md4pw, p->dc.sess_key);
+ /* create a server challenge for the client */
+ /* Set these to random values. */
+ generate_random_buffer(p->dc.srv_chal.data, 8, False);
+
+ memcpy(p->dc.srv_cred.challenge.data, p->dc.srv_chal.data, 8);
- /* Save the machine account name. */
- fstrcpy(p->dc.mach_acct, mach_acct);
+ memcpy(p->dc.clnt_chal.data , q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
+ memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
- } else {
- /* lkclXXXX take a guess at a good error message to return :-) */
- status = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
- }
+ memset((char *)p->dc.sess_key, '\0', sizeof(p->dc.sess_key));
+ p->dc.challenge_sent = True;
/* set up the LSA REQUEST CHALLENGE response */
init_net_r_req_chal(r_u, &p->dc.srv_chal, status);
-
- return r_u->status;
+
+ return status;
}
/*************************************************************************
NTSTATUS status = NT_STATUS_OK;
DOM_CHAL srv_cred;
UTIME srv_time;
-
- if (!get_valid_user_struct(p->vuid))
- return NT_STATUS_NO_SUCH_USER;
+ fstring mach_acct;
srv_time.time = 0;
- /* check that the client credentials are valid */
- if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) {
+ rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
- /* create server challenge for inclusion in the reply */
- cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred);
+ if (p->dc.challenge_sent && get_md4pw((char *)p->dc.md4pw, mach_acct)) {
- /* copy the received client credentials for use next time */
- memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
- memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
+ /* from client / server challenges and md4 password, generate sess key */
+ cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal,
+ (char *)p->dc.md4pw, p->dc.sess_key);
+
+ /* check that the client credentials are valid */
+ if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) {
+
+ /* create server challenge for inclusion in the reply */
+ cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred);
+
+ /* copy the received client credentials for use next time */
+ memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
+ memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
+
+ /* Save the machine account name. */
+ fstrcpy(p->dc.mach_acct, mach_acct);
+
+ p->dc.authenticated = True;
+
+ } else {
+ status = NT_STATUS_ACCESS_DENIED;
+ }
} else {
status = NT_STATUS_ACCESS_DENIED;
}
-
- /* set up the LSA AUTH 2 response */
+
+ /* set up the LSA AUTH response */
init_net_r_auth(r_u, &srv_cred, status);
return r_u->status;
DOM_CHAL srv_cred;
UTIME srv_time;
NEG_FLAGS srv_flgs;
-
- if (!get_valid_user_struct(p->vuid))
- return NT_STATUS_NO_SUCH_USER;
+ fstring mach_acct;
srv_time.time = 0;
- /* check that the client credentials are valid */
- if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) {
+ rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
- /* create server challenge for inclusion in the reply */
- cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred);
+ if (p->dc.challenge_sent && get_md4pw((char *)p->dc.md4pw, mach_acct)) {
+
+ /* from client / server challenges and md4 password, generate sess key */
+ cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal,
+ (char *)p->dc.md4pw, p->dc.sess_key);
+
+ /* check that the client credentials are valid */
+ if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) {
+
+ /* create server challenge for inclusion in the reply */
+ cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred);
+
+ /* copy the received client credentials for use next time */
+ memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
+ memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
+
+ /* Save the machine account name. */
+ fstrcpy(p->dc.mach_acct, mach_acct);
+
+ p->dc.authenticated = True;
- /* copy the received client credentials for use next time */
- memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
- memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
+ } else {
+ status = NT_STATUS_ACCESS_DENIED;
+ }
} else {
status = NT_STATUS_ACCESS_DENIED;
}
-
+
srv_flgs.neg_flags = 0x000001ff;
/* set up the LSA AUTH 2 response */
NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *r_u)
{
- NTSTATUS status = NT_STATUS_WRONG_PASSWORD;
+ NTSTATUS status = NT_STATUS_ACCESS_DENIED;
DOM_CRED srv_cred;
- pstring mach_acct;
+ pstring workstation;
SAM_ACCOUNT *sampass=NULL;
BOOL ret = False;
unsigned char pwd[16];
int i;
-
- if (!get_valid_user_struct(p->vuid))
- return NT_STATUS_NO_SUCH_USER;
+ uint32 acct_ctrl;
/* checks and updates credentials. creates reply credentials */
- if (!deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->clnt_id.cred, &srv_cred))
+ if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->clnt_id.cred, &srv_cred)))
return NT_STATUS_INVALID_HANDLE;
memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
DEBUG(5,("_net_srv_pwset: %d\n", __LINE__));
- rpcstr_pull(mach_acct,q_u->clnt_id.login.uni_acct_name.buffer,
- sizeof(mach_acct),q_u->clnt_id.login.uni_acct_name.uni_str_len*2,0);
+ rpcstr_pull(workstation,q_u->clnt_id.login.uni_comp_name.buffer,
+ sizeof(workstation),q_u->clnt_id.login.uni_comp_name.uni_str_len*2,0);
- DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct));
+ DEBUG(3,("Server Password Set by Wksta:[%s] on account [%s]\n", workstation, p->dc.mach_acct));
- /*
- * Check the machine account name we're changing is the same
- * as the one we've authenticated from. This prevents arbitrary
- * machines changing other machine account passwords.
- */
-
- if (!strequal(mach_acct, p->dc.mach_acct)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
pdb_init_sam(&sampass);
become_root();
- ret=pdb_getsampwnam(sampass, mach_acct);
+ ret=pdb_getsampwnam(sampass, p->dc.mach_acct);
unbecome_root();
/* Ensure the account exists and is a machine account. */
+
+ acct_ctrl = pdb_get_acct_ctrl(sampass);
- if (ret==False || !(pdb_get_acct_ctrl(sampass) & ACB_WSTRUST)) {
+ if (!(ret
+ && (acct_ctrl & ACB_WSTRUST ||
+ acct_ctrl & ACB_SVRTRUST ||
+ acct_ctrl & ACB_DOMTRUST))) {
pdb_free_sam(&sampass);
return NT_STATUS_NO_SUCH_USER;
}
+ if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) {
+ pdb_free_sam(&sampass);
+ return NT_STATUS_ACCOUNT_DISABLED;
+ }
+
DEBUG(100,("Server password set : new given value was :\n"));
for(i = 0; i < 16; i++)
DEBUG(100,("%02X ", q_u->pwd[i]));
return NT_STATUS_NO_MEMORY;
}
- if (!pdb_set_acct_ctrl (sampass, ACB_WSTRUST)) {
- pdb_free_sam(&sampass);
- /* Not quite sure what this one qualifies as, but this will do */
- return NT_STATUS_NO_MEMORY;
- }
-
if (!pdb_set_pass_changed_now (sampass)) {
pdb_free_sam(&sampass);
/* Not quite sure what this one qualifies as, but this will do */
- return NT_STATUS_NO_MEMORY;
+ return NT_STATUS_UNSUCCESSFUL;
}
become_root();
- ret = pdb_update_sam_account (sampass,False);
+ ret = pdb_update_sam_account (sampass);
unbecome_root();
if (ret)
return NT_STATUS_NO_SUCH_USER;
/* checks and updates credentials. creates reply credentials */
- if (!deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred,
- &q_u->sam_id.client.cred, &srv_cred))
+ if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred,
+ &q_u->sam_id.client.cred, &srv_cred)))
return NT_STATUS_INVALID_HANDLE;
memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
fstring nt_username, nt_domain, nt_workstation;
auth_usersupplied_info *user_info = NULL;
auth_serversupplied_info *server_info = NULL;
+ extern userdom_struct current_user_info;
+ SAM_ACCOUNT *sampw;
usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3));
if (!usr_info)
return NT_STATUS_NO_MEMORY;
ZERO_STRUCTP(usr_info);
+
+ /* store the user information, if there is any. */
+ r_u->user = usr_info;
+ r_u->switch_value = 0; /* indicates no info */
+ r_u->auth_resp = 1; /* authoritative response */
+ r_u->switch_value = 3; /* indicates type of validation user info */
if (!get_valid_user_struct(p->vuid))
return NT_STATUS_NO_SUCH_USER;
/* checks and updates credentials. creates reply credentials */
- if (!deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->sam_id.client.cred, &srv_cred))
+ if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->sam_id.client.cred, &srv_cred)))
return NT_STATUS_INVALID_HANDLE;
- else
- memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
+
+ memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
r_u->buffer_creds = 1; /* yes, we have valid server credentials */
memcpy(&r_u->srv_creds, &srv_cred, sizeof(r_u->srv_creds));
- /* store the user information, if there is any. */
- r_u->user = usr_info;
- r_u->switch_value = 0; /* indicates no info */
- r_u->auth_resp = 1; /* authoritative response */
- r_u->switch_value = 3; /* indicates type of validation user info */
-
/* find the username */
switch (q_u->sam_id.logon_level) {
DEBUG(3,("User:[%s@%s] Requested Domain:[%s]\n", nt_username,
nt_workstation, nt_domain));
-
+
+ pstrcpy(current_user_info.smb_name, nt_username);
+
/*
* Convert to a UNIX username.
*/
switch (ctr->switch_value) {
case NET_LOGON_TYPE:
{
- auth_authsupplied_info *auth_info = NULL;
- make_auth_info_fixed(&auth_info, ctr->auth.id2.lm_chal);
- /* Standard challange/response authenticaion */
- make_user_info_netlogon_network(&user_info,
- nt_username, nt_domain,
- nt_workstation,
- ctr->auth.id2.lm_chal_resp.buffer,
- ctr->auth.id2.lm_chal_resp.str_str_len,
- ctr->auth.id2.nt_chal_resp.buffer,
- ctr->auth.id2.nt_chal_resp.str_str_len);
-
- status = check_password(user_info, auth_info, &server_info);
- free_auth_info(&auth_info);
+ struct auth_context *auth_context = NULL;
+ if (!NT_STATUS_IS_OK(status = make_auth_context_fixed(&auth_context, ctr->auth.id2.lm_chal))) {
+ return status;
+ }
+
+ /* Standard challenge/response authenticaion */
+ if (!make_user_info_netlogon_network(&user_info,
+ nt_username, nt_domain,
+ nt_workstation,
+ ctr->auth.id2.lm_chal_resp.buffer,
+ ctr->auth.id2.lm_chal_resp.str_str_len,
+ ctr->auth.id2.nt_chal_resp.buffer,
+ ctr->auth.id2.nt_chal_resp.str_str_len)) {
+ status = NT_STATUS_NO_MEMORY;
+ } else {
+ status = auth_context->check_ntlm_password(auth_context, user_info, &server_info);
+ }
+ (auth_context->free)(&auth_context);
break;
}
case INTERACTIVE_LOGON_TYPE:
- /* 'Interactive' autheticaion, supplies the password in its MD4 form, encrypted
- with the session key. We will convert this to challange/responce for the
- auth subsystem to chew on */
+ /* 'Interactive' autheticaion, supplies the password in its
+ MD4 form, encrypted with the session key. We will
+ convert this to chellange/responce for the auth
+ subsystem to chew on */
{
- auth_authsupplied_info *auth_info = NULL;
- DATA_BLOB chal;
- if (!make_auth_info_subsystem(&auth_info)) {
- return NT_STATUS_NO_MEMORY;
+ struct auth_context *auth_context = NULL;
+ const uint8 *chal;
+ if (!NT_STATUS_IS_OK(status = make_auth_context_subsystem(&auth_context))) {
+ return status;
}
- chal = auth_get_challange(auth_info);
-
- make_user_info_netlogon_interactive(&user_info,
- nt_username, nt_domain,
- nt_workstation, chal.data,
- ctr->auth.id1.lm_owf.data,
- ctr->auth.id1.nt_owf.data,
- p->dc.sess_key);
- status = check_password(user_info, auth_info, &server_info);
- data_blob_free(&chal);
- free_auth_info(&auth_info);
+ chal = auth_context->get_ntlm_challenge(auth_context);
+
+ if (!make_user_info_netlogon_interactive(&user_info,
+ nt_username, nt_domain,
+ nt_workstation, chal,
+ ctr->auth.id1.lm_owf.data,
+ ctr->auth.id1.nt_owf.data,
+ p->dc.sess_key)) {
+ status = NT_STATUS_NO_MEMORY;
+ } else {
+ status = auth_context->check_ntlm_password(auth_context, user_info, &server_info);
+ }
+
+ (auth_context->free)(&auth_context);
break;
}
free_user_info(&user_info);
DEBUG(5, ("_net_sam_logon: check_password returned status %s\n",
- get_nt_error_msg(status)));
+ nt_errstr(status)));
/* Check account and password */
- if (NT_STATUS_IS_ERR(status)) {
+ if (!NT_STATUS_IS_OK(status)) {
free_server_info(&server_info);
return status;
}
{
DOM_GID *gids = NULL;
+ const DOM_SID *user_sid = NULL;
+ const DOM_SID *group_sid = NULL;
+ DOM_SID domain_sid;
+ uint32 user_rid, group_rid;
+
int num_gids = 0;
pstring my_name;
- pstring my_workgroup;
- pstring domain_groups;
-
+ fstring user_sid_string;
+ fstring group_sid_string;
+
+ sampw = server_info->sam_account;
+
/* set up pointer indicating user/password failed to be found */
usr_info->ptr_user_info = 0;
-
- /* XXXX hack to get standard_sub_basic() to use sam logon username */
- /* possibly a better way would be to do a change_to_user() call */
- sam_logon_in_ssb = True;
- pstrcpy(samlogon_user, nt_username);
- pstrcpy(my_workgroup, lp_workgroup());
+ user_sid = pdb_get_user_sid(sampw);
+ group_sid = pdb_get_group_sid(sampw);
+
+ sid_copy(&domain_sid, user_sid);
+ sid_split_rid(&domain_sid, &user_rid);
+
+ if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) {
+ DEBUG(1, ("_net_sam_logon: user %s\\%s has user sid %s\n but group sid %s.\nThe conflicting domain portions are not supported for NETLOGON calls\n",
+ pdb_get_domain(sampw), pdb_get_username(sampw),
+ sid_to_string(user_sid_string, user_sid),
+ sid_to_string(group_sid_string, group_sid)));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
pstrcpy(my_name, global_myname);
strupper(my_name);
* JRA.
*/
- *domain_groups = 0;
-
- get_domain_user_groups(domain_groups, nt_username);
-
- /*
- * make_dom_gids allocates the gids array. JRA.
- */
- gids = NULL;
- num_gids = make_dom_gids(p->mem_ctx, domain_groups, &gids);
-
- sam_logon_in_ssb = False;
-
- init_net_user_info3(p->mem_ctx, usr_info, server_info->sam_account,
- 0, /* logon_count */
- 0, /* bad_pw_count */
- num_gids, /* uint32 num_groups */
- gids , /* DOM_GID *gids */
- 0x20 , /* uint32 user_flgs (?) */
- NULL, /* uchar sess_key[16] */
- my_name , /* char *logon_srv */
- my_workgroup, /* char *logon_dom */
- &global_sam_sid, /* DOM_SID *dom_sid */
- NULL); /* char *other_sids */
+ gids = NULL;
+ get_domain_user_groups(p->mem_ctx, &num_gids, &gids, server_info->sam_account);
+
+ init_net_user_info3(p->mem_ctx, usr_info,
+ user_rid,
+ group_rid,
+
+ pdb_get_username(sampw),
+ pdb_get_fullname(sampw),
+ pdb_get_homedir(sampw),
+ pdb_get_dirdrive(sampw),
+ pdb_get_logon_script(sampw),
+ pdb_get_profile_path(sampw),
+ pdb_get_logon_time(sampw),
+ pdb_get_logoff_time(sampw),
+ pdb_get_kickoff_time(sampw),
+ pdb_get_pass_last_set_time(sampw),
+ pdb_get_pass_can_change_time(sampw),
+ pdb_get_pass_must_change_time(sampw),
+
+ 0, /* logon_count */
+ 0, /* bad_pw_count */
+ num_gids, /* uint32 num_groups */
+ gids , /* DOM_GID *gids */
+ 0x20 , /* uint32 user_flgs (?) */
+ NULL, /* uchar sess_key[16] */
+ my_name , /* char *logon_srv */
+ pdb_get_domain(sampw),
+ &domain_sid, /* DOM_SID *dom_sid */
+ /* Should be users domain sid, not servers - for trusted domains */
+
+ NULL); /* char *other_sids */
}
free_server_info(&server_info);
return status;