Mercurial > dovecot > original-hg > dovecot-1.2
annotate src/master/login-process.c @ 596:ab3590c3a7d9 HEAD
Added verbose_proctitle setting: Show more verbose process titles (in ps).
Currently shows user name and IP address. Useful for seeing who are actually
using the IMAP processes (eg. shared mailboxes or if same uid is used for
multiple accounts).
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 06 Nov 2002 16:20:50 +0200 |
parents | 3b53dd1280c6 |
children | 1906116a62ce |
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" |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
6 #include "obuffer.h" |
0 | 7 #include "fdpass.h" |
8 #include "restrict-access.h" | |
9 #include "login-process.h" | |
10 #include "auth-process.h" | |
11 #include "master-interface.h" | |
12 | |
13 #include <stdlib.h> | |
14 #include <unistd.h> | |
15 #include <syslog.h> | |
16 | |
17 typedef struct { | |
18 int refcount; | |
19 | |
20 pid_t pid; | |
21 int fd; | |
22 IO io; | |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
23 OBuffer *outbuf; |
0 | 24 unsigned int destroyed:1; |
25 } LoginProcess; | |
26 | |
27 typedef struct { | |
28 LoginProcess *process; | |
29 int login_id; | |
30 int auth_id; | |
31 int fd; | |
32 | |
596
ab3590c3a7d9
Added verbose_proctitle setting: Show more verbose process titles (in ps).
Timo Sirainen <tss@iki.fi>
parents:
532
diff
changeset
|
33 IPADDR ip; |
0 | 34 char login_tag[LOGIN_TAG_SIZE]; |
35 } LoginAuthRequest; | |
36 | |
37 static int auth_id_counter; | |
38 static Timeout to; | |
39 static HashTable *processes = NULL; | |
40 | |
41 static void login_process_destroy(LoginProcess *p); | |
42 static void login_process_unref(LoginProcess *p); | |
43 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
44 static void auth_callback(AuthCookieReplyData *cookie_reply, void *context) |
0 | 45 { |
46 const char *env[] = { | |
47 "MAIL", NULL, | |
48 "LOGIN_TAG", NULL, | |
49 NULL | |
50 }; | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
51 LoginAuthRequest *request = context; |
0 | 52 LoginProcess *process; |
53 MasterReply reply; | |
54 | |
55 env[1] = cookie_reply->mail; | |
56 env[3] = request->login_tag; | |
57 | |
58 if (cookie_reply == NULL || !cookie_reply->success) | |
59 reply.result = MASTER_RESULT_FAILURE; | |
60 else { | |
61 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
|
62 &request->ip, |
0 | 63 cookie_reply->user, |
64 cookie_reply->uid, | |
65 cookie_reply->gid, | |
66 cookie_reply->home, | |
67 cookie_reply->chroot, env); | |
68 } | |
69 | |
70 /* reply to login */ | |
71 reply.id = request->login_id; | |
72 | |
73 process = request->process; | |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
74 if (o_buffer_send(process->outbuf, &reply, sizeof(reply)) < 0) |
0 | 75 login_process_destroy(process); |
76 | |
77 (void)close(request->fd); | |
78 login_process_unref(process); | |
79 i_free(request); | |
80 } | |
81 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
82 static void login_process_input(void *context, int fd __attr_unused__, |
0 | 83 IO io __attr_unused__) |
84 { | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
85 LoginProcess *p = context; |
0 | 86 AuthProcess *auth_process; |
87 LoginAuthRequest *authreq; | |
88 MasterRequest req; | |
89 int client_fd, ret; | |
90 | |
91 ret = fd_read(p->fd, &req, sizeof(req), &client_fd); | |
92 if (ret != sizeof(req)) { | |
93 if (ret == 0) { | |
94 /* disconnected, ie. the login process died */ | |
95 } else if (ret > 0) { | |
96 /* req wasn't fully read */ | |
97 i_error("login: fd_read() couldn't read all req"); | |
98 } else { | |
99 i_error("login: fd_read() failed: %m"); | |
100 } | |
101 | |
102 login_process_destroy(p); | |
103 return; | |
104 } | |
105 | |
106 /* login process isn't trusted, validate all data to make sure | |
107 it's not trying to exploit us */ | |
108 if (!VALIDATE_STR(req.login_tag)) { | |
109 i_error("login: Received corrupted data"); | |
110 login_process_destroy(p); | |
111 return; | |
112 } | |
113 | |
114 /* ask the cookie from the auth process */ | |
115 authreq = i_new(LoginAuthRequest, 1); | |
116 p->refcount++; | |
117 authreq->process = p; | |
118 authreq->login_id = req.id; | |
119 authreq->auth_id = ++auth_id_counter; | |
120 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
|
121 memcpy(&authreq->ip, &req.ip, sizeof(IPADDR)); |
0 | 122 strcpy(authreq->login_tag, req.login_tag); |
123 | |
124 auth_process = auth_process_find(req.auth_process); | |
125 if (auth_process == NULL) { | |
126 i_error("login: Authentication process %u doesn't exist", | |
127 req.auth_process); | |
128 auth_callback(NULL, &authreq); | |
129 } else { | |
130 auth_process_request(auth_process, authreq->auth_id, req.cookie, | |
131 auth_callback, authreq); | |
132 } | |
133 } | |
134 | |
135 static LoginProcess *login_process_new(pid_t pid, int fd) | |
136 { | |
137 LoginProcess *p; | |
138 | |
139 PID_ADD_PROCESS_TYPE(pid, PROCESS_TYPE_LOGIN); | |
140 | |
141 p = i_new(LoginProcess, 1); | |
142 p->refcount = 1; | |
143 p->pid = pid; | |
144 p->fd = fd; | |
145 p->io = io_add(fd, IO_READ, login_process_input, p); | |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
146 p->outbuf = o_buffer_create_file(fd, default_pool, |
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
147 sizeof(MasterReply)*10, |
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
148 IO_PRIORITY_DEFAULT, FALSE); |
0 | 149 |
195
db6e288be0e9
Replaced INT_TO_POINTER and POINTER_TO_INT macros with POINTER_CAST and
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
150 hash_insert(processes, POINTER_CAST(pid), p); |
0 | 151 return p; |
152 } | |
153 | |
154 static void login_process_destroy(LoginProcess *p) | |
155 { | |
156 if (p->destroyed) | |
157 return; | |
158 p->destroyed = TRUE; | |
159 | |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
160 o_buffer_close(p->outbuf); |
0 | 161 io_remove(p->io); |
162 (void)close(p->fd); | |
163 | |
195
db6e288be0e9
Replaced INT_TO_POINTER and POINTER_TO_INT macros with POINTER_CAST and
Timo Sirainen <tss@iki.fi>
parents:
10
diff
changeset
|
164 hash_remove(processes, POINTER_CAST(p->pid)); |
0 | 165 login_process_unref(p); |
166 } | |
167 | |
168 static void login_process_unref(LoginProcess *p) | |
169 { | |
170 if (--p->refcount > 0) | |
171 return; | |
172 | |
410
1f0e7229ee58
Split IOBuffer into mmaped IBuffer, file IBuffer, memory data IBuffer and
Timo Sirainen <tss@iki.fi>
parents:
364
diff
changeset
|
173 o_buffer_unref(p->outbuf); |
0 | 174 i_free(p); |
175 } | |
176 | |
177 static pid_t create_login_process(void) | |
178 { | |
179 static const char *argv[] = { NULL, NULL }; | |
180 pid_t pid; | |
181 int fd[2]; | |
182 | |
183 if (set_login_uid == 0) | |
184 i_fatal("Login process must not run as root"); | |
185 | |
186 /* create communication to process with a socket pair */ | |
187 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) { | |
188 i_error("socketpair() failed: %m"); | |
189 return -1; | |
190 } | |
191 | |
192 pid = fork(); | |
193 if (pid < 0) { | |
194 (void)close(fd[0]); | |
195 (void)close(fd[1]); | |
196 i_error("fork() failed: %m"); | |
197 return -1; | |
198 } | |
199 | |
200 if (pid != 0) { | |
201 /* master */ | |
202 login_process_new(pid, fd[0]); | |
203 (void)close(fd[1]); | |
204 return pid; | |
205 } | |
206 | |
207 /* move communication handle */ | |
208 if (dup2(fd[1], LOGIN_MASTER_SOCKET_FD) < 0) | |
209 i_fatal("login: dup2() failed: %m"); | |
210 | |
211 /* move the listen handle */ | |
212 if (dup2(imap_fd, LOGIN_IMAP_LISTEN_FD) < 0) | |
213 i_fatal("login: dup2() failed: %m"); | |
214 | |
215 /* move the SSL listen handle */ | |
216 if (dup2(imaps_fd, LOGIN_IMAPS_LISTEN_FD) < 0) | |
217 i_fatal("login: dup2() failed: %m"); | |
218 | |
219 /* imap_fd and imaps_fd are closed by clean_child_process() */ | |
220 | |
221 (void)close(fd[0]); | |
222 (void)close(fd[1]); | |
223 | |
224 clean_child_process(); | |
225 | |
226 /* setup access environment - needs to be done after | |
227 clean_child_process() since it clears environment */ | |
228 restrict_access_set_env(set_login_user, set_login_uid, set_login_gid, | |
229 set_login_chroot ? set_login_dir : NULL); | |
230 | |
231 if (!set_login_chroot) { | |
232 /* no chrooting, but still change to the directory */ | |
233 if (chdir(set_login_dir) < 0) { | |
234 i_fatal("chdir(%s) failed: %m", | |
235 set_login_dir); | |
236 } | |
237 } | |
238 | |
239 if (set_ssl_cert_file != NULL) { | |
240 putenv((char *) t_strconcat("SSL_CERT_FILE=", | |
241 set_ssl_cert_file, NULL)); | |
242 } | |
243 | |
244 if (set_ssl_key_file != NULL) { | |
245 putenv((char *) t_strconcat("SSL_KEY_FILE=", | |
246 set_ssl_key_file, NULL)); | |
247 } | |
248 | |
249 if (set_disable_plaintext_auth) | |
250 putenv("DISABLE_PLAINTEXT_AUTH=1"); | |
251 | |
252 putenv((char *) t_strdup_printf("MAX_LOGGING_USERS=%d", | |
253 set_max_logging_users)); | |
254 | |
255 /* hide the path, it's ugly */ | |
256 argv[0] = strrchr(set_login_executable, '/'); | |
257 if (argv[0] == NULL) argv[0] = set_login_executable; else argv[0]++; | |
258 | |
259 execv(set_login_executable, (char **) argv); | |
260 | |
261 i_fatal("execv(%s) failed: %m", argv[0]); | |
262 return -1; | |
263 } | |
264 | |
265 static void login_hash_cleanup(void *key __attr_unused__, void *value, | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
266 void *context __attr_unused__) |
0 | 267 { |
268 LoginProcess *p = value; | |
269 | |
270 (void)close(p->fd); | |
271 } | |
272 | |
273 void login_processes_cleanup(void) | |
274 { | |
275 hash_foreach(processes, login_hash_cleanup, NULL); | |
276 } | |
277 | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
278 static void login_processes_start_missing(void *context __attr_unused__, |
0 | 279 Timeout timeout __attr_unused__) |
280 { | |
281 /* create max. one process every second, that way if it keeps | |
282 dying all the time we don't eat all cpu with fork()ing. */ | |
283 if (hash_size(processes) < set_login_processes_count) | |
284 (void)create_login_process(); | |
285 } | |
286 | |
287 void login_processes_init(void) | |
288 { | |
289 auth_id_counter = 0; | |
290 processes = hash_create(default_pool, 128, NULL, NULL); | |
291 to = timeout_add(1000, login_processes_start_missing, NULL); | |
292 } | |
293 | |
294 static void login_hash_destroy(void *key __attr_unused__, void *value, | |
10
82b7de533f98
s/user_data/context/ and some s/Data/Context/
Timo Sirainen <tss@iki.fi>
parents:
0
diff
changeset
|
295 void *context __attr_unused__) |
0 | 296 { |
297 login_process_destroy(value); | |
298 } | |
299 | |
300 void login_processes_deinit(void) | |
301 { | |
302 timeout_remove(to); | |
303 | |
304 hash_foreach(processes, login_hash_destroy, NULL); | |
305 hash_destroy(processes); | |
306 } |