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