libcli/auth: also set secure channel type in netlogon_creds_client_init().
[metze/samba/wip.git] / source3 / rpc_client / cli_netlogon.c
1 /*
2    Unix SMB/CIFS implementation.
3    NT Domain Authentication SMB / MSRPC client
4    Copyright (C) Andrew Tridgell 1992-2000
5    Copyright (C) Jeremy Allison                    1998.
6    Largely re-written by Jeremy Allison (C)        2005.
7    Copyright (C) Guenther Deschner                 2008.
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 "rpc_client/rpc_client.h"
25 #include "../libcli/auth/libcli_auth.h"
26 #include "../librpc/gen_ndr/ndr_netlogon_c.h"
27 #include "rpc_client/cli_netlogon.h"
28 #include "rpc_client/init_netlogon.h"
29 #include "rpc_client/util_netlogon.h"
30 #include "../libcli/security/security.h"
31
32 /****************************************************************************
33  Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
34  credentials chain. Stores the credentials in the struct dcinfo in the
35  netlogon pipe struct.
36 ****************************************************************************/
37
38 NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
39                                      const char *server_name,
40                                      const char *domain,
41                                      const char *clnt_name,
42                                      const char *machine_account,
43                                      const unsigned char machine_pwd[16],
44                                      enum netr_SchannelType sec_chan_type,
45                                      uint32_t *neg_flags_inout)
46 {
47         NTSTATUS status;
48         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
49         struct netr_Credential clnt_chal_send;
50         struct netr_Credential srv_chal_recv;
51         struct samr_Password password;
52         bool retried = false;
53         fstring mach_acct;
54         uint32_t neg_flags = *neg_flags_inout;
55         struct dcerpc_binding_handle *b = cli->binding_handle;
56
57         if (!ndr_syntax_id_equal(&cli->abstract_syntax,
58                                  &ndr_table_netlogon.syntax_id)) {
59                 return NT_STATUS_INVALID_PARAMETER;
60         }
61
62         TALLOC_FREE(cli->dc);
63
64         /* Store the machine account password we're going to use. */
65         memcpy(password.hash, machine_pwd, 16);
66
67         fstr_sprintf( mach_acct, "%s$", machine_account);
68
69  again:
70         /* Create the client challenge. */
71         generate_random_buffer(clnt_chal_send.data, 8);
72
73         /* Get the server challenge. */
74         status = dcerpc_netr_ServerReqChallenge(b, talloc_tos(),
75                                                 cli->srv_name_slash,
76                                                 clnt_name,
77                                                 &clnt_chal_send,
78                                                 &srv_chal_recv,
79                                                 &result);
80         if (!NT_STATUS_IS_OK(status)) {
81                 return status;
82         }
83         if (!NT_STATUS_IS_OK(result)) {
84                 return result;
85         }
86
87         /* Calculate the session key and client credentials */
88
89         cli->dc = netlogon_creds_client_init(cli,
90                                     mach_acct,
91                                     clnt_name,
92                                     sec_chan_type,
93                                     &clnt_chal_send,
94                                     &srv_chal_recv,
95                                     &password,
96                                     &clnt_chal_send,
97                                     neg_flags);
98
99         if (!cli->dc) {
100                 return NT_STATUS_NO_MEMORY;
101         }
102
103         /*
104          * Send client auth-2 challenge and receive server repy.
105          */
106
107         status = dcerpc_netr_ServerAuthenticate2(b, talloc_tos(),
108                                                  cli->srv_name_slash,
109                                                  cli->dc->account_name,
110                                                  sec_chan_type,
111                                                  cli->dc->computer_name,
112                                                  &clnt_chal_send, /* input. */
113                                                  &srv_chal_recv, /* output. */
114                                                  &neg_flags,
115                                                  &result);
116         if (!NT_STATUS_IS_OK(status)) {
117                 return status;
118         }
119         /* we might be talking to NT4, so let's downgrade in that case and retry
120          * with the returned neg_flags - gd */
121
122         if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && !retried) {
123                 retried = true;
124                 TALLOC_FREE(cli->dc);
125                 goto again;
126         }
127
128         if (!NT_STATUS_IS_OK(result)) {
129                 return result;
130         }
131
132         /*
133          * Check the returned value using the initial
134          * server received challenge.
135          */
136
137         if (!netlogon_creds_client_check(cli->dc, &srv_chal_recv)) {
138                 /*
139                  * Server replied with bad credential. Fail.
140                  */
141                 DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
142                         "replied with bad credential\n",
143                         cli->desthost ));
144                 return NT_STATUS_ACCESS_DENIED;
145         }
146
147         DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
148                 "chain established.\n",
149                 cli->desthost ));
150
151         cli->dc->negotiate_flags = neg_flags;
152         *neg_flags_inout = neg_flags;
153
154         return NT_STATUS_OK;
155 }
156
157 /* Logon domain user */
158
159 NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
160                                    TALLOC_CTX *mem_ctx,
161                                    uint32 logon_parameters,
162                                    const char *domain,
163                                    const char *username,
164                                    const char *password,
165                                    const char *workstation,
166                                    uint16_t validation_level,
167                                    int logon_type)
168 {
169         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
170         NTSTATUS status;
171         struct netr_Authenticator clnt_creds;
172         struct netr_Authenticator ret_creds;
173         union netr_LogonLevel *logon;
174         union netr_Validation validation;
175         uint8_t authoritative;
176         fstring clnt_name_slash;
177         struct dcerpc_binding_handle *b = cli->binding_handle;
178
179         ZERO_STRUCT(ret_creds);
180
181         logon = talloc_zero(mem_ctx, union netr_LogonLevel);
182         if (!logon) {
183                 return NT_STATUS_NO_MEMORY;
184         }
185
186         if (workstation) {
187                 fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
188         } else {
189                 fstr_sprintf( clnt_name_slash, "\\\\%s", lp_netbios_name() );
190         }
191
192         /* Initialise input parameters */
193
194         netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
195
196         switch (logon_type) {
197         case NetlogonInteractiveInformation: {
198
199                 struct netr_PasswordInfo *password_info;
200
201                 struct samr_Password lmpassword;
202                 struct samr_Password ntpassword;
203
204                 password_info = talloc_zero(mem_ctx, struct netr_PasswordInfo);
205                 if (!password_info) {
206                         return NT_STATUS_NO_MEMORY;
207                 }
208
209                 nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);
210
211                 if (cli->dc->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
212                         netlogon_creds_aes_encrypt(cli->dc, lmpassword.hash, 16);
213                         netlogon_creds_aes_encrypt(cli->dc, ntpassword.hash, 16);
214                 } else if (cli->dc->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
215                         netlogon_creds_arcfour_crypt(cli->dc, lmpassword.hash, 16);
216                         netlogon_creds_arcfour_crypt(cli->dc, ntpassword.hash, 16);
217                 } else {
218                         netlogon_creds_des_encrypt(cli->dc, &lmpassword);
219                         netlogon_creds_des_encrypt(cli->dc, &ntpassword);
220                 }
221
222                 password_info->identity_info.domain_name.string         = domain;
223                 password_info->identity_info.parameter_control          = logon_parameters;
224                 password_info->identity_info.logon_id_low               = 0xdead;
225                 password_info->identity_info.logon_id_high              = 0xbeef;
226                 password_info->identity_info.account_name.string        = username;
227                 password_info->identity_info.workstation.string         = clnt_name_slash;
228
229                 password_info->lmpassword = lmpassword;
230                 password_info->ntpassword = ntpassword;
231
232                 logon->password = password_info;
233
234                 break;
235         }
236         case NetlogonNetworkInformation: {
237                 struct netr_NetworkInfo *network_info;
238                 uint8 chal[8];
239                 unsigned char local_lm_response[24];
240                 unsigned char local_nt_response[24];
241                 struct netr_ChallengeResponse lm;
242                 struct netr_ChallengeResponse nt;
243
244                 ZERO_STRUCT(lm);
245                 ZERO_STRUCT(nt);
246
247                 network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
248                 if (!network_info) {
249                         return NT_STATUS_NO_MEMORY;
250                 }
251
252                 generate_random_buffer(chal, 8);
253
254                 SMBencrypt(password, chal, local_lm_response);
255                 SMBNTencrypt(password, chal, local_nt_response);
256
257                 lm.length = 24;
258                 lm.data = local_lm_response;
259
260                 nt.length = 24;
261                 nt.data = local_nt_response;
262
263                 network_info->identity_info.domain_name.string          = domain;
264                 network_info->identity_info.parameter_control           = logon_parameters;
265                 network_info->identity_info.logon_id_low                = 0xdead;
266                 network_info->identity_info.logon_id_high               = 0xbeef;
267                 network_info->identity_info.account_name.string         = username;
268                 network_info->identity_info.workstation.string          = clnt_name_slash;
269
270                 memcpy(network_info->challenge, chal, 8);
271                 network_info->nt = nt;
272                 network_info->lm = lm;
273
274                 logon->network = network_info;
275
276                 break;
277         }
278         default:
279                 DEBUG(0, ("switch value %d not supported\n",
280                         logon_type));
281                 return NT_STATUS_INVALID_INFO_CLASS;
282         }
283
284         status = dcerpc_netr_LogonSamLogon(b, mem_ctx,
285                                            cli->srv_name_slash,
286                                            lp_netbios_name(),
287                                            &clnt_creds,
288                                            &ret_creds,
289                                            logon_type,
290                                            logon,
291                                            validation_level,
292                                            &validation,
293                                            &authoritative,
294                                            &result);
295         if (!NT_STATUS_IS_OK(status)) {
296                 return status;
297         }
298
299         /* Always check returned credentials */
300         if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
301                 DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
302                 return NT_STATUS_ACCESS_DENIED;
303         }
304
305         return result;
306 }
307
308 static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx,
309                                         uint16_t validation_level,
310                                         union netr_Validation *validation,
311                                         struct netr_SamInfo3 **info3_p)
312 {
313         struct netr_SamInfo3 *info3;
314         NTSTATUS status;
315
316         if (validation == NULL) {
317                 return NT_STATUS_INVALID_PARAMETER;
318         }
319
320         switch (validation_level) {
321         case 3:
322                 if (validation->sam3 == NULL) {
323                         return NT_STATUS_INVALID_PARAMETER;
324                 }
325
326                 info3 = talloc_move(mem_ctx, &validation->sam3);
327                 break;
328         case 6:
329                 if (validation->sam6 == NULL) {
330                         return NT_STATUS_INVALID_PARAMETER;
331                 }
332
333                 info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
334                 if (info3 == NULL) {
335                         return NT_STATUS_NO_MEMORY;
336                 }
337                 status = copy_netr_SamBaseInfo(info3, &validation->sam6->base, &info3->base);
338                 if (!NT_STATUS_IS_OK(status)) {
339                         TALLOC_FREE(info3);
340                         return status;
341                 }
342
343                 info3->sidcount = validation->sam6->sidcount;
344                 info3->sids = talloc_move(info3, &validation->sam6->sids);
345                 break;
346         default:
347                 return NT_STATUS_BAD_VALIDATION_CLASS;
348         }
349
350         *info3_p = info3;
351
352         return NT_STATUS_OK;
353 }
354
355 /**
356  * Logon domain user with an 'network' SAM logon
357  *
358  * @param info3 Pointer to a NET_USER_INFO_3 already allocated by the caller.
359  **/
360
361 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
362                                            TALLOC_CTX *mem_ctx,
363                                            uint32 logon_parameters,
364                                            const char *server,
365                                            const char *username,
366                                            const char *domain,
367                                            const char *workstation,
368                                            const uint8 chal[8],
369                                            uint16_t validation_level,
370                                            DATA_BLOB lm_response,
371                                            DATA_BLOB nt_response,
372                                            struct netr_SamInfo3 **info3)
373 {
374         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
375         NTSTATUS status;
376         const char *workstation_name_slash;
377         const char *server_name_slash;
378         struct netr_Authenticator clnt_creds;
379         struct netr_Authenticator ret_creds;
380         union netr_LogonLevel *logon = NULL;
381         struct netr_NetworkInfo *network_info;
382         uint8_t authoritative;
383         union netr_Validation validation;
384         struct netr_ChallengeResponse lm;
385         struct netr_ChallengeResponse nt;
386         struct dcerpc_binding_handle *b = cli->binding_handle;
387
388         *info3 = NULL;
389
390         ZERO_STRUCT(ret_creds);
391
392         ZERO_STRUCT(lm);
393         ZERO_STRUCT(nt);
394
395         logon = talloc_zero(mem_ctx, union netr_LogonLevel);
396         if (!logon) {
397                 return NT_STATUS_NO_MEMORY;
398         }
399
400         network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
401         if (!network_info) {
402                 return NT_STATUS_NO_MEMORY;
403         }
404
405         netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
406
407         if (server[0] != '\\' && server[1] != '\\') {
408                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
409         } else {
410                 server_name_slash = server;
411         }
412
413         if (workstation[0] != '\\' && workstation[1] != '\\') {
414                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
415         } else {
416                 workstation_name_slash = workstation;
417         }
418
419         if (!workstation_name_slash || !server_name_slash) {
420                 DEBUG(0, ("talloc_asprintf failed!\n"));
421                 return NT_STATUS_NO_MEMORY;
422         }
423
424         /* Initialise input parameters */
425
426         lm.data = lm_response.data;
427         lm.length = lm_response.length;
428         nt.data = nt_response.data;
429         nt.length = nt_response.length;
430
431         network_info->identity_info.domain_name.string          = domain;
432         network_info->identity_info.parameter_control           = logon_parameters;
433         network_info->identity_info.logon_id_low                = 0xdead;
434         network_info->identity_info.logon_id_high               = 0xbeef;
435         network_info->identity_info.account_name.string         = username;
436         network_info->identity_info.workstation.string          = workstation_name_slash;
437
438         memcpy(network_info->challenge, chal, 8);
439         network_info->nt = nt;
440         network_info->lm = lm;
441
442         logon->network = network_info;
443
444         /* Marshall data and send request */
445
446         status = dcerpc_netr_LogonSamLogon(b, mem_ctx,
447                                            server_name_slash,
448                                            lp_netbios_name(),
449                                            &clnt_creds,
450                                            &ret_creds,
451                                            NetlogonNetworkInformation,
452                                            logon,
453                                            validation_level,
454                                            &validation,
455                                            &authoritative,
456                                            &result);
457         if (!NT_STATUS_IS_OK(status)) {
458                 return status;
459         }
460
461         /* Always check returned credentials. */
462         if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
463                 DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
464                 return NT_STATUS_ACCESS_DENIED;
465         }
466
467         if (!NT_STATUS_IS_OK(result)) {
468                 return result;
469         }
470
471         netlogon_creds_decrypt_samlogon_validation(cli->dc, validation_level,
472                                                    &validation);
473
474         result = map_validation_to_info3(mem_ctx, validation_level, &validation, info3);
475         if (!NT_STATUS_IS_OK(result)) {
476                 return result;
477         }
478
479         return result;
480 }
481
482 NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli,
483                                               TALLOC_CTX *mem_ctx,
484                                               uint32 logon_parameters,
485                                               const char *server,
486                                               const char *username,
487                                               const char *domain,
488                                               const char *workstation,
489                                               const uint8 chal[8],
490                                               uint16_t validation_level,
491                                               DATA_BLOB lm_response,
492                                               DATA_BLOB nt_response,
493                                               struct netr_SamInfo3 **info3)
494 {
495         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
496         NTSTATUS status;
497         const char *workstation_name_slash;
498         const char *server_name_slash;
499         union netr_LogonLevel *logon = NULL;
500         struct netr_NetworkInfo *network_info;
501         uint8_t authoritative;
502         union netr_Validation validation;
503         struct netr_ChallengeResponse lm;
504         struct netr_ChallengeResponse nt;
505         uint32_t flags = 0;
506         struct dcerpc_binding_handle *b = cli->binding_handle;
507
508         *info3 = NULL;
509
510         ZERO_STRUCT(lm);
511         ZERO_STRUCT(nt);
512
513         logon = talloc_zero(mem_ctx, union netr_LogonLevel);
514         if (!logon) {
515                 return NT_STATUS_NO_MEMORY;
516         }
517
518         network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
519         if (!network_info) {
520                 return NT_STATUS_NO_MEMORY;
521         }
522
523         if (server[0] != '\\' && server[1] != '\\') {
524                 server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
525         } else {
526                 server_name_slash = server;
527         }
528
529         if (workstation[0] != '\\' && workstation[1] != '\\') {
530                 workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
531         } else {
532                 workstation_name_slash = workstation;
533         }
534
535         if (!workstation_name_slash || !server_name_slash) {
536                 DEBUG(0, ("talloc_asprintf failed!\n"));
537                 return NT_STATUS_NO_MEMORY;
538         }
539
540         /* Initialise input parameters */
541
542         lm.data = lm_response.data;
543         lm.length = lm_response.length;
544         nt.data = nt_response.data;
545         nt.length = nt_response.length;
546
547         network_info->identity_info.domain_name.string          = domain;
548         network_info->identity_info.parameter_control           = logon_parameters;
549         network_info->identity_info.logon_id_low                = 0xdead;
550         network_info->identity_info.logon_id_high               = 0xbeef;
551         network_info->identity_info.account_name.string         = username;
552         network_info->identity_info.workstation.string          = workstation_name_slash;
553
554         memcpy(network_info->challenge, chal, 8);
555         network_info->nt = nt;
556         network_info->lm = lm;
557
558         logon->network = network_info;
559
560         /* Marshall data and send request */
561
562         status = dcerpc_netr_LogonSamLogonEx(b, mem_ctx,
563                                              server_name_slash,
564                                              lp_netbios_name(),
565                                              NetlogonNetworkInformation,
566                                              logon,
567                                              validation_level,
568                                              &validation,
569                                              &authoritative,
570                                              &flags,
571                                              &result);
572         if (!NT_STATUS_IS_OK(status)) {
573                 return status;
574         }
575
576         if (!NT_STATUS_IS_OK(result)) {
577                 return result;
578         }
579
580         netlogon_creds_decrypt_samlogon_validation(cli->dc, validation_level,
581                                                    &validation);
582
583         result = map_validation_to_info3(mem_ctx, validation_level, &validation, info3);
584         if (!NT_STATUS_IS_OK(result)) {
585                 return result;
586         }
587
588         return result;
589 }
590
591 /*********************************************************
592  Change the domain password on the PDC.
593
594  Just changes the password betwen the two values specified.
595
596  Caller must have the cli connected to the netlogon pipe
597  already.
598 **********************************************************/
599
600 NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli,
601                                             TALLOC_CTX *mem_ctx,
602                                             const char *account_name,
603                                             const unsigned char orig_trust_passwd_hash[16],
604                                             const char *new_trust_pwd_cleartext,
605                                             const unsigned char new_trust_passwd_hash[16],
606                                             enum netr_SchannelType sec_channel_type)
607 {
608         NTSTATUS result, status;
609         struct netr_Authenticator clnt_creds, srv_cred;
610         struct dcerpc_binding_handle *b = cli->binding_handle;
611
612         if (!cli->dc) {
613                 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
614                 result = rpccli_netlogon_setup_creds(cli,
615                                                      cli->desthost, /* server name */
616                                                      lp_workgroup(), /* domain */
617                                                      lp_netbios_name(), /* client name */
618                                                      account_name, /* machine account name */
619                                                      orig_trust_passwd_hash,
620                                                      sec_channel_type,
621                                                      &neg_flags);
622                 if (!NT_STATUS_IS_OK(result)) {
623                         DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n",
624                                  nt_errstr(result)));
625                         return result;
626                 }
627         }
628
629         netlogon_creds_client_authenticator(cli->dc, &clnt_creds);
630
631         if (cli->dc->negotiate_flags & NETLOGON_NEG_PASSWORD_SET2) {
632
633                 struct netr_CryptPassword new_password;
634                 uint32_t old_timeout;
635
636                 init_netr_CryptPassword(new_trust_pwd_cleartext,
637                                         cli->dc,
638                                         &new_password);
639
640                 old_timeout = dcerpc_binding_handle_set_timeout(b, 600000);
641
642                 status = dcerpc_netr_ServerPasswordSet2(b, mem_ctx,
643                                                         cli->srv_name_slash,
644                                                         cli->dc->account_name,
645                                                         sec_channel_type,
646                                                         cli->dc->computer_name,
647                                                         &clnt_creds,
648                                                         &srv_cred,
649                                                         &new_password,
650                                                         &result);
651
652                 dcerpc_binding_handle_set_timeout(b, old_timeout);
653
654                 if (!NT_STATUS_IS_OK(status)) {
655                         DEBUG(0,("dcerpc_netr_ServerPasswordSet2 failed: %s\n",
656                                 nt_errstr(status)));
657                         return status;
658                 }
659         } else {
660
661                 struct samr_Password new_password;
662                 uint32_t old_timeout;
663
664                 memcpy(new_password.hash, new_trust_passwd_hash, sizeof(new_password.hash));
665                 netlogon_creds_des_encrypt(cli->dc, &new_password);
666
667                 old_timeout = dcerpc_binding_handle_set_timeout(b, 600000);
668
669                 status = dcerpc_netr_ServerPasswordSet(b, mem_ctx,
670                                                        cli->srv_name_slash,
671                                                        cli->dc->account_name,
672                                                        sec_channel_type,
673                                                        cli->dc->computer_name,
674                                                        &clnt_creds,
675                                                        &srv_cred,
676                                                        &new_password,
677                                                        &result);
678
679                 dcerpc_binding_handle_set_timeout(b, old_timeout);
680
681                 if (!NT_STATUS_IS_OK(status)) {
682                         DEBUG(0,("dcerpc_netr_ServerPasswordSet failed: %s\n",
683                                 nt_errstr(status)));
684                         return status;
685                 }
686         }
687
688         /* Always check returned credentials. */
689         if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) {
690                 DEBUG(0,("credentials chain check failed\n"));
691                 return NT_STATUS_ACCESS_DENIED;
692         }
693
694         if (!NT_STATUS_IS_OK(result)) {
695                 DEBUG(0,("dcerpc_netr_ServerPasswordSet{2} failed: %s\n",
696                         nt_errstr(result)));
697                 return result;
698         }
699
700         return result;
701 }
702