Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/master/login-process.c @ 805:5ac361acb316 HEAD
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
cleanups and a couple of minor bugfixes.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 18 Dec 2002 17:15:41 +0200 |
parents | 86224ff16bf6 |
children | 35abd7a5d381 |
rev | line source |
---|---|
0 | 1 /* Copyright (C) 2002 Timo Sirainen */ |
2 | |
3 #include "common.h" | |
532
3b53dd1280c6
I/O buffers now use real blocking instead of setting up a sub-ioloop to
Timo Sirainen <tss@iki.fi>
parents:
410
diff
changeset
|
4 #include "ioloop.h" |
0 | 5 #include "network.h" |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
747
diff
changeset
|
6 #include "ostream.h" |
0 | 7 #include "fdpass.h" |
727
8dd8ebe6bcac
We use close-on-exec flag now to make sure that master process closes the
Timo Sirainen <tss@iki.fi>
parents:
722
diff
changeset
|
8 #include "fd-close-on-exec.h" |
697
7814b29d0862
Created env_put() and env_clean() for a bit easier handling of environment
Timo Sirainen <tss@iki.fi>
parents:
666
diff
changeset
|
9 #include "env-util.h" |
0 | 10 #include "restrict-access.h" |
722
0438621d25ff
Added virtual memory size limits to processes. Default values are pretty
Timo Sirainen <tss@iki.fi>
parents:
699
diff
changeset
|
11 #include "restrict-process-size.h" |
0 | 12 #include "login-process.h" |
13 #include "auth-process.h" | |
14 #include "master-interface.h" | |
15 | |
16 #include <unistd.h> | |
17 #include <syslog.h> | |
18 | |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
19 typedef struct _LoginProcess LoginProcess; |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
20 |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
21 struct _LoginProcess { |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
22 LoginProcess *prev_nonlisten, *next_nonlisten; |
0 | 23 int refcount; |
24 | |
25 pid_t pid; | |
26 int fd; | |
27 IO io; | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
747
diff
changeset
|
28 OStream *output; |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
29 unsigned int listening:1; |
0 | 30 unsigned int destroyed:1; |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
31 }; |
0 | 32 |
33 typedef struct { | |
34 LoginProcess *process; | |
35 int login_id; | |
36 int auth_id; | |
37 int fd; | |
38 | |
596
ab3590c3a7d9
Added verbose_proctitle setting: Show more verbose process titles (in ps).
Timo Sirainen <tss@iki.fi>
parents:
532
diff
changeset
|
39 IPADDR ip; |
0 | 40 char login_tag[LOGIN_TAG_SIZE]; |
41 } LoginAuthRequest; | |
42 | |
43 static int auth_id_counter; | |
44 static Timeout to; | |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
45 |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
46 static HashTable *processes; |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
47 static LoginProcess *oldest_nonlisten_process, *newest_nonlisten_process; |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
48 static unsigned int listening_processes; |
614
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
49 static unsigned int wanted_processes_count; |
0 | 50 |
51 static void login_process_destroy(LoginProcess *p); | |
52 static void login_process_unref(LoginProcess *p); | |
53 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
54 static void auth_callback(AuthCookieReplyData *cookie_reply, void *context) |
0 | 55 { |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
56 LoginAuthRequest *request = context; |
0 | 57 LoginProcess *process; |
58 MasterReply reply; | |
59 | |
60 if (cookie_reply == NULL || !cookie_reply->success) | |
61 reply.result = MASTER_RESULT_FAILURE; | |
62 else { | |
63 reply.result = create_imap_process(request->fd, | |
596
ab3590c3a7d9
Added verbose_proctitle setting: Show more verbose process titles (in ps).
Timo Sirainen <tss@iki.fi>
parents:
532
diff
changeset
|
64 &request->ip, |
791
6efced4f80de
Clear separation of virtual and system usernames. passwd-file didn't work
Timo Sirainen <tss@iki.fi>
parents:
764
diff
changeset
|
65 cookie_reply->system_user, |
6efced4f80de
Clear separation of virtual and system usernames. passwd-file didn't work
Timo Sirainen <tss@iki.fi>
parents:
764
diff
changeset
|
66 cookie_reply->virtual_user, |
0 | 67 cookie_reply->uid, |
68 cookie_reply->gid, | |
69 cookie_reply->home, | |
801
86224ff16bf6
Drop root privileges earlier. Close syslog more later in imap-master when
Timo Sirainen <tss@iki.fi>
parents:
791
diff
changeset
|
70 cookie_reply->chroot, |
86224ff16bf6
Drop root privileges earlier. Close syslog more later in imap-master when
Timo Sirainen <tss@iki.fi>
parents:
791
diff
changeset
|
71 cookie_reply->mail, |
86224ff16bf6
Drop root privileges earlier. Close syslog more later in imap-master when
Timo Sirainen <tss@iki.fi>
parents:
791
diff
changeset
|
72 request->login_tag); |
0 | 73 } |
74 | |
75 /* reply to login */ | |
76 reply.id = request->login_id; | |
77 | |
78 process = request->process; | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
747
diff
changeset
|
79 if (o_stream_send(process->output, &reply, sizeof(reply)) < 0) |
0 | 80 login_process_destroy(process); |
81 | |
805
5ac361acb316
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
Timo Sirainen <tss@iki.fi>
parents:
801
diff
changeset
|
82 if (close(request->fd) < 0) |
5ac361acb316
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
Timo Sirainen <tss@iki.fi>
parents:
801
diff
changeset
|
83 i_error("close(imap client) failed: %m"); |
0 | 84 login_process_unref(process); |
85 i_free(request); | |
86 } | |
87 | |
699
cc795d74d08f
Use more warnings with GCC by default. Fixed several warnings.
Timo Sirainen <tss@iki.fi>
parents:
697
diff
changeset
|
88 static void login_process_mark_nonlistening(LoginProcess *p) |
614
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
89 { |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
90 if (!p->listening) { |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
91 i_error("login: received another \"not listening\" " |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
92 "notification"); |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
93 return; |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
94 } |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
95 |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
96 p->listening = FALSE; |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
97 listening_processes--; |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
98 |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
99 p->prev_nonlisten = newest_nonlisten_process; |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
100 |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
101 if (newest_nonlisten_process != NULL) |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
102 newest_nonlisten_process->next_nonlisten = p; |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
103 newest_nonlisten_process = p; |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
104 |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
105 if (oldest_nonlisten_process == NULL) |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
106 oldest_nonlisten_process = p; |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
107 } |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
108 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
109 static void login_process_input(void *context, int fd __attr_unused__, |
0 | 110 IO io __attr_unused__) |
111 { | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
112 LoginProcess *p = context; |
0 | 113 AuthProcess *auth_process; |
114 LoginAuthRequest *authreq; | |
115 MasterRequest req; | |
116 int client_fd, ret; | |
117 | |
118 ret = fd_read(p->fd, &req, sizeof(req), &client_fd); | |
119 if (ret != sizeof(req)) { | |
120 if (ret == 0) { | |
121 /* disconnected, ie. the login process died */ | |
122 } else if (ret > 0) { | |
123 /* req wasn't fully read */ | |
124 i_error("login: fd_read() couldn't read all req"); | |
125 } else { | |
126 i_error("login: fd_read() failed: %m"); | |
127 } | |
128 | |
129 login_process_destroy(p); | |
130 return; | |
131 } | |
132 | |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
133 if (client_fd == -1) { |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
134 /* just a notification that the login process isn't |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
135 listening for new connections anymore */ |
614
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
136 login_process_mark_nonlistening(p); |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
137 return; |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
138 } |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
139 |
0 | 140 /* login process isn't trusted, validate all data to make sure |
141 it's not trying to exploit us */ | |
142 if (!VALIDATE_STR(req.login_tag)) { | |
143 i_error("login: Received corrupted data"); | |
144 login_process_destroy(p); | |
145 return; | |
146 } | |
147 | |
148 /* ask the cookie from the auth process */ | |
149 authreq = i_new(LoginAuthRequest, 1); | |
150 p->refcount++; | |
151 authreq->process = p; | |
152 authreq->login_id = req.id; | |
153 authreq->auth_id = ++auth_id_counter; | |
154 authreq->fd = client_fd; | |
596
ab3590c3a7d9
Added verbose_proctitle setting: Show more verbose process titles (in ps).
Timo Sirainen <tss@iki.fi>
parents:
532
diff
changeset
|
155 memcpy(&authreq->ip, &req.ip, sizeof(IPADDR)); |
0 | 156 strcpy(authreq->login_tag, req.login_tag); |
157 | |
158 auth_process = auth_process_find(req.auth_process); | |
159 if (auth_process == NULL) { | |
160 i_error("login: Authentication process %u doesn't exist", | |
161 req.auth_process); | |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
162 auth_callback(NULL, authreq); |
0 | 163 } else { |
164 auth_process_request(auth_process, authreq->auth_id, req.cookie, | |
165 auth_callback, authreq); | |
166 } | |
167 } | |
168 | |
169 static LoginProcess *login_process_new(pid_t pid, int fd) | |
170 { | |
171 LoginProcess *p; | |
172 | |
173 PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_LOGIN); | |
174 | |
175 p = i_new(LoginProcess, 1); | |
176 p->refcount = 1; | |
177 p->pid = pid; | |
178 p->fd = fd; | |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
179 p->listening = TRUE; |
0 | 180 p->io = io_add(fd, IO_READ, login_process_input, p); |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
747
diff
changeset
|
181 p->output = o_stream_create_file(fd, default_pool, |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
182 sizeof(MasterReply)*10, |
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
183 IO_PRIORITY_DEFAULT, FALSE); |
0 | 184 |
195
db6e288be0e9
Replaced INT_TO_POINTER and POINTER_TO_INT macros with POINTER_CAST and
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
185 hash_insert(processes, POINTER_CAST(pid), p); |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
186 listening_processes++; |
0 | 187 return p; |
188 } | |
189 | |
699
cc795d74d08f
Use more warnings with GCC by default. Fixed several warnings.
Timo Sirainen <tss@iki.fi>
parents:
697
diff
changeset
|
190 static void login_process_remove_from_lists(LoginProcess *p) |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
191 { |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
192 if (p == oldest_nonlisten_process) |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
193 oldest_nonlisten_process = p->next_nonlisten; |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
194 else |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
195 p->prev_nonlisten->next_nonlisten = p->next_nonlisten; |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
196 |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
197 if (p == newest_nonlisten_process) |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
198 newest_nonlisten_process = p->prev_nonlisten; |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
199 else |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
200 p->next_nonlisten->prev_nonlisten = p->prev_nonlisten; |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
201 |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
202 p->next_nonlisten = p->prev_nonlisten = NULL; |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
203 } |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
204 |
0 | 205 static void login_process_destroy(LoginProcess *p) |
206 { | |
207 if (p->destroyed) | |
208 return; | |
209 p->destroyed = TRUE; | |
210 | |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
211 if (p->listening) |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
212 listening_processes--; |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
213 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
747
diff
changeset
|
214 o_stream_close(p->output); |
0 | 215 io_remove(p->io); |
805
5ac361acb316
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
Timo Sirainen <tss@iki.fi>
parents:
801
diff
changeset
|
216 if (close(p->fd) < 0) |
5ac361acb316
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
Timo Sirainen <tss@iki.fi>
parents:
801
diff
changeset
|
217 i_error("close(login) failed: %m"); |
0 | 218 |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
219 if (!p->listening) |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
220 login_process_remove_from_lists(p); |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
221 |
195
db6e288be0e9
Replaced INT_TO_POINTER and POINTER_TO_INT macros with POINTER_CAST and
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
222 hash_remove(processes, POINTER_CAST(p->pid)); |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
223 |
0 | 224 login_process_unref(p); |
225 } | |
226 | |
227 static void login_process_unref(LoginProcess *p) | |
228 { | |
229 if (--p->refcount > 0) | |
230 return; | |
231 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
747
diff
changeset
|
232 o_stream_unref(p->output); |
0 | 233 i_free(p); |
234 } | |
235 | |
236 static pid_t create_login_process(void) | |
237 { | |
699
cc795d74d08f
Use more warnings with GCC by default. Fixed several warnings.
Timo Sirainen <tss@iki.fi>
parents:
697
diff
changeset
|
238 static char *argv[] = { NULL, NULL }; |
0 | 239 pid_t pid; |
240 int fd[2]; | |
241 | |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
242 if (set_login_process_per_connection && |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
243 hash_size(processes)-listening_processes >= set_max_logging_users) { |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
244 if (oldest_nonlisten_process != NULL) |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
245 login_process_destroy(oldest_nonlisten_process); |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
246 } |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
247 |
0 | 248 if (set_login_uid == 0) |
249 i_fatal("Login process must not run as root"); | |
250 | |
251 /* create communication to process with a socket pair */ | |
252 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) { | |
253 i_error("socketpair() failed: %m"); | |
254 return -1; | |
255 } | |
256 | |
257 pid = fork(); | |
258 if (pid < 0) { | |
259 (void)close(fd[0]); | |
260 (void)close(fd[1]); | |
261 i_error("fork() failed: %m"); | |
262 return -1; | |
263 } | |
264 | |
265 if (pid != 0) { | |
266 /* master */ | |
727
8dd8ebe6bcac
We use close-on-exec flag now to make sure that master process closes the
Timo Sirainen <tss@iki.fi>
parents:
722
diff
changeset
|
267 fd_close_on_exec(fd[0], TRUE); |
0 | 268 login_process_new(pid, fd[0]); |
269 (void)close(fd[1]); | |
270 return pid; | |
271 } | |
272 | |
273 /* move communication handle */ | |
274 if (dup2(fd[1], LOGIN_MASTER_SOCKET_FD) < 0) | |
805
5ac361acb316
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
Timo Sirainen <tss@iki.fi>
parents:
801
diff
changeset
|
275 i_fatal("login: dup2(master) failed: %m"); |
727
8dd8ebe6bcac
We use close-on-exec flag now to make sure that master process closes the
Timo Sirainen <tss@iki.fi>
parents:
722
diff
changeset
|
276 fd_close_on_exec(LOGIN_MASTER_SOCKET_FD, FALSE); |
0 | 277 |
278 /* move the listen handle */ | |
279 if (dup2(imap_fd, LOGIN_IMAP_LISTEN_FD) < 0) | |
805
5ac361acb316
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
Timo Sirainen <tss@iki.fi>
parents:
801
diff
changeset
|
280 i_fatal("login: dup2(imap) failed: %m"); |
727
8dd8ebe6bcac
We use close-on-exec flag now to make sure that master process closes the
Timo Sirainen <tss@iki.fi>
parents:
722
diff
changeset
|
281 fd_close_on_exec(LOGIN_IMAP_LISTEN_FD, FALSE); |
0 | 282 |
283 /* move the SSL listen handle */ | |
284 if (dup2(imaps_fd, LOGIN_IMAPS_LISTEN_FD) < 0) | |
805
5ac361acb316
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
Timo Sirainen <tss@iki.fi>
parents:
801
diff
changeset
|
285 i_fatal("login: dup2(imaps) failed: %m"); |
727
8dd8ebe6bcac
We use close-on-exec flag now to make sure that master process closes the
Timo Sirainen <tss@iki.fi>
parents:
722
diff
changeset
|
286 fd_close_on_exec(LOGIN_IMAPS_LISTEN_FD, FALSE); |
0 | 287 |
288 /* imap_fd and imaps_fd are closed by clean_child_process() */ | |
289 | |
290 (void)close(fd[0]); | |
291 (void)close(fd[1]); | |
292 | |
293 clean_child_process(); | |
294 | |
295 /* setup access environment - needs to be done after | |
296 clean_child_process() since it clears environment */ | |
297 restrict_access_set_env(set_login_user, set_login_uid, set_login_gid, | |
298 set_login_chroot ? set_login_dir : NULL); | |
299 | |
300 if (!set_login_chroot) { | |
301 /* no chrooting, but still change to the directory */ | |
805
5ac361acb316
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
Timo Sirainen <tss@iki.fi>
parents:
801
diff
changeset
|
302 if (chdir(set_login_dir) < 0) |
5ac361acb316
Marked all non-trivial buffer modifications with @UNSAFE tag. Several
Timo Sirainen <tss@iki.fi>
parents:
801
diff
changeset
|
303 i_fatal("chdir(%s) failed: %m", set_login_dir); |
0 | 304 } |
305 | |
666 | 306 if (!set_ssl_disable) { |
697
7814b29d0862
Created env_put() and env_clean() for a bit easier handling of environment
Timo Sirainen <tss@iki.fi>
parents:
666
diff
changeset
|
307 env_put(t_strconcat("SSL_CERT_FILE=", set_ssl_cert_file, NULL)); |
7814b29d0862
Created env_put() and env_clean() for a bit easier handling of environment
Timo Sirainen <tss@iki.fi>
parents:
666
diff
changeset
|
308 env_put(t_strconcat("SSL_KEY_FILE=", set_ssl_key_file, NULL)); |
7814b29d0862
Created env_put() and env_clean() for a bit easier handling of environment
Timo Sirainen <tss@iki.fi>
parents:
666
diff
changeset
|
309 env_put(t_strconcat("SSL_PARAM_FILE=", |
7814b29d0862
Created env_put() and env_clean() for a bit easier handling of environment
Timo Sirainen <tss@iki.fi>
parents:
666
diff
changeset
|
310 set_ssl_parameters_file, NULL)); |
615
0d852af6842e
Master process generates DH/RSA parameters now and stores them into file
Timo Sirainen <tss@iki.fi>
parents:
614
diff
changeset
|
311 } |
0d852af6842e
Master process generates DH/RSA parameters now and stores them into file
Timo Sirainen <tss@iki.fi>
parents:
614
diff
changeset
|
312 |
0 | 313 if (set_disable_plaintext_auth) |
697
7814b29d0862
Created env_put() and env_clean() for a bit easier handling of environment
Timo Sirainen <tss@iki.fi>
parents:
666
diff
changeset
|
314 env_put("DISABLE_PLAINTEXT_AUTH=1"); |
747
db6fb0aa16d1
Let login process also know if verbose process titles are wanted..
Timo Sirainen <tss@iki.fi>
parents:
727
diff
changeset
|
315 if (set_verbose_proctitle) |
db6fb0aa16d1
Let login process also know if verbose process titles are wanted..
Timo Sirainen <tss@iki.fi>
parents:
727
diff
changeset
|
316 env_put("VERBOSE_PROCTITLE=1"); |
0 | 317 |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
318 if (set_login_process_per_connection) { |
697
7814b29d0862
Created env_put() and env_clean() for a bit easier handling of environment
Timo Sirainen <tss@iki.fi>
parents:
666
diff
changeset
|
319 env_put("PROCESS_PER_CONNECTION=1"); |
7814b29d0862
Created env_put() and env_clean() for a bit easier handling of environment
Timo Sirainen <tss@iki.fi>
parents:
666
diff
changeset
|
320 env_put("MAX_LOGGING_USERS=1"); |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
321 } else { |
697
7814b29d0862
Created env_put() and env_clean() for a bit easier handling of environment
Timo Sirainen <tss@iki.fi>
parents:
666
diff
changeset
|
322 env_put(t_strdup_printf("MAX_LOGGING_USERS=%d", |
7814b29d0862
Created env_put() and env_clean() for a bit easier handling of environment
Timo Sirainen <tss@iki.fi>
parents:
666
diff
changeset
|
323 set_max_logging_users)); |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
324 } |
0 | 325 |
722
0438621d25ff
Added virtual memory size limits to processes. Default values are pretty
Timo Sirainen <tss@iki.fi>
parents:
699
diff
changeset
|
326 restrict_process_size(set_login_process_size); |
0438621d25ff
Added virtual memory size limits to processes. Default values are pretty
Timo Sirainen <tss@iki.fi>
parents:
699
diff
changeset
|
327 |
801
86224ff16bf6
Drop root privileges earlier. Close syslog more later in imap-master when
Timo Sirainen <tss@iki.fi>
parents:
791
diff
changeset
|
328 /* make sure we don't leak syslog fd, but do it last so that |
86224ff16bf6
Drop root privileges earlier. Close syslog more later in imap-master when
Timo Sirainen <tss@iki.fi>
parents:
791
diff
changeset
|
329 any errors above will be logged */ |
86224ff16bf6
Drop root privileges earlier. Close syslog more later in imap-master when
Timo Sirainen <tss@iki.fi>
parents:
791
diff
changeset
|
330 closelog(); |
86224ff16bf6
Drop root privileges earlier. Close syslog more later in imap-master when
Timo Sirainen <tss@iki.fi>
parents:
791
diff
changeset
|
331 |
0 | 332 /* hide the path, it's ugly */ |
333 argv[0] = strrchr(set_login_executable, '/'); | |
334 if (argv[0] == NULL) argv[0] = set_login_executable; else argv[0]++; | |
335 | |
336 execv(set_login_executable, (char **) argv); | |
337 | |
801
86224ff16bf6
Drop root privileges earlier. Close syslog more later in imap-master when
Timo Sirainen <tss@iki.fi>
parents:
791
diff
changeset
|
338 i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m", argv[0]); |
0 | 339 return -1; |
340 } | |
341 | |
615
0d852af6842e
Master process generates DH/RSA parameters now and stores them into file
Timo Sirainen <tss@iki.fi>
parents:
614
diff
changeset
|
342 void login_process_abormal_exit(pid_t pid __attr_unused__) |
0d852af6842e
Master process generates DH/RSA parameters now and stores them into file
Timo Sirainen <tss@iki.fi>
parents:
614
diff
changeset
|
343 { |
0d852af6842e
Master process generates DH/RSA parameters now and stores them into file
Timo Sirainen <tss@iki.fi>
parents:
614
diff
changeset
|
344 /* don't start raising the process count if they're dying all |
0d852af6842e
Master process generates DH/RSA parameters now and stores them into file
Timo Sirainen <tss@iki.fi>
parents:
614
diff
changeset
|
345 the time */ |
0d852af6842e
Master process generates DH/RSA parameters now and stores them into file
Timo Sirainen <tss@iki.fi>
parents:
614
diff
changeset
|
346 wanted_processes_count = 0; |
0d852af6842e
Master process generates DH/RSA parameters now and stores them into file
Timo Sirainen <tss@iki.fi>
parents:
614
diff
changeset
|
347 } |
0d852af6842e
Master process generates DH/RSA parameters now and stores them into file
Timo Sirainen <tss@iki.fi>
parents:
614
diff
changeset
|
348 |
635
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
349 static void login_hash_destroy(void *key __attr_unused__, void *value, |
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
350 void *context __attr_unused__) |
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
351 { |
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
352 login_process_destroy(value); |
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
353 } |
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
354 |
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
355 void login_processes_destroy_all(void) |
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
356 { |
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
357 hash_foreach(processes, login_hash_destroy, NULL); |
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
358 |
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
359 /* don't double their amount when restarting */ |
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
360 wanted_processes_count = 0; |
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
361 } |
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
362 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
363 static void login_processes_start_missing(void *context __attr_unused__, |
0 | 364 Timeout timeout __attr_unused__) |
365 { | |
614
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
366 if (!set_login_process_per_connection) { |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
367 /* create max. one process every second, that way if it keeps |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
368 dying all the time we don't eat all cpu with fork()ing. */ |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
369 if (listening_processes < set_login_processes_count) |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
370 (void)create_login_process(); |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
371 } else { |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
372 /* we want to respond fast when multiple clients are connecting |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
373 at once, but we also want to prevent fork-bombing. use the |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
374 same method as apache: check once a second if we need new |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
375 processes. if yes and we've used all the existing processes, |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
376 double their amount (unless we've hit the high limit). |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
377 Then for each second that didn't use all existing processes, |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
378 drop the max. process count by one. */ |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
379 if (wanted_processes_count < set_login_processes_count) |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
380 wanted_processes_count = set_login_processes_count; |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
381 else if (listening_processes == 0) |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
382 wanted_processes_count *= 2; |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
383 else if (wanted_processes_count > set_login_processes_count) |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
384 wanted_processes_count--; |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
385 |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
386 if (wanted_processes_count > set_login_max_processes_count) |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
387 wanted_processes_count = set_login_max_processes_count; |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
388 |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
389 while (listening_processes < wanted_processes_count) |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
390 (void)create_login_process(); |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
391 } |
0 | 392 } |
393 | |
394 void login_processes_init(void) | |
395 { | |
396 auth_id_counter = 0; | |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
397 listening_processes = 0; |
614
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
398 wanted_processes_count = 0; |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
399 oldest_nonlisten_process = newest_nonlisten_process = NULL; |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
400 |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
401 processes = hash_create(default_pool, 128, NULL, NULL); |
0 | 402 to = timeout_add(1000, login_processes_start_missing, NULL); |
403 } | |
404 | |
405 void login_processes_deinit(void) | |
406 { | |
407 timeout_remove(to); | |
408 | |
635
90a65c017bf0
SIGHUP reloads now settings. Logged in clients are left untouched, but
Timo Sirainen <tss@iki.fi>
parents:
615
diff
changeset
|
409 login_processes_destroy_all(); |
0 | 410 hash_destroy(processes); |
411 } |