r8814: sync for 3.0.20rc1 (up to r8805 from 3.0 tree)
[Samba.git] / source / auth / auth_util.c
blob6624631b53dd5c5df1153abb787d55c779212d2c
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
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_AUTH
30 /****************************************************************************
31 Create a UNIX user on demand.
32 ****************************************************************************/
34 static int smb_create_user(const char *domain, const char *unix_username, const char *homedir)
36 pstring add_script;
37 int ret;
39 pstrcpy(add_script, lp_adduser_script());
40 if (! *add_script)
41 return -1;
42 all_string_sub(add_script, "%u", unix_username, sizeof(pstring));
43 if (domain)
44 all_string_sub(add_script, "%D", domain, sizeof(pstring));
45 if (homedir)
46 all_string_sub(add_script, "%H", homedir, sizeof(pstring));
47 ret = smbrun(add_script,NULL);
48 flush_pwnam_cache();
49 DEBUG(ret ? 0 : 3,("smb_create_user: Running the command `%s' gave %d\n",add_script,ret));
50 return ret;
53 /****************************************************************************
54 Create a SAM_ACCOUNT - either by looking in the pdb, or by faking it up from
55 unix info.
56 ****************************************************************************/
58 NTSTATUS auth_get_sam_account(const char *user, SAM_ACCOUNT **account)
60 BOOL pdb_ret;
61 NTSTATUS nt_status;
62 if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(account))) {
63 return nt_status;
66 become_root();
67 pdb_ret = pdb_getsampwnam(*account, user);
68 unbecome_root();
70 if (!pdb_ret) {
72 struct passwd *pass = Get_Pwnam(user);
73 if (!pass)
74 return NT_STATUS_NO_SUCH_USER;
76 if (!NT_STATUS_IS_OK(nt_status = pdb_fill_sam_pw(*account, pass))) {
77 return nt_status;
80 return NT_STATUS_OK;
83 /****************************************************************************
84 Create an auth_usersupplied_data structure
85 ****************************************************************************/
87 static NTSTATUS make_user_info(auth_usersupplied_info **user_info,
88 const char *smb_name,
89 const char *internal_username,
90 const char *client_domain,
91 const char *domain,
92 const char *wksta_name,
93 DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd,
94 DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd,
95 DATA_BLOB *plaintext,
96 BOOL encrypted)
99 DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name));
101 *user_info = SMB_MALLOC_P(auth_usersupplied_info);
102 if (!user_info) {
103 DEBUG(0,("malloc failed for user_info (size %lu)\n", (unsigned long)sizeof(*user_info)));
104 return NT_STATUS_NO_MEMORY;
107 ZERO_STRUCTP(*user_info);
109 DEBUG(5,("making strings for %s's user_info struct\n", internal_username));
111 (*user_info)->smb_name.str = SMB_STRDUP(smb_name);
112 if ((*user_info)->smb_name.str) {
113 (*user_info)->smb_name.len = strlen(smb_name);
114 } else {
115 free_user_info(user_info);
116 return NT_STATUS_NO_MEMORY;
119 (*user_info)->internal_username.str = SMB_STRDUP(internal_username);
120 if ((*user_info)->internal_username.str) {
121 (*user_info)->internal_username.len = strlen(internal_username);
122 } else {
123 free_user_info(user_info);
124 return NT_STATUS_NO_MEMORY;
127 (*user_info)->domain.str = SMB_STRDUP(domain);
128 if ((*user_info)->domain.str) {
129 (*user_info)->domain.len = strlen(domain);
130 } else {
131 free_user_info(user_info);
132 return NT_STATUS_NO_MEMORY;
135 (*user_info)->client_domain.str = SMB_STRDUP(client_domain);
136 if ((*user_info)->client_domain.str) {
137 (*user_info)->client_domain.len = strlen(client_domain);
138 } else {
139 free_user_info(user_info);
140 return NT_STATUS_NO_MEMORY;
143 (*user_info)->wksta_name.str = SMB_STRDUP(wksta_name);
144 if ((*user_info)->wksta_name.str) {
145 (*user_info)->wksta_name.len = strlen(wksta_name);
146 } else {
147 free_user_info(user_info);
148 return NT_STATUS_NO_MEMORY;
151 DEBUG(5,("making blobs for %s's user_info struct\n", internal_username));
153 if (lm_pwd)
154 (*user_info)->lm_resp = data_blob(lm_pwd->data, lm_pwd->length);
155 if (nt_pwd)
156 (*user_info)->nt_resp = data_blob(nt_pwd->data, nt_pwd->length);
157 if (lm_interactive_pwd)
158 (*user_info)->lm_interactive_pwd = data_blob(lm_interactive_pwd->data, lm_interactive_pwd->length);
159 if (nt_interactive_pwd)
160 (*user_info)->nt_interactive_pwd = data_blob(nt_interactive_pwd->data, nt_interactive_pwd->length);
162 if (plaintext)
163 (*user_info)->plaintext_password = data_blob(plaintext->data, plaintext->length);
165 (*user_info)->encrypted = encrypted;
167 DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name));
169 return NT_STATUS_OK;
172 /****************************************************************************
173 Create an auth_usersupplied_data structure after appropriate mapping.
174 ****************************************************************************/
176 NTSTATUS make_user_info_map(auth_usersupplied_info **user_info,
177 const char *smb_name,
178 const char *client_domain,
179 const char *wksta_name,
180 DATA_BLOB *lm_pwd, DATA_BLOB *nt_pwd,
181 DATA_BLOB *lm_interactive_pwd, DATA_BLOB *nt_interactive_pwd,
182 DATA_BLOB *plaintext,
183 BOOL encrypted)
185 const char *domain;
186 fstring internal_username;
187 fstrcpy(internal_username, smb_name);
188 map_username(internal_username);
190 DEBUG(5, ("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n",
191 client_domain, smb_name, wksta_name));
193 /* don't allow "" as a domain, fixes a Win9X bug
194 where it doens't supply a domain for logon script
195 'net use' commands. */
197 if ( *client_domain )
198 domain = client_domain;
199 else
200 domain = lp_workgroup();
202 /* do what win2k does. Always map unknown domains to our own
203 and let the "passdb backend" handle unknown users. */
205 if ( !is_trusted_domain(domain) && !strequal(domain, get_global_sam_name()) )
206 domain = get_default_sam_name();
208 /* we know that it is a trusted domain (and we are allowing them) or it is our domain */
210 return make_user_info(user_info, smb_name, internal_username,
211 client_domain, domain, wksta_name,
212 lm_pwd, nt_pwd,
213 lm_interactive_pwd, nt_interactive_pwd,
214 plaintext, encrypted);
217 /****************************************************************************
218 Create an auth_usersupplied_data, making the DATA_BLOBs here.
219 Decrypt and encrypt the passwords.
220 ****************************************************************************/
222 BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info,
223 const char *smb_name,
224 const char *client_domain,
225 const char *wksta_name,
226 const uchar *lm_network_pwd, int lm_pwd_len,
227 const uchar *nt_network_pwd, int nt_pwd_len)
229 BOOL ret;
230 NTSTATUS nt_status;
231 DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
232 DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
234 nt_status = make_user_info_map(user_info,
235 smb_name, client_domain,
236 wksta_name,
237 lm_pwd_len ? &lm_blob : NULL,
238 nt_pwd_len ? &nt_blob : NULL,
239 NULL, NULL, NULL,
240 True);
242 ret = NT_STATUS_IS_OK(nt_status) ? True : False;
244 data_blob_free(&lm_blob);
245 data_blob_free(&nt_blob);
246 return ret;
249 /****************************************************************************
250 Create an auth_usersupplied_data, making the DATA_BLOBs here.
251 Decrypt and encrypt the passwords.
252 ****************************************************************************/
254 BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
255 const char *smb_name,
256 const char *client_domain,
257 const char *wksta_name,
258 const uchar chal[8],
259 const uchar lm_interactive_pwd[16],
260 const uchar nt_interactive_pwd[16],
261 const uchar *dc_sess_key)
263 char lm_pwd[16];
264 char nt_pwd[16];
265 unsigned char local_lm_response[24];
266 unsigned char local_nt_response[24];
267 unsigned char key[16];
269 ZERO_STRUCT(key);
270 memcpy(key, dc_sess_key, 8);
272 if (lm_interactive_pwd) memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd));
273 if (nt_interactive_pwd) memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd));
275 #ifdef DEBUG_PASSWORD
276 DEBUG(100,("key:"));
277 dump_data(100, (char *)key, sizeof(key));
279 DEBUG(100,("lm owf password:"));
280 dump_data(100, lm_pwd, sizeof(lm_pwd));
282 DEBUG(100,("nt owf password:"));
283 dump_data(100, nt_pwd, sizeof(nt_pwd));
284 #endif
286 if (lm_interactive_pwd)
287 SamOEMhash((uchar *)lm_pwd, key, sizeof(lm_pwd));
289 if (nt_interactive_pwd)
290 SamOEMhash((uchar *)nt_pwd, key, sizeof(nt_pwd));
292 #ifdef DEBUG_PASSWORD
293 DEBUG(100,("decrypt of lm owf password:"));
294 dump_data(100, lm_pwd, sizeof(lm_pwd));
296 DEBUG(100,("decrypt of nt owf password:"));
297 dump_data(100, nt_pwd, sizeof(nt_pwd));
298 #endif
300 if (lm_interactive_pwd)
301 SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response);
303 if (nt_interactive_pwd)
304 SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response);
306 /* Password info paranoia */
307 ZERO_STRUCT(key);
310 BOOL ret;
311 NTSTATUS nt_status;
312 DATA_BLOB local_lm_blob;
313 DATA_BLOB local_nt_blob;
315 DATA_BLOB lm_interactive_blob;
316 DATA_BLOB nt_interactive_blob;
318 if (lm_interactive_pwd) {
319 local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
320 lm_interactive_blob = data_blob(lm_pwd, sizeof(lm_pwd));
321 ZERO_STRUCT(lm_pwd);
324 if (nt_interactive_pwd) {
325 local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
326 nt_interactive_blob = data_blob(nt_pwd, sizeof(nt_pwd));
327 ZERO_STRUCT(nt_pwd);
330 nt_status = make_user_info_map(user_info,
331 smb_name, client_domain,
332 wksta_name,
333 lm_interactive_pwd ? &local_lm_blob : NULL,
334 nt_interactive_pwd ? &local_nt_blob : NULL,
335 lm_interactive_pwd ? &lm_interactive_blob : NULL,
336 nt_interactive_pwd ? &nt_interactive_blob : NULL,
337 NULL,
338 True);
340 ret = NT_STATUS_IS_OK(nt_status) ? True : False;
341 data_blob_free(&local_lm_blob);
342 data_blob_free(&local_nt_blob);
343 data_blob_free(&lm_interactive_blob);
344 data_blob_free(&nt_interactive_blob);
345 return ret;
350 /****************************************************************************
351 Create an auth_usersupplied_data structure
352 ****************************************************************************/
354 BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
355 const char *smb_name,
356 const char *client_domain,
357 const uint8 chal[8],
358 DATA_BLOB plaintext_password)
361 DATA_BLOB local_lm_blob;
362 DATA_BLOB local_nt_blob;
363 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
366 * Not encrypted - do so.
369 DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted format.\n"));
371 if (plaintext_password.data) {
372 unsigned char local_lm_response[24];
374 #ifdef DEBUG_PASSWORD
375 DEBUG(10,("Unencrypted password (len %d):\n",plaintext_password.length));
376 dump_data(100, plaintext_password.data, plaintext_password.length);
377 #endif
379 SMBencrypt( (const char *)plaintext_password.data, (const uchar*)chal, local_lm_response);
380 local_lm_blob = data_blob(local_lm_response, 24);
382 /* We can't do an NT hash here, as the password needs to be
383 case insensitive */
384 local_nt_blob = data_blob(NULL, 0);
386 } else {
387 local_lm_blob = data_blob(NULL, 0);
388 local_nt_blob = data_blob(NULL, 0);
391 ret = make_user_info_map(user_info, smb_name,
392 client_domain,
393 get_remote_machine_name(),
394 local_lm_blob.data ? &local_lm_blob : NULL,
395 local_nt_blob.data ? &local_nt_blob : NULL,
396 NULL, NULL,
397 plaintext_password.data ? &plaintext_password : NULL,
398 False);
400 data_blob_free(&local_lm_blob);
401 return NT_STATUS_IS_OK(ret) ? True : False;
404 /****************************************************************************
405 Create an auth_usersupplied_data structure
406 ****************************************************************************/
408 NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info,
409 const char *smb_name,
410 const char *client_domain,
411 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
413 return make_user_info_map(user_info, smb_name,
414 client_domain,
415 get_remote_machine_name(),
416 lm_resp.data ? &lm_resp : NULL,
417 nt_resp.data ? &nt_resp : NULL,
418 NULL, NULL, NULL,
419 True);
422 /****************************************************************************
423 Create a guest user_info blob, for anonymous authenticaion.
424 ****************************************************************************/
426 BOOL make_user_info_guest(auth_usersupplied_info **user_info)
428 NTSTATUS nt_status;
430 nt_status = make_user_info(user_info,
431 "","",
432 "","",
433 "",
434 NULL, NULL,
435 NULL, NULL,
436 NULL,
437 True);
439 return NT_STATUS_IS_OK(nt_status) ? True : False;
442 /****************************************************************************
443 prints a NT_USER_TOKEN to debug output.
444 ****************************************************************************/
446 void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token)
448 fstring sid_str;
449 size_t i;
451 if (!token) {
452 DEBUGC(dbg_class, dbg_lev, ("NT user token: (NULL)\n"));
453 return;
456 DEBUGC(dbg_class, dbg_lev, ("NT user token of user %s\n",
457 sid_to_string(sid_str, &token->user_sids[0]) ));
458 DEBUGADDC(dbg_class, dbg_lev, ("contains %lu SIDs\n", (unsigned long)token->num_sids));
459 for (i = 0; i < token->num_sids; i++)
460 DEBUGADDC(dbg_class, dbg_lev, ("SID[%3lu]: %s\n", (unsigned long)i,
461 sid_to_string(sid_str, &token->user_sids[i])));
463 dump_se_priv( dbg_class, dbg_lev, &token->privileges );
466 /****************************************************************************
467 prints a UNIX 'token' to debug output.
468 ****************************************************************************/
470 void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid, int n_groups, gid_t *groups)
472 int i;
473 DEBUGC(dbg_class, dbg_lev, ("UNIX token of user %ld\n", (long int)uid));
475 DEBUGADDC(dbg_class, dbg_lev, ("Primary group is %ld and contains %i supplementary groups\n", (long int)gid, n_groups));
476 for (i = 0; i < n_groups; i++)
477 DEBUGADDC(dbg_class, dbg_lev, ("Group[%3i]: %ld\n", i,
478 (long int)groups[i]));
481 /****************************************************************************
482 Create the SID list for this user.
483 ****************************************************************************/
485 static NTSTATUS create_nt_user_token(const DOM_SID *user_sid, const DOM_SID *group_sid,
486 int n_groupSIDs, DOM_SID *groupSIDs,
487 BOOL is_guest, NT_USER_TOKEN **token)
489 NTSTATUS nt_status = NT_STATUS_OK;
490 NT_USER_TOKEN *ptoken;
491 int i;
492 int sid_ndx;
494 if ((ptoken = SMB_MALLOC_P(NT_USER_TOKEN)) == NULL) {
495 DEBUG(0, ("create_nt_token: Out of memory allocating token\n"));
496 nt_status = NT_STATUS_NO_MEMORY;
497 return nt_status;
500 ZERO_STRUCTP(ptoken);
502 ptoken->num_sids = n_groupSIDs + 5;
504 if ((ptoken->user_sids = SMB_MALLOC_ARRAY( DOM_SID, ptoken->num_sids )) == NULL) {
505 DEBUG(0, ("create_nt_token: Out of memory allocating SIDs\n"));
506 nt_status = NT_STATUS_NO_MEMORY;
507 return nt_status;
510 memset((char*)ptoken->user_sids,0,sizeof(DOM_SID) * ptoken->num_sids);
513 * Note - user SID *MUST* be first in token !
514 * se_access_check depends on this.
516 * Primary group SID is second in token. Convention.
519 sid_copy(&ptoken->user_sids[PRIMARY_USER_SID_INDEX], user_sid);
520 if (group_sid)
521 sid_copy(&ptoken->user_sids[PRIMARY_GROUP_SID_INDEX], group_sid);
524 * Finally add the "standard" SIDs.
525 * The only difference between guest and "anonymous" (which we
526 * don't really support) is the addition of Authenticated_Users.
529 sid_copy(&ptoken->user_sids[2], &global_sid_World);
530 sid_copy(&ptoken->user_sids[3], &global_sid_Network);
532 if (is_guest)
533 sid_copy(&ptoken->user_sids[4], &global_sid_Builtin_Guests);
534 else
535 sid_copy(&ptoken->user_sids[4], &global_sid_Authenticated_Users);
537 sid_ndx = 5; /* next available spot */
539 for (i = 0; i < n_groupSIDs; i++) {
540 size_t check_sid_idx;
541 for (check_sid_idx = 1; check_sid_idx < ptoken->num_sids; check_sid_idx++) {
542 if (sid_equal(&ptoken->user_sids[check_sid_idx],
543 &groupSIDs[i])) {
544 break;
548 if (check_sid_idx >= ptoken->num_sids) /* Not found already */ {
549 sid_copy(&ptoken->user_sids[sid_ndx++], &groupSIDs[i]);
550 } else {
551 ptoken->num_sids--;
555 /* add privileges assigned to this user */
557 get_privileges_for_sids( &ptoken->privileges, ptoken->user_sids, ptoken->num_sids );
559 debug_nt_user_token(DBGC_AUTH, 10, ptoken);
561 if ((lp_log_nt_token_command() != NULL) &&
562 (strlen(lp_log_nt_token_command()) > 0)) {
563 TALLOC_CTX *mem_ctx;
564 char *command;
565 fstring sidstr;
566 char *user_sidstr, *group_sidstr;
568 mem_ctx = talloc_init("setnttoken");
569 if (mem_ctx == NULL)
570 return NT_STATUS_NO_MEMORY;
572 sid_to_string(sidstr, &ptoken->user_sids[0]);
573 user_sidstr = talloc_strdup(mem_ctx, sidstr);
575 group_sidstr = talloc_strdup(mem_ctx, "");
576 for (i=1; i<ptoken->num_sids; i++) {
577 sid_to_string(sidstr, &ptoken->user_sids[i]);
578 group_sidstr = talloc_asprintf(mem_ctx, "%s %s",
579 group_sidstr, sidstr);
582 command = SMB_STRDUP(lp_log_nt_token_command());
583 command = realloc_string_sub(command, "%s", user_sidstr);
584 command = realloc_string_sub(command, "%t", group_sidstr);
585 DEBUG(8, ("running command: [%s]\n", command));
586 if (smbrun(command, NULL) != 0) {
587 DEBUG(0, ("Could not log NT token\n"));
588 nt_status = NT_STATUS_ACCESS_DENIED;
590 talloc_destroy(mem_ctx);
591 SAFE_FREE(command);
594 *token = ptoken;
596 return nt_status;
599 /****************************************************************************
600 Create the SID list for this user.
601 ****************************************************************************/
603 NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, BOOL is_guest)
605 DOM_SID user_sid;
606 DOM_SID group_sid;
607 DOM_SID *group_sids;
608 NT_USER_TOKEN *token;
609 int i;
611 if (!NT_STATUS_IS_OK(uid_to_sid(&user_sid, uid))) {
612 return NULL;
614 if (!NT_STATUS_IS_OK(gid_to_sid(&group_sid, gid))) {
615 return NULL;
618 group_sids = SMB_MALLOC_ARRAY(DOM_SID, ngroups);
619 if (!group_sids) {
620 DEBUG(0, ("create_nt_token: malloc() failed for DOM_SID list!\n"));
621 return NULL;
624 for (i = 0; i < ngroups; i++) {
625 if (!NT_STATUS_IS_OK(gid_to_sid(&(group_sids)[i], (groups)[i]))) {
626 DEBUG(1, ("create_nt_token: failed to convert gid %ld to a sid!\n", (long int)groups[i]));
627 SAFE_FREE(group_sids);
628 return NULL;
632 if (!NT_STATUS_IS_OK(create_nt_user_token(&user_sid, &group_sid,
633 ngroups, group_sids, is_guest, &token))) {
634 SAFE_FREE(group_sids);
635 return NULL;
638 SAFE_FREE(group_sids);
640 return token;
643 /******************************************************************************
644 * this function returns the groups (SIDs) of the local SAM the user is in.
645 * If this samba server is a DC of the domain the user belongs to, it returns
646 * both domain groups and local / builtin groups. If the user is in a trusted
647 * domain, or samba is a member server of a domain, then this function returns
648 * local and builtin groups the user is a member of.
650 * currently this is a hack, as there is no sam implementation that is capable
651 * of groups.
653 * NOTE!! This function will fail if you pass in a winbind user without
654 * the domain --jerry
655 ******************************************************************************/
657 static NTSTATUS get_user_groups(const char *username, uid_t uid, gid_t gid,
658 int *n_groups, DOM_SID **groups, gid_t **unix_groups)
660 int n_unix_groups;
661 int i;
663 *n_groups = 0;
664 *groups = NULL;
666 if (strchr(username, *lp_winbind_separator()) == NULL) {
667 NTSTATUS result;
669 become_root();
670 result = pdb_enum_group_memberships(username, gid, groups,
671 unix_groups, n_groups);
672 unbecome_root();
673 return result;
676 /* We have the separator, this must be winbind */
678 n_unix_groups = winbind_getgroups( username, unix_groups );
680 DEBUG(10,("get_user_groups: winbind_getgroups(%s): result = %s\n",
681 username, n_unix_groups == -1 ? "FAIL" : "SUCCESS"));
683 if ( n_unix_groups == -1 )
684 return NT_STATUS_NO_SUCH_USER; /* what should this return
685 * value be? */
687 debug_unix_user_token(DBGC_CLASS, 5, uid, gid, n_unix_groups, *unix_groups);
689 /* now setup the space for storing the SIDS */
691 if (n_unix_groups > 0) {
693 *groups = SMB_MALLOC_ARRAY(DOM_SID, n_unix_groups);
695 if (!*groups) {
696 DEBUG(0, ("get_user_group: malloc() failed for DOM_SID list!\n"));
697 SAFE_FREE(*unix_groups);
698 return NT_STATUS_NO_MEMORY;
702 *n_groups = n_unix_groups;
704 for (i = 0; i < *n_groups; i++) {
705 if (!NT_STATUS_IS_OK(gid_to_sid(&(*groups)[i], (*unix_groups)[i]))) {
706 DEBUG(1, ("get_user_groups: failed to convert gid %ld to a sid!\n",
707 (long int)(*unix_groups)[i+1]));
708 SAFE_FREE(*groups);
709 SAFE_FREE(*unix_groups);
710 return NT_STATUS_NO_SUCH_USER;
714 return NT_STATUS_OK;
717 /***************************************************************************
718 Make a user_info struct
719 ***************************************************************************/
721 static NTSTATUS make_server_info(auth_serversupplied_info **server_info)
723 *server_info = SMB_MALLOC_P(auth_serversupplied_info);
724 if (!*server_info) {
725 DEBUG(0,("make_server_info: malloc failed!\n"));
726 return NT_STATUS_NO_MEMORY;
728 ZERO_STRUCTP(*server_info);
730 /* Initialise the uid and gid values to something non-zero
731 which may save us from giving away root access if there
732 is a bug in allocating these fields. */
734 (*server_info)->uid = -1;
735 (*server_info)->gid = -1;
737 return NT_STATUS_OK;
740 /***************************************************************************
741 Fill a server_info struct from a SAM_ACCOUNT with their groups
742 ***************************************************************************/
744 static NTSTATUS add_user_groups(auth_serversupplied_info **server_info,
745 const char * unix_username,
746 SAM_ACCOUNT *sampass,
747 uid_t uid, gid_t gid)
749 NTSTATUS nt_status;
750 const DOM_SID *user_sid = pdb_get_user_sid(sampass);
751 const DOM_SID *group_sid = pdb_get_group_sid(sampass);
752 int n_groupSIDs = 0;
753 DOM_SID *groupSIDs = NULL;
754 gid_t *unix_groups = NULL;
755 NT_USER_TOKEN *token;
756 BOOL is_guest;
757 uint32 rid;
759 nt_status = get_user_groups(unix_username, uid, gid,
760 &n_groupSIDs, &groupSIDs, &unix_groups);
762 if (!NT_STATUS_IS_OK(nt_status)) {
763 DEBUG(4,("get_user_groups_from_local_sam failed\n"));
764 free_server_info(server_info);
765 return nt_status;
768 is_guest = (sid_peek_rid(user_sid, &rid) && rid == DOMAIN_USER_RID_GUEST);
770 if (!NT_STATUS_IS_OK(nt_status = create_nt_user_token(user_sid, group_sid,
771 n_groupSIDs, groupSIDs, is_guest,
772 &token)))
774 DEBUG(4,("create_nt_user_token failed\n"));
775 SAFE_FREE(groupSIDs);
776 SAFE_FREE(unix_groups);
777 free_server_info(server_info);
778 return nt_status;
781 SAFE_FREE(groupSIDs);
783 (*server_info)->n_groups = n_groupSIDs;
784 (*server_info)->groups = unix_groups;
785 (*server_info)->ptok = token;
787 return nt_status;
790 /***************************************************************************
791 Make (and fill) a user_info struct from a SAM_ACCOUNT
792 ***************************************************************************/
794 NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
795 SAM_ACCOUNT *sampass)
797 NTSTATUS nt_status;
798 struct passwd *pwd;
800 if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info)))
801 return nt_status;
803 (*server_info)->sam_account = sampass;
805 if ( !(pwd = getpwnam_alloc(pdb_get_username(sampass))) ) {
806 DEBUG(1, ("User %s in passdb, but getpwnam() fails!\n",
807 pdb_get_username(sampass)));
808 free_server_info(server_info);
809 return NT_STATUS_NO_SUCH_USER;
811 (*server_info)->unix_name = smb_xstrdup(pwd->pw_name);
812 (*server_info)->gid = pwd->pw_gid;
813 (*server_info)->uid = pwd->pw_uid;
815 passwd_free(&pwd);
817 if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, pdb_get_username(sampass),
818 sampass,
819 (*server_info)->uid,
820 (*server_info)->gid)))
822 free_server_info(server_info);
823 return nt_status;
826 (*server_info)->sam_fill_level = SAM_FILL_ALL;
827 DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n",
828 pdb_get_username(sampass),
829 (*server_info)->unix_name));
831 return nt_status;
834 /***************************************************************************
835 Make (and fill) a user_info struct from a 'struct passwd' by conversion
836 to a SAM_ACCOUNT
837 ***************************************************************************/
839 NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info,
840 char *unix_username,
841 struct passwd *pwd)
843 NTSTATUS nt_status;
844 SAM_ACCOUNT *sampass = NULL;
845 if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(&sampass, pwd))) {
846 return nt_status;
848 if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) {
849 return nt_status;
852 (*server_info)->sam_account = sampass;
854 if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, unix_username,
855 sampass, pwd->pw_uid, pwd->pw_gid)))
857 return nt_status;
860 (*server_info)->unix_name = smb_xstrdup(unix_username);
862 (*server_info)->sam_fill_level = SAM_FILL_ALL;
863 (*server_info)->uid = pwd->pw_uid;
864 (*server_info)->gid = pwd->pw_gid;
865 return nt_status;
868 /***************************************************************************
869 Make (and fill) a user_info struct for a guest login.
870 ***************************************************************************/
872 static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_info)
874 NTSTATUS nt_status;
875 SAM_ACCOUNT *sampass = NULL;
876 DOM_SID guest_sid;
878 if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sampass))) {
879 return nt_status;
882 sid_copy(&guest_sid, get_global_sam_sid());
883 sid_append_rid(&guest_sid, DOMAIN_USER_RID_GUEST);
885 become_root();
886 if (!pdb_getsampwsid(sampass, &guest_sid)) {
887 unbecome_root();
888 return NT_STATUS_NO_SUCH_USER;
890 unbecome_root();
892 nt_status = make_server_info_sam(server_info, sampass);
894 if (NT_STATUS_IS_OK(nt_status)) {
895 static const char zeros[16];
896 (*server_info)->guest = True;
898 /* annoying, but the Guest really does have a session key,
899 and it is all zeros! */
900 (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
901 (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
904 return nt_status;
907 static auth_serversupplied_info *copy_serverinfo(auth_serversupplied_info *src)
909 auth_serversupplied_info *dst;
911 if (!NT_STATUS_IS_OK(make_server_info(&dst)))
912 return NULL;
914 dst->guest = src->guest;
915 dst->uid = src->uid;
916 dst->gid = src->gid;
917 dst->n_groups = src->n_groups;
918 if (src->n_groups != 0)
919 dst->groups = memdup(src->groups, sizeof(gid_t)*dst->n_groups);
920 else
921 dst->groups = NULL;
922 dst->ptok = dup_nt_token(src->ptok);
923 dst->user_session_key = data_blob(src->user_session_key.data,
924 src->user_session_key.length);
925 dst->lm_session_key = data_blob(src->lm_session_key.data,
926 src->lm_session_key.length);
927 pdb_copy_sam_account(src->sam_account, &dst->sam_account);
928 dst->pam_handle = NULL;
929 dst->unix_name = smb_xstrdup(src->unix_name);
931 return dst;
934 static auth_serversupplied_info *guest_info = NULL;
936 BOOL init_guest_info(void)
938 if (guest_info != NULL)
939 return True;
941 return NT_STATUS_IS_OK(make_new_server_info_guest(&guest_info));
944 NTSTATUS make_server_info_guest(auth_serversupplied_info **server_info)
946 *server_info = copy_serverinfo(guest_info);
947 return (*server_info != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
950 /***************************************************************************
951 Purely internal function for make_server_info_info3
952 Fill the sam account from getpwnam
953 ***************************************************************************/
954 static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx,
955 const char *domain,
956 const char *username,
957 char **found_username,
958 uid_t *uid, gid_t *gid,
959 SAM_ACCOUNT **sam_account)
961 NTSTATUS nt_status;
962 fstring dom_user, lower_username;
963 fstring real_username;
964 struct passwd *passwd;
966 fstrcpy( lower_username, username );
967 strlower_m( lower_username );
969 fstr_sprintf(dom_user, "%s%c%s", domain, *lp_winbind_separator(),
970 lower_username);
972 /* get the passwd struct but don't create the user if he/she
973 does not exist. We were explicitly called from a following
974 a winbindd authentication request so we should assume that
975 nss_winbindd is working */
977 map_username( dom_user );
979 if ( !(passwd = smb_getpwnam( dom_user, real_username, True )) )
980 return NT_STATUS_NO_SUCH_USER;
982 *uid = passwd->pw_uid;
983 *gid = passwd->pw_gid;
985 /* This is pointless -- there is no suport for differing
986 unix and windows names. Make sure to always store the
987 one we actually looked up and succeeded. Have I mentioned
988 why I hate the 'winbind use default domain' parameter?
989 --jerry */
991 *found_username = talloc_strdup( mem_ctx, real_username );
993 DEBUG(5,("fill_sam_account: located username was [%s]\n",
994 *found_username));
996 nt_status = pdb_init_sam_pw(sam_account, passwd);
997 passwd_free(&passwd);
998 return nt_status;
1001 /****************************************************************************
1002 Wrapper to allow the getpwnam() call to strip the domain name and
1003 try again in case a local UNIX user is already there. Also run through
1004 the username if we fallback to the username only.
1005 ****************************************************************************/
1007 struct passwd *smb_getpwnam( char *domuser, fstring save_username, BOOL create )
1009 struct passwd *pw = NULL;
1010 char *p;
1011 fstring username;
1013 /* we only save a copy of the username it has been mangled
1014 by winbindd use default domain */
1016 save_username[0] = '\0';
1018 /* don't call map_username() here since it has to be done higher
1019 up the stack so we don't call it mutliple times */
1021 fstrcpy( username, domuser );
1023 p = strchr_m( username, *lp_winbind_separator() );
1025 /* code for a DOMAIN\user string */
1027 if ( p ) {
1028 fstring strip_username;
1030 pw = Get_Pwnam_alloc( domuser );
1031 if ( pw ) {
1032 /* make sure we get the case of the username correct */
1033 /* work around 'winbind use default domain = yes' */
1035 if ( !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
1036 char *domain;
1038 /* split the domain and username into 2 strings */
1039 *p = '\0';
1040 domain = username;
1042 fstr_sprintf(save_username, "%s%c%s", domain, *lp_winbind_separator(), pw->pw_name);
1044 else
1045 fstrcpy( save_username, pw->pw_name );
1047 /* whew -- done! */
1048 return pw;
1051 /* setup for lookup of just the username */
1052 /* remember that p and username are overlapping memory */
1054 p++;
1055 fstrcpy( strip_username, p );
1056 fstrcpy( username, strip_username );
1059 /* just lookup a plain username */
1061 pw = Get_Pwnam_alloc(username);
1063 /* Create local user if requested. */
1065 if ( !pw && create ) {
1066 /* Don't add a machine account. */
1067 if (username[strlen(username)-1] == '$')
1068 return NULL;
1070 smb_create_user(NULL, username, NULL);
1071 pw = Get_Pwnam_alloc(username);
1074 /* one last check for a valid passwd struct */
1076 if ( pw )
1077 fstrcpy( save_username, pw->pw_name );
1079 return pw;
1082 /***************************************************************************
1083 Make a server_info struct from the info3 returned by a domain logon
1084 ***************************************************************************/
1086 NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
1087 const char *internal_username,
1088 const char *sent_nt_username,
1089 const char *domain,
1090 auth_serversupplied_info **server_info,
1091 NET_USER_INFO_3 *info3)
1093 static const char zeros[16];
1095 NTSTATUS nt_status = NT_STATUS_OK;
1096 char *found_username;
1097 const char *nt_domain;
1098 const char *nt_username;
1100 SAM_ACCOUNT *sam_account = NULL;
1101 DOM_SID user_sid;
1102 DOM_SID group_sid;
1104 uid_t uid;
1105 gid_t gid;
1107 int n_lgroupSIDs;
1108 DOM_SID *lgroupSIDs = NULL;
1110 gid_t *unix_groups = NULL;
1111 NT_USER_TOKEN *token;
1113 DOM_SID *all_group_SIDs;
1114 size_t i;
1117 Here is where we should check the list of
1118 trusted domains, and verify that the SID
1119 matches.
1122 sid_copy(&user_sid, &info3->dom_sid.sid);
1123 if (!sid_append_rid(&user_sid, info3->user_rid)) {
1124 return NT_STATUS_INVALID_PARAMETER;
1127 sid_copy(&group_sid, &info3->dom_sid.sid);
1128 if (!sid_append_rid(&group_sid, info3->group_rid)) {
1129 return NT_STATUS_INVALID_PARAMETER;
1132 if (!(nt_username = unistr2_tdup(mem_ctx, &(info3->uni_user_name)))) {
1133 /* If the server didn't give us one, just use the one we sent them */
1134 nt_username = sent_nt_username;
1137 if (!(nt_domain = unistr2_tdup(mem_ctx, &(info3->uni_logon_dom)))) {
1138 /* If the server didn't give us one, just use the one we sent them */
1139 nt_domain = domain;
1142 /* try to fill the SAM account.. If getpwnam() fails, then try the
1143 add user script (2.2.x behavior).
1145 We use the _unmapped_ username here in an attempt to provide
1146 consistent username mapping behavior between kerberos and NTLM[SSP]
1147 authentication in domain mode security. I.E. Username mapping should
1148 be applied to the fully qualified username (e.g. DOMAIN\user) and
1149 no just the login name. Yes this mean swe called map_username()
1150 unnecessarily in make_user_info_map() but that is how the current
1151 code is designed. Making the change here is the least disruptive
1152 place. -- jerry */
1154 nt_status = fill_sam_account(mem_ctx, nt_domain, sent_nt_username,
1155 &found_username, &uid, &gid, &sam_account);
1157 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) {
1158 DEBUG(3,("User %s does not exist, trying to add it\n", internal_username));
1159 smb_create_user( nt_domain, sent_nt_username, NULL);
1160 nt_status = fill_sam_account( mem_ctx, nt_domain, sent_nt_username,
1161 &found_username, &uid, &gid, &sam_account );
1164 /* if we still don't have a valid unix account check for
1165 'map to gues = bad uid' */
1167 if (!NT_STATUS_IS_OK(nt_status)) {
1168 if ( lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID ) {
1169 make_server_info_guest(server_info);
1170 return NT_STATUS_OK;
1173 DEBUG(0, ("make_server_info_info3: pdb_init_sam failed!\n"));
1174 return nt_status;
1177 if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) {
1178 pdb_free_sam(&sam_account);
1179 return NT_STATUS_NO_MEMORY;
1182 if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) {
1183 pdb_free_sam(&sam_account);
1184 return NT_STATUS_NO_MEMORY;
1187 if (!pdb_set_domain(sam_account, nt_domain, PDB_CHANGED)) {
1188 pdb_free_sam(&sam_account);
1189 return NT_STATUS_NO_MEMORY;
1192 if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) {
1193 pdb_free_sam(&sam_account);
1194 return NT_STATUS_UNSUCCESSFUL;
1197 if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) {
1198 pdb_free_sam(&sam_account);
1199 return NT_STATUS_UNSUCCESSFUL;
1202 if (!pdb_set_fullname(sam_account, unistr2_static(&(info3->uni_full_name)),
1203 PDB_CHANGED)) {
1204 pdb_free_sam(&sam_account);
1205 return NT_STATUS_NO_MEMORY;
1208 if (!pdb_set_logon_script(sam_account, unistr2_static(&(info3->uni_logon_script)), PDB_CHANGED)) {
1209 pdb_free_sam(&sam_account);
1210 return NT_STATUS_NO_MEMORY;
1213 if (!pdb_set_profile_path(sam_account, unistr2_static(&(info3->uni_profile_path)), PDB_CHANGED)) {
1214 pdb_free_sam(&sam_account);
1215 return NT_STATUS_NO_MEMORY;
1218 if (!pdb_set_homedir(sam_account, unistr2_static(&(info3->uni_home_dir)), PDB_CHANGED)) {
1219 pdb_free_sam(&sam_account);
1220 return NT_STATUS_NO_MEMORY;
1223 if (!pdb_set_dir_drive(sam_account, unistr2_static(&(info3->uni_dir_drive)), PDB_CHANGED)) {
1224 pdb_free_sam(&sam_account);
1225 return NT_STATUS_NO_MEMORY;
1228 if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) {
1229 DEBUG(4, ("make_server_info failed!\n"));
1230 pdb_free_sam(&sam_account);
1231 return nt_status;
1234 /* save this here to _net_sam_logon() doesn't fail (it assumes a
1235 valid SAM_ACCOUNT) */
1237 (*server_info)->sam_account = sam_account;
1239 (*server_info)->unix_name = smb_xstrdup(found_username);
1241 /* Fill in the unix info we found on the way */
1243 (*server_info)->sam_fill_level = SAM_FILL_ALL;
1244 (*server_info)->uid = uid;
1245 (*server_info)->gid = gid;
1247 /* Store the user group information in the server_info
1248 returned to the caller. */
1250 nt_status = get_user_groups((*server_info)->unix_name,
1251 uid, gid, &n_lgroupSIDs, &lgroupSIDs, &unix_groups);
1253 if ( !NT_STATUS_IS_OK(nt_status) ) {
1254 DEBUG(4,("get_user_groups failed\n"));
1255 return nt_status;
1258 (*server_info)->groups = unix_groups;
1259 (*server_info)->n_groups = n_lgroupSIDs;
1261 /* Create a 'combined' list of all SIDs we might want in the SD */
1263 all_group_SIDs = SMB_MALLOC_ARRAY(DOM_SID,info3->num_groups2 + info3->num_other_sids + n_lgroupSIDs);
1265 if (!all_group_SIDs) {
1266 DEBUG(0, ("malloc() failed for DOM_SID list!\n"));
1267 SAFE_FREE(lgroupSIDs);
1268 free_server_info(server_info);
1269 return NT_STATUS_NO_MEMORY;
1272 /* and create (by appending rids) the 'domain' sids */
1274 for (i = 0; i < info3->num_groups2; i++) {
1276 sid_copy(&all_group_SIDs[i], &(info3->dom_sid.sid));
1278 if (!sid_append_rid(&all_group_SIDs[i], info3->gids[i].g_rid)) {
1280 nt_status = NT_STATUS_INVALID_PARAMETER;
1282 DEBUG(3,("could not append additional group rid 0x%x\n",
1283 info3->gids[i].g_rid));
1285 SAFE_FREE(lgroupSIDs);
1286 SAFE_FREE(all_group_SIDs);
1287 free_server_info(server_info);
1289 return nt_status;
1294 /* Copy 'other' sids. We need to do sid filtering here to
1295 prevent possible elevation of privileges. See:
1297 http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
1300 for (i = 0; i < info3->num_other_sids; i++) {
1301 sid_copy(&all_group_SIDs[info3->num_groups2 + i],
1302 &info3->other_sids[i].sid);
1306 /* add local alias sids */
1308 for (i = 0; i < n_lgroupSIDs; i++) {
1309 sid_copy(&all_group_SIDs[info3->num_groups2 +
1310 info3->num_other_sids + i],
1311 &lgroupSIDs[i]);
1314 /* Where are the 'global' sids... */
1316 /* can the user be guest? if yes, where is it stored? */
1318 nt_status = create_nt_user_token(&user_sid, &group_sid,
1319 info3->num_groups2 + info3->num_other_sids + n_lgroupSIDs,
1320 all_group_SIDs, False, &token);
1322 if ( !NT_STATUS_IS_OK(nt_status) ) {
1323 DEBUG(4,("create_nt_user_token failed\n"));
1324 SAFE_FREE(lgroupSIDs);
1325 SAFE_FREE(all_group_SIDs);
1326 free_server_info(server_info);
1327 return nt_status;
1330 (*server_info)->login_server = unistr2_tdup(mem_ctx,
1331 &(info3->uni_logon_srv));
1333 (*server_info)->ptok = token;
1335 SAFE_FREE(lgroupSIDs);
1336 SAFE_FREE(all_group_SIDs);
1338 /* ensure we are never given NULL session keys */
1340 if (memcmp(info3->user_sess_key, zeros, sizeof(zeros)) == 0) {
1341 (*server_info)->user_session_key = data_blob(NULL, 0);
1342 } else {
1343 (*server_info)->user_session_key = data_blob(info3->user_sess_key, sizeof(info3->user_sess_key));
1346 if (memcmp(info3->lm_sess_key, zeros, 8) == 0) {
1347 (*server_info)->lm_session_key = data_blob(NULL, 0);
1348 } else {
1349 (*server_info)->lm_session_key = data_blob(info3->lm_sess_key, sizeof(info3->lm_sess_key));
1352 return NT_STATUS_OK;
1355 /***************************************************************************
1356 Free a user_info struct
1357 ***************************************************************************/
1359 void free_user_info(auth_usersupplied_info **user_info)
1361 DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
1362 if (*user_info != NULL) {
1363 if ((*user_info)->smb_name.str) {
1364 DEBUG(10,("structure was created for %s\n", (*user_info)->smb_name.str));
1366 SAFE_FREE((*user_info)->smb_name.str);
1367 SAFE_FREE((*user_info)->internal_username.str);
1368 SAFE_FREE((*user_info)->client_domain.str);
1369 SAFE_FREE((*user_info)->domain.str);
1370 SAFE_FREE((*user_info)->wksta_name.str);
1371 data_blob_free(&(*user_info)->lm_resp);
1372 data_blob_free(&(*user_info)->nt_resp);
1373 data_blob_clear_free(&(*user_info)->lm_interactive_pwd);
1374 data_blob_clear_free(&(*user_info)->nt_interactive_pwd);
1375 data_blob_clear_free(&(*user_info)->plaintext_password);
1376 ZERO_STRUCT(**user_info);
1378 SAFE_FREE(*user_info);
1381 /***************************************************************************
1382 Clear out a server_info struct that has been allocated
1383 ***************************************************************************/
1385 void free_server_info(auth_serversupplied_info **server_info)
1387 DEBUG(5,("attempting to free (and zero) a server_info structure\n"));
1388 if (*server_info != NULL) {
1389 pdb_free_sam(&(*server_info)->sam_account);
1391 /* call pam_end here, unless we know we are keeping it */
1392 delete_nt_token( &(*server_info)->ptok );
1393 SAFE_FREE((*server_info)->groups);
1394 SAFE_FREE((*server_info)->unix_name);
1395 data_blob_free(&(*server_info)->lm_session_key);
1396 data_blob_free(&(*server_info)->user_session_key);
1397 ZERO_STRUCT(**server_info);
1399 SAFE_FREE(*server_info);
1402 /***************************************************************************
1403 Make an auth_methods struct
1404 ***************************************************************************/
1406 BOOL make_auth_methods(struct auth_context *auth_context, auth_methods **auth_method)
1408 if (!auth_context) {
1409 smb_panic("no auth_context supplied to make_auth_methods()!\n");
1412 if (!auth_method) {
1413 smb_panic("make_auth_methods: pointer to auth_method pointer is NULL!\n");
1416 *auth_method = TALLOC_P(auth_context->mem_ctx, auth_methods);
1417 if (!*auth_method) {
1418 DEBUG(0,("make_auth_method: malloc failed!\n"));
1419 return False;
1421 ZERO_STRUCTP(*auth_method);
1423 return True;
1426 /****************************************************************************
1427 Delete a SID token.
1428 ****************************************************************************/
1430 void delete_nt_token(NT_USER_TOKEN **pptoken)
1432 if (*pptoken) {
1433 NT_USER_TOKEN *ptoken = *pptoken;
1435 SAFE_FREE( ptoken->user_sids );
1436 ZERO_STRUCTP(ptoken);
1438 SAFE_FREE(*pptoken);
1441 /****************************************************************************
1442 Duplicate a SID token.
1443 ****************************************************************************/
1445 NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken)
1447 NT_USER_TOKEN *token;
1449 if (!ptoken)
1450 return NULL;
1452 if ((token = SMB_MALLOC_P(NT_USER_TOKEN)) == NULL)
1453 return NULL;
1455 ZERO_STRUCTP(token);
1457 token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids );
1459 if ( !token ) {
1460 SAFE_FREE(token);
1461 return NULL;
1464 token->num_sids = ptoken->num_sids;
1466 /* copy the privileges; don't consider failure to be critical here */
1468 if ( !se_priv_copy( &token->privileges, &ptoken->privileges ) ) {
1469 DEBUG(0,("dup_nt_token: Failure to copy SE_PRIV!. Continuing with 0 privileges assigned.\n"));
1472 return token;
1475 /****************************************************************************
1476 Check for a SID in an NT_USER_TOKEN
1477 ****************************************************************************/
1479 BOOL nt_token_check_sid ( DOM_SID *sid, NT_USER_TOKEN *token )
1481 int i;
1483 if ( !sid || !token )
1484 return False;
1486 for ( i=0; i<token->num_sids; i++ ) {
1487 if ( sid_equal( sid, &token->user_sids[i] ) )
1488 return True;
1491 return False;
1494 BOOL nt_token_check_domain_rid( NT_USER_TOKEN *token, uint32 rid )
1496 DOM_SID domain_sid;
1498 /* if we are a domain member, the get the domain SID, else for
1499 a DC or standalone server, use our own SID */
1501 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1502 if ( !secrets_fetch_domain_sid( lp_workgroup(), &domain_sid ) ) {
1503 DEBUG(1,("nt_token_check_domain_rid: Cannot lookup SID for domain [%s]\n",
1504 lp_workgroup()));
1505 return False;
1508 else
1509 sid_copy( &domain_sid, get_global_sam_sid() );
1511 sid_append_rid( &domain_sid, rid );
1513 return nt_token_check_sid( &domain_sid, token );\
1517 * Verify whether or not given domain is trusted.
1519 * @param domain_name name of the domain to be verified
1520 * @return true if domain is one of the trusted once or
1521 * false if otherwise
1524 BOOL is_trusted_domain(const char* dom_name)
1526 DOM_SID trustdom_sid;
1527 char *pass = NULL;
1528 time_t lct;
1529 BOOL ret;
1531 /* no trusted domains for a standalone server */
1533 if ( lp_server_role() == ROLE_STANDALONE )
1534 return False;
1536 /* if we are a DC, then check for a direct trust relationships */
1538 if ( IS_DC ) {
1539 become_root();
1540 DEBUG (5,("is_trusted_domain: Checking for domain trust with [%s]\n",
1541 dom_name ));
1542 ret = secrets_fetch_trusted_domain_password(dom_name, &pass, &trustdom_sid, &lct);
1543 unbecome_root();
1544 SAFE_FREE(pass);
1545 if (ret)
1546 return True;
1548 else {
1549 NSS_STATUS result;
1551 /* If winbind is around, ask it */
1553 result = wb_is_trusted_domain(dom_name);
1555 if (result == NSS_STATUS_SUCCESS) {
1556 return True;
1559 if (result == NSS_STATUS_NOTFOUND) {
1560 /* winbind could not find the domain */
1561 return False;
1564 /* The only other possible result is that winbind is not up
1565 and running. We need to update the trustdom_cache
1566 ourselves */
1568 update_trustdom_cache();
1571 /* now the trustdom cache should be available a DC could still
1572 * have a transitive trust so fall back to the cache of trusted
1573 * domains (like a domain member would use */
1575 if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) {
1576 return True;
1579 return False;