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 }