auth: Provide a way to use the auth stack for winbindd authentication
[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 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 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 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         if (!NT_STATUS_IS_OK(status)) {
676                 goto done;
677         }
678
679         result->unix_name = talloc_strdup(result, unix_username);
680         if (result->unix_name == NULL) {
681                 status = NT_STATUS_NO_MEMORY;
682                 goto done;
683         }
684
685         result->utok.uid = pwd->pw_uid;
686         result->utok.gid = pwd->pw_gid;
687
688         *server_info = talloc_steal(mem_ctx, result);
689         status = NT_STATUS_OK;
690 done:
691         talloc_free(tmp_ctx);
692
693         return status;
694 }
695
696 static NTSTATUS get_system_info3(TALLOC_CTX *mem_ctx,
697                                  struct netr_SamInfo3 *info3)
698 {
699         NTSTATUS status;
700         struct dom_sid *system_sid;
701
702         /* Set account name */
703         init_lsa_String(&info3->base.account_name, "SYSTEM");
704
705         /* Set domain name */
706         init_lsa_StringLarge(&info3->base.logon_domain, "NT AUTHORITY");
707
708
709         /* The SID set here will be overwirtten anyway, but try and make it SID_NT_SYSTEM anyway */
710         /* Domain sid is NT_AUTHORITY */
711         
712         system_sid = dom_sid_parse_talloc(mem_ctx, SID_NT_SYSTEM);
713         if (system_sid == NULL) {
714                 return NT_STATUS_NO_MEMORY;
715         }
716         
717         status = dom_sid_split_rid(mem_ctx, system_sid, &info3->base.domain_sid, 
718                                    &info3->base.rid);
719         TALLOC_FREE(system_sid);
720         if (!NT_STATUS_IS_OK(status)) {
721                 return status;
722         }
723         
724         /* Primary gid is the same */
725         info3->base.primary_gid = info3->base.rid;
726
727         return NT_STATUS_OK;
728 }
729
730 static NTSTATUS get_guest_info3(TALLOC_CTX *mem_ctx,
731                                 struct netr_SamInfo3 *info3)
732 {
733         const char *guest_account = lp_guest_account();
734         struct dom_sid domain_sid;
735         struct passwd *pwd;
736         const char *tmp;
737
738         pwd = Get_Pwnam_alloc(mem_ctx, guest_account);
739         if (pwd == NULL) {
740                 DEBUG(0,("SamInfo3_for_guest: Unable to locate guest "
741                          "account [%s]!\n", guest_account));
742                 return NT_STATUS_NO_SUCH_USER;
743         }
744
745         /* Set account name */
746         tmp = talloc_strdup(mem_ctx, pwd->pw_name);
747         if (tmp == NULL) {
748                 return NT_STATUS_NO_MEMORY;
749         }
750         init_lsa_String(&info3->base.account_name, tmp);
751
752         /* Set domain name */
753         tmp = talloc_strdup(mem_ctx, get_global_sam_name());
754         if (tmp == NULL) {
755                 return NT_STATUS_NO_MEMORY;
756         }
757         init_lsa_StringLarge(&info3->base.logon_domain, tmp);
758
759         /* Domain sid */
760         sid_copy(&domain_sid, get_global_sam_sid());
761
762         info3->base.domain_sid = dom_sid_dup(mem_ctx, &domain_sid);
763         if (info3->base.domain_sid == NULL) {
764                 return NT_STATUS_NO_MEMORY;
765         }
766
767         /* Guest rid */
768         info3->base.rid = DOMAIN_RID_GUEST;
769
770         /* Primary gid */
771         info3->base.primary_gid = DOMAIN_RID_GUESTS;
772
773         /* Set as guest */
774         info3->base.user_flags = NETLOGON_GUEST;
775
776         TALLOC_FREE(pwd);
777         return NT_STATUS_OK;
778 }
779
780 /***************************************************************************
781  Make (and fill) a user_info struct for a guest login.
782  This *must* succeed for smbd to start. If there is no mapping entry for
783  the guest gid, then create one.
784
785  The resulting structure is a 'session_info' because
786  create_local_token() has already been called on it.  This is quite
787  nasty, as the auth subsystem isn't expect this, but the behavior is
788  left as-is for now.
789 ***************************************************************************/
790
791 static NTSTATUS make_new_session_info_guest(struct auth_session_info **session_info, struct auth_serversupplied_info **server_info)
792 {
793         static const char zeros[16] = {0};
794         const char *guest_account = lp_guest_account();
795         const char *domain = lp_netbios_name();
796         struct netr_SamInfo3 info3;
797         TALLOC_CTX *tmp_ctx;
798         NTSTATUS status;
799
800         tmp_ctx = talloc_stackframe();
801         if (tmp_ctx == NULL) {
802                 return NT_STATUS_NO_MEMORY;
803         }
804
805         ZERO_STRUCT(info3);
806
807         status = get_guest_info3(tmp_ctx, &info3);
808         if (!NT_STATUS_IS_OK(status)) {
809                 DEBUG(0, ("get_guest_info3 failed with %s\n",
810                           nt_errstr(status)));
811                 goto done;
812         }
813
814         status = make_server_info_info3(tmp_ctx,
815                                         guest_account,
816                                         domain,
817                                         server_info,
818                                         &info3);
819         if (!NT_STATUS_IS_OK(status)) {
820                 DEBUG(0, ("make_server_info_info3 failed with %s\n",
821                           nt_errstr(status)));
822                 goto done;
823         }
824
825         (*server_info)->guest = true;
826
827         /* This should not be done here (we should produce a server
828          * info, and later construct a session info from it), but for
829          * now this does not change the previous behavior */
830         status = create_local_token(tmp_ctx, *server_info, NULL,
831                                     (*server_info)->info3->base.account_name.string,
832                                     session_info);
833         if (!NT_STATUS_IS_OK(status)) {
834                 DEBUG(0, ("create_local_token failed: %s\n",
835                           nt_errstr(status)));
836                 goto done;
837         }
838         talloc_steal(NULL, *session_info);
839         talloc_steal(NULL, *server_info);
840
841         /* annoying, but the Guest really does have a session key, and it is
842            all zeros! */
843         (*session_info)->session_key = data_blob(zeros, sizeof(zeros));
844
845         status = NT_STATUS_OK;
846 done:
847         TALLOC_FREE(tmp_ctx);
848         return status;
849 }
850
851 /***************************************************************************
852  Make (and fill) a auth_session_info struct for a system user login.
853  This *must* succeed for smbd to start.
854 ***************************************************************************/
855
856 static NTSTATUS make_new_session_info_system(TALLOC_CTX *mem_ctx,
857                                             struct auth_session_info **session_info)
858 {
859         NTSTATUS status;
860         struct auth_serversupplied_info *server_info;
861         TALLOC_CTX *tmp_ctx;
862
863         tmp_ctx = talloc_stackframe();
864         if (tmp_ctx == NULL) {
865                 return NT_STATUS_NO_MEMORY;
866         }
867
868         server_info = make_server_info(tmp_ctx);
869         if (!server_info) {
870                 status = NT_STATUS_NO_MEMORY;
871                 DEBUG(0, ("failed making server_info\n"));
872                 goto done;
873         }
874
875         server_info->info3 = talloc_zero(server_info, struct netr_SamInfo3);
876         if (!server_info->info3) {
877                 status = NT_STATUS_NO_MEMORY;
878                 DEBUG(0, ("talloc failed setting info3\n"));
879                 goto done;
880         }
881
882         status = get_system_info3(server_info, server_info->info3);
883         if (!NT_STATUS_IS_OK(status)) {
884                 DEBUG(0, ("Failed creating system info3 with %s\n",
885                           nt_errstr(status)));
886                 goto done;
887         }
888
889         server_info->utok.uid = sec_initial_uid();
890         server_info->utok.gid = sec_initial_gid();
891         server_info->unix_name = talloc_asprintf(server_info,
892                                                  "NT AUTHORITY%cSYSTEM",
893                                                  *lp_winbind_separator());
894
895         if (!server_info->unix_name) {
896                 status = NT_STATUS_NO_MEMORY;
897                 DEBUG(0, ("talloc_asprintf failed setting unix_name\n"));
898                 goto done;
899         }
900
901         server_info->security_token = talloc_zero(server_info, struct security_token);
902         if (!server_info->security_token) {
903                 status = NT_STATUS_NO_MEMORY;
904                 DEBUG(0, ("talloc failed setting security token\n"));
905                 goto done;
906         }
907
908         status = add_sid_to_array_unique(server_info->security_token->sids,
909                                          &global_sid_System,
910                                          &server_info->security_token->sids,
911                                          &server_info->security_token->num_sids);
912         if (!NT_STATUS_IS_OK(status)) {
913                 goto done;
914         }
915
916         /* SYSTEM has all privilages */
917         server_info->security_token->privilege_mask = ~0;
918
919         /* Now turn the server_info into a session_info with the full token etc */
920         status = create_local_token(mem_ctx, server_info, NULL, "SYSTEM", session_info);
921         talloc_free(server_info);
922
923         if (!NT_STATUS_IS_OK(status)) {
924                 DEBUG(0, ("create_local_token failed: %s\n",
925                           nt_errstr(status)));
926                 goto done;
927         }
928
929         talloc_steal(mem_ctx, *session_info);
930
931 done:
932         TALLOC_FREE(tmp_ctx);
933         return status;
934 }
935
936 /****************************************************************************
937   Fake a auth_session_info just from a username (as a
938   session_info structure, with create_local_token() already called on
939   it.
940 ****************************************************************************/
941
942 NTSTATUS make_session_info_from_username(TALLOC_CTX *mem_ctx,
943                                          const char *username,
944                                          bool is_guest,
945                                          struct auth_session_info **session_info)
946 {
947         struct passwd *pwd;
948         NTSTATUS status;
949         struct auth_serversupplied_info *result;
950         TALLOC_CTX *tmp_ctx;
951
952         tmp_ctx = talloc_stackframe();
953         if (tmp_ctx == NULL) {
954                 return NT_STATUS_NO_MEMORY;
955         }
956
957         pwd = Get_Pwnam_alloc(tmp_ctx, username);
958         if (pwd == NULL) {
959                 status = NT_STATUS_NO_SUCH_USER;
960                 goto done;
961         }
962
963         status = make_server_info_pw(tmp_ctx, pwd->pw_name, pwd, &result);
964         if (!NT_STATUS_IS_OK(status)) {
965                 goto done;
966         }
967
968         result->nss_token = true;
969         result->guest = is_guest;
970
971         /* Now turn the server_info into a session_info with the full token etc */
972         status = create_local_token(mem_ctx,
973                                     result,
974                                     NULL,
975                                     pwd->pw_name,
976                                     session_info);
977
978 done:
979         talloc_free(tmp_ctx);
980
981         return status;
982 }
983
984 /* This function MUST only used to create the cached server_info for
985  * guest.
986  *
987  * This is a lossy conversion.  Variables known to be lost so far
988  * include:
989  *
990  * - nss_token (not needed because the only read doesn't happen
991  * for the GUEST user, as this routine populates ->security_token
992  *
993  * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
994  *
995  * - The 'server_info' parameter allows the missing 'info3' to be copied across.
996  */
997 static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
998                                                                            const struct auth_session_info *src,
999                                                                            struct auth_serversupplied_info *server_info)
1000 {
1001         struct auth_serversupplied_info *dst;
1002
1003         dst = make_server_info(mem_ctx);
1004         if (dst == NULL) {
1005                 return NULL;
1006         }
1007
1008         /* This element must be provided to convert back to an auth_serversupplied_info */
1009         SMB_ASSERT(src->unix_info);
1010
1011         dst->guest = true;
1012         dst->system = false;
1013
1014         /* This element must be provided to convert back to an
1015          * auth_serversupplied_info.  This needs to be from the
1016          * auth_session_info because the group values in particular
1017          * may change during create_local_token() processing */
1018         SMB_ASSERT(src->unix_token);
1019         dst->utok.uid = src->unix_token->uid;
1020         dst->utok.gid = src->unix_token->gid;
1021         dst->utok.ngroups = src->unix_token->ngroups;
1022         if (src->unix_token->ngroups != 0) {
1023                 dst->utok.groups = (gid_t *)talloc_memdup(
1024                         dst, src->unix_token->groups,
1025                         sizeof(gid_t)*dst->utok.ngroups);
1026         } else {
1027                 dst->utok.groups = NULL;
1028         }
1029
1030         /* We must have a security_token as otherwise the lossy
1031          * conversion without nss_token would cause create_local_token
1032          * to take the wrong path */
1033         SMB_ASSERT(src->security_token);
1034
1035         dst->security_token = dup_nt_token(dst, src->security_token);
1036         if (!dst->security_token) {
1037                 TALLOC_FREE(dst);
1038                 return NULL;
1039         }
1040
1041         dst->session_key = data_blob_talloc( dst, src->session_key.data,
1042                                                 src->session_key.length);
1043
1044         /* This is OK because this functions is only used for the
1045          * GUEST account, which has all-zero keys for both values */
1046         dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
1047                                                 src->session_key.length);
1048
1049         dst->info3 = copy_netr_SamInfo3(dst, server_info->info3);
1050         if (!dst->info3) {
1051                 TALLOC_FREE(dst);
1052                 return NULL;
1053         }
1054
1055         dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
1056         if (!dst->unix_name) {
1057                 TALLOC_FREE(dst);
1058                 return NULL;
1059         }
1060
1061         return dst;
1062 }
1063
1064 struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx,
1065                                              const struct auth_session_info *src)
1066 {
1067         struct auth_session_info *dst;
1068         DATA_BLOB blob;
1069         enum ndr_err_code ndr_err;
1070
1071         ndr_err = ndr_push_struct_blob(
1072                 &blob, talloc_tos(), src,
1073                 (ndr_push_flags_fn_t)ndr_push_auth_session_info);
1074         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1075                 DEBUG(0, ("copy_session_info(): ndr_push_auth_session_info failed: "
1076                            "%s\n", ndr_errstr(ndr_err)));
1077                 return NULL;
1078         }
1079
1080         dst = talloc(mem_ctx, struct auth_session_info);
1081         if (dst == NULL) {
1082                 DEBUG(0, ("talloc failed\n"));
1083                 TALLOC_FREE(blob.data);
1084                 return NULL;
1085         }
1086
1087         ndr_err = ndr_pull_struct_blob(
1088                 &blob, dst, dst,
1089                 (ndr_pull_flags_fn_t)ndr_pull_auth_session_info);
1090         TALLOC_FREE(blob.data);
1091
1092         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1093                 DEBUG(0, ("copy_session_info(): ndr_pull_auth_session_info failed: "
1094                            "%s\n", ndr_errstr(ndr_err)));
1095                 TALLOC_FREE(dst);
1096                 return NULL;
1097         }
1098
1099         return dst;
1100 }
1101
1102 /*
1103  * Set a new session key. Used in the rpc server where we have to override the
1104  * SMB level session key with SystemLibraryDTC
1105  */
1106
1107 bool session_info_set_session_key(struct auth_session_info *info,
1108                                  DATA_BLOB session_key)
1109 {
1110         TALLOC_FREE(info->session_key.data);
1111
1112         info->session_key = data_blob_talloc(
1113                 info, session_key.data, session_key.length);
1114
1115         return (info->session_key.data != NULL);
1116 }
1117
1118 static struct auth_session_info *guest_info = NULL;
1119
1120 static struct auth_serversupplied_info *guest_server_info = NULL;
1121
1122 bool init_guest_info(void)
1123 {
1124         if (guest_info != NULL)
1125                 return true;
1126
1127         return NT_STATUS_IS_OK(make_new_session_info_guest(&guest_info, &guest_server_info));
1128 }
1129
1130 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
1131                                 struct auth_serversupplied_info **server_info)
1132 {
1133         /* This is trickier than it would appear to need to be because
1134          * we are trying to avoid certain costly operations when the
1135          * structure is converted to a 'auth_session_info' again in
1136          * create_local_token() */
1137         *server_info = copy_session_info_serverinfo_guest(mem_ctx, guest_info, guest_server_info);
1138         return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1139 }
1140
1141 NTSTATUS make_session_info_guest(TALLOC_CTX *mem_ctx,
1142                                 struct auth_session_info **session_info)
1143 {
1144         *session_info = copy_session_info(mem_ctx, guest_info);
1145         return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1146 }
1147
1148 static struct auth_session_info *system_info = NULL;
1149
1150 NTSTATUS init_system_session_info(void)
1151 {
1152         if (system_info != NULL)
1153                 return NT_STATUS_OK;
1154
1155         return make_new_session_info_system(NULL, &system_info);
1156 }
1157
1158 NTSTATUS make_session_info_system(TALLOC_CTX *mem_ctx,
1159                                 struct auth_session_info **session_info)
1160 {
1161         if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
1162         *session_info = copy_session_info(mem_ctx, system_info);
1163         return (*session_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1164 }
1165
1166 const struct auth_session_info *get_session_info_system(void)
1167 {
1168     return system_info;
1169 }
1170
1171 /***************************************************************************
1172  Purely internal function for make_server_info_info3
1173 ***************************************************************************/
1174
1175 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
1176                               const char *username, char **found_username,
1177                               struct passwd **pwd,
1178                               bool *username_was_mapped)
1179 {
1180         char *orig_dom_user = NULL;
1181         char *dom_user = NULL;
1182         char *lower_username = NULL;
1183         char *real_username = NULL;
1184         struct passwd *passwd;
1185
1186         lower_username = talloc_strdup(mem_ctx, username);
1187         if (!lower_username) {
1188                 return NT_STATUS_NO_MEMORY;
1189         }
1190         if (!strlower_m( lower_username )) {
1191                 return NT_STATUS_INVALID_PARAMETER;
1192         }
1193
1194         orig_dom_user = talloc_asprintf(mem_ctx,
1195                                 "%s%c%s",
1196                                 domain,
1197                                 *lp_winbind_separator(),
1198                                 lower_username);
1199         if (!orig_dom_user) {
1200                 return NT_STATUS_NO_MEMORY;
1201         }
1202
1203         /* Get the passwd struct.  Try to create the account if necessary. */
1204
1205         *username_was_mapped = map_username(mem_ctx, orig_dom_user, &dom_user);
1206         if (!dom_user) {
1207                 return NT_STATUS_NO_MEMORY;
1208         }
1209
1210         passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, true );
1211         if (!passwd) {
1212                 DEBUG(3, ("Failed to find authenticated user %s via "
1213                           "getpwnam(), denying access.\n", dom_user));
1214                 return NT_STATUS_NO_SUCH_USER;
1215         }
1216
1217         if (!real_username) {
1218                 return NT_STATUS_NO_MEMORY;
1219         }
1220
1221         *pwd = passwd;
1222
1223         /* This is pointless -- there is no support for differing
1224            unix and windows names.  Make sure to always store the 
1225            one we actually looked up and succeeded. Have I mentioned
1226            why I hate the 'winbind use default domain' parameter?   
1227                                          --jerry              */
1228
1229         *found_username = talloc_strdup( mem_ctx, real_username );
1230
1231         return NT_STATUS_OK;
1232 }
1233
1234 /****************************************************************************
1235  Wrapper to allow the getpwnam() call to strip the domain name and 
1236  try again in case a local UNIX user is already there.  Also run through 
1237  the username if we fallback to the username only.
1238  ****************************************************************************/
1239
1240 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
1241                              char **p_save_username, bool create )
1242 {
1243         struct passwd *pw = NULL;
1244         char *p = NULL;
1245         char *username = NULL;
1246
1247         /* we only save a copy of the username it has been mangled 
1248            by winbindd use default domain */
1249         *p_save_username = NULL;
1250
1251         /* don't call map_username() here since it has to be done higher 
1252            up the stack so we don't call it multiple times */
1253
1254         username = talloc_strdup(mem_ctx, domuser);
1255         if (!username) {
1256                 return NULL;
1257         }
1258
1259         p = strchr_m( username, *lp_winbind_separator() );
1260
1261         /* code for a DOMAIN\user string */
1262
1263         if ( p ) {
1264                 pw = Get_Pwnam_alloc( mem_ctx, domuser );
1265                 if ( pw ) {
1266                         /* make sure we get the case of the username correct */
1267                         /* work around 'winbind use default domain = yes' */
1268
1269                         if ( lp_winbind_use_default_domain() &&
1270                              !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1271                                 char *domain;
1272
1273                                 /* split the domain and username into 2 strings */
1274                                 *p = '\0';
1275                                 domain = username;
1276
1277                                 *p_save_username = talloc_asprintf(mem_ctx,
1278                                                                 "%s%c%s",
1279                                                                 domain,
1280                                                                 *lp_winbind_separator(),
1281                                                                 pw->pw_name);
1282                                 if (!*p_save_username) {
1283                                         TALLOC_FREE(pw);
1284                                         return NULL;
1285                                 }
1286                         } else {
1287                                 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1288                         }
1289
1290                         /* whew -- done! */
1291                         return pw;
1292                 }
1293
1294                 /* setup for lookup of just the username */
1295                 /* remember that p and username are overlapping memory */
1296
1297                 p++;
1298                 username = talloc_strdup(mem_ctx, p);
1299                 if (!username) {
1300                         return NULL;
1301                 }
1302         }
1303
1304         /* just lookup a plain username */
1305
1306         pw = Get_Pwnam_alloc(mem_ctx, username);
1307
1308         /* Create local user if requested but only if winbindd
1309            is not running.  We need to protect against cases
1310            where winbindd is failing and then prematurely
1311            creating users in /etc/passwd */
1312
1313         if ( !pw && create && !winbind_ping() ) {
1314                 /* Don't add a machine account. */
1315                 if (username[strlen(username)-1] == '$')
1316                         return NULL;
1317
1318                 _smb_create_user(NULL, username, NULL);
1319                 pw = Get_Pwnam_alloc(mem_ctx, username);
1320         }
1321
1322         /* one last check for a valid passwd struct */
1323
1324         if (pw) {
1325                 *p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
1326         }
1327         return pw;
1328 }
1329
1330 /***************************************************************************
1331  Make a server_info struct from the info3 returned by a domain logon 
1332 ***************************************************************************/
1333
1334 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 
1335                                 const char *sent_nt_username,
1336                                 const char *domain,
1337                                 struct auth_serversupplied_info **server_info,
1338                                 struct netr_SamInfo3 *info3)
1339 {
1340         static const char zeros[16] = {0, };
1341
1342         NTSTATUS nt_status = NT_STATUS_OK;
1343         char *found_username = NULL;
1344         const char *nt_domain;
1345         const char *nt_username;
1346         struct dom_sid user_sid;
1347         struct dom_sid group_sid;
1348         bool username_was_mapped;
1349         struct passwd *pwd;
1350         struct auth_serversupplied_info *result;
1351
1352         /* 
1353            Here is where we should check the list of
1354            trusted domains, and verify that the SID 
1355            matches.
1356         */
1357
1358         if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
1359                 return NT_STATUS_INVALID_PARAMETER;
1360         }
1361
1362         if (!sid_compose(&group_sid, info3->base.domain_sid,
1363                          info3->base.primary_gid)) {
1364                 return NT_STATUS_INVALID_PARAMETER;
1365         }
1366
1367         nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1368         if (!nt_username) {
1369                 /* If the server didn't give us one, just use the one we sent
1370                  * them */
1371                 nt_username = sent_nt_username;
1372         }
1373
1374         nt_domain = talloc_strdup(mem_ctx, info3->base.logon_domain.string);
1375         if (!nt_domain) {
1376                 /* If the server didn't give us one, just use the one we sent
1377                  * them */
1378                 nt_domain = domain;
1379         }
1380
1381         /* If getpwnam() fails try the add user script (2.2.x behavior).
1382
1383            We use the _unmapped_ username here in an attempt to provide
1384            consistent username mapping behavior between kerberos and NTLM[SSP]
1385            authentication in domain mode security.  I.E. Username mapping
1386            should be applied to the fully qualified username
1387            (e.g. DOMAIN\user) and not just the login name.  Yes this means we
1388            called map_username() unnecessarily in make_user_info_map() but
1389            that is how the current code is designed.  Making the change here
1390            is the least disruptive place.  -- jerry */
1391
1392         /* this call will try to create the user if necessary */
1393
1394         nt_status = check_account(mem_ctx, nt_domain, sent_nt_username,
1395                                      &found_username, &pwd,
1396                                      &username_was_mapped);
1397
1398         if (!NT_STATUS_IS_OK(nt_status)) {
1399                 return nt_status;
1400         }
1401
1402         result = make_server_info(NULL);
1403         if (result == NULL) {
1404                 DEBUG(4, ("make_server_info failed!\n"));
1405                 return NT_STATUS_NO_MEMORY;
1406         }
1407
1408         result->unix_name = talloc_strdup(result, found_username);
1409
1410         /* copy in the info3 */
1411         result->info3 = copy_netr_SamInfo3(result, info3);
1412         if (result->info3 == NULL) {
1413                 TALLOC_FREE(result);
1414                 return NT_STATUS_NO_MEMORY;
1415         }
1416
1417         /* Fill in the unix info we found on the way */
1418
1419         result->utok.uid = pwd->pw_uid;
1420         result->utok.gid = pwd->pw_gid;
1421
1422         /* ensure we are never given NULL session keys */
1423
1424         if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1425                 result->session_key = data_blob_null;
1426         } else {
1427                 result->session_key = data_blob_talloc(
1428                         result, info3->base.key.key,
1429                         sizeof(info3->base.key.key));
1430         }
1431
1432         if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1433                 result->lm_session_key = data_blob_null;
1434         } else {
1435                 result->lm_session_key = data_blob_talloc(
1436                         result, info3->base.LMSessKey.key,
1437                         sizeof(info3->base.LMSessKey.key));
1438         }
1439
1440         result->nss_token |= username_was_mapped;
1441
1442         result->guest = (info3->base.user_flags & NETLOGON_GUEST);
1443
1444         *server_info = result;
1445
1446         return NT_STATUS_OK;
1447 }
1448
1449 /*****************************************************************************
1450  Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1451 ******************************************************************************/
1452
1453 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1454                                           const char *sent_nt_username,
1455                                           const char *domain,
1456                                           const struct wbcAuthUserInfo *info,
1457                                           struct auth_serversupplied_info **server_info)
1458 {
1459         struct netr_SamInfo3 *info3;
1460
1461         info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1462         if (!info3) {
1463                 return NT_STATUS_NO_MEMORY;
1464         }
1465
1466         return make_server_info_info3(mem_ctx,
1467                                       sent_nt_username, domain,
1468                                       server_info, info3);
1469 }
1470
1471 /**
1472  * Verify whether or not given domain is trusted.
1473  *
1474  * @param domain_name name of the domain to be verified
1475  * @return true if domain is one of the trusted ones or
1476  *         false if otherwise
1477  **/
1478
1479 bool is_trusted_domain(const char* dom_name)
1480 {
1481         struct dom_sid trustdom_sid;
1482         bool ret;
1483
1484         /* no trusted domains for a standalone server */
1485
1486         if ( lp_server_role() == ROLE_STANDALONE )
1487                 return false;
1488
1489         if (dom_name == NULL || dom_name[0] == '\0') {
1490                 return false;
1491         }
1492
1493         if (strequal(dom_name, get_global_sam_name())) {
1494                 return false;
1495         }
1496
1497         /* if we are a DC, then check for a direct trust relationships */
1498
1499         if ( IS_DC ) {
1500                 become_root();
1501                 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1502                           "[%s]\n", dom_name ));
1503                 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1504                 unbecome_root();
1505                 if (ret)
1506                         return true;
1507         }
1508         else {
1509                 wbcErr result;
1510
1511                 /* If winbind is around, ask it */
1512
1513                 result = wb_is_trusted_domain(dom_name);
1514
1515                 if (result == WBC_ERR_SUCCESS) {
1516                         return true;
1517                 }
1518
1519                 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1520                         /* winbind could not find the domain */
1521                         return false;
1522                 }
1523
1524                 /* The only other possible result is that winbind is not up
1525                    and running. We need to update the trustdom_cache
1526                    ourselves */
1527
1528                 update_trustdom_cache();
1529         }
1530
1531         /* now the trustdom cache should be available a DC could still
1532          * have a transitive trust so fall back to the cache of trusted
1533          * domains (like a domain member would use  */
1534
1535         if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1536                 return true;
1537         }
1538
1539         return false;
1540 }
1541
1542
1543
1544 /*
1545   on a logon error possibly map the error to success if "map to guest"
1546   is set approriately
1547 */
1548 NTSTATUS do_map_to_guest_server_info(TALLOC_CTX *mem_ctx,
1549                                      NTSTATUS status,
1550                                      const char *user,
1551                                      const char *domain,
1552                                      struct auth_serversupplied_info **server_info)
1553 {
1554         user = user ? user : "";
1555         domain = domain ? domain : "";
1556
1557         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
1558                 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
1559                     (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
1560                         DEBUG(3,("No such user %s [%s] - using guest account\n",
1561                                  user, domain));
1562                         return make_server_info_guest(mem_ctx, server_info);
1563                 }
1564         } else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1565                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
1566                         DEBUG(3,("Registered username %s for guest access\n",
1567                                 user));
1568                         return make_server_info_guest(mem_ctx, server_info);
1569                 }
1570         }
1571
1572         return status;
1573 }
1574
1575 /*
1576   Extract session key from a session info and return it in a blob
1577   if intent is KEY_USE_16BYTES, truncate it to 16 bytes
1578
1579   See sections 3.2.4.15 and 3.3.4.2 of MS-SMB
1580   Also see https://lists.samba.org/archive/cifs-protocol/2012-January/002265.html for details
1581
1582   Note that returned session_key is referencing the original key, it is supposed to be
1583   short-lived. If original session_info->session_key is gone, the reference will be broken.
1584 */
1585 NTSTATUS session_extract_session_key(const struct auth_session_info *session_info, DATA_BLOB *session_key, enum session_key_use_intent intent)
1586 {
1587
1588         if (session_key == NULL || session_info == NULL) {
1589                 return NT_STATUS_INVALID_PARAMETER;
1590         }
1591
1592         if (session_info->session_key.length == 0) {
1593                 return NT_STATUS_NO_USER_SESSION_KEY;
1594         }
1595
1596         *session_key = session_info->session_key;
1597         if (intent == KEY_USE_16BYTES) {
1598                 session_key->length = MIN(session_info->session_key.length, 16);
1599         }
1600         return NT_STATUS_OK;
1601 }