LCOV - code coverage report
Current view: top level - source3/libsmb - trusts_util.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 128 268 47.8 %
Date: 2021-09-23 10:06:22 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  Routines to operate on various trust relationships
       4             :  *  Copyright (C) Andrew Bartlett                   2001
       5             :  *  Copyright (C) Rafal Szczesniak                  2003
       6             :  *
       7             :  *  This program is free software; you can redistribute it and/or modify
       8             :  *  it under the terms of the GNU General Public License as published by
       9             :  *  the Free Software Foundation; either version 3 of the License, or
      10             :  *  (at your option) any later version.
      11             :  *  
      12             :  *  This program is distributed in the hope that it will be useful,
      13             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  *  GNU General Public License for more details.
      16             :  *  
      17             :  *  You should have received a copy of the GNU General Public License
      18             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include "includes.h"
      22             : #include "../libcli/auth/libcli_auth.h"
      23             : #include "../libcli/auth/netlogon_creds_cli.h"
      24             : #include "rpc_client/cli_netlogon.h"
      25             : #include "rpc_client/cli_pipe.h"
      26             : #include "../librpc/gen_ndr/ndr_netlogon.h"
      27             : #include "librpc/gen_ndr/secrets.h"
      28             : #include "secrets.h"
      29             : #include "passdb.h"
      30             : #include "libsmb/libsmb.h"
      31             : #include "source3/include/messages.h"
      32             : #include "source3/include/g_lock.h"
      33             : #include "lib/util/util_tdb.h"
      34             : 
      35             : /*********************************************************
      36             :  Change the domain password on the PDC.
      37             :  Do most of the legwork ourselfs.  Caller must have
      38             :  already setup the connection to the NETLOGON pipe
      39             : **********************************************************/
      40             : 
      41             : struct trust_pw_change_state {
      42             :         struct g_lock_ctx *g_ctx;
      43             :         char *g_lock_key;
      44             : };
      45             : 
      46           6 : static int trust_pw_change_state_destructor(struct trust_pw_change_state *state)
      47             : {
      48           6 :         g_lock_unlock(state->g_ctx,
      49           6 :                       string_term_tdb_data(state->g_lock_key));
      50           6 :         return 0;
      51             : }
      52             : 
      53          64 : char *trust_pw_new_value(TALLOC_CTX *mem_ctx,
      54             :                          enum netr_SchannelType sec_channel_type,
      55             :                          int security)
      56             : {
      57             :         /*
      58             :          * use secure defaults.
      59             :          */
      60          64 :         size_t min = 128;
      61          64 :         size_t max = 255;
      62             : 
      63          64 :         switch (sec_channel_type) {
      64          64 :         case SEC_CHAN_WKSTA:
      65             :         case SEC_CHAN_BDC:
      66          64 :                 if (security == SEC_DOMAIN) {
      67             :                         /*
      68             :                          * The maximum length of a trust account password.
      69             :                          * Used when we randomly create it, 15 char passwords
      70             :                          * exceed NT4's max password length.
      71             :                          */
      72          18 :                         min = 14;
      73          18 :                         max = 14;
      74             :                 }
      75          64 :                 break;
      76           0 :         case SEC_CHAN_DNS_DOMAIN:
      77             :                 /*
      78             :                  * new_len * 2 = 498 bytes is the largest possible length
      79             :                  * NL_PASSWORD_VERSION consumes the rest of the possible 512 bytes
      80             :                  * and a confounder with at least 2 bytes is required.
      81             :                  *
      82             :                  * Windows uses new_len = 120 => 240 bytes (utf16)
      83             :                  */
      84           0 :                 min = 120;
      85           0 :                 max = 120;
      86           0 :                 break;
      87           0 :         case SEC_CHAN_DOMAIN:
      88             :                 /*
      89             :                  * The maximum length of a trust account password.
      90             :                  * Used when we randomly create it, 15 char passwords
      91             :                  * exceed NT4's max password length.
      92             :                  */
      93           0 :                 min = 14;
      94           0 :                 max = 14;
      95           0 :                 break;
      96           0 :         default:
      97           0 :                 break;
      98             :         }
      99             : 
     100             :         /*
     101             :          * Create a random machine account password
     102             :          * We create a random buffer and convert that to utf8.
     103             :          * This is similar to what windows is doing.
     104             :          */
     105          64 :         return generate_random_machine_password(mem_ctx, min, max);
     106             : }
     107             : 
     108             : /*
     109             :  * Temporary function to wrap cli_auth in a lck
     110             :  */
     111             : 
     112          12 : static NTSTATUS netlogon_creds_cli_lck_auth(
     113             :         struct netlogon_creds_cli_context *context,
     114             :         struct dcerpc_binding_handle *b,
     115             :         uint8_t num_nt_hashes,
     116             :         const struct samr_Password * const *nt_hashes,
     117             :         uint8_t *idx_nt_hashes)
     118             : {
     119             :         struct netlogon_creds_cli_lck *lck;
     120             :         NTSTATUS status;
     121             : 
     122          12 :         status = netlogon_creds_cli_lck(
     123             :                 context, NETLOGON_CREDS_CLI_LCK_EXCLUSIVE,
     124             :                 talloc_tos(), &lck);
     125          12 :         if (!NT_STATUS_IS_OK(status)) {
     126           0 :                 DBG_WARNING("netlogon_creds_cli_lck failed: %s\n",
     127             :                             nt_errstr(status));
     128           0 :                 return status;
     129             :         }
     130             : 
     131          12 :         status = netlogon_creds_cli_auth(context, b, num_nt_hashes, nt_hashes,
     132             :                                          idx_nt_hashes);
     133          12 :         TALLOC_FREE(lck);
     134             : 
     135          12 :         return status;
     136             : }
     137             : 
     138           6 : NTSTATUS trust_pw_change(struct netlogon_creds_cli_context *context,
     139             :                          struct messaging_context *msg_ctx,
     140             :                          struct dcerpc_binding_handle *b,
     141             :                          const char *domain,
     142             :                          const char *dcname,
     143             :                          bool force)
     144             : {
     145           6 :         TALLOC_CTX *frame = talloc_stackframe();
     146           6 :         const char *context_name = NULL;
     147             :         struct trust_pw_change_state *state;
     148           6 :         struct cli_credentials *creds = NULL;
     149           6 :         struct secrets_domain_info1 *info = NULL;
     150           6 :         struct secrets_domain_info1_change *prev = NULL;
     151           6 :         const struct samr_Password *current_nt_hash = NULL;
     152           6 :         const struct samr_Password *previous_nt_hash = NULL;
     153           6 :         uint8_t num_nt_hashes = 0;
     154           6 :         uint8_t idx = 0;
     155           6 :         const struct samr_Password *nt_hashes[1+3] = { NULL, };
     156           6 :         uint8_t idx_nt_hashes = 0;
     157           6 :         uint8_t idx_current = UINT8_MAX;
     158           6 :         enum netr_SchannelType sec_channel_type = SEC_CHAN_NULL;
     159             :         time_t pass_last_set_time;
     160           6 :         uint32_t old_version = 0;
     161           6 :         struct pdb_trusted_domain *td = NULL;
     162           6 :         struct timeval g_timeout = { 0, };
     163           6 :         int timeout = 0;
     164           6 :         struct timeval tv = { 0, };
     165           6 :         char *new_trust_pw_str = NULL;
     166           6 :         size_t len = 0;
     167           6 :         DATA_BLOB new_trust_pw_blob = data_blob_null;
     168           6 :         uint32_t new_version = 0;
     169           6 :         uint32_t *new_trust_version = NULL;
     170             :         NTSTATUS status;
     171             :         bool ok;
     172             : 
     173           6 :         state = talloc_zero(frame, struct trust_pw_change_state);
     174           6 :         if (state == NULL) {
     175           0 :                 TALLOC_FREE(frame);
     176           0 :                 return NT_STATUS_NO_MEMORY;
     177             :         }
     178             : 
     179           6 :         state->g_ctx = g_lock_ctx_init(state, msg_ctx);
     180           6 :         if (state->g_ctx == NULL) {
     181           0 :                 TALLOC_FREE(frame);
     182           0 :                 return NT_STATUS_NO_MEMORY;
     183             :         }
     184             : 
     185           6 :         state->g_lock_key = talloc_asprintf(state,
     186             :                                 "trust_password_change_%s",
     187             :                                 domain);
     188           6 :         if (state->g_lock_key == NULL) {
     189           0 :                 TALLOC_FREE(frame);
     190           0 :                 return NT_STATUS_NO_MEMORY;
     191             :         }
     192             : 
     193           6 :         g_timeout = timeval_current_ofs(10, 0);
     194           6 :         status = g_lock_lock(state->g_ctx,
     195           6 :                              string_term_tdb_data(state->g_lock_key),
     196             :                              G_LOCK_WRITE, g_timeout);
     197           6 :         if (!NT_STATUS_IS_OK(status)) {
     198           0 :                 DEBUG(1, ("could not get g_lock on [%s]!\n",
     199             :                           state->g_lock_key));
     200           0 :                 TALLOC_FREE(frame);
     201           0 :                 return status;
     202             :         }
     203             : 
     204           6 :         talloc_set_destructor(state, trust_pw_change_state_destructor);
     205             : 
     206           6 :         status = pdb_get_trust_credentials(domain, NULL, frame, &creds);
     207           6 :         if (!NT_STATUS_IS_OK(status)) {
     208           0 :                 DEBUG(0, ("could not fetch domain creds for domain %s - %s!\n",
     209             :                           domain, nt_errstr(status)));
     210           0 :                 TALLOC_FREE(frame);
     211           0 :                 return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE;
     212             :         }
     213             : 
     214           6 :         current_nt_hash = cli_credentials_get_nt_hash(creds, frame);
     215           6 :         if (current_nt_hash == NULL) {
     216           0 :                 DEBUG(0, ("cli_credentials_get_nt_hash failed for domain %s!\n",
     217             :                           domain));
     218           0 :                 TALLOC_FREE(frame);
     219           0 :                 return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE;
     220             :         }
     221           6 :         previous_nt_hash = cli_credentials_get_old_nt_hash(creds, frame);
     222             : 
     223           6 :         old_version = cli_credentials_get_kvno(creds);
     224           6 :         pass_last_set_time = cli_credentials_get_password_last_changed_time(creds);
     225           6 :         sec_channel_type = cli_credentials_get_secure_channel_type(creds);
     226             : 
     227           6 :         new_version = old_version + 1;
     228             : 
     229           6 :         switch (sec_channel_type) {
     230           6 :         case SEC_CHAN_WKSTA:
     231             :         case SEC_CHAN_BDC:
     232           6 :                 break;
     233           0 :         case SEC_CHAN_DNS_DOMAIN:
     234             :         case SEC_CHAN_DOMAIN:
     235           0 :                 status = pdb_get_trusted_domain(frame, domain, &td);
     236           0 :                 if (!NT_STATUS_IS_OK(status)) {
     237           0 :                         DEBUG(0, ("pdb_get_trusted_domain() failed for domain %s - %s!\n",
     238             :                                   domain, nt_errstr(status)));
     239           0 :                         TALLOC_FREE(frame);
     240           0 :                         return status;
     241             :                 }
     242             : 
     243           0 :                 new_trust_version = &new_version;
     244           0 :                 break;
     245           0 :         default:
     246           0 :                 TALLOC_FREE(frame);
     247           0 :                 return NT_STATUS_NOT_SUPPORTED;
     248             :         }
     249             : 
     250           6 :         timeout = lp_machine_password_timeout();
     251           6 :         if (timeout == 0) {
     252           0 :                 if (!force) {
     253           0 :                         DEBUG(10,("machine password never expires\n"));
     254           0 :                         TALLOC_FREE(frame);
     255           0 :                         return NT_STATUS_OK;
     256             :                 }
     257             :         }
     258             : 
     259           6 :         tv.tv_sec = pass_last_set_time;
     260           6 :         DEBUG(10, ("password last changed %s\n",
     261             :                    timeval_string(talloc_tos(), &tv, false)));
     262           6 :         tv.tv_sec += timeout;
     263           6 :         DEBUGADD(10, ("password valid until %s\n",
     264             :                       timeval_string(talloc_tos(), &tv, false)));
     265             : 
     266           6 :         if (!force && !timeval_expired(&tv)) {
     267           0 :                 TALLOC_FREE(frame);
     268           0 :                 return NT_STATUS_OK;
     269             :         }
     270             : 
     271           6 :         context_name = netlogon_creds_cli_debug_string(context, talloc_tos());
     272           6 :         if (context_name == NULL) {
     273           0 :                 TALLOC_FREE(frame);
     274           0 :                 return NT_STATUS_NO_MEMORY;
     275             :         }
     276             : 
     277             :         /*
     278             :          * Create a random machine account password
     279             :          * We create a random buffer and convert that to utf8.
     280             :          * This is similar to what windows is doing.
     281             :          */
     282           6 :         new_trust_pw_str = trust_pw_new_value(frame, sec_channel_type,
     283             :                                               lp_security());
     284           6 :         if (new_trust_pw_str == NULL) {
     285           0 :                 DEBUG(0, ("trust_pw_new_value() failed\n"));
     286           0 :                 TALLOC_FREE(frame);
     287           0 :                 return NT_STATUS_NO_MEMORY;
     288             :         }
     289             : 
     290           6 :         len = strlen(new_trust_pw_str);
     291           6 :         ok = convert_string_talloc(frame, CH_UNIX, CH_UTF16,
     292             :                                    new_trust_pw_str, len,
     293             :                                    (void **)&new_trust_pw_blob.data,
     294             :                                    &new_trust_pw_blob.length);
     295           6 :         if (!ok) {
     296           0 :                 status = NT_STATUS_UNMAPPABLE_CHARACTER;
     297           0 :                 if (errno == ENOMEM) {
     298           0 :                         status = NT_STATUS_NO_MEMORY;
     299             :                 }
     300           0 :                 DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) "
     301             :                         "failed for of %s - %s\n",
     302             :                         domain, nt_errstr(status));
     303           0 :                 TALLOC_FREE(frame);
     304           0 :                 return status;
     305             :         }
     306             : 
     307           6 :         switch (sec_channel_type) {
     308             : 
     309           6 :         case SEC_CHAN_WKSTA:
     310             :         case SEC_CHAN_BDC:
     311           6 :                 status = secrets_prepare_password_change(domain, dcname,
     312             :                                                          new_trust_pw_str,
     313             :                                                          frame, &info, &prev);
     314           6 :                 if (!NT_STATUS_IS_OK(status)) {
     315           0 :                         DEBUG(0, ("secrets_prepare_password_change() failed for domain %s!\n",
     316             :                                   domain));
     317           0 :                         TALLOC_FREE(frame);
     318           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     319             :                 }
     320           6 :                 TALLOC_FREE(new_trust_pw_str);
     321             : 
     322           6 :                 if (prev != NULL) {
     323             :                         /*
     324             :                          * We had a failure before we changed the password.
     325             :                          */
     326           0 :                         nt_hashes[idx++] = &prev->password->nt_hash;
     327             : 
     328           0 :                         DEBUG(0,("%s : %s(%s): A password change was already "
     329             :                                  "started against '%s' at %s. Trying to "
     330             :                                  "recover...\n",
     331             :                                  current_timestring(talloc_tos(), false),
     332             :                                  __func__, domain,
     333             :                                  prev->password->change_server,
     334             :                                  nt_time_string(talloc_tos(),
     335             :                                  prev->password->change_time)));
     336           0 :                         DEBUG(0,("%s : %s(%s): Last failure local[%s] remote[%s] "
     337             :                                  "against '%s' at %s.\n",
     338             :                                  current_timestring(talloc_tos(), false),
     339             :                                  __func__, domain,
     340             :                                  nt_errstr(prev->local_status),
     341             :                                  nt_errstr(prev->remote_status),
     342             :                                  prev->change_server,
     343             :                                  nt_time_string(talloc_tos(),
     344             :                                  prev->change_time)));
     345             :                 }
     346             : 
     347           6 :                 idx_current = idx;
     348           6 :                 nt_hashes[idx++] = &info->password->nt_hash;
     349           6 :                 if (info->old_password != NULL) {
     350           0 :                         nt_hashes[idx++] = &info->old_password->nt_hash;
     351             :                 }
     352           6 :                 if (info->older_password != NULL) {
     353           0 :                         nt_hashes[idx++] = &info->older_password->nt_hash;
     354             :                 }
     355             : 
     356             :                 /*
     357             :                  * We use the password that's already persistent in
     358             :                  * our database in order to handle failures.
     359             :                  */
     360           6 :                 data_blob_clear_free(&new_trust_pw_blob);
     361           6 :                 new_trust_pw_blob = info->next_change->password->cleartext_blob;
     362           6 :                 break;
     363             : 
     364           0 :         case SEC_CHAN_DNS_DOMAIN:
     365             :         case SEC_CHAN_DOMAIN:
     366           0 :                 idx_current = idx;
     367           0 :                 nt_hashes[idx++] = current_nt_hash;
     368           0 :                 if (previous_nt_hash != NULL) {
     369           0 :                         nt_hashes[idx++] = previous_nt_hash;
     370             :                 }
     371           0 :                 break;
     372             : 
     373           0 :         default:
     374           0 :                 smb_panic("Unsupported secure channel type");
     375             :                 break;
     376             :         }
     377           6 :         num_nt_hashes = idx;
     378             : 
     379           6 :         DEBUG(0,("%s : %s(%s): Verifying passwords remotely %s.\n",
     380             :                  current_timestring(talloc_tos(), false),
     381             :                  __func__, domain, context_name));
     382             : 
     383             :         /*
     384             :          * Check which password the dc knows about.
     385             :          *
     386             :          * TODO:
     387             :          * If the previous password is the only password in common with the dc,
     388             :          * we better skip the password change, or use something like
     389             :          * ServerTrustPasswordsGet() or netr_ServerGetTrustInfo() to fix our
     390             :          * local secrets before doing the change.
     391             :          */
     392           6 :         status = netlogon_creds_cli_lck_auth(context, b,
     393             :                                              num_nt_hashes,
     394             :                                              nt_hashes,
     395             :                                              &idx_nt_hashes);
     396           6 :         if (!NT_STATUS_IS_OK(status)) {
     397           0 :                 DEBUG(0, ("netlogon_creds_cli_auth(%s) failed for old passwords (%u) - %s!\n",
     398             :                           context_name, num_nt_hashes, nt_errstr(status)));
     399           0 :                 TALLOC_FREE(frame);
     400           0 :                 return status;
     401             :         }
     402             : 
     403           6 :         if (prev != NULL && idx_nt_hashes == 0) {
     404           0 :                 DEBUG(0,("%s : %s(%s): Verified new password remotely "
     405             :                          "without changing %s\n",
     406             :                          current_timestring(talloc_tos(), false),
     407             :                          __func__, domain, context_name));
     408             : 
     409           0 :                 status = secrets_finish_password_change(prev->password->change_server,
     410           0 :                                                         prev->password->change_time,
     411             :                                                         info);
     412           0 :                 if (!NT_STATUS_IS_OK(status)) {
     413           0 :                         DEBUG(0, ("secrets_prepare_password_change() failed for domain %s!\n",
     414             :                                   domain));
     415           0 :                         TALLOC_FREE(frame);
     416           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     417             :                 }
     418             : 
     419           0 :                 DEBUG(0,("%s : %s(%s): Recovered previous password change.\n",
     420             :                          current_timestring(talloc_tos(), false),
     421             :                          __func__, domain));
     422           0 :                 TALLOC_FREE(frame);
     423           0 :                 return NT_STATUS_OK;
     424             :         }
     425             : 
     426           6 :         if (idx_nt_hashes != idx_current) {
     427           0 :                 DEBUG(0,("%s : %s(%s): Verified older password remotely "
     428             :                          "skip changing %s\n",
     429             :                          current_timestring(talloc_tos(), false),
     430             :                          __func__, domain, context_name));
     431             : 
     432           0 :                 if (info == NULL) {
     433           0 :                         TALLOC_FREE(frame);
     434           0 :                         return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE;
     435             :                 }
     436             : 
     437           0 :                 status = secrets_defer_password_change(dcname,
     438           0 :                                         NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE,
     439           0 :                                         NT_STATUS_NOT_COMMITTED,
     440             :                                         info);
     441           0 :                 if (!NT_STATUS_IS_OK(status)) {
     442           0 :                         DEBUG(0, ("secrets_defer_password_change() failed for domain %s!\n",
     443             :                                   domain));
     444           0 :                         TALLOC_FREE(frame);
     445           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     446             :                 }
     447           0 :                 TALLOC_FREE(frame);
     448           0 :                 return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE;
     449             :         }
     450             : 
     451           6 :         DEBUG(0,("%s : %s(%s): Verified old password remotely using %s\n",
     452             :                  current_timestring(talloc_tos(), false),
     453             :                  __func__, domain, context_name));
     454             : 
     455             :         /*
     456             :          * Return the result of trying to write the new password
     457             :          * back into the trust account file.
     458             :          */
     459             : 
     460           6 :         switch (sec_channel_type) {
     461             : 
     462           6 :         case SEC_CHAN_WKSTA:
     463             :         case SEC_CHAN_BDC:
     464             :                 /*
     465             :                  * we called secrets_prepare_password_change() above.
     466             :                  */
     467           6 :                 break;
     468             : 
     469           0 :         case SEC_CHAN_DNS_DOMAIN:
     470             :         case SEC_CHAN_DOMAIN:
     471             :                 /*
     472             :                  * we need to get the sid first for the
     473             :                  * pdb_set_trusteddom_pw call
     474             :                  */
     475           0 :                 ok = pdb_set_trusteddom_pw(domain, new_trust_pw_str,
     476           0 :                                            &td->security_identifier);
     477           0 :                 if (!ok) {
     478           0 :                         DEBUG(0, ("pdb_set_trusteddom_pw() failed for domain %s!\n",
     479             :                                   domain));
     480           0 :                         TALLOC_FREE(frame);
     481           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     482             :                 }
     483           0 :                 TALLOC_FREE(new_trust_pw_str);
     484           0 :                 break;
     485             : 
     486           0 :         default:
     487           0 :                 smb_panic("Unsupported secure channel type");
     488             :                 break;
     489             :         }
     490             : 
     491           6 :         DEBUG(0,("%s : %s(%s): Changed password locally\n",
     492             :                  current_timestring(talloc_tos(), false), __func__, domain));
     493             : 
     494           6 :         status = netlogon_creds_cli_ServerPasswordSet(context, b,
     495             :                                                       &new_trust_pw_blob,
     496             :                                                       new_trust_version);
     497           6 :         if (!NT_STATUS_IS_OK(status)) {
     498             :                 NTSTATUS status2;
     499           0 :                 const char *fn = NULL;
     500             : 
     501           0 :                 ok = dcerpc_binding_handle_is_connected(b);
     502             : 
     503           0 :                 DEBUG(0,("%s : %s(%s) remote password change with %s failed "
     504             :                          "- %s (%s)\n",
     505             :                          current_timestring(talloc_tos(), false),
     506             :                          __func__, domain, context_name,
     507             :                          nt_errstr(status),
     508             :                          ok ? "connected": "disconnected"));
     509             : 
     510           0 :                 if (!ok) {
     511             :                         /*
     512             :                          * The connection is broken, we don't
     513             :                          * know if the password was changed,
     514             :                          * we hope to have more luck next time.
     515             :                          */
     516           0 :                         status2 = secrets_failed_password_change(dcname,
     517           0 :                                                         NT_STATUS_NOT_COMMITTED,
     518             :                                                         status,
     519             :                                                         info);
     520           0 :                         fn = "secrets_failed_password_change";
     521             :                 } else {
     522             :                         /*
     523             :                          * The server rejected the change, we don't
     524             :                          * retry and defer the change to the next
     525             :                          * "machine password timeout" interval.
     526             :                          */
     527           0 :                         status2 = secrets_defer_password_change(dcname,
     528           0 :                                                         NT_STATUS_NOT_COMMITTED,
     529             :                                                         status,
     530             :                                                         info);
     531           0 :                         fn = "secrets_defer_password_change";
     532             :                 }
     533           0 :                 if (!NT_STATUS_IS_OK(status2)) {
     534           0 :                         DEBUG(0, ("%s() failed for domain %s!\n",
     535             :                                   fn, domain));
     536           0 :                         TALLOC_FREE(frame);
     537           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     538             :                 }
     539             : 
     540           0 :                 TALLOC_FREE(frame);
     541           0 :                 return status;
     542             :         }
     543             : 
     544           6 :         DEBUG(0,("%s : %s(%s): Changed password remotely using %s\n",
     545             :                  current_timestring(talloc_tos(), false),
     546             :                  __func__, domain, context_name));
     547             : 
     548           6 :         switch (sec_channel_type) {
     549             : 
     550           6 :         case SEC_CHAN_WKSTA:
     551             :         case SEC_CHAN_BDC:
     552          18 :                 status = secrets_finish_password_change(
     553           6 :                                         info->next_change->change_server,
     554           6 :                                         info->next_change->change_time,
     555             :                                         info);
     556           6 :                 if (!NT_STATUS_IS_OK(status)) {
     557           0 :                         DEBUG(0, ("secrets_finish_password_change() failed for domain %s!\n",
     558             :                                   domain));
     559           0 :                         TALLOC_FREE(frame);
     560           0 :                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
     561             :                 }
     562             : 
     563           6 :                 DEBUG(0,("%s : %s(%s): Finished password change.\n",
     564             :                          current_timestring(talloc_tos(), false),
     565             :                          __func__, domain));
     566           6 :                 break;
     567             : 
     568           0 :         case SEC_CHAN_DNS_DOMAIN:
     569             :         case SEC_CHAN_DOMAIN:
     570             :                 /*
     571             :                  * we used pdb_set_trusteddom_pw().
     572             :                  */
     573           0 :                 break;
     574             : 
     575           0 :         default:
     576           0 :                 smb_panic("Unsupported secure channel type");
     577             :                 break;
     578             :         }
     579             : 
     580           6 :         ok = cli_credentials_set_utf16_password(creds,
     581             :                                                 &new_trust_pw_blob,
     582             :                                                 CRED_SPECIFIED);
     583           6 :         if (!ok) {
     584           0 :                 DEBUG(0, ("cli_credentials_set_password failed for domain %s!\n",
     585             :                           domain));
     586           0 :                 TALLOC_FREE(frame);
     587           0 :                 return NT_STATUS_NO_MEMORY;
     588             :         }
     589             : 
     590           6 :         current_nt_hash = cli_credentials_get_nt_hash(creds, frame);
     591           6 :         if (current_nt_hash == NULL) {
     592           0 :                 DEBUG(0, ("cli_credentials_get_nt_hash failed for domain %s!\n",
     593             :                           domain));
     594           0 :                 TALLOC_FREE(frame);
     595           0 :                 return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE;
     596             :         }
     597             : 
     598             :         /*
     599             :          * Now we verify the new password.
     600             :          */
     601           6 :         idx = 0;
     602           6 :         nt_hashes[idx++] = current_nt_hash;
     603           6 :         num_nt_hashes = idx;
     604           6 :         status = netlogon_creds_cli_lck_auth(context, b,
     605             :                                              num_nt_hashes,
     606             :                                              nt_hashes,
     607             :                                              &idx_nt_hashes);
     608           6 :         if (!NT_STATUS_IS_OK(status)) {
     609           0 :                 DEBUG(0, ("netlogon_creds_cli_auth(%s) failed for new password - %s!\n",
     610             :                           context_name, nt_errstr(status)));
     611           0 :                 TALLOC_FREE(frame);
     612           0 :                 return status;
     613             :         }
     614             : 
     615           6 :         DEBUG(0,("%s : %s(%s): Verified new password remotely using %s\n",
     616             :                  current_timestring(talloc_tos(), false),
     617             :                  __func__, domain, context_name));
     618             : 
     619           6 :         TALLOC_FREE(frame);
     620           6 :         return NT_STATUS_OK;
     621             : }

Generated by: LCOV version 1.13