source: vendor/3.6.24/source3/auth/auth_util.c

Last change on this file was 860, checked in by Silvan Scherrer, 11 years ago

Samba 3.6: updated vendor to latest version

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