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