1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "lua_passwd.h"
18 #include "apr_strings.h"
19 #include "apr_errno.h"
47 static int generate_salt(char *s, size_t size, const char **errstr,
50 unsigned char rnd[32];
51 static const char itoa64[] =
52 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
54 unsigned int val = 0, bits = 0;
58 if (n > sizeof(rnd)) {
59 *errstr = apr_psprintf(pool, "generate_salt(): BUG: Buffer too small");
62 rv = apr_generate_random_bytes(rnd, n);
64 *errstr = apr_psprintf(pool, "Unable to generate random bytes: %pm",
71 val |= (rnd[n++] << bits);
74 *s++ = itoa64[val & 0x3f];
84 * Make a password record from the given information. A zero return
85 * indicates success; on failure, ctx->errstr points to the error message.
87 int mk_password_hash(passwd_ctx *ctx)
93 #if CRYPT_ALGO_SUPPORTED
100 /* XXX out >= 28 + strlen(sha1) chars - fixed len SHA */
101 apr_sha1_base64(pw, strlen(pw), ctx->out);
105 ret = generate_salt(salt, 8, &ctx->errstr, ctx->pool);
110 rv = apr_md5_encode(pw, salt, ctx->out, ctx->out_len);
111 if (rv != APR_SUCCESS) {
112 ctx->errstr = apr_psprintf(ctx->pool,
113 "could not encode password: %pm", &rv);
118 #if CRYPT_ALGO_SUPPORTED
120 ret = generate_salt(salt, 8, &ctx->errstr, ctx->pool);
123 cbuf = crypt(pw, salt);
125 rv = APR_FROM_OS_ERROR(errno);
126 ctx->errstr = apr_psprintf(ctx->pool, "crypt() failed: %pm", &rv);
127 ret = ERR_PWMISMATCH;
131 apr_cpystrn(ctx->out, cbuf, ctx->out_len - 1);
132 if (strlen(pw) > 8) {
133 char *truncpw = apr_pstrdup(ctx->pool, pw);
135 if (!strcmp(ctx->out, crypt(truncpw, salt))) {
136 ctx->errstr = apr_psprintf(ctx->pool,
137 "Warning: Password truncated to 8 "
138 "characters by CRYPT algorithm.");
140 memset(truncpw, '\0', strlen(pw));
143 #endif /* CRYPT_ALGO_SUPPORTED */
145 #if BCRYPT_ALGO_SUPPORTED
147 rv = apr_generate_random_bytes((unsigned char*)salt, 16);
148 if (rv != APR_SUCCESS) {
149 ctx->errstr = apr_psprintf(ctx->pool, "Unable to generate random "
156 ctx->cost = BCRYPT_DEFAULT_COST;
157 rv = apr_bcrypt_encode(pw, ctx->cost, (unsigned char*)salt, 16,
158 ctx->out, ctx->out_len);
159 if (rv != APR_SUCCESS) {
160 ctx->errstr = apr_psprintf(ctx->pool, "Unable to encode with "
162 ret = ERR_PWMISMATCH;
166 #endif /* BCRYPT_ALGO_SUPPORTED */
169 ctx->errstr = apr_psprintf(ctx->pool,
170 "mk_password_hash(): unsupported algorithm %d",
174 memset(pw, '\0', strlen(pw));