diff options
author | Guenter Knauf <fuankg@apache.org> | 2013-06-02 19:31:16 +0000 |
---|---|---|
committer | Guenter Knauf <fuankg@apache.org> | 2013-06-02 19:31:16 +0000 |
commit | 5dbd3677fd38758285bff2cfa77673da2a5d8941 (patch) | |
tree | 6de2d5c9cc3a8a7b2c1a0368c93e28bb23f0a55b /modules | |
parent | 288ff9e014fadd8b3382d3f7be9e896ade0d8c28 (diff) | |
download | httpd-5dbd3677fd38758285bff2cfa77673da2a5d8941.tar.gz |
Added new function r:htpassword() to mod_lua.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1488773 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules')
-rw-r--r-- | modules/lua/NWGNUmakefile | 1 | ||||
-rw-r--r-- | modules/lua/lua_passwd.c | 178 | ||||
-rw-r--r-- | modules/lua/lua_passwd.h | 91 | ||||
-rw-r--r-- | modules/lua/lua_request.c | 29 | ||||
-rw-r--r-- | modules/lua/mod_lua.dsp | 8 |
5 files changed, 307 insertions, 0 deletions
diff --git a/modules/lua/NWGNUmakefile b/modules/lua/NWGNUmakefile index 06f1daaac9..15e6c91e76 100644 --- a/modules/lua/NWGNUmakefile +++ b/modules/lua/NWGNUmakefile @@ -181,6 +181,7 @@ FILES_nlm_objs = \ $(OBJDIR)/mod_lua.o \ $(OBJDIR)/lua_apr.o \ $(OBJDIR)/lua_config.o \ + $(OBJDIR)/lua_passwd.o \ $(OBJDIR)/lua_request.o \ $(OBJDIR)/lua_vmprep.o \ $(OBJDIR)/lua_dbd.o \ diff --git a/modules/lua/lua_passwd.c b/modules/lua/lua_passwd.c new file mode 100644 index 0000000000..567712b9d2 --- /dev/null +++ b/modules/lua/lua_passwd.c @@ -0,0 +1,178 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "lua_passwd.h" +#include "apr_strings.h" +#include "apr_errno.h" + +#if APR_HAVE_STDIO_H +#include <stdio.h> +#endif + +#include "apr_md5.h" +#include "apr_sha1.h" + +#if APR_HAVE_TIME_H +#include <time.h> +#endif +#if APR_HAVE_CRYPT_H +#include <crypt.h> +#endif +#if APR_HAVE_STDLIB_H +#include <stdlib.h> +#endif +#if APR_HAVE_STRING_H +#include <string.h> +#endif +#if APR_HAVE_UNISTD_H +#include <unistd.h> +#endif +#if APR_HAVE_IO_H +#include <io.h> +#endif + +static int generate_salt(char *s, size_t size, const char **errstr, + apr_pool_t *pool) +{ + unsigned char rnd[32]; + static const char itoa64[] = + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + apr_size_t n; + unsigned int val = 0, bits = 0; + apr_status_t rv; + + n = (size * 6 + 7)/8; + if (n > sizeof(rnd)) { + *errstr = apr_psprintf(pool, "generate_salt(): BUG: Buffer too small"); + return ERR_RANDOM; + } + rv = apr_generate_random_bytes(rnd, n); + if (rv) { + *errstr = apr_psprintf(pool, "Unable to generate random bytes: %pm", + &rv); + return ERR_RANDOM; + } + n = 0; + while (size > 0) { + if (bits < 6) { + val |= (rnd[n++] << bits); + bits += 8; + } + *s++ = itoa64[val & 0x3f]; + size--; + val >>= 6; + bits -= 6; + } + *s = '\0'; + return 0; +} + +/* + * Make a password record from the given information. A zero return + * indicates success; on failure, ctx->errstr points to the error message. + */ +int mk_password_hash(passwd_ctx *ctx) +{ + char *pw; + char salt[16]; + apr_status_t rv; + int ret = 0; +#if CRYPT_ALGO_SUPPORTED + char *cbuf; +#endif + + pw = ctx->passwd; + switch (ctx->alg) { + case ALG_APSHA: + /* XXX out >= 28 + strlen(sha1) chars - fixed len SHA */ + apr_sha1_base64(pw, strlen(pw), ctx->out); + break; + + case ALG_APMD5: + ret = generate_salt(salt, 8, &ctx->errstr, ctx->pool); + if (ret != 0) { + ret = ERR_GENERAL; + break; + } + rv = apr_md5_encode(pw, salt, ctx->out, ctx->out_len); + if (rv != APR_SUCCESS) { + ctx->errstr = apr_psprintf(ctx->pool, + "could not encode password: %pm", &rv); + ret = ERR_GENERAL; + } + break; + +#if CRYPT_ALGO_SUPPORTED + case ALG_CRYPT: + ret = generate_salt(salt, 8, &ctx->errstr, ctx->pool); + if (ret != 0) + break; + cbuf = crypt(pw, salt); + if (cbuf == NULL) { + rv = APR_FROM_OS_ERROR(errno); + ctx->errstr = apr_psprintf(ctx->pool, "crypt() failed: %pm", &rv); + ret = ERR_PWMISMATCH; + break; + } + + apr_cpystrn(ctx->out, cbuf, ctx->out_len - 1); + if (strlen(pw) > 8) { + char *truncpw = apr_pstrdup(ctx->pool, pw); + truncpw[8] = '\0'; + if (!strcmp(ctx->out, crypt(truncpw, salt))) { + ctx->errstr = apr_psprintf(ctx->pool, + "Warning: Password truncated to 8 " + "characters by CRYPT algorithm."); + } + memset(truncpw, '\0', strlen(pw)); + free(truncpw); + } + break; +#endif /* CRYPT_ALGO_SUPPORTED */ + +#if BCRYPT_ALGO_SUPPORTED + case ALG_BCRYPT: + rv = apr_generate_random_bytes((unsigned char*)salt, 16); + if (rv != APR_SUCCESS) { + ctx->errstr = apr_psprintf(ctx->pool, "Unable to generate random " + "bytes: %pm", &rv); + ret = ERR_RANDOM; + break; + } + + if (ctx->cost == 0) + ctx->cost = BCRYPT_DEFAULT_COST; + rv = apr_bcrypt_encode(pw, ctx->cost, (unsigned char*)salt, 16, + ctx->out, ctx->out_len); + if (rv != APR_SUCCESS) { + ctx->errstr = apr_psprintf(ctx->pool, "Unable to encode with " + "bcrypt: %pm", &rv); + ret = ERR_PWMISMATCH; + break; + } + break; +#endif /* BCRYPT_ALGO_SUPPORTED */ + + default: + ctx->errstr = apr_psprintf(ctx->pool, + "mk_password_hash(): BUG: invalid algorithm %d", + ctx->alg); + } + memset(pw, '\0', strlen(pw)); + return ret; +} + + diff --git a/modules/lua/lua_passwd.h b/modules/lua/lua_passwd.h new file mode 100644 index 0000000000..797556bf7b --- /dev/null +++ b/modules/lua/lua_passwd.h @@ -0,0 +1,91 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _LUA_PASSWD_H +#define _LUA_PASSWD_H + +#include "apr.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include "apr_errno.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_version.h" +#if !APR_VERSION_AT_LEAST(2,0,0) +#include "apu_version.h" +#endif + +#define MAX_PASSWD_LEN 256 + +#define ALG_APMD5 0 +#define ALG_APSHA 1 +#define ALG_BCRYPT 2 +#define ALG_CRYPT 3 + +#define BCRYPT_DEFAULT_COST 5 + +#define ERR_FILEPERM 1 +#define ERR_SYNTAX 2 +#define ERR_PWMISMATCH 3 +#define ERR_INTERRUPTED 4 +#define ERR_OVERFLOW 5 +#define ERR_BADUSER 6 +#define ERR_INVALID 7 +#define ERR_RANDOM 8 +#define ERR_GENERAL 9 +#define ERR_ALG_NOT_SUPP 10 + +#if defined(WIN32) || defined(NETWARE) +#define CRYPT_ALGO_SUPPORTED 0 +#define PLAIN_ALGO_SUPPORTED 1 +#else +#define CRYPT_ALGO_SUPPORTED 1 +#define PLAIN_ALGO_SUPPORTED 0 +#endif + +#if APR_VERSION_AT_LEAST(2,0,0) || \ + (APU_MAJOR_VERSION == 1 && APU_MINOR_VERSION >= 5) +#define BCRYPT_ALGO_SUPPORTED 1 +#else +#define BCRYPT_ALGO_SUPPORTED 0 +#endif + +typedef struct passwd_ctx passwd_ctx; + +struct passwd_ctx { + apr_pool_t *pool; + const char *errstr; + char *out; + apr_size_t out_len; +// const char *passwd; + char *passwd; + int alg; + int cost; +}; + + +/* + * The following functions return zero on success; otherwise, one of + * the ERR_* codes is returned and an error message is stored in ctx->errstr. + */ + +/* + * Make a password record from the given information. + */ +int mk_password_hash(passwd_ctx *ctx); + +#endif /* _LUA_PASSWD_H */ + diff --git a/modules/lua/lua_request.c b/modules/lua/lua_request.c index a52888b406..8b6ef16e72 100644 --- a/modules/lua/lua_request.c +++ b/modules/lua/lua_request.c @@ -18,6 +18,7 @@ #include "mod_lua.h" #include "lua_apr.h" #include "lua_dbd.h" +#include "lua_passwd.h" #include "scoreboard.h" #include "util_md5.h" #include "util_script.h" @@ -842,6 +843,32 @@ static int lua_apr_sha1(lua_State *L) return 1; } +/* + * lua_apr_htpassword; r:htpassword(string [, algorithm [, cost]]) - Creates + * a htpassword hash from a string + */ +static int lua_apr_htpassword(lua_State *L) +{ + passwd_ctx ctx = { 0 }; + request_rec *r; + + r = ap_lua_check_request_rec(L, 1); + luaL_checktype(L, 2, LUA_TSTRING); + ctx.passwd = apr_pstrdup(r->pool, lua_tostring(L, 2)); + ctx.alg = luaL_optinteger(L, 3, ALG_APMD5); + ctx.cost = luaL_optinteger(L, 4, 0); + ctx.pool = r->pool; + ctx.out = apr_pcalloc(r->pool, MAX_PASSWD_LEN); + ctx.out_len = MAX_PASSWD_LEN; + if (mk_password_hash(&ctx)) { + lua_pushboolean(L, 0); + lua_pushstring(L, ctx.errstr); + return 2; + } else { + lua_pushstring(L, ctx.out); + } + return 1; +} /* * lua_ap_mpm_query; r:mpm_query(info) - Queries for MPM info @@ -2050,6 +2077,8 @@ void ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p) makefun(&lua_apr_md5, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "sha1", APR_HASH_KEY_STRING, makefun(&lua_apr_sha1, APL_REQ_FUNTYPE_LUACFUN, p)); + apr_hash_set(dispatch, "htpassword", APR_HASH_KEY_STRING, + makefun(&lua_apr_htpassword, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "escape", APR_HASH_KEY_STRING, makefun(&lua_ap_escape, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "unescape", APR_HASH_KEY_STRING, diff --git a/modules/lua/mod_lua.dsp b/modules/lua/mod_lua.dsp index 71d33b8bfb..770c13a13e 100644 --- a/modules/lua/mod_lua.dsp +++ b/modules/lua/mod_lua.dsp @@ -117,6 +117,14 @@ SOURCE=.\lua_config.h # End Source File # Begin Source File +SOURCE=.\lua_passwd.c +# End Source File +# Begin Source File + +SOURCE=.\lua_passwd.h +# End Source File +# Begin Source File + SOURCE=.\lua_request.c # End Source File # Begin Source File |