LCOV - code coverage report
Current view: top level - source4/auth/ntlm - auth_sam.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 433 522 83.0 %
Date: 2024-05-31 13:13:24 Functions: 13 13 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Password and authentication handling
       4             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2009
       5             :    Copyright (C) Gerald Carter                             2003
       6             :    Copyright (C) Stefan Metzmacher                         2005-2010
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "system/time.h"
      24             : #include <ldb.h>
      25             : #include "libcli/ldap/ldap_ndr.h"
      26             : #include "libcli/security/security.h"
      27             : #include "auth/auth.h"
      28             : #include "../libcli/auth/ntlm_check.h"
      29             : #include "auth/ntlm/auth_proto.h"
      30             : #include "auth/auth_sam.h"
      31             : #include "dsdb/gmsa/util.h"
      32             : #include "dsdb/samdb/samdb.h"
      33             : #include "dsdb/samdb/ldb_modules/util.h"
      34             : #include "dsdb/common/util.h"
      35             : #include "param/param.h"
      36             : #include "librpc/gen_ndr/ndr_irpc_c.h"
      37             : #include "librpc/gen_ndr/ndr_winbind_c.h"
      38             : #include "lib/crypto/gkdi.h"
      39             : #include "lib/messaging/irpc.h"
      40             : #include "libcli/auth/libcli_auth.h"
      41             : #include "libds/common/roles.h"
      42             : #include "lib/util/tevent_ntstatus.h"
      43             : #include "system/kerberos.h"
      44             : #include "auth/kerberos/kerberos.h"
      45             : #include "kdc/authn_policy_util.h"
      46             : #include "kdc/db-glue.h"
      47             : 
      48             : #undef DBGC_CLASS
      49             : #define DBGC_CLASS DBGC_AUTH
      50             : 
      51             : NTSTATUS auth_sam_init(void);
      52             : 
      53             : extern const char *user_attrs[];
      54             : extern const char *domain_ref_attrs[];
      55             : 
      56             : /****************************************************************************
      57             :  Do a specific test for an smb password being correct, given a smb_password and
      58             :  the lanman and NT responses.
      59             : ****************************************************************************/
      60       28309 : static NTSTATUS authsam_password_ok(struct auth4_context *auth_context,
      61             :                                     TALLOC_CTX *mem_ctx,
      62             :                                     const struct samr_Password *nt_pwd,
      63             :                                     struct smb_krb5_context *smb_krb5_context,
      64             :                                     const DATA_BLOB *stored_aes_256_key,
      65             :                                     const krb5_data *salt,
      66             :                                     const struct auth_usersupplied_info *user_info,
      67             :                                     DATA_BLOB *user_sess_key,
      68             :                                     DATA_BLOB *lm_sess_key)
      69             : {
      70        1411 :         NTSTATUS status;
      71             : 
      72       28309 :         switch (user_info->password_state) {
      73         510 :         case AUTH_PASSWORD_PLAIN:
      74             :         {
      75           0 :                 const struct auth_usersupplied_info *user_info_temp;
      76             : 
      77         510 :                 if (nt_pwd == NULL && stored_aes_256_key != NULL && user_info->password.plaintext != NULL) {
      78           0 :                         bool pw_equal;
      79           0 :                         int krb5_ret;
      80           0 :                         DATA_BLOB supplied_aes_256_key;
      81           0 :                         krb5_keyblock key;
      82          64 :                         krb5_data cleartext_data = {
      83          64 :                                 .data = user_info->password.plaintext,
      84          64 :                                 .length = strlen(user_info->password.plaintext)
      85             :                         };
      86             : 
      87          64 :                         *lm_sess_key = data_blob_null;
      88          64 :                         *user_sess_key = data_blob_null;
      89             : 
      90          64 :                         krb5_ret = smb_krb5_create_key_from_string(smb_krb5_context->krb5_context,
      91             :                                                                    NULL,
      92             :                                                                    salt,
      93             :                                                                    &cleartext_data,
      94             :                                                                    ENCTYPE_AES256_CTS_HMAC_SHA1_96,
      95             :                                                                    &key);
      96          64 :                         if (krb5_ret) {
      97           0 :                                 DBG_ERR("generation of a aes256-cts-hmac-sha1-96 key for password comparison failed: %s\n",
      98             :                                         smb_get_krb5_error_message(smb_krb5_context->krb5_context,
      99             :                                                                    krb5_ret, mem_ctx));
     100           0 :                                 return NT_STATUS_INTERNAL_ERROR;
     101             :                         }
     102             : 
     103          64 :                         supplied_aes_256_key = data_blob_const(KRB5_KEY_DATA(&key),
     104          32 :                                                                KRB5_KEY_LENGTH(&key));
     105             : 
     106          64 :                         pw_equal = data_blob_equal_const_time(&supplied_aes_256_key,
     107             :                                                               stored_aes_256_key);
     108             : 
     109          64 :                         krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &key);
     110          64 :                         if (!pw_equal) {
     111          34 :                                 return NT_STATUS_WRONG_PASSWORD;
     112             :                         }
     113          30 :                         return NT_STATUS_OK;
     114             :                 }
     115             : 
     116         446 :                 status = encrypt_user_info(mem_ctx, auth_context,
     117             :                                            AUTH_PASSWORD_HASH,
     118             :                                            user_info, &user_info_temp);
     119         446 :                 if (!NT_STATUS_IS_OK(status)) {
     120           0 :                         DEBUG(1, ("Failed to convert plaintext password to password HASH: %s\n", nt_errstr(status)));
     121           0 :                         return status;
     122             :                 }
     123         446 :                 user_info = user_info_temp;
     124             : 
     125           0 :                 FALL_THROUGH;
     126             :         }
     127             :         case AUTH_PASSWORD_HASH:
     128        1038 :                 *lm_sess_key = data_blob(NULL, 0);
     129        1038 :                 *user_sess_key = data_blob(NULL, 0);
     130        1038 :                 status = hash_password_check(mem_ctx,
     131             :                                              false,
     132        1038 :                                              lpcfg_ntlm_auth(auth_context->lp_ctx),
     133             :                                              NULL,
     134        1038 :                                              user_info->password.hash.nt,
     135        1038 :                                              user_info->mapped.account_name,
     136             :                                              NULL, nt_pwd);
     137        1038 :                 NT_STATUS_NOT_OK_RETURN(status);
     138         698 :                 break;
     139             : 
     140       27207 :         case AUTH_PASSWORD_RESPONSE:
     141       27207 :                 status = ntlm_password_check(mem_ctx,
     142             :                                              false,
     143       27207 :                                              lpcfg_ntlm_auth(auth_context->lp_ctx),
     144       27207 :                                              user_info->logon_parameters,
     145       27207 :                                              &auth_context->challenge.data,
     146             :                                              &user_info->password.response.lanman,
     147             :                                              &user_info->password.response.nt,
     148       27207 :                                              user_info->mapped.account_name,
     149       27207 :                                              user_info->client.account_name,
     150       27207 :                                              user_info->client.domain_name,
     151             :                                              NULL, nt_pwd,
     152             :                                              user_sess_key, lm_sess_key);
     153       27207 :                 NT_STATUS_NOT_OK_RETURN(status);
     154       21982 :                 break;
     155             :         }
     156             : 
     157       24090 :         return NT_STATUS_OK;
     158             : }
     159             : 
     160           9 : static void auth_sam_trigger_zero_password(TALLOC_CTX *mem_ctx,
     161             :                                            struct imessaging_context *msg_ctx,
     162             :                                            struct tevent_context *event_ctx,
     163             :                                            struct netr_SendToSamBase *send_to_sam)
     164             : {
     165           0 :         struct dcerpc_binding_handle *irpc_handle;
     166           0 :         struct winbind_SendToSam r;
     167           0 :         struct tevent_req *req;
     168           0 :         TALLOC_CTX *tmp_ctx;
     169             : 
     170           9 :         tmp_ctx = talloc_new(mem_ctx);
     171           9 :         if (tmp_ctx == NULL) {
     172           0 :                 return;
     173             :         }
     174             : 
     175           9 :         irpc_handle = irpc_binding_handle_by_name(tmp_ctx, msg_ctx,
     176             :                                                   "winbind_server",
     177             :                                                   &ndr_table_winbind);
     178           9 :         if (irpc_handle == NULL) {
     179           0 :                 DEBUG(1,(__location__ ": Unable to get binding handle for winbind\n"));
     180           0 :                 TALLOC_FREE(tmp_ctx);
     181           0 :                 return;
     182             :         }
     183             : 
     184           9 :         r.in.message = *send_to_sam;
     185             : 
     186             :         /*
     187             :          * This seem to rely on the current IRPC implementation,
     188             :          * which delivers the message in the _send function.
     189             :          *
     190             :          * TODO: we need a ONE_WAY IRPC handle and register
     191             :          * a callback and wait for it to be triggered!
     192             :          */
     193           9 :         req = dcerpc_winbind_SendToSam_r_send(tmp_ctx,
     194             :                                               event_ctx,
     195             :                                               irpc_handle,
     196             :                                               &r);
     197             : 
     198             :         /* we aren't interested in a reply */
     199           9 :         talloc_free(req);
     200           9 :         TALLOC_FREE(tmp_ctx);
     201             : 
     202             : }
     203             : 
     204             : /*
     205             :   send a message to the drepl server telling it to initiate a
     206             :   REPL_SECRET getncchanges extended op to fetch the users secrets
     207             :  */
     208         125 : static void auth_sam_trigger_repl_secret(TALLOC_CTX *mem_ctx,
     209             :                                          struct imessaging_context *msg_ctx,
     210             :                                          struct tevent_context *event_ctx,
     211             :                                          struct ldb_dn *user_dn)
     212             : {
     213           0 :         struct dcerpc_binding_handle *irpc_handle;
     214           0 :         struct drepl_trigger_repl_secret r;
     215           0 :         struct tevent_req *req;
     216           0 :         TALLOC_CTX *tmp_ctx;
     217             : 
     218         125 :         tmp_ctx = talloc_new(mem_ctx);
     219         125 :         if (tmp_ctx == NULL) {
     220           0 :                 return;
     221             :         }
     222             : 
     223         125 :         irpc_handle = irpc_binding_handle_by_name(tmp_ctx, msg_ctx,
     224             :                                                   "dreplsrv",
     225             :                                                   &ndr_table_irpc);
     226         125 :         if (irpc_handle == NULL) {
     227           0 :                 DEBUG(1,(__location__ ": Unable to get binding handle for dreplsrv\n"));
     228           0 :                 TALLOC_FREE(tmp_ctx);
     229           0 :                 return;
     230             :         }
     231             : 
     232         125 :         r.in.user_dn = ldb_dn_get_linearized(user_dn);
     233             : 
     234             :         /*
     235             :          * This seem to rely on the current IRPC implementation,
     236             :          * which delivers the message in the _send function.
     237             :          *
     238             :          * TODO: we need a ONE_WAY IRPC handle and register
     239             :          * a callback and wait for it to be triggered!
     240             :          */
     241         125 :         req = dcerpc_drepl_trigger_repl_secret_r_send(tmp_ctx,
     242             :                                                       event_ctx,
     243             :                                                       irpc_handle,
     244             :                                                       &r);
     245             : 
     246             :         /* we aren't interested in a reply */
     247         125 :         talloc_free(req);
     248         125 :         TALLOC_FREE(tmp_ctx);
     249             : }
     250             : 
     251        3766 : static const struct samr_Password *hide_invalid_nthash(const struct samr_Password *in)
     252             : {
     253             :         /*
     254             :          * This is the result of:
     255             :          *
     256             :          * E_md4hash("", zero_string_hash.hash);
     257             :          */
     258           1 :         static const struct samr_Password zero_string_hash = {
     259             :                 .hash = {
     260             :                         0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
     261             :                         0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0,
     262             :                 }
     263             :         };
     264             : 
     265        3766 :         if (in == NULL) {
     266        2470 :                 return NULL;
     267             :         }
     268             : 
     269             :         /*
     270             :          * Skip over any all-zero hashes in the history.  No known software
     271             :          * stores these but just to be sure
     272             :          */
     273        1295 :         if (all_zero(in->hash, sizeof(in->hash))) {
     274           0 :                 return NULL;
     275             :         }
     276             : 
     277             :         /*
     278             :          * This looks odd, but the password_hash module in the past has written
     279             :          * this in the rare situation where (somehow) we didn't have an old NT
     280             :          * hash (one of the old LM-only set paths)
     281             :          *
     282             :          * mem_equal_const_time() is used to avoid a timing attack
     283             :          * when comparing secret data in the server with this constant
     284             :          * value.
     285             :          */
     286        1295 :         if (mem_equal_const_time(in->hash, zero_string_hash.hash, 16)) {
     287           0 :                 in = NULL;
     288             :         }
     289             : 
     290        1295 :         return in;
     291             : }
     292             : 
     293             : /*
     294             :  * Check that a password is OK, and update badPwdCount if required.
     295             :  */
     296             : 
     297       27168 : static NTSTATUS authsam_password_check_and_record(struct auth4_context *auth_context,
     298             :                                                   TALLOC_CTX *mem_ctx,
     299             :                                                   struct ldb_dn *domain_dn,
     300             :                                                   struct ldb_message *msg,
     301             :                                                   const struct auth_usersupplied_info *user_info,
     302             :                                                   DATA_BLOB *user_sess_key,
     303             :                                                   DATA_BLOB *lm_sess_key,
     304             :                                                   bool *authoritative)
     305             : {
     306        1411 :         NTSTATUS nt_status;
     307        1411 :         NTSTATUS auth_status;
     308        1411 :         TALLOC_CTX *tmp_ctx;
     309        1411 :         int i, ret;
     310       27168 :         int history_len = 0;
     311       27168 :         struct ldb_context *sam_ctx = auth_context->sam_ctx;
     312       27168 :         const char * const attrs[] = { "pwdHistoryLength", NULL };
     313        1411 :         struct ldb_message *dom_msg;
     314        1411 :         struct samr_Password *nt_pwd;
     315       27168 :         DATA_BLOB _aes_256_key = data_blob_null;
     316       27168 :         DATA_BLOB *aes_256_key = NULL;
     317       27168 :         krb5_data _salt = { .data = NULL, .length = 0 };
     318       27168 :         krb5_data *salt = NULL;
     319       27168 :         DATA_BLOB salt_data = data_blob_null;
     320       27168 :         struct smb_krb5_context *smb_krb5_context = NULL;
     321        1411 :         const struct ldb_val *sc_val;
     322       27168 :         uint32_t userAccountControl = 0;
     323       27168 :         uint32_t current_kvno = 0;
     324        1411 :         bool am_rodc;
     325             : 
     326       27168 :         tmp_ctx = talloc_new(mem_ctx);
     327       27168 :         if (tmp_ctx == NULL) {
     328           0 :                 return NT_STATUS_NO_MEMORY;
     329             :         }
     330             : 
     331             :         /*
     332             :          * This call does more than what it appears to do, it also
     333             :          * checks for the account lockout.
     334             :          *
     335             :          * It is done here so that all parts of Samba that read the
     336             :          * password refuse to even operate on it if the account is
     337             :          * locked out, to avoid mistakes like CVE-2013-4496.
     338             :          */
     339       27168 :         nt_status = samdb_result_passwords(tmp_ctx, auth_context->lp_ctx,
     340             :                                            msg, &nt_pwd);
     341       27168 :         if (!NT_STATUS_IS_OK(nt_status)) {
     342          51 :                 TALLOC_FREE(tmp_ctx);
     343          51 :                 return nt_status;
     344             :         }
     345             : 
     346       27117 :         userAccountControl = ldb_msg_find_attr_as_uint(msg,
     347             :                                                        "userAccountControl",
     348             :                                                        0);
     349             : 
     350       27117 :         sc_val = ldb_msg_find_ldb_val(msg, "supplementalCredentials");
     351             : 
     352       27117 :         if (nt_pwd == NULL && sc_val == NULL) {
     353         127 :                 if (samdb_rodc(auth_context->sam_ctx, &am_rodc) == LDB_SUCCESS && am_rodc) {
     354             :                         /*
     355             :                          * we don't have passwords for this
     356             :                          * account. We are an RODC, and this account
     357             :                          * may be one for which we either are denied
     358             :                          * REPL_SECRET replication or we haven't yet
     359             :                          * done the replication. We return
     360             :                          * NT_STATUS_NOT_IMPLEMENTED which tells the
     361             :                          * auth code to try the next authentication
     362             :                          * mechanism. We also send a message to our
     363             :                          * drepl server to tell it to try and
     364             :                          * replicate the secrets for this account.
     365             :                          *
     366             :                          * TODO: Should we only trigger this is detected
     367             :                          * there's a chance that the password might be
     368             :                          * replicated, we should be able to detect this
     369             :                          * based on msDS-NeverRevealGroup.
     370             :                          */
     371         125 :                         auth_sam_trigger_repl_secret(auth_context,
     372             :                                                      auth_context->msg_ctx,
     373             :                                                      auth_context->event_ctx,
     374             :                                                      msg->dn);
     375         125 :                         TALLOC_FREE(tmp_ctx);
     376         125 :                         return NT_STATUS_NOT_IMPLEMENTED;
     377             :                 }
     378             :         }
     379             : 
     380             :         /*
     381             :          * If we don't have an NT password, pull a kerberos key
     382             :          * instead for plaintext.
     383             :          */
     384       26992 :         if (nt_pwd == NULL &&
     385          50 :             sc_val != NULL &&
     386          50 :             user_info->password_state == AUTH_PASSWORD_PLAIN)
     387             :         {
     388           0 :                 krb5_error_code krb5_ret;
     389             : 
     390          42 :                 krb5_ret = smb_krb5_init_context(tmp_ctx,
     391             :                                                  auth_context->lp_ctx,
     392             :                                                  &smb_krb5_context);
     393          42 :                 if (krb5_ret != 0) {
     394           0 :                         DBG_ERR("Failed to setup krb5_context: %s!\n",
     395             :                                 error_message(krb5_ret));
     396           0 :                         return NT_STATUS_INTERNAL_ERROR;
     397             :                 }
     398             : 
     399             :                 /*
     400             :                  * Get the current salt from the record
     401             :                  */
     402             : 
     403          42 :                 krb5_ret = dsdb_extract_aes_256_key(smb_krb5_context->krb5_context,
     404             :                                                     tmp_ctx,
     405             :                                                     sam_ctx,
     406             :                                                     msg,
     407             :                                                     userAccountControl,
     408             :                                                     NULL, /* kvno */
     409             :                                                     &current_kvno, /* kvno_out */
     410             :                                                     &_aes_256_key,
     411             :                                                     &salt_data);
     412          42 :                 if (krb5_ret == 0) {
     413          42 :                         aes_256_key = &_aes_256_key;
     414             : 
     415          42 :                         _salt.data = (char *)salt_data.data;
     416          42 :                         _salt.length = salt_data.length;
     417          42 :                         salt = &_salt;
     418             :                 }
     419             :         }
     420             : 
     421       26992 :         auth_status = authsam_password_ok(auth_context,
     422             :                                           tmp_ctx,
     423             :                                           nt_pwd,
     424             :                                           smb_krb5_context,
     425             :                                           aes_256_key,
     426             :                                           salt,
     427             :                                           user_info,
     428             :                                           user_sess_key, lm_sess_key);
     429             : 
     430       26992 :         if (NT_STATUS_IS_OK(auth_status)) {
     431       23686 :                 if (user_sess_key->data) {
     432       22269 :                         talloc_steal(mem_ctx, user_sess_key->data);
     433             :                 }
     434       23686 :                 if (lm_sess_key->data) {
     435       20642 :                         talloc_steal(mem_ctx, lm_sess_key->data);
     436             :                 }
     437       23686 :                 TALLOC_FREE(tmp_ctx);
     438       23686 :                 return NT_STATUS_OK;
     439             :         }
     440        3306 :         *user_sess_key = data_blob_null;
     441        3306 :         *lm_sess_key = data_blob_null;
     442             : 
     443        3306 :         if (!NT_STATUS_EQUAL(auth_status, NT_STATUS_WRONG_PASSWORD)) {
     444         224 :                 TALLOC_FREE(tmp_ctx);
     445         224 :                 return auth_status;
     446             :         }
     447             : 
     448             :         /*
     449             :          * We only continue if this was a wrong password
     450             :          * and we'll always return NT_STATUS_WRONG_PASSWORD
     451             :          * no matter what error happens.
     452             :          */
     453             : 
     454             :         /* pull the domain password property attributes */
     455        3082 :         ret = dsdb_search_one(sam_ctx, tmp_ctx, &dom_msg, domain_dn, LDB_SCOPE_BASE,
     456             :                               attrs, 0, "objectClass=domain");
     457        3082 :         if (ret == LDB_SUCCESS) {
     458        3082 :                 history_len = ldb_msg_find_attr_as_uint(dom_msg, "pwdHistoryLength", 0);
     459           0 :         } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     460           0 :                 DEBUG(3,("Couldn't find domain %s: %s!\n",
     461             :                          ldb_dn_get_linearized(domain_dn),
     462             :                          ldb_errstring(sam_ctx)));
     463             :         } else {
     464           0 :                 DEBUG(3,("error finding domain %s: %s!\n",
     465             :                          ldb_dn_get_linearized(domain_dn),
     466             :                          ldb_errstring(sam_ctx)));
     467             :         }
     468             : 
     469        3965 :         for (i = 1; i < MIN(history_len, 3); i++) {
     470        3766 :                 const struct samr_Password *nt_history_pwd = NULL;
     471           1 :                 NTTIME pwdLastSet;
     472           1 :                 NTTIME now;
     473           1 :                 int allowed_period_mins;
     474           1 :                 NTTIME allowed_period;
     475           1 :                 bool ok;
     476           1 :                 bool is_gmsa;
     477             : 
     478             :                 /* Reset these variables back to starting as empty */
     479        3766 :                 aes_256_key = NULL;
     480        3766 :                 salt = NULL;
     481             : 
     482             :                 /*
     483             :                  * Obtain the i'th old password from the NT password
     484             :                  * history for this user.
     485             :                  *
     486             :                  * We avoid issues with salts (which are not
     487             :                  * recorded for historical AES256 keys) by using the
     488             :                  * ntPwdHistory in preference.
     489             :                  */
     490        3766 :                 nt_status = samdb_result_passwords_from_history(tmp_ctx,
     491             :                                                         auth_context->lp_ctx,
     492             :                                                         msg, i,
     493             :                                                         NULL,
     494             :                                                         &nt_history_pwd);
     495             : 
     496             :                 /*
     497             :                  * Belts and braces: note that
     498             :                  * samdb_result_passwords_from_history() currently
     499             :                  * does not fail for missing attributes, it only sets
     500             :                  * nt_history_pwd = NULL, so "break" and fall down to
     501             :                  * the bad password count update if this happens
     502             :                  */
     503        3766 :                 if (!NT_STATUS_IS_OK(nt_status)) {
     504        2448 :                         break;
     505             :                 }
     506             : 
     507        3766 :                 nt_history_pwd = hide_invalid_nthash(nt_history_pwd);
     508             : 
     509             :                 /*
     510             :                  * We don't have an NT hash from the
     511             :                  * ntPwdHistory, but we can still perform the
     512             :                  * password check with the AES256
     513             :                  * key.
     514             :                  *
     515             :                  * However, this is the second preference as
     516             :                  * it will fail if the account was renamed
     517             :                  * prior to a password change (as we won't
     518             :                  * have the correct salt available to
     519             :                  * calculate the AES256 key).
     520             :                  */
     521             : 
     522        3766 :                 if (nt_history_pwd == NULL && sc_val != NULL &&
     523        2469 :                     user_info->password_state == AUTH_PASSWORD_PLAIN &&
     524         103 :                     current_kvno >= i)
     525          22 :                 {
     526           0 :                         krb5_error_code krb5_ret;
     527          32 :                         const uint32_t request_kvno = current_kvno - i;
     528             : 
     529             :                         /*
     530             :                          * Confirm we have a krb5_context set up
     531             :                          */
     532          32 :                         if (smb_krb5_context == NULL) {
     533             :                                 /*
     534             :                                  * We get here if we had a unicodePwd
     535             :                                  * for the current password, no
     536             :                                  * ntPwdHistory, a valid previous
     537             :                                  * Kerberos history AND are processing
     538             :                                  * a simple bind.
     539             :                                  *
     540             :                                  * This really is a corner case so
     541             :                                  * favour cleaner code over trying to
     542             :                                  * allow for an old password.  It is
     543             :                                  * more likely this is just a new
     544             :                                  * account.
     545             :                                  *
     546             :                                  * "break" out of the loop and fall down
     547             :                                  * to the bad password update
     548             :                                  */
     549          10 :                                 break;
     550             :                         }
     551             : 
     552             :                         /*
     553             :                          * Get the current salt from the record
     554             :                          */
     555             : 
     556          32 :                         krb5_ret = dsdb_extract_aes_256_key(smb_krb5_context->krb5_context,
     557             :                                                             tmp_ctx,
     558             :                                                             sam_ctx,
     559             :                                                             msg,
     560             :                                                             userAccountControl,
     561             :                                                             &request_kvno, /* kvno */
     562             :                                                             NULL, /* kvno_out */
     563             :                                                             &_aes_256_key,
     564             :                                                             &salt_data);
     565          32 :                         if (krb5_ret != 0) {
     566          10 :                                 break;
     567             :                         }
     568             : 
     569          22 :                         aes_256_key = &_aes_256_key;
     570             : 
     571          22 :                         _salt.data = (char *)salt_data.data;
     572          22 :                         _salt.length = salt_data.length;
     573          22 :                         salt = &_salt;
     574             : 
     575        3734 :                 } else if (nt_history_pwd == NULL) {
     576             :                         /*
     577             :                          * If we don't find element 'i' in the
     578             :                          * ntPwdHistory and can not fall back to the
     579             :                          * kerberos hash, we won't find 'i+1' ...
     580             :                          */
     581        2438 :                         break;
     582             :                 }
     583             : 
     584        1317 :                 auth_status = authsam_password_ok(auth_context, tmp_ctx,
     585             :                                                   nt_history_pwd,
     586             :                                                   smb_krb5_context,
     587             :                                                   aes_256_key,
     588             :                                                   salt,
     589             :                                                   user_info,
     590             :                                                   user_sess_key,
     591             :                                                   lm_sess_key);
     592             : 
     593        1317 :                 if (!NT_STATUS_IS_OK(auth_status)) {
     594             :                         /*
     595             :                          * If this was not a correct password, try the next
     596             :                          * one from the history
     597             :                          */
     598         883 :                         *user_sess_key = data_blob_null;
     599         883 :                         *lm_sess_key = data_blob_null;
     600         883 :                         continue;
     601             :                 }
     602             : 
     603         434 :                 if (i != 1) {
     604             :                         /*
     605             :                          * The authentication was OK, but not against
     606             :                          * the previous password, which is stored at index 1.
     607             :                          *
     608             :                          * We just return the original wrong password.
     609             :                          * This skips the update of the bad pwd count,
     610             :                          * because this is almost certainly user error
     611             :                          * (or automatic login on a computer using a cached
     612             :                          * password from before the password change),
     613             :                          * not an attack.
     614             :                          */
     615          29 :                         TALLOC_FREE(tmp_ctx);
     616          29 :                         return NT_STATUS_WRONG_PASSWORD;
     617             :                 }
     618             : 
     619         405 :                 if (user_info->flags & USER_INFO_INTERACTIVE_LOGON) {
     620             :                         /*
     621             :                          * The authentication was OK against the previous password,
     622             :                          * but it's not a NTLM network authentication,
     623             :                          * LDAP simple bind or something similar.
     624             :                          *
     625             :                          * We just return the original wrong password.
     626             :                          * This skips the update of the bad pwd count,
     627             :                          * because this is almost certainly user error
     628             :                          * (or automatic login on a computer using a cached
     629             :                          * password from before the password change),
     630             :                          * not an attack.
     631             :                          */
     632           5 :                         TALLOC_FREE(tmp_ctx);
     633           5 :                         return NT_STATUS_WRONG_PASSWORD;
     634             :                 }
     635             : 
     636             :                 /*
     637             :                  * If the password was OK, it's a NTLM network authentication
     638             :                  * and it was the previous password.
     639             :                  *
     640             :                  * Now we see if it is within the grace period,
     641             :                  * so that we don't break cached sessions on other computers
     642             :                  * before the user can lock and unlock their other screens
     643             :                  * (resetting their cached password).
     644             :                  *
     645             :                  */
     646             : 
     647             :                 /* Is the account a Group Managed Service Account? */
     648         400 :                 is_gmsa = dsdb_account_is_gmsa(sam_ctx, msg);
     649         400 :                 if (is_gmsa) {
     650             :                         /*
     651             :                          * For Group Managed Service Accounts, the previous
     652             :                          * password is allowed for five minutes after a password
     653             :                          * change.
     654             :                          */
     655          14 :                         allowed_period_mins = gkdi_max_clock_skew_mins;
     656             :                 } else {
     657             :                         /*
     658             :                          * See http://support.microsoft.com/kb/906305
     659             :                          * OldPasswordAllowedPeriod ("old password allowed
     660             :                          * period") is specified in minutes. The default is 60.
     661             :                          */
     662         386 :                         allowed_period_mins = lpcfg_old_password_allowed_period(
     663             :                                 auth_context->lp_ctx);
     664             :                 }
     665             :                 /*
     666             :                  * NTTIME uses 100ns units
     667             :                  */
     668         400 :                 allowed_period = (NTTIME) allowed_period_mins *
     669             :                                  60 * 1000*1000*10;
     670         400 :                 pwdLastSet = samdb_result_nttime(msg, "pwdLastSet", 0);
     671         400 :                 ok = dsdb_gmsa_current_time(sam_ctx, &now);
     672         400 :                 if (!ok) {
     673           0 :                         TALLOC_FREE(tmp_ctx);
     674           0 :                         return NT_STATUS_WRONG_PASSWORD;
     675             :                 }
     676             : 
     677         400 :                 if (now < pwdLastSet) {
     678             :                         /*
     679             :                          * time jump?
     680             :                          *
     681             :                          * We just return the original wrong password.
     682             :                          * This skips the update of the bad pwd count,
     683             :                          * because this is almost certainly user error
     684             :                          * (or automatic login on a computer using a cached
     685             :                          * password from before the password change),
     686             :                          * not an attack.
     687             :                          */
     688           0 :                         TALLOC_FREE(tmp_ctx);
     689           0 :                         return NT_STATUS_WRONG_PASSWORD;
     690             :                 }
     691             : 
     692         400 :                 if ((now - pwdLastSet) >= allowed_period) {
     693             :                         /*
     694             :                          * The allowed period is over.
     695             :                          *
     696             :                          * We just return the original wrong password.
     697             :                          * This skips the update of the bad pwd count,
     698             :                          * because this is almost certainly user error
     699             :                          * (or automatic login on a computer using a cached
     700             :                          * password from before the password change),
     701             :                          * not an attack.
     702             :                          */
     703           2 :                         TALLOC_FREE(tmp_ctx);
     704           2 :                         return NT_STATUS_WRONG_PASSWORD;
     705             :                 }
     706             : 
     707             :                 /*
     708             :                  * We finally allow the authentication with the
     709             :                  * previous password within the allowed period.
     710             :                  */
     711         398 :                 if (user_sess_key->data) {
     712         293 :                         talloc_steal(mem_ctx, user_sess_key->data);
     713             :                 }
     714         398 :                 if (lm_sess_key->data) {
     715         167 :                         talloc_steal(mem_ctx, lm_sess_key->data);
     716             :                 }
     717             : 
     718         398 :                 TALLOC_FREE(tmp_ctx);
     719         398 :                 return auth_status;
     720             :         }
     721             : 
     722             :         /*
     723             :          * If we are not in the allowed period or match an old password,
     724             :          * we didn't return early. Now update the badPwdCount et al.
     725             :          */
     726        2648 :         nt_status = authsam_update_bad_pwd_count(auth_context->sam_ctx,
     727             :                                                  msg, domain_dn);
     728        2648 :         if (!NT_STATUS_IS_OK(nt_status)) {
     729             :                 /*
     730             :                  * We need to return the original
     731             :                  * NT_STATUS_WRONG_PASSWORD error, so there isn't
     732             :                  * anything more we can do than write something into
     733             :                  * the log
     734             :                  */
     735           1 :                 DEBUG(0, ("Failed to note bad password for user [%s]: %s\n",
     736             :                           user_info->mapped.account_name,
     737             :                           nt_errstr(nt_status)));
     738             :         }
     739             : 
     740        2648 :         if (samdb_rodc(auth_context->sam_ctx, &am_rodc) == LDB_SUCCESS && am_rodc) {
     741          18 :                 *authoritative = false;
     742             :         }
     743             : 
     744        2648 :         TALLOC_FREE(tmp_ctx);
     745             : 
     746        2648 :         if (NT_STATUS_IS_OK(nt_status)) {
     747        2647 :                 nt_status = NT_STATUS_WRONG_PASSWORD;
     748             :         }
     749        2648 :         return nt_status;
     750             : }
     751             : 
     752       24084 : static NTSTATUS authsam_check_netlogon_trust(TALLOC_CTX *mem_ctx,
     753             :                                              struct ldb_context *sam_ctx,
     754             :                                              struct loadparm_context *lp_ctx,
     755             :                                              const struct auth_usersupplied_info *user_info,
     756             :                                              const struct auth_user_info_dc *user_info_dc,
     757             :                                              struct authn_audit_info **server_audit_info_out)
     758             : {
     759       24084 :         TALLOC_CTX *tmp_ctx = NULL;
     760             : 
     761        1410 :         static const char *authn_policy_silo_attrs[] = {
     762             :                 "msDS-AssignedAuthNPolicy",
     763             :                 "msDS-AssignedAuthNPolicySilo",
     764             :                 "objectClass", /* used to determine which set of policy
     765             :                                 * attributes apply. */
     766             :                 NULL,
     767             :         };
     768             : 
     769       24084 :         const struct authn_server_policy *authn_server_policy = NULL;
     770             : 
     771        1410 :         struct dom_sid_buf netlogon_trust_sid_buf;
     772       24084 :         const char *netlogon_trust_sid_str = NULL;
     773       24084 :         struct ldb_dn *netlogon_trust_dn = NULL;
     774       24084 :         struct ldb_message *netlogon_trust_msg = NULL;
     775             : 
     776        1410 :         int ret;
     777             : 
     778             :         /* Have we established a secure channel? */
     779       24084 :         if (user_info->netlogon_trust_account.secure_channel_type == SEC_CHAN_NULL) {
     780       12153 :                 return NT_STATUS_OK;
     781             :         }
     782             : 
     783       11931 :         if (!authn_policy_silos_and_policies_in_effect(sam_ctx)) {
     784         428 :                 return NT_STATUS_OK;
     785             :         }
     786             : 
     787             :         /*
     788             :          * We have established a secure channel, and we should have the machine
     789             :          * account’s SID.
     790             :          */
     791       11503 :         SMB_ASSERT(user_info->netlogon_trust_account.sid != NULL);
     792             : 
     793       11503 :         tmp_ctx = talloc_new(mem_ctx);
     794       11503 :         if (tmp_ctx == NULL) {
     795           0 :                 return NT_STATUS_NO_MEMORY;
     796             :         }
     797             : 
     798       11503 :         netlogon_trust_sid_str = dom_sid_str_buf(user_info->netlogon_trust_account.sid,
     799             :                                                  &netlogon_trust_sid_buf);
     800             : 
     801       11503 :         netlogon_trust_dn = ldb_dn_new_fmt(tmp_ctx, sam_ctx,
     802             :                                            "<SID=%s>",
     803             :                                            netlogon_trust_sid_str);
     804       11503 :         if (netlogon_trust_dn == NULL) {
     805           0 :                 talloc_free(tmp_ctx);
     806           0 :                 return NT_STATUS_NO_MEMORY;
     807             :         }
     808             : 
     809             :         /*
     810             :          * Look up the machine account to see if it has an applicable
     811             :          * authentication policy.
     812             :          */
     813       11503 :         ret = dsdb_search_one(sam_ctx,
     814             :                               tmp_ctx,
     815             :                               &netlogon_trust_msg,
     816             :                               netlogon_trust_dn,
     817             :                               LDB_SCOPE_BASE,
     818             :                               authn_policy_silo_attrs,
     819             :                               0,
     820             :                               NULL);
     821       11503 :         if (ret) {
     822           0 :                 talloc_free(tmp_ctx);
     823           0 :                 return dsdb_ldb_err_to_ntstatus(ret);
     824             :         }
     825             : 
     826       11503 :         ret = authn_policy_server(sam_ctx,
     827             :                                   tmp_ctx,
     828             :                                   netlogon_trust_msg,
     829             :                                   &authn_server_policy);
     830       11503 :         if (ret) {
     831           0 :                 talloc_free(tmp_ctx);
     832           0 :                 return NT_STATUS_INTERNAL_ERROR;
     833             :         }
     834             : 
     835       11503 :         if (authn_server_policy != NULL) {
     836         104 :                 struct authn_audit_info *server_audit_info = NULL;
     837           0 :                 NTSTATUS status;
     838             : 
     839             :                 /*
     840             :                  * An authentication policy applies to the machine
     841             :                  * account. Carry out the access check.
     842             :                  */
     843         104 :                 status = authn_policy_authenticate_to_service(tmp_ctx,
     844             :                                                               sam_ctx,
     845             :                                                               lp_ctx,
     846             :                                                               AUTHN_POLICY_AUTH_TYPE_NTLM,
     847             :                                                               user_info_dc,
     848             :                                                               NULL /* device_info */,
     849             :                                                               /*
     850             :                                                                * It seems that claims go ignored for
     851             :                                                                * SamLogon (see SamLogonTests —
     852             :                                                                * test_samlogon_allowed_to_computer_silo).
     853             :                                                                */
     854         104 :                                                               (struct auth_claims) {},
     855             :                                                               authn_server_policy,
     856         104 :                                                               (struct authn_policy_flags) {},
     857             :                                                               &server_audit_info);
     858         104 :                 if (server_audit_info != NULL) {
     859         104 :                         *server_audit_info_out = talloc_move(mem_ctx, &server_audit_info);
     860             :                 }
     861         104 :                 if (!NT_STATUS_IS_OK(status)) {
     862          52 :                         talloc_free(tmp_ctx);
     863          52 :                         return status;
     864             :                 }
     865             :         }
     866             : 
     867       11451 :         return NT_STATUS_OK;
     868             : }
     869             : 
     870       27218 : static NTSTATUS authsam_authenticate(struct auth4_context *auth_context,
     871             :                                      TALLOC_CTX *mem_ctx,
     872             :                                      struct ldb_dn *domain_dn,
     873             :                                      struct ldb_message *msg,
     874             :                                      const struct auth_usersupplied_info *user_info,
     875             :                                      const struct auth_user_info_dc *user_info_dc,
     876             :                                      DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key,
     877             :                                      struct authn_audit_info **client_audit_info_out,
     878             :                                      struct authn_audit_info **server_audit_info_out,
     879             :                                      bool *authoritative)
     880             : {
     881        1411 :         NTSTATUS nt_status;
     882        1411 :         int ret;
     883       27218 :         bool interactive = (user_info->password_state == AUTH_PASSWORD_HASH);
     884       27218 :         uint32_t acct_flags = samdb_result_acct_flags(msg, NULL);
     885       27218 :         struct netr_SendToSamBase *send_to_sam = NULL;
     886       27218 :         const struct authn_ntlm_client_policy *authn_client_policy = NULL;
     887       27218 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     888       27218 :         if (!tmp_ctx) {
     889           0 :                 return NT_STATUS_NO_MEMORY;
     890             :         }
     891             : 
     892             :         /* You can only do an interactive login to normal accounts */
     893       27218 :         if (user_info->flags & USER_INFO_INTERACTIVE_LOGON) {
     894         535 :                 if (!(acct_flags & ACB_NORMAL)) {
     895           9 :                         TALLOC_FREE(tmp_ctx);
     896           9 :                         return NT_STATUS_NO_SUCH_USER;
     897             :                 }
     898         526 :                 if (acct_flags & ACB_SMARTCARD_REQUIRED) {
     899           3 :                         if (acct_flags & ACB_DISABLED) {
     900           0 :                                 DEBUG(2,("authsam_authenticate: Account for user '%s' "
     901             :                                          "was disabled.\n",
     902             :                                          user_info->mapped.account_name));
     903           0 :                                 TALLOC_FREE(tmp_ctx);
     904           0 :                                 return NT_STATUS_ACCOUNT_DISABLED;
     905             :                         }
     906           3 :                         DEBUG(2,("authsam_authenticate: Account for user '%s' "
     907             :                                  "requires interactive smartcard logon.\n",
     908             :                                  user_info->mapped.account_name));
     909           3 :                         TALLOC_FREE(tmp_ctx);
     910           3 :                         return NT_STATUS_SMARTCARD_LOGON_REQUIRED;
     911             :                 }
     912             :         }
     913             : 
     914             :         /* See whether an authentication policy applies to the client. */
     915       27206 :         ret = authn_policy_ntlm_client(auth_context->sam_ctx,
     916             :                                        tmp_ctx,
     917             :                                        msg,
     918             :                                        &authn_client_policy);
     919       27206 :         if (ret) {
     920           0 :                 TALLOC_FREE(tmp_ctx);
     921           0 :                 return NT_STATUS_INTERNAL_ERROR;
     922             :         }
     923             : 
     924       27206 :         nt_status = authn_policy_ntlm_apply_device_restriction(mem_ctx,
     925             :                                                                authn_client_policy,
     926             :                                                                client_audit_info_out);
     927       27206 :         if (!NT_STATUS_IS_OK(nt_status)) {
     928             :                 /*
     929             :                  * As we didn’t get far enough to check the server policy, only
     930             :                  * the client policy will be referenced in the authentication
     931             :                  * log message.
     932             :                  */
     933          38 :                 TALLOC_FREE(tmp_ctx);
     934          38 :                 return nt_status;
     935             :         }
     936             : 
     937       27168 :         nt_status = authsam_password_check_and_record(auth_context, tmp_ctx,
     938             :                                                       domain_dn, msg,
     939             :                                                       user_info,
     940             :                                                       user_sess_key, lm_sess_key,
     941             :                                                       authoritative);
     942       27168 :         if (!NT_STATUS_IS_OK(nt_status)) {
     943        3084 :                 TALLOC_FREE(tmp_ctx);
     944        3084 :                 return nt_status;
     945             :         }
     946             : 
     947       24084 :         nt_status = authsam_check_netlogon_trust(mem_ctx,
     948             :                                                  auth_context->sam_ctx,
     949             :                                                  auth_context->lp_ctx,
     950             :                                                  user_info,
     951             :                                                  user_info_dc,
     952             :                                                  server_audit_info_out);
     953       24084 :         if (!NT_STATUS_IS_OK(nt_status)) {
     954          52 :                 TALLOC_FREE(tmp_ctx);
     955          52 :                 return nt_status;
     956             :         }
     957             : 
     958       25442 :         nt_status = authsam_account_ok(tmp_ctx, auth_context->sam_ctx,
     959       24032 :                                        user_info->logon_parameters,
     960             :                                        domain_dn,
     961             :                                        msg,
     962       24032 :                                        user_info->workstation_name,
     963       24032 :                                        user_info->mapped.account_name,
     964             :                                        false, false);
     965       24032 :         if (!NT_STATUS_IS_OK(nt_status)) {
     966         966 :                 TALLOC_FREE(tmp_ctx);
     967         966 :                 return nt_status;
     968             :         }
     969             : 
     970       23066 :         nt_status = authsam_logon_success_accounting(auth_context->sam_ctx,
     971             :                                                      msg, domain_dn,
     972             :                                                      interactive,
     973             :                                                      tmp_ctx,
     974             :                                                      &send_to_sam);
     975             : 
     976       23066 :         if (send_to_sam != NULL) {
     977           9 :                 auth_sam_trigger_zero_password(tmp_ctx,
     978             :                                                auth_context->msg_ctx,
     979             :                                                auth_context->event_ctx,
     980             :                                                send_to_sam);
     981             :         }
     982             : 
     983       23066 :         if (!NT_STATUS_IS_OK(nt_status)) {
     984           0 :                 TALLOC_FREE(tmp_ctx);
     985           0 :                 return nt_status;
     986             :         }
     987             : 
     988       23066 :         if (user_sess_key && user_sess_key->data) {
     989       21751 :                 talloc_steal(mem_ctx, user_sess_key->data);
     990             :         }
     991       23066 :         if (lm_sess_key && lm_sess_key->data) {
     992       20278 :                 talloc_steal(mem_ctx, lm_sess_key->data);
     993             :         }
     994             : 
     995       23066 :         TALLOC_FREE(tmp_ctx);
     996       23066 :         return nt_status;
     997             : }
     998             : 
     999             : 
    1000             : 
    1001       28403 : static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx,
    1002             :                                                  TALLOC_CTX *mem_ctx,
    1003             :                                                  const struct auth_usersupplied_info *user_info,
    1004             :                                                  struct auth_user_info_dc **user_info_dc,
    1005             :                                                  struct authn_audit_info **client_audit_info_out,
    1006             :                                                  struct authn_audit_info **server_audit_info_out,
    1007             :                                                  bool *authoritative)
    1008             : {
    1009        1417 :         NTSTATUS nt_status;
    1010        1417 :         int result;
    1011       28403 :         const char *account_name = user_info->mapped.account_name;
    1012        1417 :         struct ldb_message *msg;
    1013        1417 :         struct ldb_dn *domain_dn;
    1014        1417 :         DATA_BLOB user_sess_key, lm_sess_key;
    1015        1417 :         TALLOC_CTX *tmp_ctx;
    1016       28403 :         const char *p = NULL;
    1017       28403 :         struct auth_user_info_dc *reparented = NULL;
    1018       28403 :         struct authn_audit_info *client_audit_info = NULL;
    1019       28403 :         struct authn_audit_info *server_audit_info = NULL;
    1020             : 
    1021       28403 :         if (ctx->auth_ctx->sam_ctx == NULL) {
    1022           0 :                 DEBUG(0, ("No SAM available, cannot log in users\n"));
    1023           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
    1024             :         }
    1025             : 
    1026       28403 :         if (!account_name || !*account_name) {
    1027             :                 /* 'not for me' */
    1028           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1029             :         }
    1030             : 
    1031       28403 :         tmp_ctx = talloc_new(mem_ctx);
    1032       28403 :         if (!tmp_ctx) {
    1033           0 :                 return NT_STATUS_NO_MEMORY;
    1034             :         }
    1035             : 
    1036       28403 :         domain_dn = ldb_get_default_basedn(ctx->auth_ctx->sam_ctx);
    1037       28403 :         if (domain_dn == NULL) {
    1038           0 :                 talloc_free(tmp_ctx);
    1039           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
    1040             :         }
    1041             : 
    1042             :         /*
    1043             :          * If we have not already mapped this user, then now is a good
    1044             :          * time to do so, before we look it up.  We used to do this
    1045             :          * earlier, but in a multi-forest environment we want to do
    1046             :          * this mapping at the final domain.
    1047             :          *
    1048             :          * However, on the flip side we may have already mapped the
    1049             :          * user if this was an LDAP simple bind, in which case we
    1050             :          * really, really want to get back to exactly the same account
    1051             :          * we got the DN for.
    1052             :          */
    1053       28403 :         if (!user_info->cracknames_called) {
    1054       27960 :                 p = strchr_m(account_name, '@');
    1055             :         } else {
    1056             :                 /*
    1057             :                  * This is slightly nicer than double-indenting the
    1058             :                  * block below
    1059             :                  */
    1060         443 :                 p = NULL;
    1061             :         }
    1062             : 
    1063       28403 :         if (p != NULL) {
    1064        7893 :                 const char *nt4_domain = NULL;
    1065        7893 :                 const char *nt4_account = NULL;
    1066        7893 :                 bool is_my_domain = false;
    1067             : 
    1068        8853 :                 nt_status = crack_name_to_nt4_name(mem_ctx,
    1069        7893 :                                                    ctx->auth_ctx->sam_ctx,
    1070             :                                                    /*
    1071             :                                                     * DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON ?
    1072             :                                                     */
    1073             :                                                    DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
    1074             :                                                    account_name,
    1075             :                                                    &nt4_domain, &nt4_account);
    1076        7893 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1077           0 :                         talloc_free(tmp_ctx);
    1078           0 :                         return NT_STATUS_NO_SUCH_USER;
    1079             :                 }
    1080             : 
    1081        7893 :                 is_my_domain = lpcfg_is_mydomain(ctx->auth_ctx->lp_ctx, nt4_domain);
    1082        7893 :                 if (!is_my_domain) {
    1083             :                         /*
    1084             :                          * This is a user within our forest,
    1085             :                          * but in a different domain,
    1086             :                          * we're not authoritative
    1087             :                          */
    1088           0 :                         talloc_free(tmp_ctx);
    1089           0 :                         return NT_STATUS_NOT_IMPLEMENTED;
    1090             :                 }
    1091             : 
    1092             :                 /*
    1093             :                  * Let's use the NT4 account name for the lookup.
    1094             :                  */
    1095        7893 :                 account_name = nt4_account;
    1096             :         }
    1097             : 
    1098       28403 :         nt_status = authsam_search_account(tmp_ctx, ctx->auth_ctx->sam_ctx, account_name, domain_dn, &msg);
    1099       28403 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1100        1168 :                 talloc_free(tmp_ctx);
    1101        1168 :                 return nt_status;
    1102             :         }
    1103             : 
    1104       27235 :         nt_status = authsam_make_user_info_dc(tmp_ctx, ctx->auth_ctx->sam_ctx,
    1105       27235 :                                              lpcfg_netbios_name(ctx->auth_ctx->lp_ctx),
    1106       27235 :                                              lpcfg_sam_name(ctx->auth_ctx->lp_ctx),
    1107       27235 :                                              lpcfg_sam_dnsname(ctx->auth_ctx->lp_ctx),
    1108             :                                              domain_dn,
    1109             :                                              msg,
    1110             :                                              data_blob_null, data_blob_null,
    1111             :                                              user_info_dc);
    1112       27235 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1113           0 :                 talloc_free(tmp_ctx);
    1114           0 :                 return nt_status;
    1115             :         }
    1116             : 
    1117       28646 :         result = dsdb_is_protected_user(ctx->auth_ctx->sam_ctx,
    1118       27235 :                                         (*user_info_dc)->sids,
    1119       27235 :                                         (*user_info_dc)->num_sids);
    1120             :         /*
    1121             :          * We also consider an error result (a negative value) as denying the
    1122             :          * authentication.
    1123             :          */
    1124       27235 :         if (result != 0) {
    1125          17 :                 talloc_free(tmp_ctx);
    1126          17 :                 return NT_STATUS_ACCOUNT_RESTRICTION;
    1127             :         }
    1128             : 
    1129       27218 :         nt_status = authsam_authenticate(ctx->auth_ctx,
    1130             :                                          tmp_ctx,
    1131             :                                          domain_dn,
    1132             :                                          msg,
    1133             :                                          user_info,
    1134             :                                          *user_info_dc,
    1135             :                                          &user_sess_key,
    1136             :                                          &lm_sess_key,
    1137             :                                          &client_audit_info,
    1138             :                                          &server_audit_info,
    1139             :                                          authoritative);
    1140       27218 :         if (client_audit_info != NULL) {
    1141         100 :                 *client_audit_info_out = talloc_move(mem_ctx, &client_audit_info);
    1142             :         }
    1143       27218 :         if (server_audit_info != NULL) {
    1144         104 :                 *server_audit_info_out = talloc_move(mem_ctx, &server_audit_info);
    1145             :         }
    1146       27218 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1147        4152 :                 talloc_free(tmp_ctx);
    1148        4152 :                 return nt_status;
    1149             :         }
    1150             : 
    1151       23066 :         (*user_info_dc)->user_session_key = data_blob_talloc(*user_info_dc,
    1152             :                                                              user_sess_key.data,
    1153             :                                                              user_sess_key.length);
    1154       23066 :         if (user_sess_key.data) {
    1155       21751 :                 if ((*user_info_dc)->user_session_key.data == NULL) {
    1156           0 :                         TALLOC_FREE(tmp_ctx);
    1157           0 :                         return NT_STATUS_NO_MEMORY;
    1158             :                 }
    1159             :         }
    1160             : 
    1161       23066 :         (*user_info_dc)->lm_session_key = data_blob_talloc(*user_info_dc,
    1162             :                                                            lm_sess_key.data,
    1163             :                                                            lm_sess_key.length);
    1164       23066 :         if (lm_sess_key.data) {
    1165       20278 :                 if ((*user_info_dc)->lm_session_key.data == NULL) {
    1166           0 :                         TALLOC_FREE(tmp_ctx);
    1167           0 :                         return NT_STATUS_NO_MEMORY;
    1168             :                 }
    1169             :         }
    1170             : 
    1171             :         /*
    1172             :          * Release our handle to *user_info_dc. {client,server}_audit_info_out,
    1173             :          * if non-NULL, becomes the new parent.
    1174             :          */
    1175       23066 :         reparented = talloc_reparent(tmp_ctx, mem_ctx, *user_info_dc);
    1176       23066 :         if (reparented == NULL) {
    1177           0 :                 talloc_free(tmp_ctx);
    1178           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1179             :         }
    1180             : 
    1181       23066 :         talloc_free(tmp_ctx);
    1182             : 
    1183       23066 :         return NT_STATUS_OK;
    1184             : }
    1185             : 
    1186             : struct authsam_check_password_state {
    1187             :         struct auth_user_info_dc *user_info_dc;
    1188             :         struct authn_audit_info *client_audit_info;
    1189             :         struct authn_audit_info *server_audit_info;
    1190             :         bool authoritative;
    1191             : };
    1192             : 
    1193       28403 : static struct tevent_req *authsam_check_password_send(
    1194             :         TALLOC_CTX *mem_ctx,
    1195             :         struct tevent_context *ev,
    1196             :         struct auth_method_context *ctx,
    1197             :         const struct auth_usersupplied_info *user_info)
    1198             : {
    1199       28403 :         struct tevent_req *req = NULL;
    1200       28403 :         struct authsam_check_password_state *state = NULL;
    1201        1417 :         NTSTATUS status;
    1202             : 
    1203       28403 :         req = tevent_req_create(
    1204             :                 mem_ctx, &state, struct authsam_check_password_state);
    1205       28403 :         if (req == NULL) {
    1206           0 :                 return NULL;
    1207             :         }
    1208             :         /*
    1209             :          * authsam_check_password_internals() sets this to false in
    1210             :          * the rodc case, otherwise it leaves it untouched. Default to
    1211             :          * "we're authoritative".
    1212             :          */
    1213       28403 :         state->authoritative = true;
    1214             : 
    1215       28403 :         status = authsam_check_password_internals(
    1216             :                 ctx,
    1217             :                 state,
    1218             :                 user_info,
    1219       26986 :                 &state->user_info_dc,
    1220       26986 :                 &state->client_audit_info,
    1221       26986 :                 &state->server_audit_info,
    1222       26986 :                 &state->authoritative);
    1223       28403 :         if (tevent_req_nterror(req, status)) {
    1224        5337 :                 return tevent_req_post(req, ev);
    1225             :         }
    1226             : 
    1227       23066 :         tevent_req_done(req);
    1228       23066 :         return tevent_req_post(req, ev);
    1229             : }
    1230             : 
    1231       28403 : static NTSTATUS authsam_check_password_recv(
    1232             :         struct tevent_req *req,
    1233             :         TALLOC_CTX *mem_ctx,
    1234             :         struct auth_user_info_dc **interim_info,
    1235             :         const struct authn_audit_info **client_audit_info,
    1236             :         const struct authn_audit_info **server_audit_info,
    1237             :         bool *authoritative)
    1238             : {
    1239       28403 :         struct authsam_check_password_state *state = tevent_req_data(
    1240             :                 req, struct authsam_check_password_state);
    1241        1417 :         NTSTATUS status;
    1242             : 
    1243       28403 :         *authoritative = state->authoritative;
    1244             : 
    1245       28403 :         *client_audit_info = talloc_reparent(state, mem_ctx, state->client_audit_info);
    1246       28403 :         state->client_audit_info = NULL;
    1247             : 
    1248       28403 :         *server_audit_info = talloc_reparent(state, mem_ctx, state->server_audit_info);
    1249       28403 :         state->server_audit_info = NULL;
    1250             : 
    1251       28403 :         if (tevent_req_is_nterror(req, &status)) {
    1252        5337 :                 tevent_req_received(req);
    1253        5337 :                 return status;
    1254             :         }
    1255             :         /*
    1256             :          * Release our handle to state->user_info_dc.
    1257             :          * {client,server}_audit_info, if non-NULL, becomes the new parent.
    1258             :          */
    1259       23066 :         *interim_info = talloc_reparent(state, mem_ctx, state->user_info_dc);
    1260       23066 :         state->user_info_dc = NULL;
    1261             : 
    1262       23066 :         tevent_req_received(req);
    1263       23066 :         return NT_STATUS_OK;
    1264             : }
    1265             : 
    1266        1174 : static NTSTATUS authsam_ignoredomain_want_check(struct auth_method_context *ctx,
    1267             :                                                 TALLOC_CTX *mem_ctx,
    1268             :                                                 const struct auth_usersupplied_info *user_info)
    1269             : {
    1270        1174 :         if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
    1271          12 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1272             :         }
    1273             : 
    1274        1162 :         return NT_STATUS_OK;
    1275             : }
    1276             : 
    1277             : /****************************************************************************
    1278             : Check SAM security (above) but with a few extra checks.
    1279             : ****************************************************************************/
    1280       28671 : static NTSTATUS authsam_want_check(struct auth_method_context *ctx,
    1281             :                                    TALLOC_CTX *mem_ctx,
    1282             :                                    const struct auth_usersupplied_info *user_info)
    1283             : {
    1284       28671 :         const char *effective_domain = user_info->mapped.domain_name;
    1285       28671 :         bool is_local_name = false;
    1286       28671 :         bool is_my_domain = false;
    1287       28671 :         const char *p = NULL;
    1288       28671 :         struct dsdb_trust_routing_table *trt = NULL;
    1289       28671 :         const struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
    1290        1417 :         NTSTATUS status;
    1291             : 
    1292       28671 :         if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
    1293          14 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1294             :         }
    1295             : 
    1296       28657 :         if (effective_domain == NULL) {
    1297        1644 :                 effective_domain = "";
    1298             :         }
    1299             : 
    1300       28657 :         is_local_name = lpcfg_is_myname(ctx->auth_ctx->lp_ctx,
    1301             :                                         effective_domain);
    1302             : 
    1303             :         /* check whether or not we service this domain/workgroup name */
    1304       28657 :         switch (lpcfg_server_role(ctx->auth_ctx->lp_ctx)) {
    1305           0 :         case ROLE_STANDALONE:
    1306         103 :                 return NT_STATUS_OK;
    1307             : 
    1308         103 :         case ROLE_DOMAIN_MEMBER:
    1309         103 :                 if (is_local_name) {
    1310          98 :                         return NT_STATUS_OK;
    1311             :                 }
    1312             : 
    1313           5 :                 DBG_DEBUG("%s is not one of my local names (DOMAIN_MEMBER)\n",
    1314             :                           effective_domain);
    1315           5 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1316             : 
    1317       27137 :         case ROLE_ACTIVE_DIRECTORY_DC:
    1318             :                 /* handled later */
    1319       28554 :                 break;
    1320             : 
    1321           0 :         default:
    1322           0 :                 DBG_ERR("lpcfg_server_role() has an undefined value\n");
    1323           0 :                 return NT_STATUS_INVALID_SERVER_STATE;
    1324             :         }
    1325             : 
    1326             :         /*
    1327             :          * Now we handle the AD DC case...
    1328             :          */
    1329             : 
    1330       28554 :         is_my_domain = lpcfg_is_my_domain_or_realm(ctx->auth_ctx->lp_ctx,
    1331             :                                                    effective_domain);
    1332       28554 :         if (is_my_domain) {
    1333       19313 :                 return NT_STATUS_OK;
    1334             :         }
    1335             : 
    1336        9241 :         if (user_info->cracknames_called) {
    1337             :                 /*
    1338             :                  * The caller already did a cracknames call.
    1339             :                  */
    1340           0 :                 DBG_DEBUG("%s is not own domain name (DC)\n",
    1341             :                           effective_domain);
    1342           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1343             :         }
    1344             : 
    1345        9241 :         if (!strequal(effective_domain, "")) {
    1346        1379 :                 DBG_DEBUG("%s is not own domain name (DC)\n",
    1347             :                           effective_domain);
    1348        1379 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1349             :         }
    1350             : 
    1351        7862 :         p = strchr_m(user_info->mapped.account_name, '@');
    1352        7862 :         if (p == NULL) {
    1353             :                 /*
    1354             :                  * An empty to domain name should be handled
    1355             :                  * as the local domain name.
    1356             :                  */
    1357           9 :                 return NT_STATUS_OK;
    1358             :         }
    1359             : 
    1360        7853 :         effective_domain = p + 1;
    1361        7853 :         is_my_domain = lpcfg_is_my_domain_or_realm(ctx->auth_ctx->lp_ctx,
    1362             :                                                    effective_domain);
    1363        7853 :         if (is_my_domain) {
    1364        7821 :                 return NT_STATUS_OK;
    1365             :         }
    1366             : 
    1367          32 :         if (strequal(effective_domain, "")) {
    1368           2 :                 DBG_DEBUG("authsam_check_password: upn without realm (DC)\n");
    1369           2 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1370             :         }
    1371             : 
    1372             :         /*
    1373             :          * as last option we check the routing table if the
    1374             :          * domain is within our forest.
    1375             :          */
    1376          30 :         status = dsdb_trust_routing_table_load(ctx->auth_ctx->sam_ctx,
    1377             :                                                mem_ctx, &trt);
    1378          30 :         if (!NT_STATUS_IS_OK(status)) {
    1379           0 :                 DBG_ERR("authsam_check_password: dsdb_trust_routing_table_load() %s\n",
    1380             :                          nt_errstr(status));
    1381           0 :                 return status;
    1382             :         }
    1383             : 
    1384          30 :         tdo = dsdb_trust_routing_by_name(trt, effective_domain);
    1385          30 :         if (tdo == NULL) {
    1386          18 :                 DBG_DEBUG("%s is not a known TLN (DC)\n",
    1387             :                           effective_domain);
    1388          18 :                 TALLOC_FREE(trt);
    1389          18 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1390             :         }
    1391             : 
    1392          12 :         if (!(tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
    1393          12 :                 DBG_DEBUG("%s is not a TLN in our forest (DC)\n",
    1394             :                           effective_domain);
    1395          12 :                 TALLOC_FREE(trt);
    1396          12 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1397             :         }
    1398             : 
    1399             :         /*
    1400             :          * This principal is within our forest.
    1401             :          * we'll later do a crack_name_to_nt4_name()
    1402             :          * to check if it's in our domain.
    1403             :          */
    1404           0 :         TALLOC_FREE(trt);
    1405           0 :         return NT_STATUS_OK;
    1406             : }
    1407             : 
    1408             : static const struct auth_operations sam_ignoredomain_ops = {
    1409             :         .name                      = "sam_ignoredomain",
    1410             :         .want_check                = authsam_ignoredomain_want_check,
    1411             :         .check_password_send       = authsam_check_password_send,
    1412             :         .check_password_recv       = authsam_check_password_recv,
    1413             : };
    1414             : 
    1415             : static const struct auth_operations sam_ops = {
    1416             :         .name                      = "sam",
    1417             :         .want_check                = authsam_want_check,
    1418             :         .check_password_send       = authsam_check_password_send,
    1419             :         .check_password_recv       = authsam_check_password_recv,
    1420             : };
    1421             : 
    1422             : _PUBLIC_ NTSTATUS auth4_sam_init(TALLOC_CTX *);
    1423        9565 : _PUBLIC_ NTSTATUS auth4_sam_init(TALLOC_CTX *ctx)
    1424             : {
    1425         857 :         NTSTATUS ret;
    1426             : 
    1427        9565 :         ret = auth_register(ctx, &sam_ops);
    1428        9565 :         if (!NT_STATUS_IS_OK(ret)) {
    1429           0 :                 DEBUG(0,("Failed to register 'sam' auth backend!\n"));
    1430           0 :                 return ret;
    1431             :         }
    1432             : 
    1433        9565 :         ret = auth_register(ctx, &sam_ignoredomain_ops);
    1434        9565 :         if (!NT_STATUS_IS_OK(ret)) {
    1435           0 :                 DEBUG(0,("Failed to register 'sam_ignoredomain' auth backend!\n"));
    1436           0 :                 return ret;
    1437             :         }
    1438             : 
    1439        9565 :         return ret;
    1440             : }

Generated by: LCOV version 1.14