Mercurial > hg > nginx
comparison src/http/modules/ngx_http_userid_handler.c @ 408:d6e2b445c1b8
nginx-0.0.10-2004-08-27-19:40:59 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Fri, 27 Aug 2004 15:40:59 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
407:35fe251cd231 | 408:d6e2b445c1b8 |
---|---|
1 | |
2 #include <ngx_config.h> | |
3 #include <ngx_core.h> | |
4 #include <ngx_http.h> | |
5 | |
6 | |
7 #define NGX_HTTP_USERID_OFF 0x0002 | |
8 #define NGX_HTTP_USERID_ON 0x0004 | |
9 #define NGX_HTTP_USERID_LOGONLY 0x0008 | |
10 #define NGX_HTTP_USERID_TIME 0x0010 | |
11 | |
12 | |
13 typedef struct { | |
14 ngx_flag_t enable; | |
15 | |
16 ngx_int_t version; | |
17 ngx_int_t service; | |
18 | |
19 ngx_str_t name; | |
20 ngx_str_t domain; | |
21 ngx_str_t path; | |
22 time_t expires; | |
23 | |
24 ngx_int_t p3p; | |
25 ngx_str_t p3p_string; | |
26 } ngx_http_userid_conf_t; | |
27 | |
28 | |
29 typedef struct { | |
30 uint32_t uid_got[4]; | |
31 uint32_t uid_set[4]; | |
32 struct timeval tv; | |
33 } ngx_http_userid_ctx_t; | |
34 | |
35 | |
36 static ngx_int_t ngx_http_userid_get_uid(ngx_http_request_t *r, | |
37 ngx_http_userid_ctx_t *ctx, | |
38 ngx_http_userid_conf_t *conf); | |
39 | |
40 static u_char *ngx_http_userid_log_uid_got(ngx_http_request_t *r, u_char *buf, | |
41 uintptr_t data); | |
42 static u_char *ngx_http_userid_log_uid_set(ngx_http_request_t *r, u_char *buf, | |
43 uintptr_t data); | |
44 static u_char *ngx_http_userid_log_uid_time(ngx_http_request_t *r, u_char *buf, | |
45 uintptr_t data); | |
46 | |
47 static ngx_int_t ngx_http_userid_pre_conf(ngx_conf_t *cf); | |
48 static void *ngx_http_userid_create_conf(ngx_conf_t *cf); | |
49 static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, | |
50 void *child); | |
51 static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle); | |
52 | |
53 | |
54 static ngx_conf_enum_t ngx_http_userid_mask[] = { | |
55 { ngx_string("off"), NGX_HTTP_USERID_OFF }, | |
56 { ngx_string("on"), NGX_HTTP_USERID_ON }, | |
57 { ngx_string("logonly"), NGX_HTTP_USERID_LOGONLY }, | |
58 { ngx_string("time"), NGX_HTTP_USERID_TIME }, | |
59 { ngx_null_string, 0 } | |
60 }; | |
61 | |
62 | |
63 static ngx_command_t ngx_http_userid_commands[] = { | |
64 | |
65 { ngx_string("userid"), | |
66 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY, | |
67 ngx_conf_set_bitmask_slot, | |
68 NGX_HTTP_LOC_CONF_OFFSET, | |
69 offsetof(ngx_http_userid_conf_t, enable), | |
70 ngx_http_userid_mask}, | |
71 | |
72 { ngx_string("userid_service"), | |
73 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
74 ngx_conf_set_num_slot, | |
75 NGX_HTTP_LOC_CONF_OFFSET, | |
76 offsetof(ngx_http_userid_conf_t, service), | |
77 NULL}, | |
78 | |
79 { ngx_string("userid_name"), | |
80 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
81 ngx_conf_set_str_slot, | |
82 NGX_HTTP_LOC_CONF_OFFSET, | |
83 offsetof(ngx_http_userid_conf_t, name), | |
84 NULL}, | |
85 | |
86 { ngx_string("userid_domain"), | |
87 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
88 ngx_conf_set_str_slot, | |
89 NGX_HTTP_LOC_CONF_OFFSET, | |
90 offsetof(ngx_http_userid_conf_t, domain), | |
91 NULL}, | |
92 | |
93 { ngx_string("userid_path"), | |
94 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
95 ngx_conf_set_str_slot, | |
96 NGX_HTTP_LOC_CONF_OFFSET, | |
97 offsetof(ngx_http_userid_conf_t, path), | |
98 NULL}, | |
99 | |
100 { ngx_string("userid_expires"), | |
101 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
102 ngx_conf_set_sec_slot, | |
103 NGX_HTTP_LOC_CONF_OFFSET, | |
104 offsetof(ngx_http_userid_conf_t, expires), | |
105 NULL}, | |
106 | |
107 ngx_null_command | |
108 }; | |
109 | |
110 | |
111 ngx_http_module_t ngx_http_userid_module_ctx = { | |
112 ngx_http_userid_pre_conf, /* pre conf */ | |
113 | |
114 NULL, /* create main configuration */ | |
115 NULL, /* init main configuration */ | |
116 | |
117 NULL, /* create server configuration */ | |
118 NULL, /* merge server configuration */ | |
119 | |
120 ngx_http_userid_create_conf, /* create location configration */ | |
121 ngx_http_userid_merge_conf /* merge location configration */ | |
122 }; | |
123 | |
124 | |
125 ngx_module_t ngx_http_userid_module = { | |
126 NGX_MODULE, | |
127 &ngx_http_userid_module_ctx, /* module context */ | |
128 ngx_http_userid_commands, /* module directives */ | |
129 NGX_HTTP_MODULE, /* module type */ | |
130 ngx_http_userid_init, /* init module */ | |
131 NULL /* init process */ | |
132 }; | |
133 | |
134 | |
135 static ngx_http_log_op_name_t ngx_http_userid_log_fmt_ops[] = { | |
136 { ngx_string("uid_got"), 0, ngx_http_userid_log_uid_got }, | |
137 { ngx_string("uid_set"), 0, ngx_http_userid_log_uid_set }, | |
138 { ngx_string("uid_time"), TIME_T_LEN + 4, ngx_http_userid_log_uid_time }, | |
139 { ngx_null_string, 0, NULL } | |
140 }; | |
141 | |
142 | |
143 static ngx_int_t ngx_http_userid_handler(ngx_http_request_t *r) | |
144 { | |
145 ngx_int_t rc; | |
146 struct timeval tv; | |
147 ngx_http_userid_ctx_t *ctx; | |
148 ngx_http_userid_conf_t *conf; | |
149 | |
150 conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_module); | |
151 | |
152 if (conf->enable & NGX_HTTP_USERID_OFF) { | |
153 return NGX_OK; | |
154 } | |
155 | |
156 ctx = ngx_http_get_module_ctx(r, ngx_http_userid_module); | |
157 | |
158 if (ctx) { | |
159 return NGX_OK; | |
160 } | |
161 | |
162 ngx_http_create_ctx(r, ctx, ngx_http_userid_module, | |
163 sizeof(ngx_http_userid_ctx_t), | |
164 NGX_HTTP_INTERNAL_SERVER_ERROR); | |
165 | |
166 if (conf->enable & (NGX_HTTP_USERID_ON|NGX_HTTP_USERID_LOGONLY)) { | |
167 rc = ngx_http_userid_get_uid(r, ctx, conf); | |
168 | |
169 if (rc != NGX_OK) { | |
170 return rc; | |
171 } | |
172 } | |
173 | |
174 if (conf->enable & NGX_HTTP_USERID_TIME) { | |
175 ngx_gettimeofday(&ctx->tv); | |
176 } | |
177 | |
178 return NGX_OK; | |
179 } | |
180 | |
181 | |
182 static ngx_int_t ngx_http_userid_get_uid(ngx_http_request_t *r, | |
183 ngx_http_userid_ctx_t *ctx, | |
184 ngx_http_userid_conf_t *conf) | |
185 { | |
186 u_char *start, *last, *end; | |
187 uint32_t *uid; | |
188 ngx_int_t rc; | |
189 ngx_uint_t *cookies, i; | |
190 ngx_str_t src, dst; | |
191 ngx_table_elt_t *headers; | |
192 | |
193 headers = r->headers_in.headers.elts; | |
194 cookies = r->headers_in.cookies.elts; | |
195 | |
196 for (i = 0; i < r->headers_in.cookies.nelts; i++) { | |
197 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
198 "cookie: %d:\"%s\"", | |
199 cookies[i], | |
200 headers[cookies[i]].value.data); | |
201 | |
202 end = headers[cookies[i]].value.data + headers[cookies[i]].value.len; | |
203 | |
204 for (start = headers[cookies[i]].value.data; start < end; /* void */) { | |
205 | |
206 if (conf->name.len >= headers[cookies[i]].value.len | |
207 || ngx_strncmp(start, conf->name.data, conf->name.len) != 0) | |
208 { | |
209 start += conf->name.len; | |
210 while (start < end && *start++ != ';') { /* void */ } | |
211 | |
212 for (/* void */; start < end && *start == ' '; start++) { /**/ } | |
213 | |
214 continue; | |
215 } | |
216 | |
217 for (start += conf->name.len; start < end && *start == ' '; start++) | |
218 { | |
219 /* void */ | |
220 } | |
221 | |
222 if (*start != '=') { | |
223 break; | |
224 } | |
225 | |
226 for (start++; start < end && *start == ' '; start++) { /* void */ } | |
227 | |
228 for (last = start; last < end && *last != ';'; last++) { /**/ } | |
229 | |
230 if (last - start < 22) { | |
231 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
232 "client sent too short userid cookie \"%s\"", | |
233 headers[cookies[i]].value.data); | |
234 break; | |
235 } | |
236 | |
237 /* | |
238 * we have to limit encoded string to 22 characters | |
239 * because there are already the millions cookies with a garbage | |
240 * instead of the correct base64 trail "==" | |
241 */ | |
242 | |
243 src.len = 22; | |
244 src.data = start; | |
245 | |
246 rc = ngx_decode_base64(r->pool, &src, &dst); | |
247 | |
248 if (rc == NGX_ABORT) { | |
249 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
250 } | |
251 | |
252 if (rc == NGX_ERROR) { | |
253 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
254 "client sent invalid userid cookie \"%s\"", | |
255 headers[cookies[i]].value.data); | |
256 break; | |
257 } | |
258 | |
259 uid = (uint32_t *) dst.data; | |
260 ctx->uid_got[0] = uid[0]; | |
261 ctx->uid_got[1] = uid[1]; | |
262 ctx->uid_got[2] = uid[2]; | |
263 ctx->uid_got[3] = uid[3]; | |
264 | |
265 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
266 "uid: %08X%08X%08X%08X", | |
267 uid[0], uid[1], uid[2], uid[3]); | |
268 | |
269 return NGX_OK; | |
270 } | |
271 } | |
272 | |
273 return NGX_OK; | |
274 } | |
275 | |
276 | |
277 static u_char *ngx_http_userid_log_uid_got(ngx_http_request_t *r, u_char *buf, | |
278 uintptr_t data) | |
279 { | |
280 ngx_http_userid_ctx_t *ctx; | |
281 ngx_http_userid_conf_t *conf; | |
282 | |
283 ctx = ngx_http_get_module_ctx(r, ngx_http_userid_module); | |
284 | |
285 if (ctx == NULL || ctx->uid_got[3] == 0) { | |
286 if (buf == NULL) { | |
287 return (u_char *) 1; | |
288 } | |
289 | |
290 *buf = '-'; | |
291 return buf + 1; | |
292 } | |
293 | |
294 conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_module); | |
295 | |
296 if (buf == NULL) { | |
297 return (u_char *) (conf->name.len + 1 + 32); | |
298 } | |
299 | |
300 buf = ngx_cpymem(buf, conf->name.data, conf->name.len); | |
301 | |
302 *buf++ = '='; | |
303 | |
304 return buf + ngx_snprintf((char *) buf, 33, "%08X%08X%08X%08X", | |
305 ctx->uid_got[0], ctx->uid_got[1], | |
306 ctx->uid_got[2], ctx->uid_got[3]); | |
307 } | |
308 | |
309 | |
310 static u_char *ngx_http_userid_log_uid_set(ngx_http_request_t *r, u_char *buf, | |
311 uintptr_t data) | |
312 { | |
313 if (buf == NULL) { | |
314 return (u_char *) 1; | |
315 } | |
316 | |
317 *buf = '-'; | |
318 | |
319 return buf + 1; | |
320 } | |
321 | |
322 | |
323 static u_char *ngx_http_userid_log_uid_time(ngx_http_request_t *r, u_char *buf, | |
324 uintptr_t data) | |
325 { | |
326 ngx_http_userid_ctx_t *ctx; | |
327 | |
328 ctx = ngx_http_get_module_ctx(r, ngx_http_userid_module); | |
329 | |
330 if (ctx == NULL || ctx->tv.tv_sec == 0) { | |
331 *buf = '-'; | |
332 return buf + 1; | |
333 } | |
334 | |
335 return buf + ngx_snprintf((char *) buf, TIME_T_LEN + 5, | |
336 "%ld.%03ld", | |
337 ctx->tv.tv_sec, ctx->tv.tv_usec / 1000); | |
338 } | |
339 | |
340 | |
341 static ngx_int_t ngx_http_userid_pre_conf(ngx_conf_t *cf) | |
342 { | |
343 ngx_http_log_op_name_t *op; | |
344 | |
345 for (op = ngx_http_userid_log_fmt_ops; op->name.len; op++) { /* void */ } | |
346 op->op = NULL; | |
347 | |
348 op = ngx_http_log_fmt_ops; | |
349 | |
350 for (op = ngx_http_log_fmt_ops; op->op; op++) { | |
351 if (op->name.len == 0) { | |
352 op = (ngx_http_log_op_name_t *) op->op; | |
353 } | |
354 } | |
355 | |
356 op->op = (ngx_http_log_op_pt) ngx_http_userid_log_fmt_ops; | |
357 | |
358 return NGX_OK; | |
359 } | |
360 | |
361 | |
362 static void *ngx_http_userid_create_conf(ngx_conf_t *cf) | |
363 { | |
364 ngx_http_userid_conf_t *conf; | |
365 | |
366 if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_userid_conf_t)))) { | |
367 return NGX_CONF_ERROR; | |
368 } | |
369 | |
370 /* set by ngx_pcalloc(): | |
371 | |
372 conf->enable = 0; | |
373 | |
374 conf->name.len = 0; | |
375 conf->name.date = NULL; | |
376 conf->domain.len = 0; | |
377 conf->domain.date = NULL; | |
378 conf->path.len = 0; | |
379 conf->path.date = NULL; | |
380 | |
381 */ | |
382 | |
383 | |
384 return conf; | |
385 } | |
386 | |
387 | |
388 static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, | |
389 void *child) | |
390 { | |
391 ngx_http_userid_conf_t *prev = parent; | |
392 ngx_http_userid_conf_t *conf = child; | |
393 | |
394 ngx_conf_merge_bitmask_value(conf->enable, prev->enable, | |
395 (NGX_CONF_BITMASK_SET | |
396 |NGX_HTTP_USERID_OFF)); | |
397 | |
398 ngx_conf_merge_str_value(conf->name, prev->name, "uid"); | |
399 ngx_conf_merge_str_value(conf->domain, prev->domain, "."); | |
400 ngx_conf_merge_str_value(conf->path, prev->path, "/"); | |
401 | |
402 return NGX_CONF_OK; | |
403 } | |
404 | |
405 | |
406 static ngx_int_t ngx_http_userid_init(ngx_cycle_t *cycle) | |
407 { | |
408 ngx_http_handler_pt *h; | |
409 ngx_http_core_main_conf_t *cmcf; | |
410 | |
411 cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module); | |
412 | |
413 h = ngx_push_array(&cmcf->phases[NGX_HTTP_MISC_PHASE].handlers); | |
414 if (h == NULL) { | |
415 return NGX_ERROR; | |
416 } | |
417 | |
418 *h = ngx_http_userid_handler; | |
419 | |
420 return NGX_OK; | |
421 } |