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

Generated by: LCOV version 1.13