Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/master/login-process.c @ 801:86224ff16bf6 HEAD
Drop root privileges earlier. Close syslog more later in imap-master when
forking new processes, so that any errors get logged. Make sure that all
errors show up in log files - use specific exit status codes if we can't
write to log file. Make sure imap and login processes always drop root
privileges even if master process didn't ask for it for some reason.
putenv() wasn't verified to succeed - luckily we never allowed large user
given data there.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 18 Dec 2002 06:00:01 +0200 |
parents | 6efced4f80de |
children | 5ac361acb316 |
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 | |
82 (void)close(request->fd); | |
83 login_process_unref(process); | |
84 i_free(request); | |
85 } | |
86 | |
699
cc795d74d08f
Use more warnings with GCC by default. Fixed several warnings.
Timo Sirainen <tss@iki.fi>
parents:
697
diff
changeset
|
87 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
|
88 { |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
89 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
|
90 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
|
91 "notification"); |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
92 return; |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
93 } |
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 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
|
96 listening_processes--; |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
97 |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
98 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
|
99 |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
100 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
|
101 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
|
102 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
|
103 |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
104 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
|
105 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
|
106 } |
e60620644af3
login_process_per_connection = yes scales now better when multiple users are
Timo Sirainen <tss@iki.fi>
parents:
613
diff
changeset
|
107 |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
108 static void login_process_input(void *context, int fd __attr_unused__, |
0 | 109 IO io __attr_unused__) |
110 { | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
111 LoginProcess *p = context; |
0 | 112 AuthProcess *auth_process; |
113 LoginAuthRequest *authreq; | |
114 MasterRequest req; | |
115 int client_fd, ret; | |
116 | |
117 ret = fd_read(p->fd, &req, sizeof(req), &client_fd); | |
118 if (ret != sizeof(req)) { | |
119 if (ret == 0) { | |
120 /* disconnected, ie. the login process died */ | |
121 } else if (ret > 0) { | |
122 /* req wasn't fully read */ | |
123 i_error("login: fd_read() couldn't read all req"); | |
124 } else { | |
125 i_error("login: fd_read() failed: %m"); | |
126 } | |
127 | |
128 login_process_destroy(p); | |
129 return; | |
130 } | |
131 | |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
132 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
|
133 /* 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
|
134 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
|
135 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
|
136 return; |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
137 } |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
138 |
0 | 139 /* login process isn't trusted, validate all data to make sure |
140 it's not trying to exploit us */ | |
141 if (!VALIDATE_STR(req.login_tag)) { | |
142 i_error("login: Received corrupted data"); | |
143 login_process_destroy(p); | |
144 return; | |
145 } | |
146 | |
147 /* ask the cookie from the auth process */ | |
148 authreq = i_new(LoginAuthRequest, 1); | |
149 p->refcount++; | |
150 authreq->process = p; | |
151 authreq->login_id = req.id; | |
152 authreq->auth_id = ++auth_id_counter; | |
153 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
|
154 memcpy(&authreq->ip, &req.ip, sizeof(IPADDR)); |
0 | 155 strcpy(authreq->login_tag, req.login_tag); |
156 | |
157 auth_process = auth_process_find(req.auth_process); | |
158 if (auth_process == NULL) { | |
159 i_error("login: Authentication process %u doesn't exist", | |
160 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
|
161 auth_callback(NULL, authreq); |
0 | 162 } else { |
163 auth_process_request(auth_process, authreq->auth_id, req.cookie, | |
164 auth_callback, authreq); | |
165 } | |
166 } | |
167 | |
168 static LoginProcess *login_process_new(pid_t pid, int fd) | |
169 { | |
170 LoginProcess *p; | |
171 | |
172 PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_LOGIN); | |
173 | |
174 p = i_new(LoginProcess, 1); | |
175 p->refcount = 1; | |
176 p->pid = pid; | |
177 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
|
178 p->listening = TRUE; |
0 | 179 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
|
180 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
|
181 sizeof(MasterReply)*10, |
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
182 IO_PRIORITY_DEFAULT, FALSE); |
0 | 183 |
195
db6e288be0e9
Replaced INT_TO_POINTER and POINTER_TO_INT macros with POINTER_CAST and
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
184 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
|
185 listening_processes++; |
0 | 186 return p; |
187 } | |
188 | |
699
cc795d74d08f
Use more warnings with GCC by default. Fixed several warnings.
Timo Sirainen <tss@iki.fi>
parents:
697
diff
changeset
|
189 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
|
190 { |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
191 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
|
192 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
|
193 else |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
194 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
|
195 |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
196 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
|
197 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
|
198 else |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
199 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
|
200 |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
201 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
|
202 } |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
203 |
0 | 204 static void login_process_destroy(LoginProcess *p) |
205 { | |
206 if (p->destroyed) | |
207 return; | |
208 p->destroyed = TRUE; | |
209 | |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
210 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
|
211 listening_processes--; |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
212 |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
747
diff
changeset
|
213 o_stream_close(p->output); |
0 | 214 io_remove(p->io); |
215 (void)close(p->fd); | |
216 | |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
217 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
|
218 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
|
219 |
195
db6e288be0e9
Replaced INT_TO_POINTER and POINTER_TO_INT macros with POINTER_CAST and
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
220 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
|
221 |
0 | 222 login_process_unref(p); |
223 } | |
224 | |
225 static void login_process_unref(LoginProcess *p) | |
226 { | |
227 if (--p->refcount > 0) | |
228 return; | |
229 | |
764
f57c52738f90
Renamed IBuffer and OBuffer to IStream and OStream which describes their
Timo Sirainen <tss@iki.fi>
parents:
747
diff
changeset
|
230 o_stream_unref(p->output); |
0 | 231 i_free(p); |
232 } | |
233 | |
234 static pid_t create_login_process(void) | |
235 { | |
699
cc795d74d08f
Use more warnings with GCC by default. Fixed several warnings.
Timo Sirainen <tss@iki.fi>
parents:
697
diff
changeset
|
236 static char *argv[] = { NULL, NULL }; |
0 | 237 pid_t pid; |
238 int fd[2]; | |
239 | |
613
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
240 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
|
241 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
|
242 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
|
243 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
|
244 } |
1906116a62ce
Finally support for handling each login connection in it's own process.
Timo Sirainen <tss@iki.fi>
parents:
596
diff
changeset
|
245 |
0 | 246 if (set_login_uid == 0) |
247 i_fatal("Login process must not run as root"); | |
248 | |
249 /* create communication to process with a socket pair */ | |
250 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) { | |
251 i_error("socketpair() failed: %m"); | |
252 return -1; | |
253 } | |
254 | |
255 pid = fork(); | |
256 if (pid < 0) { | |
257 (void)close(fd[0]); | |
258 (void)close(fd[1]); | |
259 i_error("fork() failed: %m"); | |
260 return -1; | |
261 } | |
262 | |
263 if (pid != 0) { | |
264 /* 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
|
265 fd_close_on_exec(fd[0], TRUE); |
0 | 266 login_process_new(pid, fd[0]); |
267 (void)close(fd[1]); | |
268 return pid; | |
269 } | |
270 | |
271 /* move communication handle */ | |
272 if (dup2(fd[1], LOGIN_MASTER_SOCKET_FD) < 0) | |
273 i_fatal("login: dup2() 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
|
274 fd_close_on_exec(LOGIN_MASTER_SOCKET_FD, FALSE); |
0 | 275 |
276 /* move the listen handle */ | |
277 if (dup2(imap_fd, LOGIN_IMAP_LISTEN_FD) < 0) | |
278 i_fatal("login: dup2() 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
|
279 fd_close_on_exec(LOGIN_IMAP_LISTEN_FD, FALSE); |
0 | 280 |
281 /* move the SSL listen handle */ | |
282 if (dup2(imaps_fd, LOGIN_IMAPS_LISTEN_FD) < 0) | |
283 i_fatal("login: dup2() 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
|
284 fd_close_on_exec(LOGIN_IMAPS_LISTEN_FD, FALSE); |
0 | 285 |
286 /* imap_fd and imaps_fd are closed by clean_child_process() */ | |
287 | |
288 (void)close(fd[0]); | |
289 (void)close(fd[1]); | |
290 | |
291 clean_child_process(); | |
292 | |
293 /* setup access environment - needs to be done after | |
294 clean_child_process() since it clears environment */ | |
295 restrict_access_set_env(set_login_user, set_login_uid, set_login_gid, | |
296 set_login_chroot ? set_login_dir : NULL); | |
297 | |
298 if (!set_login_chroot) { | |
299 /* no chrooting, but still change to the directory */ | |
300 if (chdir(set_login_dir) < 0) { | |
301 i_fatal("chdir(%s) failed: %m", | |
302 set_login_dir); | |
303 } | |
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 } |