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

Generated by: LCOV version 1.14