Initial import
This commit is contained in:
commit
fb6735ff12
|
@ -0,0 +1,5 @@
|
||||||
|
USE_MD5=YES
|
||||||
|
USE_SHA1=YES
|
||||||
|
ngx_addon_name=ngx_http_accesskey_module
|
||||||
|
HTTP_MODULES="$HTTP_MODULES ngx_http_accesskey_module"
|
||||||
|
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_accesskey_module.c"
|
|
@ -0,0 +1,315 @@
|
||||||
|
/*
|
||||||
|
* nginx (c) Igor Sysoev
|
||||||
|
* this module (C) Mykola Grechukh <gns@altlinux.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <ngx_config.h>
|
||||||
|
#include <ngx_core.h>
|
||||||
|
#include <ngx_http.h>
|
||||||
|
|
||||||
|
#if (NGX_HAVE_OPENSSL_MD5_H)
|
||||||
|
#include <openssl/md5.h>
|
||||||
|
#else
|
||||||
|
#include <md5.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_OPENSSL_MD5)
|
||||||
|
#define MD5Init MD5_Init
|
||||||
|
#define MD5Update MD5_Update
|
||||||
|
#define MD5Final MD5_Final
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HAVE_OPENSSL_SHA1_H)
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#else
|
||||||
|
#include <sha.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NGX_ACCESSKEY_MD5 1
|
||||||
|
#define NGX_ACCESSKEY_SHA1 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_flag_t enable;
|
||||||
|
ngx_str_t arg;
|
||||||
|
ngx_uint_t hashmethod;
|
||||||
|
ngx_str_t signature;
|
||||||
|
ngx_array_t *signature_lengths;
|
||||||
|
ngx_array_t *signature_values;
|
||||||
|
} ngx_http_accesskey_loc_conf_t;
|
||||||
|
|
||||||
|
static ngx_int_t ngx_http_accesskey_handler(ngx_http_request_t *r);
|
||||||
|
|
||||||
|
static char *ngx_http_accesskey_signature(ngx_conf_t *cf, void *post, void *data);
|
||||||
|
static char *ngx_http_accesskey_hashmethod(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
|
||||||
|
|
||||||
|
static void *ngx_http_accesskey_create_loc_conf(ngx_conf_t *cf);
|
||||||
|
static char *ngx_http_accesskey_merge_loc_conf(ngx_conf_t *cf,
|
||||||
|
void *parent, void *child);
|
||||||
|
static ngx_int_t ngx_http_accesskey_init(ngx_conf_t *cf);
|
||||||
|
|
||||||
|
static ngx_conf_post_handler_pt ngx_http_accesskey_signature_p =
|
||||||
|
ngx_http_accesskey_signature;
|
||||||
|
|
||||||
|
static ngx_command_t ngx_http_accesskey_commands[] = {
|
||||||
|
{ ngx_string("accesskey"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
||||||
|
ngx_conf_set_flag_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_accesskey_loc_conf_t, enable),
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("accesskey_hashmethod"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_http_accesskey_hashmethod,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
0,
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
{ ngx_string("accesskey_signature"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_str_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_accesskey_loc_conf_t, signature),
|
||||||
|
&ngx_http_accesskey_signature_p },
|
||||||
|
|
||||||
|
{ ngx_string("accesskey_arg"),
|
||||||
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||||
|
ngx_conf_set_str_slot,
|
||||||
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
|
offsetof(ngx_http_accesskey_loc_conf_t, arg),
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
ngx_null_command
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_http_module_t ngx_http_accesskey_module_ctx = {
|
||||||
|
NULL, /* preconfiguration */
|
||||||
|
ngx_http_accesskey_init, /* postconfiguration */
|
||||||
|
|
||||||
|
NULL, /* create main configuration */
|
||||||
|
NULL, /* init main configuration */
|
||||||
|
|
||||||
|
NULL, /* create server configuration */
|
||||||
|
NULL, /* merge server configuration */
|
||||||
|
|
||||||
|
ngx_http_accesskey_create_loc_conf, /* create location configuration */
|
||||||
|
ngx_http_accesskey_merge_loc_conf /* merge location configuration */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ngx_module_t ngx_http_accesskey_module = {
|
||||||
|
NGX_MODULE_V1,
|
||||||
|
&ngx_http_accesskey_module_ctx, /* module context */
|
||||||
|
ngx_http_accesskey_commands, /* module directives */
|
||||||
|
NGX_HTTP_MODULE, /* module type */
|
||||||
|
NULL, /* init master */
|
||||||
|
NULL, /* init module */
|
||||||
|
NULL, /* init process */
|
||||||
|
NULL, /* init thread */
|
||||||
|
NULL, /* exit thread */
|
||||||
|
NULL, /* exit process */
|
||||||
|
NULL, /* exit master */
|
||||||
|
NGX_MODULE_V1_PADDING
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_accesskey_handler(ngx_http_request_t *r)
|
||||||
|
{
|
||||||
|
ngx_uint_t i;
|
||||||
|
ngx_uint_t hashlength,bhashlength;
|
||||||
|
ngx_http_accesskey_loc_conf_t *alcf;
|
||||||
|
|
||||||
|
alcf = ngx_http_get_module_loc_conf(r, ngx_http_accesskey_module);
|
||||||
|
|
||||||
|
if (!alcf->enable) {
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!alcf->signature_lengths || !alcf->signature_values) {
|
||||||
|
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
|
||||||
|
"accesskey enabled, but signature not configured!");
|
||||||
|
return NGX_HTTP_FORBIDDEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(alcf->hashmethod) {
|
||||||
|
case NGX_ACCESSKEY_SHA1:
|
||||||
|
bhashlength=20; break;
|
||||||
|
|
||||||
|
case NGX_ACCESSKEY_MD5:
|
||||||
|
bhashlength=16; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||||
|
"accesskey: hash not supported");
|
||||||
|
return NGX_HTTP_FORBIDDEN;
|
||||||
|
}
|
||||||
|
hashlength=bhashlength*2;
|
||||||
|
|
||||||
|
ngx_str_t args = r->args;
|
||||||
|
ngx_str_t look = alcf->arg;
|
||||||
|
|
||||||
|
ngx_uint_t j=0,k=0,l=0;
|
||||||
|
|
||||||
|
for (i = 0; i <= args.len; i++) {
|
||||||
|
if ( ( i == args.len) || (args.data[i] == '&') ) {
|
||||||
|
if (j > 1) { k = j; l = i; }
|
||||||
|
j = 0;
|
||||||
|
} else if ( (j == 0) && (i<args.len-look.len) ) {
|
||||||
|
if ( (ngx_strncmp(args.data+i, look.data, look.len) == 0)
|
||||||
|
&& (args.data[i+look.len] == '=') ) {
|
||||||
|
j=i+look.len+1;
|
||||||
|
i=j-1;
|
||||||
|
} else j=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l-k!=hashlength) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||||
|
"accesskey: length %d of \"%V\" argument is not equal %d",
|
||||||
|
l-k, &look, hashlength);
|
||||||
|
return NGX_HTTP_FORBIDDEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_str_t val;
|
||||||
|
if (ngx_http_script_run(r, &val, alcf->signature_lengths->elts, 0, alcf->signature_values->elts) == NULL) {
|
||||||
|
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||||
|
"accesskey: evaluation failed");
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||||
|
"accesskey: evaluated value of signature: \"%V\"", &val);
|
||||||
|
|
||||||
|
u_char hashb[64], hasht[128];
|
||||||
|
|
||||||
|
MD5_CTX md5;
|
||||||
|
SHA_CTX sha;
|
||||||
|
|
||||||
|
switch(alcf->hashmethod) {
|
||||||
|
case NGX_ACCESSKEY_MD5:
|
||||||
|
MD5Init(&md5);
|
||||||
|
MD5Update(&md5,val.data,val.len);
|
||||||
|
MD5Final(hashb, &md5);
|
||||||
|
break;
|
||||||
|
case NGX_ACCESSKEY_SHA1:
|
||||||
|
SHA1_Init(&sha);
|
||||||
|
SHA1_Update(&sha,val.data,val.len);
|
||||||
|
SHA1_Final(hashb,&sha);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
static u_char hex[] = "0123456789abcdef";
|
||||||
|
u_char *text = hasht;
|
||||||
|
|
||||||
|
for (i = 0; i < bhashlength; i++) {
|
||||||
|
*text++ = hex[hashb[i] >> 4];
|
||||||
|
*text++ = hex[hashb[i] & 0xf];
|
||||||
|
}
|
||||||
|
|
||||||
|
*text = '\0';
|
||||||
|
|
||||||
|
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
||||||
|
"accesskey: hash value \"%s\"", hasht);
|
||||||
|
|
||||||
|
if (ngx_strncmp(hasht,args.data+k,hashlength)!=0)
|
||||||
|
return NGX_HTTP_FORBIDDEN;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_http_accesskey_compile_signature(ngx_conf_t *cf, ngx_http_accesskey_loc_conf_t *alcf)
|
||||||
|
{
|
||||||
|
|
||||||
|
ngx_http_script_compile_t sc;
|
||||||
|
ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
|
||||||
|
|
||||||
|
sc.cf = cf;
|
||||||
|
sc.source = &alcf->signature;
|
||||||
|
sc.lengths = &alcf->signature_lengths;
|
||||||
|
sc.values = &alcf->signature_values;
|
||||||
|
sc.variables = ngx_http_script_variables_count(&alcf->signature);;
|
||||||
|
sc.complete_lengths = 1;
|
||||||
|
sc.complete_values = 1;
|
||||||
|
|
||||||
|
if (ngx_http_script_compile(&sc) != NGX_OK) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_http_accesskey_signature(ngx_conf_t *cf, void *post, void *data)
|
||||||
|
{
|
||||||
|
ngx_http_accesskey_loc_conf_t *alcf =
|
||||||
|
ngx_http_conf_get_module_loc_conf(cf, ngx_http_accesskey_module);
|
||||||
|
|
||||||
|
return ngx_http_accesskey_compile_signature(cf, alcf);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_http_accesskey_hashmethod(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
|
{
|
||||||
|
ngx_str_t *d = cf->args->elts;
|
||||||
|
ngx_http_accesskey_loc_conf_t *alcf = conf;
|
||||||
|
|
||||||
|
if ( (d[1].len == 3 ) && (ngx_strncmp(d[1].data,"md5",3) == 0) ) {
|
||||||
|
alcf->hashmethod = NGX_ACCESSKEY_MD5;
|
||||||
|
} else if ( (d[1].len == 4) && (ngx_strncmp(d[1].data,"sha1",4) == 0) ){
|
||||||
|
alcf->hashmethod = NGX_ACCESSKEY_SHA1;
|
||||||
|
} else {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"accesskey_hashmethod should be md5 or sha1, not \"%V\"", d+1);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
return NGX_CONF_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
ngx_http_accesskey_create_loc_conf(ngx_conf_t *cf)
|
||||||
|
{
|
||||||
|
ngx_http_accesskey_loc_conf_t *conf;
|
||||||
|
|
||||||
|
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_accesskey_loc_conf_t));
|
||||||
|
if (conf == NULL) {
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
conf->enable = NGX_CONF_UNSET;
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ngx_http_accesskey_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||||
|
{
|
||||||
|
ngx_http_accesskey_loc_conf_t *prev = parent;
|
||||||
|
ngx_http_accesskey_loc_conf_t *conf = child;
|
||||||
|
ngx_conf_merge_value(conf->enable, prev->enable, 0);
|
||||||
|
ngx_conf_merge_uint_value(conf->hashmethod, prev->hashmethod, NGX_ACCESSKEY_MD5);
|
||||||
|
ngx_conf_merge_str_value(conf->arg, prev->arg, "key");
|
||||||
|
ngx_conf_merge_str_value(conf->signature,prev->signature,"$remote_addr");
|
||||||
|
return ngx_http_accesskey_compile_signature(cf, conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static ngx_int_t
|
||||||
|
ngx_http_accesskey_init(ngx_conf_t *cf)
|
||||||
|
{
|
||||||
|
ngx_http_handler_pt *h;
|
||||||
|
ngx_http_core_main_conf_t *cmcf;
|
||||||
|
|
||||||
|
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
|
||||||
|
|
||||||
|
h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
|
||||||
|
if (h == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*h = ngx_http_accesskey_handler;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
}
|
Loading…
Reference in New Issue