Support SHA512 password encoding, use safe_cmp to prevent brute-force
attacks
SHA512 passwords needs more space than 64bytes
The runtime of strcmp depends on the string size, thus allows for
brute-force password attacks. Replace it by constant-time safe_cmp
when comparing usernames and passwords.
diff --git a/src/authenticators/file/file_auth.c b/src/authenticators/file/file_auth.c
index 7355bb6..205e16a 100644
--- a/src/authenticators/file/file_auth.c
+++ b/src/authenticators/file/file_auth.c
@@ -70,14 +70,31 @@
return 0;
}
+/*
+ * constant-time comparison to prevent brute-force attacks on authorize()
+ *
+ * returns zero only if s1 and s2 are bit-wise identical for the first len characters.
+ */
+static int
+safe_cmp(unsigned const char *s1, unsigned const char *s2, size_t len)
+{
+ size_t i = 0;
+ unsigned char result = 0;
+ while (i++ < len) {
+ result |= *s1++ ^ *s2++;
+ }
+ return result;
+}
int
authorize(char *username, const char *password)
{
int authorized = 0;
- char l[256], u[65], passwd[65];
+ char l[256], u[65], passwd[129];
char *newpw = NULL ;
+ size_t username_l;
+ size_t min_len;
debug( "Checking basic for user: %s; password XXXXX",
username);
@@ -88,6 +105,7 @@
username);
return 0;
}
+ username_l = strlen(username);
FILE *fp = fopen(filename, "r");
if (!fp) {
debug( "Couldn't open basic passwd file %s",
@@ -99,10 +117,20 @@
if (sscanf(l, "%64[^:]:%64s", u, passwd) != 2)
continue; /* Ignore malformed lines */
debug( "user: %s, passwd: XXXX", u);
- if (!strcmp(username, u)) {
+ min_len = strlen(u);
+ if (username_l < min_len) {
+ min_len = username_l;
+ }
+ if (!safe_cmp(username, u, min_len)) {
+ size_t newpw_l;
+ min_len = strlen(passwd);
newpw = crypt(password, passwd);
+ newpw_l = strlen(newpw);
+ if (newpw_l < min_len) {
+ min_len = newpw_l;
+ }
debug( "user: %s, passwd: XXXXX", u );
- authorized = ( strcmp (newpw, passwd) == 0 );
+ authorized = ( safe_cmp (newpw, passwd, min_len) == 0 );
break;
}
}