Nginx-ru mailing list archive (nginx-ru@sysoev.ru)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Нужен пример моду ля.
maxhl@xxxxxxxxxxxxxx wrote:
Кому нежалко скиньте какой нибудь пример.
В аттаче -- пример модуля для валидации одноразовых ссылок.
Дисклеймер: написано было давно, поэтому помидорами не кидаться.
Кроме того, есть страница
http://wiki.codemongers.com/NginxModules
В разделе Third-Party HTTP modules там исключительно одни примеры.
--
Regards,
Valery Kholodkov
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
//#if (NGX_HAVE_OPENSSL_SHA1_H)
#include <openssl/sha.h>
//#else
//#include <sha.h>
//#endif
#if (NGX_OPENSSL_SHA1)
#define SHA1Init SHA1_Init
#define SHA1Update SHA1_Update
#define SHA1Final SHA1_Final
#endif
typedef struct {
ngx_str_t secret_key;
ngx_regex_t *regex;
ngx_int_t ncaptures;
ngx_int_t authenticator_pos;
ngx_int_t fragment_pos;
ngx_int_t digest_pos;
ngx_int_t id_pos;
ngx_int_t filename_pos;
} ngx_http_securelinks_loc_conf_t;
static void *ngx_http_securelinks_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_securelinks_merge_loc_conf(ngx_conf_t *cf,
void *parent, void *child);
static ngx_int_t ngx_http_securelinks_init(ngx_cycle_t *cycle);
static char *ngx_http_securelinks_regex(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static ngx_command_t ngx_http_securelinks_commands[] = {
{ ngx_string("securelinks_regex"),
NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
ngx_http_securelinks_regex,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
{ ngx_string("securelinks_secret_key"),
NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_securelinks_loc_conf_t, secret_key),
NULL },
{ ngx_string("securelinks_authenticator_pos"),
NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_securelinks_loc_conf_t, authenticator_pos),
NULL },
{ ngx_string("securelinks_fragment_pos"),
NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_securelinks_loc_conf_t, fragment_pos),
NULL },
{ ngx_string("securelinks_digest_pos"),
NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_securelinks_loc_conf_t, digest_pos),
NULL },
{ ngx_string("securelinks_id_pos"),
NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_securelinks_loc_conf_t, id_pos),
NULL },
{ ngx_string("securelinks_filename_pos"),
NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE1,
ngx_conf_set_num_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_securelinks_loc_conf_t, filename_pos),
NULL },
ngx_null_command
};
ngx_http_module_t ngx_http_securelinks_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
NULL, /* create main configuration */
NULL, /* init main configuration */
NULL, /* create server configuration */
NULL, /* merge server configuration */
ngx_http_securelinks_create_loc_conf, /* create location configration */
ngx_http_securelinks_merge_loc_conf /* merge location configration */
};
ngx_module_t ngx_http_securelinks_module = {
NGX_MODULE_V1,
&ngx_http_securelinks_module_ctx, /* module context */
ngx_http_securelinks_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
ngx_http_securelinks_init, /* 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_securelinks_get_remote_addr_str(ngx_http_request_t *r, ngx_str_t *dest)
{
struct sockaddr_in *sin;
dest->data = ngx_palloc(r->pool, INET_ADDRSTRLEN);
if(dest->data == NULL)
return NGX_ERROR;
sin = (struct sockaddr_in *) r->connection->sockaddr;
dest->len = ngx_inet_ntop(sin->sin_family,
&sin->sin_addr, dest->data, INET_ADDRSTRLEN);
return NGX_OK;
}
static ngx_int_t
ngx_http_securelinks_handler(ngx_http_request_t *r)
{
ngx_http_securelinks_loc_conf_t *rlcf;
ngx_int_t *captures;
ngx_int_t rc;
ngx_str_t authenticator;
ngx_str_t fragment;
ngx_str_t digest;
ngx_str_t id;
ngx_str_t filename;
SHA_CTX sha1;
u_char sha1_digest[SHA_DIGEST_LENGTH];
ngx_str_t remote_addr;
ngx_str_t hex_digest;
ngx_str_t rewritten_uri;
char *p;
rlcf = ngx_http_get_module_loc_conf(r, ngx_http_securelinks_module);
if (rlcf->regex == NULL) {
return NGX_DECLINED;
}
if(ngx_http_securelinks_get_remote_addr_str(r, &remote_addr) != NGX_OK)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
captures = ngx_palloc(r->pool, (rlcf->ncaptures + 1) * sizeof(int) * 3);
if (captures == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
rc = ngx_regex_exec(rlcf->regex, &r->uri, captures, (rlcf->ncaptures + 1) *
3);
if(rc == NGX_REGEX_NO_MATCHED) {
return NGX_HTTP_NOT_FOUND;
}
if (rc < 0) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
ngx_regex_exec_n " failed: %d on \"%V\"", rc, &r->uri);
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
authenticator.data = r->uri.data + captures[2 * rlcf->authenticator_pos];
authenticator.len = captures[2 * rlcf->authenticator_pos + 1] - captures[2
* rlcf->authenticator_pos];
fragment.data = r->uri.data + captures[2 * rlcf->fragment_pos];
fragment.len = captures[2 * rlcf->fragment_pos + 1] - captures[2 *
rlcf->fragment_pos];
digest.data = r->uri.data + captures[2 * rlcf->digest_pos];
digest.len = captures[2 * rlcf->digest_pos + 1] - captures[2 *
rlcf->digest_pos];
id.data = r->uri.data + captures[2 * rlcf->id_pos];
id.len = captures[2 * rlcf->id_pos + 1] - captures[2 * rlcf->id_pos];
filename.data = r->uri.data + captures[2 * rlcf->filename_pos];
filename.len = captures[2 * rlcf->filename_pos + 1] - captures[2 *
rlcf->filename_pos];
SHA1_Init(&sha1);
SHA1_Update(&sha1, remote_addr.data, remote_addr.len);
SHA1_Update(&sha1, ":", sizeof(char));
SHA1_Update(&sha1, authenticator.data, authenticator.len);
SHA1_Update(&sha1, ":", sizeof(char));
SHA1_Update(&sha1, fragment.data, fragment.len);
SHA1_Update(&sha1, ":", sizeof(char));
SHA1_Update(&sha1, filename.data, filename.len);
SHA1_Update(&sha1, ":", sizeof(char));
SHA1_Update(&sha1, rlcf->secret_key.data, rlcf->secret_key.len);
SHA1_Final(sha1_digest, &sha1);
#ifdef SECURELINKS_DEBUG
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
"verified sequence \"%V:%V:%V:%V:%V\"", &remote_addr,
&authenticator, &fragment, &filename, &rlcf->secret_key);
#endif
hex_digest.data = ngx_palloc(r->pool, (2 * SHA_DIGEST_LENGTH + 1 ) *
sizeof(char));
if (hex_digest.data == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
ngx_digest_text(hex_digest.data, sha1_digest, SHA_DIGEST_LENGTH);
hex_digest.len = 2 * SHA_DIGEST_LENGTH;
// Verify digest
if(ngx_strncasecmp(digest.data, hex_digest.data, (digest.len <
hex_digest.len) ? digest.len : hex_digest.len)) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
"digest mismatch: \"%V\" vs \"%V\" for \"%V\"", &digest,
&hex_digest, &r->uri);
return NGX_HTTP_NOT_FOUND;
}
rewritten_uri.len = 1 + fragment.len + 1 + filename.len;
rewritten_uri.data = ngx_palloc(r->pool, rewritten_uri.len);
if (rewritten_uri.data == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
p = rewritten_uri.data;
*p++ = '/';
ngx_memcpy(p, fragment.data, fragment.len);
p += fragment.len;
*p++ = '/';
ngx_memcpy(p, filename.data, filename.len);
p += filename.len;
r->uri.data = rewritten_uri.data;
r->uri.len = rewritten_uri.len;
return NGX_DECLINED;
}
static void *
ngx_http_securelinks_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_securelinks_loc_conf_t *conf;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_securelinks_loc_conf_t));
if (conf == NULL) {
return NGX_CONF_ERROR;
}
conf->secret_key.len = 0;
conf->secret_key.data = NULL;
conf->regex = NULL;
conf->authenticator_pos = NGX_CONF_UNSET;
conf->fragment_pos = NGX_CONF_UNSET;
conf->digest_pos = NGX_CONF_UNSET;
conf->id_pos = NGX_CONF_UNSET;
conf->filename_pos = NGX_CONF_UNSET;
return conf;
}
static char *
ngx_http_securelinks_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
ngx_http_securelinks_loc_conf_t *prev = parent;
ngx_http_securelinks_loc_conf_t *conf = child;
ngx_conf_merge_str_value(conf->secret_key, prev->secret_key, "");
ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL);
return NGX_CONF_OK;
}
static ngx_int_t
ngx_http_securelinks_init(ngx_cycle_t *cycle)
{
ngx_http_handler_pt *h;
ngx_http_core_main_conf_t *cmcf;
cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
h = ngx_array_push(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
*h = ngx_http_securelinks_handler;
h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}
*h = ngx_http_securelinks_handler;
return NGX_OK;
}
static char *
ngx_http_securelinks_regex(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_securelinks_loc_conf_t *lcf = conf;
ngx_str_t *value, err;
ngx_int_t n;
value = cf->args->elts;
lcf->regex = ngx_regex_compile(&value[1], 0, cf->pool, &err);
if (lcf->regex == NULL) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
return NGX_CONF_ERROR;
}
n = ngx_regex_capture_count(lcf->regex);
if (n < 0) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
ngx_regex_capture_count_n " failed for "
"pattern \"%V\"", &value[1]);
return NGX_CONF_ERROR;
}
lcf->ncaptures = n;
return NGX_CONF_OK;
}
|