first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[samba.git] / source / rpc_client / cli_netlogon.c
1 /* 
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
4  *  RPC Pipe client / server routines
5  *  Copyright (C) Andrew Tridgell              1992-1997,
6  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
7  *  Copyright (C) Paul Ashton                       1997.
8  *  Copyright (C) Jeremy Allison                    1998.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *  
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *  
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25
26 #ifdef SYSLOG
27 #undef SYSLOG
28 #endif
29
30 #include "includes.h"
31
32 extern int DEBUGLEVEL;
33 extern pstring scope;
34 extern pstring global_myname;
35 extern fstring global_myworkgroup;
36
37 /****************************************************************************
38 Generate the next creds to use.
39 ****************************************************************************/
40
41 static void gen_next_creds( struct cli_state *cli, DOM_CRED *new_clnt_cred)
42 {
43   /*
44    * Create the new client credentials.
45    */
46
47   cli->clnt_cred.timestamp.time = time(NULL);
48
49   memcpy(new_clnt_cred, &cli->clnt_cred, sizeof(*new_clnt_cred));
50
51   /* Calculate the new credentials. */
52   cred_create(cli->sess_key, &(cli->clnt_cred.challenge),
53               new_clnt_cred->timestamp, &(new_clnt_cred->challenge));
54
55 }
56
57 #if UNUSED_CODE
58 /****************************************************************************
59 do a LSA Logon Control2
60 ****************************************************************************/
61 BOOL cli_net_logon_ctrl2(struct cli_state *cli, uint32 status_level)
62 {
63   prs_struct rbuf;
64   prs_struct buf; 
65   NET_Q_LOGON_CTRL2 q_l;
66   BOOL ok = False;
67
68   prs_init(&buf , 1024, 4, False);
69   prs_init(&rbuf, 0,    4, True );
70
71   /* create and send a MSRPC command with api NET_LOGON_CTRL2 */
72
73   DEBUG(4,("do_net_logon_ctrl2 from %s status level:%x\n",
74            global_myname, status_level));
75
76   /* store the parameters */
77   init_q_logon_ctrl2(&q_l, cli->srv_name_slash, status_level);
78
79   /* turn parameters into data stream */
80   if(!net_io_q_logon_ctrl2("", &q_l,  &buf, 0)) {
81     DEBUG(0,("cli_net_logon_ctrl2: Error : failed to marshall NET_Q_LOGON_CTRL2 struct.\n"));
82     prs_mem_free(&buf);
83     prs_mem_free(&rbuf);
84     return False;
85   }
86
87   /* send the data on \PIPE\ */
88   if (rpc_api_pipe_req(cli, NET_LOGON_CTRL2, &buf, &rbuf))
89   {
90     NET_R_LOGON_CTRL2 r_l;
91
92     /*
93      * Unmarshall the return buffer.
94      */
95     ok = net_io_r_logon_ctrl2("", &r_l, &rbuf, 0);
96                 
97     if (ok && r_l.status != 0)
98     {
99       /* report error code */
100       DEBUG(0,("do_net_logon_ctrl2: Error %s\n", get_nt_error_msg(r_l.status)));
101       cli->nt_error = r_l.status;
102       ok = False;
103     }
104   }
105
106   prs_mem_free(&buf);
107   prs_mem_free(&rbuf);
108
109   return ok;
110 }
111 #endif
112
113 /****************************************************************************
114 LSA Authenticate 2
115
116 Send the client credential, receive back a server credential.
117 Ensure that the server credential returned matches the session key 
118 encrypt of the server challenge originally received. JRA.
119 ****************************************************************************/
120
121 BOOL cli_net_auth2(struct cli_state *cli, uint16 sec_chan, 
122                    uint32 neg_flags, DOM_CHAL *srv_chal)
123 {
124   prs_struct rbuf;
125   prs_struct buf; 
126   NET_Q_AUTH_2 q_a;
127   BOOL ok = False;
128
129   prs_init(&buf , 1024, 4, False);
130   prs_init(&rbuf, 0,    4, True );
131
132   /* create and send a MSRPC command with api NET_AUTH2 */
133
134   DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n",
135          cli->srv_name_slash, cli->mach_acct, sec_chan, global_myname,
136          credstr(cli->clnt_cred.challenge.data), neg_flags));
137
138   /* store the parameters */
139   init_q_auth_2(&q_a, cli->srv_name_slash, cli->mach_acct, sec_chan, global_myname,
140                 &cli->clnt_cred.challenge, neg_flags);
141
142   /* turn parameters into data stream */
143   if(!net_io_q_auth_2("", &q_a,  &buf, 0)) {
144     DEBUG(0,("cli_net_auth2: Error : failed to marshall NET_Q_AUTH_2 struct.\n"));
145     prs_mem_free(&buf);
146     prs_mem_free(&rbuf);
147     return False;
148   }
149
150   /* send the data on \PIPE\ */
151   if (rpc_api_pipe_req(cli, NET_AUTH2, &buf, &rbuf))
152   {
153     NET_R_AUTH_2 r_a;
154
155     ok = net_io_r_auth_2("", &r_a, &rbuf, 0);
156                 
157     if (ok && r_a.status != 0)
158     {
159       /* report error code */
160       DEBUG(0,("cli_net_auth2: Error %s\n", get_nt_error_msg(r_a.status)));
161       cli->nt_error = r_a.status;
162       ok = False;
163     }
164
165     if (ok)
166     {
167       /* 
168        * Check the returned value using the initial
169        * server received challenge.
170        */
171       UTIME zerotime;
172
173       zerotime.time = 0;
174       if(cred_assert( &r_a.srv_chal, cli->sess_key, srv_chal, zerotime) == 0) {
175         /*
176          * Server replied with bad credential. Fail.
177          */
178         DEBUG(0,("cli_net_auth2: server %s replied with bad credential (bad machine \
179 password ?).\n", cli->desthost ));
180         ok = False;
181       }
182     }
183
184 #if 0
185     /*
186      * Try commenting this out to see if this makes the connect
187      * work for a NT 3.51 PDC. JRA.
188      */
189
190     if (ok && r_a.srv_flgs.neg_flags != q_a.clnt_flgs.neg_flags)
191     {
192       /* report different neg_flags */
193       DEBUG(0,("cli_net_auth2: error neg_flags (q,r) differ - (%x,%x)\n",
194           q_a.clnt_flgs.neg_flags, r_a.srv_flgs.neg_flags));
195       ok = False;
196     }
197 #endif
198
199   }
200
201   prs_mem_free(&buf);
202   prs_mem_free(&rbuf);
203
204   return ok;
205 }
206
207 /****************************************************************************
208 LSA Request Challenge. Sends our challenge to server, then gets
209 server response. These are used to generate the credentials.
210 ****************************************************************************/
211
212 BOOL cli_net_req_chal(struct cli_state *cli, DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal)
213 {
214   prs_struct rbuf;
215   prs_struct buf; 
216   NET_Q_REQ_CHAL q_c;
217   BOOL valid_chal = False;
218
219   prs_init(&buf , 1024, 4, False);
220   prs_init(&rbuf, 0,    4, True );
221
222   /* create and send a MSRPC command with api NET_REQCHAL */
223
224   DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s: %s\n",
225          cli->desthost, global_myname, credstr(clnt_chal->data)));
226
227   /* store the parameters */
228   init_q_req_chal(&q_c, cli->srv_name_slash, global_myname, clnt_chal);
229
230   /* turn parameters into data stream */
231   if(!net_io_q_req_chal("", &q_c,  &buf, 0)) {
232     DEBUG(0,("cli_net_req_chal: Error : failed to marshall NET_Q_REQ_CHAL struct.\n"));
233     prs_mem_free(&buf);
234     prs_mem_free(&rbuf);
235     return False;
236   }
237
238   /* send the data on \PIPE\ */
239   if (rpc_api_pipe_req(cli, NET_REQCHAL, &buf, &rbuf))
240   {
241     NET_R_REQ_CHAL r_c;
242     BOOL ok;
243
244     ok = net_io_r_req_chal("", &r_c, &rbuf, 0);
245                 
246     if (ok && r_c.status != 0)
247     {
248       /* report error code */
249       DEBUG(0,("cli_net_req_chal: Error %s\n", get_nt_error_msg(r_c.status)));
250       cli->nt_error = r_c.status;
251       ok = False;
252     }
253
254     if (ok)
255     {
256       /* ok, at last: we're happy. return the challenge */
257       memcpy(srv_chal, r_c.srv_chal.data, sizeof(srv_chal->data));
258       valid_chal = True;
259     }
260   }
261
262   prs_mem_free(&buf);
263   prs_mem_free(&rbuf);
264
265   return valid_chal;
266 }
267
268 /***************************************************************************
269 LSA Server Password Set.
270 ****************************************************************************/
271
272 BOOL cli_net_srv_pwset(struct cli_state *cli, uint8 hashed_mach_pwd[16])
273 {
274   prs_struct rbuf;
275   prs_struct buf; 
276   DOM_CRED new_clnt_cred;
277   NET_Q_SRV_PWSET q_s;
278   BOOL ok = False;
279   uint16 sec_chan_type = 2;
280
281   gen_next_creds( cli, &new_clnt_cred);
282
283   prs_init(&buf , 1024, 4, False);
284   prs_init(&rbuf, 0,    4, True );
285
286   /* create and send a MSRPC command with api NET_SRV_PWSET */
287
288   DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s clnt %s %x\n",
289            cli->srv_name_slash, cli->mach_acct, sec_chan_type, global_myname,
290            credstr(new_clnt_cred.challenge.data), new_clnt_cred.timestamp.time));
291
292   /* store the parameters */
293   init_q_srv_pwset(&q_s, cli->srv_name_slash, cli->mach_acct, sec_chan_type,
294                    global_myname, &new_clnt_cred, (char *)hashed_mach_pwd);
295
296   /* turn parameters into data stream */
297   if(!net_io_q_srv_pwset("", &q_s,  &buf, 0)) {
298     DEBUG(0,("cli_net_srv_pwset: Error : failed to marshall NET_Q_SRV_PWSET struct.\n"));
299     prs_mem_free(&buf);
300     prs_mem_free(&rbuf);
301     return False;
302   }
303
304   /* send the data on \PIPE\ */
305   if (rpc_api_pipe_req(cli, NET_SRVPWSET, &buf, &rbuf))
306   {
307     NET_R_SRV_PWSET r_s;
308
309     ok = net_io_r_srv_pwset("", &r_s, &rbuf, 0);
310                 
311     if (ok && r_s.status != 0)
312     {
313       /* report error code */
314       DEBUG(0,("cli_net_srv_pwset: %s\n", get_nt_error_msg(r_s.status)));
315       cli->nt_error = r_s.status;
316       ok = False;
317     }
318
319     /* Update the credentials. */
320     if (ok && !clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &(r_s.srv_cred)))
321     {
322       /*
323        * Server replied with bad credential. Fail.
324        */
325       DEBUG(0,("cli_net_srv_pwset: server %s replied with bad credential (bad machine \
326 password ?).\n", cli->desthost ));
327       ok = False;
328     }
329   }
330
331   prs_mem_free(&buf);
332   prs_mem_free(&rbuf);
333
334   return ok;
335 }
336
337 /***************************************************************************
338 LSA SAM Logon - interactive or network.
339 ****************************************************************************/
340
341 BOOL cli_net_sam_logon(struct cli_state *cli, NET_ID_INFO_CTR *ctr, 
342                        NET_USER_INFO_3 *user_info3)
343 {
344   DOM_CRED new_clnt_cred;
345   DOM_CRED dummy_rtn_creds;
346   prs_struct rbuf;
347   prs_struct buf; 
348   uint16 validation_level = 3;
349   NET_Q_SAM_LOGON q_s;
350   BOOL ok = False;
351
352   gen_next_creds( cli, &new_clnt_cred);
353
354   prs_init(&buf , 1024, 4, False);
355   prs_init(&rbuf, 0,    4, True );
356
357   /* create and send a MSRPC command with api NET_SAMLOGON */
358
359   DEBUG(4,("cli_net_sam_logon: srv:%s mc:%s clnt %s %x ll: %d\n",
360              cli->srv_name_slash, global_myname, 
361              credstr(new_clnt_cred.challenge.data), cli->clnt_cred.timestamp.time,
362              ctr->switch_value));
363
364   memset(&dummy_rtn_creds, '\0', sizeof(dummy_rtn_creds));
365         dummy_rtn_creds.timestamp.time = time(NULL);
366
367   /* store the parameters */
368   q_s.validation_level = validation_level;
369   init_sam_info(&q_s.sam_id, cli->srv_name_slash, global_myname,
370          &new_clnt_cred, &dummy_rtn_creds, ctr->switch_value, ctr);
371
372   /* turn parameters into data stream */
373   if(!net_io_q_sam_logon("", &q_s,  &buf, 0)) {
374     DEBUG(0,("cli_net_sam_logon: Error : failed to marshall NET_Q_SAM_LOGON struct.\n"));
375     prs_mem_free(&buf);
376     prs_mem_free(&rbuf);
377     return False;
378   }
379
380   /* send the data on \PIPE\ */
381   if (rpc_api_pipe_req(cli, NET_SAMLOGON, &buf, &rbuf))
382   {
383     NET_R_SAM_LOGON r_s;
384
385     r_s.user = user_info3;
386
387     ok = net_io_r_sam_logon("", &r_s, &rbuf, 0);
388                 
389     if (ok && r_s.status != 0)
390     {
391       /* report error code */
392       DEBUG(0,("cli_net_sam_logon: %s\n", get_nt_error_msg(r_s.status)));
393       cli->nt_error = r_s.status;
394       ok = False;
395     }
396
397     /* Update the credentials. */
398     if (ok && !clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &(r_s.srv_creds)))
399     {
400       /*
401        * Server replied with bad credential. Fail.
402        */
403       DEBUG(0,("cli_net_sam_logon: server %s replied with bad credential (bad machine \
404 password ?).\n", cli->desthost ));
405         ok = False;
406     }
407
408     if (ok && r_s.switch_value != 3)
409     {
410       /* report different switch_value */
411       DEBUG(0,("cli_net_sam_logon: switch_value of 3 expected %x\n",
412                    r_s.switch_value));
413       ok = False;
414     }
415   }
416
417   prs_mem_free(&buf);
418   prs_mem_free(&rbuf);
419
420   return ok;
421 }
422
423 /***************************************************************************
424 LSA SAM Logoff.
425
426 This currently doesnt work correctly as the domain controller 
427 returns NT_STATUS_INVALID_INFO_CLASS - we obviously need to
428 send a different info level. Right now though, I'm not sure
429 what that needs to be (I need to see one on the wire before
430 I can be sure). JRA.
431 ****************************************************************************/
432 BOOL cli_net_sam_logoff(struct cli_state *cli, NET_ID_INFO_CTR *ctr)
433 {
434   DOM_CRED new_clnt_cred;
435   DOM_CRED dummy_rtn_creds;
436   prs_struct rbuf;
437   prs_struct buf; 
438   NET_Q_SAM_LOGOFF q_s;
439   BOOL ok = False;
440
441   gen_next_creds( cli, &new_clnt_cred);
442
443   prs_init(&buf , 1024, 4, False);
444   prs_init(&rbuf, 0,    4, True );
445
446   /* create and send a MSRPC command with api NET_SAMLOGOFF */
447
448   DEBUG(4,("cli_net_sam_logoff: srv:%s mc:%s clnt %s %x ll: %d\n",
449             cli->srv_name_slash, global_myname,
450             credstr(new_clnt_cred.challenge.data), new_clnt_cred.timestamp.time,
451             ctr->switch_value));
452
453   memset(&dummy_rtn_creds, '\0', sizeof(dummy_rtn_creds));
454
455   init_sam_info(&q_s.sam_id, cli->srv_name_slash, global_myname,
456                 &new_clnt_cred, &dummy_rtn_creds, ctr->switch_value, ctr);
457
458   /* turn parameters into data stream */
459   if(!net_io_q_sam_logoff("", &q_s,  &buf, 0)) {
460     DEBUG(0,("cli_net_sam_logoff: Error : failed to marshall NET_Q_SAM_LOGOFF struct.\n"));
461     prs_mem_free(&buf);
462     prs_mem_free(&rbuf);
463     return False;
464   }
465
466   /* send the data on \PIPE\ */
467   if (rpc_api_pipe_req(cli, NET_SAMLOGOFF, &buf, &rbuf))
468   {
469     NET_R_SAM_LOGOFF r_s;
470
471     ok = net_io_r_sam_logoff("", &r_s, &rbuf, 0);
472                 
473     if (ok && r_s.status != 0)
474     {
475       /* report error code */
476       DEBUG(0,("cli_net_sam_logoff: %s\n", get_nt_error_msg(r_s.status)));
477       cli->nt_error = r_s.status;
478       ok = False;
479     }
480
481     /* Update the credentials. */
482     if (ok && !clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &(r_s.srv_creds)))
483     {
484       /*
485        * Server replied with bad credential. Fail.
486        */
487       DEBUG(0,("cli_net_sam_logoff: server %s replied with bad credential (bad machine \
488 password ?).\n", cli->desthost ));
489       ok = False;
490     }
491   }
492
493   prs_mem_free(&buf);
494   prs_mem_free(&rbuf);
495
496   return ok;
497 }
498
499 /*********************************************************
500  Change the domain password on the PDC.
501 **********************************************************/
502
503 static BOOL modify_trust_password( char *domain, char *remote_machine, 
504                           unsigned char orig_trust_passwd_hash[16],
505                           unsigned char new_trust_passwd_hash[16])
506 {
507   struct cli_state cli;
508
509   ZERO_STRUCT(cli);
510   if(cli_initialise(&cli) == False) {
511     DEBUG(0,("modify_trust_password: unable to initialize client connection.\n"));
512     return False;
513   }
514
515   if(!resolve_name( remote_machine, &cli.dest_ip, 0x20)) {
516     DEBUG(0,("modify_trust_password: Can't resolve address for %s\n", remote_machine));
517     return False;
518   }
519
520   if (ismyip(cli.dest_ip)) {
521     DEBUG(0,("modify_trust_password: Machine %s is one of our addresses. Cannot add \
522 to ourselves.\n", remote_machine));
523     return False;
524   }
525
526   if (!cli_connect(&cli, remote_machine, &cli.dest_ip)) {
527     DEBUG(0,("modify_trust_password: unable to connect to SMB server on \
528 machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
529     return False;
530   }
531   
532   if (!attempt_netbios_session_request(&cli, global_myname, remote_machine, &cli.dest_ip)) {
533     DEBUG(0,("modify_trust_password: machine %s rejected the NetBIOS \
534 session request. Error was %s\n", remote_machine, cli_errstr(&cli) ));
535     return False;
536   }
537
538   cli.protocol = PROTOCOL_NT1;
539     
540   if (!cli_negprot(&cli)) {
541     DEBUG(0,("modify_trust_password: machine %s rejected the negotiate protocol. \
542 Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
543     cli_shutdown(&cli);
544     return False;
545   }
546
547   if (cli.protocol != PROTOCOL_NT1) {
548     DEBUG(0,("modify_trust_password: machine %s didn't negotiate NT protocol.\n", 
549             remote_machine));
550     cli_shutdown(&cli);
551     return False;
552   }
553     
554   /*
555    * Do an anonymous session setup.
556    */
557     
558   if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) {
559     DEBUG(0,("modify_trust_password: machine %s rejected the session setup. \
560 Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
561     cli_shutdown(&cli);
562     return False;
563   }
564     
565   if (!(cli.sec_mode & 1)) {
566     DEBUG(0,("modify_trust_password: machine %s isn't in user level security mode\n",
567           remote_machine));
568     cli_shutdown(&cli);
569     return False;
570   }
571     
572   if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
573     DEBUG(0,("modify_trust_password: machine %s rejected the tconX on the IPC$ share. \
574 Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
575     cli_shutdown(&cli);
576     return False;
577   }
578
579   /*
580    * Ok - we have an anonymous connection to the IPC$ share.
581    * Now start the NT Domain stuff :-).
582    */
583     
584   if(cli_nt_session_open(&cli, PIPE_NETLOGON) == False) {
585     DEBUG(0,("modify_trust_password: unable to open the domain client session to \
586 machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli)));
587     cli_nt_session_close(&cli);
588     cli_ulogoff(&cli);
589     cli_shutdown(&cli);
590     return False;
591   } 
592   
593   if(cli_nt_setup_creds(&cli, orig_trust_passwd_hash) == False) {
594     DEBUG(0,("modify_trust_password: unable to setup the PDC credentials to machine \
595 %s. Error was : %s.\n", remote_machine, cli_errstr(&cli)));
596     cli_nt_session_close(&cli);
597     cli_ulogoff(&cli);
598     cli_shutdown(&cli);
599     return False;
600   } 
601
602   if( cli_nt_srv_pwset( &cli,new_trust_passwd_hash ) == False) {
603     DEBUG(0,("modify_trust_password: unable to change password for machine %s in domain \
604 %s to Domain controller %s. Error was %s.\n", global_myname, domain, remote_machine, 
605                             cli_errstr(&cli)));
606     cli_close(&cli, cli.nt_pipe_fnum);
607     cli_ulogoff(&cli);
608     cli_shutdown(&cli);
609     return False;
610   }
611
612   cli_nt_session_close(&cli);
613   cli_ulogoff(&cli);
614   cli_shutdown(&cli);
615
616   return True;
617 }
618
619 /************************************************************************
620  Change the trust account password for a domain.
621  The user of this function must have locked the trust password file for
622  update.
623 ************************************************************************/
624
625 BOOL change_trust_account_password( char *domain, char *remote_machine_list)
626 {
627   fstring remote_machine;
628   unsigned char old_trust_passwd_hash[16];
629   unsigned char new_trust_passwd_hash[16];
630   time_t lct;
631   BOOL res;
632
633   if(!get_trust_account_password( old_trust_passwd_hash, &lct)) {
634     DEBUG(0,("change_trust_account_password: unable to read the machine \
635 account password for domain %s.\n", domain));
636     return False;
637   }
638
639   /*
640    * Create the new (random) password.
641    */
642   generate_random_buffer( new_trust_passwd_hash, 16, True);
643
644   while(remote_machine_list && 
645         next_token(&remote_machine_list, remote_machine, 
646                    LIST_SEP, sizeof(remote_machine))) {
647     strupper(remote_machine);
648     if(strequal(remote_machine, "*")) {
649
650       /*
651        * We have been asked to dynamcially determine the IP addresses of the PDC.
652        */
653
654       struct in_addr *ip_list = NULL;
655       int count = 0;
656       int i;
657
658       if(!get_dc_list(domain, &ip_list, &count))
659         continue;
660
661       /*
662        * Try and connect to the PDC/BDC list in turn as an IP
663        * address used as a string.
664        */
665
666       for(i = 0; i < count; i++) {
667         fstring dc_name;
668         if(!lookup_pdc_name(global_myname, domain, &ip_list[i], dc_name))
669           continue;
670         if((res = modify_trust_password( domain, dc_name,
671                                          old_trust_passwd_hash, new_trust_passwd_hash)))
672           break;
673       }
674
675       if(ip_list != NULL)
676         free((char *)ip_list);
677
678     } else {
679       res = modify_trust_password( domain, remote_machine,
680                                    old_trust_passwd_hash, new_trust_passwd_hash);
681     }
682
683     if(res) {
684       DEBUG(0,("%s : change_trust_account_password: Changed password for \
685 domain %s.\n", timestring(False), domain));
686       /*
687        * Return the result of trying to write the new password
688        * back into the trust account file.
689        */
690       res = set_trust_account_password(new_trust_passwd_hash);
691       memset(new_trust_passwd_hash, 0, 16);
692       memset(old_trust_passwd_hash, 0, 16);
693       return res;
694     }
695   }
696
697   memset(new_trust_passwd_hash, 0, 16);
698   memset(old_trust_passwd_hash, 0, 16);
699
700   DEBUG(0,("%s : change_trust_account_password: Failed to change password for \
701 domain %s.\n", timestring(False), domain));
702   return False;
703 }