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