source: branches/samba-3.2.x/source/smbd/password.c

Last change on this file was 261, checked in by Herwig Bauernfeind, 16 years ago

password.c: $ vs : in 3.2 branch

File size: 23.0 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 Password and authentication handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "includes.h"
22
23/* users from session setup */
24static char *session_userlist = NULL;
25/* workgroup from session setup. */
26static char *session_workgroup = NULL;
27
28/* this holds info on user ids that are already validated for this VC */
29static user_struct *validated_users;
30static uint16_t next_vuid = VUID_OFFSET;
31static int num_validated_vuids;
32
33enum server_allocated_state { SERVER_ALLOCATED_REQUIRED_YES,
34 SERVER_ALLOCATED_REQUIRED_NO,
35 SERVER_ALLOCATED_REQUIRED_ANY};
36
37static user_struct *get_valid_user_struct_internal(uint16 vuid,
38 enum server_allocated_state server_allocated)
39{
40 user_struct *usp;
41 int count=0;
42
43 if (vuid == UID_FIELD_INVALID)
44 return NULL;
45
46 for (usp=validated_users;usp;usp=usp->next,count++) {
47 if (vuid == usp->vuid) {
48 switch (server_allocated) {
49 case SERVER_ALLOCATED_REQUIRED_YES:
50 if (usp->server_info == NULL) {
51 continue;
52 }
53 break;
54 case SERVER_ALLOCATED_REQUIRED_NO:
55 if (usp->server_info != NULL) {
56 continue;
57 }
58 case SERVER_ALLOCATED_REQUIRED_ANY:
59 break;
60 }
61 if (count > 10) {
62 DLIST_PROMOTE(validated_users, usp);
63 }
64 return usp;
65 }
66 }
67
68 return NULL;
69}
70
71/****************************************************************************
72 Check if a uid has been validated, and return an pointer to the user_struct
73 if it has. NULL if not. vuid is biased by an offset. This allows us to
74 tell random client vuid's (normally zero) from valid vuids.
75****************************************************************************/
76
77user_struct *get_valid_user_struct(uint16 vuid)
78{
79 return get_valid_user_struct_internal(vuid,
80 SERVER_ALLOCATED_REQUIRED_YES);
81}
82
83bool is_partial_auth_vuid(uint16 vuid)
84{
85 if (vuid == UID_FIELD_INVALID) {
86 return False;
87 }
88 return get_valid_user_struct_internal(vuid,
89 SERVER_ALLOCATED_REQUIRED_NO) ? True : False;
90}
91
92/****************************************************************************
93 Get the user struct of a partial NTLMSSP login
94****************************************************************************/
95
96user_struct *get_partial_auth_user_struct(uint16 vuid)
97{
98 return get_valid_user_struct_internal(vuid,
99 SERVER_ALLOCATED_REQUIRED_NO);
100}
101
102/****************************************************************************
103 Invalidate a uid.
104****************************************************************************/
105
106void invalidate_vuid(uint16 vuid)
107{
108 user_struct *vuser = NULL;
109
110 if (vuid == UID_FIELD_INVALID) {
111 return;
112 }
113
114 vuser = get_valid_user_struct_internal(vuid,
115 SERVER_ALLOCATED_REQUIRED_ANY);
116 if (vuser == NULL) {
117 return;
118 }
119
120 session_yield(vuser);
121
122 data_blob_free(&vuser->session_key);
123
124 if (vuser->auth_ntlmssp_state) {
125 auth_ntlmssp_end(&vuser->auth_ntlmssp_state);
126 }
127
128 DLIST_REMOVE(validated_users, vuser);
129
130 /* clear the vuid from the 'cache' on each connection, and
131 from the vuid 'owner' of connections */
132 conn_clear_vuid_cache(vuid);
133
134 TALLOC_FREE(vuser);
135 num_validated_vuids--;
136}
137
138/****************************************************************************
139 Invalidate all vuid entries for this process.
140****************************************************************************/
141
142void invalidate_all_vuids(void)
143{
144 user_struct *usp, *next=NULL;
145
146 for (usp=validated_users;usp;usp=next) {
147 next = usp->next;
148 invalidate_vuid(usp->vuid);
149 }
150}
151
152static void increment_next_vuid(uint16_t *vuid)
153{
154 *vuid += 1;
155
156 /* Check for vuid wrap. */
157 if (*vuid == UID_FIELD_INVALID) {
158 *vuid = VUID_OFFSET;
159 }
160}
161
162/****************************************************
163 Create a new partial auth user struct.
164*****************************************************/
165
166int register_initial_vuid(void)
167{
168 user_struct *vuser;
169
170 /* Paranoia check. */
171 if(lp_security() == SEC_SHARE) {
172 smb_panic("register_initial_vuid: "
173 "Tried to register uid in security=share");
174 }
175
176 /* Limit allowed vuids to 16bits - VUID_OFFSET. */
177 if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) {
178 return UID_FIELD_INVALID;
179 }
180
181 if((vuser = talloc_zero(NULL, user_struct)) == NULL) {
182 DEBUG(0,("register_initial_vuid: "
183 "Failed to talloc users struct!\n"));
184 return UID_FIELD_INVALID;
185 }
186
187 /* Allocate a free vuid. Yes this is a linear search... */
188 while( get_valid_user_struct_internal(next_vuid,
189 SERVER_ALLOCATED_REQUIRED_ANY) != NULL ) {
190 increment_next_vuid(&next_vuid);
191 }
192
193 DEBUG(10,("register_initial_vuid: allocated vuid = %u\n",
194 (unsigned int)next_vuid ));
195
196 vuser->vuid = next_vuid;
197
198 /*
199 * This happens in an unfinished NTLMSSP session setup. We
200 * need to allocate a vuid between the first and second calls
201 * to NTLMSSP.
202 */
203 increment_next_vuid(&next_vuid);
204 num_validated_vuids++;
205
206 DLIST_ADD(validated_users, vuser);
207 return vuser->vuid;
208}
209
210/**
211 * register that a valid login has been performed, establish 'session'.
212 * @param server_info The token returned from the authentication process.
213 * (now 'owned' by register_existing_vuid)
214 *
215 * @param session_key The User session key for the login session (now also
216 * 'owned' by register_existing_vuid)
217 *
218 * @param respose_blob The NT challenge-response, if available. (May be
219 * freed after this call)
220 *
221 * @param smb_name The untranslated name of the user
222 *
223 * @return Newly allocated vuid, biased by an offset. (This allows us to
224 * tell random client vuid's (normally zero) from valid vuids.)
225 *
226 */
227
228int register_existing_vuid(uint16 vuid,
229 auth_serversupplied_info *server_info,
230 DATA_BLOB session_key,
231 DATA_BLOB response_blob,
232 const char *smb_name)
233{
234 user_struct *vuser = get_partial_auth_user_struct(vuid);
235 if (!vuser) {
236 goto fail;
237 }
238
239 /* Use this to keep tabs on all our info from the authentication */
240 vuser->server_info = server_info;
241
242 /* Ensure that the server_info will disappear with
243 * the vuser it is now attached to */
244
245 talloc_steal(vuser, vuser->server_info);
246
247 /* the next functions should be done by a SID mapping system (SMS) as
248 * the new real sam db won't have reference to unix uids or gids
249 */
250
251 vuser->uid = server_info->uid;
252 vuser->gid = server_info->gid;
253
254 vuser->n_groups = server_info->n_groups;
255 if (vuser->n_groups) {
256 if (!(vuser->groups = (gid_t *)talloc_memdup(vuser,
257 server_info->groups,
258 sizeof(gid_t)*vuser->n_groups))) {
259 DEBUG(0,("register_existing_vuid: "
260 "failed to talloc_memdup vuser->groups\n"));
261 goto fail;
262 }
263 }
264
265 vuser->guest = server_info->guest;
266 fstrcpy(vuser->user.unix_name, server_info->unix_name);
267
268 /* This is a potentially untrusted username */
269 alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$",
270 sizeof(vuser->user.smb_name));
271
272 fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account));
273 fstrcpy(vuser->user.full_name,
274 pdb_get_fullname(server_info->sam_account));
275
276 {
277 /* Keep the homedir handy */
278 const char *homedir =
279 pdb_get_homedir(server_info->sam_account);
280 const char *logon_script =
281 pdb_get_logon_script(server_info->sam_account);
282
283 if (!IS_SAM_DEFAULT(server_info->sam_account,
284 PDB_UNIXHOMEDIR)) {
285 const char *unix_homedir =
286 pdb_get_unix_homedir(server_info->sam_account);
287 if (unix_homedir) {
288 vuser->unix_homedir = unix_homedir;
289 }
290 } else {
291 struct passwd *passwd =
292 getpwnam_alloc(vuser, vuser->user.unix_name);
293 if (passwd) {
294#ifdef __OS2__
295 /* On OS/2 we use drive letters which have a colon. This is also the field
296 separator in master.passwd, so we use a $ instead of a colon for the drive
297 separator, ie e$/user instead of e:/user. This code simply exchanges any $
298 for a : in the user's homedir */
299 if (passwd->pw_dir[1] == '$')
300 passwd->pw_dir[1] = ':';
301#endif
302 vuser->unix_homedir = passwd->pw_dir;
303
304 /* Ensure that the unix_homedir now
305 * belongs to vuser, so it goes away
306 * with it, not with passwd below: */
307 talloc_steal(vuser, vuser->unix_homedir);
308 TALLOC_FREE(passwd);
309 }
310 }
311
312 if (homedir) {
313 vuser->homedir = homedir;
314 }
315 if (logon_script) {
316 vuser->logon_script = logon_script;
317 }
318 }
319 vuser->session_key = session_key;
320
321 DEBUG(10,("register_existing_vuid: (%u,%u) %s %s %s guest=%d\n",
322 (unsigned int)vuser->uid,
323 (unsigned int)vuser->gid,
324 vuser->user.unix_name, vuser->user.smb_name,
325 vuser->user.domain, vuser->guest ));
326
327 DEBUG(3, ("register_existing_vuid: User name: %s\t"
328 "Real name: %s\n", vuser->user.unix_name,
329 vuser->user.full_name));
330
331 if (server_info->ptok) {
332 vuser->nt_user_token = dup_nt_token(vuser, server_info->ptok);
333 } else {
334 DEBUG(1, ("register_existing_vuid: server_info does not "
335 "contain a user_token - cannot continue\n"));
336 goto fail;
337 }
338
339 DEBUG(3,("register_existing_vuid: UNIX uid %d is UNIX user %s, "
340 "and will be vuid %u\n",
341 (int)vuser->uid,vuser->user.unix_name, vuser->vuid));
342
343 if (!session_claim(vuser)) {
344 DEBUG(1, ("register_existing_vuid: Failed to claim session "
345 "for vuid=%d\n",
346 vuser->vuid));
347 goto fail;
348 }
349
350 /* Register a home dir service for this user if
351 (a) This is not a guest connection,
352 (b) we have a home directory defined
353 (c) there s not an existing static share by that name
354 If a share exists by this name (autoloaded or not) reuse it . */
355
356 vuser->homes_snum = -1;
357
358 if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) {
359 int servicenumber = lp_servicenumber(vuser->user.unix_name);
360 if ( servicenumber == -1 ) {
361 DEBUG(3, ("Adding homes service for user '%s' using "
362 "home directory: '%s'\n",
363 vuser->user.unix_name, vuser->unix_homedir));
364 vuser->homes_snum =
365 add_home_service(vuser->user.unix_name,
366 vuser->user.unix_name,
367 vuser->unix_homedir);
368 } else {
369 DEBUG(3, ("Using static (or previously created) "
370 "service for user '%s'; path = '%s'\n",
371 vuser->user.unix_name,
372 lp_pathname(servicenumber) ));
373 vuser->homes_snum = servicenumber;
374 }
375 }
376
377 if (srv_is_signing_negotiated() && !vuser->guest &&
378 !srv_signing_started()) {
379 /* Try and turn on server signing on the first non-guest
380 * sessionsetup. */
381 srv_set_signing(vuser->session_key, response_blob);
382 }
383
384 /* fill in the current_user_info struct */
385 set_current_user_info( &vuser->user );
386 return vuser->vuid;
387
388 fail:
389
390 if (vuser) {
391 invalidate_vuid(vuid);
392 }
393 return UID_FIELD_INVALID;
394}
395
396/****************************************************************************
397 Add a name to the session users list.
398****************************************************************************/
399
400void add_session_user(const char *user)
401{
402 struct passwd *pw;
403 char *tmp;
404
405 pw = Get_Pwnam_alloc(talloc_tos(), user);
406
407 if (pw == NULL) {
408 return;
409 }
410
411 if (session_userlist == NULL) {
412 session_userlist = SMB_STRDUP(pw->pw_name);
413 goto done;
414 }
415
416 if (in_list(pw->pw_name,session_userlist,False) ) {
417 goto done;
418 }
419
420 if (strlen(session_userlist) > 128 * 1024) {
421 DEBUG(3,("add_session_user: session userlist already "
422 "too large.\n"));
423 goto done;
424 }
425
426 if (asprintf(&tmp, "%s %s", session_userlist, pw->pw_name) == -1) {
427 DEBUG(3, ("asprintf failed\n"));
428 goto done;
429 }
430
431 SAFE_FREE(session_userlist);
432 session_userlist = tmp;
433 done:
434 TALLOC_FREE(pw);
435}
436
437/****************************************************************************
438 In security=share mode we need to store the client workgroup, as that's
439 what Vista uses for the NTLMv2 calculation.
440****************************************************************************/
441
442void add_session_workgroup(const char *workgroup)
443{
444 if (session_workgroup) {
445 SAFE_FREE(session_workgroup);
446 }
447 session_workgroup = smb_xstrdup(workgroup);
448}
449
450/****************************************************************************
451 In security=share mode we need to return the client workgroup, as that's
452 what Vista uses for the NTLMv2 calculation.
453****************************************************************************/
454
455const char *get_session_workgroup(void)
456{
457 return session_workgroup;
458}
459
460/****************************************************************************
461 Check if a user is in a netgroup user list. If at first we don't succeed,
462 try lower case.
463****************************************************************************/
464
465bool user_in_netgroup(const char *user, const char *ngname)
466{
467#ifdef HAVE_NETGROUP
468 static char *mydomain = NULL;
469 fstring lowercase_user;
470
471 if (mydomain == NULL)
472 yp_get_default_domain(&mydomain);
473
474 if(mydomain == NULL) {
475 DEBUG(5,("Unable to get default yp domain, "
476 "let's try without specifying it\n"));
477 }
478
479 DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
480 user, mydomain?mydomain:"(ANY)", ngname));
481
482 if (innetgr(ngname, NULL, user, mydomain)) {
483 DEBUG(5,("user_in_netgroup: Found\n"));
484 return (True);
485 } else {
486
487 /*
488 * Ok, innetgr is case sensitive. Try once more with lowercase
489 * just in case. Attempt to fix #703. JRA.
490 */
491
492 fstrcpy(lowercase_user, user);
493 strlower_m(lowercase_user);
494
495 DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
496 lowercase_user, mydomain?mydomain:"(ANY)", ngname));
497
498 if (innetgr(ngname, NULL, lowercase_user, mydomain)) {
499 DEBUG(5,("user_in_netgroup: Found\n"));
500 return (True);
501 }
502 }
503#endif /* HAVE_NETGROUP */
504 return False;
505}
506
507/****************************************************************************
508 Check if a user is in a user list - can check combinations of UNIX
509 and netgroup lists.
510****************************************************************************/
511
512bool user_in_list(const char *user,const char **list)
513{
514 if (!list || !*list)
515 return False;
516
517 DEBUG(10,("user_in_list: checking user %s in list\n", user));
518
519 while (*list) {
520
521 DEBUG(10,("user_in_list: checking user |%s| against |%s|\n",
522 user, *list));
523
524 /*
525 * Check raw username.
526 */
527 if (strequal(user, *list))
528 return(True);
529
530 /*
531 * Now check to see if any combination
532 * of UNIX and netgroups has been specified.
533 */
534
535 if(**list == '@') {
536 /*
537 * Old behaviour. Check netgroup list
538 * followed by UNIX list.
539 */
540 if(user_in_netgroup(user, *list +1))
541 return True;
542 if(user_in_group(user, *list +1))
543 return True;
544 } else if (**list == '+') {
545
546 if((*(*list +1)) == '&') {
547 /*
548 * Search UNIX list followed by netgroup.
549 */
550 if(user_in_group(user, *list +2))
551 return True;
552 if(user_in_netgroup(user, *list +2))
553 return True;
554
555 } else {
556
557 /*
558 * Just search UNIX list.
559 */
560
561 if(user_in_group(user, *list +1))
562 return True;
563 }
564
565 } else if (**list == '&') {
566
567 if(*(*list +1) == '+') {
568 /*
569 * Search netgroup list followed by UNIX list.
570 */
571 if(user_in_netgroup(user, *list +2))
572 return True;
573 if(user_in_group(user, *list +2))
574 return True;
575 } else {
576 /*
577 * Just search netgroup list.
578 */
579 if(user_in_netgroup(user, *list +1))
580 return True;
581 }
582 }
583
584 list++;
585 }
586 return(False);
587}
588
589/****************************************************************************
590 Check if a username is valid.
591****************************************************************************/
592
593static bool user_ok(const char *user, int snum)
594{
595 char **valid, **invalid;
596 bool ret;
597
598 valid = invalid = NULL;
599 ret = True;
600
601 if (lp_invalid_users(snum)) {
602 str_list_copy(talloc_tos(), &invalid, lp_invalid_users(snum));
603 if (invalid &&
604 str_list_substitute(invalid, "%S", lp_servicename(snum))) {
605
606 /* This is used in sec=share only, so no current user
607 * around to pass to str_list_sub_basic() */
608
609 if ( invalid && str_list_sub_basic(invalid, "", "") ) {
610 ret = !user_in_list(user,
611 (const char **)invalid);
612 }
613 }
614 }
615 TALLOC_FREE(invalid);
616
617 if (ret && lp_valid_users(snum)) {
618 str_list_copy(talloc_tos(), &valid, lp_valid_users(snum));
619 if ( valid &&
620 str_list_substitute(valid, "%S", lp_servicename(snum)) ) {
621
622 /* This is used in sec=share only, so no current user
623 * around to pass to str_list_sub_basic() */
624
625 if ( valid && str_list_sub_basic(valid, "", "") ) {
626 ret = user_in_list(user, (const char **)valid);
627 }
628 }
629 }
630 TALLOC_FREE(valid);
631
632 if (ret && lp_onlyuser(snum)) {
633 char **user_list = str_list_make(
634 talloc_tos(), lp_username(snum), NULL);
635 if (user_list &&
636 str_list_substitute(user_list, "%S",
637 lp_servicename(snum))) {
638 ret = user_in_list(user, (const char **)user_list);
639 }
640 TALLOC_FREE(user_list);
641 }
642
643 return(ret);
644}
645
646/****************************************************************************
647 Validate a group username entry. Return the username or NULL.
648****************************************************************************/
649
650static char *validate_group(char *group, DATA_BLOB password,int snum)
651{
652#ifdef HAVE_NETGROUP
653 {
654 char *host, *user, *domain;
655 setnetgrent(group);
656 while (getnetgrent(&host, &user, &domain)) {
657 if (user) {
658 if (user_ok(user, snum) &&
659 password_ok(user,password)) {
660 endnetgrent();
661 return(user);
662 }
663 }
664 }
665 endnetgrent();
666 }
667#endif
668
669#ifdef HAVE_GETGRENT
670 {
671 struct group *gptr;
672 setgrent();
673 while ((gptr = (struct group *)getgrent())) {
674 if (strequal(gptr->gr_name,group))
675 break;
676 }
677
678 /*
679 * As user_ok can recurse doing a getgrent(), we must
680 * copy the member list onto the heap before
681 * use. Bug pointed out by leon@eatworms.swmed.edu.
682 */
683
684 if (gptr) {
685 char *member_list = NULL;
686 size_t list_len = 0;
687 char *member;
688 int i;
689
690 for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) {
691 list_len += strlen(gptr->gr_mem[i])+1;
692 }
693 list_len++;
694
695 member_list = (char *)SMB_MALLOC(list_len);
696 if (!member_list) {
697 endgrent();
698 return NULL;
699 }
700
701 *member_list = '\0';
702 member = member_list;
703
704 for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) {
705 size_t member_len = strlen(gptr->gr_mem[i])+1;
706
707 DEBUG(10,("validate_group: = gr_mem = "
708 "%s\n", gptr->gr_mem[i]));
709
710 safe_strcpy(member, gptr->gr_mem[i],
711 list_len - (member-member_list));
712 member += member_len;
713 }
714
715 endgrent();
716
717 member = member_list;
718 while (*member) {
719 if (user_ok(member,snum) &&
720 password_ok(member,password)) {
721 char *name = talloc_strdup(talloc_tos(),
722 member);
723 SAFE_FREE(member_list);
724 return name;
725 }
726
727 DEBUG(10,("validate_group = member = %s\n",
728 member));
729
730 member += strlen(member) + 1;
731 }
732
733 SAFE_FREE(member_list);
734 } else {
735 endgrent();
736 return NULL;
737 }
738 }
739#endif
740 return(NULL);
741}
742
743/****************************************************************************
744 Check for authority to login to a service with a given username/password.
745 Note this is *NOT* used when logging on using sessionsetup_and_X.
746****************************************************************************/
747
748bool authorise_login(int snum, fstring user, DATA_BLOB password,
749 bool *guest)
750{
751 bool ok = False;
752
753#ifdef DEBUG_PASSWORD
754 DEBUG(100,("authorise_login: checking authorisation on "
755 "user=%s pass=%s\n", user,password.data));
756#endif
757
758 *guest = False;
759
760 /* there are several possibilities:
761 1) login as the given user with given password
762 2) login as a previously registered username with the given
763 password
764 3) login as a session list username with the given password
765 4) login as a previously validated user/password pair
766 5) login as the "user =" user with given password
767 6) login as the "user =" user with no password
768 (guest connection)
769 7) login as guest user with no password
770
771 if the service is guest_only then steps 1 to 5 are skipped
772 */
773
774 /* now check the list of session users */
775 if (!ok) {
776 char *auser;
777 char *user_list = NULL;
778 char *saveptr;
779
780 if ( session_userlist )
781 user_list = SMB_STRDUP(session_userlist);
782 else
783 user_list = SMB_STRDUP("");
784
785 if (!user_list)
786 return(False);
787
788 for (auser = strtok_r(user_list, LIST_SEP, &saveptr);
789 !ok && auser;
790 auser = strtok_r(NULL, LIST_SEP, &saveptr)) {
791 fstring user2;
792 fstrcpy(user2,auser);
793 if (!user_ok(user2,snum))
794 continue;
795
796 if (password_ok(user2,password)) {
797 ok = True;
798 fstrcpy(user,user2);
799 DEBUG(3,("authorise_login: ACCEPTED: session "
800 "list username (%s) and given "
801 "password ok\n", user));
802 }
803 }
804
805 SAFE_FREE(user_list);
806 }
807
808 /* check the user= fields and the given password */
809 if (!ok && lp_username(snum)) {
810 TALLOC_CTX *ctx = talloc_tos();
811 char *auser;
812 char *user_list = talloc_strdup(ctx, lp_username(snum));
813 char *saveptr;
814
815 if (!user_list) {
816 goto check_guest;
817 }
818
819 user_list = talloc_string_sub(ctx,
820 user_list,
821 "%S",
822 lp_servicename(snum));
823
824 if (!user_list) {
825 goto check_guest;
826 }
827
828 for (auser = strtok_r(user_list, LIST_SEP, &saveptr);
829 auser && !ok;
830 auser = strtok_r(NULL, LIST_SEP, &saveptr)) {
831 if (*auser == '@') {
832 auser = validate_group(auser+1,password,snum);
833 if (auser) {
834 ok = True;
835 fstrcpy(user,auser);
836 DEBUG(3,("authorise_login: ACCEPTED: "
837 "group username and given "
838 "password ok (%s)\n", user));
839 }
840 } else {
841 fstring user2;
842 fstrcpy(user2,auser);
843 if (user_ok(user2,snum) &&
844 password_ok(user2,password)) {
845 ok = True;
846 fstrcpy(user,user2);
847 DEBUG(3,("authorise_login: ACCEPTED: "
848 "user list username and "
849 "given password ok (%s)\n",
850 user));
851 }
852 }
853 }
854 }
855
856 check_guest:
857
858 /* check for a normal guest connection */
859 if (!ok && GUEST_OK(snum)) {
860 struct passwd *guest_pw;
861 fstring guestname;
862 fstrcpy(guestname,lp_guestaccount());
863 guest_pw = Get_Pwnam_alloc(talloc_tos(), guestname);
864 if (guest_pw != NULL) {
865 fstrcpy(user,guestname);
866 ok = True;
867 DEBUG(3,("authorise_login: ACCEPTED: guest account "
868 "and guest ok (%s)\n", user));
869 } else {
870 DEBUG(0,("authorise_login: Invalid guest account "
871 "%s??\n",guestname));
872 }
873 TALLOC_FREE(guest_pw);
874 *guest = True;
875 }
876
877 if (ok && !user_ok(user, snum)) {
878 DEBUG(0,("authorise_login: rejected invalid user %s\n",user));
879 ok = False;
880 }
881
882 return(ok);
883}
Note: See TracBrowser for help on using the repository browser.