Correctly check for errors in strlower_m() returns.
[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         if (!strlower_m( lower_username )) {
1256                 return NT_STATUS_INVALID_PARAMETER;
1257         }
1258
1259         orig_dom_user = talloc_asprintf(mem_ctx,
1260                                 "%s%c%s",
1261                                 domain,
1262                                 *lp_winbind_separator(),
1263                                 lower_username);
1264         if (!orig_dom_user) {
1265                 return NT_STATUS_NO_MEMORY;
1266         }
1267
1268         /* Get the passwd struct.  Try to create the account if necessary. */
1269
1270         *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1271         if (!dom_user) {
1272                 return NT_STATUS_NO_MEMORY;
1273         }
1274
1275         passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true );
1276         if (!passwd) {
1277                 DEBUG(3, ("Failed to find authenticated user %s via "
1278                           "getpwnam(), denying access.\n", dom_user));
1279                 return NT_STATUS_NO_SUCH_USER;
1280         }
1281
1282         if (!real_username) {
1283                 return NT_STATUS_NO_MEMORY;
1284         }
1285
1286         *pwd = passwd;
1287
1288         /* This is pointless -- there is no support for differing
1289            unix and windows names.  Make sure to always store the 
1290            one we actually looked up and succeeded. Have I mentioned
1291            why I hate the 'winbind use default domain' parameter?   
1292                                          --jerry              */
1293
1294         *found_username = talloc_strdup( mem_ctx, real_username );
1295
1296         return NT_STATUS_OK;
1297 }
1298
1299 /****************************************************************************
1300  Wrapper to allow the getpwnam() call to strip the domain name and 
1301  try again in case a local UNIX user is already there.  Also run through 
1302  the username if we fallback to the username only.
1303  ****************************************************************************/
1304
1305 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1306                              char **p_save_username, bool create )
1307 {
1308         struct passwd *pw = NULL;
1309         char *p = NULL;
1310         char *username = NULL;
1311
1312         /* we only save a copy of the username it has been mangled 
1313            by winbindd use default domain */
1314         *p_save_username = NULL;
1315
1316         /* don't call map_username() here since it has to be done higher 
1317            up the stack so we don't call it multiple times */
1318
1319         username = talloc_strdup(mem_ctx, domuser);
1320         if (!username) {
1321                 return NULL;
1322         }
1323
1324         p = strchr_m( username, *lp_winbind_separator() );
1325
1326         /* code for a DOMAIN\user string */
1327
1328         if ( p ) {
1329                 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1330                 if ( pw ) {
1331                         /* make sure we get the case of the username correct */
1332                         /* work around 'winbind use default domain = yes' */
1333
1334                         if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1335                                 char *domain;
1336
1337                                 /* split the domain and username into 2 strings */
1338                                 *p = '\0';
1339                                 domain = username;
1340
1341                                 *p_save_username = talloc_asprintf(mem_ctx,
1342                                                                 "%s%c%s",
1343                                                                 domain,
1344                                                                 *lp_winbind_separator(),
1345                                                                 pw->pw_name);
1346                                 if (!*p_save_username) {
1347                                         TALLOC_FREE(pw);
1348                                         return NULL;
1349                                 }
1350                         } else {
1351                                 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1352                         }
1353
1354                         /* whew -- done! */
1355                         return pw;
1356                 }
1357
1358                 /* setup for lookup of just the username */
1359                 /* remember that p and username are overlapping memory */
1360
1361                 p++;
1362                 username = talloc_strdup(mem_ctx, p);
1363                 if (!username) {
1364                         return NULL;
1365                 }
1366         }
1367
1368         /* just lookup a plain username */
1369
1370         pw = Get_Pwnam_alloc(mem_ctx, username);
1371
1372         /* Create local user if requested but only if winbindd
1373            is not running.  We need to protect against cases
1374            where winbindd is failing and then prematurely
1375            creating users in /etc/passwd */
1376
1377         if ( !pw && create && !winbind_ping() ) {
1378                 /* Don't add a machine account. */
1379                 if (username[strlen(username)-1] == '$')
1380                         return NULL;
1381
1382                 _smb_create_user(NULL, username, NULL);
1383                 pw = Get_Pwnam_alloc(mem_ctx, username);
1384         }
1385
1386         /* one last check for a valid passwd struct */
1387
1388         if (pw) {
1389                 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1390         }
1391         return pw;
1392 }
1393
1394 /***************************************************************************
1395  Make a server_info struct from the info3 returned by a domain logon 
1396 ***************************************************************************/
1397
1398 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 
1399                                 const char *sent_nt_username,
1400                                 const char *domain,
1401                                 struct auth_serversupplied_info **server_info,
1402                                 struct netr_SamInfo3 *info3)
1403 {
1404         static const char zeros[16] = {0, };
1405
1406         NTSTATUS nt_status = NT_STATUS_OK;
1407         char *found_username = NULL;
1408         const char *nt_domain;
1409         const char *nt_username;
1410         struct dom_sid user_sid;
1411         struct dom_sid group_sid;
1412         bool username_was_mapped;
1413         struct passwd *pwd;
1414         struct auth_serversupplied_info *result;
1415
1416         /* 
1417            Here is where we should check the list of
1418            trusted domains, and verify that the SID 
1419            matches.
1420         */
1421
1422         if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
1423                 return NT_STATUS_INVALID_PARAMETER;
1424         }
1425
1426         if (!sid_compose(&group_sid, info3->base.domain_sid,
1427                          info3->base.primary_gid)) {
1428                 return NT_STATUS_INVALID_PARAMETER;
1429         }
1430
1431         nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1432         if (!nt_username) {
1433                 /* If the server didn't give us one, just use the one we sent
1434                  * them */
1435                 nt_username = sent_nt_username;
1436         }
1437
1438         nt_domain = talloc_strdup(mem_ctx, info3->base.logon_domain.string);
1439         if (!nt_domain) {
1440                 /* If the server didn't give us one, just use the one we sent
1441                  * them */
1442                 nt_domain = domain;
1443         }
1444
1445         /* If getpwnam() fails try the add user script (2.2.x behavior).
1446
1447            We use the _unmapped_ username here in an attempt to provide
1448            consistent username mapping behavior between kerberos and NTLM[SSP]
1449            authentication in domain mode security.  I.E. Username mapping
1450            should be applied to the fully qualified username
1451            (e.g. DOMAIN\user) and not just the login name.  Yes this means we
1452            called map_username() unnecessarily in make_user_info_map() but
1453            that is how the current code is designed.  Making the change here
1454            is the least disruptive place.  -- jerry */
1455
1456         /* this call will try to create the user if necessary */
1457
1458         nt_status = check_account(mem_ctx, nt_domain, sent_nt_username,
1459                                      &found_username, &pwd,
1460                                      &username_was_mapped);
1461
1462         if (!NT_STATUS_IS_OK(nt_status)) {
1463                 return nt_status;
1464         }
1465
1466         result = make_server_info(NULL);
1467         if (result == NULL) {
1468                 DEBUG(4, ("make_server_info failed!\n"));
1469                 return NT_STATUS_NO_MEMORY;
1470         }
1471
1472         result->unix_name = talloc_strdup(result, found_username);
1473
1474         /* copy in the info3 */
1475         result->info3 = copy_netr_SamInfo3(result, info3);
1476         if (result->info3 == NULL) {
1477                 TALLOC_FREE(result);
1478                 return NT_STATUS_NO_MEMORY;
1479         }
1480
1481         /* Fill in the unix info we found on the way */
1482
1483         result->utok.uid = pwd->pw_uid;
1484         result->utok.gid = pwd->pw_gid;
1485
1486         /* ensure we are never given NULL session keys */
1487
1488         if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1489                 result->session_key = data_blob_null;
1490         } else {
1491                 result->session_key = data_blob_talloc(
1492                         result, info3->base.key.key,
1493                         sizeof(info3->base.key.key));
1494         }
1495
1496         if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1497                 result->lm_session_key = data_blob_null;
1498         } else {
1499                 result->lm_session_key = data_blob_talloc(
1500                         result, info3->base.LMSessKey.key,
1501                         sizeof(info3->base.LMSessKey.key));
1502         }
1503
1504         result->nss_token |= username_was_mapped;
1505
1506         result->guest = (info3->base.user_flags & NETLOGON_GUEST);
1507
1508         *server_info = result;
1509
1510         return NT_STATUS_OK;
1511 }
1512
1513 /*****************************************************************************
1514  Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1515 ******************************************************************************/
1516
1517 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1518                                           const char *sent_nt_username,
1519                                           const char *domain,
1520                                           const struct wbcAuthUserInfo *info,
1521                                           struct auth_serversupplied_info **server_info)
1522 {
1523         struct netr_SamInfo3 *info3;
1524
1525         info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1526         if (!info3) {
1527                 return NT_STATUS_NO_MEMORY;
1528         }
1529
1530         return make_server_info_info3(mem_ctx,
1531                                       sent_nt_username, domain,
1532                                       server_info, info3);
1533 }
1534
1535 /**
1536  * Verify whether or not given domain is trusted.
1537  *
1538  * @param domain_name name of the domain to be verified
1539  * @return true if domain is one of the trusted ones or
1540  *         false if otherwise
1541  **/
1542
1543 bool is_trusted_domain(const char* dom_name)
1544 {
1545         struct dom_sid trustdom_sid;
1546         bool ret;
1547
1548         /* no trusted domains for a standalone server */
1549
1550         if ( lp_server_role() == ROLE_STANDALONE )
1551                 return false;
1552
1553         if (dom_name == NULL || dom_name[0] == '\0') {
1554                 return false;
1555         }
1556
1557         if (strequal(dom_name, get_global_sam_name())) {
1558                 return false;
1559         }
1560
1561         /* if we are a DC, then check for a direct trust relationships */
1562
1563         if ( IS_DC ) {
1564                 become_root();
1565                 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1566                           "[%s]\n", dom_name ));
1567                 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1568                 unbecome_root();
1569                 if (ret)
1570                         return true;
1571         }
1572         else {
1573                 wbcErr result;
1574
1575                 /* If winbind is around, ask it */
1576
1577                 result = wb_is_trusted_domain(dom_name);
1578
1579                 if (result == WBC_ERR_SUCCESS) {
1580                         return true;
1581                 }
1582
1583                 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1584                         /* winbind could not find the domain */
1585                         return false;
1586                 }
1587
1588                 /* The only other possible result is that winbind is not up
1589                    and running. We need to update the trustdom_cache
1590                    ourselves */
1591
1592                 update_trustdom_cache();
1593         }
1594
1595         /* now the trustdom cache should be available a DC could still
1596          * have a transitive trust so fall back to the cache of trusted
1597          * domains (like a domain member would use  */
1598
1599         if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1600                 return true;
1601         }
1602
1603         return false;
1604 }
1605
1606
1607
1608 /*
1609   on a logon error possibly map the error to success if "map to guest"
1610   is set approriately
1611 */
1612 NTSTATUS do_map_to_guest_server_info(NTSTATUS status,
1613                                      struct auth_serversupplied_info **server_info,
1614                                      const char *user, const char *domain)
1615 {
1616         user = user ? user : "";
1617         domain = domain ? domain : "";
1618
1619         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1620                 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
1621                     (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
1622                         DEBUG(3,("No such user %s [%s] - using guest account\n",
1623                                  user, domain));
1624                         return make_server_info_guest(NULL, server_info);
1625                 }
1626         } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1627                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
1628                         DEBUG(3,("Registered username %s for guest access\n",
1629                                 user));
1630                         return make_server_info_guest(NULL, server_info);
1631                 }
1632         }
1633
1634         return status;
1635 }
1636
1637 /*
1638   Extract session key from a session info and return it in a blob
1639   if intent is KEY_USE_16BYTES, truncate it to 16 bytes
1640
1641   See sections 3.2.4.15 and 3.3.4.2 of MS-SMB
1642   Also see https://lists.samba.org/archive/cifs-protocol/2012-January/002265.html for details
1643
1644   Note that returned session_key is referencing the original key, it is supposed to be
1645   short-lived. If original session_info->session_key is gone, the reference will be broken.
1646 */
1647 NTSTATUS session_extract_session_key(const struct auth_session_info *session_info, DATA_BLOB *session_key, enum session_key_use_intent intent)
1648 {
1649
1650         if (session_key == NULL || session_info == NULL) {
1651                 return NT_STATUS_INVALID_PARAMETER;
1652         }
1653
1654         if (session_info->session_key.length == 0) {
1655                 return NT_STATUS_NO_USER_SESSION_KEY;
1656         }
1657
1658         *session_key = session_info->session_key;
1659         if (intent == KEY_USE_16BYTES) {
1660                 session_key->length = MIN(session_info->session_key.length, 16);
1661         }
1662         return NT_STATUS_OK;
1663 }