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

Generated by: LCOV version 1.14