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

Generated by: LCOV version 1.14