]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: auth/threads: use of crypt() is not thread-safe
authorWilly Tarreau <w@1wt.eu>
Mon, 29 Oct 2018 17:02:54 +0000 (18:02 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 29 Oct 2018 17:06:02 +0000 (18:06 +0100)
It was reported here that authentication may fail when threads are
enabled :

    https://bugzilla.redhat.com/show_bug.cgi?id=1643941

While I couldn't reproduce the issue, it's obvious that there is a
problem with the use of the non-reentrant crypt() function there.
On Linux systems there's crypt_r() but not on the vast majority of
other ones. Thus a first approach consists in placing a lock around
this crypt() call. Another patch may relax it when crypt_r() is
available.

This fix must be backported to 1.8. Thanks to Ryan O'Hara for the
quick notification.

include/common/hathreads.h
src/auth.c

index 1f3fe8dd6081a93b3d8d9e5d96acdbf769eb5dbb..d2fd400e0138d1e8b128eed9c6183e1e69af2a54 100644 (file)
@@ -386,6 +386,7 @@ enum lock_label {
        PIPES_LOCK,
        START_LOCK,
        TLSKEYS_REF_LOCK,
+       AUTH_LOCK,
        LOCK_LABELS
 };
 struct lock_stat {
@@ -501,6 +502,7 @@ static inline const char *lock_label(enum lock_label label)
        case PIPES_LOCK:           return "PIPES";
        case START_LOCK:           return "START";
        case TLSKEYS_REF_LOCK:     return "TLSKEYS_REF";
+       case AUTH_LOCK:            return "AUTH";
        case LOCK_LABELS:          break; /* keep compiler happy */
        };
        /* only way to come here is consecutive to an internal bug */
index 3dd3a1de0d97ff096d7a9e5b3240e0e71fcb997d..599a3abbc1a028d6919f9bc4ca7b53906040c016 100644 (file)
@@ -28,6 +28,7 @@
 #include <types/global.h>
 #include <common/config.h>
 #include <common/errors.h>
+#include <common/hathreads.h>
 
 #include <proto/acl.h>
 #include <proto/log.h>
 
 struct userlist *userlist = NULL;    /* list of all existing userlists */
 
+#ifdef CONFIG_HAP_CRYPT
+__decl_hathreads(static HA_SPINLOCK_T auth_lock);
+#endif
+
 /* find targets for selected gropus. The function returns pointer to
  * the userlist struct ot NULL if name is NULL/empty or unresolvable.
  */
@@ -245,7 +250,9 @@ check_user(struct userlist *ul, const char *user, const char *pass)
 
        if (!(u->flags & AU_O_INSECURE)) {
 #ifdef CONFIG_HAP_CRYPT
+               HA_SPIN_LOCK(AUTH_LOCK, &auth_lock);
                ep = crypt(pass, u->pass);
+               HA_SPIN_UNLOCK(AUTH_LOCK, &auth_lock);
 #else
                return 0;
 #endif