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