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