~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/http/modules/ngx_http_secure_link_module.c

Version: ~ [ nginx-1.4.1 ] ~ [ nginx-1.5.0 ] ~

  1 
  2 /*
  3  * Copyright (C) Igor Sysoev
  4  * Copyright (C) Nginx, Inc.
  5  */
  6 
  7 
  8 #include <ngx_config.h>
  9 #include <ngx_core.h>
 10 #include <ngx_http.h>
 11 #include <ngx_md5.h>
 12 
 13 
 14 typedef struct {
 15     ngx_http_complex_value_t  *variable;
 16     ngx_http_complex_value_t  *md5;
 17     ngx_str_t                  secret;
 18 } ngx_http_secure_link_conf_t;
 19 
 20 
 21 typedef struct {
 22     ngx_str_t                  expires;
 23 } ngx_http_secure_link_ctx_t;
 24 
 25 
 26 static ngx_int_t ngx_http_secure_link_old_variable(ngx_http_request_t *r,
 27     ngx_http_secure_link_conf_t *conf, ngx_http_variable_value_t *v,
 28     uintptr_t data);
 29 static ngx_int_t ngx_http_secure_link_expires_variable(ngx_http_request_t *r,
 30     ngx_http_variable_value_t *v, uintptr_t data);
 31 static void *ngx_http_secure_link_create_conf(ngx_conf_t *cf);
 32 static char *ngx_http_secure_link_merge_conf(ngx_conf_t *cf, void *parent,
 33     void *child);
 34 static ngx_int_t ngx_http_secure_link_add_variables(ngx_conf_t *cf);
 35 
 36 
 37 static ngx_command_t  ngx_http_secure_link_commands[] = {
 38 
 39     { ngx_string("secure_link"),
 40       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
 41       ngx_http_set_complex_value_slot,
 42       NGX_HTTP_LOC_CONF_OFFSET,
 43       offsetof(ngx_http_secure_link_conf_t, variable),
 44       NULL },
 45 
 46     { ngx_string("secure_link_md5"),
 47       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
 48       ngx_http_set_complex_value_slot,
 49       NGX_HTTP_LOC_CONF_OFFSET,
 50       offsetof(ngx_http_secure_link_conf_t, md5),
 51       NULL },
 52 
 53     { ngx_string("secure_link_secret"),
 54       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
 55       ngx_conf_set_str_slot,
 56       NGX_HTTP_LOC_CONF_OFFSET,
 57       offsetof(ngx_http_secure_link_conf_t, secret),
 58       NULL },
 59 
 60       ngx_null_command
 61 };
 62 
 63 
 64 static ngx_http_module_t  ngx_http_secure_link_module_ctx = {
 65     ngx_http_secure_link_add_variables,    /* preconfiguration */
 66     NULL,                                  /* postconfiguration */
 67 
 68     NULL,                                  /* create main configuration */
 69     NULL,                                  /* init main configuration */
 70 
 71     NULL,                                  /* create server configuration */
 72     NULL,                                  /* merge server configuration */
 73 
 74     ngx_http_secure_link_create_conf,      /* create location configuration */
 75     ngx_http_secure_link_merge_conf        /* merge location configuration */
 76 };
 77 
 78 
 79 ngx_module_t  ngx_http_secure_link_module = {
 80     NGX_MODULE_V1,
 81     &ngx_http_secure_link_module_ctx,      /* module context */
 82     ngx_http_secure_link_commands,         /* module directives */
 83     NGX_HTTP_MODULE,                       /* module type */
 84     NULL,                                  /* init master */
 85     NULL,                                  /* init module */
 86     NULL,                                  /* init process */
 87     NULL,                                  /* init thread */
 88     NULL,                                  /* exit thread */
 89     NULL,                                  /* exit process */
 90     NULL,                                  /* exit master */
 91     NGX_MODULE_V1_PADDING
 92 };
 93 
 94 
 95 static ngx_str_t  ngx_http_secure_link_name = ngx_string("secure_link");
 96 static ngx_str_t  ngx_http_secure_link_expires_name =
 97     ngx_string("secure_link_expires");
 98 
 99 
100 static ngx_int_t
101 ngx_http_secure_link_variable(ngx_http_request_t *r,
102     ngx_http_variable_value_t *v, uintptr_t data)
103 {
104     u_char                       *p, *last;
105     ngx_str_t                     val, hash;
106     time_t                        expires;
107     ngx_md5_t                     md5;
108     ngx_http_secure_link_ctx_t   *ctx;
109     ngx_http_secure_link_conf_t  *conf;
110     u_char                        hash_buf[16], md5_buf[16];
111 
112     conf = ngx_http_get_module_loc_conf(r, ngx_http_secure_link_module);
113 
114     if (conf->secret.data) {
115         return ngx_http_secure_link_old_variable(r, conf, v, data);
116     }
117 
118     if (conf->variable == NULL || conf->md5 == NULL) {
119         goto not_found;
120     }
121 
122     if (ngx_http_complex_value(r, conf->variable, &val) != NGX_OK) {
123         return NGX_ERROR;
124     }
125 
126     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
127                    "secure link: \"%V\"", &val);
128 
129     last = val.data + val.len;
130 
131     p = ngx_strlchr(val.data, last, ',');
132     expires = 0;
133 
134     if (p) {
135         val.len = p++ - val.data;
136 
137         expires = ngx_atotm(p, last - p);
138         if (expires <= 0) {
139             goto not_found;
140         }
141 
142         ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_secure_link_ctx_t));
143         if (ctx == NULL) {
144             return NGX_ERROR;
145         }
146 
147         ngx_http_set_ctx(r, ctx, ngx_http_secure_link_module);
148 
149         ctx->expires.len = last - p;
150         ctx->expires.data = p;
151     }
152 
153     if (val.len > 24) {
154         goto not_found;
155     }
156 
157     hash.len = 16;
158     hash.data = hash_buf;
159 
160     if (ngx_decode_base64url(&hash, &val) != NGX_OK) {
161         goto not_found;
162     }
163 
164     if (hash.len != 16) {
165         goto not_found;
166     }
167 
168     if (ngx_http_complex_value(r, conf->md5, &val) != NGX_OK) {
169         return NGX_ERROR;
170     }
171 
172     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
173                    "secure link md5: \"%V\"", &val);
174 
175     ngx_md5_init(&md5);
176     ngx_md5_update(&md5, val.data, val.len);
177     ngx_md5_final(md5_buf, &md5);
178 
179     if (ngx_memcmp(hash_buf, md5_buf, 16) != 0) {
180         goto not_found;
181     }
182 
183     v->data = (u_char *) ((expires && expires < ngx_time()) ? "" : "1");
184     v->len = 1;
185     v->valid = 1;
186     v->no_cacheable = 0;
187     v->not_found = 0;
188 
189     return NGX_OK;
190 
191 not_found:
192 
193     v->not_found = 1;
194 
195     return NGX_OK;
196 }
197 
198 
199 static ngx_int_t
200 ngx_http_secure_link_old_variable(ngx_http_request_t *r,
201     ngx_http_secure_link_conf_t *conf, ngx_http_variable_value_t *v,
202     uintptr_t data)
203 {
204     u_char      *p, *start, *end, *last;
205     size_t       len;
206     ngx_int_t    n;
207     ngx_uint_t   i;
208     ngx_md5_t    md5;
209     u_char       hash[16];
210 
211     p = &r->unparsed_uri.data[1];
212     last = r->unparsed_uri.data + r->unparsed_uri.len;
213 
214     while (p < last) {
215         if (*p++ == '/') {
216             start = p;
217             goto md5_start;
218         }
219     }
220 
221     goto not_found;
222 
223 md5_start:
224 
225     while (p < last) {
226         if (*p++ == '/') {
227             end = p - 1;
228             goto url_start;
229         }
230     }
231 
232     goto not_found;
233 
234 url_start:
235 
236     len = last - p;
237 
238     if (end - start != 32 || len == 0) {
239         goto not_found;
240     }
241 
242     ngx_md5_init(&md5);
243     ngx_md5_update(&md5, p, len);
244     ngx_md5_update(&md5, conf->secret.data, conf->secret.len);
245     ngx_md5_final(hash, &md5);
246 
247     for (i = 0; i < 16; i++) {
248         n = ngx_hextoi(&start[2 * i], 2);
249         if (n == NGX_ERROR || n != hash[i]) {
250             goto not_found;
251         }
252     }
253 
254     v->len = len;
255     v->valid = 1;
256     v->no_cacheable = 0;
257     v->not_found = 0;
258     v->data = p;
259 
260     return NGX_OK;
261 
262 not_found:
263 
264     v->not_found = 1;
265 
266     return NGX_OK;
267 }
268 
269 
270 static ngx_int_t
271 ngx_http_secure_link_expires_variable(ngx_http_request_t *r,
272     ngx_http_variable_value_t *v, uintptr_t data)
273 {
274     ngx_http_secure_link_ctx_t  *ctx;
275 
276     ctx = ngx_http_get_module_ctx(r, ngx_http_secure_link_module);
277 
278     if (ctx) {
279         v->len = ctx->expires.len;
280         v->valid = 1;
281         v->no_cacheable = 0;
282         v->not_found = 0;
283         v->data = ctx->expires.data;
284 
285     } else {
286         v->not_found = 1;
287     }
288 
289     return NGX_OK;
290 }
291 
292 
293 static void *
294 ngx_http_secure_link_create_conf(ngx_conf_t *cf)
295 {
296     ngx_http_secure_link_conf_t  *conf;
297 
298     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_secure_link_conf_t));
299     if (conf == NULL) {
300         return NULL;
301     }
302 
303     /*
304      * set by ngx_pcalloc():
305      *
306      *     conf->variable = NULL;
307      *     conf->md5 = NULL;
308      *     conf->secret = { 0, NULL };
309      */
310 
311     return conf;
312 }
313 
314 
315 static char *
316 ngx_http_secure_link_merge_conf(ngx_conf_t *cf, void *parent, void *child)
317 {
318     ngx_http_secure_link_conf_t *prev = parent;
319     ngx_http_secure_link_conf_t *conf = child;
320 
321     if (conf->secret.data) {
322         if (conf->variable || conf->md5) {
323             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
324                                "\"secure_link_secret\" cannot be mixed with "
325                                "\"secure_link\" and \"secure_link_md5\"");
326             return NGX_CONF_ERROR;
327         }
328 
329         return NGX_CONF_OK;
330     }
331 
332     if (conf->variable == NULL) {
333         conf->variable = prev->variable;
334     }
335 
336     if (conf->md5 == NULL) {
337         conf->md5 = prev->md5;
338     }
339 
340     if (conf->variable == NULL && conf->md5 == NULL) {
341         conf->secret = prev->secret;
342     }
343 
344     return NGX_CONF_OK;
345 }
346 
347 
348 static ngx_int_t
349 ngx_http_secure_link_add_variables(ngx_conf_t *cf)
350 {
351     ngx_http_variable_t  *var;
352 
353     var = ngx_http_add_variable(cf, &ngx_http_secure_link_name, 0);
354     if (var == NULL) {
355         return NGX_ERROR;
356     }
357 
358     var->get_handler = ngx_http_secure_link_variable;
359 
360     var = ngx_http_add_variable(cf, &ngx_http_secure_link_expires_name, 0);
361     if (var == NULL) {
362         return NGX_ERROR;
363     }
364 
365     var->get_handler = ngx_http_secure_link_expires_variable;
366 
367     return NGX_OK;
368 }
369 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.