LCOV - code coverage report
Current view: top level - source3/auth - check_samsec.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 157 282 55.7 %
Date: 2024-06-13 04:01:37 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Password and authentication handling
       4             :    Copyright (C) Andrew Tridgell              1992-2000
       5             :    Copyright (C) Luke Kenneth Casson Leighton 1996-2000
       6             :    Copyright (C) Andrew Bartlett              2001-2003
       7             :    Copyright (C) Gerald Carter                2003
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "auth.h"
      25             : #include "../libcli/auth/libcli_auth.h"
      26             : #include "passdb.h"
      27             : #include "lib/util/memcache.h"
      28             : 
      29             : #undef DBGC_CLASS
      30             : #define DBGC_CLASS DBGC_AUTH
      31             : 
      32             : /****************************************************************************
      33             :  Do a specific test for an smb password being correct, given a smb_password and
      34             :  the lanman and NT responses.
      35             : ****************************************************************************/
      36             : 
      37         495 : static NTSTATUS sam_password_ok(TALLOC_CTX *mem_ctx,
      38             :                                 const char *username,
      39             :                                 uint32_t acct_ctrl,
      40             :                                 const DATA_BLOB *challenge,
      41             :                                 const uint8_t *lm_pw,
      42             :                                 const uint8_t *nt_pw,
      43             :                                 const struct auth_usersupplied_info *user_info,
      44             :                                 DATA_BLOB *user_sess_key,
      45             :                                 DATA_BLOB *lm_sess_key)
      46             : {
      47             :         NTSTATUS status;
      48             :         struct samr_Password _lm_hash, _nt_hash;
      49         495 :         struct samr_Password *lm_hash = NULL;
      50         495 :         struct samr_Password *nt_hash = NULL;
      51             : 
      52         495 :         *user_sess_key = data_blob_null;
      53         495 :         *lm_sess_key = data_blob_null;
      54             : 
      55         495 :         if (acct_ctrl & ACB_PWNOTREQ) {
      56           0 :                 if (lp_null_passwords()) {
      57           0 :                         DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", username));
      58           0 :                         return NT_STATUS_OK;
      59             :                 } else {
      60           0 :                         DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", username));
      61           0 :                         return NT_STATUS_LOGON_FAILURE;
      62             :                 }
      63             :         }
      64             : 
      65         495 :         if (lm_pw) {
      66          43 :                 memcpy(_lm_hash.hash, lm_pw, sizeof(_lm_hash.hash));
      67          43 :                 lm_hash = &_lm_hash;
      68             :         }
      69         495 :         if (nt_pw) {
      70         495 :                 memcpy(_nt_hash.hash, nt_pw, sizeof(_nt_hash.hash));
      71         495 :                 nt_hash = &_nt_hash;
      72             :         }
      73         495 :         switch (user_info->password_state) {
      74           0 :         case AUTH_PASSWORD_HASH:
      75           0 :                 status = hash_password_check(mem_ctx, lp_lanman_auth(),
      76           0 :                                              user_info->password.hash.lanman,
      77           0 :                                              user_info->password.hash.nt,
      78             :                                              username,
      79             :                                              lm_hash,
      80             :                                              nt_hash);
      81           0 :                 if (NT_STATUS_IS_OK(status)) {
      82           0 :                         if (nt_pw) {
      83           0 :                                 *user_sess_key = data_blob_talloc(mem_ctx, NULL, 16);
      84           0 :                                 if (!user_sess_key->data) {
      85           0 :                                         return NT_STATUS_NO_MEMORY;
      86             :                                 }
      87           0 :                                 SMBsesskeygen_ntv1(nt_pw, user_sess_key->data);
      88             :                         }
      89             :                 }
      90           0 :                 return status;
      91             : 
      92             :         /* Eventually we should test plaintext passwords in their own
      93             :          * function, not assuming the caller has done a
      94             :          * mapping */
      95         495 :         case AUTH_PASSWORD_PLAIN:
      96             :         case AUTH_PASSWORD_RESPONSE:
      97         770 :                 return ntlm_password_check(mem_ctx, lp_lanman_auth(),
      98         495 :                                            lp_ntlm_auth(),
      99         220 :                                            user_info->logon_parameters,
     100             :                                            challenge,
     101             :                                            &user_info->password.response.lanman, &user_info->password.response.nt,
     102             :                                            username,
     103         220 :                                            user_info->client.account_name,
     104         220 :                                            user_info->client.domain_name,
     105             :                                            lm_hash,
     106             :                                            nt_hash,
     107             :                                            user_sess_key, lm_sess_key);
     108           0 :         default:
     109           0 :                 DEBUG(0,("user_info constructed for user '%s' was invalid - password_state=%u invalid.\n", username, user_info->password_state));
     110           0 :                 return NT_STATUS_INTERNAL_ERROR;
     111             :         }
     112             : }
     113             : 
     114             : /****************************************************************************
     115             :  Check if a user is allowed to logon at this time. Note this is the
     116             :  servers local time, as logon hours are just specified as a weekly
     117             :  bitmask.
     118             : ****************************************************************************/
     119             : 
     120         457 : static bool logon_hours_ok(struct samu *sampass)
     121             : {
     122             :         /* In logon hours first bit is Sunday from 12AM to 1AM */
     123             :         const uint8_t *hours;
     124             :         struct tm *utctime;
     125             :         time_t lasttime;
     126             :         const char *asct;
     127             :         uint8_t bitmask, bitpos;
     128             : 
     129         457 :         hours = pdb_get_hours(sampass);
     130         457 :         if (!hours) {
     131           0 :                 DEBUG(5,("logon_hours_ok: No hours restrictions for user %s\n",pdb_get_username(sampass)));
     132           0 :                 return True;
     133             :         }
     134             : 
     135         457 :         lasttime = time(NULL);
     136         457 :         utctime = gmtime(&lasttime);
     137         457 :         if (!utctime) {
     138           0 :                 DEBUG(1, ("logon_hours_ok: failed to get gmtime. Failing logon for user %s\n",
     139             :                         pdb_get_username(sampass) ));
     140           0 :                 return False;
     141             :         }
     142             : 
     143             :         /* find the corresponding byte and bit */
     144         457 :         bitpos = (utctime->tm_wday * 24 + utctime->tm_hour) % 168;
     145         457 :         bitmask = 1 << (bitpos % 8);
     146             : 
     147         457 :         if (! (hours[bitpos/8] & bitmask)) {
     148           0 :                 struct tm *t = localtime(&lasttime);
     149           0 :                 if (!t) {
     150           0 :                         asct = "INVALID TIME";
     151             :                 } else {
     152           0 :                         asct = asctime(t);
     153           0 :                         if (!asct) {
     154           0 :                                 asct = "INVALID TIME";
     155             :                         }
     156             :                 }
     157             : 
     158           0 :                 DEBUG(1, ("logon_hours_ok: Account for user %s not allowed to "
     159             :                           "logon at this time (%s).\n",
     160             :                           pdb_get_username(sampass), asct ));
     161           0 :                 return False;
     162             :         }
     163             : 
     164         457 :         asct = asctime(utctime);
     165         457 :         DEBUG(5,("logon_hours_ok: user %s allowed to logon at this time (%s)\n",
     166             :                 pdb_get_username(sampass), asct ? asct : "UNKNOWN TIME" ));
     167             : 
     168         457 :         return True;
     169             : }
     170             : 
     171             : /****************************************************************************
     172             :  Do a specific test for a struct samu being valid for this connection
     173             :  (ie not disabled, expired and the like).
     174             : ****************************************************************************/
     175             : 
     176         457 : static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx,
     177             :                                struct samu *sampass,
     178             :                                const struct auth_usersupplied_info *user_info)
     179             : {
     180         457 :         uint32_t acct_ctrl = pdb_get_acct_ctrl(sampass);
     181             :         char *workstation_list;
     182             :         time_t kickoff_time;
     183             : 
     184         457 :         DEBUG(4,("sam_account_ok: Checking SMB password for user %s\n",pdb_get_username(sampass)));
     185             : 
     186             :         /* Quit if the account was disabled. */
     187         457 :         if (acct_ctrl & ACB_DISABLED) {
     188           0 :                 DEBUG(1,("sam_account_ok: Account for user '%s' was disabled.\n", pdb_get_username(sampass)));
     189           0 :                 return NT_STATUS_ACCOUNT_DISABLED;
     190             :         }
     191             : 
     192             :         /* Quit if the account was locked out. */
     193         457 :         if (acct_ctrl & ACB_AUTOLOCK) {
     194           0 :                 DEBUG(1,("sam_account_ok: Account for user %s was locked out.\n", pdb_get_username(sampass)));
     195           0 :                 return NT_STATUS_ACCOUNT_LOCKED_OUT;
     196             :         }
     197             : 
     198             :         /* Quit if the account is not allowed to logon at this time. */
     199         457 :         if (! logon_hours_ok(sampass)) {
     200           0 :                 return NT_STATUS_INVALID_LOGON_HOURS;
     201             :         }
     202             : 
     203             :         /* Test account expire time */
     204             : 
     205         457 :         kickoff_time = pdb_get_kickoff_time(sampass);
     206         457 :         if (kickoff_time != 0 && time(NULL) > kickoff_time) {
     207           0 :                 DEBUG(1,("sam_account_ok: Account for user '%s' has expired.\n", pdb_get_username(sampass)));
     208           0 :                 DEBUG(3,("sam_account_ok: Account expired at '%ld' unix time.\n", (long)kickoff_time));
     209           0 :                 return NT_STATUS_ACCOUNT_EXPIRED;
     210             :         }
     211             : 
     212         457 :         if (!(pdb_get_acct_ctrl(sampass) & ACB_PWNOEXP) && !(pdb_get_acct_ctrl(sampass) & ACB_PWNOTREQ)) {
     213         454 :                 time_t must_change_time = pdb_get_pass_must_change_time(sampass);
     214         454 :                 time_t last_set_time = pdb_get_pass_last_set_time(sampass);
     215             : 
     216             :                 /* check for immediate expiry "must change at next logon"
     217             :                  * for a user account. */
     218         454 :                 if (((acct_ctrl & (ACB_WSTRUST|ACB_SVRTRUST)) == 0) && (last_set_time == 0)) {
     219           0 :                         DEBUG(1,("sam_account_ok: Account for user '%s' password must change!\n", pdb_get_username(sampass)));
     220           0 :                         return NT_STATUS_PASSWORD_MUST_CHANGE;
     221             :                 }
     222             : 
     223             :                 /* check for expired password */
     224         454 :                 if (must_change_time < time(NULL) && must_change_time != 0) {
     225           0 :                         DEBUG(1,("sam_account_ok: Account for user '%s' password expired!\n", pdb_get_username(sampass)));
     226           0 :                         DEBUG(1,("sam_account_ok: Password expired at '%s' (%ld) unix time.\n", http_timestring(talloc_tos(), must_change_time), (long)must_change_time));
     227           0 :                         return NT_STATUS_PASSWORD_EXPIRED;
     228             :                 }
     229             :         }
     230             : 
     231             :         /* Test workstation. Workstation list is comma separated. */
     232             : 
     233         457 :         workstation_list = talloc_strdup(mem_ctx, pdb_get_workstations(sampass));
     234         457 :         if (!workstation_list)
     235           0 :                 return NT_STATUS_NO_MEMORY;
     236             : 
     237         457 :         if (*workstation_list) {
     238           0 :                 bool invalid_ws = True;
     239           0 :                 char *tok = NULL;
     240           0 :                 const char *s = workstation_list;
     241           0 :                 char *machine_name = talloc_asprintf(mem_ctx, "%s$", user_info->workstation_name);
     242             : 
     243           0 :                 if (machine_name == NULL)
     244           0 :                         return NT_STATUS_NO_MEMORY;
     245             : 
     246           0 :                 while (next_token_talloc(mem_ctx, &s, &tok, ",")) {
     247           0 :                         DEBUG(10,("sam_account_ok: checking for workstation match %s and %s\n",
     248             :                                   tok, user_info->workstation_name));
     249           0 :                         if(strequal(tok, user_info->workstation_name)) {
     250           0 :                                 invalid_ws = False;
     251           0 :                                 break;
     252             :                         }
     253           0 :                         if (tok[0] == '+') {
     254           0 :                                 DEBUG(10,("sam_account_ok: checking for workstation %s in group: %s\n",
     255             :                                         machine_name, tok + 1));
     256           0 :                                 if (user_in_group(machine_name, tok + 1)) {
     257           0 :                                         invalid_ws = False;
     258           0 :                                         break;
     259             :                                 }
     260             :                         }
     261           0 :                         TALLOC_FREE(tok);
     262             :                 }
     263           0 :                 TALLOC_FREE(tok);
     264           0 :                 TALLOC_FREE(machine_name);
     265             : 
     266           0 :                 if (invalid_ws)
     267           0 :                         return NT_STATUS_INVALID_WORKSTATION;
     268             :         }
     269             : 
     270         457 :         if (acct_ctrl & ACB_DOMTRUST) {
     271           0 :                 DEBUG(2,("sam_account_ok: Domain trust account %s denied by server\n", pdb_get_username(sampass)));
     272           0 :                 return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT;
     273             :         }
     274             : 
     275         457 :         if (acct_ctrl & ACB_SVRTRUST) {
     276           0 :                 if (!(user_info->logon_parameters & MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT)) {
     277           0 :                         DEBUG(2,("sam_account_ok: Server trust account %s denied by server\n", pdb_get_username(sampass)));
     278           0 :                         return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT;
     279             :                 }
     280             :         }
     281             : 
     282         457 :         if (acct_ctrl & ACB_WSTRUST) {
     283           3 :                 if (!(user_info->logon_parameters & MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT)) {
     284           0 :                         DEBUG(2,("sam_account_ok: Wksta trust account %s denied by server\n", pdb_get_username(sampass)));
     285           0 :                         return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
     286             :                 }
     287             :         }
     288         457 :         return NT_STATUS_OK;
     289             : }
     290             : 
     291             : /**
     292             :  * Check whether the given password is one of the last two
     293             :  * password history entries. If so, the bad pwcount should
     294             :  * not be incremented even though the actual password check
     295             :  * failed.
     296             :  */
     297          36 : static bool need_to_increment_bad_pw_count(
     298             :         const DATA_BLOB *challenge,
     299             :         struct samu* sampass,
     300             :         const struct auth_usersupplied_info *user_info)
     301             : {
     302             :         uint8_t i;
     303             :         const uint8_t *pwhistory;
     304             :         uint32_t pwhistory_len;
     305             :         uint32_t policy_pwhistory_len;
     306             :         uint32_t acct_ctrl;
     307             :         const char *username;
     308          36 :         TALLOC_CTX *mem_ctx = talloc_stackframe();
     309          36 :         bool result = true;
     310             : 
     311          36 :         pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY,
     312             :                                &policy_pwhistory_len);
     313          36 :         if (policy_pwhistory_len == 0) {
     314          36 :                 goto done;
     315             :         }
     316             : 
     317           0 :         pwhistory = pdb_get_pw_history(sampass, &pwhistory_len);
     318           0 :         if (!pwhistory || pwhistory_len == 0) {
     319           0 :                 goto done;
     320             :         }
     321             : 
     322           0 :         acct_ctrl = pdb_get_acct_ctrl(sampass);
     323           0 :         username = pdb_get_username(sampass);
     324             : 
     325           0 :         for (i=1; i < MIN(MIN(3, policy_pwhistory_len), pwhistory_len); i++) {
     326             :                 const uint8_t *salt;
     327             :                 const uint8_t *nt_pw;
     328             :                 NTSTATUS status;
     329           0 :                 DATA_BLOB user_sess_key = data_blob_null;
     330           0 :                 DATA_BLOB lm_sess_key = data_blob_null;
     331             : 
     332           0 :                 salt = &pwhistory[i*PW_HISTORY_ENTRY_LEN];
     333           0 :                 nt_pw = salt + PW_HISTORY_SALT_LEN;
     334             : 
     335           0 :                 if (all_zero(nt_pw, NT_HASH_LEN)) {
     336             :                         /* skip zero password hash */
     337           0 :                         continue;
     338             :                 }
     339             : 
     340           0 :                 if (!all_zero(salt, PW_HISTORY_SALT_LEN)) {
     341             :                         /* skip nonzero salt (old format entry) */
     342           0 :                         continue;
     343             :                 }
     344             : 
     345           0 :                 status = sam_password_ok(mem_ctx,
     346             :                                          username, acct_ctrl,
     347             :                                          challenge,
     348             :                                          NULL, nt_pw,
     349             :                                          user_info, &user_sess_key, &lm_sess_key);
     350           0 :                 if (NT_STATUS_IS_OK(status)) {
     351           0 :                         result = false;
     352           0 :                         break;
     353             :                 }
     354             :         }
     355             : 
     356           0 : done:
     357          36 :         TALLOC_FREE(mem_ctx);
     358          36 :         return result;
     359             : }
     360             : 
     361             : /****************************************************************************
     362             : check if a username/password is OK assuming the password is a 24 byte
     363             : SMB hash supplied in the user_info structure
     364             : return an NT_STATUS constant.
     365             : ****************************************************************************/
     366             : 
     367         547 : NTSTATUS check_sam_security(const DATA_BLOB *challenge,
     368             :                             TALLOC_CTX *mem_ctx,
     369             :                             const struct auth_usersupplied_info *user_info,
     370             :                             struct auth_serversupplied_info **server_info)
     371             : {
     372         547 :         struct samu *sampass=NULL;
     373             :         bool ret;
     374             :         NTSTATUS nt_status;
     375             :         NTSTATUS update_login_attempts_status;
     376         547 :         DATA_BLOB user_sess_key = data_blob_null;
     377         547 :         DATA_BLOB lm_sess_key = data_blob_null;
     378         547 :         bool updated_badpw = False;
     379             :         const char *username;
     380             :         const uint8_t *nt_pw;
     381             :         const uint8_t *lm_pw;
     382             :         uint32_t acct_ctrl;
     383         547 :         char *mutex_name_by_user = NULL;
     384         547 :         struct named_mutex *mtx = NULL;
     385             : 
     386             :         /* the returned struct gets kept on the server_info, by means
     387             :            of a steal further down */
     388             : 
     389         547 :         sampass = samu_new(mem_ctx);
     390         547 :         if (sampass == NULL) {
     391           0 :                 return NT_STATUS_NO_MEMORY;
     392             :         }
     393             : 
     394             :         /* get the account information */
     395             : 
     396         547 :         become_root();
     397         547 :         ret = pdb_getsampwnam(sampass, user_info->mapped.account_name);
     398         547 :         unbecome_root();
     399             : 
     400         547 :         if (!ret) {
     401          52 :                 DEBUG(3,("check_sam_security: Couldn't find user '%s' in "
     402             :                          "passdb.\n", user_info->mapped.account_name));
     403          52 :                 TALLOC_FREE(sampass);
     404          52 :                 return NT_STATUS_NO_SUCH_USER;
     405             :         }
     406             : 
     407         495 :         acct_ctrl = pdb_get_acct_ctrl(sampass);
     408         495 :         username = pdb_get_username(sampass);
     409         495 :         nt_pw = pdb_get_nt_passwd(sampass);
     410         495 :         lm_pw = pdb_get_lanman_passwd(sampass);
     411             : 
     412             :         /* Quit if the account was locked out. */
     413         495 :         if (acct_ctrl & ACB_AUTOLOCK) {
     414           0 :                 DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", username));
     415           0 :                 TALLOC_FREE(sampass);
     416           0 :                 return NT_STATUS_ACCOUNT_LOCKED_OUT;
     417             :         }
     418             : 
     419         495 :         nt_status = sam_password_ok(mem_ctx,
     420             :                                     username, acct_ctrl,
     421             :                                     challenge, lm_pw, nt_pw,
     422             :                                     user_info, &user_sess_key, &lm_sess_key);
     423             : 
     424             :         /*
     425             :          * We must re-load the sam acount information under a mutex
     426             :          * lock to ensure we don't miss any concurrent account lockout
     427             :          * changes.
     428             :          */
     429             : 
     430             :         /* Clear out old sampass info. */
     431         495 :         TALLOC_FREE(sampass);
     432         495 :         acct_ctrl = 0;
     433         495 :         username = NULL;
     434         495 :         nt_pw = NULL;
     435         495 :         lm_pw = NULL;
     436             : 
     437         495 :         sampass = samu_new(mem_ctx);
     438         495 :         if (sampass == NULL) {
     439           0 :                 return NT_STATUS_NO_MEMORY;
     440             :         }
     441             : 
     442         495 :         mutex_name_by_user = talloc_asprintf(mem_ctx,
     443             :                                              "check_sam_security_mutex_%s",
     444         220 :                                              user_info->mapped.account_name);
     445         495 :         if (mutex_name_by_user == NULL) {
     446           0 :                 nt_status = NT_STATUS_NO_MEMORY;
     447           0 :                 goto done;
     448             :         }
     449             : 
     450             :         /* Grab the named mutex under root with 30 second timeout. */
     451         495 :         become_root();
     452         495 :         mtx = grab_named_mutex(mem_ctx, mutex_name_by_user, 30);
     453         495 :         if (mtx != NULL) {
     454             :                 /* Re-load the account information if we got the mutex. */
     455         495 :                 ret = pdb_getsampwnam(sampass, user_info->mapped.account_name);
     456             :         }
     457         495 :         unbecome_root();
     458             : 
     459             :         /* Everything from here on until mtx is freed is done under the mutex.*/
     460             : 
     461         495 :         if (mtx == NULL) {
     462           0 :                 DBG_ERR("Acquisition of mutex %s failed "
     463             :                         "for user %s\n",
     464             :                         mutex_name_by_user,
     465             :                         user_info->mapped.account_name);
     466           0 :                 nt_status = NT_STATUS_INTERNAL_ERROR;
     467           0 :                 goto done;
     468             :         }
     469             : 
     470         495 :         if (!ret) {
     471             :                 /*
     472             :                  * Re-load of account failed. This could only happen if the
     473             :                  * user was deleted in the meantime.
     474             :                  */
     475           0 :                 DBG_NOTICE("reload of user '%s' in passdb failed.\n",
     476             :                            user_info->mapped.account_name);
     477           0 :                 nt_status = NT_STATUS_NO_SUCH_USER;
     478           0 :                 goto done;
     479             :         }
     480             : 
     481             :         /* Re-load the account control info. */
     482         495 :         acct_ctrl = pdb_get_acct_ctrl(sampass);
     483         495 :         username = pdb_get_username(sampass);
     484             : 
     485             :         /*
     486             :          * Check if the account is now locked out - now under the mutex.
     487             :          * This can happen if the server is under
     488             :          * a password guess attack and the ACB_AUTOLOCK is set by
     489             :          * another process.
     490             :          */
     491         495 :         if (acct_ctrl & ACB_AUTOLOCK) {
     492           0 :                 DBG_NOTICE("Account for user %s was locked out.\n", username);
     493           0 :                 nt_status = NT_STATUS_ACCOUNT_LOCKED_OUT;
     494           0 :                 goto done;
     495             :         }
     496             : 
     497             :         /* Notify passdb backend of login success/failure. If not
     498             :            NT_STATUS_OK the backend doesn't like the login */
     499             : 
     500         495 :         update_login_attempts_status = pdb_update_login_attempts(sampass, NT_STATUS_IS_OK(nt_status));
     501             : 
     502         495 :         if (!NT_STATUS_IS_OK(nt_status)) {
     503          38 :                 bool increment_bad_pw_count = false;
     504             : 
     505          56 :                 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_WRONG_PASSWORD) &&
     506          54 :                     (acct_ctrl & ACB_NORMAL) &&
     507          36 :                     NT_STATUS_IS_OK(update_login_attempts_status))
     508             :                 {
     509          18 :                         increment_bad_pw_count =
     510          18 :                                 need_to_increment_bad_pw_count(
     511             :                                         challenge, sampass, user_info);
     512             :                 }
     513             : 
     514          38 :                 if (increment_bad_pw_count) {
     515          36 :                         pdb_increment_bad_password_count(sampass);
     516          36 :                         updated_badpw = True;
     517             :                 } else {
     518           2 :                         pdb_update_bad_password_count(sampass,
     519             :                                                       &updated_badpw);
     520             :                 }
     521          38 :                 if (updated_badpw){
     522             :                         NTSTATUS status;
     523             : 
     524          36 :                         become_root();
     525          36 :                         status = pdb_update_sam_account(sampass);
     526          36 :                         unbecome_root();
     527             : 
     528          36 :                         if (!NT_STATUS_IS_OK(status)) {
     529           0 :                                 DEBUG(1, ("Failed to modify entry: %s\n",
     530             :                                           nt_errstr(status)));
     531             :                         }
     532             :                 }
     533          38 :                 goto done;
     534             :         }
     535             : 
     536             :         /*
     537             :          * We must only reset the bad password count if the login was
     538             :          * successful, including checking account policies
     539             :          */
     540         457 :         nt_status = sam_account_ok(mem_ctx, sampass, user_info);
     541         457 :         if (!NT_STATUS_IS_OK(nt_status)) {
     542           0 :                 goto done;
     543             :         }
     544             : 
     545         911 :         if ((acct_ctrl & ACB_NORMAL) &&
     546         454 :             (pdb_get_bad_password_count(sampass) > 0)){
     547             :                 NTSTATUS status;
     548             : 
     549           0 :                 pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
     550           0 :                 pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
     551             : 
     552           0 :                 become_root();
     553           0 :                 status = pdb_update_sam_account(sampass);
     554           0 :                 unbecome_root();
     555             : 
     556           0 :                 if (!NT_STATUS_IS_OK(status)) {
     557           0 :                         DEBUG(1, ("Failed to modify entry: %s\n",
     558             :                                   nt_errstr(status)));
     559             :                 }
     560             :         }
     561             : 
     562         457 :         become_root();
     563         457 :         nt_status = make_server_info_sam(mem_ctx, sampass, server_info);
     564         457 :         unbecome_root();
     565             : 
     566         457 :         if (!NT_STATUS_IS_OK(nt_status)) {
     567           0 :                 DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status)));
     568           0 :                 goto done;
     569             :         }
     570             : 
     571         457 :         (*server_info)->session_key =
     572         457 :                 data_blob_talloc(*server_info, user_sess_key.data,
     573             :                                  user_sess_key.length);
     574         457 :         data_blob_free(&user_sess_key);
     575             : 
     576         457 :         (*server_info)->lm_session_key =
     577         457 :                 data_blob_talloc(*server_info, lm_sess_key.data,
     578             :                                  lm_sess_key.length);
     579         457 :         data_blob_free(&lm_sess_key);
     580             : 
     581         457 :         (*server_info)->nss_token |= user_info->was_mapped;
     582             : 
     583         495 : done:
     584             :         /*
     585             :          * Always flush the getpwsid cache or this will grow indefinetly for
     586             :          * each NTLM auththentication.
     587             :          */
     588         495 :         memcache_flush(NULL, PDB_GETPWSID_CACHE);
     589         495 :         TALLOC_FREE(sampass);
     590         495 :         data_blob_free(&user_sess_key);
     591         495 :         data_blob_free(&lm_sess_key);
     592         495 :         TALLOC_FREE(mutex_name_by_user);
     593         495 :         TALLOC_FREE(mtx);
     594         495 :         return nt_status;
     595             : }
     596             : 
     597             : /* This helper function for winbindd returns a very similar value to
     598             :  * what a NETLOGON call would give, without the indirection */
     599           1 : NTSTATUS check_sam_security_info3(const DATA_BLOB *challenge,
     600             :                                   TALLOC_CTX *mem_ctx,
     601             :                                   const struct auth_usersupplied_info *user_info,
     602             :                                   struct netr_SamInfo3 **pinfo3)
     603             : {
     604           1 :         struct auth_serversupplied_info *server_info = NULL;
     605             :         struct netr_SamInfo3 *info3;
     606             :         NTSTATUS status;
     607           1 :         TALLOC_CTX *frame = talloc_stackframe();
     608             : 
     609           1 :         status = check_sam_security(challenge, talloc_tos(), user_info,
     610             :                                     &server_info);
     611           1 :         if (!NT_STATUS_IS_OK(status)) {
     612           0 :                 DEBUG(10, ("check_sam_security failed: %s\n",
     613             :                            nt_errstr(status)));
     614           0 :                 goto done;
     615             :         }
     616             : 
     617           1 :         info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
     618           1 :         if (info3 == NULL) {
     619           0 :                 status = NT_STATUS_NO_MEMORY;
     620           0 :                 goto done;
     621             :         }
     622             : 
     623           1 :         status = serverinfo_to_SamInfo3(server_info, info3);
     624           1 :         if (!NT_STATUS_IS_OK(status)) {
     625           0 :                 DEBUG(10, ("serverinfo_to_SamInfo3 failed: %s\n",
     626             :                            nt_errstr(status)));
     627           0 :                 goto done;
     628             :         }
     629           1 :         *pinfo3 = info3;
     630           1 :         status =  NT_STATUS_OK;
     631           1 : done:
     632           1 :         TALLOC_FREE(frame);
     633           1 :         return status;
     634             : }

Generated by: LCOV version 1.13