summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorGuenter Knauf <fuankg@apache.org>2013-06-02 19:31:16 +0000
committerGuenter Knauf <fuankg@apache.org>2013-06-02 19:31:16 +0000
commit5dbd3677fd38758285bff2cfa77673da2a5d8941 (patch)
tree6de2d5c9cc3a8a7b2c1a0368c93e28bb23f0a55b /modules
parent288ff9e014fadd8b3382d3f7be9e896ade0d8c28 (diff)
downloadhttpd-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/NWGNUmakefile1
-rw-r--r--modules/lua/lua_passwd.c178
-rw-r--r--modules/lua/lua_passwd.h91
-rw-r--r--modules/lua/lua_request.c29
-rw-r--r--modules/lua/mod_lua.dsp8
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