summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/auth.c263
-rw-r--r--source3/smbd/auth_domain.c2
-rw-r--r--source3/smbd/auth_rhosts.c40
-rw-r--r--source3/smbd/auth_server.c27
-rw-r--r--source3/smbd/auth_smbpasswd.c228
-rw-r--r--source3/smbd/auth_unix.c17
-rw-r--r--source3/smbd/auth_util.c564
-rw-r--r--source3/smbd/password.c51
-rw-r--r--source3/smbd/reply.c37
-rw-r--r--source3/smbd/service.c12
-rw-r--r--source3/smbd/sesssetup.c356
11 files changed, 1086 insertions, 511 deletions
diff --git a/source3/smbd/auth.c b/source3/smbd/auth.c
index 4bdbdf5555..4d1a566833 100644
--- a/source3/smbd/auth.c
+++ b/source3/smbd/auth.c
@@ -50,183 +50,160 @@ static BOOL check_domain_match(char *user, char *domain)
This functions does NOT need to be in a become_root()/unbecome_root() pair
as it makes the calls itself when needed.
+
+ The return value takes precedence over the contents of the server_info
+ struct. When the return is other than NT_STATUS_NOPROBLEMO the contents
+ of that structure is undefined.
+
****************************************************************************/
NTSTATUS check_password(const auth_usersupplied_info *user_info,
- auth_serversupplied_info *server_info)
+ auth_serversupplied_info **server_info)
{
NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
BOOL done_pam = False;
-
- 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)) {
+
+ DEBUG(3, ("check_password: Checking password for unmapped user %s\\%s@%s with the new password interface\n",
+ user_info->smb_name.str, user_info->client_domain.str, user_info->wksta_name.str));
+
+ /* This needs to be sorted: If it doesn't match, what should we do? */
+ if (!check_domain_match(user_info->smb_name.str, user_info->domain.str)) {
return NT_STATUS_LOGON_FAILURE;
}
if (!NT_STATUS_IS_OK(nt_status)) {
nt_status = check_rhosts_security(user_info, server_info);
+ if (NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(7, ("check_password: Password (rhosts) for user %s suceeded\n", user_info->smb_name.str));
+ } else {
+ DEBUG(5, ("check_password: Password (rhosts)for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status)));
+
+ }
}
if ((lp_security() == SEC_DOMAIN) && !NT_STATUS_IS_OK(nt_status)) {
nt_status = check_domain_security(user_info, server_info);
+ if (NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(7, ("check_password: Password (domain) for user %s suceeded\n", user_info->smb_name.str));
+ } else {
+ DEBUG(5, ("check_password: Password (domain) for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status)));
+
+ }
}
if ((lp_security() == SEC_SERVER) && !NT_STATUS_IS_OK(nt_status)) {
nt_status = check_server_security(user_info, server_info);
+ if (NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(7, ("check_password: Password (server) for user %s suceeded\n", user_info->smb_name.str));
+ } else {
+ DEBUG(5, ("check_password: Password (server) for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status)));
+
+ }
}
if (lp_security() >= SEC_SERVER) {
- smb_user_control(user_info->unix_username.str, nt_status);
+ smb_user_control(user_info, *server_info, nt_status);
}
if (!NT_STATUS_IS_OK(nt_status)) {
- if ((user_info->plaintext_password.len > 0)
- && (!lp_plaintext_to_smbpasswd())) {
+ if (user_info->encrypted || lp_plaintext_to_smbpasswd()) {
+ nt_status = check_smbpasswd_security(user_info, server_info);
+ } else {
nt_status = check_unix_security(user_info, server_info);
done_pam = True;
- } else {
- nt_status = check_smbpasswd_security(user_info, server_info);
}
+
+ if (NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(7, ("check_password: Password (unix/smbpasswd) for user %s suceeded\n", user_info->smb_name.str));
+ } else {
+ DEBUG(5, ("check_password: Password (unix/smbpasswd) for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status)));
+
+ }
}
+
if (NT_STATUS_IS_OK(nt_status) && !done_pam) {
/* We might not be root if we are an RPC call */
become_root();
- nt_status = smb_pam_accountcheck(user_info->unix_username.str);
+ nt_status = smb_pam_accountcheck(pdb_get_username((*server_info)->sam_account));
unbecome_root();
- }
+ if (NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(5, ("check_password: PAM Account for user %s suceeded\n", user_info->smb_name.str));
+ } else {
+ DEBUG(3, ("check_password: PAM Account for user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status)));
+
+ }
+ }
+
if (NT_STATUS_IS_OK(nt_status)) {
- DEBUG(5, ("check_password: Password for smb user %s suceeded\n", user_info->smb_username.str));
+ DEBUG(5, ("check_password: Password for smb user %s suceeded\n", user_info->smb_name.str));
} else {
- DEBUG(3, ("check_password: Password for smb user %s FAILED with error %s\n", user_info->smb_username.str, get_nt_error_msg(nt_status)));
-
+ DEBUG(3, ("check_password: Password for smb user %s FAILED with error %s\n", user_info->smb_name.str, get_nt_error_msg(nt_status)));
+ ZERO_STRUCTP(server_info);
}
+
return nt_status;
}
/****************************************************************************
- COMPATABILITY INTERFACES:
- ***************************************************************************/
-
-/****************************************************************************
-check if a username/password is OK assuming the password is a 24 byte
-SMB hash
-return True if the password is correct, False otherwise
+ Squash an NT_STATUS return in line with requirements for unauthenticated
+ connections. (session setups in particular)
****************************************************************************/
-NTSTATUS pass_check_smb_with_chal(char *smb_user, char *unix_user,
- char *domain, char* workstation,
- uchar chal[8],
- uchar *lm_pwd, int lm_pwd_len,
- uchar *nt_pwd, int nt_pwd_len)
+NTSTATUS nt_status_squash(NTSTATUS nt_status)
{
-
- auth_usersupplied_info user_info;
- auth_serversupplied_info server_info;
- AUTH_STR ourdomain, theirdomain, unix_username, smb_username,
- wksta_name;
- NTSTATUS result;
+ if NT_STATUS_IS_OK(nt_status) {
+ return nt_status;
+ } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) {
+ /* Match WinXP and don't give the game away */
+ return NT_STATUS_LOGON_FAILURE;
- ZERO_STRUCT(user_info);
- ZERO_STRUCT(ourdomain);
- ZERO_STRUCT(theirdomain);
- ZERO_STRUCT(smb_username);
- ZERO_STRUCT(wksta_name);
-
- ourdomain.str = lp_workgroup();
- ourdomain.len = strlen(ourdomain.str);
-
- theirdomain.str = domain;
- theirdomain.len = strlen(theirdomain.str);
-
- user_info.requested_domain = theirdomain;
- user_info.domain = ourdomain;
-
- smb_username.str = smb_user;
- smb_username.len = strlen(smb_username.str);
-
- /* If unix user is NULL, use smb user */
-
- unix_username.str = unix_user ? unix_user : smb_user;
- unix_username.len = strlen(unix_username.str);
-
- user_info.unix_username = unix_username;
- user_info.smb_username = smb_username;
-
- wksta_name.str = workstation;
- wksta_name.len = strlen(workstation);
-
- user_info.wksta_name = wksta_name;
-
- memcpy(user_info.chal, chal, 8);
-
- if ((lm_pwd_len >= 24 || nt_pwd_len >= 24) ||
- (lp_encrypted_passwords() && (lm_pwd_len == 0) && lp_null_passwords())) {
- /* if 24 bytes long assume it is an encrypted password */
-
- user_info.lm_resp.buffer = (uint8 *)lm_pwd;
- user_info.lm_resp.len = lm_pwd_len;
- user_info.nt_resp.buffer = (uint8 *)nt_pwd;
- user_info.nt_resp.len = nt_pwd_len;
-
+ } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) {
+ /* Match WinXP and don't give the game away */
+ return NT_STATUS_LOGON_FAILURE;
} else {
- unsigned char local_lm_response[24];
- unsigned char local_nt_response[24];
-
- /*
- * Not encrypted - do so.
- */
-
- DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n"));
-
- if (lm_pwd_len > 0) {
- SMBencrypt( (uchar *)lm_pwd, user_info.chal, local_lm_response);
- user_info.lm_resp.buffer = (uint8 *)local_lm_response;
- user_info.lm_resp.len = 24;
-
-
- /* WATCH OUT. This doesn't work if the incoming password is incorrectly cased.
- We might want to add a check here and only do an LM in that case */
+ return nt_status;
+ }
+}
- /* This encrypts the lm_pwd feild, which actualy contains the password
- rather than the nt_pwd field becouse that contains nothing */
- SMBNTencrypt((uchar *)lm_pwd, user_info.chal, local_nt_response);
- user_info.nt_resp.buffer = (uint8 *)local_nt_response;
- user_info.nt_resp.len = 24;
- }
-
- user_info.plaintext_password.str = (char *)lm_pwd;
- user_info.plaintext_password.len = lm_pwd_len;
- }
- result = check_password(&user_info, &server_info);
+/****************************************************************************
+ COMPATABILITY INTERFACES:
+ ***************************************************************************/
- free_serversupplied_info(&server_info); /* No info needed */
+/****************************************************************************
+check if a username/password is OK assuming the password is a 24 byte
+SMB hash
+return True if the password is correct, False otherwise
+****************************************************************************/
- return result;
-}
+static NTSTATUS pass_check_smb(char *smb_name,
+ char *domain,
+ DATA_BLOB lm_pwd,
+ DATA_BLOB nt_pwd,
+ DATA_BLOB plaintext_password,
+ BOOL encrypted)
-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)
{
- uchar chal[8];
-
- if (!last_challenge(chal)) {
- generate_random_buffer( chal, 8, False);
- }
-
- return pass_check_smb_with_chal(smb_user, unix_user,
- domain, workstation, chal,
- lm_pwd, lm_pwd_len,
- nt_pwd, nt_pwd_len);
-
+ NTSTATUS nt_status;
+ auth_usersupplied_info *user_info = NULL;
+ auth_serversupplied_info *server_info = NULL;
+
+ make_user_info_for_reply(&user_info, smb_name,
+ domain,
+ lm_pwd,
+ nt_pwd,
+ plaintext_password,
+ encrypted);
+
+ nt_status = check_password(user_info, &server_info);
+ free_user_info(&user_info);
+ free_server_info(&server_info);
+ return nt_status;
}
/****************************************************************************
@@ -234,36 +211,32 @@ check if a username/password pair is OK either via the system password
database or the encrypted SMB password database
return True if the password is correct, False otherwise
****************************************************************************/
-BOOL password_ok(char *user, char *password, int pwlen)
+BOOL password_ok(char *smb_name, DATA_BLOB password_blob)
{
- extern fstring remote_machine;
- /*
- * This hack must die! But until I rewrite the rest of samba
- * it must stay - abartlet 2001-08-03
- */
-
- if ((pwlen == 0) && !lp_null_passwords()) {
- DEBUG(4,("Null passwords not allowed.\n"));
- return False;
- }
-
- /* 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, remote_machine, lp_workgroup(), NULL, 0, (unsigned char *)password, pwlen))) {
- return True;
- }
+ DATA_BLOB null_password = data_blob(NULL, 0);
+ extern BOOL global_encrypted_passwords_negotiated;
- if (NT_STATUS_IS_OK(pass_check_smb(user, NULL, remote_machine, lp_workgroup(), (unsigned char *)password, pwlen, NULL, 0))) {
- return True;
+ if (global_encrypted_passwords_negotiated) {
+ /*
+ * The password could be either NTLM or plain LM. Try NTLM first,
+ * but fall-through as required.
+ * NTLMv2 makes no sense here.
+ */
+ if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, password_blob, null_password, global_encrypted_passwords_negotiated))) {
+ return True;
+ }
+
+ if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), password_blob, null_password, null_password, global_encrypted_passwords_negotiated))) {
+ return True;
+ }
+ } else {
+ if (NT_STATUS_IS_OK(pass_check_smb(smb_name, lp_workgroup(), null_password, null_password, password_blob, global_encrypted_passwords_negotiated))) {
+ return True;
+ }
}
return False;
}
-/* Free a auth_serversupplied_info structure */
-void free_serversupplied_info(auth_serversupplied_info *server_info)
-{
- SAFE_FREE(server_info->group_rids);
-}
diff --git a/source3/smbd/auth_domain.c b/source3/smbd/auth_domain.c
index bcd41bacdb..f20da19607 100644
--- a/source3/smbd/auth_domain.c
+++ b/source3/smbd/auth_domain.c
@@ -29,7 +29,7 @@ BOOL global_machine_password_needs_changing = False;
****************************************************************************/
NTSTATUS check_domain_security(const auth_usersupplied_info *user_info,
- auth_serversupplied_info *server_info)
+ auth_serversupplied_info **server_info)
{
NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
char *p, *pserver;
diff --git a/source3/smbd/auth_rhosts.c b/source3/smbd/auth_rhosts.c
index 9f5f1e10e5..9c07e48a9b 100644
--- a/source3/smbd/auth_rhosts.c
+++ b/source3/smbd/auth_rhosts.c
@@ -131,11 +131,11 @@ static BOOL check_user_equiv(const char *user, const char *remote, const char *e
/****************************************************************************
check for a possible hosts equiv or rhosts entry for the user
****************************************************************************/
-static BOOL check_hosts_equiv(char *user) /* should be const... */
+
+static BOOL check_hosts_equiv(struct passwd *pass)
{
char *fname = NULL;
pstring rhostsfile;
- struct passwd *pass = Get_Pwnam(user);
if (!pass)
return(False);
@@ -149,15 +149,15 @@ static BOOL check_hosts_equiv(char *user) /* should be const... */
}
if (lp_use_rhosts())
- {
- char *home = pass->pw_dir;
- if (home) {
- slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home);
- if (check_user_equiv(pass->pw_name,client_name(),rhostsfile))
- return(True);
- }
- }
-
+ {
+ char *home = pass->pw_dir;
+ if (home) {
+ slprintf(rhostsfile, sizeof(rhostsfile)-1, "%s/.rhosts", home);
+ if (check_user_equiv(pass->pw_name,client_name(),rhostsfile))
+ return(True);
+ }
+ }
+
return(False);
}
@@ -166,15 +166,21 @@ static BOOL check_hosts_equiv(char *user) /* should be const... */
****************************************************************************/
NTSTATUS check_rhosts_security(const auth_usersupplied_info *user_info,
- auth_serversupplied_info *server_info)
+ auth_serversupplied_info **server_info)
{
NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
-
- become_root();
- if (check_hosts_equiv(user_info->unix_username.str)) {
- nt_status = NT_STATUS_OK;
+ struct passwd *pass = Get_Pwnam(user_info->internal_username.str);
+
+ if (pass) {
+ become_root();
+ if (check_hosts_equiv(pass)) {
+ nt_status = NT_STATUS_OK;
+ make_server_info_pw(server_info, pass);
+ }
+ unbecome_root();
+ } else {
+ nt_status = NT_STATUS_NO_SUCH_USER;
}
- unbecome_root();
return nt_status;
}
diff --git a/source3/smbd/auth_server.c b/source3/smbd/auth_server.c
index 520417e3e0..ddbc284d50 100644
--- a/source3/smbd/auth_server.c
+++ b/source3/smbd/auth_server.c
@@ -115,7 +115,7 @@ struct cli_state *server_cryptkey(void)
- Validate a password with the password server.
****************************************************************************/
-NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info)
+NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info)
{
struct cli_state *cli;
static unsigned char badpass[24];
@@ -134,8 +134,8 @@ NTSTATUS check_server_security(const auth_usersupplied_info *user_info, auth_ser
if(badpass[0] == 0)
memset(badpass, 0x1f, sizeof(badpass));
- if((user_info->nt_resp.len == sizeof(badpass)) &&
- !memcmp(badpass, user_info->nt_resp.buffer, sizeof(badpass))) {
+ if((user_info->nt_resp.length == sizeof(badpass)) &&
+ !memcmp(badpass, user_info->nt_resp.data, sizeof(badpass))) {
/*
* Very unlikely, our random bad password is the same as the users
* password.
@@ -206,11 +206,11 @@ use this machine as the password server.\n"));
* not guest enabled, we can try with the real password.
*/
- if (!cli_session_setup(cli, user_info->smb_username.str,
- (char *)user_info->lm_resp.buffer,
- user_info->lm_resp.len,
- (char *)user_info->nt_resp.buffer,
- user_info->nt_resp.len,
+ if (!cli_session_setup(cli, user_info->smb_name.str,
+ (char *)user_info->lm_resp.data,
+ user_info->lm_resp.length,
+ (char *)user_info->nt_resp.data,
+ user_info->nt_resp.length,
user_info->domain.str)) {
DEBUG(1,("password server %s rejected the password\n", cli->desthost));
/* Make this cli_nt_error() when the conversion is in */
@@ -227,5 +227,16 @@ use this machine as the password server.\n"));
cli_ulogoff(cli);
+ if NT_STATUS_IS_OK(nt_status) {
+ struct passwd *pass = Get_Pwnam(user_info->internal_username.str);
+ if (pass) {
+ if (!make_server_info_pw(server_info, pass)) {
+ nt_status = NT_STATUS_NO_MEMORY;
+ }
+ } else {
+ nt_status = NT_STATUS_NO_SUCH_USER;
+ }
+ }
+
return(nt_status);
}
diff --git a/source3/smbd/auth_smbpasswd.c b/source3/smbd/auth_smbpasswd.c
index 84ca8d03be..d4283429ce 100644
--- a/source3/smbd/auth_smbpasswd.c
+++ b/source3/smbd/auth_smbpasswd.c
@@ -26,53 +26,65 @@
/****************************************************************************
core of smb password checking routine.
****************************************************************************/
-static BOOL smb_pwd_check_ntlmv1(const uchar *password,
+static BOOL smb_pwd_check_ntlmv1(DATA_BLOB nt_response,
const uchar *part_passwd,
- const uchar *c8,
- char user_sess_key[16])
+ DATA_BLOB sec_blob,
+ uint8 user_sess_key[16])
{
- /* Finish the encryption of part_passwd. */
- uchar p24[24];
-
- if (part_passwd == NULL) {
- DEBUG(10,("No password set - DISALLOWING access\n"));
- /* No password set - always false ! */
- return False;
- }
+ /* Finish the encryption of part_passwd. */
+ uchar p24[24];
+
+ if (part_passwd == NULL) {
+ DEBUG(10,("No password set - DISALLOWING access\n"));
+ /* No password set - always false ! */
+ return False;
+ }
+
+ if (sec_blob.length != 8) {
+ DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challange size (%d)\n", sec_blob.length));
+ return False;
+ }
+
+ if (nt_response.length != 24) {
+ DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", nt_response.length));
+ return False;
+ }
- SMBOWFencrypt(part_passwd, c8, p24);
+ SMBOWFencrypt(part_passwd, sec_blob.data, p24);
if (user_sess_key != NULL)
{
SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key);
}
-
-
-
+
+
+
#if DEBUG_PASSWORD
DEBUG(100,("Part password (P16) was |"));
dump_data(100, part_passwd, 16);
DEBUG(100,("Password from client was |"));
- dump_data(100, password, 24);
+ dump_data(100, nt_response.data, nt_response.length);
DEBUG(100,("Given challenge was |"));
- dump_data(100, c8, 8);
+ dump_data(100, sec_blob.data, sec_blob.length);
DEBUG(100,("Value from encryption was |"));
dump_data(100, p24, 24);
#endif
- return (memcmp(p24, password, 24) == 0);
+ return (memcmp(p24, nt_response.data, 24) == 0);
}
/****************************************************************************
core of smb password checking routine.
****************************************************************************/
-static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len,
+static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response,
const uchar *part_passwd,
- const uchar *c8,
+ const DATA_BLOB sec_blob,
const char *user, const char *domain,
- char user_sess_key[16])
+ uint8 user_sess_key[16])
{
/* Finish the encryption of part_passwd. */
uchar kr[16];
- uchar resp[16];
+ uchar value_from_encryption[16];
+ uchar client_response[16];
+ DATA_BLOB client_key_data;
if (part_passwd == NULL)
{
@@ -81,25 +93,42 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len,
return False;
}
+ if (ntv2_response.length < 16) {
+ /* We MUST have more than 16 bytes, or the stuff below will go
+ crazy... */
+ DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n",
+ ntv2_response.length));
+ return False;
+ }
+
+ client_key_data = data_blob(ntv2_response.data+16, ntv2_response.length-16);
+ memcpy(client_response, ntv2_response.data, ntv2_response.length);
+
+ if (!client_key_data.data) {
+ return False;
+ }
+
ntv2_owf_gen(part_passwd, user, domain, kr);
- SMBOWFencrypt_ntv2(kr, c8, 8, password+16, pwd_len-16, (char *)resp);
+ SMBOWFencrypt_ntv2(kr, sec_blob, client_key_data, (char *)value_from_encryption);
if (user_sess_key != NULL)
{
- SMBsesskeygen_ntv2(kr, resp, user_sess_key);
+ SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key);
}
#if DEBUG_PASSWORD
DEBUG(100,("Part password (P16) was |"));
dump_data(100, part_passwd, 16);
DEBUG(100,("Password from client was |"));
- dump_data(100, password, pwd_len);
+ dump_data(100, ntv2_response.data, ntv2_response.length);
+ DEBUG(100,("Variable data from client was |"));
+ dump_data(100, ntv2_response.data, ntv2_response.length);
DEBUG(100,("Given challenge was |"));
- dump_data(100, c8, 8);
+ dump_data(100, sec_blob.data, sec_blob.length);
DEBUG(100,("Value from encryption was |"));
- dump_data(100, resp, 16);
+ dump_data(100, value_from_encryption, 16);
#endif
-
- return (memcmp(resp, password, 16) == 0);
+ data_blob_clear_free(&client_key_data);
+ return (memcmp(value_from_encryption, client_response, 16) == 0);
}
@@ -107,11 +136,12 @@ static BOOL smb_pwd_check_ntlmv2(const uchar *password, size_t pwd_len,
Do a specific test for an smb password being correct, given a smb_password and
the lanman and NT responses.
****************************************************************************/
-NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, char user_sess_key[16])
+NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info, uint8 user_sess_key[16])
{
const uint8 *nt_pw, *lm_pw;
uint16 acct_ctrl = pdb_get_acct_ctrl(sampass);
-
+ uint32 ntlmssp_flags;
+
if (!user_info || !sampass)
return NT_STATUS_LOGON_FAILURE;
@@ -119,12 +149,12 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use
{
if (lp_null_passwords())
{
- DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", sampass->username));
+ DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", pdb_get_username(sampass)));
return(NT_STATUS_OK);
}
else
{
- DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", sampass->username));
+ DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", pdb_get_username(sampass)));
return(NT_STATUS_LOGON_FAILURE);
}
}
@@ -132,61 +162,84 @@ NTSTATUS sam_password_ok(SAM_ACCOUNT *sampass, const auth_usersupplied_info *use
nt_pw = pdb_get_nt_passwd(sampass);
lm_pw = pdb_get_lanman_passwd(sampass);
- if (nt_pw != NULL && user_info->nt_resp.len > 0) {
- if ((user_info->nt_resp.len > 24 )) {
+ ntlmssp_flags = user_info->ntlmssp_flags;
+
+ if (nt_pw == NULL) {
+ DEBUG(3,("smb_password_ok: NO NT password stored for user %s.\n",
+ pdb_get_username(sampass)));
+ /* No return, we want to check the LM hash below in this case */
+ ntlmssp_flags &= (~(NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2));
+ }
+
+ if (ntlmssp_flags & NTLMSSP_NEGOTIATE_NTLM2) {
/* We have the NT MD4 hash challenge available - see if we can
use it (ie. does it exist in the smbpasswd file).
*/
DEBUG(4,("smb_password_ok: Checking NTLMv2 password\n"));
- if (smb_pwd_check_ntlmv2( user_info->nt_resp.buffer,
- user_info->nt_resp.len,
+ if (smb_pwd_check_ntlmv2( user_info->nt_resp,
nt_pw,
- user_info->chal, user_info->smb_username.str,
- user_info->requested_domain.str,
+ user_info->sec_blob, user_info->smb_name.str,
+ user_info->client_domain.str,
user_sess_key))
{
return NT_STATUS_OK;
} else {
- DEBUG(4,("smb_password_ok: NTLMv2 password check failed\n"));
- return NT_STATUS_WRONG_PASSWORD;
+ DEBUG(3,("smb_password_ok: NTLMv2 password check failed\n"));
+ return NT_STATUS_WRONG_PASSWORD;
}
-
- } else if (lp_ntlm_auth() && (user_info->nt_resp.len == 24)) {
+ } else if (ntlmssp_flags & NTLMSSP_NEGOTIATE_NTLM) {
+ if (lp_ntlm_auth()) {
/* We have the NT MD4 hash challenge available - see if we can
use it (ie. does it exist in the smbpasswd file).
*/
- DEBUG(4,("smb_password_ok: Checking NT MD4 password\n"));
- if (smb_pwd_check_ntlmv1(user_info->nt_resp.buffer,
- nt_pw, user_info->chal,
- user_sess_key))
- {
- return NT_STATUS_OK;
+ DEBUG(4,("smb_password_ok: Checking NT MD4 password\n"));
+ if (smb_pwd_check_ntlmv1(user_info->nt_resp,
+ nt_pw, user_info->sec_blob,
+ user_sess_key))
+ {
+ return NT_STATUS_OK;
+ } else {
+ DEBUG(3,("smb_password_ok: NT MD4 password check failed for user %s\n",pdb_get_username(sampass)));
+ return NT_STATUS_WRONG_PASSWORD;
+ }
} else {
- DEBUG(4,("smb_password_ok: NT MD4 password check failed\n"));
- return NT_STATUS_WRONG_PASSWORD;
+ DEBUG(2,("smb_password_ok: NTLMv1 passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass)));
+ /* No return, we want to check the LM hash below in this case */
}
- } else {
- return NT_STATUS_LOGON_FAILURE;
- }
}
- if (lm_pw != NULL && user_info->lm_resp.len == 24) {
- if (lp_lanman_auth()) {
- DEBUG(4,("smb_password_ok: Checking LM password\n"));
- if (smb_pwd_check_ntlmv1(user_info->lm_resp.buffer,
- lm_pw, user_info->chal,
- user_sess_key))
- {
- return NT_STATUS_OK;
- } else {
- DEBUG(4,("smb_password_ok: LM password check failed\n"));
- return NT_STATUS_WRONG_PASSWORD;
- }
+ if (lm_pw == NULL) {
+ DEBUG(3,("smb_password_ok: NO LanMan password set for user %s (and no NT password supplied)\n",pdb_get_username(sampass)));
+ ntlmssp_flags &= (~NTLMSSP_NEGOTIATE_OEM);
+ }
+
+ if (ntlmssp_flags & NTLMSSP_NEGOTIATE_OEM) {
+
+ if (user_info->lm_resp.length != 24) {
+ DEBUG(2,("smb_password_ok: invalid LanMan password length (%d) for user %s\n",
+ user_info->nt_resp.length, pdb_get_username(sampass)));
}
+
+ if (!lp_lanman_auth()) {
+ DEBUG(3,("smb_password_ok: Lanman passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass)));
+ return NT_STATUS_LOGON_FAILURE;
+ }
+
+ DEBUG(4,("smb_password_ok: Checking LM password\n"));
+ if (smb_pwd_check_ntlmv1(user_info->lm_resp,
+ lm_pw, user_info->sec_blob,
+ user_sess_key))
+ {
+ return NT_STATUS_OK;
+ } else {
+ DEBUG(4,("smb_password_ok: LM password check failed for user %s\n",pdb_get_username(sampass)));
+ return NT_STATUS_WRONG_PASSWORD;
+ }
}
- /* Should not be reached */
- return NT_STATUS_LOGON_FAILURE;
+ /* Should not be reached, but if they send nothing... */
+ DEBUG(3,("smb_password_ok: NEITHER LanMan nor NT password supplied for user %s\n",pdb_get_username(sampass)));
+ return NT_STATUS_WRONG_PASSWORD;
}
/****************************************************************************
@@ -290,33 +343,58 @@ SMB hash supplied in the user_info structure
return an NT_STATUS constant.
****************************************************************************/
-NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info)
+NTSTATUS check_smbpasswd_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info)
{
SAM_ACCOUNT *sampass=NULL;
BOOL ret;
NTSTATUS nt_status;
+ uint8 user_sess_key[16];
+ const uint8* lm_hash;
pdb_init_sam(&sampass);
/* get the account information */
become_root();
- ret = pdb_getsampwnam(sampass, user_info->unix_username.str);
+ ret = pdb_getsampwnam(sampass, user_info->internal_username.str);
unbecome_root();
if (ret == False)
{
- DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->unix_username.str));
+ DEBUG(1,("Couldn't find user '%s' in passdb file.\n", user_info->internal_username.str));
pdb_free_sam(&sampass);
return NT_STATUS_NO_SUCH_USER;
}
- nt_status = sam_password_ok(sampass, user_info, (char *)(server_info->session_key));
+ nt_status = sam_password_ok(sampass, user_info, user_sess_key);
- if NT_STATUS_IS_OK(nt_status) {
- nt_status = sam_account_ok(sampass, user_info);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ pdb_free_sam(&sampass);
+ return nt_status;
}
- pdb_free_sam(&sampass);
+ nt_status = sam_account_ok(sampass, user_info);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ pdb_free_sam(&sampass);
+ return nt_status;
+ }
+
+ if (!make_server_info_sam(server_info, sampass)) {
+ DEBUG(0,("failed to malloc memory for server_info\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ lm_hash = pdb_get_lanman_passwd((*server_info)->sam_account);
+ if (lm_hash) {
+ memcpy((*server_info)->first_8_lm_hash, lm_hash, 8);
+ }
+
+ memcpy((*server_info)->session_key, user_sess_key, sizeof(user_sess_key));
+
return nt_status;
}
+
+
+
+
diff --git a/source3/smbd/auth_unix.c b/source3/smbd/auth_unix.c
index 29a2a6eafb..d456da1fdf 100644
--- a/source3/smbd/auth_unix.c
+++ b/source3/smbd/auth_unix.c
@@ -82,22 +82,27 @@ check if a username/password is OK assuming the password
in PLAIN TEXT
****************************************************************************/
-NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info)
+NTSTATUS check_unix_security(const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info)
{
NTSTATUS nt_status;
struct passwd *pass = NULL;
become_root();
-
- pass = Get_Pwnam(user_info->unix_username.str);
+ pass = Get_Pwnam(user_info->internal_username.str);
nt_status = pass_check(pass,
- pass ? pass->pw_name : user_info->unix_username.str,
- user_info->plaintext_password.str,
- user_info->plaintext_password.len,
+ pass ? pass->pw_name : user_info->internal_username.str,
+ (char *)user_info->plaintext_password.data,
+ user_info->plaintext_password.length-1,
lp_update_encrypted() ?
update_smbpassword_file : NULL,
True);
+
+ if NT_STATUS_IS_OK(nt_status) {
+ if (pass) {
+ make_server_info_pw(server_info, pass);
+ }
+ }
unbecome_root();
diff --git a/source3/smbd/auth_util.c b/source3/smbd/auth_util.c
index d3b9aa7001..297c482af5 100644
--- a/source3/smbd/auth_util.c
+++ b/source3/smbd/auth_util.c
@@ -25,6 +25,8 @@
/* Data to do lanman1/2 password challenge. */
static unsigned char saved_challenge[8];
static BOOL challenge_sent=False;
+extern fstring remote_machine;
+extern pstring global_myname;
/*******************************************************************
Get the next challenge value - no repeats.
@@ -64,7 +66,7 @@ BOOL last_challenge(unsigned char *challenge)
Create a UNIX user on demand.
****************************************************************************/
-static int smb_create_user(char *unix_user, char *homedir)
+static int smb_create_user(const char *unix_user, const char *homedir)
{
pstring add_script;
int ret;
@@ -100,40 +102,560 @@ static int smb_delete_user(char *unix_user)
Add and Delete UNIX users on demand, based on NTSTATUS codes.
****************************************************************************/
-void smb_user_control(char *unix_user, NTSTATUS nt_status)
+void smb_user_control(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info, NTSTATUS nt_status)
{
struct passwd *pwd=NULL;
if (NT_STATUS_IS_OK(nt_status)) {
- /*
- * User validated ok against Domain controller.
- * If the admin wants us to try and create a UNIX
- * user on the fly, do so.
- */
- if(lp_adduser_script() && !(pwd = smb_getpwnam(unix_user,True)))
- smb_create_user(unix_user, NULL);
-
- if(lp_adduser_script() && pwd) {
- SMB_STRUCT_STAT st;
+ if (!(server_info->sam_fill_level & SAM_FILL_UNIX)) {
+
/*
- * Also call smb_create_user if the users home directory
- * doesn't exist. Used with winbindd to allow the script to
- * create the home directory for a user mapped with winbindd.
+ * User validated ok against Domain controller.
+ * If the admin wants us to try and create a UNIX
+ * user on the fly, do so.
*/
+
+ if(lp_adduser_script() && !(pwd = Get_Pwnam(user_info->internal_username.str))) {
+ smb_create_user(user_info->internal_username.str, NULL);
+ }
+ } else {
+ if(lp_adduser_script()) {
+ SMB_STRUCT_STAT st;
+ const char *home_dir = pdb_get_homedir(server_info->sam_account);
+ /*
+ * Also call smb_create_user if the users home directory
+ * doesn't exist. Used with winbindd to allow the script to
+ * create the home directory for a user mapped with winbindd.
+ */
- if (pwd->pw_dir && (sys_stat(pwd->pw_dir, &st) == -1) && (errno == ENOENT))
- smb_create_user(unix_user, pwd->pw_dir);
+ if (home_dir &&
+ (sys_stat(home_dir, &st) == -1) && (errno == ENOENT)) {
+ smb_create_user(user_info->internal_username.str, home_dir);
+ }
+ }
}
-
- } else if (NT_STATUS_V(nt_status) == NT_STATUS_V(NT_STATUS_NO_SUCH_USER)) {
+ } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) {
/*
* User failed to validate ok against Domain controller.
* If the failure was "user doesn't exist" and admin
* wants us to try and delete that UNIX user on the fly,
* do so.
*/
- if(lp_deluser_script() && smb_getpwnam(unix_user,True))
- smb_delete_user(unix_user);
+ if (lp_deluser_script()) {
+ smb_delete_user(user_info->internal_username.str);
+ }
+ }
+}
+
+/****************************************************************************
+ Create an auth_usersupplied_data structure
+****************************************************************************/
+
+BOOL make_user_info(auth_usersupplied_info **user_info,
+ char *smb_name, char *internal_username,
+ char *client_domain, char *domain,
+ char *wksta_name, DATA_BLOB sec_blob,
+ DATA_BLOB lm_pwd, DATA_BLOB nt_pwd,
+ DATA_BLOB plaintext,
+ uint32 ntlmssp_flags, BOOL encrypted)
+{
+
+ DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name));
+
+ *user_info = malloc(sizeof(**user_info));
+ if (!user_info) {
+ DEBUG(0,("malloc failed for user_info (size %d)\n", sizeof(*user_info)));
+ return False;
+ }
+
+ ZERO_STRUCTP(*user_info);
+
+ DEBUG(5,("makeing strings for %s's user_info struct\n", internal_username));
+
+ (*user_info)->smb_name.str = strdup(smb_name);
+ if ((*user_info)->smb_name.str) {
+ (*user_info)->smb_name.len = strlen(smb_name);
+ } else {
+ free_user_info(user_info);
+ return False;
+ }
+
+ (*user_info)->internal_username.str = strdup(internal_username);
+ if ((*user_info)->internal_username.str) {
+ (*user_info)->internal_username.len = strlen(internal_username);
+ } else {
+ free_user_info(user_info);
+ return False;
+ }
+
+ (*user_info)->domain.str = strdup(domain);
+ if ((*user_info)->domain.str) {
+ (*user_info)->domain.len = strlen(domain);
+ } else {
+ free_user_info(user_info);
+ return False;
+ }
+
+ (*user_info)->client_domain.str = strdup(client_domain);
+ if ((*user_info)->client_domain.str) {
+ (*user_info)->client_domain.len = strlen(client_domain);
+ } else {
+ free_user_info(user_info);
+ return False;
+ }
+
+ (*user_info)->wksta_name.str = strdup(wksta_name);
+ if ((*user_info)->wksta_name.str) {
+ (*user_info)->wksta_name.len = strlen(wksta_name);
+ } else {
+ free_user_info(user_info);
+ return False;
}
+
+ DEBUG(5,("makeing blobs for %s's user_info struct\n", internal_username));
+
+ (*user_info)->sec_blob = data_blob(sec_blob.data, sec_blob.length);
+ (*user_info)->lm_resp = data_blob(lm_pwd.data, lm_pwd.length);
+ (*user_info)->nt_resp = data_blob(nt_pwd.data, nt_pwd.length);
+ (*user_info)->plaintext_password = data_blob(plaintext.data, plaintext.length);
+
+ (*user_info)->encrypted = encrypted;
+ (*user_info)->ntlmssp_flags = ntlmssp_flags;
+
+ DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name));
+
+ return True;
}
+
+/****************************************************************************
+ Create an auth_usersupplied_data structure after appropriate mapping.
+****************************************************************************/
+
+BOOL make_user_info_map(auth_usersupplied_info **user_info,
+ char *smb_name,
+ char *client_domain,
+ char *wksta_name, DATA_BLOB sec_blob,
+ DATA_BLOB lm_pwd, DATA_BLOB nt_pwd,
+ DATA_BLOB plaintext,
+ uint32 ntlmssp_flags, BOOL encrypted)
+{
+ char *domain;
+ fstring internal_username;
+ fstrcpy(internal_username, smb_name);
+ map_username(internal_username);
+
+ if (lp_allow_trusted_domains()) {
+ domain = client_domain;
+ } else {
+ domain = lp_workgroup();
+ }
+
+ return make_user_info(user_info,
+ smb_name, internal_username,
+ client_domain, domain,
+ wksta_name, sec_blob,
+ lm_pwd, nt_pwd,
+ plaintext,
+ ntlmssp_flags, encrypted);
+
+}
+
+/****************************************************************************
+ Create an auth_usersupplied_data, making the DATA_BLOBs here.
+ Decrupt and encrypt the passwords.
+****************************************************************************/
+
+BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info,
+ char *smb_name,
+ char *client_domain,
+ char *wksta_name, uchar chal[8],
+ uchar *lm_network_pwd, int lm_pwd_len,
+ uchar *nt_network_pwd, int nt_pwd_len)
+{
+ BOOL ret;
+ DATA_BLOB sec_blob = data_blob(chal, sizeof(chal));
+ DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
+ DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
+ DATA_BLOB plaintext_blob = data_blob(NULL, 0);
+ uint32 ntlmssp_flags = 0;
+
+ if (lm_pwd_len)
+ ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM;
+ if (nt_pwd_len)
+ ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM;
+
+ ret = make_user_info_map(user_info,
+ smb_name, client_domain,
+ wksta_name, sec_blob,
+ nt_blob, lm_blob,
+ plaintext_blob,
+ ntlmssp_flags, True);
+
+ data_blob_free(&lm_blob);
+ data_blob_free(&nt_blob);
+ return ret;
+}
+
+/****************************************************************************
+ Create an auth_usersupplied_data, making the DATA_BLOBs here.
+ Decrupt and encrypt the passwords.
+****************************************************************************/
+
+BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
+ char *smb_name,
+ char *client_domain,
+ char *wksta_name,
+ uchar *lm_interactive_pwd, int lm_pwd_len,
+ uchar *nt_interactive_pwd, int nt_pwd_len,
+ uchar *dc_sess_key)
+{
+ char nt_pwd[16];
+ char lm_pwd[16];
+ unsigned char local_lm_response[24];
+ unsigned char local_nt_response[24];
+ unsigned char key[16];
+ uint8 chal[8];
+ uint32 ntlmssp_flags = 0;
+
+ generate_random_buffer(chal, 8, False);
+
+ memset(key, 0, 16);
+ memcpy(key, dc_sess_key, 8);
+
+ memcpy(lm_pwd, lm_interactive_pwd, 16);
+ memcpy(nt_pwd, nt_interactive_pwd, 16);
+
+#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
+
+ generate_random_buffer(chal, 8, False);
+ SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response);
+ SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response);
+
+ /* Password info parinoia */
+ ZERO_STRUCT(lm_pwd);
+ ZERO_STRUCT(nt_pwd);
+ ZERO_STRUCT(key);
+
+ {
+ BOOL ret;
+ DATA_BLOB sec_blob = data_blob(chal, sizeof(chal));
+ DATA_BLOB local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
+ DATA_BLOB local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
+ DATA_BLOB plaintext_blob = data_blob(NULL, 0);
+
+ ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_NTLM;
+ ret = make_user_info_map(user_info,
+ smb_name, client_domain,
+ wksta_name, sec_blob,
+ local_nt_blob,
+ local_lm_blob,
+ plaintext_blob,
+ ntlmssp_flags, True);
+
+ data_blob_free(&local_lm_blob);
+ data_blob_free(&local_nt_blob);
+ return ret;
+ }
+}
+
+/****************************************************************************
+ Create an auth_usersupplied_data structure
+****************************************************************************/
+
+BOOL make_user_info_for_winbind(auth_usersupplied_info **user_info,
+ char *username,
+ char *domain,
+ char *password)
+{
+ unsigned char local_lm_response[24];
+ unsigned char local_nt_response[24];
+ char chal[8];
+ DATA_BLOB local_lm_blob;
+ DATA_BLOB local_nt_blob;
+ DATA_BLOB plaintext_blob;
+ uint32 ntlmssp_flags = 0;
+
+ /*
+ * Not encrypted - do so.
+ */
+
+ DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n"));
+
+ generate_random_buffer(chal, 8, False);
+
+ if (*password) {
+ SMBencrypt( (uchar *)password, chal, local_lm_response);
+
+ /* This encrypts the lm_pwd feild, which actualy contains the password
+ rather than the nt_pwd field becouse that contains nothing */
+
+ /* WATCH OUT. This doesn't work if the incoming password is incorrectly cased.
+ We might want to add a check here and only do an LM in that case */
+
+ SMBNTencrypt((uchar *)password, chal, local_nt_response);
+
+ local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
+ local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
+ plaintext_blob = data_blob(password, strlen(password)+1);
+ if ((!local_lm_blob.data) || (!local_nt_blob.data)|| (!plaintext_blob.data)) {
+ data_blob_free(&local_lm_blob);
+ data_blob_free(&local_nt_blob);
+ data_blob_clear_free(&plaintext_blob);
+ return False;
+ }
+ ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM | NTLMSSP_NEGOTIATE_NTLM;
+ } else {
+ local_lm_blob = data_blob(NULL, 0);
+ local_nt_blob = data_blob(NULL, 0);
+ plaintext_blob = data_blob(NULL, 0);
+ }
+
+ {
+ BOOL ret;
+ DATA_BLOB sec_blob = data_blob(chal, sizeof(chal));
+
+ if (!sec_blob.data) {
+ return False;
+ }
+
+ ret = make_user_info(user_info,
+ username, username,
+ domain, domain,
+ global_myname, sec_blob,
+ local_nt_blob,
+ local_lm_blob,
+ plaintext_blob,
+ ntlmssp_flags, False);
+
+ data_blob_free(&local_lm_blob);
+ data_blob_free(&local_nt_blob);
+ data_blob_clear_free(&plaintext_blob);
+ return ret;
+ }
+}
+
+/****************************************************************************
+ Create an auth_usersupplied_data, making the DATA_BLOBs here.
+ Decrupt and encrypt the passwords.
+****************************************************************************/
+
+BOOL make_user_info_winbind_crap(auth_usersupplied_info **user_info,
+ char *smb_name,
+ char *client_domain,
+ uchar chal[8],
+ uchar *lm_network_pwd, int lm_pwd_len,
+ uchar *nt_network_pwd, int nt_pwd_len)
+{
+ BOOL ret;
+ DATA_BLOB sec_blob = data_blob(chal, sizeof(chal));
+ DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
+ DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
+ DATA_BLOB plaintext_blob = data_blob(NULL, 0);
+ uint32 ntlmssp_flags = 0;
+
+ if (lm_pwd_len)
+ ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM;
+ if (nt_pwd_len)
+ ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM;
+
+ ret = make_user_info(user_info,
+ smb_name, smb_name,
+ client_domain, client_domain,
+ global_myname, sec_blob,
+ nt_blob, lm_blob,
+ plaintext_blob,
+ ntlmssp_flags, True);
+
+ data_blob_free(&lm_blob);
+ data_blob_free(&nt_blob);
+ return ret;
+}
+
+/****************************************************************************
+ Create an auth_usersupplied_data structure
+****************************************************************************/
+
+BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
+ char *smb_name,
+ char *client_domain,
+ DATA_BLOB lm_resp, DATA_BLOB nt_resp,
+ DATA_BLOB plaintext_password,
+ BOOL encrypted)
+{
+ uchar chal[8];
+
+ DATA_BLOB local_lm_blob;
+ DATA_BLOB local_nt_blob;
+ DATA_BLOB sec_blob;
+ BOOL ret = False;
+ uint32 ntlmssp_flags = 0;
+
+ if (encrypted) {
+ DATA_BLOB no_plaintext_blob = data_blob(NULL, 0);
+ if (!last_challenge(chal)) {
+ DEBUG(0,("Encrypted login but no challange set!\n"));
+ return False;
+ }
+ sec_blob = data_blob(chal, 8);
+
+ if (lm_resp.length == 24) {
+ ntlmssp_flags |= NTLMSSP_NEGOTIATE_OEM;
+ }
+ if (nt_resp.length == 0) {
+ } else if (nt_resp.length == 24) {
+ ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM;
+ } else {
+ ntlmssp_flags |= NTLMSSP_NEGOTIATE_NTLM2;
+ }
+
+ return make_user_info_map(user_info, smb_name,
+ client_domain,
+ remote_machine, sec_blob,
+ lm_resp,
+ nt_resp,
+ no_plaintext_blob,
+ ntlmssp_flags, encrypted);
+ }
+
+ generate_random_buffer(chal, 8, False);
+
+ sec_blob = data_blob(chal, 8);
+
+ /*
+ * Not encrypted - do so.
+ */
+
+ DEBUG(5,("pass_check_smb: User passwords not in encrypted format.\n"));
+
+ if (plaintext_password.data) {
+ unsigned char local_lm_response[24];
+
+ SMBencrypt( (uchar *)plaintext_password.data, chal, local_lm_response);
+ local_lm_blob = data_blob(local_lm_response, 24);
+
+ /* We can't do an NT hash here, as the password needs to be case insensitive */
+ local_nt_blob = data_blob(NULL, 0);
+
+ ntlmssp_flags = NTLMSSP_NEGOTIATE_OEM;
+ } else {
+ local_lm_blob = data_blob(NULL, 0);
+ local_nt_blob = data_blob(NULL, 0);
+ }
+
+ ret = make_user_info_map(user_info, smb_name,
+ client_domain,
+ remote_machine,
+ sec_blob,
+ local_lm_blob,
+ local_nt_blob,
+ plaintext_password,
+ ntlmssp_flags, encrypted);
+
+ data_blob_free(&local_lm_blob);
+ return ret;
+}
+
+BOOL make_server_info(auth_serversupplied_info **server_info)
+{
+ *server_info = malloc(sizeof(**server_info));
+ if (!*server_info) {
+ DEBUG(0,("make_server_info_sam: malloc failed!\n"));
+ return False;
+ }
+ ZERO_STRUCTP(*server_info);
+ return True;
+}
+
+BOOL make_server_info_sam(auth_serversupplied_info **server_info, SAM_ACCOUNT *sampass)
+{
+ if (!make_server_info(server_info)) {
+ return False;
+ }
+
+ (*server_info)->sam_fill_level = SAM_FILL_ALL;
+ (*server_info)->sam_account = sampass;
+
+ DEBUG(5,("make_server_info_sam: made sever info for user %s\n",
+ pdb_get_username((*server_info)->sam_account)));
+ return True;
+}
+
+BOOL make_server_info_pw(auth_serversupplied_info **server_info, struct passwd *pwd)
+{
+ SAM_ACCOUNT *sampass = NULL;
+ if (!pdb_init_sam_pw(&sampass, pwd)) {
+ return False;
+ }
+ return make_server_info_sam(server_info, sampass);
+}
+
+void free_user_info(auth_usersupplied_info **user_info)
+{
+ DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
+ if (*user_info != NULL) {
+ if ((*user_info)->smb_name.str) {
+ DEBUG(10,("structure was created for %s\n", (*user_info)->smb_name.str));
+ }
+ SAFE_FREE((*user_info)->smb_name.str);
+ SAFE_FREE((*user_info)->internal_username.str);
+ SAFE_FREE((*user_info)->client_domain.str);
+ SAFE_FREE((*user_info)->domain.str);
+ data_blob_free(&(*user_info)->sec_blob);
+ data_blob_free(&(*user_info)->lm_resp);
+ data_blob_free(&(*user_info)->nt_resp);
+ SAFE_FREE((*user_info)->interactive_password);
+ data_blob_clear_free(&(*user_info)->plaintext_password);
+ ZERO_STRUCT(**user_info);
+ }
+ SAFE_FREE(*user_info);
+}
+
+/***************************************************************************
+ Clear out a server_info struct that has been allocated
+***************************************************************************/
+void free_server_info(auth_serversupplied_info **server_info)
+{
+ if (*server_info != NULL) {
+ pdb_free_sam(&(*server_info)->sam_account);
+
+ /* call pam_end here, unless we know we are keeping it */
+ SAFE_FREE((*server_info)->group_rids);
+
+ ZERO_STRUCT(**server_info);
+ }
+ SAFE_FREE(*server_info);
+}
+
+/***************************************************************************
+ Make a server_info struct for a guest user
+***************************************************************************/
+void make_server_info_guest(auth_serversupplied_info **server_info)
+{
+ struct passwd *pass = sys_getpwnam(lp_guestaccount(-1));
+
+ if (pass) {
+ make_server_info_pw(server_info, pass);
+ }
+}
+
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index e8f40f1fa3..01eabfda5e 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -197,10 +197,11 @@ has been given. vuid is biased by an offset. This allows us to
tell random client vuid's (normally zero) from valid vuids.
****************************************************************************/
-int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name,
- char *domain,BOOL guest, char *full_name)
+int register_vuid(auth_serversupplied_info *server_info, char *smb_name, BOOL guest)
{
user_struct *vuser = NULL;
+ uid_t *puid;
+ gid_t *pgid;
/* Ensure no vuid gets registered in share level security. */
if(lp_security() == SEC_SHARE)
@@ -217,8 +218,14 @@ int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name,
ZERO_STRUCTP(vuser);
- DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)uid, (unsigned int)gid,
- unix_name, requested_name, domain, guest ));
+ puid = pdb_get_uid(server_info->sam_account);
+ pgid = pdb_get_gid(server_info->sam_account);
+
+ if (!puid || !pgid) {
+ DEBUG(0,("Attempted session setup with invalid user. No uid/gid in SAM_ACCOUNT\n"));
+ free(vuser);
+ return UID_FIELD_INVALID;
+ }
/* Allocate a free vuid. Yes this is a linear search... :-) */
while( get_valid_user_struct(next_vuid) != NULL ) {
@@ -231,13 +238,19 @@ int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name,
DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid ));
vuser->vuid = next_vuid;
- vuser->uid = uid;
- vuser->gid = gid;
+ vuser->uid = *puid;
+ vuser->gid = *pgid;
vuser->guest = guest;
- fstrcpy(vuser->user.unix_name,unix_name);
- fstrcpy(vuser->user.smb_name,requested_name);
- fstrcpy(vuser->user.domain,domain);
- fstrcpy(vuser->user.full_name, full_name);
+ fstrcpy(vuser->user.unix_name, pdb_get_username(server_info->sam_account));
+ fstrcpy(vuser->user.smb_name, smb_name);
+ fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account));
+ fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account));
+
+ DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n",
+ (unsigned int)vuser->uid,
+ (unsigned int)vuser->gid,
+ vuser->user.unix_name, vuser->user.smb_name, vuser->user.domain, guest ));
+
DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,vuser->user.full_name));
vuser->n_groups = 0;
@@ -332,7 +345,7 @@ BOOL user_ok(char *user,int snum)
/****************************************************************************
validate a group username entry. Return the username or NULL
****************************************************************************/
-static char *validate_group(char *group,char *password,int pwlen,int snum)
+static char *validate_group(char *group, DATA_BLOB password,int snum)
{
#ifdef HAVE_NETGROUP
{
@@ -341,7 +354,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum)
while (getnetgrent(&host, &user, &domain)) {
if (user) {
if (user_ok(user, snum) &&
- password_ok(user,password,pwlen)) {
+ password_ok(user,password)) {
endnetgrent();
return(user);
}
@@ -396,7 +409,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum)
static fstring name;
fstrcpy(name,member);
if (user_ok(name,snum) &&
- password_ok(name,password,pwlen)) {
+ password_ok(name,password)) {
endgrent();
return(&name[0]);
}
@@ -419,7 +432,7 @@ static char *validate_group(char *group,char *password,int pwlen,int snum)
Note this is *NOT* used when logging on using sessionsetup_and_X.
****************************************************************************/
-BOOL authorise_login(int snum,char *user,char *password, int pwlen,
+BOOL authorise_login(int snum,char *user, DATA_BLOB password,
BOOL *guest,BOOL *force,uint16 vuid)
{
BOOL ok = False;
@@ -427,7 +440,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen,
#if DEBUG_PASSWORD
DEBUG(100,("authorise_login: checking authorisation on user=%s pass=%s\n",
- user,password));
+ user,password.data));
#endif
*guest = False;
@@ -472,7 +485,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen,
/* check for a previously registered guest username */
if (!ok && (vuser != 0) && vuser->guest) {
if (user_ok(vuser->user.unix_name,snum) &&
- password_ok(vuser->user.unix_name, password, pwlen)) {
+ password_ok(vuser->user.unix_name, password)) {
fstrcpy(user, vuser->user.unix_name);
vuser->guest = False;
DEBUG(3,("authorise_login: ACCEPTED: given password with registered user %s\n", user));
@@ -494,7 +507,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen,
if (!user_ok(user2,snum))
continue;
- if (password_ok(user2,password, pwlen)) {
+ if (password_ok(user2,password)) {
ok = True;
fstrcpy(user,user2);
DEBUG(3,("authorise_login: ACCEPTED: session list username (%s) \
@@ -526,7 +539,7 @@ and given password ok\n", user));
for (auser=strtok(user_list,LIST_SEP); auser && !ok;
auser = strtok(NULL,LIST_SEP)) {
if (*auser == '@') {
- auser = validate_group(auser+1,password,pwlen,snum);
+ auser = validate_group(auser+1,password,snum);
if (auser) {
ok = True;
fstrcpy(user,auser);
@@ -536,7 +549,7 @@ and given password ok (%s)\n", user));
} else {
fstring user2;
fstrcpy(user2,auser);
- if (user_ok(user2,snum) && password_ok(user2,password,pwlen)) {
+ if (user_ok(user2,snum) && password_ok(user2,password)) {
ok = True;
fstrcpy(user,user2);
DEBUG(3,("authorise_login: ACCEPTED: user list username \
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index ca7bcb9c5f..b60738d23d 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -159,14 +159,16 @@ int reply_tcon(connection_struct *conn,
int pwlen=0;
NTSTATUS nt_status;
char *p;
-
+ DATA_BLOB password_blob;
+
START_PROFILE(SMBtcon);
*service = *password = *dev = 0;
p = smb_buf(inbuf)+1;
p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1;
- p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1;
+ pwlen = srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1;
+ p += pwlen;
p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1;
p = strrchr_m(service,'\\');
@@ -174,7 +176,9 @@ int reply_tcon(connection_struct *conn,
pstrcpy(service, p+1);
}
- conn = make_connection(service,password,pwlen,dev,vuid,&nt_status);
+ password_blob = data_blob(password, pwlen+1);
+
+ conn = make_connection(service,password_blob,dev,vuid,&nt_status);
if (!conn) {
END_PROFILE(SMBtcon);
@@ -200,16 +204,17 @@ int reply_tcon(connection_struct *conn,
int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
{
fstring service;
- pstring password;
+ DATA_BLOB password;
pstring devicename;
NTSTATUS nt_status;
uint16 vuid = SVAL(inbuf,smb_uid);
int passlen = SVAL(inbuf,smb_vwv3);
pstring path;
char *p, *q;
- START_PROFILE(SMBtconX);
-
- *service = *password = *devicename = 0;
+ extern BOOL global_encrypted_passwords_negotiated;
+ START_PROFILE(SMBtconX);
+
+ *service = *devicename = 0;
/* we might have to close an old one */
if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
@@ -220,17 +225,17 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
return ERROR_DOS(ERRDOS,ERRbuftoosmall);
}
- memcpy(password,smb_buf(inbuf),passlen);
- password[passlen]=0;
+ if (global_encrypted_passwords_negotiated) {
+ password = data_blob(smb_buf(inbuf),passlen);
+ } else {
+ password = data_blob(smb_buf(inbuf),passlen+1);
+ /* Ensure correct termination */
+ password.data[passlen]=0;
+ }
+
p = smb_buf(inbuf) + passlen;
p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
- if (passlen != 24) {
- if (strequal(password," "))
- *password = 0;
- passlen = strlen(password);
- }
-
/*
* the service name can be either: \\server\share
* or share directly like on the DELL PowerVault 705
@@ -250,7 +255,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
DEBUG(4,("Got device type %s\n",devicename));
- conn = make_connection(service,password,passlen,devicename,vuid,&nt_status);
+ conn = make_connection(service,password,devicename,vuid,&nt_status);
if (!conn) {
END_PROFILE(SMBtconX);
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 37f4610b9d..f6296201ae 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -79,7 +79,7 @@ BOOL set_current_service(connection_struct *conn,BOOL do_chdir)
Add a home service. Returns the new service number or -1 if fail.
****************************************************************************/
-int add_home_service(char *service, char *homedir)
+int add_home_service(const char *service, const char *homedir)
{
int iHomeService;
int iService;
@@ -320,8 +320,8 @@ static void set_admin_user(connection_struct *conn)
Make a connection to a service.
****************************************************************************/
-connection_struct *make_connection(char *service,char *password,
- int pwlen, char *dev,uint16 vuid, NTSTATUS *status)
+connection_struct *make_connection(char *service, DATA_BLOB password,
+ char *dev,uint16 vuid, NTSTATUS *status)
{
int snum;
struct passwd *pass = NULL;
@@ -361,7 +361,7 @@ connection_struct *make_connection(char *service,char *password,
if (validated_username(vuid)) {
fstring unix_username;
fstrcpy(unix_username,validated_username(vuid));
- return(make_connection(unix_username,password,pwlen,dev,vuid,status));
+ return(make_connection(unix_username,password,dev,vuid,status));
}
} else {
/* Security = share. Try with current_user_info.smb_name
@@ -370,7 +370,7 @@ connection_struct *make_connection(char *service,char *password,
fstring unix_username;
fstrcpy(unix_username,current_user_info.smb_name);
map_username(unix_username);
- return(make_connection(unix_username,password,pwlen,dev,vuid,status));
+ return(make_connection(unix_username,password,dev,vuid,status));
}
}
}
@@ -387,7 +387,7 @@ connection_struct *make_connection(char *service,char *password,
/* shall we let them in? */
- if (!authorise_login(snum,user,password,pwlen,&guest,&force,vuid)) {
+ if (!authorise_login(snum,user,password,&guest,&force,vuid)) {
DEBUG( 2, ( "Invalid username/password for %s [%s]\n", service, user ) );
*status = NT_STATUS_WRONG_PASSWORD;
return NULL;
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 2d9f624b80..5331127cb5 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -264,14 +264,16 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
DATA_BLOB auth;
char *workgroup, *user, *machine;
DATA_BLOB lmhash, nthash, sess_key;
+ DATA_BLOB plaintext_password = data_blob(NULL, 0);
+ DATA_BLOB sec_blob;
uint32 ntlmssp_command, neg_flags;
NTSTATUS nt_status;
int sess_vuid;
- gid_t gid;
- uid_t uid;
- char *full_name;
char *p;
- const struct passwd *pw;
+ char chal[8];
+
+ auth_usersupplied_info *user_info = NULL;
+ auth_serversupplied_info *server_info = NULL;
if (!spnego_parse_auth(blob1, &auth)) {
#if 0
@@ -305,36 +307,40 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
file_save("lmhash1.dat", lmhash.data, lmhash.length);
#endif
- nt_status = pass_check_smb(user, user,
- workgroup, machine,
- lmhash.data,
- lmhash.length,
- nthash.data,
- nthash.length);
-
- data_blob_free(&nthash);
+ if (!last_challenge(chal)) {
+ DEBUG(0,("Encrypted login but no challange set!\n"));
+ return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ }
+ sec_blob = data_blob(chal, 8);
+ if (!sec_blob.data) {
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ if (!make_user_info_map(&user_info,
+ user, workgroup,
+ machine, sec_blob,
+ lmhash, nthash,
+ plaintext_password,
+ neg_flags, True)) {
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ nt_status = check_password(user_info, &server_info);
+
+ free_user_info(&user_info);
+
data_blob_free(&lmhash);
-
+
+ data_blob_free(&nthash);
+
if (!NT_STATUS_IS_OK(nt_status)) {
- return ERROR_NT(nt_status);
+ return ERROR_NT(nt_status_squash(nt_status));
}
- /* the password is good - let them in */
- pw = smb_getpwnam(user,False);
- if (!pw) {
- DEBUG(1,("Username %s is invalid on this system\n",user));
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
- }
- gid = pw->pw_gid;
- uid = pw->pw_uid;
- full_name = pw->pw_gecos;
-
- sess_vuid = register_vuid(uid,gid,user,user,workgroup,False, full_name);
+ sess_vuid = register_vuid(server_info, user, False);
- free(user);
- free(workgroup);
- free(machine);
-
+ free_server_info(&server_info);
+
if (sess_vuid == -1) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
@@ -360,30 +366,16 @@ reply to a session setup spnego anonymous packet
static int reply_spnego_anonymous(connection_struct *conn, char *inbuf, char *outbuf,
int length, int bufsize)
{
- char *user;
int sess_vuid;
- gid_t gid;
- uid_t uid;
- char *full_name;
char *p;
- const struct passwd *pw;
+ auth_serversupplied_info *server_info = NULL;
DEBUG(3,("Got anonymous request\n"));
- user = lp_guestaccount(-1);
-
- /* the password is good - let them in */
- pw = smb_getpwnam(user,False);
- if (!pw) {
- DEBUG(1,("Guest username %s is invalid on this system\n",user));
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
- }
- gid = pw->pw_gid;
- uid = pw->pw_uid;
- full_name = pw->pw_gecos;
-
- sess_vuid = register_vuid(uid,gid,user,user,lp_workgroup(),True,full_name);
-
+ make_server_info_guest(&server_info);
+ sess_vuid = register_vuid(server_info, lp_guestaccount(-1), False);
+ free_server_info(&server_info);
+
if (sess_vuid == -1) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
@@ -414,7 +406,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,cha
extern uint32 global_client_caps;
int ret;
- DEBUG(3,("Doing spego session setup\n"));
+ DEBUG(3,("Doing spnego session setup\n"));
if (global_client_caps == 0) {
global_client_caps = IVAL(inbuf,smb_vwv10);
@@ -464,16 +456,11 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
int length,int bufsize)
{
int sess_vuid;
- gid_t gid;
- uid_t uid;
- char* full_name;
int smb_bufsize;
- int smb_apasslen = 0;
- pstring smb_apasswd;
- int smb_ntpasslen = 0;
- pstring smb_ntpasswd;
+ DATA_BLOB lm_resp;
+ DATA_BLOB nt_resp;
+ DATA_BLOB plaintext_password;
pstring user;
- pstring orig_user;
fstring domain;
fstring native_os;
fstring native_lanman;
@@ -486,9 +473,18 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
extern fstring remote_machine;
extern userdom_struct current_user_info;
extern int max_send;
+
+ auth_usersupplied_info *user_info = NULL;
+ auth_serversupplied_info *server_info = NULL;
+
BOOL doencrypt = global_encrypted_passwords_negotiated;
+
START_PROFILE(SMBsesssetupX);
+ ZERO_STRUCT(lm_resp);
+ ZERO_STRUCT(nt_resp);
+ ZERO_STRUCT(plaintext_password);
+
DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
/* a SPNEGO session setup has 12 command words, whereas a normal
@@ -503,28 +499,35 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
}
- *smb_apasswd = *smb_ntpasswd = 0;
-
smb_bufsize = SVAL(inbuf,smb_vwv2);
-
+
if (Protocol < PROTOCOL_NT1) {
- smb_apasslen = SVAL(inbuf,smb_vwv7);
- if (smb_apasslen > MAX_PASS_LEN) {
+ uint16 passlen1 = SVAL(inbuf,smb_vwv7);
+ if (passlen1 > MAX_PASS_LEN) {
return ERROR_DOS(ERRDOS,ERRbuftoosmall);
}
- memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
- srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE);
-
- if (!doencrypt && (lp_security() != SEC_SERVER)) {
- smb_apasslen = strlen(smb_apasswd);
+ if (doencrypt) {
+ lm_resp = data_blob(smb_buf(inbuf), passlen1);
+ } else {
+ plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
+ if (!plaintext_password.data) {
+ DEBUG(0,("reply_sesssetup_and_X: malloc failed for plaintext_password!\n"));
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ } else {
+ /* Ensure null termination */
+ plaintext_password.data[passlen1] = 0;
+ }
}
+
+ srvstr_pull(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), -1, STR_TERMINATE);
+
} else {
uint16 passlen1 = SVAL(inbuf,smb_vwv7);
uint16 passlen2 = SVAL(inbuf,smb_vwv8);
enum remote_arch_types ra_type = get_remote_arch();
char *p = smb_buf(inbuf);
-
+
if(global_client_caps == 0)
global_client_caps = IVAL(inbuf,smb_vwv11);
@@ -539,16 +542,13 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
}
}
- if (passlen1 != 24 && passlen2 < 24)
- doencrypt = False;
-
if (passlen1 > MAX_PASS_LEN) {
return ERROR_DOS(ERRDOS,ERRbuftoosmall);
}
-
+
passlen1 = MIN(passlen1, MAX_PASS_LEN);
passlen2 = MIN(passlen2, MAX_PASS_LEN);
-
+
if (!doencrypt) {
/* both Win95 and WinNT stuff up the password lengths for
non-encrypting systems. Uggh.
@@ -591,23 +591,20 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
passlen1 = 1;
}
}
-
+
/* Save the lanman2 password and the NT md4 password. */
- smb_apasslen = passlen1;
- memcpy(smb_apasswd,p,smb_apasslen);
-
- smb_ntpasslen = passlen2;
- memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
-
- if (smb_apasslen != 24 || !doencrypt) {
- /* trim the password */
- smb_apasslen = strlen(smb_apasswd);
-
- /* wfwg sometimes uses a space instead of a null */
- if (strequal(smb_apasswd," ")) {
- smb_apasslen = 0;
- *smb_apasswd = 0;
- }
+
+ if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
+ doencrypt = False;
+ }
+
+ if (doencrypt) {
+ lm_resp = data_blob(p, passlen1);
+ nt_resp = data_blob(p+passlen1, passlen2);
+ } else {
+ plaintext_password = data_blob(p, passlen1+1);
+ /* Ensure null termination */
+ plaintext_password.data[passlen1] = 0;
}
p += passlen1 + passlen2;
@@ -630,15 +627,29 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
- if (lp_security() == SEC_SHARE) {
- /* in share level we should ignore any passwords */
- smb_ntpasslen = 0;
- smb_apasslen = 0;
+ DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, remote_machine));
+
+ /* If no username is sent use the guest account */
+ if (!*user) {
+ pstrcpy(user,lp_guestaccount(-1));
guest = True;
}
+ pstrcpy(current_user_info.smb_name,user);
+
+ reload_services(True);
+
+ if (lp_security() == SEC_SHARE) {
+ /* in share level we should ignore any passwords */
+
+ data_blob_free(&lm_resp);
+ data_blob_free(&nt_resp);
+ data_blob_free(&plaintext_password);
- DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",user, domain, remote_machine));
+ guest = True;
+ map_username(user);
+ add_session_user(user);
+ }
if (done_sesssetup && lp_restrict_anonymous()) {
/* tests show that even if browsing is done over
@@ -649,106 +660,61 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
* only deny connections that have no session
* information. If a domain has been provided, then
* it's not a purely anonymous connection. AAB */
- if (!*user && !*smb_apasswd && !*domain) {
+ if (!*user && !*domain) {
DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
+
+ data_blob_free(&lm_resp);
+ data_blob_free(&nt_resp);
+ data_blob_free(&plaintext_password);
+
END_PROFILE(SMBsesssetupX);
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
}
-
- /* If no username is sent use the guest account */
- if (!*user) {
- pstrcpy(user,lp_guestaccount(-1));
- guest = True;
- }
-
- pstrcpy(current_user_info.smb_name,user);
-
- reload_services(True);
-
- /*
- * Save the username before mapping. We will use
- * the original username sent to us for security=server
- * and security=domain checking.
- */
-
- pstrcpy( orig_user, user);
-
- /*
- * Always try the "DOMAIN\user" lookup first, as this is the most
- * specific case. If this fails then try the simple "user" lookup.
- * But don't do this for guests, as this is always a local user.
- */
if (!guest) {
- pstring dom_user;
-
- /* Work out who's who */
-
- slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
- domain, lp_winbind_separator(), user);
-
- if (sys_getpwnam(dom_user) != NULL) {
- pstrcpy(user, dom_user);
- DEBUG(3,("Using unix username %s\n", dom_user));
+ NTSTATUS nt_status;
+ if (!make_user_info_for_reply(&user_info,
+ user, domain,
+ lm_resp, nt_resp,
+ plaintext_password, doencrypt)) {
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
}
- /*
- * Pass the user through the NT -> unix user mapping
- * function.
- */
+ nt_status = check_password(user_info, &server_info);
- (void)map_username(user);
+ free_user_info(&user_info);
- /*
- * Do any UNIX username case mangling.
- */
- smb_getpwnam(user, True);
- }
-
- add_session_user(user);
-
- if (!guest) {
- NTSTATUS nt_status;
- nt_status = pass_check_smb(orig_user, user,
- domain, remote_machine,
- (unsigned char *)smb_apasswd,
- smb_apasslen,
- (unsigned char *)smb_ntpasswd,
- smb_ntpasslen);
-
- if NT_STATUS_IS_OK(nt_status) {
-
- } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) {
- if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
- (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
- DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
- pstrcpy(user,lp_guestaccount(-1));
- guest = True;
- } else {
- /* Match WinXP and don't give the game away */
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
- }
- } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) {
- if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
- pstrcpy(user,lp_guestaccount(-1));
- DEBUG(3,("Registered username %s for guest access\n",user));
- guest = True;
- } else {
+ data_blob_free(&lm_resp);
+ data_blob_free(&nt_resp);
+ data_blob_free(&plaintext_password);
+
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) {
+ if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
+ (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
+ DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
+ pstrcpy(user,lp_guestaccount(-1));
+ guest = True;
+
+ }
+ } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) {
+ if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
+ pstrcpy(user,lp_guestaccount(-1));
+ DEBUG(3,("Registered username %s for guest access\n",user));
+ guest = True;
+ }
/* Match WinXP and don't give the game away */
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
- } else {
- return ERROR_NT(nt_status);
+
+ if (!guest) {
+ free_server_info(&server_info);
+ return ERROR_NT(nt_status_squash(nt_status));
+ }
}
}
- if (!strequal(user,lp_guestaccount(-1)) &&
- lp_servicenumber(user) < 0) {
- add_home_service(user,get_user_home_dir(user));
- }
-
-
/* it's ok - setup a reply */
if (Protocol < PROTOCOL_NT1) {
set_message(outbuf,3,0,True);
@@ -763,30 +729,26 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
/* perhaps grab OS version here?? */
}
- /* Set the correct uid in the outgoing and incoming packets
- We will use this on future requests to determine which
- user we should become.
- */
- {
- const struct passwd *pw = smb_getpwnam(user,False);
- if (!pw) {
- DEBUG(1,("Username %s is invalid on this system\n",user));
- END_PROFILE(SMBsesssetupX);
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
+ if (guest) {
+ SSVAL(outbuf,smb_vwv2,1);
+ free_server_info(&server_info);
+ make_server_info_guest(&server_info);
+ } else {
+ const char *home_dir = pdb_get_homedir(server_info->sam_account);
+ const char *username = pdb_get_username(server_info->sam_account);
+ if ((home_dir && *home_dir)
+ && (lp_servicenumber(username) < 0)) {
+ add_home_service(username, home_dir);
}
- gid = pw->pw_gid;
- uid = pw->pw_uid;
- full_name = pw->pw_gecos;
}
-
- if (guest)
- SSVAL(outbuf,smb_vwv2,1);
-
+
/* register the name and uid as being validated, so further connections
to a uid can get through without a password, on the same VC */
-
- sess_vuid = register_vuid(uid,gid,user,orig_user,domain,guest, full_name);
-
+
+ sess_vuid = register_vuid(server_info, user, guest);
+
+ free_server_info(&server_info);
+
if (sess_vuid == -1) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}