Mercurial > hg > nginx-mail
comparison src/http/modules/ngx_http_secure_link_module.c @ 665:0b460e61bdcd default tip
Merge with nginx 1.0.0.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 25 Apr 2011 04:22:17 +0400 |
parents | be70f83b184f |
children |
comparison
equal
deleted
inserted
replaced
572:06419a2298a9 | 665:0b460e61bdcd |
---|---|
9 #include <ngx_http.h> | 9 #include <ngx_http.h> |
10 #include <ngx_md5.h> | 10 #include <ngx_md5.h> |
11 | 11 |
12 | 12 |
13 typedef struct { | 13 typedef struct { |
14 ngx_str_t secret; | 14 ngx_http_complex_value_t *variable; |
15 ngx_http_complex_value_t *md5; | |
16 ngx_str_t secret; | |
15 } ngx_http_secure_link_conf_t; | 17 } ngx_http_secure_link_conf_t; |
16 | 18 |
17 | 19 |
20 typedef struct { | |
21 ngx_str_t expires; | |
22 } ngx_http_secure_link_ctx_t; | |
23 | |
24 | |
25 static ngx_int_t ngx_http_secure_link_old_variable(ngx_http_request_t *r, | |
26 ngx_http_secure_link_conf_t *conf, ngx_http_variable_value_t *v, | |
27 uintptr_t data); | |
28 static ngx_int_t ngx_http_secure_link_expires_variable(ngx_http_request_t *r, | |
29 ngx_http_variable_value_t *v, uintptr_t data); | |
18 static void *ngx_http_secure_link_create_conf(ngx_conf_t *cf); | 30 static void *ngx_http_secure_link_create_conf(ngx_conf_t *cf); |
19 static char *ngx_http_secure_link_merge_conf(ngx_conf_t *cf, void *parent, | 31 static char *ngx_http_secure_link_merge_conf(ngx_conf_t *cf, void *parent, |
20 void *child); | 32 void *child); |
21 static ngx_int_t ngx_http_secure_link_add_variables(ngx_conf_t *cf); | 33 static ngx_int_t ngx_http_secure_link_add_variables(ngx_conf_t *cf); |
22 | 34 |
23 | 35 |
24 static ngx_command_t ngx_http_secure_link_commands[] = { | 36 static ngx_command_t ngx_http_secure_link_commands[] = { |
37 | |
38 { ngx_string("secure_link"), | |
39 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
40 ngx_http_set_complex_value_slot, | |
41 NGX_HTTP_LOC_CONF_OFFSET, | |
42 offsetof(ngx_http_secure_link_conf_t, variable), | |
43 NULL }, | |
44 | |
45 { ngx_string("secure_link_md5"), | |
46 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
47 ngx_http_set_complex_value_slot, | |
48 NGX_HTTP_LOC_CONF_OFFSET, | |
49 offsetof(ngx_http_secure_link_conf_t, md5), | |
50 NULL }, | |
25 | 51 |
26 { ngx_string("secure_link_secret"), | 52 { ngx_string("secure_link_secret"), |
27 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | 53 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, |
28 ngx_conf_set_str_slot, | 54 ngx_conf_set_str_slot, |
29 NGX_HTTP_LOC_CONF_OFFSET, | 55 NGX_HTTP_LOC_CONF_OFFSET, |
63 NULL, /* exit master */ | 89 NULL, /* exit master */ |
64 NGX_MODULE_V1_PADDING | 90 NGX_MODULE_V1_PADDING |
65 }; | 91 }; |
66 | 92 |
67 | 93 |
68 static ngx_str_t ngx_http_secure_link = ngx_string("secure_link"); | 94 static ngx_str_t ngx_http_secure_link_name = ngx_string("secure_link"); |
95 static ngx_str_t ngx_http_secure_link_expires_name = | |
96 ngx_string("secure_link_expires"); | |
69 | 97 |
70 | 98 |
71 static ngx_int_t | 99 static ngx_int_t |
72 ngx_http_secure_link_variable(ngx_http_request_t *r, | 100 ngx_http_secure_link_variable(ngx_http_request_t *r, |
73 ngx_http_variable_value_t *v, uintptr_t data) | 101 ngx_http_variable_value_t *v, uintptr_t data) |
74 { | 102 { |
75 u_char *p, *start, *end, *last; | 103 u_char *p, *last; |
76 size_t len; | 104 ngx_str_t val, hash; |
77 ngx_int_t n; | 105 time_t expires; |
78 ngx_uint_t i; | 106 ngx_md5_t md5; |
79 ngx_md5_t md5; | 107 ngx_http_secure_link_ctx_t *ctx; |
80 ngx_http_secure_link_conf_t *conf; | 108 ngx_http_secure_link_conf_t *conf; |
81 u_char hash[16]; | 109 u_char hash_buf[16], md5_buf[16]; |
82 | 110 |
83 conf = ngx_http_get_module_loc_conf(r, ngx_http_secure_link_module); | 111 conf = ngx_http_get_module_loc_conf(r, ngx_http_secure_link_module); |
84 | 112 |
85 if (conf->secret.len == 0) { | 113 if (conf->secret.len) { |
86 goto not_found; | 114 return ngx_http_secure_link_old_variable(r, conf, v, data); |
87 } | 115 } |
116 | |
117 if (conf->variable == NULL || conf->md5 == NULL) { | |
118 goto not_found; | |
119 } | |
120 | |
121 if (ngx_http_complex_value(r, conf->variable, &val) != NGX_OK) { | |
122 return NGX_ERROR; | |
123 } | |
124 | |
125 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
126 "secure link: \"%V\"", &val); | |
127 | |
128 last = val.data + val.len; | |
129 | |
130 p = ngx_strlchr(val.data, last, ','); | |
131 expires = 0; | |
132 | |
133 if (p) { | |
134 val.len = p++ - val.data; | |
135 | |
136 expires = ngx_atotm(p, last - p); | |
137 if (expires <= 0) { | |
138 goto not_found; | |
139 } | |
140 | |
141 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_secure_link_ctx_t)); | |
142 if (ctx == NULL) { | |
143 return NGX_ERROR; | |
144 } | |
145 | |
146 ngx_http_set_ctx(r, ctx, ngx_http_secure_link_module); | |
147 | |
148 ctx->expires.len = last - p; | |
149 ctx->expires.data = p; | |
150 } | |
151 | |
152 if (val.len > 24) { | |
153 goto not_found; | |
154 } | |
155 | |
156 hash.len = 16; | |
157 hash.data = hash_buf; | |
158 | |
159 if (ngx_decode_base64url(&hash, &val) != NGX_OK) { | |
160 goto not_found; | |
161 } | |
162 | |
163 if (hash.len != 16) { | |
164 goto not_found; | |
165 } | |
166 | |
167 if (ngx_http_complex_value(r, conf->md5, &val) != NGX_OK) { | |
168 return NGX_ERROR; | |
169 } | |
170 | |
171 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
172 "secure link md5: \"%V\"", &val); | |
173 | |
174 ngx_md5_init(&md5); | |
175 ngx_md5_update(&md5, val.data, val.len); | |
176 ngx_md5_final(md5_buf, &md5); | |
177 | |
178 if (ngx_memcmp(hash_buf, md5_buf, 16) != 0) { | |
179 goto not_found; | |
180 } | |
181 | |
182 v->data = (u_char *) ((expires && expires < ngx_time()) ? "0" : "1"); | |
183 v->len = 1; | |
184 v->valid = 1; | |
185 v->no_cacheable = 0; | |
186 v->not_found = 0; | |
187 | |
188 return NGX_OK; | |
189 | |
190 not_found: | |
191 | |
192 v->not_found = 1; | |
193 | |
194 return NGX_OK; | |
195 } | |
196 | |
197 | |
198 static ngx_int_t | |
199 ngx_http_secure_link_old_variable(ngx_http_request_t *r, | |
200 ngx_http_secure_link_conf_t *conf, ngx_http_variable_value_t *v, | |
201 uintptr_t data) | |
202 { | |
203 u_char *p, *start, *end, *last; | |
204 size_t len; | |
205 ngx_int_t n; | |
206 ngx_uint_t i; | |
207 ngx_md5_t md5; | |
208 u_char hash[16]; | |
88 | 209 |
89 p = &r->unparsed_uri.data[1]; | 210 p = &r->unparsed_uri.data[1]; |
90 last = r->unparsed_uri.data + r->unparsed_uri.len; | 211 last = r->unparsed_uri.data + r->unparsed_uri.len; |
91 | 212 |
92 while (p < last) { | 213 while (p < last) { |
143 | 264 |
144 return NGX_OK; | 265 return NGX_OK; |
145 } | 266 } |
146 | 267 |
147 | 268 |
269 static ngx_int_t | |
270 ngx_http_secure_link_expires_variable(ngx_http_request_t *r, | |
271 ngx_http_variable_value_t *v, uintptr_t data) | |
272 { | |
273 ngx_http_secure_link_ctx_t *ctx; | |
274 | |
275 ctx = ngx_http_get_module_ctx(r, ngx_http_secure_link_module); | |
276 | |
277 if (ctx) { | |
278 v->len = ctx->expires.len; | |
279 v->valid = 1; | |
280 v->no_cacheable = 0; | |
281 v->not_found = 0; | |
282 v->data = ctx->expires.data; | |
283 | |
284 } else { | |
285 v->not_found = 1; | |
286 } | |
287 | |
288 return NGX_OK; | |
289 } | |
290 | |
291 | |
148 static void * | 292 static void * |
149 ngx_http_secure_link_create_conf(ngx_conf_t *cf) | 293 ngx_http_secure_link_create_conf(ngx_conf_t *cf) |
150 { | 294 { |
151 ngx_http_secure_link_conf_t *conf; | 295 ngx_http_secure_link_conf_t *conf; |
152 | 296 |
156 } | 300 } |
157 | 301 |
158 /* | 302 /* |
159 * set by ngx_pcalloc(): | 303 * set by ngx_pcalloc(): |
160 * | 304 * |
161 * conf->secret = { 0, NULL } | 305 * conf->variable = NULL; |
306 * conf->md5 = NULL; | |
307 * conf->secret = { 0, NULL }; | |
162 */ | 308 */ |
163 | 309 |
164 return conf; | 310 return conf; |
165 } | 311 } |
166 | 312 |
171 ngx_http_secure_link_conf_t *prev = parent; | 317 ngx_http_secure_link_conf_t *prev = parent; |
172 ngx_http_secure_link_conf_t *conf = child; | 318 ngx_http_secure_link_conf_t *conf = child; |
173 | 319 |
174 ngx_conf_merge_str_value(conf->secret, prev->secret, ""); | 320 ngx_conf_merge_str_value(conf->secret, prev->secret, ""); |
175 | 321 |
322 if (conf->variable == NULL) { | |
323 conf->variable = prev->variable; | |
324 } | |
325 | |
326 if (conf->md5 == NULL) { | |
327 conf->md5 = prev->md5; | |
328 } | |
329 | |
176 return NGX_CONF_OK; | 330 return NGX_CONF_OK; |
177 } | 331 } |
178 | 332 |
179 | 333 |
180 static ngx_int_t | 334 static ngx_int_t |
181 ngx_http_secure_link_add_variables(ngx_conf_t *cf) | 335 ngx_http_secure_link_add_variables(ngx_conf_t *cf) |
182 { | 336 { |
183 ngx_http_variable_t *var; | 337 ngx_http_variable_t *var; |
184 | 338 |
185 var = ngx_http_add_variable(cf, &ngx_http_secure_link, NGX_HTTP_VAR_NOHASH); | 339 var = ngx_http_add_variable(cf, &ngx_http_secure_link_name, 0); |
186 if (var == NULL) { | 340 if (var == NULL) { |
187 return NGX_ERROR; | 341 return NGX_ERROR; |
188 } | 342 } |
189 | 343 |
190 var->get_handler = ngx_http_secure_link_variable; | 344 var->get_handler = ngx_http_secure_link_variable; |
191 | 345 |
192 return NGX_OK; | 346 var = ngx_http_add_variable(cf, &ngx_http_secure_link_expires_name, 0); |
193 } | 347 if (var == NULL) { |
348 return NGX_ERROR; | |
349 } | |
350 | |
351 var->get_handler = ngx_http_secure_link_expires_variable; | |
352 | |
353 return NGX_OK; | |
354 } |