LCOV - code coverage report
Current view: top level - source4/auth/ntlm - auth_sam.c (source / functions) Hit Total Coverage
Test: coverage report for smb2.twrp.listdir_fix f886ca1c Lines: 423 516 82.0 %
Date: 2023-11-07 19:11:32 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       28115 : 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       28115 :         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        1023 :                 *lm_sess_key = data_blob(NULL, 0);
     127        1023 :                 *user_sess_key = data_blob(NULL, 0);
     128        1023 :                 status = hash_password_check(mem_ctx, 
     129             :                                              false,
     130        1023 :                                              lpcfg_ntlm_auth(auth_context->lp_ctx),
     131             :                                              NULL,
     132        1023 :                                              user_info->password.hash.nt,
     133        1023 :                                              user_info->mapped.account_name,
     134             :                                              NULL, nt_pwd);
     135        1023 :                 NT_STATUS_NOT_OK_RETURN(status);
     136         683 :                 break;
     137             :                 
     138       27028 :         case AUTH_PASSWORD_RESPONSE:
     139       27028 :                 status = ntlm_password_check(mem_ctx, 
     140             :                                              false,
     141       27028 :                                              lpcfg_ntlm_auth(auth_context->lp_ctx),
     142       27028 :                                              user_info->logon_parameters, 
     143       27028 :                                              &auth_context->challenge.data, 
     144             :                                              &user_info->password.response.lanman, 
     145             :                                              &user_info->password.response.nt,
     146       27028 :                                              user_info->mapped.account_name,
     147       27028 :                                              user_info->client.account_name, 
     148       27028 :                                              user_info->client.domain_name, 
     149             :                                              NULL, nt_pwd,
     150             :                                              user_sess_key, lm_sess_key);
     151       27028 :                 NT_STATUS_NOT_OK_RETURN(status);
     152       21841 :                 break;
     153             :         }
     154             : 
     155       23927 :         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       26995 : 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       26995 :         int history_len = 0;
     309       26995 :         struct ldb_context *sam_ctx = auth_context->sam_ctx;
     310       26995 :         const char * const attrs[] = { "pwdHistoryLength", NULL };
     311        1404 :         struct ldb_message *dom_msg;
     312        1404 :         struct samr_Password *nt_pwd;
     313       26995 :         DATA_BLOB _aes_256_key = data_blob_null;
     314       26995 :         DATA_BLOB *aes_256_key = NULL;
     315       26995 :         krb5_data _salt = { .data = NULL, .length = 0 };
     316       26995 :         krb5_data *salt = NULL;
     317       26995 :         DATA_BLOB salt_data = data_blob_null;
     318       26995 :         struct smb_krb5_context *smb_krb5_context = NULL;
     319        1404 :         const struct ldb_val *sc_val;
     320       26995 :         uint32_t userAccountControl = 0;
     321       26995 :         uint32_t current_kvno = 0;
     322        1404 :         bool am_rodc;
     323             : 
     324       26995 :         tmp_ctx = talloc_new(mem_ctx);
     325       26995 :         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       26995 :         nt_status = samdb_result_passwords(tmp_ctx, auth_context->lp_ctx,
     338             :                                            msg, &nt_pwd);
     339       26995 :         if (!NT_STATUS_IS_OK(nt_status)) {
     340          50 :                 TALLOC_FREE(tmp_ctx);
     341          50 :                 return nt_status;
     342             :         }
     343             : 
     344       26945 :         userAccountControl = ldb_msg_find_attr_as_uint(msg,
     345             :                                                        "userAccountControl",
     346             :                                                        0);
     347             : 
     348       26945 :         sc_val = ldb_msg_find_ldb_val(msg, "supplementalCredentials");
     349             : 
     350       26945 :         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       26820 :         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       26820 :         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       26820 :         if (NT_STATUS_IS_OK(auth_status)) {
     428       23541 :                 if (user_sess_key->data) {
     429       22139 :                         talloc_steal(mem_ctx, user_sess_key->data);
     430             :                 }
     431       23541 :                 if (lm_sess_key->data) {
     432       20528 :                         talloc_steal(mem_ctx, lm_sess_key->data);
     433             :                 }
     434       23541 :                 TALLOC_FREE(tmp_ctx);
     435       23541 :                 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       23927 : 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       23927 :         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       23927 :         const struct authn_server_policy *authn_server_policy = NULL;
     747             : 
     748        1403 :         struct dom_sid_buf netlogon_trust_sid_buf;
     749       23927 :         const char *netlogon_trust_sid_str = NULL;
     750       23927 :         struct ldb_dn *netlogon_trust_dn = NULL;
     751       23927 :         struct ldb_message *netlogon_trust_msg = NULL;
     752             : 
     753        1403 :         int ret;
     754             : 
     755             :         /* Have we established a secure channel? */
     756       23927 :         if (user_info->netlogon_trust_account.secure_channel_type == SEC_CHAN_NULL) {
     757       12032 :                 return NT_STATUS_OK;
     758             :         }
     759             : 
     760       11895 :         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       11468 :         SMB_ASSERT(user_info->netlogon_trust_account.sid != NULL);
     769             : 
     770       11468 :         tmp_ctx = talloc_new(mem_ctx);
     771       11468 :         if (tmp_ctx == NULL) {
     772           0 :                 return NT_STATUS_NO_MEMORY;
     773             :         }
     774             : 
     775       11468 :         netlogon_trust_sid_str = dom_sid_str_buf(user_info->netlogon_trust_account.sid,
     776             :                                                  &netlogon_trust_sid_buf);
     777             : 
     778       11468 :         netlogon_trust_dn = ldb_dn_new_fmt(tmp_ctx, sam_ctx,
     779             :                                            "<SID=%s>",
     780             :                                            netlogon_trust_sid_str);
     781       11468 :         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       11468 :         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       11468 :         if (ret) {
     799           0 :                 talloc_free(tmp_ctx);
     800           0 :                 return dsdb_ldb_err_to_ntstatus(ret);
     801             :         }
     802             : 
     803       11468 :         ret = authn_policy_server(sam_ctx,
     804             :                                   tmp_ctx,
     805             :                                   netlogon_trust_msg,
     806             :                                   &authn_server_policy);
     807       11468 :         if (ret) {
     808           0 :                 talloc_free(tmp_ctx);
     809           0 :                 return NT_STATUS_INTERNAL_ERROR;
     810             :         }
     811             : 
     812       11468 :         if (authn_server_policy != NULL) {
     813          80 :                 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          80 :                 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          80 :                                                               (struct auth_claims) {},
     827             :                                                               authn_server_policy,
     828          80 :                                                               (struct authn_policy_flags) {},
     829             :                                                               &server_audit_info);
     830          80 :                 if (server_audit_info != NULL) {
     831          80 :                         *server_audit_info_out = talloc_move(mem_ctx, &server_audit_info);
     832             :                 }
     833          80 :                 if (!NT_STATUS_IS_OK(status)) {
     834          36 :                         talloc_free(tmp_ctx);
     835          36 :                         return status;
     836             :                 }
     837             :         }
     838             : 
     839       11432 :         return NT_STATUS_OK;
     840             : }
     841             : 
     842       27038 : static NTSTATUS authsam_authenticate(struct auth4_context *auth_context,
     843             :                                      TALLOC_CTX *mem_ctx,
     844             :                                      struct ldb_dn *domain_dn,
     845             :                                      struct ldb_message *msg,
     846             :                                      const struct auth_usersupplied_info *user_info,
     847             :                                      const struct auth_user_info_dc *user_info_dc,
     848             :                                      DATA_BLOB *user_sess_key, DATA_BLOB *lm_sess_key,
     849             :                                      struct authn_audit_info **client_audit_info_out,
     850             :                                      struct authn_audit_info **server_audit_info_out,
     851             :                                      bool *authoritative)
     852             : {
     853        1404 :         NTSTATUS nt_status;
     854        1404 :         int ret;
     855       27038 :         bool interactive = (user_info->password_state == AUTH_PASSWORD_HASH);
     856       27038 :         uint32_t acct_flags = samdb_result_acct_flags(msg, NULL);
     857       27038 :         struct netr_SendToSamBase *send_to_sam = NULL;
     858       27038 :         const struct authn_ntlm_client_policy *authn_client_policy = NULL;
     859       27038 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     860       27038 :         if (!tmp_ctx) {
     861           0 :                 return NT_STATUS_NO_MEMORY;
     862             :         }
     863             : 
     864             :         /* You can only do an interactive login to normal accounts */
     865       27038 :         if (user_info->flags & USER_INFO_INTERACTIVE_LOGON) {
     866         515 :                 if (!(acct_flags & ACB_NORMAL)) {
     867           5 :                         TALLOC_FREE(tmp_ctx);
     868           5 :                         return NT_STATUS_NO_SUCH_USER;
     869             :                 }
     870         510 :                 if (acct_flags & ACB_SMARTCARD_REQUIRED) {
     871           0 :                         if (acct_flags & ACB_DISABLED) {
     872           0 :                                 DEBUG(2,("authsam_authenticate: Account for user '%s' "
     873             :                                          "was disabled.\n",
     874             :                                          user_info->mapped.account_name));
     875           0 :                                 TALLOC_FREE(tmp_ctx);
     876           0 :                                 return NT_STATUS_ACCOUNT_DISABLED;
     877             :                         }
     878           0 :                         DEBUG(2,("authsam_authenticate: Account for user '%s' "
     879             :                                  "requires interactive smartcard logon.\n",
     880             :                                  user_info->mapped.account_name));
     881           0 :                         TALLOC_FREE(tmp_ctx);
     882           0 :                         return NT_STATUS_SMARTCARD_LOGON_REQUIRED;
     883             :                 }
     884             :         }
     885             : 
     886             :         /* See whether an authentication policy applies to the client. */
     887       27033 :         ret = authn_policy_ntlm_client(auth_context->sam_ctx,
     888             :                                        tmp_ctx,
     889             :                                        msg,
     890             :                                        &authn_client_policy);
     891       27033 :         if (ret) {
     892           0 :                 TALLOC_FREE(tmp_ctx);
     893           0 :                 return NT_STATUS_INTERNAL_ERROR;
     894             :         }
     895             : 
     896       27033 :         nt_status = authn_policy_ntlm_apply_device_restriction(mem_ctx,
     897             :                                                                authn_client_policy,
     898             :                                                                client_audit_info_out);
     899       27033 :         if (!NT_STATUS_IS_OK(nt_status)) {
     900             :                 /*
     901             :                  * As we didn’t get far enough to check the server policy, only
     902             :                  * the client policy will be referenced in the authentication
     903             :                  * log message.
     904             :                  */
     905          38 :                 TALLOC_FREE(tmp_ctx);
     906          38 :                 return nt_status;
     907             :         }
     908             : 
     909       26995 :         nt_status = authsam_password_check_and_record(auth_context, tmp_ctx,
     910             :                                                       domain_dn, msg,
     911             :                                                       user_info,
     912             :                                                       user_sess_key, lm_sess_key,
     913             :                                                       authoritative);
     914       26995 :         if (!NT_STATUS_IS_OK(nt_status)) {
     915        3068 :                 TALLOC_FREE(tmp_ctx);
     916        3068 :                 return nt_status;
     917             :         }
     918             : 
     919       23927 :         nt_status = authsam_check_netlogon_trust(mem_ctx,
     920             :                                                  auth_context->sam_ctx,
     921             :                                                  auth_context->lp_ctx,
     922             :                                                  user_info,
     923             :                                                  user_info_dc,
     924             :                                                  server_audit_info_out);
     925       23927 :         if (!NT_STATUS_IS_OK(nt_status)) {
     926          36 :                 TALLOC_FREE(tmp_ctx);
     927          36 :                 return nt_status;
     928             :         }
     929             : 
     930       25294 :         nt_status = authsam_account_ok(tmp_ctx, auth_context->sam_ctx,
     931       23891 :                                        user_info->logon_parameters,
     932             :                                        domain_dn,
     933             :                                        msg,
     934       23891 :                                        user_info->workstation_name,
     935       23891 :                                        user_info->mapped.account_name,
     936             :                                        false, false);
     937       23891 :         if (!NT_STATUS_IS_OK(nt_status)) {
     938         960 :                 TALLOC_FREE(tmp_ctx);
     939         960 :                 return nt_status;
     940             :         }
     941             : 
     942       22931 :         nt_status = authsam_logon_success_accounting(auth_context->sam_ctx,
     943             :                                                      msg, domain_dn,
     944             :                                                      interactive,
     945             :                                                      tmp_ctx,
     946             :                                                      &send_to_sam);
     947             : 
     948       22931 :         if (send_to_sam != NULL) {
     949           9 :                 auth_sam_trigger_zero_password(tmp_ctx,
     950             :                                                auth_context->msg_ctx,
     951             :                                                auth_context->event_ctx,
     952             :                                                send_to_sam);
     953             :         }
     954             : 
     955       22931 :         if (!NT_STATUS_IS_OK(nt_status)) {
     956           0 :                 TALLOC_FREE(tmp_ctx);
     957           0 :                 return nt_status;
     958             :         }
     959             : 
     960       22931 :         if (user_sess_key && user_sess_key->data) {
     961       21623 :                 talloc_steal(mem_ctx, user_sess_key->data);
     962             :         }
     963       22931 :         if (lm_sess_key && lm_sess_key->data) {
     964       20158 :                 talloc_steal(mem_ctx, lm_sess_key->data);
     965             :         }
     966             : 
     967       22931 :         TALLOC_FREE(tmp_ctx);
     968       22931 :         return nt_status;
     969             : }
     970             : 
     971             : 
     972             : 
     973       27778 : static NTSTATUS authsam_check_password_internals(struct auth_method_context *ctx,
     974             :                                                  TALLOC_CTX *mem_ctx,
     975             :                                                  const struct auth_usersupplied_info *user_info, 
     976             :                                                  struct auth_user_info_dc **user_info_dc,
     977             :                                                  struct authn_audit_info **client_audit_info_out,
     978             :                                                  struct authn_audit_info **server_audit_info_out,
     979             :                                                  bool *authoritative)
     980             : {
     981        1410 :         NTSTATUS nt_status;
     982        1410 :         int result;
     983       27778 :         const char *account_name = user_info->mapped.account_name;
     984        1410 :         struct ldb_message *msg;
     985        1410 :         struct ldb_dn *domain_dn;
     986        1410 :         DATA_BLOB user_sess_key, lm_sess_key;
     987        1410 :         TALLOC_CTX *tmp_ctx;
     988       27778 :         const char *p = NULL;
     989       27778 :         struct auth_user_info_dc *reparented = NULL;
     990       27778 :         struct authn_audit_info *client_audit_info = NULL;
     991       27778 :         struct authn_audit_info *server_audit_info = NULL;
     992             : 
     993       27778 :         if (ctx->auth_ctx->sam_ctx == NULL) {
     994           0 :                 DEBUG(0, ("No SAM available, cannot log in users\n"));
     995           0 :                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
     996             :         }
     997             : 
     998       27778 :         if (!account_name || !*account_name) {
     999             :                 /* 'not for me' */
    1000           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1001             :         }
    1002             : 
    1003       27778 :         tmp_ctx = talloc_new(mem_ctx);
    1004       27778 :         if (!tmp_ctx) {
    1005           0 :                 return NT_STATUS_NO_MEMORY;
    1006             :         }
    1007             : 
    1008       27778 :         domain_dn = ldb_get_default_basedn(ctx->auth_ctx->sam_ctx);
    1009       27778 :         if (domain_dn == NULL) {
    1010           0 :                 talloc_free(tmp_ctx);
    1011           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
    1012             :         }
    1013             : 
    1014             :         /*
    1015             :          * If we have not already mapped this user, then now is a good
    1016             :          * time to do so, before we look it up.  We used to do this
    1017             :          * earlier, but in a multi-forest environment we want to do
    1018             :          * this mapping at the final domain.
    1019             :          *
    1020             :          * However, on the flip side we may have already mapped the
    1021             :          * user if this was an LDAP simple bind, in which case we
    1022             :          * really, really want to get back to exactly the same account
    1023             :          * we got the DN for.
    1024             :          */
    1025       27778 :         if (!user_info->cracknames_called) {
    1026       27337 :                 p = strchr_m(account_name, '@');
    1027             :         } else {
    1028             :                 /*
    1029             :                  * This is slightly nicer than double-indenting the
    1030             :                  * block below
    1031             :                  */
    1032         441 :                 p = NULL;
    1033             :         }
    1034             : 
    1035       27778 :         if (p != NULL) {
    1036        7895 :                 const char *nt4_domain = NULL;
    1037        7895 :                 const char *nt4_account = NULL;
    1038        7895 :                 bool is_my_domain = false;
    1039             : 
    1040        8855 :                 nt_status = crack_name_to_nt4_name(mem_ctx,
    1041        7895 :                                                    ctx->auth_ctx->sam_ctx,
    1042             :                                                    /*
    1043             :                                                     * DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON ?
    1044             :                                                     */
    1045             :                                                    DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
    1046             :                                                    account_name,
    1047             :                                                    &nt4_domain, &nt4_account);
    1048        7895 :                 if (!NT_STATUS_IS_OK(nt_status)) {
    1049           0 :                         talloc_free(tmp_ctx);
    1050           0 :                         return NT_STATUS_NO_SUCH_USER;
    1051             :                 }
    1052             : 
    1053        7895 :                 is_my_domain = lpcfg_is_mydomain(ctx->auth_ctx->lp_ctx, nt4_domain);
    1054        7895 :                 if (!is_my_domain) {
    1055             :                         /*
    1056             :                          * This is a user within our forest,
    1057             :                          * but in a different domain,
    1058             :                          * we're not authoritative
    1059             :                          */
    1060           0 :                         talloc_free(tmp_ctx);
    1061           0 :                         return NT_STATUS_NOT_IMPLEMENTED;
    1062             :                 }
    1063             : 
    1064             :                 /*
    1065             :                  * Let's use the NT4 account name for the lookup.
    1066             :                  */
    1067        7895 :                 account_name = nt4_account;
    1068             :         }
    1069             : 
    1070       27778 :         nt_status = authsam_search_account(tmp_ctx, ctx->auth_ctx->sam_ctx, account_name, domain_dn, &msg);
    1071       27778 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1072         723 :                 talloc_free(tmp_ctx);
    1073         723 :                 return nt_status;
    1074             :         }
    1075             : 
    1076       27055 :         nt_status = authsam_make_user_info_dc(tmp_ctx, ctx->auth_ctx->sam_ctx,
    1077       27055 :                                              lpcfg_netbios_name(ctx->auth_ctx->lp_ctx),
    1078       27055 :                                              lpcfg_sam_name(ctx->auth_ctx->lp_ctx),
    1079       27055 :                                              lpcfg_sam_dnsname(ctx->auth_ctx->lp_ctx),
    1080             :                                              domain_dn,
    1081             :                                              msg,
    1082             :                                              data_blob_null, data_blob_null,
    1083             :                                              user_info_dc);
    1084       27055 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1085           0 :                 talloc_free(tmp_ctx);
    1086           0 :                 return nt_status;
    1087             :         }
    1088             : 
    1089       28459 :         result = dsdb_is_protected_user(ctx->auth_ctx->sam_ctx,
    1090       27055 :                                         (*user_info_dc)->sids,
    1091       27055 :                                         (*user_info_dc)->num_sids);
    1092             :         /*
    1093             :          * We also consider an error result (a negative value) as denying the
    1094             :          * authentication.
    1095             :          */
    1096       27055 :         if (result != 0) {
    1097          17 :                 talloc_free(tmp_ctx);
    1098          17 :                 return NT_STATUS_ACCOUNT_RESTRICTION;
    1099             :         }
    1100             : 
    1101       27038 :         nt_status = authsam_authenticate(ctx->auth_ctx,
    1102             :                                          tmp_ctx,
    1103             :                                          domain_dn,
    1104             :                                          msg,
    1105             :                                          user_info,
    1106             :                                          *user_info_dc,
    1107             :                                          &user_sess_key,
    1108             :                                          &lm_sess_key,
    1109             :                                          &client_audit_info,
    1110             :                                          &server_audit_info,
    1111             :                                          authoritative);
    1112       27038 :         if (client_audit_info != NULL) {
    1113         100 :                 *client_audit_info_out = talloc_move(mem_ctx, &client_audit_info);
    1114             :         }
    1115       27038 :         if (server_audit_info != NULL) {
    1116          80 :                 *server_audit_info_out = talloc_move(mem_ctx, &server_audit_info);
    1117             :         }
    1118       27038 :         if (!NT_STATUS_IS_OK(nt_status)) {
    1119        4107 :                 talloc_free(tmp_ctx);
    1120        4107 :                 return nt_status;
    1121             :         }
    1122             : 
    1123       22931 :         (*user_info_dc)->user_session_key = data_blob_talloc(*user_info_dc,
    1124             :                                                              user_sess_key.data,
    1125             :                                                              user_sess_key.length);
    1126       22931 :         if (user_sess_key.data) {
    1127       21623 :                 if ((*user_info_dc)->user_session_key.data == NULL) {
    1128           0 :                         TALLOC_FREE(tmp_ctx);
    1129           0 :                         return NT_STATUS_NO_MEMORY;
    1130             :                 }
    1131             :         }
    1132             : 
    1133       22931 :         (*user_info_dc)->lm_session_key = data_blob_talloc(*user_info_dc,
    1134             :                                                            lm_sess_key.data,
    1135             :                                                            lm_sess_key.length);
    1136       22931 :         if (lm_sess_key.data) {
    1137       20158 :                 if ((*user_info_dc)->lm_session_key.data == NULL) {
    1138           0 :                         TALLOC_FREE(tmp_ctx);
    1139           0 :                         return NT_STATUS_NO_MEMORY;
    1140             :                 }
    1141             :         }
    1142             : 
    1143             :         /*
    1144             :          * Release our handle to *user_info_dc. {client,server}_audit_info_out,
    1145             :          * if non-NULL, becomes the new parent.
    1146             :          */
    1147       22931 :         reparented = talloc_reparent(tmp_ctx, mem_ctx, *user_info_dc);
    1148       22931 :         if (reparented == NULL) {
    1149           0 :                 talloc_free(tmp_ctx);
    1150           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1151             :         }
    1152             : 
    1153       22931 :         talloc_free(tmp_ctx);
    1154             : 
    1155       22931 :         return NT_STATUS_OK;
    1156             : }
    1157             : 
    1158             : struct authsam_check_password_state {
    1159             :         struct auth_user_info_dc *user_info_dc;
    1160             :         struct authn_audit_info *client_audit_info;
    1161             :         struct authn_audit_info *server_audit_info;
    1162             :         bool authoritative;
    1163             : };
    1164             : 
    1165       27778 : static struct tevent_req *authsam_check_password_send(
    1166             :         TALLOC_CTX *mem_ctx,
    1167             :         struct tevent_context *ev,
    1168             :         struct auth_method_context *ctx,
    1169             :         const struct auth_usersupplied_info *user_info)
    1170             : {
    1171       27778 :         struct tevent_req *req = NULL;
    1172       27778 :         struct authsam_check_password_state *state = NULL;
    1173        1410 :         NTSTATUS status;
    1174             : 
    1175       27778 :         req = tevent_req_create(
    1176             :                 mem_ctx, &state, struct authsam_check_password_state);
    1177       27778 :         if (req == NULL) {
    1178           0 :                 return NULL;
    1179             :         }
    1180             :         /*
    1181             :          * authsam_check_password_internals() sets this to false in
    1182             :          * the rodc case, otherwise it leaves it untouched. Default to
    1183             :          * "we're authoritative".
    1184             :          */
    1185       27778 :         state->authoritative = true;
    1186             : 
    1187       27778 :         status = authsam_check_password_internals(
    1188             :                 ctx,
    1189             :                 state,
    1190             :                 user_info,
    1191       26368 :                 &state->user_info_dc,
    1192       26368 :                 &state->client_audit_info,
    1193       26368 :                 &state->server_audit_info,
    1194       26368 :                 &state->authoritative);
    1195       27778 :         if (tevent_req_nterror(req, status)) {
    1196        4847 :                 return tevent_req_post(req, ev);
    1197             :         }
    1198             : 
    1199       22931 :         tevent_req_done(req);
    1200       22931 :         return tevent_req_post(req, ev);
    1201             : }
    1202             : 
    1203       27778 : static NTSTATUS authsam_check_password_recv(
    1204             :         struct tevent_req *req,
    1205             :         TALLOC_CTX *mem_ctx,
    1206             :         struct auth_user_info_dc **interim_info,
    1207             :         const struct authn_audit_info **client_audit_info,
    1208             :         const struct authn_audit_info **server_audit_info,
    1209             :         bool *authoritative)
    1210             : {
    1211       27778 :         struct authsam_check_password_state *state = tevent_req_data(
    1212             :                 req, struct authsam_check_password_state);
    1213        1410 :         NTSTATUS status;
    1214             : 
    1215       27778 :         *authoritative = state->authoritative;
    1216             : 
    1217       27778 :         *client_audit_info = talloc_reparent(state, mem_ctx, state->client_audit_info);
    1218       27778 :         state->client_audit_info = NULL;
    1219             : 
    1220       27778 :         *server_audit_info = talloc_reparent(state, mem_ctx, state->server_audit_info);
    1221       27778 :         state->server_audit_info = NULL;
    1222             : 
    1223       27778 :         if (tevent_req_is_nterror(req, &status)) {
    1224        4847 :                 tevent_req_received(req);
    1225        4847 :                 return status;
    1226             :         }
    1227             :         /*
    1228             :          * Release our handle to state->user_info_dc.
    1229             :          * {client,server}_audit_info, if non-NULL, becomes the new parent.
    1230             :          */
    1231       22931 :         *interim_info = talloc_reparent(state, mem_ctx, state->user_info_dc);
    1232       22931 :         state->user_info_dc = NULL;
    1233             : 
    1234       22931 :         tevent_req_received(req);
    1235       22931 :         return NT_STATUS_OK;
    1236             : }
    1237             : 
    1238         703 : static NTSTATUS authsam_ignoredomain_want_check(struct auth_method_context *ctx,
    1239             :                                                 TALLOC_CTX *mem_ctx,
    1240             :                                                 const struct auth_usersupplied_info *user_info)
    1241             : {
    1242         703 :         if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
    1243          12 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1244             :         }
    1245             : 
    1246         691 :         return NT_STATUS_OK;
    1247             : }
    1248             : 
    1249             : /****************************************************************************
    1250             : Check SAM security (above) but with a few extra checks.
    1251             : ****************************************************************************/
    1252       28047 : static NTSTATUS authsam_want_check(struct auth_method_context *ctx,
    1253             :                                    TALLOC_CTX *mem_ctx,
    1254             :                                    const struct auth_usersupplied_info *user_info)
    1255             : {
    1256       28047 :         const char *effective_domain = user_info->mapped.domain_name;
    1257       28047 :         bool is_local_name = false;
    1258       28047 :         bool is_my_domain = false;
    1259       28047 :         const char *p = NULL;
    1260       28047 :         struct dsdb_trust_routing_table *trt = NULL;
    1261       28047 :         const struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
    1262        1410 :         NTSTATUS status;
    1263             : 
    1264       28047 :         if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
    1265          14 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1266             :         }
    1267             : 
    1268       28033 :         if (effective_domain == NULL) {
    1269        1644 :                 effective_domain = "";
    1270             :         }
    1271             : 
    1272       28033 :         is_local_name = lpcfg_is_myname(ctx->auth_ctx->lp_ctx,
    1273             :                                         effective_domain);
    1274             : 
    1275             :         /* check whether or not we service this domain/workgroup name */
    1276       28033 :         switch (lpcfg_server_role(ctx->auth_ctx->lp_ctx)) {
    1277           0 :         case ROLE_STANDALONE:
    1278         103 :                 return NT_STATUS_OK;
    1279             : 
    1280         103 :         case ROLE_DOMAIN_MEMBER:
    1281         103 :                 if (is_local_name) {
    1282          98 :                         return NT_STATUS_OK;
    1283             :                 }
    1284             : 
    1285           5 :                 DBG_DEBUG("%s is not one of my local names (DOMAIN_MEMBER)\n",
    1286             :                           effective_domain);
    1287           5 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1288             : 
    1289       26520 :         case ROLE_ACTIVE_DIRECTORY_DC:
    1290             :                 /* handled later */
    1291       27930 :                 break;
    1292             : 
    1293           0 :         default:
    1294           0 :                 DBG_ERR("lpcfg_server_role() has an undefined value\n");
    1295           0 :                 return NT_STATUS_INVALID_SERVER_STATE;
    1296             :         }
    1297             : 
    1298             :         /*
    1299             :          * Now we handle the AD DC case...
    1300             :          */
    1301             : 
    1302       27930 :         is_my_domain = lpcfg_is_my_domain_or_realm(ctx->auth_ctx->lp_ctx,
    1303             :                                                    effective_domain);
    1304       27930 :         if (is_my_domain) {
    1305       19161 :                 return NT_STATUS_OK;
    1306             :         }
    1307             : 
    1308        8769 :         if (user_info->cracknames_called) {
    1309             :                 /*
    1310             :                  * The caller already did a cracknames call.
    1311             :                  */
    1312           0 :                 DBG_DEBUG("%s is not own domain name (DC)\n",
    1313             :                           effective_domain);
    1314           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1315             :         }
    1316             : 
    1317        8769 :         if (!strequal(effective_domain, "")) {
    1318         908 :                 DBG_DEBUG("%s is not own domain name (DC)\n",
    1319             :                           effective_domain);
    1320         908 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1321             :         }
    1322             : 
    1323        7861 :         p = strchr_m(user_info->mapped.account_name, '@');
    1324        7861 :         if (p == NULL) {
    1325             :                 /*
    1326             :                  * An empty to domain name should be handled
    1327             :                  * as the local domain name.
    1328             :                  */
    1329           5 :                 return NT_STATUS_OK;
    1330             :         }
    1331             : 
    1332        7856 :         effective_domain = p + 1;
    1333        7856 :         is_my_domain = lpcfg_is_my_domain_or_realm(ctx->auth_ctx->lp_ctx,
    1334             :                                                    effective_domain);
    1335        7856 :         if (is_my_domain) {
    1336        7823 :                 return NT_STATUS_OK;
    1337             :         }
    1338             : 
    1339          33 :         if (strequal(effective_domain, "")) {
    1340           2 :                 DBG_DEBUG("authsam_check_password: upn without realm (DC)\n");
    1341           2 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1342             :         }
    1343             : 
    1344             :         /*
    1345             :          * as last option we check the routing table if the
    1346             :          * domain is within our forest.
    1347             :          */
    1348          31 :         status = dsdb_trust_routing_table_load(ctx->auth_ctx->sam_ctx,
    1349             :                                                mem_ctx, &trt);
    1350          31 :         if (!NT_STATUS_IS_OK(status)) {
    1351           0 :                 DBG_ERR("authsam_check_password: dsdb_trust_routing_table_load() %s\n",
    1352             :                          nt_errstr(status));
    1353           0 :                 return status;
    1354             :         }
    1355             : 
    1356          31 :         tdo = dsdb_trust_routing_by_name(trt, effective_domain);
    1357          31 :         if (tdo == NULL) {
    1358          18 :                 DBG_DEBUG("%s is not a known TLN (DC)\n",
    1359             :                           effective_domain);
    1360          18 :                 TALLOC_FREE(trt);
    1361          18 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1362             :         }
    1363             : 
    1364          13 :         if (!(tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST)) {
    1365          13 :                 DBG_DEBUG("%s is not a TLN in our forest (DC)\n",
    1366             :                           effective_domain);
    1367          13 :                 TALLOC_FREE(trt);
    1368          13 :                 return NT_STATUS_NOT_IMPLEMENTED;
    1369             :         }
    1370             : 
    1371             :         /*
    1372             :          * This principal is within our forest.
    1373             :          * we'll later do a crack_name_to_nt4_name()
    1374             :          * to check if it's in our domain.
    1375             :          */
    1376           0 :         TALLOC_FREE(trt);
    1377           0 :         return NT_STATUS_OK;
    1378             : }
    1379             : 
    1380             : static const struct auth_operations sam_ignoredomain_ops = {
    1381             :         .name                      = "sam_ignoredomain",
    1382             :         .want_check                = authsam_ignoredomain_want_check,
    1383             :         .check_password_send       = authsam_check_password_send,
    1384             :         .check_password_recv       = authsam_check_password_recv,
    1385             : };
    1386             : 
    1387             : static const struct auth_operations sam_ops = {
    1388             :         .name                      = "sam",
    1389             :         .want_check                = authsam_want_check,
    1390             :         .check_password_send       = authsam_check_password_send,
    1391             :         .check_password_recv       = authsam_check_password_recv,
    1392             : };
    1393             : 
    1394             : _PUBLIC_ NTSTATUS auth4_sam_init(TALLOC_CTX *);
    1395        9620 : _PUBLIC_ NTSTATUS auth4_sam_init(TALLOC_CTX *ctx)
    1396             : {
    1397         837 :         NTSTATUS ret;
    1398             : 
    1399        9620 :         ret = auth_register(ctx, &sam_ops);
    1400        9620 :         if (!NT_STATUS_IS_OK(ret)) {
    1401           0 :                 DEBUG(0,("Failed to register 'sam' auth backend!\n"));
    1402           0 :                 return ret;
    1403             :         }
    1404             : 
    1405        9620 :         ret = auth_register(ctx, &sam_ignoredomain_ops);
    1406        9620 :         if (!NT_STATUS_IS_OK(ret)) {
    1407           0 :                 DEBUG(0,("Failed to register 'sam_ignoredomain' auth backend!\n"));
    1408           0 :                 return ret;
    1409             :         }
    1410             : 
    1411        9620 :         return ret;
    1412             : }

Generated by: LCOV version 1.14