Merge commit 'release-4-0-0alpha15' into master4-tmp
[vlendec/samba-autobuild/.git] / source3 / auth / auth_util.c
1 /*
2    Unix SMB/CIFS implementation.
3    Authentication utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett 2001
6    Copyright (C) Jeremy Allison 2000-2001
7    Copyright (C) Rafal Szczesniak 2002
8    Copyright (C) Volker Lendecke 2006
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 3 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, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "auth.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../lib/crypto/arcfour.h"
28 #include "rpc_client/init_lsa.h"
29 #include "../libcli/security/security.h"
30 #include "../lib/util/util_pw.h"
31 #include "lib/winbind_util.h"
32 #include "passdb.h"
33
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_AUTH
36
37 /****************************************************************************
38  Create a UNIX user on demand.
39 ****************************************************************************/
40
41 static int _smb_create_user(const char *domain, const char *unix_username, const char *homedir)
42 {
43         TALLOC_CTX *ctx = talloc_tos();
44         char *add_script;
45         int ret;
46
47         add_script = talloc_strdup(ctx, lp_adduser_script());
48         if (!add_script || !*add_script) {
49                 return -1;
50         }
51         add_script = talloc_all_string_sub(ctx,
52                                 add_script,
53                                 "%u",
54                                 unix_username);
55         if (!add_script) {
56                 return -1;
57         }
58         if (domain) {
59                 add_script = talloc_all_string_sub(ctx,
60                                         add_script,
61                                         "%D",
62                                         domain);
63                 if (!add_script) {
64                         return -1;
65                 }
66         }
67         if (homedir) {
68                 add_script = talloc_all_string_sub(ctx,
69                                 add_script,
70                                 "%H",
71                                 homedir);
72                 if (!add_script) {
73                         return -1;
74                 }
75         }
76         ret = smbrun(add_script,NULL);
77         flush_pwnam_cache();
78         DEBUG(ret ? 0 : 3,
79                 ("smb_create_user: Running the command `%s' gave %d\n",
80                  add_script,ret));
81         return ret;
82 }
83
84 /****************************************************************************
85  Create an auth_usersupplied_data structure after appropriate mapping.
86 ****************************************************************************/
87
88 NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info,
89                             const char *smb_name,
90                             const char *client_domain,
91                             const char *workstation_name,
92                             DATA_BLOB *lm_pwd,
93                             DATA_BLOB *nt_pwd,
94                             const struct samr_Password *lm_interactive_pwd,
95                             const struct samr_Password *nt_interactive_pwd,
96                             const char *plaintext,
97                             enum auth_password_state password_state)
98 {
99         const char *domain;
100         NTSTATUS result;
101         bool was_mapped;
102         char *internal_username = NULL;
103
104         was_mapped = map_username(talloc_tos(), smb_name, &internal_username);
105         if (!internal_username) {
106                 return NT_STATUS_NO_MEMORY;
107         }
108
109         DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
110                  client_domain, smb_name, workstation_name));
111
112         domain = client_domain;
113
114         /* If you connect to a Windows domain member using a bogus domain name,
115          * the Windows box will map the BOGUS\user to SAMNAME\user.  Thus, if
116          * the Windows box is a DC the name will become DOMAIN\user and be
117          * authenticated against AD, if the Windows box is a member server but
118          * not a DC the name will become WORKSTATION\user.  A standalone
119          * non-domain member box will also map to WORKSTATION\user.
120          * This also deals with the client passing in a "" domain */
121
122         if (!is_trusted_domain(domain) &&
123             !strequal(domain, my_sam_name()))
124         {
125                 if (lp_map_untrusted_to_domain())
126                         domain = my_sam_name();
127                 else
128                         domain = get_global_sam_name();
129                 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
130                           "workstation [%s]\n",
131                           client_domain, domain, smb_name, workstation_name));
132         }
133
134         /* We know that the given domain is trusted (and we are allowing them),
135          * it is our global SAM name, or for legacy behavior it is our
136          * primary domain name */
137
138         result = make_user_info(user_info, smb_name, internal_username,
139                               client_domain, domain, workstation_name,
140                               lm_pwd, nt_pwd,
141                               lm_interactive_pwd, nt_interactive_pwd,
142                               plaintext, password_state);
143         if (NT_STATUS_IS_OK(result)) {
144                 /* We have tried mapping */
145                 (*user_info)->mapped_state = True;
146                 /* did we actually map the user to a different name? */
147                 (*user_info)->was_mapped = was_mapped;
148         }
149         return result;
150 }
151
152 /****************************************************************************
153  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
154  Decrypt and encrypt the passwords.
155 ****************************************************************************/
156
157 bool make_user_info_netlogon_network(struct auth_usersupplied_info **user_info,
158                                      const char *smb_name, 
159                                      const char *client_domain, 
160                                      const char *workstation_name,
161                                      uint32 logon_parameters,
162                                      const uchar *lm_network_pwd,
163                                      int lm_pwd_len,
164                                      const uchar *nt_network_pwd,
165                                      int nt_pwd_len)
166 {
167         bool ret;
168         NTSTATUS status;
169         DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
170         DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
171
172         status = make_user_info_map(user_info,
173                                     smb_name, client_domain, 
174                                     workstation_name,
175                                     lm_pwd_len ? &lm_blob : NULL, 
176                                     nt_pwd_len ? &nt_blob : NULL,
177                                     NULL, NULL, NULL,
178                                     AUTH_PASSWORD_RESPONSE);
179
180         if (NT_STATUS_IS_OK(status)) {
181                 (*user_info)->logon_parameters = logon_parameters;
182         }
183         ret = NT_STATUS_IS_OK(status) ? True : False;
184
185         data_blob_free(&lm_blob);
186         data_blob_free(&nt_blob);
187         return ret;
188 }
189
190 /****************************************************************************
191  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
192  Decrypt and encrypt the passwords.
193 ****************************************************************************/
194
195 bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_info,
196                                          const char *smb_name, 
197                                          const char *client_domain, 
198                                          const char *workstation_name,
199                                          uint32 logon_parameters,
200                                          const uchar chal[8], 
201                                          const uchar lm_interactive_pwd[16], 
202                                          const uchar nt_interactive_pwd[16], 
203                                          const uchar *dc_sess_key)
204 {
205         struct samr_Password lm_pwd;
206         struct samr_Password nt_pwd;
207         unsigned char local_lm_response[24];
208         unsigned char local_nt_response[24];
209         unsigned char key[16];
210
211         memcpy(key, dc_sess_key, 16);
212
213         if (lm_interactive_pwd)
214                 memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash));
215
216         if (nt_interactive_pwd)
217                 memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash));
218
219 #ifdef DEBUG_PASSWORD
220         DEBUG(100,("key:"));
221         dump_data(100, key, sizeof(key));
222
223         DEBUG(100,("lm owf password:"));
224         dump_data(100, lm_pwd.hash, sizeof(lm_pwd.hash));
225
226         DEBUG(100,("nt owf password:"));
227         dump_data(100, nt_pwd.hash, sizeof(nt_pwd.hash));
228 #endif
229
230         if (lm_interactive_pwd)
231                 arcfour_crypt(lm_pwd.hash, key, sizeof(lm_pwd.hash));
232
233         if (nt_interactive_pwd)
234                 arcfour_crypt(nt_pwd.hash, key, sizeof(nt_pwd.hash));
235
236 #ifdef DEBUG_PASSWORD
237         DEBUG(100,("decrypt of lm owf password:"));
238         dump_data(100, lm_pwd.hash, sizeof(lm_pwd));
239
240         DEBUG(100,("decrypt of nt owf password:"));
241         dump_data(100, nt_pwd.hash, sizeof(nt_pwd));
242 #endif
243
244         if (lm_interactive_pwd)
245                 SMBOWFencrypt(lm_pwd.hash, chal,
246                               local_lm_response);
247
248         if (nt_interactive_pwd)
249                 SMBOWFencrypt(nt_pwd.hash, chal,
250                               local_nt_response);
251
252         /* Password info paranoia */
253         ZERO_STRUCT(key);
254
255         {
256                 bool ret;
257                 NTSTATUS nt_status;
258                 DATA_BLOB local_lm_blob;
259                 DATA_BLOB local_nt_blob;
260
261                 if (lm_interactive_pwd) {
262                         local_lm_blob = data_blob(local_lm_response,
263                                                   sizeof(local_lm_response));
264                 }
265
266                 if (nt_interactive_pwd) {
267                         local_nt_blob = data_blob(local_nt_response,
268                                                   sizeof(local_nt_response));
269                 }
270
271                 nt_status = make_user_info_map(
272                         user_info, 
273                         smb_name, client_domain, workstation_name,
274                         lm_interactive_pwd ? &local_lm_blob : NULL,
275                         nt_interactive_pwd ? &local_nt_blob : NULL,
276                         lm_interactive_pwd ? &lm_pwd : NULL,
277                         nt_interactive_pwd ? &nt_pwd : NULL,
278                         NULL, AUTH_PASSWORD_HASH);
279
280                 if (NT_STATUS_IS_OK(nt_status)) {
281                         (*user_info)->logon_parameters = logon_parameters;
282                 }
283
284                 ret = NT_STATUS_IS_OK(nt_status) ? True : False;
285                 data_blob_free(&local_lm_blob);
286                 data_blob_free(&local_nt_blob);
287                 return ret;
288         }
289 }
290
291
292 /****************************************************************************
293  Create an auth_usersupplied_data structure
294 ****************************************************************************/
295
296 bool make_user_info_for_reply(struct auth_usersupplied_info **user_info,
297                               const char *smb_name, 
298                               const char *client_domain,
299                               const uint8 chal[8],
300                               DATA_BLOB plaintext_password)
301 {
302
303         DATA_BLOB local_lm_blob;
304         DATA_BLOB local_nt_blob;
305         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
306         char *plaintext_password_string;
307         /*
308          * Not encrypted - do so.
309          */
310
311         DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
312                  "format.\n"));
313         if (plaintext_password.data && plaintext_password.length) {
314                 unsigned char local_lm_response[24];
315
316 #ifdef DEBUG_PASSWORD
317                 DEBUG(10,("Unencrypted password (len %d):\n",
318                           (int)plaintext_password.length));
319                 dump_data(100, plaintext_password.data,
320                           plaintext_password.length);
321 #endif
322
323                 SMBencrypt( (const char *)plaintext_password.data,
324                             (const uchar*)chal, local_lm_response);
325                 local_lm_blob = data_blob(local_lm_response, 24);
326
327                 /* We can't do an NT hash here, as the password needs to be
328                    case insensitive */
329                 local_nt_blob = data_blob_null; 
330         } else {
331                 local_lm_blob = data_blob_null; 
332                 local_nt_blob = data_blob_null; 
333         }
334
335         plaintext_password_string = talloc_strndup(talloc_tos(),
336                                                    (const char *)plaintext_password.data,
337                                                    plaintext_password.length);
338         if (!plaintext_password_string) {
339                 return False;
340         }
341
342         ret = make_user_info_map(
343                 user_info, smb_name, client_domain, 
344                 get_remote_machine_name(),
345                 local_lm_blob.data ? &local_lm_blob : NULL,
346                 local_nt_blob.data ? &local_nt_blob : NULL,
347                 NULL, NULL,
348                 plaintext_password_string,
349                 AUTH_PASSWORD_PLAIN);
350
351         if (plaintext_password_string) {
352                 memset(plaintext_password_string, '\0', strlen(plaintext_password_string));
353                 talloc_free(plaintext_password_string);
354         }
355
356         data_blob_free(&local_lm_blob);
357         return NT_STATUS_IS_OK(ret) ? True : False;
358 }
359
360 /****************************************************************************
361  Create an auth_usersupplied_data structure
362 ****************************************************************************/
363
364 NTSTATUS make_user_info_for_reply_enc(struct auth_usersupplied_info **user_info,
365                                       const char *smb_name,
366                                       const char *client_domain, 
367                                       DATA_BLOB lm_resp, DATA_BLOB nt_resp)
368 {
369         return make_user_info_map(user_info, smb_name, 
370                                   client_domain, 
371                                   get_remote_machine_name(), 
372                                   lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
373                                   nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
374                                   NULL, NULL, NULL,
375                                   AUTH_PASSWORD_RESPONSE);
376 }
377
378 /****************************************************************************
379  Create a guest user_info blob, for anonymous authenticaion.
380 ****************************************************************************/
381
382 bool make_user_info_guest(struct auth_usersupplied_info **user_info)
383 {
384         NTSTATUS nt_status;
385
386         nt_status = make_user_info(user_info, 
387                                    "","", 
388                                    "","", 
389                                    "", 
390                                    NULL, NULL, 
391                                    NULL, NULL, 
392                                    NULL,
393                                    AUTH_PASSWORD_RESPONSE);
394
395         return NT_STATUS_IS_OK(nt_status) ? True : False;
396 }
397
398 static NTSTATUS log_nt_token(struct security_token *token)
399 {
400         TALLOC_CTX *frame = talloc_stackframe();
401         char *command;
402         char *group_sidstr;
403         size_t i;
404
405         if ((lp_log_nt_token_command() == NULL) ||
406             (strlen(lp_log_nt_token_command()) == 0)) {
407                 TALLOC_FREE(frame);
408                 return NT_STATUS_OK;
409         }
410
411         group_sidstr = talloc_strdup(frame, "");
412         for (i=1; i<token->num_sids; i++) {
413                 group_sidstr = talloc_asprintf(
414                         frame, "%s %s", group_sidstr,
415                         sid_string_talloc(frame, &token->sids[i]));
416         }
417
418         command = talloc_string_sub(
419                 frame, lp_log_nt_token_command(),
420                 "%s", sid_string_talloc(frame, &token->sids[0]));
421         command = talloc_string_sub(frame, command, "%t", group_sidstr);
422
423         if (command == NULL) {
424                 TALLOC_FREE(frame);
425                 return NT_STATUS_NO_MEMORY;
426         }
427
428         DEBUG(8, ("running command: [%s]\n", command));
429         if (smbrun(command, NULL) != 0) {
430                 DEBUG(0, ("Could not log NT token\n"));
431                 TALLOC_FREE(frame);
432                 return NT_STATUS_ACCESS_DENIED;
433         }
434
435         TALLOC_FREE(frame);
436         return NT_STATUS_OK;
437 }
438
439 /*
440  * Create the token to use from server_info->info3 and
441  * server_info->sids (the info3/sam groups). Find the unix gids.
442  */
443
444 NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
445                             const struct auth_serversupplied_info *server_info,
446                             DATA_BLOB *session_key,
447                             struct auth_serversupplied_info **session_info_out)
448 {
449         struct security_token *t;
450         NTSTATUS status;
451         size_t i;
452         struct dom_sid tmp_sid;
453         struct auth_serversupplied_info *session_info;
454         struct wbcUnixId *ids;
455
456         /* Ensure we can't possible take a code path leading to a
457          * null defref. */
458         if (!server_info) {
459                 return NT_STATUS_LOGON_FAILURE;
460         }
461
462         session_info = copy_serverinfo(mem_ctx, server_info);
463
464         if (!session_info) {
465                 return NT_STATUS_NO_MEMORY;
466         }
467
468         if (session_key) {
469                 data_blob_free(&session_info->session_key);
470                 session_info->session_key = data_blob_talloc(session_info,
471                                                                   session_key->data,
472                                                                   session_key->length);
473                 if (!session_info->session_key.data && session_key->length) {
474                         return NT_STATUS_NO_MEMORY;
475                 }
476         }
477
478         if (session_info->security_token) {
479                 /* Just copy the token, it has already been finalised
480                  * (nasty hack to support a cached guest session_info,
481                  * and a possible strategy for auth_samba4 to pass in
482                  * a finalised session) */
483                 *session_info_out = session_info;
484                 return NT_STATUS_OK;
485         }
486
487         /*
488          * If winbind is not around, we can not make much use of the SIDs the
489          * domain controller provided us with. Likewise if the user name was
490          * mapped to some local unix user.
491          */
492
493         if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
494             (session_info->nss_token)) {
495                 status = create_token_from_username(session_info,
496                                                     session_info->unix_name,
497                                                     session_info->guest,
498                                                     &session_info->utok.uid,
499                                                     &session_info->utok.gid,
500                                                     &session_info->unix_name,
501                                                     &session_info->security_token);
502
503         } else {
504                 status = create_local_nt_token_from_info3(session_info,
505                                                           session_info->guest,
506                                                           session_info->info3,
507                                                           &session_info->extra,
508                                                           &session_info->security_token);
509         }
510
511         if (!NT_STATUS_IS_OK(status)) {
512                 return status;
513         }
514
515         /* Convert the SIDs to gids. */
516
517         session_info->utok.ngroups = 0;
518         session_info->utok.groups = NULL;
519
520         t = session_info->security_token;
521
522         ids = talloc_array(talloc_tos(), struct wbcUnixId,
523                            t->num_sids);
524         if (ids == NULL) {
525                 return NT_STATUS_NO_MEMORY;
526         }
527
528         if (!sids_to_unix_ids(t->sids, t->num_sids, ids)) {
529                 TALLOC_FREE(ids);
530                 return NT_STATUS_NO_MEMORY;
531         }
532
533         /* Start at index 1, where the groups start. */
534
535         for (i=1; i<t->num_sids; i++) {
536
537                 if (ids[i].type != WBC_ID_TYPE_GID) {
538                         DEBUG(10, ("Could not convert SID %s to gid, "
539                                    "ignoring it\n",
540                                    sid_string_dbg(&t->sids[i])));
541                         continue;
542                 }
543                 if (!add_gid_to_array_unique(session_info, ids[i].id.gid,
544                                              &session_info->utok.groups,
545                                              &session_info->utok.ngroups)) {
546                         return NT_STATUS_NO_MEMORY;
547                 }
548         }
549
550         /*
551          * Add the "Unix Group" SID for each gid to catch mapped groups
552          * and their Unix equivalent.  This is to solve the backwards
553          * compatibility problem of 'valid users = +ntadmin' where
554          * ntadmin has been paired with "Domain Admins" in the group
555          * mapping table.  Otherwise smb.conf would need to be changed
556          * to 'valid user = "Domain Admins"'.  --jerry
557          *
558          * For consistency we also add the "Unix User" SID,
559          * so that the complete unix token is represented within
560          * the nt token.
561          */
562
563         uid_to_unix_users_sid(session_info->utok.uid, &tmp_sid);
564
565         add_sid_to_array_unique(session_info->security_token, &tmp_sid,
566                                 &session_info->security_token->sids,
567                                 &session_info->security_token->num_sids);
568
569         for ( i=0; i<session_info->utok.ngroups; i++ ) {
570                 gid_to_unix_groups_sid(session_info->utok.groups[i], &tmp_sid);
571                 add_sid_to_array_unique(session_info->security_token, &tmp_sid,
572                                         &session_info->security_token->sids,
573                                         &session_info->security_token->num_sids);
574         }
575
576         security_token_debug(DBGC_AUTH, 10, session_info->security_token);
577         debug_unix_user_token(DBGC_AUTH, 10,
578                               session_info->utok.uid,
579                               session_info->utok.gid,
580                               session_info->utok.ngroups,
581                               session_info->utok.groups);
582
583         status = log_nt_token(session_info->security_token);
584         if (!NT_STATUS_IS_OK(status)) {
585                 return status;
586         }
587
588         *session_info_out = session_info;
589         return NT_STATUS_OK;
590 }
591
592 /***************************************************************************
593  Make (and fill) a server_info struct from a 'struct passwd' by conversion
594  to a struct samu
595 ***************************************************************************/
596
597 NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info,
598                              char *unix_username,
599                              struct passwd *pwd)
600 {
601         NTSTATUS status;
602         struct samu *sampass = NULL;
603         char *qualified_name = NULL;
604         TALLOC_CTX *mem_ctx = NULL;
605         struct dom_sid u_sid;
606         enum lsa_SidType type;
607         struct auth_serversupplied_info *result;
608
609         /*
610          * The SID returned in server_info->sam_account is based
611          * on our SAM sid even though for a pure UNIX account this should
612          * not be the case as it doesn't really exist in the SAM db.
613          * This causes lookups on "[in]valid users" to fail as they
614          * will lookup this name as a "Unix User" SID to check against
615          * the user token. Fix this by adding the "Unix User"\unix_username
616          * SID to the sid array. The correct fix should probably be
617          * changing the server_info->sam_account user SID to be a
618          * S-1-22 Unix SID, but this might break old configs where
619          * plaintext passwords were used with no SAM backend.
620          */
621
622         mem_ctx = talloc_init("make_server_info_pw_tmp");
623         if (!mem_ctx) {
624                 return NT_STATUS_NO_MEMORY;
625         }
626
627         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
628                                         unix_users_domain_name(),
629                                         unix_username );
630         if (!qualified_name) {
631                 TALLOC_FREE(mem_ctx);
632                 return NT_STATUS_NO_MEMORY;
633         }
634
635         if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
636                                                 NULL, NULL,
637                                                 &u_sid, &type)) {
638                 TALLOC_FREE(mem_ctx);
639                 return NT_STATUS_NO_SUCH_USER;
640         }
641
642         TALLOC_FREE(mem_ctx);
643
644         if (type != SID_NAME_USER) {
645                 return NT_STATUS_NO_SUCH_USER;
646         }
647
648         if ( !(sampass = samu_new( NULL )) ) {
649                 return NT_STATUS_NO_MEMORY;
650         }
651
652         status = samu_set_unix( sampass, pwd );
653         if (!NT_STATUS_IS_OK(status)) {
654                 return status;
655         }
656
657         /* In pathological cases the above call can set the account
658          * name to the DOMAIN\username form. Reset the account name
659          * using unix_username */
660         pdb_set_username(sampass, unix_username, PDB_SET);
661
662         /* set the user sid to be the calculated u_sid */
663         pdb_set_user_sid(sampass, &u_sid, PDB_SET);
664
665         result = make_server_info(NULL);
666         if (result == NULL) {
667                 TALLOC_FREE(sampass);
668                 return NT_STATUS_NO_MEMORY;
669         }
670
671         status = samu_to_SamInfo3(result, sampass, lp_netbios_name(),
672                                   &result->info3, &result->extra);
673         TALLOC_FREE(sampass);
674         if (!NT_STATUS_IS_OK(status)) {
675                 DEBUG(10, ("Failed to convert samu to info3: %s\n",
676                            nt_errstr(status)));
677                 TALLOC_FREE(result);
678                 return status;
679         }
680
681         result->unix_name = talloc_strdup(result, unix_username);
682         result->sanitized_username = sanitize_username(result, unix_username);
683
684         if ((result->unix_name == NULL)
685             || (result->sanitized_username == NULL)) {
686                 TALLOC_FREE(result);
687                 return NT_STATUS_NO_MEMORY;
688         }
689
690         result->utok.uid = pwd->pw_uid;
691         result->utok.gid = pwd->pw_gid;
692
693         *server_info = result;
694
695         return NT_STATUS_OK;
696 }
697
698 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
699                                 struct netr_SamInfo3 *info3)
700 {
701         const char *guest_account = lp_guestaccount();
702         struct dom_sid domain_sid;
703         struct passwd *pwd;
704         const char *tmp;
705
706         pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
707         if (pwd == NULL) {
708                 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
709                          "account [%s]!\n", guest_account));
710                 return NT_STATUS_NO_SUCH_USER;
711         }
712
713         /* Set acount name */
714         tmp = talloc_strdup(mem_ctx, pwd->pw_name);
715         if (tmp == NULL) {
716                 return NT_STATUS_NO_MEMORY;
717         }
718         init_lsa_String(&info3->base.account_name, tmp);
719
720         /* Set domain name */
721         tmp = talloc_strdup(mem_ctx, get_global_sam_name());
722         if (tmp == NULL) {
723                 return NT_STATUS_NO_MEMORY;
724         }
725         init_lsa_StringLarge(&info3->base.domain, tmp);
726
727         /* Domain sid */
728         sid_copy(&domain_sid, get_global_sam_sid());
729
730         info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
731         if (info3->base.domain_sid == NULL) {
732                 return NT_STATUS_NO_MEMORY;
733         }
734
735         /* Guest rid */
736         info3->base.rid = DOMAIN_RID_GUEST;
737
738         /* Primary gid */
739         info3->base.primary_gid = BUILTIN_RID_GUESTS;
740
741         TALLOC_FREE(pwd);
742         return NT_STATUS_OK;
743 }
744
745 /***************************************************************************
746  Make (and fill) a user_info struct for a guest login.
747  This *must* succeed for smbd to start. If there is no mapping entry for
748  the guest gid, then create one.
749
750  The resulting structure is a 'session_info' because
751  create_local_token() has already been called on it.  This is quite
752  nasty, as the auth subsystem isn't expect this, but the behaviour is
753  left as-is for now.
754 ***************************************************************************/
755
756 static NTSTATUS make_new_server_info_guest(struct auth_serversupplied_info **session_info)
757 {
758         struct auth_serversupplied_info *server_info;
759         static const char zeros[16] = {0};
760         const char *guest_account = lp_guestaccount();
761         const char *domain = lp_netbios_name();
762         struct netr_SamInfo3 info3;
763         TALLOC_CTX *tmp_ctx;
764         NTSTATUS status;
765         fstring tmp;
766
767         tmp_ctx = talloc_stackframe();
768         if (tmp_ctx == NULL) {
769                 return NT_STATUS_NO_MEMORY;
770         }
771
772         ZERO_STRUCT(info3);
773
774         status = get_guest_info3(tmp_ctx, &info3);
775         if (!NT_STATUS_IS_OK(status)) {
776                 DEBUG(0, ("get_guest_info3 failed with %s\n",
777                           nt_errstr(status)));
778                 goto done;
779         }
780
781         status = make_server_info_info3(tmp_ctx,
782                                         guest_account,
783                                         domain,
784                                         &server_info,
785                                         &info3);
786         if (!NT_STATUS_IS_OK(status)) {
787                 DEBUG(0, ("make_server_info_info3 failed with %s\n",
788                           nt_errstr(status)));
789                 goto done;
790         }
791
792         server_info->guest = True;
793
794         /* This should not be done here (we should produce a server
795          * info, and later construct a session info from it), but for
796          * now this does not change the previous behaviours */
797         status = create_local_token(tmp_ctx, server_info, NULL, session_info);
798         TALLOC_FREE(server_info);
799         if (!NT_STATUS_IS_OK(status)) {
800                 DEBUG(0, ("create_local_token failed: %s\n",
801                           nt_errstr(status)));
802                 goto done;
803         }
804         talloc_steal(NULL, *session_info);
805
806         /* annoying, but the Guest really does have a session key, and it is
807            all zeros! */
808         (*session_info)->session_key = data_blob(zeros, sizeof(zeros));
809         (*session_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
810
811         alpha_strcpy(tmp, (*session_info)->info3->base.account_name.string,
812                      ". _-$", sizeof(tmp));
813         (*session_info)->sanitized_username = talloc_strdup(*session_info, tmp);
814
815         status = NT_STATUS_OK;
816 done:
817         TALLOC_FREE(tmp_ctx);
818         return status;
819 }
820
821 /***************************************************************************
822  Make (and fill) a auth_session_info struct for a system user login.
823  This *must* succeed for smbd to start.
824 ***************************************************************************/
825
826 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
827                                             struct auth_serversupplied_info **session_info)
828 {
829         struct passwd *pwd;
830         NTSTATUS status;
831
832         pwd = getpwuid_alloc(mem_ctx, sec_initial_uid());
833         if (pwd == NULL) {
834                 return NT_STATUS_NO_SUCH_USER;
835         }
836
837         status = make_session_info_from_username(mem_ctx,
838                                                  pwd->pw_name,
839                                                  false,
840                                                  session_info);
841         TALLOC_FREE(pwd);
842         if (!NT_STATUS_IS_OK(status)) {
843                 return status;
844         }
845
846         (*session_info)->system = true;
847
848         status = add_sid_to_array_unique((*session_info)->security_token->sids,
849                                          &global_sid_System,
850                                          &(*session_info)->security_token->sids,
851                                          &(*session_info)->security_token->num_sids);
852         if (!NT_STATUS_IS_OK(status)) {
853                 TALLOC_FREE((*session_info));
854                 return status;
855         }
856
857         return NT_STATUS_OK;
858 }
859
860 /****************************************************************************
861   Fake a auth_serversupplied_info just from a username (as a
862   session_info structure, with create_local_token() already called on
863   it.
864 ****************************************************************************/
865
866 NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx,
867                                          const char *username,
868                                          bool is_guest,
869                                          struct auth_serversupplied_info **session_info)
870 {
871         struct auth_serversupplied_info *result;
872         struct passwd *pwd;
873         NTSTATUS status;
874
875         pwd = Get_Pwnam_alloc(talloc_tos(), username);
876         if (pwd == NULL) {
877                 return NT_STATUS_NO_SUCH_USER;
878         }
879
880         status = make_server_info_pw(&result, pwd->pw_name, pwd);
881
882         TALLOC_FREE(pwd);
883
884         if (!NT_STATUS_IS_OK(status)) {
885                 return status;
886         }
887
888         result->nss_token = true;
889         result->guest = is_guest;
890
891         /* Now turn the server_info into a session_info with the full token etc */
892         status = create_local_token(mem_ctx, result, NULL, session_info);
893         talloc_free(result);
894         return status;
895 }
896
897
898 struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx,
899                                                  const struct auth_serversupplied_info *src)
900 {
901         struct auth_serversupplied_info *dst;
902
903         dst = make_server_info(mem_ctx);
904         if (dst == NULL) {
905                 return NULL;
906         }
907
908         dst->guest = src->guest;
909         dst->system = src->system;
910         dst->utok.uid = src->utok.uid;
911         dst->utok.gid = src->utok.gid;
912         dst->utok.ngroups = src->utok.ngroups;
913         if (src->utok.ngroups != 0) {
914                 dst->utok.groups = (gid_t *)talloc_memdup(
915                         dst, src->utok.groups,
916                         sizeof(gid_t)*dst->utok.ngroups);
917         } else {
918                 dst->utok.groups = NULL;
919         }
920
921         if (src->security_token) {
922                 dst->security_token = dup_nt_token(dst, src->security_token);
923                 if (!dst->security_token) {
924                         TALLOC_FREE(dst);
925                         return NULL;
926                 }
927         }
928
929         dst->session_key = data_blob_talloc( dst, src->session_key.data,
930                                                 src->session_key.length);
931
932         dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data,
933                                                 src->lm_session_key.length);
934
935         dst->info3 = copy_netr_SamInfo3(dst, src->info3);
936         if (!dst->info3) {
937                 TALLOC_FREE(dst);
938                 return NULL;
939         }
940         dst->extra = src->extra;
941
942         dst->unix_name = talloc_strdup(dst, src->unix_name);
943         if (!dst->unix_name) {
944                 TALLOC_FREE(dst);
945                 return NULL;
946         }
947
948         dst->sanitized_username = talloc_strdup(dst, src->sanitized_username);
949         if (!dst->sanitized_username) {
950                 TALLOC_FREE(dst);
951                 return NULL;
952         }
953
954         return dst;
955 }
956
957 /*
958  * Set a new session key. Used in the rpc server where we have to override the
959  * SMB level session key with SystemLibraryDTC
960  */
961
962 bool session_info_set_session_key(struct auth_serversupplied_info *info,
963                                  DATA_BLOB session_key)
964 {
965         TALLOC_FREE(info->session_key.data);
966
967         info->session_key = data_blob_talloc(
968                 info, session_key.data, session_key.length);
969
970         return (info->session_key.data != NULL);
971 }
972
973 static struct auth_serversupplied_info *guest_info = NULL;
974
975 bool init_guest_info(void)
976 {
977         if (guest_info != NULL)
978                 return True;
979
980         return NT_STATUS_IS_OK(make_new_server_info_guest(&guest_info));
981 }
982
983 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
984                                 struct auth_serversupplied_info **server_info)
985 {
986         *server_info = copy_serverinfo(mem_ctx, guest_info);
987         return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
988 }
989
990 static struct auth_serversupplied_info *system_info = NULL;
991
992 NTSTATUS init_system_info(void)
993 {
994         if (system_info != NULL)
995                 return NT_STATUS_OK;
996
997         return make_new_session_info_system(NULL, &system_info);
998 }
999
1000 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1001                                 struct auth_serversupplied_info **session_info)
1002 {
1003         if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1004         *session_info = copy_serverinfo(mem_ctx, system_info);
1005         return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1006 }
1007
1008 const struct auth_serversupplied_info *get_session_info_system(void)
1009 {
1010     return system_info;
1011 }
1012
1013 bool copy_current_user(struct current_user *dst, struct current_user *src)
1014 {
1015         gid_t *groups;
1016         struct security_token *nt_token;
1017
1018         groups = (gid_t *)memdup(src->ut.groups,
1019                                  sizeof(gid_t) * src->ut.ngroups);
1020         if ((src->ut.ngroups != 0) && (groups == NULL)) {
1021                 return False;
1022         }
1023
1024         nt_token = dup_nt_token(NULL, src->nt_user_token);
1025         if (nt_token == NULL) {
1026                 SAFE_FREE(groups);
1027                 return False;
1028         }
1029
1030         dst->conn = src->conn;
1031         dst->vuid = src->vuid;
1032         dst->ut.uid = src->ut.uid;
1033         dst->ut.gid = src->ut.gid;
1034         dst->ut.ngroups = src->ut.ngroups;
1035         dst->ut.groups = groups;
1036         dst->nt_user_token = nt_token;
1037         return True;
1038 }
1039
1040 /***************************************************************************
1041  Purely internal function for make_server_info_info3
1042 ***************************************************************************/
1043
1044 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1045                               const char *username, char **found_username,
1046                               struct passwd **pwd,
1047                               bool *username_was_mapped)
1048 {
1049         char *orig_dom_user = NULL;
1050         char *dom_user = NULL;
1051         char *lower_username = NULL;
1052         char *real_username = NULL;
1053         struct passwd *passwd;
1054
1055         lower_username = talloc_strdup(mem_ctx, username);
1056         if (!lower_username) {
1057                 return NT_STATUS_NO_MEMORY;
1058         }
1059         strlower_m( lower_username );
1060
1061         orig_dom_user = talloc_asprintf(mem_ctx,
1062                                 "%s%c%s",
1063                                 domain,
1064                                 *lp_winbind_separator(),
1065                                 lower_username);
1066         if (!orig_dom_user) {
1067                 return NT_STATUS_NO_MEMORY;
1068         }
1069
1070         /* Get the passwd struct.  Try to create the account if necessary. */
1071
1072         *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1073         if (!dom_user) {
1074                 return NT_STATUS_NO_MEMORY;
1075         }
1076
1077         passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, True );
1078         if (!passwd) {
1079                 DEBUG(3, ("Failed to find authenticated user %s via "
1080                           "getpwnam(), denying access.\n", dom_user));
1081                 return NT_STATUS_NO_SUCH_USER;
1082         }
1083
1084         if (!real_username) {
1085                 return NT_STATUS_NO_MEMORY;
1086         }
1087
1088         *pwd = passwd;
1089
1090         /* This is pointless -- there is no suport for differing 
1091            unix and windows names.  Make sure to always store the 
1092            one we actually looked up and succeeded. Have I mentioned
1093            why I hate the 'winbind use default domain' parameter?   
1094                                          --jerry              */
1095
1096         *found_username = talloc_strdup( mem_ctx, real_username );
1097
1098         return NT_STATUS_OK;
1099 }
1100
1101 /****************************************************************************
1102  Wrapper to allow the getpwnam() call to strip the domain name and 
1103  try again in case a local UNIX user is already there.  Also run through 
1104  the username if we fallback to the username only.
1105  ****************************************************************************/
1106
1107 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1108                              char **p_save_username, bool create )
1109 {
1110         struct passwd *pw = NULL;
1111         char *p = NULL;
1112         char *username = NULL;
1113
1114         /* we only save a copy of the username it has been mangled 
1115            by winbindd use default domain */
1116         *p_save_username = NULL;
1117
1118         /* don't call map_username() here since it has to be done higher 
1119            up the stack so we don't call it multiple times */
1120
1121         username = talloc_strdup(mem_ctx, domuser);
1122         if (!username) {
1123                 return NULL;
1124         }
1125
1126         p = strchr_m( username, *lp_winbind_separator() );
1127
1128         /* code for a DOMAIN\user string */
1129
1130         if ( p ) {
1131                 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1132                 if ( pw ) {
1133                         /* make sure we get the case of the username correct */
1134                         /* work around 'winbind use default domain = yes' */
1135
1136                         if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1137                                 char *domain;
1138
1139                                 /* split the domain and username into 2 strings */
1140                                 *p = '\0';
1141                                 domain = username;
1142
1143                                 *p_save_username = talloc_asprintf(mem_ctx,
1144                                                                 "%s%c%s",
1145                                                                 domain,
1146                                                                 *lp_winbind_separator(),
1147                                                                 pw->pw_name);
1148                                 if (!*p_save_username) {
1149                                         TALLOC_FREE(pw);
1150                                         return NULL;
1151                                 }
1152                         } else {
1153                                 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1154                         }
1155
1156                         /* whew -- done! */
1157                         return pw;
1158                 }
1159
1160                 /* setup for lookup of just the username */
1161                 /* remember that p and username are overlapping memory */
1162
1163                 p++;
1164                 username = talloc_strdup(mem_ctx, p);
1165                 if (!username) {
1166                         return NULL;
1167                 }
1168         }
1169
1170         /* just lookup a plain username */
1171
1172         pw = Get_Pwnam_alloc(mem_ctx, username);
1173
1174         /* Create local user if requested but only if winbindd
1175            is not running.  We need to protect against cases
1176            where winbindd is failing and then prematurely
1177            creating users in /etc/passwd */
1178
1179         if ( !pw && create && !winbind_ping() ) {
1180                 /* Don't add a machine account. */
1181                 if (username[strlen(username)-1] == '$')
1182                         return NULL;
1183
1184                 _smb_create_user(NULL, username, NULL);
1185                 pw = Get_Pwnam_alloc(mem_ctx, username);
1186         }
1187
1188         /* one last check for a valid passwd struct */
1189
1190         if (pw) {
1191                 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1192         }
1193         return pw;
1194 }
1195
1196 /***************************************************************************
1197  Make a server_info struct from the info3 returned by a domain logon 
1198 ***************************************************************************/
1199
1200 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 
1201                                 const char *sent_nt_username,
1202                                 const char *domain,
1203                                 struct auth_serversupplied_info **server_info,
1204                                 struct netr_SamInfo3 *info3)
1205 {
1206         static const char zeros[16] = {0, };
1207
1208         NTSTATUS nt_status = NT_STATUS_OK;
1209         char *found_username = NULL;
1210         const char *nt_domain;
1211         const char *nt_username;
1212         bool username_was_mapped;
1213         struct passwd *pwd;
1214         struct auth_serversupplied_info *result;
1215         struct dom_sid *group_sid;
1216         struct netr_SamInfo3 *i3;
1217
1218         /* 
1219            Here is where we should check the list of
1220            trusted domains, and verify that the SID 
1221            matches.
1222         */
1223
1224         nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1225         if (!nt_username) {
1226                 /* If the server didn't give us one, just use the one we sent
1227                  * them */
1228                 nt_username = sent_nt_username;
1229         }
1230
1231         nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string);
1232         if (!nt_domain) {
1233                 /* If the server didn't give us one, just use the one we sent
1234                  * them */
1235                 nt_domain = domain;
1236         }
1237
1238         /* If getpwnam() fails try the add user script (2.2.x behavior).
1239
1240            We use the _unmapped_ username here in an attempt to provide
1241            consistent username mapping behavior between kerberos and NTLM[SSP]
1242            authentication in domain mode security.  I.E. Username mapping
1243            should be applied to the fully qualified username
1244            (e.g. DOMAIN\user) and not just the login name.  Yes this means we
1245            called map_username() unnecessarily in make_user_info_map() but
1246            that is how the current code is designed.  Making the change here
1247            is the least disruptive place.  -- jerry */
1248
1249         /* this call will try to create the user if necessary */
1250
1251         nt_status = check_account(mem_ctx, nt_domain, sent_nt_username,
1252                                      &found_username, &pwd,
1253                                      &username_was_mapped);
1254
1255         if (!NT_STATUS_IS_OK(nt_status)) {
1256                 return nt_status;
1257         }
1258
1259         result = make_server_info(NULL);
1260         if (result == NULL) {
1261                 DEBUG(4, ("make_server_info failed!\n"));
1262                 return NT_STATUS_NO_MEMORY;
1263         }
1264
1265         result->unix_name = talloc_strdup(result, found_username);
1266
1267         result->sanitized_username = sanitize_username(result,
1268                                                        result->unix_name);
1269         if (result->sanitized_username == NULL) {
1270                 TALLOC_FREE(result);
1271                 return NT_STATUS_NO_MEMORY;
1272         }
1273
1274         /* copy in the info3 */
1275         result->info3 = i3 = copy_netr_SamInfo3(result, info3);
1276         if (result->info3 == NULL) {
1277                 TALLOC_FREE(result);
1278                 return NT_STATUS_NO_MEMORY;
1279         }
1280
1281         /* Fill in the unix info we found on the way */
1282         result->utok.uid = pwd->pw_uid;
1283         result->utok.gid = pwd->pw_gid;
1284
1285         /* We can't just trust that the primary group sid sent us is something
1286          * we can really use. Obtain the useable sid, and store the original
1287          * one as an additional group if it had to be replaced */
1288         nt_status = get_primary_group_sid(mem_ctx, found_username,
1289                                           &pwd, &group_sid);
1290         if (!NT_STATUS_IS_OK(nt_status)) {
1291                 TALLOC_FREE(result);
1292                 return nt_status;
1293         }
1294
1295         /* store and check if it is the same we got originally */
1296         sid_peek_rid(group_sid, &i3->base.primary_gid);
1297         if (i3->base.primary_gid != info3->base.primary_gid) {
1298                 uint32_t n = i3->base.groups.count;
1299                 /* not the same, store the original as an additional group */
1300                 i3->base.groups.rids =
1301                         talloc_realloc(i3, i3->base.groups.rids,
1302                                         struct samr_RidWithAttribute, n + 1);
1303                 if (i3->base.groups.rids == NULL) {
1304                         TALLOC_FREE(result);
1305                         return NT_STATUS_NO_MEMORY;
1306                 }
1307                 i3->base.groups.rids[n].rid = info3->base.primary_gid;
1308                 i3->base.groups.rids[n].attributes = SE_GROUP_ENABLED;
1309                 i3->base.groups.count = n + 1;
1310         }
1311
1312         /* ensure we are never given NULL session keys */
1313
1314         if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1315                 result->session_key = data_blob_null;
1316         } else {
1317                 result->session_key = data_blob_talloc(
1318                         result, info3->base.key.key,
1319                         sizeof(info3->base.key.key));
1320         }
1321
1322         if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1323                 result->lm_session_key = data_blob_null;
1324         } else {
1325                 result->lm_session_key = data_blob_talloc(
1326                         result, info3->base.LMSessKey.key,
1327                         sizeof(info3->base.LMSessKey.key));
1328         }
1329
1330         result->nss_token |= username_was_mapped;
1331
1332         *server_info = result;
1333
1334         return NT_STATUS_OK;
1335 }
1336
1337 /*****************************************************************************
1338  Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1339 ******************************************************************************/
1340
1341 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1342                                           const char *sent_nt_username,
1343                                           const char *domain,
1344                                           const struct wbcAuthUserInfo *info,
1345                                           struct auth_serversupplied_info **server_info)
1346 {
1347         struct netr_SamInfo3 *info3;
1348
1349         info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1350         if (!info3) {
1351                 return NT_STATUS_NO_MEMORY;
1352         }
1353
1354         return make_server_info_info3(mem_ctx,
1355                                       sent_nt_username, domain,
1356                                       server_info, info3);
1357 }
1358
1359 /**
1360  * Verify whether or not given domain is trusted.
1361  *
1362  * @param domain_name name of the domain to be verified
1363  * @return true if domain is one of the trusted ones or
1364  *         false if otherwise
1365  **/
1366
1367 bool is_trusted_domain(const char* dom_name)
1368 {
1369         struct dom_sid trustdom_sid;
1370         bool ret;
1371
1372         /* no trusted domains for a standalone server */
1373
1374         if ( lp_server_role() == ROLE_STANDALONE )
1375                 return False;
1376
1377         if (dom_name == NULL || dom_name[0] == '\0') {
1378                 return false;
1379         }
1380
1381         if (strequal(dom_name, get_global_sam_name())) {
1382                 return false;
1383         }
1384
1385         /* if we are a DC, then check for a direct trust relationships */
1386
1387         if ( IS_DC ) {
1388                 become_root();
1389                 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1390                           "[%s]\n", dom_name ));
1391                 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1392                 unbecome_root();
1393                 if (ret)
1394                         return True;
1395         }
1396         else {
1397                 wbcErr result;
1398
1399                 /* If winbind is around, ask it */
1400
1401                 result = wb_is_trusted_domain(dom_name);
1402
1403                 if (result == WBC_ERR_SUCCESS) {
1404                         return True;
1405                 }
1406
1407                 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1408                         /* winbind could not find the domain */
1409                         return False;
1410                 }
1411
1412                 /* The only other possible result is that winbind is not up
1413                    and running. We need to update the trustdom_cache
1414                    ourselves */
1415
1416                 update_trustdom_cache();
1417         }
1418
1419         /* now the trustdom cache should be available a DC could still
1420          * have a transitive trust so fall back to the cache of trusted
1421          * domains (like a domain member would use  */
1422
1423         if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1424                 return True;
1425         }
1426
1427         return False;
1428 }
1429