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