#define MAX_HASH_LEN 128 #define MAX_USER_LEN 128 void consttime_memcpy_if(int condition, void *dst, const void *src, size_t n) { /* 0 -> -1 = ff, 1 -> 0 */ const uint8_t c = (uint8_t)condition - 1; uint8_t *d = dst; uint8_t *s = src; while (n--) { *d = (c & *d) | (~c & *s); d++; s++; } } ... char hashbuf[MAX_HASH_LEN + 1] = /* XXX Calibrate number of iterations to local CPU speed. */ "$sha1$600000$xxxxxxxx$xxxxxxxxxxxxxxxxxxxxxxxxxxxx"; char request_user[MAX_USER_LEN + 1]; char buf[BUFSIZ], *htpasswd_user, *htpasswd_pass; FILE *fp; unsigned ok = 0, ok1; if (strlen(request->hr_authuser) > MAX_USER_LEN) return bozo_http_error(httpd, 401, "bad auth"); (void)memset(request_user, 0, sizeof request_user); (void)strlcpy(request_user, request->hr_authuser, sizeof request_user); fp = fopen(...); ...; while (fgets(buf, sizeof buf, fp) != NULL) { parse_htpasswd_line(buf, &htpasswd_user, &htpasswd_pass); ok1 = consttime_memequal(htpasswd_user, request_user, MAX_USER_LEN); consttime_memcpy_if(ok1, hashbuf, htpasswd_pass, MAX_HASH_LEN); ok |= ok1; } fclose(cp); ok &= (strcmp(crypt(request->ht_authpass, hashbuf), hashbuf) == 0); return ok? 0 : bozo_http_error(httpd, 401, "bad auth"); ...