[mod_auth] add htpasswd -s (SHA1) support if openssl is used (needs openssl for SHA1). This doesn't use any salt, md5 with salt is probably better.

git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2870 152afb58-edef-0310-8abb-c4023f1b3aa9
svn/tags/lighttpd-1.4.33
Stefan Bühler 2013-04-29 13:08:25 +00:00
parent 0342dfef1d
commit c26b50d9ad
4 changed files with 59 additions and 1 deletions

1
NEWS
View File

@ -11,6 +11,7 @@ NEWS
* call ERR_clear_error only for ssl connections in CON_STATE_ERROR
* reject non ASCII characters in HTTP header names
* [mod_auth] use crypt() on encrypted password instead of extracting salt first (fixes #2483)
* [mod_auth] add htpasswd -s (SHA1) support if openssl is used (needs openssl for SHA1). This doesn't use any salt, md5 with salt is probably better.
- 1.4.32 - 2012-11-21
* Code cleanup with clang/sparse (fixes #2437, thx kibi)

View File

@ -29,6 +29,10 @@
#include "md5.h"
#ifdef USE_OPENSSL
#include <openssl/sha.h>
#endif
#define HASHLEN 16
#define HASHHEXLEN 32
typedef unsigned char HASH[HASHLEN];
@ -599,6 +603,35 @@ static void apr_md5_encode(const char *pw, const char *salt, char *result, size_
apr_cpystrn(result, passwd, nbytes - 1);
}
#ifdef USE_OPENSSL
static void apr_sha_encode(const char *pw, char *result, size_t nbytes) {
static const unsigned char base64_data[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned char digest[21]; /* multiple of 3 for base64 encoding */
int i;
memset(result, 0, nbytes);
/* need 5 bytes for "{SHA}", 28 for base64 (3 bytes -> 4 bytes) of SHA1 (20 bytes), 1 terminating */
if (nbytes < 5 + 28 + 1) return;
SHA1((const unsigned char*) pw, strlen(pw), digest);
digest[20] = 0;
strcpy(result, "{SHA}");
result = result + 5;
for (i = 0; i < 21; i += 3) {
unsigned int v = (digest[i] << 16) | (digest[i+1] << 8) | digest[i+2];
result[3] = base64_data[v & 0x3f]; v >>= 6;
result[2] = base64_data[v & 0x3f]; v >>= 6;
result[1] = base64_data[v & 0x3f]; v >>= 6;
result[0] = base64_data[v & 0x3f];
result += 4;
}
result[-1] = '='; /* last digest character was already end of string, pad it */
*result = '\0';
}
#endif
/**
*
@ -643,6 +676,11 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p
*/
apr_md5_encode(pw, password->ptr, sample, sizeof(sample));
return (strcmp(sample, password->ptr) == 0) ? 0 : 1;
#ifdef USE_OPENSSL
} else if (0 == strncmp(password->ptr, "{SHA}", 5)) {
apr_sha_encode(pw, sample, sizeof(sample));
return (strcmp(sample, password->ptr) == 0) ? 0 : 1;
#endif
} else {
#ifdef HAVE_CRYPT
char *crypted;

View File

@ -1,2 +1,3 @@
des:12tMnfw882VDQ
md5:$1$md5$kIa7Juuiv8zja0ILQPR36/
sha:{SHA}2PRZAyDhNDqRW2OUFwZQqPNdaSY=

View File

@ -8,7 +8,7 @@ BEGIN {
use strict;
use IO::Socket;
use Test::More tests => 15;
use Test::More tests => 17;
use LightyTest;
my $tf = LightyTest->new();
@ -65,6 +65,24 @@ EOF
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (des) (lowercase)');
$t->{REQUEST} = ( <<EOF
GET /server-config HTTP/1.0
Host: auth-htpasswd.example.org
Authorization: Basic c2hhOnNoYQ==
EOF
);
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (sha)');
$t->{REQUEST} = ( <<EOF
GET /server-config HTTP/1.0
Host: auth-htpasswd.example.org
Authorization: Basic c2hhOnNoYg==
EOF
);
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
ok($tf->handle_http($t) == 0, 'Basic-Auth: Valid Auth-token - htpasswd (sha, wrong password)');
SKIP: {
skip "no md5 for crypt under cygwin", 1 if $^O eq 'cygwin';