|
1 // Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca> |
|
2 // |
|
3 // This program is free software; you can redistribute it and/or modify |
|
4 // it under the terms of the GNU General Public License as published by |
|
5 // the Free Software Foundation; either version 2 of the License, or |
|
6 // (at your option) any later version. |
|
7 // |
|
8 // This program is distributed in the hope that it will be useful, |
|
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
11 // GNU General Public License for more details. |
|
12 // |
|
13 // You should have received a copy of the GNU General Public License |
|
14 // along with this program; if not, write to the Free Software |
|
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
16 |
|
17 #include <config.h> |
|
18 #include <stdlib.h> |
|
19 #include "ac/time.h" |
|
20 #include <unistd.h> |
|
21 #include "authvlib.h" |
|
22 #include "misc/exec.h" |
|
23 #include "misc/lookup.h" |
|
24 #include "vdomain/vdomain.h" |
|
25 |
|
26 #ifndef HAVE_GETHOSTNAME |
|
27 int gethostname(char *name, size_t len); |
|
28 #endif |
|
29 |
|
30 void set_domain(mystring& name, mystring& domain) |
|
31 { |
|
32 int sep = name.find_first_of(config->separators()); |
|
33 if(sep >= 0) { |
|
34 domain = name.right(sep+1); |
|
35 name = name.left(sep); |
|
36 } |
|
37 else { |
|
38 domain = getenv("TCPLOCALHOST"); |
|
39 if(!domain) { |
|
40 char tmp[256]; |
|
41 if(gethostname(tmp, 256)) |
|
42 fail_temporary("Error determining local host name"); |
|
43 domain = tmp; |
|
44 } |
|
45 } |
|
46 if(!name) |
|
47 fail_login("Empty user name"); |
|
48 if(!domain) |
|
49 fail_login("Empty domain name"); |
|
50 } |
|
51 |
|
52 static vdomain* domain = 0; |
|
53 |
|
54 void set_user(const pwentry* pw) |
|
55 { |
|
56 pw->export_env(); |
|
57 if(!!exec_presetuid && execute(exec_presetuid)) |
|
58 fail_temporary("Execution of presetuid failed"); |
|
59 if(setgid(pw->gid) == -1 || |
|
60 setuid(pw->uid) == -1 || |
|
61 chdir(pw->home.c_str()) == -1) |
|
62 fail_temporary("Bad user data in password file"); |
|
63 domain = new vdomain(*pw); |
|
64 config = &domain->config; |
|
65 } |
|
66 |
|
67 static user_data* check(mystring fulluser, mystring password, |
|
68 bool virtual_only) |
|
69 { |
|
70 mystring virtname; |
|
71 pwentry* basepw; |
|
72 if(!lookup_baseuser(fulluser, basepw, virtname)) |
|
73 fail_login("Invalid or unknown base user or domain"); |
|
74 presetenv("VUSER=", virtname); |
|
75 if(!virtname) { |
|
76 if(virtual_only) |
|
77 return 0; |
|
78 if(!basepw->authenticate(password)) |
|
79 fail_login("Invalid or incorrect password"); |
|
80 set_user(basepw); |
|
81 return new user_data(basepw, "", ""); |
|
82 } |
|
83 else { |
|
84 set_user(basepw); |
|
85 vpwentry* vpw = domain->lookup(virtname, true); |
|
86 if(!vpw || !vpw->mailbox) |
|
87 fail_login("Invalid or unknown virtual user"); |
|
88 if(!vpw->authenticate(password)) |
|
89 fail_login("Invalid or incorrect password"); |
|
90 if(vpw->expiry < (unsigned)time(0)) |
|
91 fail_login("Account has expired"); |
|
92 vpw->export_env(); |
|
93 return new user_data(basepw, vpw->mailbox, vpw->name); |
|
94 } |
|
95 } |
|
96 |
|
97 user_data* authenticate(mystring name, mystring pass, mystring domain, |
|
98 bool virtual_only) |
|
99 { |
|
100 mystring baseuser; |
|
101 if(!is_local(domain)) { |
|
102 mystring baseuser = find_virtual(domain); |
|
103 if(!!baseuser) |
|
104 name = baseuser + "-" + name; |
|
105 } |
|
106 user_data* result = check(name, pass, virtual_only); |
|
107 if(result && !!exec_postsetuid && execute(exec_postsetuid)) |
|
108 fail_temporary("Execution of presetuid failed"); |
|
109 return result; |
|
110 } |