Browse Source

[core] Provide safe wrapper for crypt if crypt_r is not available

personal/stbuehler/wip
Stefan Bühler 11 years ago
parent
commit
ab9421a5e1
  1. 9
      configure.ac
  2. 2
      include/lighttpd/utils.h
  3. 19
      src/CMakeLists.txt
  4. 27
      src/common/utils.c
  5. 9
      src/main/plugin_core.c
  6. 27
      src/modules/mod_auth.c

9
configure.ac

@ -305,6 +305,7 @@ AC_ARG_ENABLE(profiler,
AM_CONDITIONAL([WITH_PROFILER], [test "x$profiler" = "xyes"])
dnl search for crypt_r and (fallback) for crypt
save_LIBS=$LIBS
LIBS=
AC_SEARCH_LIBS(crypt_r,crypt,[
@ -314,6 +315,14 @@ AC_SEARCH_LIBS(crypt_r,crypt,[
])
CRYPT_LIB=$LIBS
],[
AC_SEARCH_LIBS(crypt,crypt,[
AC_CHECK_HEADERS([crypt.h],[
AC_DEFINE([HAVE_CRYPT_H], [1], [crypt.h])
])
CRYPT_LIB=$LIBS
])
])
LIBS=$save_LIBS
AC_SUBST(CRYPT_LIB)

2
include/lighttpd/utils.h

@ -101,6 +101,8 @@ LI_API gsize li_dirent_buf_size(DIR * dirp);
LI_API void li_apr_sha1_base64(GString *dest, const GString *passwd);
LI_API void li_apr_md5_crypt(GString *dest, const GString *password, const GString *salt);
LI_API void li_safe_crypt(GString *dest, const GString *password, const GString *salt);
INLINE GString* _li_g_string_append_len(GString *s, const gchar *val, gssize len);
INLINE void li_g_string_clear(GString *s);

19
src/CMakeLists.txt

@ -50,12 +50,15 @@ CHECK_INCLUDE_FILES(execinfo.h HAVE_EXECINFO_H)
CHECK_INCLUDE_FILES(crypt.h HAVE_CRYPT_H)
IF(HAVE_CRYPT_H)
# check if we need libcrypt for crypt_r()
CHECK_LIBRARY_EXISTS(crypt crypt_r "" HAVE_LIBCRYPT)
CHECK_LIBRARY_EXISTS(crypt crypt_r "" HAVE_LIBCRYPT_CRYPT_R)
IF(HAVE_LIBCRYPT_CRYPT_R)
SET(HAVE_CRYPT_R 1 FORCE)
SET(HAVE_LIBCRYPT 1 FORCE)
ELSE(HAVE_LIBCRYPT_CRYPT_R)
CHECK_LIBRARY_EXISTS(crypt crypt "" HAVE_LIBCRYPT)
ENDIF(HAVE_LIBCRYPT_CRYPT_R)
ENDIF(HAVE_CRYPT_H)
CHECK_FUNCTION_EXISTS(crypt_r HAVE_CRYPT_R)
IF(HAVE_LIBCRYPT)
SET(HAVE_CRYPT_R 1 FORCE)
ENDIF(HAVE_LIBCRYPT)
CHECK_LIBRARY_EXISTS(kvm kvm_open "" HAVE_LIBKVM)
@ -363,10 +366,6 @@ IF(HAVE_LIBSSL AND HAVE_LIBCRYPTO)
TARGET_LINK_LIBRARIES(mod_openssl crypto)
ENDIF(HAVE_LIBSSL AND HAVE_LIBCRYPTO)
IF(HAVE_LIBCRYPT)
TARGET_LINK_LIBRARIES(mod_auth crypt)
ENDIF(HAVE_LIBCRYPT)
ADD_TARGET_PROPERTIES(lighttpd-${PACKAGE_VERSION}-common LINK_FLAGS ${COMMON_LDFLAGS})
ADD_TARGET_PROPERTIES(lighttpd-${PACKAGE_VERSION}-common COMPILE_FLAGS ${COMMON_CFLAGS})
@ -382,6 +381,10 @@ ADD_TARGET_PROPERTIES(lighttpd2-worker COMPILE_FLAGS ${COMMON_CFLAGS})
ADD_TARGET_PROPERTIES(lighttpd2 LINK_FLAGS ${COMMON_LDFLAGS})
ADD_TARGET_PROPERTIES(lighttpd2 COMPILE_FLAGS ${COMMON_CFLAGS})
IF(HAVE_LIBCRYPT)
TARGET_LINK_LIBRARIES(lighttpd-${PACKAGE_VERSION}-common crypt)
ENDIF(HAVE_LIBCRYPT)
IF(HAVE_LIBKVM)
TARGET_LINK_LIBRARIES(lighttpd-${PACKAGE_VERSION}-common kvm)
ENDIF(HAVE_LIBKVM)

27
src/common/utils.c

@ -16,8 +16,8 @@
#include <stdio.h>
#include <fcntl.h>
#if 0
#include <stropts.h>
#ifdef HAVE_CRYPT_H
# include <crypt.h>
#endif
/* for send/li_receive_fd */
@ -965,6 +965,29 @@ void li_apr_md5_crypt(GString *dest, const GString *password, const GString *sal
md5_crypt_to64(dest, digest[11] , 2);
}
void li_safe_crypt(GString *dest, const GString *password, const GString *salt) {
if (g_str_has_prefix(salt->str, "$apr1$")) {
li_apr_md5_crypt(dest, password, salt);
} else {
#ifdef HAVE_CRYPT_R
struct crypt_data buffer;
memset(&buffer, 0, sizeof(buffer));
g_string_assign(dest, crypt_r(password->str, salt->str, &buffer));
#else
/* This is an acceptable hack: any library that uses crypt() itself is "broken"
* for threaded usage anyway; and our own usage is protected.
*/
static GStaticMutex crypt_mutex = G_STATIC_MUTEX_INIT;
g_static_mutex_lock(&crypt_mutex);
g_string_assign(crypt(password->str, salt->str));
g_static_mutex_unlock(&crypt_mutex);
#endif
}
}
void li_g_queue_merge(GQueue *dest, GQueue *src) {
assert(dest != src);

9
src/main/plugin_core.c

@ -1955,7 +1955,7 @@ static const liPluginAngel angelcbs[] = {
};
#include <sys/types.h>
static void plugin_core_prepare_worker(liServer *srv, liPlugin *p, liWorker *wrk) {
static void plugin_core_prepare(liServer *srv, liPlugin *p) {
guint i;
UNUSED(p);
@ -1978,6 +1978,10 @@ static void plugin_core_prepare_worker(liServer *srv, liPlugin *p, liWorker *wrk
}
}
g_mutex_unlock(srv->action_mutex);
}
static void plugin_core_prepare_worker(liServer *srv, liPlugin *p, liWorker *wrk) {
UNUSED(p);
#if defined(LIGHTY_OS_LINUX)
/* sched_setaffinity is only available on linux */
@ -2003,6 +2007,8 @@ static void plugin_core_prepare_worker(liServer *srv, liPlugin *p, liWorker *wrk
CPU_SET(v->data.number, &mask);
DEBUG(srv, "binding worker #%u to cpu %u", wrk->ndx+1, (guint)v->data.number);
} else {
guint i;
g_string_truncate(wrk->tmp_str, 0);
arr = v->data.list;
@ -2030,5 +2036,6 @@ void li_plugin_core_init(liServer *srv, liPlugin *p, gpointer userdata) {
p->setups = setups;
p->angelcbs = angelcbs;
p->handle_prepare = plugin_core_prepare;
p->handle_prepare_worker = plugin_core_prepare_worker;
}

27
src/modules/mod_auth.c

@ -65,10 +65,6 @@
#include <lighttpd/plugin_core.h>
#ifdef HAVE_CRYPT_H
# include <crypt.h>
#endif
LI_API gboolean mod_auth_init(liModules *mods, liModule *mod);
LI_API gboolean mod_auth_free(liModules *mods, liModule *mod);
@ -284,8 +280,8 @@ static gboolean auth_backend_htpasswd(liVRequest *vr, const GString *username, c
if (NULL == afd) return FALSE;
/* unknown user? */
if (!(pass = g_hash_table_lookup(afd->users, username->str))) {
/* unknown user or empty crypt? */
if (NULL == (pass = g_hash_table_lookup(afd->users, username->str)) || '\0' == pass[0]) {
if (debug) {
VR_DEBUG(vr, "User \"%s\" not found", username->str);
}
@ -302,8 +298,7 @@ static gboolean auth_backend_htpasswd(liVRequest *vr, const GString *username, c
}
goto out;
}
} else
if (g_str_has_prefix(pass, "{SHA}")) {
} else if (g_str_has_prefix(pass, "{SHA}")) {
li_apr_sha1_base64(vr->wrk->tmp_str, password);
if (0 != g_strcmp0(pass, vr->wrk->tmp_str->str)) {
@ -312,23 +307,17 @@ static gboolean auth_backend_htpasswd(liVRequest *vr, const GString *username, c
}
goto out;
}
}
#ifdef HAVE_CRYPT_R
else {
struct crypt_data buffer;
const gchar *crypted;
memset(&buffer, 0, sizeof(buffer));
crypted = crypt_r(password->str, pass, &buffer);
} else {
const GString salt = { (gchar*) pass, strlen(pass), 0 };
li_safe_crypt(vr->wrk->tmp_str, password, &salt);
if (0 != g_strcmp0(pass, crypted)) {
if (0 != g_strcmp0(pass, vr->wrk->tmp_str->str)) {
if (debug) {
VR_DEBUG(vr, "Password crypt \"%s\" doesn't match \"%s\" for user \"%s\"", crypted, pass, username->str);
VR_DEBUG(vr, "Password crypt \"%s\" doesn't match \"%s\" for user \"%s\"", vr->wrk->tmp_str->str, pass, username->str);
}
goto out;
}
}
#endif
res = TRUE;

Loading…
Cancel
Save