From dec3cbcaf097a3d6fab9359e001279447a5f4def Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 16 Sep 2001 06:35:35 +0000 Subject: Fix up workstaion and kickoff time checks, moved to auth_smbpasswd.c where they can have general effect. Fixed up workstaion support in the rest of samba, so that we can do these checks. Pass through the workstation for cli_net_logon(), if supplied. (This used to be commit 7f04a139b2ee34b4c282590509cdf21395815a7a) --- source3/auth/auth.c | 23 ++++++++++--------- source3/auth/auth_sam.c | 45 +++++++++++++++++++++++++++++++++++--- source3/rpc_client/cli_login.c | 6 ++++- source3/rpc_server/srv_netlog_nt.c | 40 +++++---------------------------- source3/rpc_server/srv_pipe.c | 23 ++++++++----------- source3/smbd/auth.c | 23 ++++++++++--------- source3/smbd/auth_smbpasswd.c | 45 +++++++++++++++++++++++++++++++++++--- source3/smbd/reply.c | 11 ++++++---- 8 files changed, 136 insertions(+), 80 deletions(-) (limited to 'source3') diff --git a/source3/auth/auth.c b/source3/auth/auth.c index 0101aa65a2..5b6b2d4c42 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -25,8 +25,6 @@ extern int DEBUGLEVEL; -extern pstring global_myname; - /**************************************************************************** Check user is in correct domain if required ****************************************************************************/ @@ -63,7 +61,8 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; BOOL done_pam = False; - DEBUG(3, ("check_password: Checking password for smb user %s with the new password interface\n", user_info->smb_username.str)); + DEBUG(3, ("check_password: Checking password for smb user %s\\%s@%s with the new password interface\n", + user_info->smb_username.str, user_info->requested_domain.str, user_info->wksta_name.str)); if (!check_domain_match(user_info->smb_username.str, user_info->domain.str)) { return NT_STATUS_LOGON_FAILURE; } @@ -122,7 +121,8 @@ return True if the password is correct, False otherwise ****************************************************************************/ NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, - char *domain, uchar chal[8], + char *domain, char* workstation, + uchar chal[8], uchar *lm_pwd, int lm_pwd_len, uchar *nt_pwd, int nt_pwd_len) { @@ -158,8 +158,8 @@ NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, user_info.unix_username = unix_username; user_info.smb_username = smb_username; - user_info.wksta_name.str = client_name(); - user_info.wksta_name.len = strlen(client_name()); + wksta_name.str = workstation; + wksta_name.len = strlen(workstation); user_info.wksta_name = wksta_name; @@ -204,7 +204,8 @@ NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, return check_password(&user_info, &server_info); } -NTSTATUS pass_check_smb(char *smb_user, char *unix_user, char *domain, +NTSTATUS pass_check_smb(char *smb_user, char *unix_user, + char *domain, char *workstation, uchar *lm_pwd, int lm_pwd_len, uchar *nt_pwd, int nt_pwd_len) { @@ -214,7 +215,8 @@ NTSTATUS pass_check_smb(char *smb_user, char *unix_user, char *domain, generate_random_buffer( chal, 8, False); } - return pass_check_smb_with_chal(smb_user, unix_user, domain, chal, + return pass_check_smb_with_chal(smb_user, unix_user, + domain, workstation, chal, lm_pwd, lm_pwd_len, nt_pwd, nt_pwd_len); @@ -227,6 +229,7 @@ return True if the password is correct, False otherwise ****************************************************************************/ BOOL password_ok(char *user, char *password, int pwlen) { + extern fstring remote_machine; /* * This hack must die! But until I rewrite the rest of samba @@ -240,11 +243,11 @@ BOOL password_ok(char *user, char *password, int pwlen) /* The password could be either NTLM or plain LM. Try NTLM first, but fall-through as required. */ - if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen))) { + if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, remote_machine, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen))) { return True; } - if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0))) { + if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, remote_machine, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0))) { return True; } diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c index 111a35e068..b61fde4206 100644 --- a/source3/auth/auth_sam.c +++ b/source3/auth/auth_sam.c @@ -112,9 +112,9 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) { uint8 *nt_pw, *lm_pw; - uint16 acct_ctrl; - - acct_ctrl = pdb_get_acct_ctrl(sampass); + uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); + char *workstation_list; + time_t kickoff_time; /* Quit if the account was disabled. */ if(acct_ctrl & ACB_DISABLED) { @@ -122,6 +122,45 @@ NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use return(NT_STATUS_ACCOUNT_DISABLED); } + /* Test account expire time */ + + kickoff_time = pdb_get_kickoff_time(sampass); + if (kickoff_time != (time_t)-1) { + if (time(NULL) > kickoff_time) { + return NT_STATUS_ACCOUNT_EXPIRED; + } + } + + /* Test workstation. Workstation list is comma separated. */ + + workstation_list = strdup(pdb_get_workstations(sampass)); + + if (workstation_list) { + if (*workstation_list) { + BOOL invalid_ws = True; + char *s = workstation_list; + + fstring tok; + + while (next_token(&s, tok, ",", sizeof(tok))) { + DEBUG(10,("checking for workstation match %s and %s (len=%d)\n", + tok, user_info->wksta_name.str, user_info->wksta_name.len)); + if(strequal(tok, user_info->wksta_name.str)) { + invalid_ws = False; + break; + } + } + + free(workstation_list); + if (invalid_ws) + return NT_STATUS_INVALID_WORKSTATION; + } else { + free(workstation_list); + } + } else { + return NT_STATUS_NO_MEMORY; + } + if (acct_ctrl & ACB_PWNOTREQ) { if (lp_null_passwords()) diff --git a/source3/rpc_client/cli_login.c b/source3/rpc_client/cli_login.c index 88d3aeda83..de0c9ac62a 100644 --- a/source3/rpc_client/cli_login.c +++ b/source3/rpc_client/cli_login.c @@ -167,7 +167,11 @@ NTSTATUS cli_nt_login_network(struct cli_state *cli, /* Create the structure needed for SAM logon. */ init_id_info2(&ctr->auth.id2, user_info->domain.str, 0, smb_userid_low, 0, - user_info->smb_username.str, cli->clnt_name_slash, + user_info->smb_username.str, + /* Send our cleint's workstaion name if we have it, otherwise ours */ + ((user_info->wksta_name.len > 0) ? + user_info->wksta_name.str : + cli->clnt_name_slash), user_info->chal, user_info->lm_resp.buffer, user_info->lm_resp.len, user_info->nt_resp.buffer, user_info->nt_resp.len); diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 26da5ac061..ab5a0ff49e 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -6,6 +6,7 @@ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, * Copyright (C) Paul Ashton 1997. * Copyright (C) Jeremy Allison 1998-2001. + * Copyirht (C) Andrew Bartlett 2001. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -473,7 +474,7 @@ NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOF _net_logon_any: Use the new authentications subsystem to log in. *************************************************************************/ -static NTSTATUS _net_logon_any(NET_ID_INFO_CTR *ctr, char *user, char *domain, char *sess_key) +static NTSTATUS _net_logon_any(NET_ID_INFO_CTR *ctr, char *user, char *domain, char *workstation, char *sess_key) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; @@ -508,12 +509,10 @@ static NTSTATUS _net_logon_any(NET_ID_INFO_CTR *ctr, char *user, char *domain, c user_info.unix_username = smb_username; /* For the time-being */ user_info.smb_username = smb_username; -#if 0 - user_info.wksta_name.str = cleint_name(); - user_info.wksta_name.len = strlen(client_name()); + user_info.wksta_name.str = workstation; + user_info.wksta_name.len = strlen(workstation); user_info.wksta_name = wksta_name; -#endif DEBUG(10,("_net_logon_any: Attempting validation level %d.\n", ctr->switch_value)); switch (ctr->switch_value) { @@ -667,7 +666,7 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * 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, (char *)p->dc.sess_key); + status = _net_logon_any(q_u->sam_id.ctr, nt_username, nt_domain, nt_workstation, (char *)p->dc.sess_key); /* Check account and password */ @@ -686,35 +685,6 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * return NT_STATUS_NO_SUCH_USER; } - /* Test account expire time */ - - if (time(NULL) > sampass->kickoff_time) - return NT_STATUS_ACCOUNT_EXPIRED; - - /* Test workstation. Workstation list is comma separated. */ - - if (sampass->workstations && *sampass->workstations) { - char *s = strdup(sampass->workstations); - BOOL invalid_ws = True; - fstring tok; - - while(next_token(&s, tok, ",", sizeof(tok))) { - if(strequal(tok, nt_workstation)) { - invalid_ws = False; - break; - } - } - - free(s); - - if (invalid_ws) - return NT_STATUS_INVALID_WORKSTATION; - } - - /* Test logon hours. */ - - /* Test must change password. */ - /* 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 4a09410e81..8629592c4c 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -302,6 +302,7 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm rpcstr_pull(domain, ntlmssp_resp->domain, sizeof(fstring), ntlmssp_resp->hdr_domain.str_str_len*2, 0); rpcstr_pull(wks, ntlmssp_resp->wks, sizeof(fstring), ntlmssp_resp->hdr_wks.str_str_len*2, 0); } else { + /* What charset are these meant to be in? */ fstrcpy(user_name, ntlmssp_resp->user); fstrcpy(domain, ntlmssp_resp->domain); fstrcpy(wks, ntlmssp_resp->wks); @@ -328,24 +329,24 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm if((strlen(user_name) == 0) && (ntlmssp_resp->hdr_nt_resp.str_str_len==0)) - { + { guest_user = True; - - fstrcpy(pipe_user_name, lp_guestaccount(-1)); + + fstrcpy(pipe_user_name, lp_guestaccount(-1)); DEBUG(100,("Null user in NTLMSSP verification. Using guest = %s\n", pipe_user_name)); smb_passwd_ptr = null_smb_passwd; - + } else { /* * Pass the user through the NT -> unix user mapping * function. */ - + fstrcpy(pipe_user_name, user_name); (void)map_username(pipe_user_name); - + /* * Do the length checking only if user is not NULL. */ @@ -368,7 +369,8 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm become_root(); p->ntlmssp_auth_validated = - NT_STATUS_IS_OK(pass_check_smb_with_chal(pipe_user_name, NULL, domain, + NT_STATUS_IS_OK(pass_check_smb_with_chal(pipe_user_name, NULL, + domain, wks, (uchar*)p->challenge, lm_owf, lm_pw_len, nt_owf, nt_pw_len)); @@ -391,13 +393,6 @@ failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name unbecome_root(); - /* Quit if the account was disabled. */ - if((pdb_get_acct_ctrl(sampass) & ACB_DISABLED) || !pdb_get_lanman_passwd(sampass)) { - DEBUG(1,("Account for user '%s' was disabled.\n", pipe_user_name)); - pdb_free_sam(sampass); - return False; - } - if(!pdb_get_nt_passwd(sampass)) { DEBUG(1,("Account for user '%s' has no NT password hash.\n", pipe_user_name)); pdb_free_sam(sampass); diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c index 0101aa65a2..5b6b2d4c42 100644 --- a/source3/smbd/auth.c +++ b/source3/smbd/auth.c @@ -25,8 +25,6 @@ extern int DEBUGLEVEL; -extern pstring global_myname; - /**************************************************************************** Check user is in correct domain if required ****************************************************************************/ @@ -63,7 +61,8 @@ NTSTATUS check_password(const auth_usersupplied_info *user_info, NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; BOOL done_pam = False; - DEBUG(3, ("check_password: Checking password for smb user %s with the new password interface\n", user_info->smb_username.str)); + DEBUG(3, ("check_password: Checking password for smb user %s\\%s@%s with the new password interface\n", + user_info->smb_username.str, user_info->requested_domain.str, user_info->wksta_name.str)); if (!check_domain_match(user_info->smb_username.str, user_info->domain.str)) { return NT_STATUS_LOGON_FAILURE; } @@ -122,7 +121,8 @@ return True if the password is correct, False otherwise ****************************************************************************/ NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, - char *domain, uchar chal[8], + char *domain, char* workstation, + uchar chal[8], uchar *lm_pwd, int lm_pwd_len, uchar *nt_pwd, int nt_pwd_len) { @@ -158,8 +158,8 @@ NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, user_info.unix_username = unix_username; user_info.smb_username = smb_username; - user_info.wksta_name.str = client_name(); - user_info.wksta_name.len = strlen(client_name()); + wksta_name.str = workstation; + wksta_name.len = strlen(workstation); user_info.wksta_name = wksta_name; @@ -204,7 +204,8 @@ NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user, return check_password(&user_info, &server_info); } -NTSTATUS pass_check_smb(char *smb_user, char *unix_user, char *domain, +NTSTATUS pass_check_smb(char *smb_user, char *unix_user, + char *domain, char *workstation, uchar *lm_pwd, int lm_pwd_len, uchar *nt_pwd, int nt_pwd_len) { @@ -214,7 +215,8 @@ NTSTATUS pass_check_smb(char *smb_user, char *unix_user, char *domain, generate_random_buffer( chal, 8, False); } - return pass_check_smb_with_chal(smb_user, unix_user, domain, chal, + return pass_check_smb_with_chal(smb_user, unix_user, + domain, workstation, chal, lm_pwd, lm_pwd_len, nt_pwd, nt_pwd_len); @@ -227,6 +229,7 @@ return True if the password is correct, False otherwise ****************************************************************************/ BOOL password_ok(char *user, char *password, int pwlen) { + extern fstring remote_machine; /* * This hack must die! But until I rewrite the rest of samba @@ -240,11 +243,11 @@ BOOL password_ok(char *user, char *password, int pwlen) /* The password could be either NTLM or plain LM. Try NTLM first, but fall-through as required. */ - if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen))) { + if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, remote_machine, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen))) { return True; } - if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0))) { + if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, remote_machine, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0))) { return True; } diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c index 111a35e068..b61fde4206 100644 --- a/source3/smbd/auth_smbpasswd.c +++ b/source3/smbd/auth_smbpasswd.c @@ -112,9 +112,9 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len, NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info) { uint8 *nt_pw, *lm_pw; - uint16 acct_ctrl; - - acct_ctrl = pdb_get_acct_ctrl(sampass); + uint16 acct_ctrl = pdb_get_acct_ctrl(sampass); + char *workstation_list; + time_t kickoff_time; /* Quit if the account was disabled. */ if(acct_ctrl & ACB_DISABLED) { @@ -122,6 +122,45 @@ NTSTATUS smb_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use return(NT_STATUS_ACCOUNT_DISABLED); } + /* Test account expire time */ + + kickoff_time = pdb_get_kickoff_time(sampass); + if (kickoff_time != (time_t)-1) { + if (time(NULL) > kickoff_time) { + return NT_STATUS_ACCOUNT_EXPIRED; + } + } + + /* Test workstation. Workstation list is comma separated. */ + + workstation_list = strdup(pdb_get_workstations(sampass)); + + if (workstation_list) { + if (*workstation_list) { + BOOL invalid_ws = True; + char *s = workstation_list; + + fstring tok; + + while (next_token(&s, tok, ",", sizeof(tok))) { + DEBUG(10,("checking for workstation match %s and %s (len=%d)\n", + tok, user_info->wksta_name.str, user_info->wksta_name.len)); + if(strequal(tok, user_info->wksta_name.str)) { + invalid_ws = False; + break; + } + } + + free(workstation_list); + if (invalid_ws) + return NT_STATUS_INVALID_WORKSTATION; + } else { + free(workstation_list); + } + } else { + return NT_STATUS_NO_MEMORY; + } + if (acct_ctrl & ACB_PWNOTREQ) { if (lp_null_passwords()) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index a379bf1f7f..1559cd30df 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3,7 +3,8 @@ Version 1.9. Main SMB reply routines Copyright (C) Andrew Tridgell 1992-1998 - + Copyright (C) Andrew Bartlett 2001 + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -41,6 +42,8 @@ extern int global_oplock_break; uint32 global_client_caps = 0; unsigned int smb_echo_count = 0; +extern fstring remote_machine; + /**************************************************************************** report a possible attack via the password buffer overflow bug ****************************************************************************/ @@ -66,7 +69,7 @@ int reply_special(char *inbuf,char *outbuf) int msg_type = CVAL(inbuf,0); int msg_flags = CVAL(inbuf,1); pstring name1,name2; - extern fstring remote_machine; + extern fstring local_machine; int len; char name_type = 0; @@ -637,7 +640,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int } - DEBUG(3,("sesssetupX:name=[%s]\n",user)); + DEBUG(3,("sesssetupX:name=[%s]@[%s]\n",user, remote_machine)); /* If name ends in $ then I think it's asking about whether a */ /* computer with that name (minus the $) has access. For now */ @@ -720,7 +723,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int if (!guest) { NTSTATUS nt_status; nt_status = pass_check_smb(orig_user, user, - domain, + domain, remote_machine, (unsigned char *)smb_apasswd, smb_apasslen, (unsigned char *)smb_ntpasswd, -- cgit