mirror of
https://github.com/apache/httpd.git
synced 2025-08-08 15:02:10 +03:00
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
This commit is contained in:
@@ -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 \
|
||||
|
178
modules/lua/lua_passwd.c
Normal file
178
modules/lua/lua_passwd.c
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
|
91
modules/lua/lua_passwd.h
Normal file
91
modules/lua/lua_passwd.h
Normal file
@@ -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 */
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user