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