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