mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2025-01-03 14:56:34 -05:00
commit
d7f401e36c
30
configure.ac
30
configure.ac
@ -100,6 +100,7 @@ AC_CHECK_HEADERS([sys/timeb.h])
|
||||
AC_CHECK_HEADERS([sys/socket.h])
|
||||
AC_CHECK_HEADERS([pwd.h grp.h])
|
||||
AC_CHECK_HEADERS([sys/resource.h])
|
||||
AC_CHECK_HEADERS([crypt.h])
|
||||
|
||||
AC_C_BIGENDIAN
|
||||
|
||||
@ -122,6 +123,15 @@ AC_CHECK_FUNCS([gettimeofday])
|
||||
AC_CHECK_FUNCS([ftime])
|
||||
AC_CHECK_FUNCS([getrlimit])
|
||||
|
||||
dnl check for crypt():
|
||||
AC_SEARCH_LIBS([crypt_r], [crypt], [
|
||||
AC_DEFINE([HAVE_CRYPT_R], [1], [Define if you have crypt_r])
|
||||
], [
|
||||
AC_SEARCH_LIBS([crypt], [crypt], [
|
||||
AC_DEFINE([HAVE_CRYPT], [1], [Define if you have crypt])
|
||||
])
|
||||
])
|
||||
|
||||
dnl Do not check for poll on Darwin, it is broken in some versions
|
||||
AS_IF([test "${SYS}" != "darwin"], [
|
||||
AC_CHECK_FUNCS([poll])
|
||||
@ -226,6 +236,26 @@ PKG_HAVE_WITH_MODULES([OPENSSL], [openssl >= 1.1.0], [
|
||||
LIBS="${LIBS} ${OPENSSL_LIBS}"
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl librhash - first try pkgconfig and then basic search
|
||||
dnl since the function is defined in rhash.h we need to check for that first,
|
||||
dnl before we can check for the function, bit crude but seems to work.
|
||||
dnl
|
||||
|
||||
PKG_CHECK_MODULES([LIBRHASH], [librhash], [
|
||||
CFLAGS="${CFLAGS} ${LIBRHASH_CFLAGS}"
|
||||
LIBS="${LIBS} ${LIBRHASH_LIBS}"
|
||||
], [
|
||||
AC_CHECK_HEADER([rhash.h], [
|
||||
AC_CHECK_LIB(rhash, rhash_library_init, [], [
|
||||
AC_MSG_ERROR([${LIBRHASH_PKG_ERRORS}. librhash is required.])
|
||||
])
|
||||
], [
|
||||
AC_MSG_ERROR([${LIBRHASH_PKG_ERRORS}. librhash is required.])
|
||||
])
|
||||
])
|
||||
|
||||
|
||||
dnl Check for library-specific functions
|
||||
AC_CHECK_FUNCS([xsltSaveResultToString])
|
||||
|
||||
|
@ -17,6 +17,7 @@ noinst_HEADERS = \
|
||||
global.h \
|
||||
util.h \
|
||||
util_string.h \
|
||||
util_crypt.h \
|
||||
errors.h \
|
||||
curl.h \
|
||||
slave.h \
|
||||
@ -29,7 +30,6 @@ noinst_HEADERS = \
|
||||
fserve.h \
|
||||
xslt.h \
|
||||
yp.h \
|
||||
md5.h \
|
||||
digest.h \
|
||||
prng.h \
|
||||
matchfile.h \
|
||||
@ -71,6 +71,7 @@ icecast_SOURCES = \
|
||||
global.c \
|
||||
util.c \
|
||||
util_string.c \
|
||||
util_crypt.c \
|
||||
errors.c \
|
||||
slave.c \
|
||||
source.c \
|
||||
@ -82,7 +83,6 @@ icecast_SOURCES = \
|
||||
fserve.c \
|
||||
admin.c \
|
||||
resourcematch.c \
|
||||
md5.c \
|
||||
digest.c \
|
||||
prng.c \
|
||||
matchfile.c \
|
||||
|
21
src/admin.c
21
src/admin.c
@ -80,6 +80,7 @@
|
||||
#include "reportxml.h"
|
||||
#include "reportxml_helper.h"
|
||||
#include "xml2json.h"
|
||||
#include "util_crypt.h"
|
||||
|
||||
#include "format.h"
|
||||
|
||||
@ -1839,6 +1840,10 @@ static void command_dashboard (client_t *client, source_t *source, adm
|
||||
}
|
||||
}
|
||||
|
||||
if (!util_crypt_is_new_secure()) {
|
||||
__reportxml_add_maintenance(reportnode, config->reportxml_db, "40d134e3-fbbe-46b1-a409-9b2ca8954528", "warning", "No secure password hash support detected.", NULL);
|
||||
}
|
||||
|
||||
reportxml_helper_add_value_health(resource, "status", health);
|
||||
|
||||
reportxml_node_add_child(incident, resource);
|
||||
@ -1922,6 +1927,12 @@ static void command_version (client_t *client, source_t *source, adm
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
"getaddrinfo",
|
||||
#endif
|
||||
#ifdef HAVE_CRYPT
|
||||
"crypt",
|
||||
#endif
|
||||
#ifdef HAVE_CRYPT_R
|
||||
"crypt_r",
|
||||
#endif
|
||||
#ifdef WIN32
|
||||
"win32",
|
||||
#endif
|
||||
@ -2035,6 +2046,16 @@ static void command_version (client_t *client, source_t *source, adm
|
||||
reportxml_helper_add_value_flag(rflags, "bound-inet6", listensocket_container_is_family_included(global.listensockets, SOCK_FAMILY_INET6));
|
||||
global_unlock();
|
||||
|
||||
reportxml_helper_add_value_flag(rflags, "crypt-1", util_crypt_is_supported("$1$"));
|
||||
reportxml_helper_add_value_flag(rflags, "crypt-3", util_crypt_is_supported("$3$"));
|
||||
reportxml_helper_add_value_flag(rflags, "crypt-5", util_crypt_is_supported("$5$"));
|
||||
reportxml_helper_add_value_flag(rflags, "crypt-6", util_crypt_is_supported("$6$"));
|
||||
reportxml_helper_add_value_flag(rflags, "crypt-7", util_crypt_is_supported("$7$"));
|
||||
reportxml_helper_add_value_flag(rflags, "crypt-md5", util_crypt_is_supported("$md5$"));
|
||||
reportxml_helper_add_value_flag(rflags, "crypt-sha1", util_crypt_is_supported("$sha1$"));
|
||||
reportxml_helper_add_value_flag(rflags, "crypt-y", util_crypt_is_supported("$y$"));
|
||||
reportxml_helper_add_value_flag(rflags, "crypt-gy", util_crypt_is_supported("$gy$"));
|
||||
|
||||
refobject_unref(config);
|
||||
refobject_unref(dependencies);
|
||||
refobject_unref(cflags);
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include "client.h"
|
||||
#include "cfgfile.h"
|
||||
#include "common/httpp/httpp.h"
|
||||
#include "md5.h"
|
||||
#include "util_crypt.h"
|
||||
|
||||
#include "logging.h"
|
||||
#define CATMODULE "auth_htpasswd"
|
||||
@ -68,22 +68,6 @@ static void htpasswd_clear(auth_t *self)
|
||||
}
|
||||
|
||||
|
||||
/* md5 hash */
|
||||
static char *get_hash(const char *data, int len)
|
||||
{
|
||||
struct MD5Context context;
|
||||
unsigned char digest[16];
|
||||
|
||||
MD5Init(&context);
|
||||
|
||||
MD5Update(&context, (const unsigned char *)data, len);
|
||||
|
||||
MD5Final(digest, &context);
|
||||
|
||||
return util_bin_to_hex(digest, 16);
|
||||
}
|
||||
|
||||
|
||||
static int compare_users(void *arg, void *a, void *b)
|
||||
{
|
||||
htpasswd_user *user1 = (htpasswd_user *)a;
|
||||
@ -200,15 +184,11 @@ static auth_result htpasswd_auth (auth_client *auth_user)
|
||||
entry.name = client->username;
|
||||
if (avl_get_by_key (htpasswd->users, &entry, &result) == 0) {
|
||||
htpasswd_user *found = result;
|
||||
char *hashed_pw;
|
||||
|
||||
thread_rwlock_unlock (&htpasswd->file_rwlock);
|
||||
hashed_pw = get_hash (client->password, strlen (client->password));
|
||||
if (strcmp (found->pass, hashed_pw) == 0) {
|
||||
free (hashed_pw);
|
||||
if (util_crypt_check(client->password, found->pass)) {
|
||||
return AUTH_OK;
|
||||
}
|
||||
free (hashed_pw);
|
||||
ICECAST_LOG_DEBUG("incorrect password for client with username: %s", client->username);
|
||||
return AUTH_FAILED;
|
||||
}
|
||||
@ -291,7 +271,7 @@ static auth_result htpasswd_adduser (auth_t *auth, const char *username, const c
|
||||
return AUTH_FAILED;
|
||||
}
|
||||
|
||||
hashed_password = get_hash(password, strlen(password));
|
||||
hashed_password = util_crypt_hash(password);
|
||||
if (hashed_password) {
|
||||
fprintf(passwdfile, "%s:%s\n", username, hashed_password);
|
||||
free(hashed_password);
|
||||
|
@ -16,11 +16,13 @@
|
||||
|
||||
/* for strcmp() and strdup() */
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "auth.h"
|
||||
#include "cfgfile.h"
|
||||
#include "client.h"
|
||||
#include "util.h"
|
||||
#include "util_crypt.h"
|
||||
|
||||
#include "logging.h"
|
||||
#define CATMODULE "auth_static"
|
||||
@ -30,6 +32,7 @@ typedef struct auth_static {
|
||||
char *password;
|
||||
auth_alter_t action;
|
||||
char *arg;
|
||||
bool is_hashed;
|
||||
} auth_static_t;
|
||||
|
||||
static auth_result static_auth(auth_client *auth_user)
|
||||
@ -48,8 +51,13 @@ static auth_result static_auth(auth_client *auth_user)
|
||||
if (!client->password)
|
||||
return AUTH_NOMATCH;
|
||||
|
||||
if (strcmp(auth_info->password, client->password) != 0)
|
||||
return AUTH_FAILED;
|
||||
if (auth_info->is_hashed) {
|
||||
if (!util_crypt_check(client->password, auth_info->password))
|
||||
return AUTH_FAILED;
|
||||
} else {
|
||||
if (strcmp(auth_info->password, client->password) != 0)
|
||||
return AUTH_FAILED;
|
||||
}
|
||||
|
||||
|
||||
if (auth_info->action != AUTH_ALTER_NOOP) {
|
||||
@ -118,6 +126,8 @@ int auth_get_static_auth (auth_t *authenticator, config_options_t *options)
|
||||
if (auth_info->password)
|
||||
free(auth_info->password);
|
||||
auth_info->password = strdup(options->value);
|
||||
} else if (strcmp(options->name, "hashed") == 0) {
|
||||
auth_info->is_hashed = util_str_to_bool(options->value);
|
||||
} else if (strcmp(options->name, "action") == 0) {
|
||||
auth_info->action = auth_str2alter(options->value);
|
||||
if (auth_info->action == AUTH_ALTER_NOOP) {
|
||||
|
27
src/digest.c
27
src/digest.c
@ -17,7 +17,6 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "digest.h"
|
||||
#include "md5.h"
|
||||
|
||||
#include "logging.h"
|
||||
#define CATMODULE "digest"
|
||||
@ -32,7 +31,6 @@ struct digest_tag {
|
||||
/* state */
|
||||
int done;
|
||||
union {
|
||||
struct MD5Context md5;
|
||||
struct {
|
||||
/* 1600 bits algorithm hashing state */
|
||||
uint64_t hash[25];
|
||||
@ -328,9 +326,6 @@ const char *digest_algo_id2str(digest_algo_t algo)
|
||||
{
|
||||
switch (algo) {
|
||||
|
||||
case DIGEST_ALGO_MD5:
|
||||
return "MD5";
|
||||
break;
|
||||
case DIGEST_ALGO_SHA3_224:
|
||||
return "SHA3-224";
|
||||
break;
|
||||
@ -350,9 +345,6 @@ const char *digest_algo_id2str(digest_algo_t algo)
|
||||
ssize_t digest_algo_length_bytes(digest_algo_t algo)
|
||||
{
|
||||
switch (algo) {
|
||||
case DIGEST_ALGO_MD5:
|
||||
return 16;
|
||||
break;
|
||||
case DIGEST_ALGO_SHA3_224:
|
||||
return 224/8;
|
||||
break;
|
||||
@ -379,9 +371,6 @@ digest_t * digest_new(digest_algo_t algo)
|
||||
|
||||
digest->algo = algo;
|
||||
switch (algo) {
|
||||
case DIGEST_ALGO_MD5:
|
||||
MD5Init(&(digest->state.md5));
|
||||
break;
|
||||
case DIGEST_ALGO_SHA3_224:
|
||||
sha3_init(digest, 224);
|
||||
break;
|
||||
@ -427,10 +416,6 @@ ssize_t digest_write(digest_t *digest, const void *data, size_t len)
|
||||
return -1;
|
||||
|
||||
switch (digest->algo) {
|
||||
case DIGEST_ALGO_MD5:
|
||||
MD5Update(&(digest->state.md5), (const unsigned char *)data, len);
|
||||
return len;
|
||||
break;
|
||||
case DIGEST_ALGO_SHA3_224:
|
||||
case DIGEST_ALGO_SHA3_256:
|
||||
case DIGEST_ALGO_SHA3_384:
|
||||
@ -455,17 +440,6 @@ ssize_t digest_read(digest_t *digest, void *buf, size_t len)
|
||||
digest->done = 1;
|
||||
|
||||
switch (digest->algo) {
|
||||
case DIGEST_ALGO_MD5:
|
||||
if (len < HASH_LEN) {
|
||||
unsigned char buffer[HASH_LEN];
|
||||
MD5Final(buffer, &(digest->state.md5));
|
||||
memcpy(buf, buffer, len);
|
||||
return len;
|
||||
} else {
|
||||
MD5Final((unsigned char*)buf, &(digest->state.md5));
|
||||
return HASH_LEN;
|
||||
}
|
||||
break;
|
||||
case DIGEST_ALGO_SHA3_224:
|
||||
case DIGEST_ALGO_SHA3_256:
|
||||
case DIGEST_ALGO_SHA3_384:
|
||||
@ -490,7 +464,6 @@ ssize_t digest_length_bytes(digest_t *digest)
|
||||
static size_t __digest_algo_blocklength(digest_algo_t algo)
|
||||
{
|
||||
switch (algo) {
|
||||
case DIGEST_ALGO_MD5: return 64; break;
|
||||
case DIGEST_ALGO_SHA3_224: return 144; break;
|
||||
case DIGEST_ALGO_SHA3_256: return 136; break;
|
||||
case DIGEST_ALGO_SHA3_384: return 104; break;
|
||||
|
@ -15,7 +15,6 @@ REFOBJECT_FORWARD_TYPE(digest_t);
|
||||
REFOBJECT_FORWARD_TYPE(hmac_t);
|
||||
|
||||
typedef enum {
|
||||
DIGEST_ALGO_MD5,
|
||||
DIGEST_ALGO_SHA3_224,
|
||||
DIGEST_ALGO_SHA3_256,
|
||||
DIGEST_ALGO_SHA3_384,
|
||||
|
@ -62,6 +62,8 @@
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
|
||||
#include <rhash.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "cfgfile.h"
|
||||
#include "util.h"
|
||||
@ -604,6 +606,11 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* likely libigloo already did this for us, however how should we know?
|
||||
* Still/Only required for htpasswd MD5 support.
|
||||
*/
|
||||
rhash_library_init();
|
||||
|
||||
/* parse the '-c icecast.xml' option
|
||||
** only, so that we can read a configfile
|
||||
*/
|
||||
|
280
src/md5.c
280
src/md5.c
@ -1,280 +0,0 @@
|
||||
/* Icecast
|
||||
*
|
||||
* This program is distributed under the GNU General Public License, version 2.
|
||||
* A copy of this license is included with this source.
|
||||
*
|
||||
* Copyright 2000-2004, Jack Moffitt <jack@xiph.org,
|
||||
* Michael Smith <msmith@xiph.org>,
|
||||
* oddsock <oddsock@xiph.org>,
|
||||
* Karl Heyes <karl@xiph.org>
|
||||
* and others (see AUTHORS for details).
|
||||
* Copyright 2014-2015, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
|
||||
*/
|
||||
|
||||
/*
|
||||
* md5.c
|
||||
*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5Context structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*/
|
||||
|
||||
/* Modified for icecast by Mike Smith <msmith@xiph.org>, mostly changing header
|
||||
* and type definitions
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include "compat.h"
|
||||
#include "md5.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static void MD5Transform(uint32_t buf[4], uint32_t const in[HASH_LEN]);
|
||||
|
||||
/*
|
||||
* Note: this code is harmless on little-endian machines.
|
||||
*/
|
||||
static void byteReverse(unsigned char *buf, unsigned longs)
|
||||
{
|
||||
uint32_t t;
|
||||
do
|
||||
{
|
||||
t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
|
||||
((unsigned) buf[1] << 8 | buf[0]);
|
||||
*(uint32_t *) buf = t;
|
||||
buf += 4;
|
||||
}
|
||||
while (--longs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
void MD5Init(struct MD5Context *ctx)
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bits[0] = 0;
|
||||
ctx->bits[1] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
void MD5Update(struct MD5Context *ctx, unsigned char const *buf,
|
||||
unsigned len)
|
||||
{
|
||||
uint32_t t;
|
||||
|
||||
/* Update bitcount */
|
||||
|
||||
t = ctx->bits[0];
|
||||
if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t)
|
||||
ctx->bits[1]++;
|
||||
|
||||
/* Carry from low to high */
|
||||
ctx->bits[1] += len >> 29;
|
||||
|
||||
t = (t >> 3) & 0x3f;
|
||||
/* Bytes already in shsInfo->data */
|
||||
|
||||
/* Handle any leading odd-sized chunks */
|
||||
if (t)
|
||||
{
|
||||
unsigned char *p = (unsigned char *) ctx->in + t;
|
||||
t = 64 - t;
|
||||
if (len < t)
|
||||
{
|
||||
memcpy(p, buf, len);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(p, buf, t);
|
||||
byteReverse(ctx->in, HASH_LEN);
|
||||
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
}
|
||||
/* Process data in 64-byte chunks */
|
||||
|
||||
while (len >= 64)
|
||||
{
|
||||
memcpy(ctx->in, buf, 64);
|
||||
byteReverse(ctx->in, HASH_LEN);
|
||||
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
memcpy(ctx->in, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void MD5Final(unsigned char digest[HASH_LEN], struct MD5Context *ctx)
|
||||
{
|
||||
unsigned count;
|
||||
unsigned char *p;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
count = (ctx->bits[0] >> 3) & 0x3F;
|
||||
|
||||
/* Set the first char of padding to 0x80. This is safe since there is
|
||||
always at least one byte free */
|
||||
p = ctx->in + count;
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 64 bytes */
|
||||
count = 64 - 1 - count;
|
||||
|
||||
/* Pad out to 56 mod 64 */
|
||||
if (count < 8)
|
||||
{
|
||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||
memset(p, 0, count);
|
||||
byteReverse(ctx->in, HASH_LEN);
|
||||
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
|
||||
/* Now fill the next block with 56 bytes */
|
||||
memset(ctx->in, 0, 56);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Pad block to 56 bytes */
|
||||
memset(p, 0, count - 8);
|
||||
}
|
||||
byteReverse(ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
((uint32_t *) ctx->in)[14] = ctx->bits[0];
|
||||
((uint32_t *) ctx->in)[15] = ctx->bits[1];
|
||||
|
||||
MD5Transform(ctx->buf, (uint32_t *) ctx->in);
|
||||
byteReverse((unsigned char *) ctx->buf, 4);
|
||||
memcpy(digest, ctx->buf, HASH_LEN);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
/* In case it's sensitive */
|
||||
}
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
# define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
# define F2(x, y, z) F1(z, x, y)
|
||||
# define F3(x, y, z) (x ^ y ^ z)
|
||||
# define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
# define MD5STEP(f, w, x, y, z, data, s) do { w += f(x, y, z) + data; w = (w<<s) | (w>>(32-s)); w += x; }while(0)
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
static void MD5Transform(uint32_t buf[4], uint32_t const in[HASH_LEN])
|
||||
{
|
||||
register uint32_t a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
35
src/md5.h
35
src/md5.h
@ -1,35 +0,0 @@
|
||||
/* Icecast
|
||||
*
|
||||
* This program is distributed under the GNU General Public License, version 2.
|
||||
* A copy of this license is included with this source.
|
||||
*
|
||||
* Copyright 2000-2004, Jack Moffitt <jack@xiph.org,
|
||||
* Michael Smith <msmith@xiph.org>,
|
||||
* oddsock <oddsock@xiph.org>,
|
||||
* Karl Heyes <karl@xiph.org>
|
||||
* and others (see AUTHORS for details).
|
||||
*/
|
||||
|
||||
#ifndef __MD5_H__
|
||||
#define __MD5_H__
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
#define HASH_LEN 16
|
||||
|
||||
struct MD5Context
|
||||
{
|
||||
uint32_t buf[4];
|
||||
uint32_t bits[2];
|
||||
unsigned char in[64];
|
||||
};
|
||||
|
||||
void MD5Init(struct MD5Context *context);
|
||||
void MD5Update(struct MD5Context *context, unsigned char const *buf,
|
||||
unsigned len);
|
||||
void MD5Final(unsigned char digest[HASH_LEN], struct MD5Context *context);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -33,5 +33,11 @@ ctest_string_renderer_test_LDADD = \
|
||||
icecast-string_renderer.o
|
||||
check_PROGRAMS += ctest_string_renderer.test
|
||||
|
||||
ctest_crypt_test_SOURCES = tests/ctest_crypt.c
|
||||
ctest_crypt_test_LDADD = \
|
||||
icecast-util_string.o \
|
||||
icecast-util_crypt.o
|
||||
check_PROGRAMS += ctest_crypt.test
|
||||
|
||||
# Add all programs to TESTS
|
||||
TESTS = $(check_PROGRAMS)
|
||||
|
78
src/tests/ctest_crypt.c
Normal file
78
src/tests/ctest_crypt.c
Normal file
@ -0,0 +1,78 @@
|
||||
/* Icecast
|
||||
*
|
||||
* This program is distributed under the GNU General Public License, version 2.
|
||||
* A copy of this license is included with this source.
|
||||
*
|
||||
* Copyright 2018-2023, Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>,
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rhash.h>
|
||||
|
||||
#include <igloo/tap.h>
|
||||
#include <igloo/ro.h>
|
||||
|
||||
#include "../util_crypt.h"
|
||||
|
||||
/* Workaround: Avoiding the need to add global.c */
|
||||
igloo_ro_t igloo_instance = igloo_RO_NULL;
|
||||
|
||||
void test_md5_hash(const char *in, const char *expect, bool positive)
|
||||
{
|
||||
char *out = util_crypt_hash_oldstyle(in);
|
||||
|
||||
if (positive) {
|
||||
igloo_tap_test("md5 positive vector", strcmp(out, expect) == 0);
|
||||
igloo_tap_test("md5 positive match", util_crypt_check(in, expect));
|
||||
} else {
|
||||
igloo_tap_test("md5 negative vector", strcmp(out, expect) != 0);
|
||||
igloo_tap_test("md5 negative match", !util_crypt_check(in, expect));
|
||||
}
|
||||
|
||||
free(out);
|
||||
}
|
||||
|
||||
static void test_md5(void)
|
||||
{
|
||||
struct vector {
|
||||
const char *in;
|
||||
const char *out;
|
||||
};
|
||||
static const struct vector table_pos[] = {
|
||||
{"", "d41d8cd98f00b204e9800998ecf8427e"},
|
||||
{"\n", "68b329da9893e34099c7d8ad5cb9c940"}
|
||||
};
|
||||
static const struct vector table_neg[] = {
|
||||
{"XXX", "d41d8cd98f00b204e9800998ecf8427e"},
|
||||
{"YYY", "1234567890abcdef1234567890abcdef"}
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < (sizeof(table_pos)/sizeof(*table_pos)); i++) {
|
||||
test_md5_hash(table_pos[i].in, table_pos[i].out, true);
|
||||
}
|
||||
|
||||
for (i = 0; i < (sizeof(table_neg)/sizeof(*table_neg)); i++) {
|
||||
test_md5_hash(table_neg[i].in, table_neg[i].out, false);
|
||||
}
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
igloo_tap_init();
|
||||
igloo_tap_exit_on(igloo_TAP_EXIT_ON_FIN, NULL);
|
||||
|
||||
rhash_library_init();
|
||||
|
||||
igloo_tap_group_run("md5 vectors", test_md5);
|
||||
igloo_tap_fin();
|
||||
|
||||
return EXIT_FAILURE; // return failure as we should never reach this point!
|
||||
}
|
||||
|
250
src/util_crypt.c
Normal file
250
src/util_crypt.c
Normal file
@ -0,0 +1,250 @@
|
||||
/* Icecast
|
||||
*
|
||||
* Copyright 2023 Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
|
||||
*
|
||||
* This program is distributed under the GNU General Public License, version 2.
|
||||
* A copy of this license is included with this source.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rhash.h>
|
||||
|
||||
#ifdef HAVE_CRYPT_H
|
||||
#include <crypt.h>
|
||||
#endif
|
||||
|
||||
#if (defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT)) && defined(HAVE_PTHREAD)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include <igloo/prng.h>
|
||||
|
||||
#include "global.h"
|
||||
#include "util_crypt.h"
|
||||
#include "util_string.h"
|
||||
|
||||
#define HASH_LEN 16
|
||||
|
||||
#if !defined(HAVE_CRYPT_R) && defined(HAVE_CRYPT) && defined(HAVE_PTHREAD)
|
||||
static pthread_mutex_t crypt_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
#if (defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT)) && HAVE_PTHREAD
|
||||
struct algo {
|
||||
const char prefix[4];
|
||||
const size_t saltlen;
|
||||
const bool secure;
|
||||
};
|
||||
|
||||
static pthread_once_t crypt_detect = PTHREAD_ONCE_INIT;
|
||||
static const struct algo *new_algo;
|
||||
#define HAVE_new_algo
|
||||
|
||||
void crypt_detect_run(void)
|
||||
{
|
||||
static const struct algo list[] = {{"$6$", 12, true}, {"$5$", 12, true}, {"$1$", 6, false}};
|
||||
|
||||
for (size_t i = 0; i < (sizeof(list)/sizeof(*list)); i++) {
|
||||
if (util_crypt_is_supported(list[i].prefix)) {
|
||||
new_algo = &(list[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
char * util_crypt_hash_oldstyle(const char *pw)
|
||||
{
|
||||
unsigned char digest[HASH_LEN];
|
||||
|
||||
if (rhash_msg(RHASH_MD5, pw, strlen(pw), digest) != 0)
|
||||
return NULL;
|
||||
|
||||
return util_bin_to_hex(digest, HASH_LEN);
|
||||
}
|
||||
|
||||
char * util_crypt_hash(const char *pw)
|
||||
{
|
||||
#if (defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT)) && HAVE_PTHREAD
|
||||
if (pthread_once(&crypt_detect, crypt_detect_run) != 0)
|
||||
return NULL;
|
||||
|
||||
if (new_algo) {
|
||||
char input[128];
|
||||
char salt[64];
|
||||
char *salt_base64;
|
||||
ssize_t len;
|
||||
#ifdef HAVE_CRYPT_R
|
||||
struct crypt_data data;
|
||||
#elif defined(HAVE_CRYPT) && defined(HAVE_PTHREAD)
|
||||
char *data;
|
||||
#endif
|
||||
|
||||
/* if this is true, we have a bug */
|
||||
if (new_algo->saltlen > sizeof(salt))
|
||||
return NULL;
|
||||
|
||||
len = igloo_prng_read(igloo_instance, salt, new_algo->saltlen, igloo_PRNG_FLAG_NONE);
|
||||
if (len != (ssize_t)new_algo->saltlen)
|
||||
return NULL;
|
||||
|
||||
salt_base64 = util_base64_encode(salt, new_algo->saltlen);
|
||||
if (!salt_base64)
|
||||
return NULL;
|
||||
|
||||
snprintf(input, sizeof(input), "%s%s", new_algo->prefix, salt_base64);
|
||||
|
||||
free(salt_base64);
|
||||
|
||||
#ifdef HAVE_CRYPT_R
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
return strdup(crypt_r(pw, input, &data));
|
||||
#elif defined(HAVE_CRYPT) && defined(HAVE_PTHREAD)
|
||||
if (pthread_mutex_lock(&crypt_mutex) != 0)
|
||||
return NULL;
|
||||
|
||||
data = strdup(crypt(pw, input));
|
||||
pthread_mutex_unlock(&crypt_mutex);
|
||||
return data;
|
||||
#else
|
||||
#error "BUG"
|
||||
#endif
|
||||
} else {
|
||||
#endif
|
||||
return util_crypt_hash_oldstyle(pw);
|
||||
#if (defined(HAVE_CRYPT_R) || defined(HAVE_CRYPT)) && HAVE_PTHREAD
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool util_crypt_check(const char *plain, const char *crypted)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (!plain || !crypted)
|
||||
return false;
|
||||
|
||||
len = strlen(crypted);
|
||||
if (!len)
|
||||
return false;
|
||||
|
||||
/* below here we know that plain and crypted are non-null and that crypted is at least one byte long */
|
||||
|
||||
if (len == (HASH_LEN*2) && crypted[0] != '$') {
|
||||
char *digest = util_crypt_hash_oldstyle(plain);
|
||||
bool res;
|
||||
|
||||
if (!digest)
|
||||
return false;
|
||||
|
||||
res = strcmp(digest, crypted) == 0;
|
||||
free(digest);
|
||||
return res;
|
||||
}
|
||||
|
||||
if (crypted[0] == '$') {
|
||||
const char *cres;
|
||||
#ifdef HAVE_CRYPT_R
|
||||
struct crypt_data data;
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
cres = crypt_r(plain, crypted, &data);
|
||||
if (cres && strcmp(crypted, cres) == 0)
|
||||
return true;
|
||||
#elif defined(HAVE_CRYPT) && defined(HAVE_PTHREAD)
|
||||
bool res = false;
|
||||
|
||||
if (pthread_mutex_lock(&crypt_mutex) != 0)
|
||||
return false;
|
||||
|
||||
cres = crypt(plain, crypted);
|
||||
if (cres && strcmp(crypted, cres) == 0)
|
||||
res = true;
|
||||
pthread_mutex_unlock(&crypt_mutex);
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool util_crypt_is_supported(const char *prefix)
|
||||
{
|
||||
static const struct {
|
||||
const char *plain;
|
||||
const char *crypted;
|
||||
const bool expected;
|
||||
} vectors[] = {
|
||||
{"abc", "$1$xxxxxxxx$3GbMJKRcRFz50R9Q96xFb.", true},
|
||||
{"abX", "$1$xxxxxxxx$3GbMJKRcRFz50R9Q96xFb.", false},
|
||||
{"abc", "$1$xxxxxxxx$3GbMJKRcRFz50R9Q96xFbY", false},
|
||||
{"abX", "$1$xxxxxxxx$3GbMJKRcRFz50R9Q96xFbY", false},
|
||||
{"abc", "$3$$e0fba38268d0ec66ef1cb452d5885e53", true},
|
||||
{"abX", "$3$$e0fba38268d0ec66ef1cb452d5885e53", false},
|
||||
{"abc", "$3$$e0fba38268d0ec66ef1cb452d5885e5Y", false},
|
||||
{"abX", "$3$$e0fba38268d0ec66ef1cb452d5885e5Y", false},
|
||||
{"abc", "$5$xxxxxxxxxxxxxxxx$zNpAueQbvBleD3aSz0KwnySLaHSedk8ULXPvT1m7DUC", true},
|
||||
{"abX", "$5$xxxxxxxxxxxxxxxx$zNpAueQbvBleD3aSz0KwnySLaHSedk8ULXPvT1m7DUC", false},
|
||||
{"abc", "$5$xxxxxxxxxxxxxxxx$zNpAueQbvBleD3aSz0KwnySLaHSedk8ULXPvT1m7DUY", false},
|
||||
{"abX", "$5$xxxxxxxxxxxxxxxx$zNpAueQbvBleD3aSz0KwnySLaHSedk8ULXPvT1m7DUY", false},
|
||||
{"abc", "$6$xxxxxxxxxxxxxxxx$yNfBmH1zabagyi9HZwRuCgebrSjfr1zXUE6pFhnTG1BcvINxhgU53sjSUJDnQ5s6FPq8NSIntrpmc5ox87wX5.", true},
|
||||
{"abX", "$6$xxxxxxxxxxxxxxxx$yNfBmH1zabagyi9HZwRuCgebrSjfr1zXUE6pFhnTG1BcvINxhgU53sjSUJDnQ5s6FPq8NSIntrpmc5ox87wX5.", false},
|
||||
{"abc", "$6$xxxxxxxxxxxxxxxx$yNfBmH1zabagyi9HZwRuCgebrSjfr1zXUE6pFhnTG1BcvINxhgU53sjSUJDnQ5s6FPq8NSIntrpmc5ox87wX5Y", false},
|
||||
{"abX", "$6$xxxxxxxxxxxxxxxx$yNfBmH1zabagyi9HZwRuCgebrSjfr1zXUE6pFhnTG1BcvINxhgU53sjSUJDnQ5s6FPq8NSIntrpmc5ox87wX5Y", false},
|
||||
{"abc", "$7$DU..../....2Q9obwLhin8qvQl6sisAO/$n4xOT1fpjmazI6Ekeq3slWypZS0PKKV/QVpUE1X0MH6", true},
|
||||
{"abX", "$7$DU..../....2Q9obwLhin8qvQl6sisAO/$n4xOT1fpjmazI6Ekeq3slWypZS0PKKV/QVpUE1X0MH6", false},
|
||||
{"abc", "$7$DU..../....2Q9obwLhin8qvQl6sisAO/$n4xOT1fpjmazI6Ekeq3slWypZS0PKKV/QVpUE1X0MHY", false},
|
||||
{"abX", "$7$DU..../....2Q9obwLhin8qvQl6sisAO/$n4xOT1fpjmazI6Ekeq3slWypZS0PKKV/QVpUE1X0MHY", false},
|
||||
{"abc", "$md5$GUBv0xjJ$$59nlXSorBz79sJsp1gfwk1", true},
|
||||
{"abX", "$md5$GUBv0xjJ$$59nlXSorBz79sJsp1gfwk1", false},
|
||||
{"abc", "$md5$GUBv0xjJ$$59nlXSorBz79sJsp1gfwkY", false},
|
||||
{"abX", "$md5$GUBv0xjJ$$59nlXSorBz79sJsp1gfwkY", false},
|
||||
{"abc", "$sha1$40000$jtNX3nZ2$Cw.7bEep2dEG6qIx3.0HkiF/YoLW", true},
|
||||
{"abX", "$sha1$40000$jtNX3nZ2$Cw.7bEep2dEG6qIx3.0HkiF/YoLW", false},
|
||||
{"abc", "$sha1$40000$jtNX3nZ2$Cw.7bEep2dEG6qIx3.0HkiF/YoLY", false},
|
||||
{"abX", "$sha1$40000$jtNX3nZ2$Cw.7bEep2dEG6qIx3.0HkiF/YoLY", false},
|
||||
{"abc", "$y$j9T$F5Jx5fExrKuPp53xLKQ..1$aC5fZPrKSlHTuOtuJjdRm7BCdVfOnO9UIkyfXQcyB83", true},
|
||||
{"abX", "$y$j9T$F5Jx5fExrKuPp53xLKQ..1$aC5fZPrKSlHTuOtuJjdRm7BCdVfOnO9UIkyfXQcyB83", false},
|
||||
{"abc", "$y$j9T$F5Jx5fExrKuPp53xLKQ..1$aC5fZPrKSlHTuOtuJjdRm7BCdVfOnO9UIkyfXQcyB8Y", false},
|
||||
{"abX", "$y$j9T$F5Jx5fExrKuPp53xLKQ..1$aC5fZPrKSlHTuOtuJjdRm7BCdVfOnO9UIkyfXQcyB8Y", false},
|
||||
{"abc", "$gy$jCT$HM87v.7RwpQLba8fDjNSk1$3jEy/aqqTrXmZVCK3RqOQJJS8ve8hM5pSUTTkaTO.l5", true},
|
||||
{"abX", "$gy$jCT$HM87v.7RwpQLba8fDjNSk1$3jEy/aqqTrXmZVCK3RqOQJJS8ve8hM5pSUTTkaTO.l5", false},
|
||||
{"abc", "$gy$jCT$HM87v.7RwpQLba8fDjNSk1$3jEy/aqqTrXmZVCK3RqOQJJS8ve8hM5pSUTTkaTO.lY", false},
|
||||
{"abX", "$gy$jCT$HM87v.7RwpQLba8fDjNSk1$3jEy/aqqTrXmZVCK3RqOQJJS8ve8hM5pSUTTkaTO.lY", false}
|
||||
};
|
||||
size_t prefixlen = strlen(prefix);
|
||||
bool supported = false;
|
||||
|
||||
for (size_t i = 0; i < (sizeof(vectors)/sizeof(*vectors)); i++) {
|
||||
if (strncmp(vectors[i].crypted, prefix, prefixlen) == 0) {
|
||||
bool res = util_crypt_check(vectors[i].plain, vectors[i].crypted);
|
||||
if (res != vectors[i].expected)
|
||||
return false;
|
||||
supported = true;
|
||||
}
|
||||
}
|
||||
|
||||
return supported;
|
||||
}
|
||||
|
||||
bool util_crypt_is_new_secure(void)
|
||||
{
|
||||
#ifdef HAVE_new_algo
|
||||
if (pthread_once(&crypt_detect, crypt_detect_run) != 0)
|
||||
return NULL;
|
||||
|
||||
return new_algo->secure;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
22
src/util_crypt.h
Normal file
22
src/util_crypt.h
Normal file
@ -0,0 +1,22 @@
|
||||
/* Icecast
|
||||
*
|
||||
* Copyright 2023 Philipp "ph3-der-loewe" Schafft <lion@lion.leolix.org>
|
||||
*
|
||||
* This program is distributed under the GNU General Public License, version 2.
|
||||
* A copy of this license is included with this source.
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_CRYPT_H__
|
||||
#define __UTIL_CRYPT_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
char * util_crypt_hash(const char *pw);
|
||||
bool util_crypt_check(const char *plain, const char *crypted);
|
||||
bool util_crypt_is_supported(const char *prefix);
|
||||
bool util_crypt_is_new_secure(void);
|
||||
|
||||
/* Exported for tests only!: */
|
||||
char * util_crypt_hash_oldstyle(const char *pw);
|
||||
|
||||
#endif /* __UTIL_CRYPT_H__ */
|
Loading…
Reference in New Issue
Block a user