summaryrefslogtreecommitdiff
path: root/source3/rpc_server
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2001-08-03 13:09:23 +0000
committerAndrew Bartlett <abartlet@samba.org>2001-08-03 13:09:23 +0000
commit986372901e85a79343ba32f590a4a3e7658d2565 (patch)
tree19c863631c1c0da0535adf090dbb4c566e7e9d3b /source3/rpc_server
parent8dad2a1310c6dc908934ac836377cbfed8f7a010 (diff)
downloadsamba-986372901e85a79343ba32f590a4a3e7658d2565.tar.gz
samba-986372901e85a79343ba32f590a4a3e7658d2565.tar.bz2
samba-986372901e85a79343ba32f590a4a3e7658d2565.zip
This is my 'Authentication Rewrite' version 1.01, mostly as submitted to
samba-technical a few weeks ago. The idea here is to standardize the checking of user names and passwords, thereby ensuring that all authtentications pass the same standards. The interface currently implemented in as nt_status = check_password(user_info, server_info) where user_info contains (mostly) the authentication data, and server_info contains things like the user-id they got, and their resolved user name. The current ugliness with the way the structures are created will be killed the next revision, when they will be created and malloced by creator functions. This patch also includes the first implementation of NTLMv2 in HEAD, but which needs some more testing. We also add a hack to allow plaintext passwords to be compared with smbpasswd, not the system password database. Finally, this patch probably reintroduces the PAM accounts bug we had in 2.2.0, I'll fix that once this hits the tree. (I've just finished testing it on a wide variety of platforms, so I want to get this patch in). (This used to be commit b30b6202f31d339b48d51c0d38174cafd1cfcd42)
Diffstat (limited to 'source3/rpc_server')
-rw-r--r--source3/rpc_server/srv_netlog_nt.c225
-rw-r--r--source3/rpc_server/srv_pipe.c18
2 files changed, 140 insertions, 103 deletions
diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c
index 14f3e1d211..385fec5862 100644
--- a/source3/rpc_server/srv_netlog_nt.c
+++ b/source3/rpc_server/srv_netlog_nt.c
@@ -441,97 +441,138 @@ uint32 _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOFF
}
/*************************************************************************
- net_login_interactive:
+ _net_logon_any: Use the new authentications subsystem to log in.
*************************************************************************/
-static uint32 net_login_interactive(NET_ID_INFO_1 *id1, SAM_ACCOUNT *sampass, pipes_struct *p)
+static uint32 _net_logon_any(NET_ID_INFO_CTR *ctr, char *user, char *domain, char *sess_key)
{
- uint32 status = 0x0;
- char nt_pwd[16];
- char lm_pwd[16];
- unsigned char key[16];
+ uint32 nt_status = NT_STATUS_LOGON_FAILURE;
- memset(key, 0, 16);
- memcpy(key, p->dc.sess_key, 8);
+ unsigned char local_lm_response[24];
+ unsigned char local_nt_response[24];
- memcpy(lm_pwd, id1->lm_owf.data, 16);
- memcpy(nt_pwd, id1->nt_owf.data, 16);
+ auth_usersupplied_info user_info;
+ auth_serversupplied_info server_info;
+ AUTH_STR ourdomain, theirdomain, smb_username, wksta_name;
-#ifdef DEBUG_PASSWORD
- DEBUG(100,("key:"));
- dump_data(100, (char *)key, 16);
+ DEBUG(5, ("_net_logon_any: entered with user %s and domain %s\n", user, domain));
+
+ ZERO_STRUCT(user_info);
+ ZERO_STRUCT(server_info);
+ ZERO_STRUCT(ourdomain);
+ ZERO_STRUCT(theirdomain);
+ ZERO_STRUCT(smb_username);
+ ZERO_STRUCT(wksta_name);
+
+ ourdomain.str = lp_workgroup();
+ ourdomain.len = strlen(ourdomain.str);
- DEBUG(100,("lm owf password:"));
- dump_data(100, lm_pwd, 16);
+ theirdomain.str = domain;
+ theirdomain.len = strlen(theirdomain.str);
- DEBUG(100,("nt owf password:"));
- dump_data(100, nt_pwd, 16);
-#endif
+ user_info.requested_domain = theirdomain;
+ user_info.domain = ourdomain;
+
+ smb_username.str = user;
+ smb_username.len = strlen(smb_username.str);
- SamOEMhash((uchar *)lm_pwd, key, 16);
- SamOEMhash((uchar *)nt_pwd, key, 16);
+ user_info.requested_username = smb_username; /* For the time-being */
+ user_info.smb_username = smb_username;
-#ifdef DEBUG_PASSWORD
- DEBUG(100,("decrypt of lm owf password:"));
- dump_data(100, lm_pwd, 16);
+#if 0
+ user_info.wksta_name.str = cleint_name();
+ user_info.wksta_name.len = strlen(client_name());
- DEBUG(100,("decrypt of nt owf password:"));
- dump_data(100, nt_pwd, 16);
+ user_info.wksta_name = wksta_name;
#endif
- if (memcmp(pdb_get_lanman_passwd(sampass), lm_pwd, 16) != 0 ||
- memcmp(pdb_get_nt_passwd(sampass), nt_pwd, 16) != 0) {
- status = NT_STATUS_WRONG_PASSWORD;
- }
-
- return status;
-}
-
-/*************************************************************************
- _net_login_network:
- *************************************************************************/
-
-static uint32 net_login_network(NET_ID_INFO_2 *id2, SAM_ACCOUNT *sampass)
-{
- uint8 *nt_pwd, *lanman_pwd;
-
- DEBUG(5,("net_login_network: lm_len: %d nt_len: %d\n",
- id2->hdr_lm_chal_resp.str_str_len,
- id2->hdr_nt_chal_resp.str_str_len));
-
- /* JRA. Check the NT password first if it exists - this is a higher quality
- password, if it exists and it doesn't match - fail. */
+ DEBUG(10,("_net_logon_any: Attempting validation level %d.\n", ctr->switch_value));
+ switch (ctr->switch_value) {
+ case NET_LOGON_TYPE:
+ user_info.lm_resp.buffer = (uint8 *)ctr->auth.id2.lm_chal_resp.buffer;
+ user_info.lm_resp.len = ctr->auth.id2.lm_chal_resp.str_str_len;
+ user_info.nt_resp.buffer = (uint8 *)ctr->auth.id2.nt_chal_resp.buffer;
+ user_info.nt_resp.len = ctr->auth.id2.nt_chal_resp.str_str_len;
+ memcpy(user_info.chal, ctr->auth.id2.lm_chal, 8);
+ break;
+ case INTERACTIVE_LOGON_TYPE:
+ {
+ char nt_pwd[16];
+ char lm_pwd[16];
+ unsigned char key[16];
+
+ memset(key, 0, 16);
+ memcpy(key, sess_key, 8);
+
+ memcpy(lm_pwd, ctr->auth.id1.lm_owf.data, 16);
+ memcpy(nt_pwd, ctr->auth.id1.nt_owf.data, 16);
- nt_pwd = pdb_get_nt_passwd(sampass);
- lanman_pwd = pdb_get_lanman_passwd(sampass);
+#ifdef DEBUG_PASSWORD
+ DEBUG(100,("key:"));
+ dump_data(100, (char *)key, 16);
+
+ DEBUG(100,("lm owf password:"));
+ dump_data(100, lm_pwd, 16);
+
+ DEBUG(100,("nt owf password:"));
+ dump_data(100, nt_pwd, 16);
+#endif
+
+ SamOEMhash((uchar *)lm_pwd, key, 16);
+ SamOEMhash((uchar *)nt_pwd, key, 16);
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(100,("decrypt of lm owf password:"));
+ dump_data(100, lm_pwd, 16);
+
+ DEBUG(100,("decrypt of nt owf password:"));
+ dump_data(100, nt_pwd, 16);
+#endif
- if (id2->hdr_nt_chal_resp.str_str_len == 24 && nt_pwd) {
- if(smb_password_check((char *)id2->nt_chal_resp.buffer,
- nt_pwd, id2->lm_chal))
- return NT_STATUS_NOPROBLEMO;
- else
- return NT_STATUS_WRONG_PASSWORD;
+ generate_random_buffer(user_info.chal, 8, False);
+ SMBOWFencrypt(lm_pwd, user_info.chal, local_lm_response);
+ SMBOWFencrypt(nt_pwd, user_info.chal, local_nt_response);
+ user_info.lm_resp.buffer = (uint8 *)local_lm_response;
+ user_info.lm_resp.len = 24;
+ user_info.nt_resp.buffer = (uint8 *)local_nt_response;
+ user_info.nt_resp.len = 24;
+ break;
}
+#if 0
+ case GENERAL_LOGON_TYPE:
+ /* plaintext login. plaintext username and password */
- /* lkclXXXX this is not a good place to put disabling of LM hashes in.
- if that is to be done, first move this entire function into a
- library routine that calls the two smb_password_check() functions.
- if disabling LM hashes (which nt can do for security reasons) then
- an attempt should be made to disable them everywhere (which nt does
- not do, for various security-hole reasons).
- */
+ /*
+ * Not encrypted - do so.
+ */
+
+ SMBencrypt( (uchar *)ctr->auth.id4....., user_info.chal, local_lm_response);
+ SMBNTencrypt((uchar *)ctr->auth.id4......., user_info.chal, local_nt_response);
+ user_info.lm_resp.buffer = (uint8 *)local_lm_response;
+ user_info.lm_resp.len = 24;
+ user_info.nt_resp.buffer = (uint8 *)local_nt_response;
+ user_info.nt_resp.len = 24;
+
+ user_info.plaintext_password.str = ;
+ user_info.plaintext_password.len = ;
+ break;
+#endif
+ default:
+ DEBUG(2,("SAM Logon: unsupported switch value\n"));
+ return NT_STATUS_INVALID_INFO_CLASS;
+ } /* end switch */
+
+ nt_status = check_password(&user_info, &server_info);
- if (id2->hdr_lm_chal_resp.str_str_len == 24 && lanman_pwd &&
- smb_password_check((char *)id2->lm_chal_resp.buffer,
- lanman_pwd, id2->lm_chal))
- return NT_STATUS_NOPROBLEMO;
+ DEBUG(5, ("_net_logon_any: exited with status %d\n", nt_status));
- /* oops! neither password check succeeded */
+ return nt_status;
- return NT_STATUS_WRONG_PASSWORD;
}
+
+
/*************************************************************************
_net_sam_logon
*************************************************************************/
@@ -542,11 +583,12 @@ uint32 _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_
NET_USER_INFO_3 *usr_info = NULL;
DOM_CRED srv_cred;
SAM_ACCOUNT *sampass = NULL;
- uint16 acct_ctrl;
UNISTR2 *uni_samlogon_user = NULL;
+ UNISTR2 *uni_samlogon_domain = NULL;
fstring nt_username;
+ fstring nt_domain;
BOOL ret;
-
+
usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3));
if (!usr_info)
return NT_STATUS_NO_MEMORY;
@@ -576,11 +618,13 @@ uint32 _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_
switch (q_u->sam_id.logon_level) {
case INTERACTIVE_LOGON_TYPE:
uni_samlogon_user = &q_u->sam_id.ctr->auth.id1.uni_user_name;
+ uni_samlogon_domain = &q_u->sam_id.ctr->auth.id1.uni_domain_name;
DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. ", lp_workgroup()));
break;
case NET_LOGON_TYPE:
uni_samlogon_user = &q_u->sam_id.ctr->auth.id2.uni_user_name;
+ uni_samlogon_domain = &q_u->sam_id.ctr->auth.id2.uni_domain_name;
DEBUG(3,("SAM Logon (Network). Domain:[%s]. ", lp_workgroup()));
break;
@@ -592,8 +636,9 @@ uint32 _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_
/* check username exists */
rpcstr_pull(nt_username,uni_samlogon_user->buffer,sizeof(nt_username),uni_samlogon_user->uni_str_len*2,0);
+ rpcstr_pull(nt_domain,uni_samlogon_domain->buffer,sizeof(nt_domain),uni_samlogon_domain->uni_str_len*2,0);
- DEBUG(3,("User:[%s]\n", nt_username));
+ DEBUG(3,("User:[%s] Requested Domain:[%s]\n", nt_username, nt_domain));
/*
* Convert to a UNIX username.
@@ -601,6 +646,17 @@ uint32 _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_
map_username(nt_username);
+ DEBUG(10,("Attempting validation level %d for mapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username));
+
+ status = _net_logon_any(q_u->sam_id.ctr, nt_username, nt_domain, p->dc.sess_key);
+
+ /* Check account and password */
+
+ if (status != NT_STATUS_NOPROBLEMO) {
+ pdb_free_sam(sampass);
+ return status;
+ }
+
pdb_init_sam(&sampass);
/* get the account information */
@@ -613,33 +669,6 @@ uint32 _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_
return NT_STATUS_NO_SUCH_USER;
}
- acct_ctrl = pdb_get_acct_ctrl(sampass);
-
- if (acct_ctrl & ACB_DISABLED) {
- pdb_free_sam(sampass);
- return NT_STATUS_ACCOUNT_DISABLED;
- }
-
- /* Validate password - if required. */
-
- if (!(acct_ctrl & ACB_PWNOTREQ)) {
- switch (q_u->sam_id.logon_level) {
- case INTERACTIVE_LOGON_TYPE:
- /* interactive login. */
- status = net_login_interactive(&q_u->sam_id.ctr->auth.id1, sampass, p);
- break;
- case NET_LOGON_TYPE:
- /* network login. lm challenge and 24 byte responses */
- status = net_login_network(&q_u->sam_id.ctr->auth.id2, sampass);
- break;
- }
- }
-
- if (status != NT_STATUS_NOPROBLEMO) {
- pdb_free_sam(sampass);
- return status;
- }
-
/* lkclXXXX this is the point at which, if the login was
successful, that the SAM Local Security Authority should
record that the user is logged in to the domain.
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index cd17de77f3..277cd13522 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -263,7 +263,9 @@ BOOL create_next_pdu(pipes_struct *p)
static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlmssp_resp)
{
uchar lm_owf[24];
- uchar nt_owf[24];
+ uchar nt_owf[128];
+ int nt_pw_len;
+ int lm_pw_len;
fstring user_name;
fstring pipe_user_name;
fstring domain;
@@ -307,13 +309,16 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm
DEBUG(5,("user: %s domain: %s wks: %s\n", user_name, domain, wks));
+ nt_pw_len = MIN(sizeof(nt_owf), ntlmssp_resp->hdr_nt_resp.str_str_len);
+ lm_pw_len = MIN(sizeof(lm_owf), ntlmssp_resp->hdr_lm_resp.str_str_len);
+
memcpy(lm_owf, ntlmssp_resp->lm_resp, sizeof(lm_owf));
- memcpy(nt_owf, ntlmssp_resp->nt_resp, sizeof(nt_owf));
+ memcpy(nt_owf, ntlmssp_resp->nt_resp, nt_pw_len);
#ifdef DEBUG_PASSWORD
DEBUG(100,("lm, nt owfs, chal\n"));
dump_data(100, (char *)lm_owf, sizeof(lm_owf));
- dump_data(100, (char *)nt_owf, sizeof(nt_owf));
+ dump_data(100, (char *)nt_owf, nt_pw_len);
dump_data(100, (char *)p->challenge, 8);
#endif
@@ -362,8 +367,11 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm
become_root();
- if(!(p->ntlmssp_auth_validated = pass_check_smb(pipe_user_name, domain,
- (uchar*)p->challenge, lm_owf, nt_owf))) {
+ if(!(p->ntlmssp_auth_validated =
+ pass_check_smb_with_chal(pipe_user_name, domain,
+ (uchar*)p->challenge,
+ lm_owf, lm_pw_len,
+ nt_owf, nt_pw_len) == NT_STATUS_NOPROBLEMO)) {
DEBUG(1,("api_pipe_ntlmssp_verify: User %s\\%s from machine %s \
failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name ));
unbecome_root();