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