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

Generated by: LCOV version 1.13