diff options
-rw-r--r-- | source4/auth/auth.c | 26 | ||||
-rw-r--r-- | source4/auth/auth.h | 42 | ||||
-rw-r--r-- | source4/auth/auth_anonymous.c | 2 | ||||
-rw-r--r-- | source4/auth/auth_domain.c | 17 | ||||
-rw-r--r-- | source4/auth/auth_sam.c | 87 | ||||
-rw-r--r-- | source4/auth/auth_unix.c | 25 | ||||
-rw-r--r-- | source4/auth/auth_util.c | 373 | ||||
-rw-r--r-- | source4/auth/auth_winbind.c | 26 | ||||
-rw-r--r-- | source4/auth/ntlm_check.c | 154 | ||||
-rw-r--r-- | source4/auth/ntlmssp/ntlmssp_server.c | 25 | ||||
-rw-r--r-- | source4/rpc_server/lsa/dcesrv_lsa.c | 2 | ||||
-rw-r--r-- | source4/rpc_server/netlogon/dcerpc_netlogon.c | 53 | ||||
-rw-r--r-- | source4/scripting/ejs/smbcalls_auth.c | 35 | ||||
-rw-r--r-- | source4/smb_server/sesssetup.c | 113 |
14 files changed, 516 insertions, 464 deletions
diff --git a/source4/auth/auth.c b/source4/auth/auth.c index d05aa54e50a..db1a0a1c719 100644 --- a/source4/auth/auth.c +++ b/source4/auth/auth.c @@ -113,7 +113,6 @@ NTSTATUS auth_get_challenge(struct auth_context *auth_ctx, const uint8_t **_chal * of that structure is undefined. * * @param user_info Contains the user supplied components, including the passwords. - * Must be created with make_user_info() or one of its wrappers. * * @param auth_context Supplies the challenges and some other data. * Must be created with make_auth_context(), and the challenges should be @@ -133,16 +132,25 @@ NTSTATUS auth_check_password(struct auth_context *auth_ctx, struct auth_serversupplied_info **server_info) { /* if all the modules say 'not for me' this is reasonable */ - NTSTATUS nt_status = NT_STATUS_NO_SUCH_USER; + NTSTATUS nt_status; struct auth_method_context *method; const char *method_name = "NO METHOD"; const uint8_t *challenge; + struct auth_usersupplied_info *user_info_tmp; DEBUG(3, ("auth_check_password: Checking password for unmapped user [%s]\\[%s]@[%s]\n", user_info->client.domain_name, user_info->client.account_name, user_info->workstation_name)); + if (!user_info->mapped_state) { + nt_status = map_user_info(mem_ctx, user_info, &user_info_tmp); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + user_info = user_info_tmp; + } + DEBUGADD(3,("auth_check_password: mapped user is: [%s]\\[%s]@[%s]\n", - user_info->domain_name, user_info->account_name, user_info->workstation_name)); + user_info->mapped.domain_name, user_info->mapped.account_name, user_info->workstation_name)); nt_status = auth_get_challenge(auth_ctx, &challenge); @@ -160,15 +168,7 @@ NTSTATUS auth_check_password(struct auth_context *auth_ctx, DEBUG(10, ("challenge is: \n")); dump_data(5, auth_ctx->challenge.data.data, auth_ctx->challenge.data.length); -#ifdef DEBUG_PASSWORD - DEBUG(100, ("user_info has passwords of length %d and %d\n", - user_info->lm_resp.length, user_info->nt_resp.length)); - DEBUG(100, ("lm:\n")); - dump_data(100, user_info->lm_resp.data, user_info->lm_resp.length); - DEBUG(100, ("nt:\n")); - dump_data(100, user_info->nt_resp.data, user_info->nt_resp.length); -#endif - + nt_status = NT_STATUS_NO_SUCH_USER; /* If all the modules say 'not for me', then this is reasonable */ for (method = auth_ctx->methods; method; method = method->next) { NTSTATUS result; @@ -186,7 +186,7 @@ NTSTATUS auth_check_password(struct auth_context *auth_ctx, if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(2,("auth_check_password: %s authentication for user [%s\\%s] FAILED with error %s\n", - method_name, user_info->domain_name, user_info->account_name, + method_name, user_info->mapped.domain_name, user_info->mapped.account_name, nt_errstr(nt_status))); return nt_status; } diff --git a/source4/auth/auth.h b/source4/auth/auth.h index b4f08b28591..0b12328b3ca 100644 --- a/source4/auth/auth.h +++ b/source4/auth/auth.h @@ -40,27 +40,38 @@ #define USER_INFO_CASE_INSENSITIVE_PASSWORD 0x02 /* password may be in any case */ #define USER_INFO_DONT_CHECK_UNIX_ACCOUNT 0x04 /* dont check unix account status */ +enum auth_password_state { + AUTH_PASSWORD_RESPONSE, + AUTH_PASSWORD_HASH, + AUTH_PASSWORD_PLAIN +}; + struct auth_usersupplied_info { - const char *account_name; - const char *domain_name; const char *workstation_name; const char *remote_host; + BOOL mapped_state; /* the values the client gives us */ struct { const char *account_name; const char *domain_name; - } client; - - BOOL encrypted; - - DATA_BLOB lm_resp; - DATA_BLOB nt_resp; - DATA_BLOB lm_interactive_password; - DATA_BLOB nt_interactive_password; - DATA_BLOB plaintext_password; - + } client, mapped; + + enum auth_password_state password_state; + + union { + struct { + DATA_BLOB lanman; + DATA_BLOB nt; + } response; + struct { + struct samr_Password *lanman; + struct samr_Password *nt; + } hash; + + char *plaintext; + } password; uint32_t flags; }; @@ -157,7 +168,12 @@ struct auth_critical_sizes { int sizeof_auth_context; int sizeof_auth_usersupplied_info; int sizeof_auth_serversupplied_info; - int sizeof_auth_str; }; + NTSTATUS encrypt_user_info(TALLOC_CTX *mem_ctx, struct auth_context *auth_context, + enum auth_password_state to_state, + const struct auth_usersupplied_info *user_info_in, + const struct auth_usersupplied_info **user_info_encrypted); + + #endif /* _SMBAUTH_H_ */ diff --git a/source4/auth/auth_anonymous.c b/source4/auth/auth_anonymous.c index 43255504130..82aa69c72af 100644 --- a/source4/auth/auth_anonymous.c +++ b/source4/auth/auth_anonymous.c @@ -37,7 +37,7 @@ static NTSTATUS anonymous_check_password(struct auth_method_context *ctx, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **_server_info) { - if (user_info->account_name && *user_info->account_name) { + if (user_info->client.account_name && *user_info->client.account_name) { return NT_STATUS_NOT_IMPLEMENTED; } diff --git a/source4/auth/auth_domain.c b/source4/auth/auth_domain.c index 339cc185312..25701499020 100644 --- a/source4/auth/auth_domain.c +++ b/source4/auth/auth_domain.c @@ -53,9 +53,6 @@ static NTSTATUS domain_check_password(struct auth_method_context *ctx, return NT_STATUS_INVALID_PARAMETER; } - if (!user_info->account_name) { - return NT_STATUS_INVALID_PARAMETER; - } if (!user_info->workstation_name) { return NT_STATUS_INVALID_PARAMETER; } @@ -97,18 +94,18 @@ static NTSTATUS domain_check_password(struct auth_method_context *ctx, return status; } - ninfo.identity_info.domain_name.string = user_info->domain_name; + ninfo.identity_info.domain_name.string = user_info->client.domain_name; ninfo.identity_info.parameter_control = 0; ninfo.identity_info.logon_id_low = 0; ninfo.identity_info.logon_id_high = 0; - ninfo.identity_info.account_name.string = user_info->account_name; + ninfo.identity_info.account_name.string = user_info->client.account_name; ninfo.identity_info.workstation.string = user_info->workstation_name; memcpy(ninfo.challenge, ctx->auth_ctx->challenge.data.data, sizeof(ninfo.challenge)); - ninfo.nt.length = user_info->nt_resp.length; - ninfo.nt.data = user_info->nt_resp.data; - ninfo.lm.length = user_info->lm_resp.length; - ninfo.lm.data = user_info->lm_resp.data; + ninfo.nt.length = user_info->password.response.nt.length; + ninfo.nt.data = user_info->password.response.nt.data; + ninfo.lm.length = user_info->password.response.lanman.length; + ninfo.lm.data = user_info->password.response.lanman.data; r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p)); r.in.workstation = cli_credentials_get_workstation(credentials); @@ -135,7 +132,7 @@ static NTSTATUS domain_check_password(struct auth_method_context *ctx, } status = make_server_info_netlogon_validation(mem_ctx, - user_info->account_name, + user_info->client.account_name, r.in.validation_level, &r.out.validation, server_info); return status; diff --git a/source4/auth/auth_sam.c b/source4/auth/auth_sam.c index 7f5f41e58c6..f697164cd46 100644 --- a/source4/auth/auth_sam.c +++ b/source4/auth/auth_sam.c @@ -31,7 +31,7 @@ Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ -static NTSTATUS authsam_password_ok(const struct auth_context *auth_context, +static NTSTATUS authsam_password_ok(struct auth_context *auth_context, TALLOC_CTX *mem_ctx, uint16_t acct_flags, const struct samr_Password *lm_pwd, @@ -45,25 +45,54 @@ static NTSTATUS authsam_password_ok(const struct auth_context *auth_context, if (acct_flags & ACB_PWNOTREQ) { if (lp_null_passwords()) { DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", - user_info->account_name)); + user_info->mapped.account_name)); return NT_STATUS_OK; } else { DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", - user_info->account_name)); + user_info->mapped.account_name)); return NT_STATUS_LOGON_FAILURE; } } - status = ntlm_password_check(mem_ctx, &auth_context->challenge.data, - &user_info->lm_resp, &user_info->nt_resp, - &user_info->lm_interactive_password, - &user_info->nt_interactive_password, - user_info->account_name, - user_info->client.account_name, - user_info->client.domain_name, - lm_pwd->hash, nt_pwd->hash, - user_sess_key, lm_sess_key); - NT_STATUS_NOT_OK_RETURN(status); + switch (user_info->password_state) { + case AUTH_PASSWORD_PLAIN: + { + const struct auth_usersupplied_info *user_info_temp; + status = encrypt_user_info(mem_ctx, auth_context, + AUTH_PASSWORD_HASH, + user_info, &user_info_temp); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Failed to convert plaintext password to password HASH: %s\n", nt_errstr(status))); + return status; + } + user_info = user_info_temp; + + /* NO break */ + } + case AUTH_PASSWORD_HASH: + status = hash_password_check(mem_ctx, + user_info->password.hash.lanman, + user_info->password.hash.nt, + user_info->mapped.account_name, + user_info->client.account_name, + user_info->client.domain_name, + lm_pwd, nt_pwd, + user_sess_key, lm_sess_key); + NT_STATUS_NOT_OK_RETURN(status); + break; + + case AUTH_PASSWORD_RESPONSE: + status = ntlm_password_check(mem_ctx, &auth_context->challenge.data, + &user_info->password.response.lanman, + &user_info->password.response.nt, + user_info->mapped.account_name, + user_info->client.account_name, + user_info->client.domain_name, + lm_pwd, nt_pwd, + user_sess_key, lm_sess_key); + NT_STATUS_NOT_OK_RETURN(status); + break; + } if (user_sess_key && user_sess_key->data) { talloc_steal(auth_context, user_sess_key->data); @@ -88,23 +117,23 @@ static NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, const char *workstation_list, const struct auth_usersupplied_info *user_info) { - DEBUG(4,("authsam_account_ok: Checking SMB password for user %s\n", user_info->account_name)); + DEBUG(4,("authsam_account_ok: Checking SMB password for user %s\n", user_info->mapped.account_name)); /* Quit if the account was disabled. */ if (acct_flags & ACB_DISABLED) { - DEBUG(1,("authsam_account_ok: Account for user '%s' was disabled.\n", user_info->account_name)); + DEBUG(1,("authsam_account_ok: Account for user '%s' was disabled.\n", user_info->mapped.account_name)); return NT_STATUS_ACCOUNT_DISABLED; } /* Quit if the account was locked out. */ if (acct_flags & ACB_AUTOLOCK) { - DEBUG(1,("authsam_account_ok: Account for user %s was locked out.\n", user_info->account_name)); + DEBUG(1,("authsam_account_ok: Account for user %s was locked out.\n", user_info->mapped.account_name)); return NT_STATUS_ACCOUNT_LOCKED_OUT; } /* Test account expire time */ if ((acct_expiry) != -1 && time(NULL) > nt_time_to_unix(acct_expiry)) { - DEBUG(1,("authsam_account_ok: Account for user '%s' has expired.\n", user_info->account_name)); + DEBUG(1,("authsam_account_ok: Account for user '%s' has expired.\n", user_info->mapped.account_name)); DEBUG(3,("authsam_account_ok: Account expired at '%s'.\n", nt_time_string(mem_ctx, acct_expiry))); return NT_STATUS_ACCOUNT_EXPIRED; @@ -114,14 +143,14 @@ static NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, /* check for immediate expiry "must change at next logon" */ if (must_change_time == 0 && last_set_time != 0) { DEBUG(1,("sam_account_ok: Account for user '%s' password must change!.\n", - user_info->account_name)); + user_info->mapped.account_name)); return NT_STATUS_PASSWORD_MUST_CHANGE; } /* check for expired password */ if ((must_change_time) != 0 && nt_time_to_unix(must_change_time) < time(NULL)) { DEBUG(1,("sam_account_ok: Account for user '%s' password expired!.\n", - user_info->account_name)); + user_info->mapped.account_name)); DEBUG(1,("sam_account_ok: Password expired at '%s' unix time.\n", nt_time_string(mem_ctx, must_change_time))); return NT_STATUS_PASSWORD_EXPIRED; @@ -152,17 +181,17 @@ static NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx, } if (acct_flags & ACB_DOMTRUST) { - DEBUG(2,("sam_account_ok: Domain trust account %s denied by server\n", user_info->account_name)); + DEBUG(2,("sam_account_ok: Domain trust account %s denied by server\n", user_info->mapped.account_name)); return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT; } if (acct_flags & ACB_SVRTRUST) { - DEBUG(2,("sam_account_ok: Server trust account %s denied by server\n", user_info->account_name)); + DEBUG(2,("sam_account_ok: Server trust account %s denied by server\n", user_info->mapped.account_name)); return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT; } if (acct_flags & ACB_WSTRUST) { - DEBUG(4,("sam_account_ok: Wksta trust account %s denied by server\n", user_info->account_name)); + DEBUG(4,("sam_account_ok: Wksta trust account %s denied by server\n", user_info->mapped.account_name)); return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT; } @@ -311,7 +340,7 @@ static NTSTATUS authsam_search_account(TALLOC_CTX *mem_ctx, struct ldb_context * return NT_STATUS_OK; } -static NTSTATUS authsam_authenticate(const struct auth_context *auth_context, +static NTSTATUS authsam_authenticate(struct auth_context *auth_context, TALLOC_CTX *mem_ctx, struct ldb_context *sam_ctx, struct ldb_message **msgs, struct ldb_message **msgs_domain, @@ -332,7 +361,7 @@ static NTSTATUS authsam_authenticate(const struct auth_context *auth_context, /* Quit if the account was locked out. */ if (acct_flags & ACB_AUTOLOCK) { DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", - user_info->account_name)); + user_info->mapped.account_name)); return NT_STATUS_ACCOUNT_LOCKED_OUT; } @@ -517,7 +546,7 @@ static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx struct auth_serversupplied_info **server_info) { NTSTATUS nt_status; - const char *account_name = user_info->account_name; + const char *account_name = user_info->mapped.account_name; struct ldb_message **msgs; struct ldb_message **domain_msgs; struct ldb_context *sam_ctx; @@ -570,8 +599,8 @@ static NTSTATUS authsam_check_password(struct auth_method_context *ctx, const char *domain; BOOL is_local_name, is_my_domain; - is_local_name = is_myname(user_info->domain_name); - is_my_domain = strequal(user_info->domain_name, lp_workgroup()); + is_local_name = is_myname(user_info->mapped.domain_name); + is_my_domain = strequal(user_info->mapped.domain_name, lp_workgroup()); /* check whether or not we service this domain/workgroup name */ switch (lp_server_role()) { @@ -581,7 +610,7 @@ static NTSTATUS authsam_check_password(struct auth_method_context *ctx, case ROLE_DOMAIN_MEMBER: if (!is_local_name) { DEBUG(6,("authsam_check_password: %s is not one of my local names (%s)\n", - user_info->domain_name, (lp_server_role() == ROLE_DOMAIN_MEMBER + user_info->mapped.domain_name, (lp_server_role() == ROLE_DOMAIN_MEMBER ? "ROLE_DOMAIN_MEMBER" : "ROLE_STANDALONE") )); return NT_STATUS_NOT_IMPLEMENTED; } @@ -591,7 +620,7 @@ static NTSTATUS authsam_check_password(struct auth_method_context *ctx, case ROLE_DOMAIN_BDC: if (!is_local_name && !is_my_domain) { DEBUG(6,("authsam_check_password: %s is not one of my local names or domain name (DC)\n", - user_info->domain_name)); + user_info->mapped.domain_name)); return NT_STATUS_NOT_IMPLEMENTED; } domain = lp_workgroup(); diff --git a/source4/auth/auth_unix.c b/source4/auth/auth_unix.c index ecdd770362d..0c2db48c563 100644 --- a/source4/auth/auth_unix.c +++ b/source4/auth/auth_unix.c @@ -38,7 +38,7 @@ static NTSTATUS authunix_make_server_info(TALLOC_CTX *mem_ctx, server_info->authenticated = True; - server_info->account_name = talloc_strdup(server_info, talloc_strdup(mem_ctx, user_info->account_name)); + server_info->account_name = talloc_strdup(server_info, talloc_strdup(mem_ctx, user_info->mapped.account_name)); NT_STATUS_HAVE_NO_MEMORY(server_info->account_name); server_info->domain_name = talloc_strdup(server_info, talloc_strdup(mem_ctx, "unix")); @@ -379,8 +379,8 @@ static NTSTATUS check_unix_password(TALLOC_CTX *ctx, const struct auth_usersuppl return NT_STATUS_NO_MEMORY; } - info->account_name = user_info->account_name; - info->plaintext_password = (char *)(user_info->plaintext_password.data); + info->account_name = user_info->mapped.account_name; + info->plaintext_password = user_info->password.plaintext; pamconv = talloc(ctx, struct pam_conv); if (pamconv == NULL) { @@ -395,13 +395,13 @@ static NTSTATUS check_unix_password(TALLOC_CTX *ctx, const struct auth_usersuppl * if true set up a crack name routine. */ - nt_status = smb_pam_start(&pamh, user_info->account_name, user_info->remote_host, pamconv); + nt_status = smb_pam_start(&pamh, user_info->mapped.account_name, user_info->remote_host, pamconv); if (!NT_STATUS_IS_OK(nt_status)) { smb_pam_end(pamh); return nt_status; } - nt_status = smb_pam_auth(pamh, user_info->account_name); + nt_status = smb_pam_auth(pamh, user_info->mapped.account_name); if (!NT_STATUS_IS_OK(nt_status)) { smb_pam_end(pamh); return nt_status; @@ -409,13 +409,13 @@ static NTSTATUS check_unix_password(TALLOC_CTX *ctx, const struct auth_usersuppl if ( ! (user_info->flags & USER_INFO_DONT_CHECK_UNIX_ACCOUNT)) { - nt_status = smb_pam_account(pamh, user_info->account_name); + nt_status = smb_pam_account(pamh, user_info->mapped.account_name); if (!NT_STATUS_IS_OK(nt_status)) { smb_pam_end(pamh); return nt_status; } - nt_status = smb_pam_setcred(pamh, user_info->account_name); + nt_status = smb_pam_setcred(pamh, user_info->mapped.account_name); if (!NT_STATUS_IS_OK(nt_status)) { smb_pam_end(pamh); return nt_status; @@ -598,8 +598,8 @@ static NTSTATUS check_unix_password(TALLOC_CTX *ctx, const struct auth_usersuppl NTSTATUS nt_status; int level = lp_passwordlevel(); - username = talloc_strdup(ctx, user_info->account_name); - password = talloc_strdup(ctx, user_info->plaintext_password.data); + username = talloc_strdup(ctx, user_info->mapped.account_name); + password = talloc_strdup(ctx, user_info->password.plaintext); nt_status = talloc_getpwnam(ctx, username, &pws); if (!NT_STATUS_IS_OK(nt_status)) { @@ -772,7 +772,12 @@ static NTSTATUS authunix_check_password(struct auth_method_context *ctx, TALLOC_CTX *check_ctx; NTSTATUS nt_status; - if (! user_info->account_name && ! *user_info->account_name) { + if (! user_info->mapped.account_name || ! *user_info->mapped.account_name) { + /* 'not for me' */ + return NT_STATUS_NOT_IMPLEMENTED; + } + + if (user_info->password_state != AUTH_PASSWORD_PLAIN) { return NT_STATUS_INVALID_PARAMETER; } diff --git a/source4/auth/auth_util.c b/source4/auth/auth_util.c index 2c8787726b4..433041348ec 100644 --- a/source4/auth/auth_util.c +++ b/source4/auth/auth_util.c @@ -38,135 +38,32 @@ NTSTATUS auth_get_challenge_not_implemented(struct auth_method_context *ctx, TAL } /**************************************************************************** - Create an auth_usersupplied_data structure -****************************************************************************/ -NTSTATUS make_user_info(TALLOC_CTX *mem_ctx, - const char *c_account_name, - const char *account_name, - const char *c_domain_name, - const char *domain_name, - const char *workstation_name, - const char *remote_host, - DATA_BLOB *lm_password, DATA_BLOB *nt_password, - DATA_BLOB *lm_interactive_password, DATA_BLOB *nt_interactive_password, - DATA_BLOB *plaintext_password, BOOL encrypted, uint32_t flags, - struct auth_usersupplied_info **_user_info) -{ - struct auth_usersupplied_info *user_info; - DATA_BLOB blob; - - DEBUG(5,("attempting to make a user_info for %s (%s)\n", account_name, c_account_name)); - - user_info = talloc(mem_ctx, struct auth_usersupplied_info); - NT_STATUS_HAVE_NO_MEMORY(user_info); - - DEBUG(5,("making strings for %s's user_info struct\n", account_name)); - - user_info->client.account_name = talloc_strdup(user_info, c_account_name); - NT_STATUS_HAVE_NO_MEMORY(user_info->client.account_name); - - user_info->account_name = talloc_strdup(user_info, account_name); - NT_STATUS_HAVE_NO_MEMORY(user_info->account_name); - - user_info->client.domain_name = talloc_strdup(user_info, c_domain_name); - if (c_domain_name && !user_info->client.domain_name) { - return NT_STATUS_NO_MEMORY; - } - - user_info->domain_name = talloc_strdup(user_info, domain_name); - NT_STATUS_HAVE_NO_MEMORY(user_info->domain_name); - - user_info->workstation_name = talloc_strdup(user_info, workstation_name); - NT_STATUS_HAVE_NO_MEMORY(user_info->workstation_name); - - user_info->remote_host = talloc_strdup(user_info, remote_host); - NT_STATUS_HAVE_NO_MEMORY(user_info->remote_host); - - DEBUG(5,("making blobs for %s's user_info struct\n", account_name)); - - if (lm_password) { - blob = data_blob_dup_talloc(user_info, lm_password); - NT_STATUS_HAVE_NO_MEMORY(blob.data); - } else { - blob = data_blob(NULL, 0); - } - user_info->lm_resp = blob; - - if (nt_password) { - blob = data_blob_dup_talloc(user_info, nt_password); - NT_STATUS_HAVE_NO_MEMORY(blob.data); - } else { - blob = data_blob(NULL, 0); - } - user_info->nt_resp = blob; - - if (lm_interactive_password) { - blob = data_blob_dup_talloc(user_info, lm_interactive_password); - NT_STATUS_HAVE_NO_MEMORY(blob.data); - } else { - blob = data_blob(NULL, 0); - } - user_info->lm_interactive_password = blob; - - if (nt_interactive_password) { - blob = data_blob_dup_talloc(user_info, nt_interactive_password); - NT_STATUS_HAVE_NO_MEMORY(blob.data); - } else { - blob = data_blob(NULL, 0); - } - user_info->nt_interactive_password = blob; - - if (plaintext_password) { - blob = data_blob_dup_talloc(user_info, plaintext_password); - NT_STATUS_HAVE_NO_MEMORY(blob.data); - } else { - blob = data_blob(NULL, 0); - } - user_info->plaintext_password = blob; - - user_info->encrypted = encrypted; - user_info->flags = flags; - - DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , account_name, c_account_name)); - - *_user_info = user_info; - - return NT_STATUS_OK; -} - -/**************************************************************************** Create an auth_usersupplied_data structure after appropriate mapping. ****************************************************************************/ -NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx, - const char *c_account_name, - const char *c_domain_name, - const char *workstation_name, - DATA_BLOB *lm_password, DATA_BLOB *nt_password, - DATA_BLOB *lm_interactive_password, DATA_BLOB *nt_interactive_password, - DATA_BLOB *plaintext, BOOL encrypted, - struct auth_usersupplied_info **user_info) +NTSTATUS map_user_info(TALLOC_CTX *mem_ctx, + const struct auth_usersupplied_info *user_info, + struct auth_usersupplied_info **user_info_mapped) { const char *domain; - const char *account_name; + char *account_name; char *d; - DEBUG(5,("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n", - c_domain_name, c_account_name, workstation_name)); - - account_name = c_account_name; + DEBUG(5,("map_user_info: Mapping user [%s]\\[%s] from workstation [%s]\n", + user_info->client.domain_name, user_info->client.account_name, user_info->workstation_name)); + account_name = talloc_strdup(mem_ctx, user_info->client.account_name); + if (!account_name) { + return NT_STATUS_NO_MEMORY; + } + /* don't allow "" as a domain, fixes a Win9X bug where it doens't supply a domain for logon script 'net use' commands. */ /* Split user@realm names into user and realm components. This is TODO to fix with proper userprincipalname support */ - if (c_domain_name && *c_domain_name) { - domain = c_domain_name; - } else if (strchr_m(c_account_name, '@')) { - account_name = talloc_strdup(mem_ctx, c_account_name); - if (!account_name) { - return NT_STATUS_NO_MEMORY; - } + if (user_info->client.domain_name && *user_info->client.domain_name) { + domain = user_info->client.domain_name; + } else if (strchr_m(user_info->client.account_name, '@')) { d = strchr_m(account_name, '@'); if (!d) { return NT_STATUS_INTERNAL_ERROR; @@ -178,121 +75,155 @@ NTSTATUS make_user_info_map(TALLOC_CTX *mem_ctx, domain = lp_workgroup(); } - return make_user_info(mem_ctx, - c_account_name, account_name, - c_domain_name, domain, - workstation_name, - workstation_name, - lm_password, nt_password, - lm_interactive_password, nt_interactive_password, - plaintext, encrypted, 0x00, - user_info); -} + *user_info_mapped = talloc(mem_ctx, struct auth_usersupplied_info); + if (!*user_info_mapped) { + return NT_STATUS_NO_MEMORY; + } + talloc_reference(*user_info_mapped, user_info); + **user_info_mapped = *user_info; + (*user_info_mapped)->mapped_state = True; + (*user_info_mapped)->mapped.domain_name = talloc_strdup(*user_info_mapped, domain); + (*user_info_mapped)->mapped.account_name = talloc_strdup(*user_info_mapped, account_name); + talloc_free(account_name); + if (!(*user_info_mapped)->mapped.domain_name + || !(*user_info_mapped)->mapped.account_name) { + return NT_STATUS_NO_MEMORY; + } -/**************************************************************************** - Create an auth_usersupplied_data, making the DATA_BLOBs here. - Decrypt and encrypt the passwords. -****************************************************************************/ -NTSTATUS make_user_info_netlogon_network(TALLOC_CTX *mem_ctx, - const char *c_account_name, - const char *c_domain_name, - const char *workstation_name, - const uint8_t *lm_network_password, int lm_password_len, - const uint8_t *nt_network_password, int nt_password_len, - struct auth_usersupplied_info **user_info) -{ - DATA_BLOB lm_blob = data_blob_const(lm_network_password, lm_password_len); - DATA_BLOB nt_blob = data_blob_const(nt_network_password, nt_password_len); - - return make_user_info_map(mem_ctx, - c_account_name, - c_domain_name, - workstation_name, - lm_password_len ? &lm_blob : NULL, - nt_password_len ? &nt_blob : NULL, - NULL, NULL, NULL, True, - user_info); + return NT_STATUS_OK; } /**************************************************************************** - Create an auth_usersupplied_data, making the DATA_BLOBs here. - Decrypt and encrypt the passwords. + Create an auth_usersupplied_data structure after appropriate mapping. ****************************************************************************/ -NTSTATUS make_user_info_netlogon_interactive(TALLOC_CTX *mem_ctx, - const char *c_account_name, - const char *c_domain_name, - const char *workstation_name, - const uint8_t chal[8], - const struct samr_Password *lm_interactive_password, - const struct samr_Password *nt_interactive_password, - struct auth_usersupplied_info **user_info) + + NTSTATUS encrypt_user_info(TALLOC_CTX *mem_ctx, struct auth_context *auth_context, + enum auth_password_state to_state, + const struct auth_usersupplied_info *user_info_in, + const struct auth_usersupplied_info **user_info_encrypted) { NTSTATUS nt_status; - DATA_BLOB local_lm_blob; - DATA_BLOB local_nt_blob; - - DATA_BLOB lm_interactive_blob; - DATA_BLOB nt_interactive_blob; - uint8_t local_lm_response[24]; - uint8_t local_nt_response[24]; - - SMBOWFencrypt(lm_interactive_password->hash, chal, local_lm_response); - SMBOWFencrypt(nt_interactive_password->hash, chal, local_nt_response); - - local_lm_blob = data_blob_const(local_lm_response, sizeof(local_lm_response)); - lm_interactive_blob = data_blob_const(lm_interactive_password->hash, - sizeof(lm_interactive_password->hash)); - - local_nt_blob = data_blob_const(local_nt_response, sizeof(local_nt_response)); - nt_interactive_blob = data_blob_const(nt_interactive_password->hash, - sizeof(nt_interactive_password->hash)); - - nt_status = make_user_info_map(mem_ctx, - c_account_name, - c_domain_name, - workstation_name, - &local_lm_blob, - &local_nt_blob, - &lm_interactive_blob, - &nt_interactive_blob, - NULL, True, - user_info); - return nt_status; -} + struct auth_usersupplied_info *user_info_temp; + switch (to_state) { + case AUTH_PASSWORD_RESPONSE: + switch (user_info_in->password_state) { + case AUTH_PASSWORD_PLAIN: + { + const struct auth_usersupplied_info *user_info_temp2; + nt_status = encrypt_user_info(mem_ctx, auth_context, + AUTH_PASSWORD_HASH, + user_info_in, &user_info_temp2); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + user_info_in = user_info_temp2; + } + case AUTH_PASSWORD_HASH: + { + const uint8_t *challenge; + DATA_BLOB chall_blob; + user_info_temp = talloc(mem_ctx, struct auth_usersupplied_info); + if (!user_info_temp) { + return NT_STATUS_NO_MEMORY; + } + talloc_reference(user_info_temp, user_info_in); + *user_info_temp = *user_info_in; + user_info_temp->mapped_state = to_state; + + nt_status = auth_get_challenge(auth_context, &challenge); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + chall_blob = data_blob_talloc(mem_ctx, challenge, 8); + if (lp_client_ntlmv2_auth()) { + DATA_BLOB names_blob = NTLMv2_generate_names_blob(mem_ctx, lp_netbios_name(), lp_workgroup()); + DATA_BLOB lmv2_response, ntlmv2_response, lmv2_session_key, ntlmv2_session_key; + + if (!SMBNTLMv2encrypt_hash(user_info_temp, + user_info_in->client.account_name, + user_info_in->client.domain_name, + user_info_in->password.hash.nt->hash, &chall_blob, + &names_blob, + &lmv2_response, &ntlmv2_response, + &lmv2_session_key, &ntlmv2_session_key)) { + data_blob_free(&names_blob); + return NT_STATUS_NO_MEMORY; + } + data_blob_free(&names_blob); + user_info_temp->password.response.lanman = lmv2_response; + user_info_temp->password.response.nt = ntlmv2_response; + + data_blob_free(&lmv2_session_key); + data_blob_free(&ntlmv2_session_key); + } else { + DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, 24); + SMBOWFencrypt(user_info_in->password.hash.nt->hash, challenge, blob.data); + + user_info_temp->password.response.nt = blob; + if (lp_client_lanman_auth() && user_info_in->password.hash.lanman) { + DATA_BLOB lm_blob = data_blob_talloc(mem_ctx, NULL, 24); + SMBOWFencrypt(user_info_in->password.hash.lanman->hash, challenge, blob.data); + user_info_temp->password.response.lanman = lm_blob; + } else { + /* if not sending the LM password, send the NT password twice */ + user_info_temp->password.response.lanman = user_info_temp->password.response.nt; + } + } -/**************************************************************************** - Create an auth_usersupplied_data structure -****************************************************************************/ -NTSTATUS make_user_info_for_reply_enc(TALLOC_CTX *mem_ctx, - const char *c_account_name, - const char *c_domain_name, - const char *workstation_name, - DATA_BLOB lm_resp, DATA_BLOB nt_resp, - struct auth_usersupplied_info **user_info) -{ - return make_user_info_map(mem_ctx, - c_account_name, - c_domain_name, - workstation_name, - lm_resp.data ? &lm_resp : NULL, - nt_resp.data ? &nt_resp : NULL, - NULL, NULL, NULL, True, - user_info); -} + user_info_in = user_info_temp; + } + case AUTH_PASSWORD_RESPONSE: + *user_info_encrypted = user_info_in; + } + break; + case AUTH_PASSWORD_HASH: + { + switch (user_info_in->password_state) { + case AUTH_PASSWORD_PLAIN: + { + struct samr_Password lanman; + struct samr_Password nt; + + user_info_temp = talloc(mem_ctx, struct auth_usersupplied_info); + if (!user_info_temp) { + return NT_STATUS_NO_MEMORY; + } + talloc_reference(user_info_temp, user_info_in); + *user_info_temp = *user_info_in; + user_info_temp->mapped_state = to_state; + + if (E_deshash(user_info_in->password.plaintext, lanman.hash)) { + user_info_temp->password.hash.lanman = talloc(user_info_temp, + struct samr_Password); + *user_info_temp->password.hash.lanman = lanman; + } else { + user_info_temp->password.hash.lanman = NULL; + } + + E_md4hash(user_info_in->password.plaintext, nt.hash); + user_info_temp->password.hash.nt = talloc(user_info_temp, + struct samr_Password); + *user_info_temp->password.hash.nt = nt; + + user_info_in = user_info_temp; + } + case AUTH_PASSWORD_HASH: + *user_info_encrypted = user_info_in; + break; + default: + return NT_STATUS_INVALID_PARAMETER; + break; + } + break; + } + default: + return NT_STATUS_INVALID_PARAMETER; + } -/**************************************************************************** - Create a anonymous user_info blob, for anonymous authenticaion. -****************************************************************************/ -NTSTATUS make_user_info_anonymous(TALLOC_CTX *mem_ctx, struct auth_usersupplied_info **user_info) -{ - return make_user_info(mem_ctx, - "", "", "", "", "", "", - NULL, NULL, NULL, NULL, - NULL, True, 0x00, - user_info); + return NT_STATUS_OK; } - /*************************************************************************** Make a server_info struct from the info3 returned by a domain logon ***************************************************************************/ diff --git a/source4/auth/auth_winbind.c b/source4/auth/auth_winbind.c index 8a6a5a720bf..878e706b9b5 100644 --- a/source4/auth/auth_winbind.c +++ b/source4/auth/auth_winbind.c @@ -59,27 +59,35 @@ static NTSTATUS winbind_check_password(struct auth_method_context *ctx, struct netr_SamInfo3 info3; /* Send off request */ + const struct auth_usersupplied_info *user_info_temp; + nt_status = encrypt_user_info(mem_ctx, ctx->auth_ctx, + AUTH_PASSWORD_RESPONSE, + user_info, &user_info_temp); + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + user_info = user_info_temp; ZERO_STRUCT(request); ZERO_STRUCT(response); request.flags = WBFLAG_PAM_INFO3_NDR; fstrcpy(request.data.auth_crap.user, - user_info->account_name); + user_info->client.account_name); fstrcpy(request.data.auth_crap.domain, - user_info->domain_name); + user_info->client.domain_name); fstrcpy(request.data.auth_crap.workstation, user_info->workstation_name); memcpy(request.data.auth_crap.chal, ctx->auth_ctx->challenge.data.data, sizeof(request.data.auth_crap.chal)); - request.data.auth_crap.lm_resp_len = MIN(user_info->lm_resp.length, + request.data.auth_crap.lm_resp_len = MIN(user_info->password.response.lanman.length, sizeof(request.data.auth_crap.lm_resp)); - request.data.auth_crap.nt_resp_len = MIN(user_info->nt_resp.length, + request.data.auth_crap.nt_resp_len = MIN(user_info->password.response.nt.length, sizeof(request.data.auth_crap.nt_resp)); - memcpy(request.data.auth_crap.lm_resp, user_info->lm_resp.data, + memcpy(request.data.auth_crap.lm_resp, user_info->password.response.lanman.data, request.data.auth_crap.lm_resp_len); - memcpy(request.data.auth_crap.nt_resp, user_info->nt_resp.data, + memcpy(request.data.auth_crap.nt_resp, user_info->password.response.nt.data, request.data.auth_crap.nt_resp_len); result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response); @@ -96,19 +104,19 @@ static NTSTATUS winbind_check_password(struct auth_method_context *ctx, validation.sam3 = &info3; nt_status = make_server_info_netlogon_validation(mem_ctx, - user_info->account_name, + user_info->client.account_name, 3, &validation, server_info); return nt_status; } else if (result == NSS_STATUS_SUCCESS && !response.extra_data) { DEBUG(0, ("Winbindd authenticated the user [%s]\\[%s], " "but did not include the required info3 reply!\n", - user_info->domain_name, user_info->account_name)); + user_info->client.domain_name, user_info->client.account_name)); return NT_STATUS_INSUFFICIENT_LOGON_INFO; } else if (NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("Winbindd authentication for [%s]\\[%s] failed, " "but no error code is available!\n", - user_info->domain_name, user_info->account_name)); + user_info->client.domain_name, user_info->client.account_name)); return NT_STATUS_NO_LOGON_SERVERS; } diff --git a/source4/auth/ntlm_check.c b/source4/auth/ntlm_check.c index b3087419709..fb7dd3384d0 100644 --- a/source4/auth/ntlm_check.c +++ b/source4/auth/ntlm_check.c @@ -22,6 +22,7 @@ #include "includes.h" #include "lib/crypto/crypto.h" +#include "librpc/gen_ndr/ndr_samr.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -205,39 +206,32 @@ static BOOL smb_sess_key_ntlmv2(TALLOC_CTX *mem_ctx, } /** - * Check a challenge-response password against the value of the NT or - * LM password hash. + * Compare password hashes against those from the SAM * * @param mem_ctx talloc context - * @param challenge 8-byte challenge. If all zero, forces plaintext comparison - * @param nt_response 'unicode' NT response to the challenge, or unicode password - * @param lm_response ASCII or LANMAN response to the challenge, or password in DOS code page + * @param client_lanman LANMAN password hash, as supplied by the client + * @param client_nt NT (MD4) password hash, as supplied by the client * @param username internal Samba username, for log messages * @param client_username username the client used * @param client_domain domain name the client used (may be mapped) - * @param nt_pw MD4 unicode password from our passdb or similar - * @param lm_pw LANMAN ASCII password from our passdb or similar + * @param stored_lanman LANMAN password hash, as stored on the SAM + * @param stored_nt NT (MD4) password hash, as stored on the SAM * @param user_sess_key User session key * @param lm_sess_key LM session key (first 8 bytes of the LM hash) */ -NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, - const DATA_BLOB *challenge, - const DATA_BLOB *lm_response, - const DATA_BLOB *nt_response, - const DATA_BLOB *lm_interactive_password, - const DATA_BLOB *nt_interactive_password, +NTSTATUS hash_password_check(TALLOC_CTX *mem_ctx, + const struct samr_Password *client_lanman, + const struct samr_Password *client_nt, const char *username, const char *client_username, const char *client_domain, - const uint8_t *lm_pw, const uint8_t *nt_pw, + const struct samr_Password *stored_lanman, + const struct samr_Password *stored_nt, DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key) { - static const uint8_t zeros[8]; - DATA_BLOB tmp_sess_key; - - if (nt_pw == NULL) { + if (stored_nt == NULL) { DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n", username)); } @@ -249,17 +243,11 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, *user_sess_key = data_blob(NULL, 0); } - if (nt_interactive_password && nt_interactive_password->length && nt_pw) { - if (nt_interactive_password->length != 16) { - DEBUG(3,("ntlm_password_check: Interactive logon: Invalid NT password length (%d) supplied for user %s\n", (int)nt_interactive_password->length, - username)); - return NT_STATUS_WRONG_PASSWORD; - } - - if (memcmp(nt_interactive_password->data, nt_pw, 16) == 0) { + if (client_nt && stored_nt) { + if (memcmp(client_nt->hash, stored_nt->hash, sizeof(stored_nt->hash)) == 0) { if (user_sess_key) { *user_sess_key = data_blob_talloc(mem_ctx, NULL, 16); - SMBsesskeygen_ntv1(nt_pw, user_sess_key->data); + SMBsesskeygen_ntv1(stored_nt->hash, user_sess_key->data); } return NT_STATUS_OK; } else { @@ -268,20 +256,14 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, return NT_STATUS_WRONG_PASSWORD; } - } else if (lm_interactive_password && lm_interactive_password->length && lm_pw) { - if (lm_interactive_password->length != 16) { - DEBUG(3,("ntlm_password_check: Interactive logon: Invalid LANMAN password length (%d) supplied for user %s\n", (int)lm_interactive_password->length, - username)); - return NT_STATUS_WRONG_PASSWORD; - } - + } else if (client_lanman && stored_lanman) { if (!lp_lanman_auth()) { DEBUG(3,("ntlm_password_check: Interactive logon: only LANMAN password supplied for user %s, and LM passwords are disabled!\n", username)); return NT_STATUS_WRONG_PASSWORD; } - if (memcmp(lm_interactive_password->data, lm_pw, 16) == 0) { + if (memcmp(client_lanman->hash, stored_lanman->hash, sizeof(stored_lanman->hash)) == 0) { return NT_STATUS_OK; } else { DEBUG(3,("ntlm_password_check: Interactive logon: LANMAN password check failed for user %s\n", @@ -289,6 +271,52 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, return NT_STATUS_WRONG_PASSWORD; } } + return NT_STATUS_WRONG_PASSWORD; +} + +/** + * Check a challenge-response password against the value of the NT or + * LM password hash. + * + * @param mem_ctx talloc context + * @param challenge 8-byte challenge. If all zero, forces plaintext comparison + * @param nt_response 'unicode' NT response to the challenge, or unicode password + * @param lm_response ASCII or LANMAN response to the challenge, or password in DOS code page + * @param username internal Samba username, for log messages + * @param client_username username the client used + * @param client_domain domain name the client used (may be mapped) + * @param stored_lanman LANMAN ASCII password from our passdb or similar + * @param stored_nt MD4 unicode password from our passdb or similar + * @param user_sess_key User session key + * @param lm_sess_key LM session key (first 8 bytes of the LM hash) + */ + +NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, + const DATA_BLOB *challenge, + const DATA_BLOB *lm_response, + const DATA_BLOB *nt_response, + const char *username, + const char *client_username, + const char *client_domain, + const struct samr_Password *stored_lanman, + const struct samr_Password *stored_nt, + DATA_BLOB *user_sess_key, + DATA_BLOB *lm_sess_key) +{ + static const uint8_t zeros[8]; + DATA_BLOB tmp_sess_key; + + if (stored_nt == NULL) { + DEBUG(3,("ntlm_password_check: NO NT password stored for user %s.\n", + username)); + } + + if (lm_sess_key) { + *lm_sess_key = data_blob(NULL, 0); + } + if (user_sess_key) { + *user_sess_key = data_blob(NULL, 0); + } /* Check for cleartext netlogon. Used by Exchange 5.5. */ if (challenge->length == sizeof(zeros) && @@ -296,10 +324,10 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, DEBUG(4,("ntlm_password_check: checking plaintext passwords for user %s\n", username)); - if (nt_pw && nt_response->length) { + if (stored_nt && nt_response->length) { uint8_t pwhash[16]; mdfour(pwhash, nt_response->data, nt_response->length); - if (memcmp(pwhash, nt_pw, sizeof(pwhash)) == 0) { + if (memcmp(pwhash, stored_nt->hash, sizeof(pwhash)) == 0) { return NT_STATUS_OK; } else { DEBUG(3,("ntlm_password_check: NT (Unicode) plaintext password check failed for user %s\n", @@ -311,7 +339,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, DEBUG(3,("ntlm_password_check: (plaintext password check) LANMAN passwords NOT PERMITTED for user %s\n", username)); - } else if (lm_pw && lm_response->length) { + } else if (stored_lanman && lm_response->length) { uint8_t dospwd[14]; uint8_t p16[16]; ZERO_STRUCT(dospwd); @@ -322,7 +350,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, /* we *might* need to upper-case the string here */ E_P16((const uint8_t *)dospwd, p16); - if (memcmp(p16, lm_pw, sizeof(p16)) == 0) { + if (memcmp(p16, stored_lanman->hash, sizeof(p16)) == 0) { return NT_STATUS_OK; } else { DEBUG(3,("ntlm_password_check: LANMAN (ASCII) plaintext password check failed for user %s\n", @@ -340,14 +368,14 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, (unsigned long)nt_response->length, username)); } - if (nt_response->length > 24 && nt_pw) { + if (nt_response->length > 24 && stored_nt) { /* We have the NT MD4 hash challenge available - see if we can use it */ DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with domain [%s]\n", client_domain)); if (smb_pwd_check_ntlmv2(mem_ctx, nt_response, - nt_pw, challenge, + stored_nt->hash, challenge, client_username, client_domain, False, @@ -364,7 +392,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, DEBUG(4,("ntlm_password_check: Checking NTLMv2 password with uppercased version of domain [%s]\n", client_domain)); if (smb_pwd_check_ntlmv2(mem_ctx, nt_response, - nt_pw, challenge, + stored_nt->hash, challenge, client_username, client_domain, True, @@ -381,7 +409,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, DEBUG(4,("ntlm_password_check: Checking NTLMv2 password without a domain\n")); if (smb_pwd_check_ntlmv2(mem_ctx, nt_response, - nt_pw, challenge, + stored_nt->hash, challenge, client_username, "", False, @@ -396,7 +424,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, } else { DEBUG(3,("ntlm_password_check: NTLMv2 password check failed\n")); } - } else if (nt_response->length == 24 && nt_pw) { + } else if (nt_response->length == 24 && stored_nt) { 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). @@ -404,13 +432,13 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, DEBUG(4,("ntlm_password_check: Checking NT MD4 password\n")); if (smb_pwd_check_ntlmv1(mem_ctx, nt_response, - nt_pw, challenge, + stored_nt->hash, challenge, user_sess_key)) { /* The LM session key for this response is not very secure, so use it only if we otherwise allow LM authentication */ - if (lp_lanman_auth() && lm_pw) { - *lm_sess_key = data_blob_talloc(mem_ctx, lm_pw, 8); + if (lp_lanman_auth() && stored_lanman) { + *lm_sess_key = data_blob_talloc(mem_ctx, stored_lanman->hash, 8); } return NT_STATUS_OK; } else { @@ -440,31 +468,31 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, if (!lp_lanman_auth()) { DEBUG(3,("ntlm_password_check: Lanman passwords NOT PERMITTED for user %s\n", username)); - } else if (!lm_pw) { + } else if (!stored_lanman) { DEBUG(3,("ntlm_password_check: NO LanMan password set for user %s (and no NT password supplied)\n", username)); } else { DEBUG(4,("ntlm_password_check: Checking LM password\n")); if (smb_pwd_check_ntlmv1(mem_ctx, lm_response, - lm_pw, challenge, + stored_lanman->hash, challenge, NULL)) { /* The session key for this response is still very odd. It not very secure, so use it only if we otherwise allow LM authentication */ - if (lp_lanman_auth() && lm_pw) { + if (lp_lanman_auth() && stored_lanman) { uint8_t first_8_lm_hash[16]; - memcpy(first_8_lm_hash, lm_pw, 8); + memcpy(first_8_lm_hash, stored_lanman->hash, 8); memset(first_8_lm_hash + 8, '\0', 8); *user_sess_key = data_blob_talloc(mem_ctx, first_8_lm_hash, 16); - *lm_sess_key = data_blob_talloc(mem_ctx, lm_pw, 8); + *lm_sess_key = data_blob_talloc(mem_ctx, stored_lanman->hash, 8); } return NT_STATUS_OK; } } - if (!nt_pw) { + if (!stored_nt) { DEBUG(4,("ntlm_password_check: LM password check failed for user, no NT password %s\n",username)); return NT_STATUS_WRONG_PASSWORD; } @@ -475,7 +503,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, DEBUG(4,("ntlm_password_check: Checking LMv2 password with domain %s\n", client_domain)); if (smb_pwd_check_ntlmv2(mem_ctx, lm_response, - nt_pw, challenge, + stored_nt->hash, challenge, client_username, client_domain, False, @@ -487,7 +515,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, * torture test */ smb_sess_key_ntlmv2(mem_ctx, nt_response, - nt_pw, challenge, + stored_nt->hash, challenge, client_username, client_domain, False, @@ -508,7 +536,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, DEBUG(4,("ntlm_password_check: Checking LMv2 password with upper-cased version of domain %s\n", client_domain)); if (smb_pwd_check_ntlmv2(mem_ctx, lm_response, - nt_pw, challenge, + stored_nt->hash, challenge, client_username, client_domain, True, @@ -520,7 +548,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, * torture test */ smb_sess_key_ntlmv2(mem_ctx, nt_response, - nt_pw, challenge, + stored_nt->hash, challenge, client_username, client_domain, True, @@ -541,7 +569,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, DEBUG(4,("ntlm_password_check: Checking LMv2 password without a domain\n")); if (smb_pwd_check_ntlmv2(mem_ctx, lm_response, - nt_pw, challenge, + stored_nt->hash, challenge, client_username, "", False, @@ -553,7 +581,7 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, * torture test */ smb_sess_key_ntlmv2(mem_ctx, nt_response, - nt_pw, challenge, + stored_nt->hash, challenge, client_username, "", False, @@ -578,18 +606,18 @@ NTSTATUS ntlm_password_check(TALLOC_CTX *mem_ctx, if (lp_ntlm_auth()) { if (smb_pwd_check_ntlmv1(mem_ctx, lm_response, - nt_pw, challenge, + stored_nt->hash, challenge, NULL)) { /* The session key for this response is still very odd. It not very secure, so use it only if we otherwise allow LM authentication */ - if (lp_lanman_auth() && lm_pw) { + if (lp_lanman_auth() && stored_lanman) { uint8_t first_8_lm_hash[16]; - memcpy(first_8_lm_hash, lm_pw, 8); + memcpy(first_8_lm_hash, stored_lanman->hash, 8); memset(first_8_lm_hash + 8, '\0', 8); *user_sess_key = data_blob_talloc(mem_ctx, first_8_lm_hash, 16); - *lm_sess_key = data_blob_talloc(mem_ctx, lm_pw, 8); + *lm_sess_key = data_blob_talloc(mem_ctx, stored_lanman->hash, 8); } return NT_STATUS_OK; } diff --git a/source4/auth/ntlmssp/ntlmssp_server.c b/source4/auth/ntlmssp/ntlmssp_server.c index 5885db8decc..90f567be2be 100644 --- a/source4/auth/ntlmssp/ntlmssp_server.c +++ b/source4/auth/ntlmssp/ntlmssp_server.c @@ -686,18 +686,23 @@ static NTSTATUS auth_ntlmssp_set_challenge(struct gensec_ntlmssp_state *gensec_n static NTSTATUS auth_ntlmssp_check_password(struct gensec_ntlmssp_state *gensec_ntlmssp_state, DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) { - struct auth_usersupplied_info *user_info = NULL; NTSTATUS nt_status; + struct auth_usersupplied_info *user_info = talloc(gensec_ntlmssp_state, struct auth_usersupplied_info); + if (!user_info) { + return NT_STATUS_NO_MEMORY; + } - nt_status = make_user_info_map(gensec_ntlmssp_state, - gensec_ntlmssp_state->user, - gensec_ntlmssp_state->domain, - gensec_ntlmssp_state->workstation, - gensec_ntlmssp_state->lm_resp.data ? &gensec_ntlmssp_state->lm_resp : NULL, - gensec_ntlmssp_state->nt_resp.data ? &gensec_ntlmssp_state->nt_resp : NULL, - NULL, NULL, NULL, True, - &user_info); - NT_STATUS_NOT_OK_RETURN(nt_status); + user_info->flags = 0; + user_info->mapped_state = False; + user_info->client.account_name = gensec_ntlmssp_state->user; + user_info->client.domain_name = gensec_ntlmssp_state->domain; + user_info->workstation_name = gensec_ntlmssp_state->workstation; + + user_info->password_state = AUTH_PASSWORD_RESPONSE; + user_info->password.response.lanman = gensec_ntlmssp_state->lm_resp; + user_info->password.response.lanman.data = talloc_steal(user_info, gensec_ntlmssp_state->lm_resp.data); + user_info->password.response.nt = gensec_ntlmssp_state->nt_resp; + user_info->password.response.nt.data = talloc_steal(user_info, gensec_ntlmssp_state->nt_resp.data); nt_status = auth_check_password(gensec_ntlmssp_state->auth_context, gensec_ntlmssp_state, user_info, &gensec_ntlmssp_state->server_info); diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c index 71132119ac4..78973776f1a 100644 --- a/source4/rpc_server/lsa/dcesrv_lsa.c +++ b/source4/rpc_server/lsa/dcesrv_lsa.c @@ -619,7 +619,7 @@ static NTSTATUS lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALL samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "securityIdentifier", sid_string); } - /* pull in all the template attributes. Note this is always from the global samdb */ + /* pull in all the template attributes. */ ret = samdb_copy_template(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "(&(name=TemplateTrustedDomain)(objectclass=trustedDomainTemplate))"); if (ret != 0) { diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index ca7b938ea67..31db7c81f38 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -436,13 +436,21 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_ struct auth_usersupplied_info *user_info; struct auth_serversupplied_info *server_info; NTSTATUS nt_status; - const uint8_t *chal; static const char zeros[16]; struct netr_SamBaseInfo *sam; struct netr_SamInfo2 *sam2; struct netr_SamInfo3 *sam3; struct netr_SamInfo6 *sam6; + user_info = talloc(mem_ctx, struct auth_usersupplied_info); + if (!user_info) { + return NT_STATUS_NO_MEMORY; + } + + user_info->flags = 0; + user_info->mapped_state = False; + user_info->remote_host = NULL; + switch (r->in.logon_level) { case 1: case 3: @@ -464,21 +472,26 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_ dce_call->event_ctx); NT_STATUS_NOT_OK_RETURN(nt_status); - nt_status = auth_get_challenge(auth_context, &chal); - NT_STATUS_NOT_OK_RETURN(nt_status); + user_info->client.account_name = r->in.logon.network->identity_info.account_name.string; + user_info->client.domain_name = r->in.logon.network->identity_info.domain_name.string; + user_info->workstation_name = r->in.logon.network->identity_info.workstation.string; + + user_info->password_state = AUTH_PASSWORD_HASH; + user_info->password.hash.lanman = talloc(user_info, struct samr_Password); + if (!user_info->password.hash.lanman) { + return NT_STATUS_NO_MEMORY; + } + *user_info->password.hash.lanman = r->in.logon.password->lmpassword; - nt_status = make_user_info_netlogon_interactive(mem_ctx, - r->in.logon.password->identity_info.account_name.string, - r->in.logon.password->identity_info.domain_name.string, - r->in.logon.password->identity_info.workstation.string, - chal, - &r->in.logon.password->lmpassword, - &r->in.logon.password->ntpassword, - &user_info); - NT_STATUS_NOT_OK_RETURN(nt_status); + user_info->password.hash.nt = talloc(user_info, struct samr_Password); + if (!user_info->password.hash.nt) { + return NT_STATUS_NO_MEMORY; + } + *user_info->password.hash.nt = r->in.logon.password->ntpassword; break; case 2: case 6: + /* TODO: we need to deny anonymous access here */ nt_status = auth_context_create(mem_ctx, lp_auth_methods(), &auth_context, dce_call->event_ctx); @@ -487,14 +500,14 @@ static NTSTATUS netr_LogonSamLogonEx(struct dcesrv_call_state *dce_call, TALLOC_ nt_status = auth_context_set_challenge(auth_context, r->in.logon.network->challenge, "netr_LogonSamLogonWithFlags"); NT_STATUS_NOT_OK_RETURN(nt_status); - nt_status = make_user_info_netlogon_network(auth_context, - r->in.logon.network->identity_info.account_name.string, - r->in.logon.network->identity_info.domain_name.string, - r->in.logon.network->identity_info.workstation.string, - r->in.logon.network->lm.data, r->in.logon.network->lm.length, - r->in.logon.network->nt.data, r->in.logon.network->nt.length, - &user_info); - NT_STATUS_NOT_OK_RETURN(nt_status); + user_info->client.account_name = r->in.logon.network->identity_info.account_name.string; + user_info->client.domain_name = r->in.logon.network->identity_info.domain_name.string; + user_info->workstation_name = r->in.logon.network->identity_info.workstation.string; + + user_info->password_state = AUTH_PASSWORD_RESPONSE; + user_info->password.response.lanman = data_blob(r->in.logon.network->lm.data, r->in.logon.network->lm.length); + user_info->password.response.nt = data_blob(r->in.logon.network->nt.data, r->in.logon.network->nt.length); + break; default: return NT_STATUS_INVALID_PARAMETER; diff --git a/source4/scripting/ejs/smbcalls_auth.c b/source4/scripting/ejs/smbcalls_auth.c index 87d5327e04f..4b3534b4cc3 100644 --- a/source4/scripting/ejs/smbcalls_auth.c +++ b/source4/scripting/ejs/smbcalls_auth.c @@ -47,16 +47,31 @@ static int ejs_doauth(TALLOC_CTX *tmp_ctx, struct MprVar *auth, const char *user goto done; } - pw_blob = data_blob(password, strlen(password)+1), - make_user_info(tmp_ctx, username, username, - domain, domain, - remote_host, remote_host, - NULL, NULL, - NULL, NULL, - &pw_blob, False, - USER_INFO_CASE_INSENSITIVE_USERNAME | - USER_INFO_DONT_CHECK_UNIX_ACCOUNT, - &user_info); + pw_blob = data_blob(password, strlen(password)+1); + + user_info = talloc(tmp_ctx, struct auth_usersupplied_info); + if (!user_info) { + mprSetPropertyValue(auth, "result", mprCreateBoolVar(False)); + mprSetPropertyValue(auth, "report", mprString("talloc failed")); + goto done; + } + + user_info->mapped_state = True; + user_info->client.account_name = username; + user_info->mapped.account_name = username; + user_info->client.domain_name = domain; + user_info->mapped.domain_name = domain; + + user_info->workstation_name = remote_host; + + user_info->remote_host = remote_host; + + user_info->password_state = AUTH_PASSWORD_PLAIN; + user_info->password.plaintext = talloc_strdup(user_info, password); + + user_info->flags = USER_INFO_CASE_INSENSITIVE_USERNAME | + USER_INFO_DONT_CHECK_UNIX_ACCOUNT; + nt_status = auth_check_password(auth_context, tmp_ctx, user_info, &server_info); if (!NT_STATUS_IS_OK(nt_status)) { mprSetPropertyValue(auth, "result", mprCreateBoolVar(False)); diff --git a/source4/smb_server/sesssetup.c b/source4/smb_server/sesssetup.c index d209d96aad2..f8c16d8c69d 100644 --- a/source4/smb_server/sesssetup.c +++ b/source4/smb_server/sesssetup.c @@ -50,7 +50,7 @@ static NTSTATUS sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *s struct auth_serversupplied_info *server_info = NULL; struct auth_session_info *session_info; struct smbsrv_session *smb_sess; - char *remote_machine; + const char *remote_machine = NULL; TALLOC_CTX *mem_ctx; sess->old.out.vuid = UID_FIELD_INVALID; @@ -63,17 +63,31 @@ static NTSTATUS sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *s req->smb_conn->negotiate.max_send = sess->old.in.bufsize; } - remote_machine = socket_get_peer_addr(req->smb_conn->connection->socket, mem_ctx); - status = make_user_info_for_reply_enc(req->smb_conn, - sess->old.in.user, sess->old.in.domain, - remote_machine, - sess->old.in.password, - data_blob(NULL, 0), - &user_info); - if (!NT_STATUS_IS_OK(status)) { + if (req->smb_conn->negotiate.called_name) { + remote_machine = req->smb_conn->negotiate.called_name->name; + } + + if (!remote_machine) { + remote_machine = socket_get_peer_addr(req->smb_conn->connection->socket, mem_ctx); + } + + user_info = talloc(req->smb_conn, struct auth_usersupplied_info); + if (!user_info) { talloc_free(mem_ctx); - return NT_STATUS_ACCESS_DENIED; + return NT_STATUS_NO_MEMORY; } + + user_info->mapped_state = False; + user_info->flags = 0; + user_info->client.account_name = sess->old.in.user; + user_info->client.domain_name = sess->old.in.domain; + user_info->workstation_name = remote_machine; + user_info->remote_host = socket_get_peer_addr(req->smb_conn->connection->socket, mem_ctx); + + user_info->password_state = AUTH_PASSWORD_RESPONSE; + user_info->password.response.lanman = sess->old.in.password; + user_info->password.response.lanman.data = talloc_steal(user_info, sess->old.in.password.data); + user_info->password.response.nt = data_blob(NULL, 0); status = auth_check_password(req->smb_conn->negotiate.auth_context, mem_ctx, user_info, &server_info); @@ -118,6 +132,8 @@ static NTSTATUS sesssetup_old(struct smbsrv_request *req, union smb_sesssetup *s static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *sess) { NTSTATUS status; + const char *remote_machine = NULL; + struct smbsrv_session *smb_sess; struct auth_usersupplied_info *user_info = NULL; struct auth_serversupplied_info *server_info = NULL; @@ -136,55 +152,44 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s } if (req->smb_conn->negotiate.spnego_negotiated) { - struct auth_context *auth_context; - if (sess->nt1.in.user && *sess->nt1.in.user) { - return NT_STATUS_LOGON_FAILURE; - } - - status = make_user_info_anonymous(mem_ctx, &user_info); - if (!NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); - return status; - } - - /* TODO: should we use just "anonymous" here? */ - status = auth_context_create(mem_ctx, lp_auth_methods(), - &auth_context, - req->smb_conn->connection->event.ctx); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(mem_ctx); - return status; - } - - status = auth_check_password(auth_context, mem_ctx, - user_info, &server_info); - } else { - const char *remote_machine = NULL; - - if (req->smb_conn->negotiate.called_name) { - remote_machine = req->smb_conn->negotiate.called_name->name; - } - - if (!remote_machine) { - remote_machine = socket_get_peer_addr(req->smb_conn->connection->socket, mem_ctx); - } - - status = make_user_info_for_reply_enc(req->smb_conn, - sess->nt1.in.user, sess->nt1.in.domain, - remote_machine, - sess->nt1.in.password1, - sess->nt1.in.password2, - &user_info); - if (!NT_STATUS_IS_OK(status)) { - talloc_free(mem_ctx); - return NT_STATUS_ACCESS_DENIED; + /* We can't accept a normal login, because we + * don't have a challenge */ + return NT_STATUS_LOGON_FAILURE; } - - status = auth_check_password(req->smb_conn->negotiate.auth_context, - req, user_info, &server_info); } + if (req->smb_conn->negotiate.called_name) { + remote_machine = req->smb_conn->negotiate.called_name->name; + } + + if (!remote_machine) { + remote_machine = socket_get_peer_addr(req->smb_conn->connection->socket, mem_ctx); + } + + user_info = talloc(req->smb_conn, struct auth_usersupplied_info); + if (!user_info) { + talloc_free(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + + user_info->mapped_state = False; + user_info->flags = 0; + user_info->client.account_name = sess->nt1.in.user; + user_info->client.domain_name = sess->nt1.in.domain; + user_info->workstation_name = remote_machine; + user_info->remote_host = socket_get_peer_addr(req->smb_conn->connection->socket, mem_ctx); + + user_info->password_state = AUTH_PASSWORD_RESPONSE; + user_info->password.response.lanman = sess->nt1.in.password1; + user_info->password.response.lanman.data = talloc_steal(user_info, sess->nt1.in.password1.data); + user_info->password.response.nt = sess->nt1.in.password2; + user_info->password.response.nt.data = talloc_steal(user_info, sess->nt1.in.password2.data); + + status = auth_check_password(req->smb_conn->negotiate.auth_context, + req, user_info, &server_info); + if (!NT_STATUS_IS_OK(status)) { talloc_free(mem_ctx); return auth_nt_status_squash(status); |