s3:auth Make Samba3 use the new common struct auth_usersupplied_info
[mat/samba.git] / source3 / auth / auth_util.c
1 /*
2    Unix SMB/CIFS implementation.
3    Authentication utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Andrew Bartlett 2001
6    Copyright (C) Jeremy Allison 2000-2001
7    Copyright (C) Rafal Szczesniak 2002
8    Copyright (C) Volker Lendecke 2006
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 "smbd/globals.h"
26 #include "../libcli/auth/libcli_auth.h"
27 #include "../lib/crypto/arcfour.h"
28
29 #undef DBGC_CLASS
30 #define DBGC_CLASS DBGC_AUTH
31
32 /****************************************************************************
33  Create a UNIX user on demand.
34 ****************************************************************************/
35
36 static int _smb_create_user(const char *domain, const char *unix_username, const char *homedir)
37 {
38         TALLOC_CTX *ctx = talloc_tos();
39         char *add_script;
40         int ret;
41
42         add_script = talloc_strdup(ctx, lp_adduser_script());
43         if (!add_script || !*add_script) {
44                 return -1;
45         }
46         add_script = talloc_all_string_sub(ctx,
47                                 add_script,
48                                 "%u",
49                                 unix_username);
50         if (!add_script) {
51                 return -1;
52         }
53         if (domain) {
54                 add_script = talloc_all_string_sub(ctx,
55                                         add_script,
56                                         "%D",
57                                         domain);
58                 if (!add_script) {
59                         return -1;
60                 }
61         }
62         if (homedir) {
63                 add_script = talloc_all_string_sub(ctx,
64                                 add_script,
65                                 "%H",
66                                 homedir);
67                 if (!add_script) {
68                         return -1;
69                 }
70         }
71         ret = smbrun(add_script,NULL);
72         flush_pwnam_cache();
73         DEBUG(ret ? 0 : 3,
74                 ("smb_create_user: Running the command `%s' gave %d\n",
75                  add_script,ret));
76         return ret;
77 }
78
79 /****************************************************************************
80  Create an auth_usersupplied_data structure after appropriate mapping.
81 ****************************************************************************/
82
83 NTSTATUS make_user_info_map(struct auth_usersupplied_info **user_info,
84                             const char *smb_name,
85                             const char *client_domain,
86                             const char *workstation_name,
87                             DATA_BLOB *lm_pwd,
88                             DATA_BLOB *nt_pwd,
89                             const struct samr_Password *lm_interactive_pwd,
90                             const struct samr_Password *nt_interactive_pwd,
91                             const char *plaintext,
92                             enum auth_password_state password_state)
93 {
94         const char *domain;
95         NTSTATUS result;
96         bool was_mapped;
97         fstring internal_username;
98         fstrcpy(internal_username, smb_name);
99         was_mapped = map_username(internal_username);
100
101         DEBUG(5, ("Mapping user [%s]\\[%s] from workstation [%s]\n",
102                  client_domain, smb_name, workstation_name));
103
104         domain = client_domain;
105
106         /* If you connect to a Windows domain member using a bogus domain name,
107          * the Windows box will map the BOGUS\user to SAMNAME\user.  Thus, if
108          * the Windows box is a DC the name will become DOMAIN\user and be
109          * authenticated against AD, if the Windows box is a member server but
110          * not a DC the name will become WORKSTATION\user.  A standalone
111          * non-domain member box will also map to WORKSTATION\user.
112          * This also deals with the client passing in a "" domain */
113
114         if (!is_trusted_domain(domain) &&
115             !strequal(domain, my_sam_name()))
116         {
117                 if (lp_map_untrusted_to_domain())
118                         domain = my_sam_name();
119                 else
120                         domain = get_global_sam_name();
121                 DEBUG(5, ("Mapped domain from [%s] to [%s] for user [%s] from "
122                           "workstation [%s]\n",
123                           client_domain, domain, smb_name, workstation_name));
124         }
125
126         /* We know that the given domain is trusted (and we are allowing them),
127          * it is our global SAM name, or for legacy behavior it is our
128          * primary domain name */
129
130         result = make_user_info(user_info, smb_name, internal_username,
131                               client_domain, domain, workstation_name,
132                               lm_pwd, nt_pwd,
133                               lm_interactive_pwd, nt_interactive_pwd,
134                               plaintext, password_state);
135         if (NT_STATUS_IS_OK(result)) {
136                 /* We have tried mapping */
137                 (*user_info)->mapped_state = True;
138                 /* did we actually map the user to a different name? */
139                 (*user_info)->was_mapped = was_mapped;
140         }
141         return result;
142 }
143
144 /****************************************************************************
145  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
146  Decrypt and encrypt the passwords.
147 ****************************************************************************/
148
149 bool make_user_info_netlogon_network(struct auth_usersupplied_info **user_info,
150                                      const char *smb_name, 
151                                      const char *client_domain, 
152                                      const char *workstation_name,
153                                      uint32 logon_parameters,
154                                      const uchar *lm_network_pwd,
155                                      int lm_pwd_len,
156                                      const uchar *nt_network_pwd,
157                                      int nt_pwd_len)
158 {
159         bool ret;
160         NTSTATUS status;
161         DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
162         DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
163
164         status = make_user_info_map(user_info,
165                                     smb_name, client_domain, 
166                                     workstation_name,
167                                     lm_pwd_len ? &lm_blob : NULL, 
168                                     nt_pwd_len ? &nt_blob : NULL,
169                                     NULL, NULL, NULL,
170                                     AUTH_PASSWORD_RESPONSE);
171
172         if (NT_STATUS_IS_OK(status)) {
173                 (*user_info)->logon_parameters = logon_parameters;
174         }
175         ret = NT_STATUS_IS_OK(status) ? True : False;
176
177         data_blob_free(&lm_blob);
178         data_blob_free(&nt_blob);
179         return ret;
180 }
181
182 /****************************************************************************
183  Create an auth_usersupplied_data, making the DATA_BLOBs here. 
184  Decrypt and encrypt the passwords.
185 ****************************************************************************/
186
187 bool make_user_info_netlogon_interactive(struct auth_usersupplied_info **user_info,
188                                          const char *smb_name, 
189                                          const char *client_domain, 
190                                          const char *workstation_name,
191                                          uint32 logon_parameters,
192                                          const uchar chal[8], 
193                                          const uchar lm_interactive_pwd[16], 
194                                          const uchar nt_interactive_pwd[16], 
195                                          const uchar *dc_sess_key)
196 {
197         struct samr_Password lm_pwd;
198         struct samr_Password nt_pwd;
199         unsigned char local_lm_response[24];
200         unsigned char local_nt_response[24];
201         unsigned char key[16];
202
203         memcpy(key, dc_sess_key, 16);
204
205         if (lm_interactive_pwd)
206                 memcpy(lm_pwd.hash, lm_interactive_pwd, sizeof(lm_pwd.hash));
207
208         if (nt_interactive_pwd)
209                 memcpy(nt_pwd.hash, nt_interactive_pwd, sizeof(nt_pwd.hash));
210
211 #ifdef DEBUG_PASSWORD
212         DEBUG(100,("key:"));
213         dump_data(100, key, sizeof(key));
214
215         DEBUG(100,("lm owf password:"));
216         dump_data(100, lm_pwd.hash, sizeof(lm_pwd.hash));
217
218         DEBUG(100,("nt owf password:"));
219         dump_data(100, nt_pwd.hash, sizeof(nt_pwd.hash));
220 #endif
221
222         if (lm_interactive_pwd)
223                 arcfour_crypt(lm_pwd.hash, key, sizeof(lm_pwd.hash));
224
225         if (nt_interactive_pwd)
226                 arcfour_crypt(nt_pwd.hash, key, sizeof(nt_pwd.hash));
227
228 #ifdef DEBUG_PASSWORD
229         DEBUG(100,("decrypt of lm owf password:"));
230         dump_data(100, lm_pwd.hash, sizeof(lm_pwd));
231
232         DEBUG(100,("decrypt of nt owf password:"));
233         dump_data(100, nt_pwd.hash, sizeof(nt_pwd));
234 #endif
235
236         if (lm_interactive_pwd)
237                 SMBOWFencrypt(lm_pwd.hash, chal,
238                               local_lm_response);
239
240         if (nt_interactive_pwd)
241                 SMBOWFencrypt(nt_pwd.hash, chal,
242                               local_nt_response);
243
244         /* Password info paranoia */
245         ZERO_STRUCT(key);
246
247         {
248                 bool ret;
249                 NTSTATUS nt_status;
250                 DATA_BLOB local_lm_blob;
251                 DATA_BLOB local_nt_blob;
252
253                 if (lm_interactive_pwd) {
254                         local_lm_blob = data_blob(local_lm_response,
255                                                   sizeof(local_lm_response));
256                 }
257
258                 if (nt_interactive_pwd) {
259                         local_nt_blob = data_blob(local_nt_response,
260                                                   sizeof(local_nt_response));
261                 }
262
263                 nt_status = make_user_info_map(
264                         user_info, 
265                         smb_name, client_domain, workstation_name,
266                         lm_interactive_pwd ? &local_lm_blob : NULL,
267                         nt_interactive_pwd ? &local_nt_blob : NULL,
268                         lm_interactive_pwd ? &lm_pwd : NULL,
269                         nt_interactive_pwd ? &nt_pwd : NULL,
270                         NULL, AUTH_PASSWORD_HASH);
271
272                 if (NT_STATUS_IS_OK(nt_status)) {
273                         (*user_info)->logon_parameters = logon_parameters;
274                 }
275
276                 ret = NT_STATUS_IS_OK(nt_status) ? True : False;
277                 data_blob_free(&local_lm_blob);
278                 data_blob_free(&local_nt_blob);
279                 return ret;
280         }
281 }
282
283
284 /****************************************************************************
285  Create an auth_usersupplied_data structure
286 ****************************************************************************/
287
288 bool make_user_info_for_reply(struct auth_usersupplied_info **user_info,
289                               const char *smb_name, 
290                               const char *client_domain,
291                               const uint8 chal[8],
292                               DATA_BLOB plaintext_password)
293 {
294
295         DATA_BLOB local_lm_blob;
296         DATA_BLOB local_nt_blob;
297         NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
298         char *plaintext_password_string;
299         /*
300          * Not encrypted - do so.
301          */
302
303         DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
304                  "format.\n"));
305         if (plaintext_password.data && plaintext_password.length) {
306                 unsigned char local_lm_response[24];
307
308 #ifdef DEBUG_PASSWORD
309                 DEBUG(10,("Unencrypted password (len %d):\n",
310                           (int)plaintext_password.length));
311                 dump_data(100, plaintext_password.data,
312                           plaintext_password.length);
313 #endif
314
315                 SMBencrypt( (const char *)plaintext_password.data,
316                             (const uchar*)chal, local_lm_response);
317                 local_lm_blob = data_blob(local_lm_response, 24);
318
319                 /* We can't do an NT hash here, as the password needs to be
320                    case insensitive */
321                 local_nt_blob = data_blob_null; 
322         } else {
323                 local_lm_blob = data_blob_null; 
324                 local_nt_blob = data_blob_null; 
325         }
326
327         plaintext_password_string = talloc_strndup(talloc_tos(),
328                                                    (const char *)plaintext_password.data,
329                                                    plaintext_password.length);
330         if (!plaintext_password_string) {
331                 return False;
332         }
333
334         ret = make_user_info_map(
335                 user_info, smb_name, client_domain, 
336                 get_remote_machine_name(),
337                 local_lm_blob.data ? &local_lm_blob : NULL,
338                 local_nt_blob.data ? &local_nt_blob : NULL,
339                 NULL, NULL,
340                 plaintext_password_string,
341                 AUTH_PASSWORD_PLAIN);
342
343         if (plaintext_password_string) {
344                 memset(plaintext_password_string, '\0', strlen(plaintext_password_string));
345                 talloc_free(plaintext_password_string);
346         }
347
348         data_blob_free(&local_lm_blob);
349         return NT_STATUS_IS_OK(ret) ? True : False;
350 }
351
352 /****************************************************************************
353  Create an auth_usersupplied_data structure
354 ****************************************************************************/
355
356 NTSTATUS make_user_info_for_reply_enc(struct auth_usersupplied_info **user_info,
357                                       const char *smb_name,
358                                       const char *client_domain, 
359                                       DATA_BLOB lm_resp, DATA_BLOB nt_resp)
360 {
361         return make_user_info_map(user_info, smb_name, 
362                                   client_domain, 
363                                   get_remote_machine_name(), 
364                                   lm_resp.data && (lm_resp.length > 0) ? &lm_resp : NULL,
365                                   nt_resp.data && (nt_resp.length > 0) ? &nt_resp : NULL,
366                                   NULL, NULL, NULL,
367                                   AUTH_PASSWORD_RESPONSE);
368 }
369
370 /****************************************************************************
371  Create a guest user_info blob, for anonymous authenticaion.
372 ****************************************************************************/
373
374 bool make_user_info_guest(struct auth_usersupplied_info **user_info)
375 {
376         NTSTATUS nt_status;
377
378         nt_status = make_user_info(user_info, 
379                                    "","", 
380                                    "","", 
381                                    "", 
382                                    NULL, NULL, 
383                                    NULL, NULL, 
384                                    NULL,
385                                    AUTH_PASSWORD_RESPONSE);
386
387         return NT_STATUS_IS_OK(nt_status) ? True : False;
388 }
389
390 static NTSTATUS log_nt_token(NT_USER_TOKEN *token)
391 {
392         TALLOC_CTX *frame = talloc_stackframe();
393         char *command;
394         char *group_sidstr;
395         size_t i;
396
397         if ((lp_log_nt_token_command() == NULL) ||
398             (strlen(lp_log_nt_token_command()) == 0)) {
399                 TALLOC_FREE(frame);
400                 return NT_STATUS_OK;
401         }
402
403         group_sidstr = talloc_strdup(frame, "");
404         for (i=1; i<token->num_sids; i++) {
405                 group_sidstr = talloc_asprintf(
406                         frame, "%s %s", group_sidstr,
407                         sid_string_talloc(frame, &token->user_sids[i]));
408         }
409
410         command = talloc_string_sub(
411                 frame, lp_log_nt_token_command(),
412                 "%s", sid_string_talloc(frame, &token->user_sids[0]));
413         command = talloc_string_sub(frame, command, "%t", group_sidstr);
414
415         if (command == NULL) {
416                 TALLOC_FREE(frame);
417                 return NT_STATUS_NO_MEMORY;
418         }
419
420         DEBUG(8, ("running command: [%s]\n", command));
421         if (smbrun(command, NULL) != 0) {
422                 DEBUG(0, ("Could not log NT token\n"));
423                 TALLOC_FREE(frame);
424                 return NT_STATUS_ACCESS_DENIED;
425         }
426
427         TALLOC_FREE(frame);
428         return NT_STATUS_OK;
429 }
430
431 /*
432  * Create the token to use from server_info->info3 and
433  * server_info->sids (the info3/sam groups). Find the unix gids.
434  */
435
436 NTSTATUS create_local_token(struct auth_serversupplied_info *server_info)
437 {
438         NTSTATUS status;
439         size_t i;
440         struct dom_sid tmp_sid;
441
442         /*
443          * If winbind is not around, we can not make much use of the SIDs the
444          * domain controller provided us with. Likewise if the user name was
445          * mapped to some local unix user.
446          */
447
448         if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
449             (server_info->nss_token)) {
450                 status = create_token_from_username(server_info,
451                                                     server_info->unix_name,
452                                                     server_info->guest,
453                                                     &server_info->utok.uid,
454                                                     &server_info->utok.gid,
455                                                     &server_info->unix_name,
456                                                     &server_info->ptok);
457
458         } else {
459                 status = create_local_nt_token_from_info3(server_info,
460                                                           server_info->guest,
461                                                           server_info->info3,
462                                                           &server_info->extra,
463                                                           &server_info->ptok);
464         }
465
466         if (!NT_STATUS_IS_OK(status)) {
467                 return status;
468         }
469
470         /* Convert the SIDs to gids. */
471
472         server_info->utok.ngroups = 0;
473         server_info->utok.groups = NULL;
474
475         /* Start at index 1, where the groups start. */
476
477         for (i=1; i<server_info->ptok->num_sids; i++) {
478                 gid_t gid;
479                 struct dom_sid *sid = &server_info->ptok->user_sids[i];
480
481                 if (!sid_to_gid(sid, &gid)) {
482                         DEBUG(10, ("Could not convert SID %s to gid, "
483                                    "ignoring it\n", sid_string_dbg(sid)));
484                         continue;
485                 }
486                 add_gid_to_array_unique(server_info, gid,
487                                         &server_info->utok.groups,
488                                         &server_info->utok.ngroups);
489         }
490
491         /*
492          * Add the "Unix Group" SID for each gid to catch mapped groups
493          * and their Unix equivalent.  This is to solve the backwards
494          * compatibility problem of 'valid users = +ntadmin' where
495          * ntadmin has been paired with "Domain Admins" in the group
496          * mapping table.  Otherwise smb.conf would need to be changed
497          * to 'valid user = "Domain Admins"'.  --jerry
498          *
499          * For consistency we also add the "Unix User" SID,
500          * so that the complete unix token is represented within
501          * the nt token.
502          */
503
504         uid_to_unix_users_sid(server_info->utok.uid, &tmp_sid);
505
506         add_sid_to_array_unique(server_info->ptok, &tmp_sid,
507                                 &server_info->ptok->user_sids,
508                                 &server_info->ptok->num_sids);
509
510         for ( i=0; i<server_info->utok.ngroups; i++ ) {
511                 gid_to_unix_groups_sid(server_info->utok.groups[i], &tmp_sid);
512                 add_sid_to_array_unique(server_info->ptok, &tmp_sid,
513                                         &server_info->ptok->user_sids,
514                                         &server_info->ptok->num_sids);
515         }
516
517         debug_nt_user_token(DBGC_AUTH, 10, server_info->ptok);
518         debug_unix_user_token(DBGC_AUTH, 10,
519                               server_info->utok.uid,
520                               server_info->utok.gid,
521                               server_info->utok.ngroups,
522                               server_info->utok.groups);
523
524         status = log_nt_token(server_info->ptok);
525         return status;
526 }
527
528 /***************************************************************************
529  Make (and fill) a server_info struct from a 'struct passwd' by conversion
530  to a struct samu
531 ***************************************************************************/
532
533 NTSTATUS make_server_info_pw(struct auth_serversupplied_info **server_info,
534                              char *unix_username,
535                              struct passwd *pwd)
536 {
537         NTSTATUS status;
538         struct samu *sampass = NULL;
539         char *qualified_name = NULL;
540         TALLOC_CTX *mem_ctx = NULL;
541         struct dom_sid u_sid;
542         enum lsa_SidType type;
543         struct auth_serversupplied_info *result;
544
545         /*
546          * The SID returned in server_info->sam_account is based
547          * on our SAM sid even though for a pure UNIX account this should
548          * not be the case as it doesn't really exist in the SAM db.
549          * This causes lookups on "[in]valid users" to fail as they
550          * will lookup this name as a "Unix User" SID to check against
551          * the user token. Fix this by adding the "Unix User"\unix_username
552          * SID to the sid array. The correct fix should probably be
553          * changing the server_info->sam_account user SID to be a
554          * S-1-22 Unix SID, but this might break old configs where
555          * plaintext passwords were used with no SAM backend.
556          */
557
558         mem_ctx = talloc_init("make_server_info_pw_tmp");
559         if (!mem_ctx) {
560                 return NT_STATUS_NO_MEMORY;
561         }
562
563         qualified_name = talloc_asprintf(mem_ctx, "%s\\%s",
564                                         unix_users_domain_name(),
565                                         unix_username );
566         if (!qualified_name) {
567                 TALLOC_FREE(mem_ctx);
568                 return NT_STATUS_NO_MEMORY;
569         }
570
571         if (!lookup_name(mem_ctx, qualified_name, LOOKUP_NAME_ALL,
572                                                 NULL, NULL,
573                                                 &u_sid, &type)) {
574                 TALLOC_FREE(mem_ctx);
575                 return NT_STATUS_NO_SUCH_USER;
576         }
577
578         TALLOC_FREE(mem_ctx);
579
580         if (type != SID_NAME_USER) {
581                 return NT_STATUS_NO_SUCH_USER;
582         }
583
584         if ( !(sampass = samu_new( NULL )) ) {
585                 return NT_STATUS_NO_MEMORY;
586         }
587
588         status = samu_set_unix( sampass, pwd );
589         if (!NT_STATUS_IS_OK(status)) {
590                 return status;
591         }
592
593         /* In pathological cases the above call can set the account
594          * name to the DOMAIN\username form. Reset the account name
595          * using unix_username */
596         pdb_set_username(sampass, unix_username, PDB_SET);
597
598         /* set the user sid to be the calculated u_sid */
599         pdb_set_user_sid(sampass, &u_sid, PDB_SET);
600
601         result = make_server_info(NULL);
602         if (result == NULL) {
603                 TALLOC_FREE(sampass);
604                 return NT_STATUS_NO_MEMORY;
605         }
606
607         status = samu_to_SamInfo3(result, sampass, global_myname(),
608                                   &result->info3, &result->extra);
609         TALLOC_FREE(sampass);
610         if (!NT_STATUS_IS_OK(status)) {
611                 DEBUG(10, ("Failed to convert samu to info3: %s\n",
612                            nt_errstr(status)));
613                 TALLOC_FREE(result);
614                 return status;
615         }
616
617         result->unix_name = talloc_strdup(result, unix_username);
618         result->sanitized_username = sanitize_username(result, unix_username);
619
620         if ((result->unix_name == NULL)
621             || (result->sanitized_username == NULL)) {
622                 TALLOC_FREE(result);
623                 return NT_STATUS_NO_MEMORY;
624         }
625
626         result->utok.uid = pwd->pw_uid;
627         result->utok.gid = pwd->pw_gid;
628
629         *server_info = result;
630
631         return NT_STATUS_OK;
632 }
633
634 /***************************************************************************
635  Make (and fill) a user_info struct for a guest login.
636  This *must* succeed for smbd to start. If there is no mapping entry for
637  the guest gid, then create one.
638 ***************************************************************************/
639
640 static NTSTATUS make_new_server_info_guest(struct auth_serversupplied_info **server_info)
641 {
642         NTSTATUS status;
643         struct samu *sampass = NULL;
644         struct dom_sid guest_sid;
645         bool ret;
646         static const char zeros[16] = {0, };
647         fstring tmp;
648
649         if ( !(sampass = samu_new( NULL )) ) {
650                 return NT_STATUS_NO_MEMORY;
651         }
652
653         sid_compose(&guest_sid, get_global_sam_sid(), DOMAIN_RID_GUEST);
654
655         become_root();
656         ret = pdb_getsampwsid(sampass, &guest_sid);
657         unbecome_root();
658
659         if (!ret) {
660                 TALLOC_FREE(sampass);
661                 return NT_STATUS_NO_SUCH_USER;
662         }
663
664         status = make_server_info_sam(server_info, sampass);
665         if (!NT_STATUS_IS_OK(status)) {
666                 TALLOC_FREE(sampass);
667                 return status;
668         }
669
670         TALLOC_FREE(sampass);
671
672         (*server_info)->guest = True;
673
674         status = create_local_token(*server_info);
675         if (!NT_STATUS_IS_OK(status)) {
676                 DEBUG(10, ("create_local_token failed: %s\n",
677                            nt_errstr(status)));
678                 return status;
679         }
680
681         /* annoying, but the Guest really does have a session key, and it is
682            all zeros! */
683         (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
684         (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
685
686         alpha_strcpy(tmp, (*server_info)->info3->base.account_name.string,
687                      ". _-$", sizeof(tmp));
688         (*server_info)->sanitized_username = talloc_strdup(*server_info, tmp);
689
690         return NT_STATUS_OK;
691 }
692
693 /***************************************************************************
694  Make (and fill) a user_info struct for a system user login.
695  This *must* succeed for smbd to start.
696 ***************************************************************************/
697
698 static NTSTATUS make_new_server_info_system(TALLOC_CTX *mem_ctx,
699                                             struct auth_serversupplied_info **server_info)
700 {
701         struct passwd *pwd;
702         NTSTATUS status;
703
704         pwd = getpwuid_alloc(mem_ctx, sec_initial_uid());
705         if (pwd == NULL) {
706                 return NT_STATUS_NO_MEMORY;
707         }
708
709         status = make_serverinfo_from_username(mem_ctx,
710                                              pwd->pw_name,
711                                              false,
712                                              server_info);
713         if (!NT_STATUS_IS_OK(status)) {
714                 return status;
715         }
716
717         (*server_info)->system = true;
718
719         return NT_STATUS_OK;
720 }
721
722 /****************************************************************************
723   Fake a auth_serversupplied_info just from a username
724 ****************************************************************************/
725
726 NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx,
727                                        const char *username,
728                                        bool is_guest,
729                                        struct auth_serversupplied_info **presult)
730 {
731         struct auth_serversupplied_info *result;
732         struct passwd *pwd;
733         NTSTATUS status;
734
735         pwd = getpwnam_alloc(talloc_tos(), username);
736         if (pwd == NULL) {
737                 return NT_STATUS_NO_SUCH_USER;
738         }
739
740         status = make_server_info_pw(&result, pwd->pw_name, pwd);
741
742         TALLOC_FREE(pwd);
743
744         if (!NT_STATUS_IS_OK(status)) {
745                 return status;
746         }
747
748         result->nss_token = true;
749         result->guest = is_guest;
750
751         status = create_local_token(result);
752
753         if (!NT_STATUS_IS_OK(status)) {
754                 TALLOC_FREE(result);
755                 return status;
756         }
757
758         *presult = result;
759         return NT_STATUS_OK;
760 }
761
762
763 struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx,
764                                                  const struct auth_serversupplied_info *src)
765 {
766         struct auth_serversupplied_info *dst;
767
768         dst = make_server_info(mem_ctx);
769         if (dst == NULL) {
770                 return NULL;
771         }
772
773         dst->guest = src->guest;
774         dst->system = src->system;
775         dst->utok.uid = src->utok.uid;
776         dst->utok.gid = src->utok.gid;
777         dst->utok.ngroups = src->utok.ngroups;
778         if (src->utok.ngroups != 0) {
779                 dst->utok.groups = (gid_t *)TALLOC_MEMDUP(
780                         dst, src->utok.groups,
781                         sizeof(gid_t)*dst->utok.ngroups);
782         } else {
783                 dst->utok.groups = NULL;
784         }
785
786         if (src->ptok) {
787                 dst->ptok = dup_nt_token(dst, src->ptok);
788                 if (!dst->ptok) {
789                         TALLOC_FREE(dst);
790                         return NULL;
791                 }
792         }
793
794         dst->user_session_key = data_blob_talloc( dst, src->user_session_key.data,
795                                                 src->user_session_key.length);
796
797         dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data,
798                                                 src->lm_session_key.length);
799
800         dst->info3 = copy_netr_SamInfo3(dst, src->info3);
801         if (!dst->info3) {
802                 TALLOC_FREE(dst);
803                 return NULL;
804         }
805         dst->extra = src->extra;
806
807         dst->pam_handle = NULL;
808         dst->unix_name = talloc_strdup(dst, src->unix_name);
809         if (!dst->unix_name) {
810                 TALLOC_FREE(dst);
811                 return NULL;
812         }
813
814         dst->sanitized_username = talloc_strdup(dst, src->sanitized_username);
815         if (!dst->sanitized_username) {
816                 TALLOC_FREE(dst);
817                 return NULL;
818         }
819
820         return dst;
821 }
822
823 /*
824  * Set a new session key. Used in the rpc server where we have to override the
825  * SMB level session key with SystemLibraryDTC
826  */
827
828 bool server_info_set_session_key(struct auth_serversupplied_info *info,
829                                  DATA_BLOB session_key)
830 {
831         TALLOC_FREE(info->user_session_key.data);
832
833         info->user_session_key = data_blob_talloc(
834                 info, session_key.data, session_key.length);
835
836         return (info->user_session_key.data != NULL);
837 }
838
839 static struct auth_serversupplied_info *guest_info = NULL;
840
841 bool init_guest_info(void)
842 {
843         if (guest_info != NULL)
844                 return True;
845
846         return NT_STATUS_IS_OK(make_new_server_info_guest(&guest_info));
847 }
848
849 NTSTATUS make_server_info_guest(TALLOC_CTX *mem_ctx,
850                                 struct auth_serversupplied_info **server_info)
851 {
852         *server_info = copy_serverinfo(mem_ctx, guest_info);
853         return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
854 }
855
856 static struct auth_serversupplied_info *system_info = NULL;
857
858 bool init_system_info(void)
859 {
860         if (system_info != NULL)
861                 return True;
862
863         return NT_STATUS_IS_OK(make_new_server_info_system(talloc_autofree_context(), &system_info));
864 }
865
866 NTSTATUS make_server_info_system(TALLOC_CTX *mem_ctx,
867                                 struct auth_serversupplied_info **server_info)
868 {
869         if (system_info == NULL) return NT_STATUS_UNSUCCESSFUL;
870         *server_info = copy_serverinfo(mem_ctx, system_info);
871         return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
872 }
873
874 bool copy_current_user(struct current_user *dst, struct current_user *src)
875 {
876         gid_t *groups;
877         NT_USER_TOKEN *nt_token;
878
879         groups = (gid_t *)memdup(src->ut.groups,
880                                  sizeof(gid_t) * src->ut.ngroups);
881         if ((src->ut.ngroups != 0) && (groups == NULL)) {
882                 return False;
883         }
884
885         nt_token = dup_nt_token(NULL, src->nt_user_token);
886         if (nt_token == NULL) {
887                 SAFE_FREE(groups);
888                 return False;
889         }
890
891         dst->conn = src->conn;
892         dst->vuid = src->vuid;
893         dst->ut.uid = src->ut.uid;
894         dst->ut.gid = src->ut.gid;
895         dst->ut.ngroups = src->ut.ngroups;
896         dst->ut.groups = groups;
897         dst->nt_user_token = nt_token;
898         return True;
899 }
900
901 /***************************************************************************
902  Purely internal function for make_server_info_info3
903 ***************************************************************************/
904
905 static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain,
906                               const char *username, char **found_username,
907                               struct passwd **pwd,
908                               bool *username_was_mapped)
909 {
910         fstring dom_user, lower_username;
911         fstring real_username;
912         struct passwd *passwd;
913
914         fstrcpy( lower_username, username );
915         strlower_m( lower_username );
916
917         fstr_sprintf(dom_user, "%s%c%s", domain, *lp_winbind_separator(), 
918                 lower_username);
919
920         /* Get the passwd struct.  Try to create the account if necessary. */
921
922         *username_was_mapped = map_username(dom_user);
923
924         passwd = smb_getpwnam( NULL, dom_user, real_username, True );
925         if (!passwd) {
926                 DEBUG(3, ("Failed to find authenticated user %s via "
927                           "getpwnam(), denying access.\n", dom_user));
928                 return NT_STATUS_NO_SUCH_USER;
929         }
930
931         *pwd = passwd;
932
933         /* This is pointless -- there is no suport for differing 
934            unix and windows names.  Make sure to always store the 
935            one we actually looked up and succeeded. Have I mentioned
936            why I hate the 'winbind use default domain' parameter?   
937                                          --jerry              */
938
939         *found_username = talloc_strdup( mem_ctx, real_username );
940
941         return NT_STATUS_OK;
942 }
943
944 /****************************************************************************
945  Wrapper to allow the getpwnam() call to strip the domain name and 
946  try again in case a local UNIX user is already there.  Also run through 
947  the username if we fallback to the username only.
948  ****************************************************************************/
949
950 struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, char *domuser,
951                              fstring save_username, bool create )
952 {
953         struct passwd *pw = NULL;
954         char *p;
955         fstring username;
956
957         /* we only save a copy of the username it has been mangled 
958            by winbindd use default domain */
959
960         save_username[0] = '\0';
961
962         /* don't call map_username() here since it has to be done higher 
963            up the stack so we don't call it multiple times */
964
965         fstrcpy( username, domuser );
966
967         p = strchr_m( username, *lp_winbind_separator() );
968
969         /* code for a DOMAIN\user string */
970
971         if ( p ) {
972                 fstring strip_username;
973
974                 pw = Get_Pwnam_alloc( mem_ctx, domuser );
975                 if ( pw ) {     
976                         /* make sure we get the case of the username correct */
977                         /* work around 'winbind use default domain = yes' */
978
979                         if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
980                                 char *domain;
981
982                                 /* split the domain and username into 2 strings */
983                                 *p = '\0';
984                                 domain = username;
985
986                                 fstr_sprintf(save_username, "%s%c%s", domain, *lp_winbind_separator(), pw->pw_name);
987                         }
988                         else
989                                 fstrcpy( save_username, pw->pw_name );
990
991                         /* whew -- done! */             
992                         return pw;
993                 }
994
995                 /* setup for lookup of just the username */
996                 /* remember that p and username are overlapping memory */
997
998                 p++;
999                 fstrcpy( strip_username, p );
1000                 fstrcpy( username, strip_username );
1001         }
1002
1003         /* just lookup a plain username */
1004
1005         pw = Get_Pwnam_alloc(mem_ctx, username);
1006
1007         /* Create local user if requested but only if winbindd
1008            is not running.  We need to protect against cases
1009            where winbindd is failing and then prematurely
1010            creating users in /etc/passwd */
1011
1012         if ( !pw && create && !winbind_ping() ) {
1013                 /* Don't add a machine account. */
1014                 if (username[strlen(username)-1] == '$')
1015                         return NULL;
1016
1017                 _smb_create_user(NULL, username, NULL);
1018                 pw = Get_Pwnam_alloc(mem_ctx, username);
1019         }
1020
1021         /* one last check for a valid passwd struct */
1022
1023         if ( pw )
1024                 fstrcpy( save_username, pw->pw_name );
1025
1026         return pw;
1027 }
1028
1029 /***************************************************************************
1030  Make a server_info struct from the info3 returned by a domain logon 
1031 ***************************************************************************/
1032
1033 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 
1034                                 const char *sent_nt_username,
1035                                 const char *domain,
1036                                 struct auth_serversupplied_info **server_info,
1037                                 struct netr_SamInfo3 *info3)
1038 {
1039         static const char zeros[16] = {0, };
1040
1041         NTSTATUS nt_status = NT_STATUS_OK;
1042         char *found_username = NULL;
1043         const char *nt_domain;
1044         const char *nt_username;
1045         bool username_was_mapped;
1046         struct passwd *pwd;
1047         struct auth_serversupplied_info *result;
1048         struct dom_sid *group_sid;
1049         struct netr_SamInfo3 *i3;
1050
1051         /* 
1052            Here is where we should check the list of
1053            trusted domains, and verify that the SID 
1054            matches.
1055         */
1056
1057         nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string);
1058         if (!nt_username) {
1059                 /* If the server didn't give us one, just use the one we sent
1060                  * them */
1061                 nt_username = sent_nt_username;
1062         }
1063
1064         nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string);
1065         if (!nt_domain) {
1066                 /* If the server didn't give us one, just use the one we sent
1067                  * them */
1068                 nt_domain = domain;
1069         }
1070
1071         /* If getpwnam() fails try the add user script (2.2.x behavior).
1072
1073            We use the _unmapped_ username here in an attempt to provide
1074            consistent username mapping behavior between kerberos and NTLM[SSP]
1075            authentication in domain mode security.  I.E. Username mapping
1076            should be applied to the fully qualified username
1077            (e.g. DOMAIN\user) and not just the login name.  Yes this means we
1078            called map_username() unnecessarily in make_user_info_map() but
1079            that is how the current code is designed.  Making the change here
1080            is the least disruptive place.  -- jerry */
1081
1082         /* this call will try to create the user if necessary */
1083
1084         nt_status = check_account(mem_ctx, nt_domain, sent_nt_username,
1085                                      &found_username, &pwd,
1086                                      &username_was_mapped);
1087
1088         if (!NT_STATUS_IS_OK(nt_status)) {
1089                 return nt_status;
1090         }
1091
1092         result = make_server_info(NULL);
1093         if (result == NULL) {
1094                 DEBUG(4, ("make_server_info failed!\n"));
1095                 return NT_STATUS_NO_MEMORY;
1096         }
1097
1098         result->unix_name = talloc_strdup(result, found_username);
1099
1100         result->sanitized_username = sanitize_username(result,
1101                                                        result->unix_name);
1102         if (result->sanitized_username == NULL) {
1103                 TALLOC_FREE(result);
1104                 return NT_STATUS_NO_MEMORY;
1105         }
1106
1107         /* copy in the info3 */
1108         result->info3 = i3 = copy_netr_SamInfo3(result, info3);
1109         if (result->info3 == NULL) {
1110                 TALLOC_FREE(result);
1111                 return NT_STATUS_NO_MEMORY;
1112         }
1113
1114         /* Fill in the unix info we found on the way */
1115         result->utok.uid = pwd->pw_uid;
1116         result->utok.gid = pwd->pw_gid;
1117
1118         /* We can't just trust that the primary group sid sent us is something
1119          * we can really use. Obtain the useable sid, and store the original
1120          * one as an additional group if it had to be replaced */
1121         nt_status = get_primary_group_sid(mem_ctx, found_username,
1122                                           &pwd, &group_sid);
1123         if (!NT_STATUS_IS_OK(nt_status)) {
1124                 TALLOC_FREE(result);
1125                 return nt_status;
1126         }
1127
1128         /* store and check if it is the same we got originally */
1129         sid_peek_rid(group_sid, &i3->base.primary_gid);
1130         if (i3->base.primary_gid != info3->base.primary_gid) {
1131                 uint32_t n = i3->base.groups.count;
1132                 /* not the same, store the original as an additional group */
1133                 i3->base.groups.rids =
1134                         talloc_realloc(i3, i3->base.groups.rids,
1135                                         struct samr_RidWithAttribute, n + 1);
1136                 if (i3->base.groups.rids == NULL) {
1137                         TALLOC_FREE(result);
1138                         return NT_STATUS_NO_MEMORY;
1139                 }
1140                 i3->base.groups.rids[n].rid = info3->base.primary_gid;
1141                 i3->base.groups.rids[n].attributes = SE_GROUP_ENABLED;
1142                 i3->base.groups.count = n + 1;
1143         }
1144
1145         /* ensure we are never given NULL session keys */
1146
1147         if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
1148                 result->user_session_key = data_blob_null;
1149         } else {
1150                 result->user_session_key = data_blob_talloc(
1151                         result, info3->base.key.key,
1152                         sizeof(info3->base.key.key));
1153         }
1154
1155         if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
1156                 result->lm_session_key = data_blob_null;
1157         } else {
1158                 result->lm_session_key = data_blob_talloc(
1159                         result, info3->base.LMSessKey.key,
1160                         sizeof(info3->base.LMSessKey.key));
1161         }
1162
1163         result->nss_token |= username_was_mapped;
1164
1165         *server_info = result;
1166
1167         return NT_STATUS_OK;
1168 }
1169
1170 /*****************************************************************************
1171  Make a server_info struct from the wbcAuthUserInfo returned by a domain logon
1172 ******************************************************************************/
1173
1174 NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx,
1175                                           const char *sent_nt_username,
1176                                           const char *domain,
1177                                           const struct wbcAuthUserInfo *info,
1178                                           struct auth_serversupplied_info **server_info)
1179 {
1180         struct netr_SamInfo3 *info3;
1181
1182         info3 = wbcAuthUserInfo_to_netr_SamInfo3(mem_ctx, info);
1183         if (!info3) {
1184                 return NT_STATUS_NO_MEMORY;
1185         }
1186
1187         return make_server_info_info3(mem_ctx,
1188                                       sent_nt_username, domain,
1189                                       server_info, info3);
1190 }
1191
1192 /**
1193  * Verify whether or not given domain is trusted.
1194  *
1195  * @param domain_name name of the domain to be verified
1196  * @return true if domain is one of the trusted ones or
1197  *         false if otherwise
1198  **/
1199
1200 bool is_trusted_domain(const char* dom_name)
1201 {
1202         struct dom_sid trustdom_sid;
1203         bool ret;
1204
1205         /* no trusted domains for a standalone server */
1206
1207         if ( lp_server_role() == ROLE_STANDALONE )
1208                 return False;
1209
1210         if (dom_name == NULL || dom_name[0] == '\0') {
1211                 return false;
1212         }
1213
1214         if (strequal(dom_name, get_global_sam_name())) {
1215                 return false;
1216         }
1217
1218         /* if we are a DC, then check for a direct trust relationships */
1219
1220         if ( IS_DC ) {
1221                 become_root();
1222                 DEBUG (5,("is_trusted_domain: Checking for domain trust with "
1223                           "[%s]\n", dom_name ));
1224                 ret = pdb_get_trusteddom_pw(dom_name, NULL, NULL, NULL);
1225                 unbecome_root();
1226                 if (ret)
1227                         return True;
1228         }
1229         else {
1230                 wbcErr result;
1231
1232                 /* If winbind is around, ask it */
1233
1234                 result = wb_is_trusted_domain(dom_name);
1235
1236                 if (result == WBC_ERR_SUCCESS) {
1237                         return True;
1238                 }
1239
1240                 if (result == WBC_ERR_DOMAIN_NOT_FOUND) {
1241                         /* winbind could not find the domain */
1242                         return False;
1243                 }
1244
1245                 /* The only other possible result is that winbind is not up
1246                    and running. We need to update the trustdom_cache
1247                    ourselves */
1248
1249                 update_trustdom_cache();
1250         }
1251
1252         /* now the trustdom cache should be available a DC could still
1253          * have a transitive trust so fall back to the cache of trusted
1254          * domains (like a domain member would use  */
1255
1256         if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1257                 return True;
1258         }
1259
1260         return False;
1261 }
1262