Mercurial > hg > nginx-quic
comparison src/imap/ngx_imap_auth_http_module.c @ 521:6f00349b98e5 release-0.1.35
nginx-0.1.35-RELEASE import
*) Feature: the "working_directory" directive.
*) Feature: the "port_in_redirect" directive.
*) Bugfix: the segmentation fault was occurred if the backend response
header was in several packets; the bug had appeared in 0.1.29.
*) Bugfix: if more than 10 servers were configured or some server did
not use the "listen" directive, then the segmentation fault was
occurred on the start.
*) Bugfix: the segmentation fault might occur if the response was
bigger than the temporary file.
*) Bugfix: nginx returned the 400 response on requests like
"GET http://www.domain.com/uri HTTP/1.0"; the bug had appeared in
0.1.28.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 07 Jun 2005 15:56:31 +0000 |
parents | |
children | 09b42134ac0c |
comparison
equal
deleted
inserted
replaced
520:1fecc7e0d717 | 521:6f00349b98e5 |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_event.h> | |
10 #include <ngx_event_connect.h> | |
11 #include <ngx_imap.h> | |
12 | |
13 | |
14 typedef struct { | |
15 ngx_peers_t *peers; | |
16 | |
17 ngx_msec_t timeout; | |
18 | |
19 ngx_str_t host_header; | |
20 ngx_str_t uri; | |
21 } ngx_imap_auth_http_conf_t; | |
22 | |
23 | |
24 typedef struct { | |
25 ngx_buf_t *request; | |
26 ngx_peer_connection_t peer; | |
27 } ngx_imap_auth_http_ctx_t; | |
28 | |
29 | |
30 static void ngx_imap_auth_http_write_handler(ngx_event_t *wev); | |
31 static void ngx_imap_auth_http_read_handler(ngx_event_t *rev); | |
32 static void ngx_imap_auth_http_block_read(ngx_event_t *rev); | |
33 static void ngx_imap_auth_http_dummy_handler(ngx_event_t *ev); | |
34 static ngx_buf_t *ngx_imap_auth_http_create_request(ngx_imap_session_t *s, | |
35 ngx_imap_auth_http_conf_t *ahcf); | |
36 | |
37 static void *ngx_imap_auth_http_create_conf(ngx_conf_t *cf); | |
38 static char *ngx_imap_auth_http_merge_conf(ngx_conf_t *cf, void *parent, | |
39 void *child); | |
40 static char *ngx_imap_auth_http(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | |
41 | |
42 | |
43 static ngx_command_t ngx_imap_auth_http_commands[] = { | |
44 | |
45 { ngx_string("auth_http"), | |
46 NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1, | |
47 ngx_imap_auth_http, | |
48 NGX_IMAP_SRV_CONF_OFFSET, | |
49 0, | |
50 NULL }, | |
51 | |
52 { ngx_string("auth_http_timeout"), | |
53 NGX_IMAP_MAIN_CONF|NGX_IMAP_SRV_CONF|NGX_CONF_TAKE1, | |
54 ngx_conf_set_msec_slot, | |
55 NGX_IMAP_SRV_CONF_OFFSET, | |
56 offsetof(ngx_imap_auth_http_conf_t, timeout), | |
57 NULL }, | |
58 | |
59 ngx_null_command | |
60 }; | |
61 | |
62 | |
63 static ngx_imap_module_t ngx_imap_auth_http_module_ctx = { | |
64 NULL, /* create main configuration */ | |
65 NULL, /* init main configuration */ | |
66 | |
67 ngx_imap_auth_http_create_conf, /* create server configuration */ | |
68 ngx_imap_auth_http_merge_conf /* merge server configuration */ | |
69 }; | |
70 | |
71 | |
72 ngx_module_t ngx_imap_auth_http_module = { | |
73 NGX_MODULE_V1, | |
74 &ngx_imap_auth_http_module_ctx, /* module context */ | |
75 ngx_imap_auth_http_commands, /* module directives */ | |
76 NGX_IMAP_MODULE, /* module type */ | |
77 NULL, /* init module */ | |
78 NULL /* init process */ | |
79 }; | |
80 | |
81 | |
82 static char *ngx_imap_auth_http_protocol[] = { "pop3", "imap" }; | |
83 | |
84 | |
85 void | |
86 ngx_imap_auth_http_init(ngx_imap_session_t *s) | |
87 { | |
88 ngx_int_t rc; | |
89 ngx_imap_auth_http_ctx_t *ctx; | |
90 ngx_imap_auth_http_conf_t *ahcf; | |
91 | |
92 ctx = ngx_pcalloc(s->connection->pool, sizeof(ngx_imap_auth_http_ctx_t)); | |
93 if (ctx == NULL) { | |
94 ngx_imap_close_connection(s->connection); | |
95 return; | |
96 } | |
97 | |
98 ahcf = ngx_imap_get_module_srv_conf(s, ngx_imap_auth_http_module); | |
99 | |
100 ctx->request = ngx_imap_auth_http_create_request(s, ahcf); | |
101 if (ctx->request == NULL) { | |
102 ngx_imap_close_connection(s->connection); | |
103 return; | |
104 } | |
105 | |
106 ngx_imap_set_ctx(s, ctx, ngx_imap_auth_http_module); | |
107 | |
108 ctx->peer.peers = ahcf->peers; | |
109 ctx->peer.log = s->connection->log; | |
110 ctx->peer.log_error = NGX_ERROR_ERR; | |
111 | |
112 rc = ngx_event_connect_peer(&ctx->peer); | |
113 | |
114 if (rc == NGX_ERROR) { | |
115 ngx_imap_close_connection(s->connection); | |
116 return; | |
117 } | |
118 | |
119 ctx->peer.connection->data = s; | |
120 ctx->peer.connection->pool = s->connection->pool; | |
121 | |
122 s->connection->read->handler = ngx_imap_auth_http_block_read; | |
123 ctx->peer.connection->read->handler = ngx_imap_auth_http_read_handler; | |
124 ctx->peer.connection->write->handler = ngx_imap_auth_http_write_handler; | |
125 | |
126 if (rc == NGX_OK) { | |
127 ngx_imap_auth_http_write_handler(ctx->peer.connection->write); | |
128 return; | |
129 } | |
130 | |
131 ngx_add_timer(ctx->peer.connection->read, ahcf->timeout); | |
132 ngx_add_timer(ctx->peer.connection->write, ahcf->timeout); | |
133 } | |
134 | |
135 | |
136 static void | |
137 ngx_imap_auth_http_write_handler(ngx_event_t *wev) | |
138 { | |
139 ssize_t n, size; | |
140 ngx_connection_t *c; | |
141 ngx_imap_session_t *s; | |
142 ngx_imap_auth_http_ctx_t *ctx; | |
143 ngx_imap_auth_http_conf_t *ahcf; | |
144 | |
145 c = wev->data; | |
146 s = c->data; | |
147 | |
148 ctx = ngx_imap_get_module_ctx(s, ngx_imap_auth_http_module); | |
149 | |
150 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, wev->log, 0, | |
151 "imap auth http write handler"); | |
152 | |
153 if (wev->timedout) { | |
154 ngx_log_error(NGX_LOG_ERR, wev->log, NGX_ETIMEDOUT, | |
155 "auth http server timed out"); | |
156 ngx_imap_close_connection(ctx->peer.connection); | |
157 ngx_imap_close_connection(s->connection); | |
158 return; | |
159 } | |
160 | |
161 size = ctx->request->last - ctx->request->pos; | |
162 | |
163 n = ngx_send(c, ctx->request->pos, size); | |
164 | |
165 if (n == NGX_ERROR) { | |
166 ngx_imap_close_connection(ctx->peer.connection); | |
167 ngx_imap_close_connection(s->connection); | |
168 return; | |
169 } | |
170 | |
171 if (n > 0) { | |
172 ctx->request->pos += n; | |
173 | |
174 if (n == size) { | |
175 wev->handler = ngx_imap_auth_http_dummy_handler; | |
176 | |
177 if (wev->timer_set) { | |
178 ngx_del_timer(wev); | |
179 } | |
180 | |
181 return; | |
182 } | |
183 } | |
184 | |
185 if (!wev->timer_set) { | |
186 ahcf = ngx_imap_get_module_srv_conf(s, ngx_imap_auth_http_module); | |
187 ngx_add_timer(wev, ahcf->timeout); | |
188 } | |
189 } | |
190 | |
191 | |
192 static void | |
193 ngx_imap_auth_http_read_handler(ngx_event_t *rev) | |
194 { | |
195 ngx_peers_t *peers; | |
196 ngx_connection_t *c; | |
197 ngx_imap_session_t *s; | |
198 #if 0 | |
199 ngx_imap_auth_http_ctx_t *ctx; | |
200 #endif | |
201 | |
202 c = rev->data; | |
203 s = c->data; | |
204 | |
205 #if 0 | |
206 ctx = ngx_imap_get_module_ctx(s, ngx_imap_auth_http_module); | |
207 #endif | |
208 | |
209 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0, | |
210 "imap auth http read handler"); | |
211 | |
212 peers = NULL; | |
213 | |
214 ngx_imap_proxy_init(s, peers); | |
215 } | |
216 | |
217 | |
218 static void | |
219 ngx_imap_auth_http_block_read(ngx_event_t *rev) | |
220 { | |
221 ngx_connection_t *c; | |
222 ngx_imap_session_t *s; | |
223 ngx_imap_auth_http_ctx_t *ctx; | |
224 | |
225 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, rev->log, 0, | |
226 "imap auth http block read"); | |
227 | |
228 if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { | |
229 c = rev->data; | |
230 s = c->data; | |
231 | |
232 ctx = ngx_imap_get_module_ctx(s, ngx_imap_auth_http_module); | |
233 | |
234 ngx_imap_close_connection(ctx->peer.connection); | |
235 ngx_imap_close_connection(s->connection); | |
236 } | |
237 } | |
238 | |
239 | |
240 static void | |
241 ngx_imap_auth_http_dummy_handler(ngx_event_t *ev) | |
242 { | |
243 ngx_log_debug0(NGX_LOG_DEBUG_IMAP, ev->log, 0, | |
244 "imap auth http dummy handler"); | |
245 } | |
246 | |
247 | |
248 static ngx_buf_t * | |
249 ngx_imap_auth_http_create_request(ngx_imap_session_t *s, | |
250 ngx_imap_auth_http_conf_t *ahcf) | |
251 { | |
252 size_t len; | |
253 ngx_buf_t *b; | |
254 | |
255 len = sizeof("GET ") - 1 + ahcf->uri.len + sizeof(" HTTP/1.0" CRLF) - 1 | |
256 + sizeof("Host: ") - 1 + ahcf->host_header.len + sizeof(CRLF) - 1 | |
257 + sizeof("Auth-Method: plain" CRLF) - 1 | |
258 + sizeof("Auth-User: ") - 1 + s->login.len + sizeof(CRLF) - 1 | |
259 + sizeof("Auth-Pass: ") - 1 + s->passwd.len + sizeof(CRLF) - 1 | |
260 + sizeof("Auth-Protocol: imap" CRLF) - 1 | |
261 + sizeof("Client-IP: ") - 1 + s->connection->addr_text.len | |
262 + sizeof(CRLF) - 1 | |
263 + sizeof(CRLF) - 1; | |
264 | |
265 b = ngx_create_temp_buf(s->connection->pool, len); | |
266 if (b == NULL) { | |
267 return NULL; | |
268 } | |
269 | |
270 b->last = ngx_cpymem(b->last, "GET ", sizeof("GET ") - 1); | |
271 b->last = ngx_cpymem(b->last, ahcf->uri.data, ahcf->uri.len); | |
272 b->last = ngx_cpymem(b->last, " HTTP/1.0" CRLF, | |
273 sizeof(" HTTP/1.0" CRLF) - 1); | |
274 | |
275 b->last = ngx_cpymem(b->last, "Host: ", sizeof("Host: ") - 1); | |
276 b->last = ngx_cpymem(b->last, ahcf->host_header.data, | |
277 ahcf->host_header.len); | |
278 *b->last++ = CR; *b->last++ = LF; | |
279 | |
280 b->last = ngx_cpymem(b->last, "Auth-Method: plain" CRLF, | |
281 sizeof("Auth-Method: plain" CRLF) - 1); | |
282 | |
283 b->last = ngx_cpymem(b->last, "Auth-User: ", sizeof("Auth-User: ") - 1); | |
284 b->last = ngx_cpymem(b->last, s->login.data, s->login.len); | |
285 *b->last++ = CR; *b->last++ = LF; | |
286 | |
287 b->last = ngx_cpymem(b->last, "Auth-Pass: ", sizeof("Auth-Pass: ") - 1); | |
288 b->last = ngx_cpymem(b->last, s->passwd.data, s->passwd.len); | |
289 *b->last++ = CR; *b->last++ = LF; | |
290 | |
291 b->last = ngx_cpymem(b->last, "Auth-Protocol: ", | |
292 sizeof("Auth-Protocol: ") - 1); | |
293 b->last = ngx_cpymem(b->last, ngx_imap_auth_http_protocol[s->protocol], | |
294 sizeof("imap") - 1); | |
295 *b->last++ = CR; *b->last++ = LF; | |
296 | |
297 b->last = ngx_cpymem(b->last, "Client-IP: ", sizeof("Client-IP: ") - 1); | |
298 b->last = ngx_cpymem(b->last, s->connection->addr_text.data, | |
299 s->connection->addr_text.len); | |
300 *b->last++ = CR; *b->last++ = LF; | |
301 | |
302 /* add "\r\n" at the header end */ | |
303 *b->last++ = CR; *b->last++ = LF; | |
304 | |
305 #if (NGX_DEBUG) | |
306 { | |
307 ngx_str_t l; | |
308 | |
309 l.len = b->last - b->pos; | |
310 l.data = b->pos; | |
311 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, s->connection->log, 0, | |
312 "imap auth http header:\n\"%V\"", &l); | |
313 } | |
314 #endif | |
315 | |
316 return b; | |
317 } | |
318 | |
319 | |
320 static void * | |
321 ngx_imap_auth_http_create_conf(ngx_conf_t *cf) | |
322 { | |
323 ngx_imap_auth_http_conf_t *ahcf; | |
324 | |
325 ahcf = ngx_pcalloc(cf->pool, sizeof(ngx_imap_auth_http_conf_t)); | |
326 if (ahcf == NULL) { | |
327 return NGX_CONF_ERROR; | |
328 } | |
329 | |
330 ahcf->timeout = NGX_CONF_UNSET_MSEC; | |
331 | |
332 return ahcf; | |
333 } | |
334 | |
335 | |
336 static char * | |
337 ngx_imap_auth_http_merge_conf(ngx_conf_t *cf, void *parent, void *child) | |
338 { | |
339 ngx_imap_auth_http_conf_t *prev = parent; | |
340 ngx_imap_auth_http_conf_t *conf = child; | |
341 | |
342 if (conf->peers == NULL) { | |
343 conf->peers = prev->peers; | |
344 conf->host_header = prev->host_header; | |
345 conf->uri = prev->uri; | |
346 } | |
347 | |
348 ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); | |
349 | |
350 return NGX_CONF_OK; | |
351 } | |
352 | |
353 | |
354 static char * | |
355 ngx_imap_auth_http(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
356 { | |
357 ngx_imap_auth_http_conf_t *ahcf = conf; | |
358 | |
359 ngx_uint_t i; | |
360 ngx_str_t *value, *url; | |
361 ngx_inet_upstream_t inet_upstream; | |
362 #if (NGX_HAVE_UNIX_DOMAIN) | |
363 ngx_unix_domain_upstream_t unix_upstream; | |
364 #endif | |
365 | |
366 value = cf->args->elts; | |
367 | |
368 url = &value[1]; | |
369 | |
370 if (ngx_strncasecmp(url->data, "unix:", 5) == 0) { | |
371 | |
372 #if (NGX_HAVE_UNIX_DOMAIN) | |
373 | |
374 ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t)); | |
375 | |
376 unix_upstream.name = *url; | |
377 unix_upstream.url = *url; | |
378 unix_upstream.uri_part = 1; | |
379 | |
380 ahcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream); | |
381 if (ahcf->peers == NULL) { | |
382 return NGX_CONF_ERROR; | |
383 } | |
384 | |
385 ahcf->peers->peer[0].uri_separator = ":"; | |
386 | |
387 ahcf->host_header.len = sizeof("localhost") - 1; | |
388 ahcf->host_header.data = (u_char *) "localhost"; | |
389 ahcf->uri = unix_upstream.uri; | |
390 | |
391 #else | |
392 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
393 "the unix domain sockets are not supported " | |
394 "on this platform"); | |
395 return NGX_CONF_ERROR; | |
396 | |
397 #endif | |
398 | |
399 } else { | |
400 ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t)); | |
401 | |
402 inet_upstream.name = *url; | |
403 inet_upstream.url = *url; | |
404 inet_upstream.default_port_value = 80; | |
405 inet_upstream.uri_part = 1; | |
406 | |
407 ahcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream); | |
408 if (ahcf->peers == NULL) { | |
409 return NGX_CONF_ERROR; | |
410 } | |
411 | |
412 for (i = 0; i < ahcf->peers->number; i++) { | |
413 ahcf->peers->peer[i].uri_separator = ":"; | |
414 } | |
415 | |
416 ahcf->host_header = inet_upstream.host_header; | |
417 ahcf->uri = inet_upstream.uri; | |
418 } | |
419 | |
420 return NGX_CONF_OK; | |
421 } |