sync 3.0 into HEAD for the last time
[vlendec/samba-autobuild/.git] / source3 / nsswitch / winbindd_util.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon for ntdom nss module
5
6    Copyright (C) Tim Potter 2000-2001
7    Copyright (C) 2001 by Martin Pool <mbp@samba.org>
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 2 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, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "winbindd.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_WINBIND
28
29 /**
30  * @file winbindd_util.c
31  *
32  * Winbind daemon for NT domain authentication nss module.
33  **/
34
35
36 /**
37  * Used to clobber name fields that have an undefined value.
38  *
39  * Correct code should never look at a field that has this value.
40  **/
41
42 static const fstring name_deadbeef = "<deadbeef>";
43
44 /* The list of trusted domains.  Note that the list can be deleted and
45    recreated using the init_domain_list() function so pointers to
46    individual winbindd_domain structures cannot be made.  Keep a copy of
47    the domain name instead. */
48
49 static struct winbindd_domain *_domain_list;
50
51 struct winbindd_domain *domain_list(void)
52 {
53         /* Initialise list */
54
55         if (!_domain_list)
56                 init_domain_list();
57
58         return _domain_list;
59 }
60
61 /* Free all entries in the trusted domain list */
62
63 void free_domain_list(void)
64 {
65         struct winbindd_domain *domain = _domain_list;
66
67         while(domain) {
68                 struct winbindd_domain *next = domain->next;
69                 
70                 DLIST_REMOVE(_domain_list, domain);
71                 SAFE_FREE(domain);
72                 domain = next;
73         }
74 }
75
76
77 /* Add a trusted domain to our list of domains */
78 static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name,
79                                                   struct winbindd_methods *methods,
80                                                   DOM_SID *sid)
81 {
82         struct winbindd_domain *domain;
83         char *contact_name;
84         const char *alternative_name = NULL;
85         
86         /* ignore alt_name if we are not in an AD domain */
87         
88         if ( (lp_security() == SEC_ADS) && alt_name && *alt_name) {
89                 alternative_name = alt_name;
90         }
91         
92         /* We can't call domain_list() as this function is called from
93            init_domain_list() and we'll get stuck in a loop. */
94         for (domain = _domain_list; domain; domain = domain->next) {
95                 if (strcasecmp(domain_name, domain->name) == 0 ||
96                     strcasecmp(domain_name, domain->alt_name) == 0) {
97                         return domain;
98                 }
99                 if (alternative_name && *alternative_name) {
100                         if (strcasecmp(alternative_name, domain->name) == 0 ||
101                             strcasecmp(alternative_name, domain->alt_name) == 0) {
102                                 return domain;
103                         }
104                 }
105         }
106         
107         /* Create new domain entry */
108
109         if ((domain = (struct winbindd_domain *)
110              malloc(sizeof(*domain))) == NULL)
111                 return NULL;
112
113         /* Fill in fields */
114         
115         ZERO_STRUCTP(domain);
116
117         /* prioritise the short name */
118         if (strchr_m(domain_name, '.') && alternative_name && *alternative_name) {
119                 fstrcpy(domain->name, alternative_name);
120                 fstrcpy(domain->alt_name, domain_name);
121         } else {
122                 fstrcpy(domain->name, domain_name);
123                 if (alternative_name) {
124                         fstrcpy(domain->alt_name, alternative_name);
125                 }
126         }
127
128         domain->methods = methods;
129         domain->backend = NULL;
130         domain->sequence_number = DOM_SEQUENCE_NONE;
131         domain->last_seq_check = 0;
132         if (sid) {
133                 sid_copy(&domain->sid, sid);
134         }
135         
136         /* see if this is a native mode win2k domain (use realm name if possible) */
137            
138         contact_name = *domain->alt_name ? domain->alt_name : domain->name;
139         domain->native_mode = cm_check_for_native_mode_win2k( contact_name );
140         
141         DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", contact_name,
142                 domain->native_mode ? "native" : "mixed (or NT4)" ));
143
144         /* Link to domain list */
145         DLIST_ADD(_domain_list, domain);
146         
147         DEBUG(1,("Added domain %s %s %s\n", 
148                  domain->name, domain->alt_name,
149                  sid?sid_string_static(&domain->sid):""));
150         
151         return domain;
152 }
153
154 /********************************************************************
155  Periodically we need to refresh the trusted domain cache for smbd 
156 ********************************************************************/
157
158 void rescan_trusted_domains( void )
159 {
160         static time_t last_scan;
161         time_t now = time(NULL);
162         struct winbindd_domain *mydomain = NULL;
163         
164         /* see if the time has come... */
165         
166         if ( (now > last_scan) && ((now-last_scan) < WINBINDD_RESCAN_FREQ) )
167                 return;
168                 
169         /* get the handle for our domain */
170         
171         if ( (mydomain = find_domain_from_name(lp_workgroup())) == NULL ) {
172                 DEBUG(0,("rescan_trusted_domains: Can't find my own domain!\n"));
173                 return;
174         }
175         
176         /* this will only add new domains we didn't already know about */
177         
178         add_trusted_domains( mydomain );
179
180         last_scan = now;
181         
182         return; 
183 }
184
185 /********************************************************************
186   rescan our domains looking for new trusted domains
187 ********************************************************************/
188
189 void add_trusted_domains( struct winbindd_domain *domain )
190 {
191         TALLOC_CTX *mem_ctx;
192         NTSTATUS result;
193         time_t t;
194         char **names;
195         char **alt_names;
196         int num_domains = 0;
197         DOM_SID *dom_sids, null_sid;
198         int i;
199         struct winbindd_domain *new_domain;
200
201         /* trusted domains might be disabled */
202         if (!lp_allow_trusted_domains()) {
203                 return;
204         }
205
206         DEBUG(1, ("scanning trusted domain list\n"));
207
208         if (!(mem_ctx = talloc_init("init_domain_list")))
209                 return;
210            
211         ZERO_STRUCTP(&null_sid);
212
213         t = time(NULL);
214         
215         /* ask the DC what domains it trusts */
216         
217         result = domain->methods->trusted_domains(domain, mem_ctx, (unsigned int *)&num_domains,
218                 &names, &alt_names, &dom_sids);
219                 
220         if ( NT_STATUS_IS_OK(result) ) {
221
222                 /* Add each domain to the trusted domain list */
223                 
224                 for(i = 0; i < num_domains; i++) {
225                         DEBUG(10,("Found domain %s\n", names[i]));
226                         add_trusted_domain(names[i], alt_names?alt_names[i]:NULL,
227                                 domain->methods, &dom_sids[i]);
228                                            
229                         /* if the SID was empty, we better set it now */
230                         
231                         if ( sid_equal(&dom_sids[i], &null_sid) ) {
232                         
233                                 new_domain = find_domain_from_name(names[i]);
234                                  
235                                 /* this should never happen */
236                                 if ( !new_domain ) {    
237                                         DEBUG(0,("rescan_trust_domains: can't find the domain I just added! [%s]\n",
238                                                 names[i]));
239                                         break;
240                                 }
241                                  
242                                 /* call the cache method; which will operate on the winbindd_domain \
243                                    passed in and choose either rpc or ads as appropriate */
244
245                                 result = domain->methods->domain_sid( new_domain, &new_domain->sid );
246                                  
247                                 if ( NT_STATUS_IS_OK(result) )
248                                         sid_copy( &dom_sids[i], &new_domain->sid );
249                         }
250                         
251                         /* store trusted domain in the cache */
252                         trustdom_cache_store(names[i], alt_names ? alt_names[i] : NULL,
253                                              &dom_sids[i], t + WINBINDD_RESCAN_FREQ);
254                 }
255         }
256
257         talloc_destroy(mem_ctx);
258 }
259
260 /* Look up global info for the winbind daemon */
261 BOOL init_domain_list(void)
262 {
263         extern struct winbindd_methods cache_methods;
264         struct winbindd_domain *domain;
265
266         /* Free existing list */
267         free_domain_list();
268
269         /* Add ourselves as the first entry */
270         
271         domain = add_trusted_domain( lp_workgroup(), lp_realm(), &cache_methods, NULL);
272         
273         /* get any alternate name for the primary domain */
274         
275         cache_methods.alternate_name(domain);
276         
277         /* now we have the correct netbios (short) domain name */
278         
279         if ( *domain->name )
280                 set_global_myworkgroup( domain->name );
281                 
282         if (!secrets_fetch_domain_sid(domain->name, &domain->sid)) {
283                 DEBUG(1, ("Could not fetch sid for our domain %s\n",
284                           domain->name));
285                 return False;
286         }
287
288         /* do an initial scan for trusted domains */
289         add_trusted_domains(domain);
290
291         return True;
292 }
293
294 /* Given a domain name, return the struct winbindd domain info for it 
295    if it is actually working. */
296
297 struct winbindd_domain *find_domain_from_name(const char *domain_name)
298 {
299         struct winbindd_domain *domain;
300
301         /* Search through list */
302
303         for (domain = domain_list(); domain != NULL; domain = domain->next) {
304                 if (strequal(domain_name, domain->name) ||
305                     (domain->alt_name[0] && strequal(domain_name, domain->alt_name)))
306                         return domain;
307         }
308
309         /* Not found */
310
311         return NULL;
312 }
313
314 /* Given a domain sid, return the struct winbindd domain info for it */
315
316 struct winbindd_domain *find_domain_from_sid(DOM_SID *sid)
317 {
318         struct winbindd_domain *domain;
319
320         /* Search through list */
321
322         for (domain = domain_list(); domain != NULL; domain = domain->next) {
323                 if (sid_compare_domain(sid, &domain->sid) == 0)
324                         return domain;
325         }
326
327         /* Not found */
328
329         return NULL;
330 }
331
332 /* Lookup a sid in a domain from a name */
333
334 BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain, 
335                                  const char *name, DOM_SID *sid, 
336                                  enum SID_NAME_USE *type)
337 {
338         NTSTATUS result;
339         TALLOC_CTX *mem_ctx;
340         /* Don't bother with machine accounts */
341
342         if (name[strlen(name) - 1] == '$')
343                 return False;
344
345         mem_ctx = talloc_init("lookup_sid_by_name for %s\n", name);
346         if (!mem_ctx) 
347                 return False;
348         
349         /* Lookup name */
350         result = domain->methods->name_to_sid(domain, mem_ctx, name, sid, type);
351
352         talloc_destroy(mem_ctx);
353         
354         /* Return rid and type if lookup successful */
355         if (!NT_STATUS_IS_OK(result)) {
356                 *type = SID_NAME_UNKNOWN;
357         }
358
359         return NT_STATUS_IS_OK(result);
360 }
361
362 /**
363  * @brief Lookup a name in a domain from a sid.
364  *
365  * @param sid Security ID you want to look up.
366  * @param name On success, set to the name corresponding to @p sid.
367  * @param dom_name On success, set to the 'domain name' corresponding to @p sid.
368  * @param type On success, contains the type of name: alias, group or
369  * user.
370  * @retval True if the name exists, in which case @p name and @p type
371  * are set, otherwise False.
372  **/
373 BOOL winbindd_lookup_name_by_sid(DOM_SID *sid,
374                                  fstring dom_name,
375                                  fstring name,
376                                  enum SID_NAME_USE *type)
377 {
378         char *names;
379         NTSTATUS result;
380         TALLOC_CTX *mem_ctx;
381         BOOL rv = False;
382         struct winbindd_domain *domain;
383
384         domain = find_domain_from_sid(sid);
385
386         if (!domain) {
387                 DEBUG(1,("Can't find domain from sid\n"));
388                 return False;
389         }
390
391         /* Lookup name */
392
393         if (!(mem_ctx = talloc_init("winbindd_lookup_name_by_sid")))
394                 return False;
395         
396         result = domain->methods->sid_to_name(domain, mem_ctx, sid, &names, type);
397
398         /* Return name and type if successful */
399         
400         if ((rv = NT_STATUS_IS_OK(result))) {
401                 fstrcpy(dom_name, domain->name);
402                 fstrcpy(name, names);
403         } else {
404                 *type = SID_NAME_UNKNOWN;
405                 fstrcpy(name, name_deadbeef);
406         }
407         
408         talloc_destroy(mem_ctx);
409
410         return rv;
411 }
412
413
414 /* Free state information held for {set,get,end}{pw,gr}ent() functions */
415
416 void free_getent_state(struct getent_state *state)
417 {
418         struct getent_state *temp;
419
420         /* Iterate over state list */
421
422         temp = state;
423
424         while(temp != NULL) {
425                 struct getent_state *next;
426
427                 /* Free sam entries then list entry */
428
429                 SAFE_FREE(state->sam_entries);
430                 DLIST_REMOVE(state, state);
431                 next = temp->next;
432
433                 SAFE_FREE(temp);
434                 temp = next;
435         }
436 }
437
438 /* Parse winbindd related parameters */
439
440 BOOL winbindd_param_init(void)
441 {
442         /* Parse winbind uid and winbind_gid parameters */
443
444         if (!lp_idmap_uid(&server_state.uid_low, &server_state.uid_high)) {
445                 DEBUG(0, ("winbindd: idmap uid range missing or invalid\n"));
446                 DEBUG(0, ("winbindd: cannot continue, exiting.\n"));
447                 return False;
448         }
449         
450         if (!lp_idmap_gid(&server_state.gid_low, &server_state.gid_high)) {
451                 DEBUG(0, ("winbindd: idmap gid range missing or invalid\n"));
452                 DEBUG(0, ("winbindd: cannot continue, exiting.\n"));
453                 return False;
454         }
455         
456         return True;
457 }
458
459 /* Check if a domain is present in a comma-separated list of domains */
460
461 BOOL check_domain_env(char *domain_env, char *domain)
462 {
463         fstring name;
464         const char *tmp = domain_env;
465
466         while(next_token(&tmp, name, ",", sizeof(fstring))) {
467                 if (strequal(name, domain))
468                         return True;
469         }
470
471         return False;
472 }
473
474 /* Parse a string of the form DOMAIN/user into a domain and a user */
475
476 BOOL parse_domain_user(const char *domuser, fstring domain, fstring user)
477 {
478         char *p = strchr(domuser,*lp_winbind_separator());
479
480         if ( !p ) {
481                 fstrcpy(user, domuser);
482                 
483                 if ( lp_winbind_use_default_domain() )
484                         fstrcpy(domain, lp_workgroup());
485                 else
486                         fstrcpy( domain, "" );
487         } 
488         else {
489                 fstrcpy(user, p+1);
490                 fstrcpy(domain, domuser);
491                 domain[PTR_DIFF(p, domuser)] = 0;
492         }
493         
494         strupper_m(domain);
495         
496         return True;
497 }
498
499 /*
500     Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
501     'winbind separator' options.
502     This means:
503         - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
504         lp_workgroup
505          
506 */
507 void fill_domain_username(fstring name, const char *domain, const char *user)
508 {
509         if(lp_winbind_use_default_domain() &&
510             !strcmp(lp_workgroup(), domain)) {
511                 strlcpy(name, user, sizeof(fstring));
512         } else {
513                 slprintf(name, sizeof(fstring) - 1, "%s%s%s",
514                          domain, lp_winbind_separator(),
515                          user);
516         }
517 }
518
519 /*
520  * Winbindd socket accessor functions
521  */
522
523 char *get_winbind_priv_pipe_dir(void) 
524 {
525         return lock_path(WINBINDD_PRIV_SOCKET_SUBDIR);
526 }
527
528 /* Open the winbindd socket */
529
530 static int _winbindd_socket = -1;
531 static int _winbindd_priv_socket = -1;
532
533 int open_winbindd_socket(void)
534 {
535         if (_winbindd_socket == -1) {
536                 _winbindd_socket = create_pipe_sock(
537                         WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME, 0755);
538                 DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n",
539                            _winbindd_socket));
540         }
541
542         return _winbindd_socket;
543 }
544
545 int open_winbindd_priv_socket(void)
546 {
547         if (_winbindd_priv_socket == -1) {
548                 _winbindd_priv_socket = create_pipe_sock(
549                         get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
550                 DEBUG(10, ("open_winbindd_priv_socket: opened socket fd %d\n",
551                            _winbindd_priv_socket));
552         }
553
554         return _winbindd_priv_socket;
555 }
556
557 /* Close the winbindd socket */
558
559 void close_winbindd_socket(void)
560 {
561         if (_winbindd_socket != -1) {
562                 DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
563                            _winbindd_socket));
564                 close(_winbindd_socket);
565                 _winbindd_socket = -1;
566         }
567         if (_winbindd_priv_socket != -1) {
568                 DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
569                            _winbindd_priv_socket));
570                 close(_winbindd_priv_socket);
571                 _winbindd_priv_socket = -1;
572         }
573 }
574
575 /*
576  * Client list accessor functions
577  */
578
579 static struct winbindd_cli_state *_client_list;
580 static int _num_clients;
581
582 /* Return list of all connected clients */
583
584 struct winbindd_cli_state *winbindd_client_list(void)
585 {
586         return _client_list;
587 }
588
589 /* Add a connection to the list */
590
591 void winbindd_add_client(struct winbindd_cli_state *cli)
592 {
593         DLIST_ADD(_client_list, cli);
594         _num_clients++;
595 }
596
597 /* Remove a client from the list */
598
599 void winbindd_remove_client(struct winbindd_cli_state *cli)
600 {
601         DLIST_REMOVE(_client_list, cli);
602         _num_clients--;
603 }
604
605 /* Close all open clients */
606
607 void winbindd_kill_all_clients(void)
608 {
609         struct winbindd_cli_state *cl = winbindd_client_list();
610
611         DEBUG(10, ("winbindd_kill_all_clients: going postal\n"));
612
613         while (cl) {
614                 struct winbindd_cli_state *next;
615                 
616                 next = cl->next;
617                 winbindd_remove_client(cl);
618                 cl = next;
619         }
620 }
621
622 /* Return number of open clients */
623
624 int winbindd_num_clients(void)
625 {
626         return _num_clients;
627 }
628
629 /* Help with RID -> SID conversion */
630
631 DOM_SID *rid_to_talloced_sid(struct winbindd_domain *domain,
632                                     TALLOC_CTX *mem_ctx,
633                                     uint32 rid) 
634 {
635         DOM_SID *sid;
636         sid = talloc(mem_ctx, sizeof(*sid));
637         if (!sid) {
638                 smb_panic("rid_to_to_talloced_sid: talloc for DOM_SID failed!\n");
639         }
640         sid_copy(sid, &domain->sid);
641         sid_append_rid(sid, rid);
642         return sid;
643 }
644         
645 /*****************************************************************************
646  For idmap conversion: convert one record to new format
647  Ancient versions (eg 2.2.3a) of winbindd_idmap.tdb mapped DOMAINNAME/rid
648  instead of the SID.
649 *****************************************************************************/
650 static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state)
651 {
652         struct winbindd_domain *domain;
653         char *p;
654         DOM_SID sid;
655         uint32 rid;
656         fstring keystr;
657         fstring dom_name;
658         TDB_DATA key2;
659         BOOL *failed = (BOOL *)state;
660
661         DEBUG(10,("Converting %s\n", key.dptr));
662
663         p = strchr(key.dptr, '/');
664         if (!p)
665                 return 0;
666
667         *p = 0;
668         fstrcpy(dom_name, key.dptr);
669         *p++ = '/';
670
671         domain = find_domain_from_name(dom_name);
672         if (domain == NULL) {
673                 /* We must delete the old record. */
674                 DEBUG(0,("Unable to find domain %s\n", dom_name ));
675                 DEBUG(0,("deleting record %s\n", key.dptr ));
676
677                 if (tdb_delete(tdb, key) != 0) {
678                         DEBUG(0, ("Unable to delete record %s\n", key.dptr));
679                         *failed = True;
680                         return -1;
681                 }
682
683                 return 0;
684         }
685
686         rid = atoi(p);
687
688         sid_copy(&sid, &domain->sid);
689         sid_append_rid(&sid, rid);
690
691         sid_to_string(keystr, &sid);
692         key2.dptr = keystr;
693         key2.dsize = strlen(keystr) + 1;
694
695         if (tdb_store(tdb, key2, data, TDB_INSERT) != 0) {
696                 DEBUG(0,("Unable to add record %s\n", key2.dptr ));
697                 *failed = True;
698                 return -1;
699         }
700
701         if (tdb_store(tdb, data, key2, TDB_REPLACE) != 0) {
702                 DEBUG(0,("Unable to update record %s\n", data.dptr ));
703                 *failed = True;
704                 return -1;
705         }
706
707         if (tdb_delete(tdb, key) != 0) {
708                 DEBUG(0,("Unable to delete record %s\n", key.dptr ));
709                 *failed = True;
710                 return -1;
711         }
712
713         return 0;
714 }
715
716 /* These definitions are from sam/idmap_tdb.c. Replicated here just
717    out of laziness.... :-( */
718
719 /* High water mark keys */
720 #define HWM_GROUP  "GROUP HWM"
721 #define HWM_USER   "USER HWM"
722
723 /* idmap version determines auto-conversion */
724 #define IDMAP_VERSION 2
725
726
727 /*****************************************************************************
728  Convert the idmap database from an older version.
729 *****************************************************************************/
730
731 static BOOL idmap_convert(const char *idmap_name)
732 {
733         int32 vers;
734         BOOL bigendianheader;
735         BOOL failed = False;
736         TDB_CONTEXT *idmap_tdb;
737
738         if (!(idmap_tdb = tdb_open_log(idmap_name, 0,
739                                         TDB_DEFAULT, O_RDWR,
740                                         0600))) {
741                 DEBUG(0, ("idmap_convert: Unable to open idmap database\n"));
742                 return False;
743         }
744
745         bigendianheader = (idmap_tdb->flags & TDB_BIGENDIAN) ? True : False;
746
747         vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION");
748
749         if (((vers == -1) && bigendianheader) || (IREV(vers) == IDMAP_VERSION)) {
750                 /* Arrggghh ! Bytereversed or old big-endian - make order independent ! */
751                 /*
752                  * high and low records were created on a
753                  * big endian machine and will need byte-reversing.
754                  */
755
756                 int32 wm;
757
758                 wm = tdb_fetch_int32(idmap_tdb, HWM_USER);
759
760                 if (wm != -1) {
761                         wm = IREV(wm);
762                 }  else {
763                         wm = server_state.uid_low;
764                 }
765
766                 if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) {
767                         DEBUG(0, ("idmap_convert: Unable to byteswap user hwm in idmap database\n"));
768                         tdb_close(idmap_tdb);
769                         return False;
770                 }
771
772                 wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP);
773                 if (wm != -1) {
774                         wm = IREV(wm);
775                 } else {
776                         wm = server_state.gid_low;
777                 }
778
779                 if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) {
780                         DEBUG(0, ("idmap_convert: Unable to byteswap group hwm in idmap database\n"));
781                         tdb_close(idmap_tdb);
782                         return False;
783                 }
784         }
785
786         /* the old format stored as DOMAIN/rid - now we store the SID direct */
787         tdb_traverse(idmap_tdb, convert_fn, &failed);
788
789         if (failed) {
790                 DEBUG(0, ("Problem during conversion\n"));
791                 tdb_close(idmap_tdb);
792                 return False;
793         }
794
795         if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == -1) {
796                 DEBUG(0, ("idmap_convert: Unable to dtore idmap version in databse\n"));
797                 tdb_close(idmap_tdb);
798                 return False;
799         }
800
801         tdb_close(idmap_tdb);
802         return True;
803 }
804
805 /*****************************************************************************
806  Convert the idmap database from an older version if necessary
807 *****************************************************************************/
808
809 BOOL winbindd_upgrade_idmap(void)
810 {
811         pstring idmap_name;
812         pstring backup_name;
813         SMB_STRUCT_STAT stbuf;
814         TDB_CONTEXT *idmap_tdb;
815
816         pstrcpy(idmap_name, lock_path("winbindd_idmap.tdb"));
817
818         if (!file_exist(idmap_name, &stbuf)) {
819                 /* nothing to convert return */
820                 return True;
821         }
822
823         if (!(idmap_tdb = tdb_open_log(idmap_name, 0,
824                                         TDB_DEFAULT, O_RDWR,
825                                         0600))) {
826                 DEBUG(0, ("idmap_convert: Unable to open idmap database\n"));
827                 return False;
828         }
829
830         if (tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION") == IDMAP_VERSION) {
831                 /* nothing to convert return */
832                 tdb_close(idmap_tdb);
833                 return True;
834         }
835
836         /* backup_tdb expects the tdb not to be open */
837         tdb_close(idmap_tdb);
838
839         DEBUG(0, ("Upgrading winbindd_idmap.tdb from an old version\n"));
840
841         pstrcpy(backup_name, idmap_name);
842         pstrcat(backup_name, ".bak");
843
844         if (backup_tdb(idmap_name, backup_name) != 0) {
845                 DEBUG(0, ("Could not backup idmap database\n"));
846                 return False;
847         }
848
849         return idmap_convert(idmap_name);
850 }
851
852 /*******************************************************************
853  wrapper around retrieving the trust account password
854 *******************************************************************/
855
856 BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16],
857                           time_t *pass_last_set_time, uint32 *channel)
858 {
859         DOM_SID sid;
860         char *pwd;
861
862         /* if we are a DC and this is not our domain, then lookup an account
863            for the domain trust */
864            
865         if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains() ) 
866         {
867                 if ( !secrets_fetch_trusted_domain_password(domain, &pwd, &sid, 
868                         pass_last_set_time) ) 
869                 {
870                         DEBUG(0, ("get_trust_pw: could not fetch trust account "
871                                   "password for trusted domain %s\n", domain));
872                         return False;
873                 }
874                 
875                 *channel = SEC_CHAN_DOMAIN;
876                 E_md4hash(pwd, ret_pwd);
877                 SAFE_FREE(pwd);
878
879                 return True;
880         }
881         else    /* just get the account for our domain (covers 
882                    ROLE_DOMAIN_MEMBER as well */
883         {
884                 /* get the machine trust account for our domain */
885
886                 if ( !secrets_fetch_trust_account_password (lp_workgroup(), ret_pwd,
887                         pass_last_set_time, channel) ) 
888                 {
889                         DEBUG(0, ("get_trust_pw: could not fetch trust account "
890                                   "password for my domain %s\n", domain));
891                         return False;
892                 }
893                 
894                 return True;
895         }
896         
897         /* Failure */
898         return False;
899 }
900