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