summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2001-10-31 10:46:25 +0000
committerAndrew Bartlett <abartlet@samba.org>2001-10-31 10:46:25 +0000
commit60f0627afb167faad57385d44f0b587186a7ac2b (patch)
treef7a03b2e1b90d1234c48fffaeaf92986060a0e77 /source3
parent83575bd3868ef3993107460d2c8e05f382eae351 (diff)
downloadsamba-60f0627afb167faad57385d44f0b587186a7ac2b.tar.gz
samba-60f0627afb167faad57385d44f0b587186a7ac2b.tar.bz2
samba-60f0627afb167faad57385d44f0b587186a7ac2b.zip
This is a farily large patch (3300 lines) and reworks most of the AuthRewrite
code. In particular this assists tpot in some of his work, becouse it provides the connection between the authenticaion and the vuid generation. Major Changes: - Fully malloc'ed structures. - Massive rework of the code so that all structures are made and destroyed using malloc and free, rather than hanging around on the stack. - SAM_ACCOUNT unix uids and gids are now pointers to the same, to allow them to be declared 'invalid' without the chance that people might get ROOT by default. - kill off some of the "DOMAIN\user" lookups. These can be readded at a more appropriate place (probably domain_client_validate.c) in the future. They don't belong in session setups. - Massive introduction of DATA_BLOB structures, particularly for passwords. - Use NTLMSSP flags to tell the backend what its getting, rather than magic lenghths. - Fix winbind back up again, but tpot is redoing this soon anyway. - Abstract much of the work in srv_netlog_nt back into auth helper functions. This is a LARGE change, and any assistance is testing it is appriciated. Domain logons are still broken (as far as I can tell) but other functionality seems intact. Needs testing with a wide variety of MS clients. Andrew Bartlett (This used to be commit f70fb819b2f57bd57232b51808345e2319d52f6c)
Diffstat (limited to 'source3')
-rw-r--r--source3/Makefile.in2
-rw-r--r--source3/auth/auth.c263
-rw-r--r--source3/auth/auth_domain.c2
-rw-r--r--source3/auth/auth_rhosts.c40
-rw-r--r--source3/auth/auth_sam.c228
-rw-r--r--source3/auth/auth_server.c27
-rw-r--r--source3/auth/auth_unix.c17
-rw-r--r--source3/auth/auth_util.c564
-rw-r--r--source3/include/auth.h53
-rw-r--r--source3/include/smb.h4
-rw-r--r--source3/libsmb/domain_client_validate.c61
-rw-r--r--source3/libsmb/smbencrypt.c16
-rw-r--r--source3/nsswitch/winbindd_pam.c87
-rw-r--r--source3/passdb/passdb.c64
-rw-r--r--source3/passdb/pdb_smbpasswd.c23
-rw-r--r--source3/printing/nt_printing.c12
-rw-r--r--source3/rpc_client/cli_login.c8
-rw-r--r--source3/rpc_parse/parse_net.c2
-rw-r--r--source3/rpc_server/srv_netlog_nt.c197
-rw-r--r--source3/rpc_server/srv_pipe.c76
-rw-r--r--source3/rpc_server/srv_srvsvc_nt.c12
-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
32 files changed, 2216 insertions, 1139 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index f582bd8e19..ea15da5ca3 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -398,7 +398,7 @@ WINBINDD_OBJ1 = \
nsswitch/winbindd_cm.o
NECESSARY_BECAUSE_SAMBA_DEPENDENCIES_ARE_SO_BROKEN_OBJ = \
- libsmb/domain_client_validate.o \
+ libsmb/domain_client_validate.o smbd/auth_util.o \
rpc_client/cli_netlogon.o rpc_client/cli_login.o
WINBINDD_OBJ = \
diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index 4bdbdf5555..4d1a566833 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/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/auth/auth_domain.c b/source3/auth/auth_domain.c
index bcd41bacdb..f20da19607 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/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/auth/auth_rhosts.c b/source3/auth/auth_rhosts.c
index 9f5f1e10e5..9c07e48a9b 100644
--- a/source3/auth/auth_rhosts.c
+++ b/source3/auth/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/auth/auth_sam.c b/source3/auth/auth_sam.c
index 84ca8d03be..d4283429ce 100644
--- a/source3/auth/auth_sam.c
+++ b/source3/auth/auth_sam.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/auth/auth_server.c b/source3/auth/auth_server.c
index 520417e3e0..ddbc284d50 100644
--- a/source3/auth/auth_server.c
+++ b/source3/auth/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/auth/auth_unix.c b/source3/auth/auth_unix.c
index 29a2a6eafb..d456da1fdf 100644
--- a/source3/auth/auth_unix.c
+++ b/source3/auth/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/auth/auth_util.c b/source3/auth/auth_util.c
index d3b9aa7001..297c482af5 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/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/include/auth.h b/source3/include/auth.h
index 9e99600e98..427cb8b489 100644
--- a/source3/include/auth.h
+++ b/source3/include/auth.h
@@ -35,58 +35,44 @@ typedef struct unicode_string
uchar *unistr;
} AUTH_UNISTR;
-/* AUTH_BUFFER - 8-bit byte buffer */
-typedef struct auth_buffer
-{
- int len;
- uint8 *buffer;
-} AUTH_BUFFER;
-
-typedef struct net_password
-{
- AUTH_BUFFER lm_resp;
- AUTH_BUFFER nt_resp;
-} auth_net_password;
-
typedef struct interactive_password
{
OWF_INFO lm_owf; /* LM OWF Password */
OWF_INFO nt_owf; /* NT OWF Password */
} auth_interactive_password;
-typedef struct plaintext_password
-{
- AUTH_STR password;
-} auth_plaintext_password;
-
typedef struct usersupplied_info
{
- AUTH_BUFFER lm_resp;
- AUTH_BUFFER nt_resp;
+ DATA_BLOB lm_resp;
+ DATA_BLOB nt_resp;
auth_interactive_password * interactive_password;
- AUTH_STR plaintext_password;
+ DATA_BLOB plaintext_password;
- uint8 chal[8];
+ BOOL encrypted;
+
+ uint32 ntlmssp_flags;
+
+ DATA_BLOB sec_blob;
- AUTH_STR requested_domain; /* domain name string */
+ AUTH_STR client_domain; /* domain name string */
AUTH_STR domain; /* domain name after mapping */
- AUTH_STR unix_username; /* username after mapping */
- AUTH_STR smb_username; /* username before mapping */
+ AUTH_STR internal_username; /* username after mapping */
+ AUTH_STR smb_name; /* username before mapping */
AUTH_STR wksta_name; /* workstation name (netbios calling name) unicode string */
} auth_usersupplied_info;
+#define SAM_FILL_NAME 0x01
+#define SAM_FILL_INFO3 0x02
+#define SAM_FILL_SAM 0x04
+#define SAM_FILL_UNIX 0x08
+#define SAM_FILL_ALL (SAM_FILL_NAME | SAM_FILL_INFO3 | SAM_FILL_SAM | SAM_FILL_UNIX)
+
typedef struct serversupplied_info
{
- AUTH_STR full_name;
- AUTH_STR unix_user;
-
BOOL guest;
- uid_t unix_uid;
- gid_t unix_gid;
-
/* This groups info is needed for when we become_user() for this uid */
int n_groups;
gid_t *groups;
@@ -98,6 +84,11 @@ typedef struct serversupplied_info
uchar session_key[16];
+ uint8 first_8_lm_hash[8];
+
+ uint32 sam_fill_level; /* How far is this structure filled? */
+
+ SAM_ACCOUNT *sam_account;
} auth_serversupplied_info;
#endif /* _SMBAUTH_H_ */
diff --git a/source3/include/smb.h b/source3/include/smb.h
index dea5bb66df..0e48b4c6c0 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -591,8 +591,8 @@ typedef struct sam_passwd
pstring unknown_str ; /* don't know what this is, yet. */
pstring munged_dial ; /* munged path name and dial-back tel number */
- uid_t uid; /* this is actually the unix uid_t */
- gid_t gid; /* this is actually the unix gid_t */
+ uid_t *uid; /* this is a pointer to the unix uid_t */
+ gid_t *gid; /* this is a pointer to the unix gid_t */
uint32 user_rid; /* Primary User ID */
uint32 group_rid; /* Primary Group ID */
diff --git a/source3/libsmb/domain_client_validate.c b/source3/libsmb/domain_client_validate.c
index 26a727b1f1..20db1ee4d6 100644
--- a/source3/libsmb/domain_client_validate.c
+++ b/source3/libsmb/domain_client_validate.c
@@ -271,7 +271,7 @@ static BOOL find_connect_pdc(struct cli_state *pcli,
************************************************************************/
NTSTATUS domain_client_validate(const auth_usersupplied_info *user_info,
- auth_serversupplied_info *server_info,
+ auth_serversupplied_info **server_info,
char *server, unsigned char *trust_passwd,
time_t last_change_time)
{
@@ -282,6 +282,7 @@ NTSTATUS domain_client_validate(const auth_usersupplied_info *user_info,
uint32 smb_uid_low;
BOOL connected_ok = False;
NTSTATUS status;
+ struct passwd *pass;
/*
* Check that the requested domain is not our own machine name.
@@ -330,34 +331,48 @@ NTSTATUS domain_client_validate(const auth_usersupplied_info *user_info,
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("domain_client_validate: unable to validate password "
"for user %s in domain %s to Domain controller %s. "
- "Error was %s.\n", user_info->smb_username.str,
+ "Error was %s.\n", user_info->smb_name.str,
user_info->domain.str, cli.srv_name_slash,
get_nt_error_msg(status)));
- }
+ } else {
- /*
- * Here, if we really want it, we have lots of info about the user
- * in info3.
- */
+ /*
+ * Here, if we really want it, we have lots of info about the user
+ * in info3.
+ */
+
+ pass = Get_Pwnam(user_info->internal_username.str);
+ if (pass) {
+ make_server_info_pw(server_info, pass);
+ if (!server_info) {
+ status = NT_STATUS_NO_MEMORY;
+ }
+ } else {
+ status = NT_STATUS_NO_SUCH_USER;
+ }
+ }
/* Store the user group information in the server_info returned to
the caller. */
-
- if ((server_info->group_rids = malloc(info3.num_groups2 *
- sizeof(uint32))) == NULL) {
- DEBUG(1, ("out of memory allocating rid group membership\n"));
- status = NT_STATUS_NO_MEMORY;
- } else {
- int i;
-
- server_info->n_rids = info3.num_groups2;
-
- for (i = 0; i < server_info->n_rids; i++) {
- server_info->group_rids[i] = info3.gids[i].g_rid;
- DEBUG(5, ("** adding group rid 0x%x\n",
- info3.gids[i].g_rid));
- }
- }
+
+ if (NT_STATUS_IS_OK(status)) {
+ if (((*server_info)->group_rids = malloc(info3.num_groups2 *
+ sizeof(uint32))) == NULL) {
+ DEBUG(1, ("out of memory allocating rid group membership\n"));
+ status = NT_STATUS_NO_MEMORY;
+ free_server_info(server_info);
+ } else {
+ int i;
+
+ (*server_info)->n_rids = info3.num_groups2;
+
+ for (i = 0; i < (*server_info)->n_rids; i++) {
+ (*server_info)->group_rids[i] = info3.gids[i].g_rid;
+ DEBUG(5, ("** adding group rid 0x%x\n",
+ info3.gids[i].g_rid));
+ }
+ }
+ }
#if 0
/*
diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c
index 2868b02ed9..c1c4750e05 100644
--- a/source3/libsmb/smbencrypt.c
+++ b/source3/libsmb/smbencrypt.c
@@ -216,27 +216,27 @@ BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[
/* Does the md5 encryption from the NT hash for NTLMv2. */
void SMBOWFencrypt_ntv2(const uchar kr[16],
- const uchar * srv_chal, int srv_chal_len,
- const uchar * cli_chal, int cli_chal_len,
+ const DATA_BLOB srv_chal,
+ const DATA_BLOB cli_chal,
char resp_buf[16])
{
HMACMD5Context ctx;
hmac_md5_init_limK_to_64(kr, 16, &ctx);
- hmac_md5_update(srv_chal, srv_chal_len, &ctx);
- hmac_md5_update(cli_chal, cli_chal_len, &ctx);
+ hmac_md5_update(srv_chal.data, srv_chal.length, &ctx);
+ hmac_md5_update(cli_chal.data, cli_chal.length, &ctx);
hmac_md5_final((unsigned char *)resp_buf, &ctx);
#ifdef DEBUG_PASSWORD
DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n"));
- dump_data(100, srv_chal, srv_chal_len);
- dump_data(100, cli_chal, cli_chal_len);
+ dump_data(100, srv_chal.data, srv_chal.length);
+ dump_data(100, cli_chal.data, cli_chal.length);
dump_data(100, resp_buf, 16);
#endif
}
void SMBsesskeygen_ntv2(const uchar kr[16],
- const uchar * nt_resp, char sess_key[16])
+ const uchar * nt_resp, uint8 sess_key[16])
{
HMACMD5Context ctx;
@@ -251,7 +251,7 @@ void SMBsesskeygen_ntv2(const uchar kr[16],
}
void SMBsesskeygen_ntv1(const uchar kr[16],
- const uchar * nt_resp, char sess_key[16])
+ const uchar * nt_resp, uint8 sess_key[16])
{
mdfour((unsigned char *)sess_key, kr, 16);
diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c
index 5cf819a19d..59623b9f04 100644
--- a/source3/nsswitch/winbindd_pam.c
+++ b/source3/nsswitch/winbindd_pam.c
@@ -60,12 +60,8 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
unsigned char trust_passwd[16];
time_t last_change_time;
- unsigned char local_lm_response[24];
- unsigned char local_nt_response[24];
-
- auth_usersupplied_info user_info;
- auth_serversupplied_info server_info;
- AUTH_STR theirdomain, smb_username, wksta_name;
+ auth_usersupplied_info *user_info;
+ auth_serversupplied_info *server_info;
DEBUG(3, ("[%5d]: pam auth %s\n", state->pid,
state->request.data.auth.user));
@@ -82,37 +78,10 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
passlen = strlen(state->request.data.auth.pass);
- ZERO_STRUCT(user_info);
- ZERO_STRUCT(theirdomain);
- ZERO_STRUCT(smb_username);
- ZERO_STRUCT(wksta_name);
-
- theirdomain.str = name_domain;
- theirdomain.len = strlen(theirdomain.str);
-
- user_info.requested_domain = theirdomain;
- user_info.domain = theirdomain;
-
- user_info.smb_username.str = name_user;
- user_info.smb_username.len = strlen(name_user);
-
- user_info.unix_username.str = name_user;
- user_info.unix_username.len = strlen(name_user);
-
- user_info.wksta_name.str = global_myname;
- user_info.wksta_name.len = strlen(user_info.wksta_name.str);
-
- user_info.wksta_name = wksta_name;
-
- generate_random_buffer( user_info.chal, 8, False);
-
if (state->request.data.auth.pass[0]) {
- SMBencrypt((uchar *)state->request.data.auth.pass, user_info.chal, local_lm_response);
- user_info.lm_resp.buffer = (uint8 *)local_lm_response;
- user_info.lm_resp.len = 24;
- SMBNTencrypt((uchar *)state->request.data.auth.pass, user_info.chal, local_nt_response);
- user_info.nt_resp.buffer = (uint8 *)local_nt_response;
- user_info.nt_resp.len = 24;
+ make_user_info_for_winbind(&user_info,
+ name_user, name_domain,
+ state->request.data.auth.pass);
} else {
return WINBINDD_ERROR;
}
@@ -137,11 +106,11 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
for each authentication performed. This can theoretically
be optimised to use an already open IPC$ connection. */
- result = domain_client_validate(&user_info, &server_info,
+ result = domain_client_validate(user_info, &server_info,
auth_dc, trust_passwd,
last_change_time);
- free_serversupplied_info(&server_info); /* No info needed */
+ free_server_info(&server_info); /* No info needed */
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
@@ -154,9 +123,8 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
fstring name_domain, name_user, auth_dc;
unsigned char trust_passwd[16];
time_t last_change_time;
- auth_usersupplied_info user_info;
- auth_serversupplied_info server_info;
- AUTH_STR theirdomain, smb_username, wksta_name;
+ auth_usersupplied_info *user_info;
+ auth_serversupplied_info *server_info;
DEBUG(3, ("[%5d]: pam auth crap %s\n", state->pid,
state->request.data.auth_crap.user));
@@ -166,36 +134,11 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
parse_domain_user(state->request.data.auth_crap.user, name_domain,
name_user);
- ZERO_STRUCT(user_info);
- ZERO_STRUCT(theirdomain);
- ZERO_STRUCT(smb_username);
- ZERO_STRUCT(wksta_name);
+ make_user_info_winbind_crap(&user_info, name_user,
+ name_domain, state->request.data.auth_crap.chal,
+ (uchar *)state->request.data.auth_crap.lm_resp, 24,
+ (uchar *)state->request.data.auth_crap.nt_resp, 24);
- theirdomain.str = name_domain;
- theirdomain.len = strlen(theirdomain.str);
-
- user_info.requested_domain = theirdomain;
- user_info.domain = theirdomain;
-
- user_info.smb_username.str = name_user;
- user_info.smb_username.len = strlen(name_user);
-
- user_info.unix_username.str = name_user;
- user_info.unix_username.len = strlen(name_user);
-
- user_info.wksta_name.str = global_myname;
- user_info.wksta_name.len = strlen(user_info.wksta_name.str);
-
- user_info.wksta_name = wksta_name;
-
- memcpy(user_info.chal, state->request.data.auth_crap.chal, 8);
-
- user_info.lm_resp.buffer = (uchar *)state->request.data.auth_crap.lm_resp;
- user_info.nt_resp.buffer = (uchar *)state->request.data.auth_crap.nt_resp;
-
- user_info.lm_resp.len = 24;
- user_info.nt_resp.len = 24;
-
/*
* Get the machine account password for our primary domain
*/
@@ -216,11 +159,11 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
for each authentication performed. This can theoretically
be optimised to use an already open IPC$ connection. */
- result = domain_client_validate(&user_info, &server_info,
+ result = domain_client_validate(user_info, &server_info,
auth_dc, trust_passwd,
last_change_time);
- free_serversupplied_info(&server_info); /* No info needed */
+ free_server_info(&server_info); /* No info needed */
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c
index 6a96426a9f..05d448f963 100644
--- a/source3/passdb/passdb.c
+++ b/source3/passdb/passdb.c
@@ -135,8 +135,9 @@ BOOL pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, struct passwd *pwd)
pdb_set_username(*new_sam_acct, pwd->pw_name);
pdb_set_fullname(*new_sam_acct, pwd->pw_gecos);
- pdb_set_uid(*new_sam_acct, pwd->pw_uid);
- pdb_set_gid(*new_sam_acct, pwd->pw_gid);
+
+ pdb_set_uid(*new_sam_acct, &pwd->pw_uid);
+ pdb_set_gid(*new_sam_acct, &pwd->pw_gid);
pdb_set_user_rid(*new_sam_acct, pdb_uid_to_user_rid(pwd->pw_uid));
pdb_set_group_rid(*new_sam_acct, pdb_gid_to_group_rid(pwd->pw_gid));
@@ -186,6 +187,9 @@ static BOOL pdb_free_sam_contents(SAM_ACCOUNT *user)
SAFE_FREE(user->nt_pw);
SAFE_FREE(user->lm_pw);
+
+ SAFE_FREE(user->uid);
+ SAFE_FREE(user->gid);
return True;
}
@@ -1113,20 +1117,20 @@ uint32 pdb_get_group_rid (const SAM_ACCOUNT *sampass)
return (-1);
}
-uid_t pdb_get_uid (const SAM_ACCOUNT *sampass)
+uid_t *pdb_get_uid (const SAM_ACCOUNT *sampass)
{
if (sampass)
return (sampass->uid);
else
- return ((uid_t)-1);
+ return (NULL);
}
-gid_t pdb_get_gid (const SAM_ACCOUNT *sampass)
+gid_t *pdb_get_gid (const SAM_ACCOUNT *sampass)
{
if (sampass)
return (sampass->gid);
else
- return ((gid_t)-1);
+ return (NULL);
}
const char* pdb_get_username (const SAM_ACCOUNT *sampass)
@@ -1330,22 +1334,62 @@ BOOL pdb_set_logons_divs (SAM_ACCOUNT *sampass, uint16 hours)
return True;
}
-BOOL pdb_set_uid (SAM_ACCOUNT *sampass, uid_t uid)
+/*********************************************************************
+ Set the user's UNIX uid, as a pointer to malloc'ed memory.
+ ********************************************************************/
+
+BOOL pdb_set_uid (SAM_ACCOUNT *sampass, const uid_t *uid)
{
if (!sampass)
return False;
+
+ if (!uid) {
+ /* Allow setting to NULL */
+ SAFE_FREE(sampass->uid);
+ return True;
+ }
+
+ if (sampass->uid!=NULL)
+ DEBUG(4,("pdb_set_nt_passwd: uid non NULL overwritting ?\n"));
+ else
+ sampass->uid=(uid_t *)malloc(sizeof(uid_t));
+
+ if (sampass->uid==NULL)
+ return False;
+
+ *sampass->uid = *uid;
- sampass->uid = uid;
return True;
+
}
-BOOL pdb_set_gid (SAM_ACCOUNT *sampass, gid_t gid)
+/*********************************************************************
+ Set the user's UNIX gid, as a pointer to malloc'ed memory.
+ ********************************************************************/
+
+BOOL pdb_set_gid (SAM_ACCOUNT *sampass, const gid_t *gid)
{
if (!sampass)
return False;
+
+ if (!gid) {
+ /* Allow setting to NULL */
+ SAFE_FREE(sampass->gid);
+ return True;
+ }
+
+ if (sampass->gid!=NULL)
+ DEBUG(4,("pdb_set_nt_passwd: gid non NULL overwritting ?\n"));
+ else
+ sampass->gid=(gid_t *)malloc(sizeof(gid_t));
+
+ if (sampass->gid==NULL)
+ return False;
+
+ *sampass->gid = *gid;
- sampass->gid = gid;
return True;
+
}
BOOL pdb_set_user_rid (SAM_ACCOUNT *sampass, uint32 rid)
diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c
index 8524275f12..e190be99a5 100644
--- a/source3/passdb/pdb_smbpasswd.c
+++ b/source3/passdb/pdb_smbpasswd.c
@@ -1135,12 +1135,22 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
********************************************************************/
static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampass)
{
+ uid_t *uid;
+ gid_t *gid;
+
if (sampass == NULL)
return False;
+ uid = pdb_get_uid(sampass);
+ gid = pdb_get_gid(sampass);
+
+ if (!uid || !gid) {
+ DEBUG(0,("build_sam_pass: Failing attempt to store user without a UNIX uid or gid. \n"));
+ return False;
+ }
ZERO_STRUCTP(smb_pw);
- smb_pw->smb_userid=pdb_get_uid(sampass);
+ smb_pw->smb_userid=*uid;
smb_pw->smb_name=pdb_get_username(sampass);
smb_pw->smb_passwd=pdb_get_lanman_passwd(sampass);
@@ -1149,12 +1159,12 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas
smb_pw->acct_ctrl=pdb_get_acct_ctrl(sampass);
smb_pw->pass_last_set_time=pdb_get_pass_last_set_time(sampass);
- if (smb_pw->smb_userid != pdb_user_rid_to_uid(pdb_get_user_rid(sampass))) {
+ if (*uid != pdb_user_rid_to_uid(pdb_get_user_rid(sampass))) {
DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n"));
return False;
}
- if (pdb_get_gid(sampass) != pdb_group_rid_to_gid(pdb_get_group_rid(sampass))) {
+ if (*gid != pdb_group_rid_to_gid(pdb_get_group_rid(sampass))) {
DEBUG(0,("build_sam_pass: Failing attempt to store user with non-gid based primary group RID. \n"));
return False;
}
@@ -1184,14 +1194,15 @@ static BOOL build_sam_account(SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw
return False;
}
+ pdb_set_uid (sam_pass, &pwfile->pw_uid);
+ pdb_set_gid (sam_pass, &pwfile->pw_gid);
+
/* FIXME!! This doesn't belong here. Should be set in net_sam_logon()
--jerry */
+
pstrcpy(samlogon_user, pw_buf->smb_name);
-
sam_logon_in_ssb = True;
- pdb_set_uid (sam_pass, pwfile->pw_uid);
- pdb_set_gid (sam_pass, pwfile->pw_gid);
pdb_set_fullname(sam_pass, pwfile->pw_gecos);
pdb_set_user_rid(sam_pass, pdb_uid_to_user_rid (pwfile->pw_uid));
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index 9b5f7379f5..e4e33d257f 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -927,7 +927,7 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
int action;
NTSTATUS nt_status;
pstring driverpath;
- fstring null_pw;
+ DATA_BLOB null_pw;
files_struct *fsp = NULL;
BOOL bad_path;
SMB_STRUCT_STAT st;
@@ -943,10 +943,10 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
/* connect to the print$ share under the same account as the user connected to the rpc pipe */
/* Null password is ok - we are already an authenticated user... */
- *null_pw = '\0';
+ null_pw = data_blob(NULL, 0);
become_root();
- conn = make_connection("print$", null_pw, 0, "A:", user->vuid, &nt_status);
+ conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
unbecome_root();
if (conn == NULL) {
@@ -1230,7 +1230,7 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
pstring new_dir;
pstring old_name;
pstring new_name;
- fstring null_pw;
+ DATA_BLOB null_pw;
connection_struct *conn;
NTSTATUS nt_status;
int ver = 0;
@@ -1252,8 +1252,8 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
/* connect to the print$ share under the same account as the user connected to the rpc pipe */
/* Null password is ok - we are already an authenticated user... */
- *null_pw = '\0';
- conn = make_connection("print$", null_pw, 0, "A:", user->vuid, &nt_status);
+ null_pw = data_blob(NULL, 0);
+ conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
if (conn == NULL) {
DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
diff --git a/source3/rpc_client/cli_login.c b/source3/rpc_client/cli_login.c
index 0f54d5512c..eaedb1613a 100644
--- a/source3/rpc_client/cli_login.c
+++ b/source3/rpc_client/cli_login.c
@@ -169,14 +169,14 @@ 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,
+ user_info->smb_name.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);
+ user_info->sec_blob.data,
+ user_info->lm_resp.data, user_info->lm_resp.length,
+ user_info->nt_resp.data, user_info->nt_resp.length);
/* Send client sam-logon request - update credentials on success. */
return cli_net_sam_logon(cli, ctr, user_info3);
diff --git a/source3/rpc_parse/parse_net.c b/source3/rpc_parse/parse_net.c
index 2f0dd1eb62..c546213173 100644
--- a/source3/rpc_parse/parse_net.c
+++ b/source3/rpc_parse/parse_net.c
@@ -1193,7 +1193,7 @@ static BOOL smb_io_sam_info(char *desc, DOM_SAM_INFO *sam, prs_struct *ps, int d
void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr, SAM_ACCOUNT *sampw,
uint16 logon_count, uint16 bad_pw_count,
uint32 num_groups, DOM_GID *gids,
- uint32 user_flgs, char *sess_key,
+ uint32 user_flgs, uchar *sess_key,
char *logon_srv, char *logon_dom,
DOM_SID *dom_sid, char *other_sids)
{
diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c
index 0f2b672d38..26054117fb 100644
--- a/source3/rpc_server/srv_netlog_nt.c
+++ b/source3/rpc_server/srv_netlog_nt.c
@@ -484,123 +484,6 @@ NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOF
return r_u->status;
}
-/*************************************************************************
- _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 *workstation, char *sess_key)
-{
- NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
-
- unsigned char local_lm_response[24];
- unsigned char local_nt_response[24];
-
- auth_usersupplied_info user_info;
- auth_serversupplied_info server_info;
- AUTH_STR ourdomain, theirdomain, smb_username, wksta_name;
-
- 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);
-
- theirdomain.str = domain;
- theirdomain.len = strlen(theirdomain.str);
-
- user_info.requested_domain = theirdomain;
- user_info.domain = ourdomain;
-
- smb_username.str = user;
- smb_username.len = strlen(smb_username.str);
-
- user_info.unix_username = smb_username; /* For the time-being */
- user_info.smb_username = smb_username;
-
- user_info.wksta_name.str = workstation;
- user_info.wksta_name.len = strlen(workstation);
-
- user_info.wksta_name = wksta_name;
-
- DEBUG(10,("_net_logon_any: Attempting validation level %d.\n", ctr->switch_value));
- switch (ctr->switch_value) {
- case NET_LOGON_TYPE:
- /* Standard challange/response authenticaion */
-
- 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:
- /* 'Interactive' autheticaion, supplies the password in its MD4 form, encrypted
- with the session key. We will convert this to challange/responce for the
- auth subsystem to chew on */
- {
- 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);
-
-#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(user_info.chal, 8, False);
- SMBOWFencrypt((const unsigned char *)lm_pwd, user_info.chal, local_lm_response);
- SMBOWFencrypt((const unsigned char *)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;
- }
- 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);
-
- DEBUG(5, ("_net_logon_any: exited with status %s\n",
- get_nt_error_msg(nt_status)));
-
- free_serversupplied_info(&server_info); /* No info needed */
-
- return nt_status;
-}
-
-
/*************************************************************************
_net_sam_logon
@@ -610,15 +493,16 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
{
NTSTATUS status = NT_STATUS_OK;
NET_USER_INFO_3 *usr_info = NULL;
+ NET_ID_INFO_CTR *ctr = q_u->sam_id.ctr;
DOM_CRED srv_cred;
SAM_ACCOUNT *sampass = NULL;
UNISTR2 *uni_samlogon_user = NULL;
UNISTR2 *uni_samlogon_domain = NULL;
UNISTR2 *uni_samlogon_workstation = NULL;
fstring nt_username, nt_domain, nt_workstation;
-
- BOOL ret;
-
+ auth_usersupplied_info *user_info;
+ auth_serversupplied_info *server_info;
+
usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3));
if (!usr_info)
return NT_STATUS_NO_MEMORY;
@@ -647,16 +531,17 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
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;
- uni_samlogon_workstation = &q_u->sam_id.ctr->auth.id1.uni_wksta_name;
+ uni_samlogon_user = &ctr->auth.id1.uni_user_name;
+ uni_samlogon_domain = &ctr->auth.id1.uni_domain_name;
+
+ uni_samlogon_workstation = &ctr->auth.id1.uni_wksta_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;
- uni_samlogon_workstation = &q_u->sam_id.ctr->auth.id2.uni_wksta_name;
+ uni_samlogon_user = &ctr->auth.id2.uni_user_name;
+ uni_samlogon_domain = &ctr->auth.id2.uni_domain_name;
+ uni_samlogon_workstation = &ctr->auth.id2.uni_wksta_name;
DEBUG(3,("SAM Logon (Network). Domain:[%s]. ", lp_workgroup()));
break;
@@ -678,29 +563,51 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
* Convert to a UNIX username.
*/
- map_username(nt_username);
+ DEBUG(5,("Attempting validation level %d for unmapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username));
- DEBUG(10,("Attempting validation level %d for mapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username));
+ switch (ctr->switch_value) {
+ case NET_LOGON_TYPE:
+ /* Standard challange/response authenticaion */
+ make_user_info_netlogon_network(&user_info,
+ nt_username, nt_domain,
+ nt_workstation, ctr->auth.id2.lm_chal,
+ ctr->auth.id2.lm_chal_resp.buffer,
+ ctr->auth.id2.lm_chal_resp.str_str_len,
+ ctr->auth.id2.nt_chal_resp.buffer,
+ ctr->auth.id2.nt_chal_resp.str_str_len);
+ break;
+ case INTERACTIVE_LOGON_TYPE:
+ /* 'Interactive' autheticaion, supplies the password in its MD4 form, encrypted
+ with the session key. We will convert this to challange/responce for the
+ auth subsystem to chew on */
+ {
+ make_user_info_netlogon_interactive(&user_info,
+ nt_username, nt_domain,
+ nt_workstation,
+ ctr->auth.id1.lm_owf.data, 16,
+ ctr->auth.id1.lm_owf.data, 16,
+ p->dc.sess_key);
+ break;
+ }
+ default:
+ DEBUG(2,("SAM Logon: unsupported switch value\n"));
+ return NT_STATUS_INVALID_INFO_CLASS;
+ } /* end switch */
+
+ status = check_password(user_info, &server_info);
- status = _net_logon_any(q_u->sam_id.ctr, nt_username, nt_domain, nt_workstation, (char *)p->dc.sess_key);
+ free_user_info(&user_info);
+
+ DEBUG(5, ("_net_sam_logon: exiting with status %s\n",
+ get_nt_error_msg(status)));
/* Check account and password */
- if (NT_STATUS_IS_ERR(status))
+ if (NT_STATUS_IS_ERR(status)) {
+ free_server_info(&server_info);
return status;
-
- pdb_init_sam(&sampass);
-
- /* get the account information */
- become_root();
- ret = pdb_getsampwnam(sampass, nt_username);
- unbecome_root();
-
- if (ret == False) {
- pdb_free_sam(&sampass);
- return NT_STATUS_NO_SUCH_USER;
}
-
+
/* 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. */
@@ -748,12 +655,14 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
num_gids, /* uint32 num_groups */
gids , /* DOM_GID *gids */
0x20 , /* uint32 user_flgs (?) */
- NULL, /* char sess_key[16] */
+ NULL, /* uchar sess_key[16] */
my_name , /* char *logon_srv */
my_workgroup, /* char *logon_dom */
&global_sam_sid, /* DOM_SID *dom_sid */
NULL); /* char *other_sids */
}
- pdb_free_sam(&sampass);
+ free_server_info(&server_info);
return status;
}
+
+
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index 6f3c050519..21de4d3d2b 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -269,10 +269,16 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm
fstring domain;
fstring wks;
BOOL guest_user = False;
- SAM_ACCOUNT *sampass = NULL;
uchar null_smb_passwd[16];
+
const uchar *smb_passwd_ptr = NULL;
+ auth_usersupplied_info *user_info;
+ auth_serversupplied_info *server_info;
+
+ uid_t *puid;
+ uid_t *pgid;
+
DEBUG(5,("api_pipe_ntlmssp_verify: checking user details\n"));
memset(p->user_name, '\0', sizeof(p->user_name));
@@ -336,14 +342,6 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm
} 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.
*/
@@ -362,41 +360,28 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm
}
if(!guest_user) {
+ NTSTATUS nt_status;
- become_root();
-
- p->ntlmssp_auth_validated =
- 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));
- if (!p->ntlmssp_auth_validated) {
- 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();
+ if (!make_user_info_netlogon_network(&user_info,
+ user_name, domain, wks, (uchar*)p->challenge,
+ lm_owf, lm_pw_len,
+ nt_owf, nt_pw_len)) {
+ DEBUG(0,("make_user_info_netlogon_network failed! Failing authenticaion.\n"));
return False;
}
- pdb_init_sam(&sampass);
-
- if(!pdb_getsampwnam(sampass, pipe_user_name)) {
- DEBUG(1,("api_pipe_ntlmssp_verify: Cannot find user %s in smb passwd database.\n",
- pipe_user_name));
- pdb_free_sam(&sampass);
- unbecome_root();
- return False;
- }
+ nt_status = check_password(user_info, &server_info);
+
+ free_user_info(&user_info);
- unbecome_root();
+ p->ntlmssp_auth_validated = NT_STATUS_IS_OK(nt_status);
- 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);
+ if (!p->ntlmssp_auth_validated) {
+ 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 ));
+ free_server_info(&server_info);
return False;
- }
-
- smb_passwd_ptr = pdb_get_lanman_passwd(sampass);
+ }
}
/*
@@ -405,7 +390,7 @@ failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name
{
uchar p24[24];
- NTLMSSPOWFencrypt(smb_passwd_ptr, lm_owf, p24);
+ NTLMSSPOWFencrypt(server_info->first_8_lm_hash, lm_owf, p24);
{
unsigned char j = 0;
int ind;
@@ -447,8 +432,17 @@ failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name
* Store the UNIX credential data (uid/gid pair) in the pipe structure.
*/
- p->pipe_user.uid = pdb_get_uid(sampass);
- p->pipe_user.gid = pdb_get_gid(sampass);
+ puid = pdb_get_uid(server_info->sam_account);
+ pgid = pdb_get_gid(server_info->sam_account);
+
+ if (!puid || !pgid) {
+ DEBUG(0,("Attempted authenticated pipe with invalid user. No uid/gid in SAM_ACCOUNT\n"));
+ free_server_info(&server_info);
+ return False;
+ }
+
+ p->pipe_user.uid = *puid;
+ p->pipe_user.gid = *pgid;
/* Set up pipe user group membership. */
initialise_groups(pipe_user_name, p->pipe_user.uid, p->pipe_user.gid);
@@ -461,7 +455,7 @@ failed authentication on named pipe %s.\n", domain, pipe_user_name, wks, p->name
p->ntlmssp_auth_validated = True;
- pdb_free_sam(&sampass);
+ pdb_free_sam(&server_info->sam_account);
return True;
}
diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c
index 44e44cfa3a..7369c9d37d 100644
--- a/source3/rpc_server/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srv_srvsvc_nt.c
@@ -1574,7 +1574,7 @@ NTSTATUS _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDE
{
SEC_DESC *psd = NULL;
size_t sd_size;
- fstring null_pw;
+ DATA_BLOB null_pw;
pstring filename;
pstring qualname;
files_struct *fsp = NULL;
@@ -1594,12 +1594,12 @@ NTSTATUS _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDE
unistr2_to_ascii(qualname, &q_u->uni_qual_name, sizeof(qualname));
/* Null password is ok - we are already an authenticated user... */
- *null_pw = '\0';
+ null_pw = data_blob(NULL, 0);
get_current_user(&user, p);
become_root();
- conn = make_connection(qualname, null_pw, 0, "A:", user.vuid, &nt_status);
+ conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status);
unbecome_root();
if (conn == NULL) {
@@ -1678,7 +1678,7 @@ NTSTATUS _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *
SRV_R_NET_FILE_SET_SECDESC *r_u)
{
BOOL ret;
- fstring null_pw;
+ DATA_BLOB null_pw;
pstring filename;
pstring qualname;
files_struct *fsp = NULL;
@@ -1698,12 +1698,12 @@ NTSTATUS _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *
unistr2_to_ascii(qualname, &q_u->uni_qual_name, sizeof(qualname));
/* Null password is ok - we are already an authenticated user... */
- *null_pw = '\0';
+ null_pw = data_blob(NULL, 0);
get_current_user(&user, p);
become_root();
- conn = make_connection(qualname, null_pw, 0, "A:", user.vuid, &nt_status);
+ conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status);
unbecome_root();
if (conn == NULL) {
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);
}