diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-07-08 16:30:22 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-07-08 16:34:34 +0300 |
commit | 08a7915aaf08e9d2187fd3f26e0326673d4c8eb1 (patch) | |
tree | 7d9f02b59945ae7577e79c3cbfe5182b3a22e4b8 | |
parent | 4e2b6995088963e287de5dcc507a5ab14a7134b1 (diff) | |
download | vmod-basicauth-08a7915aaf08e9d2187fd3f26e0326673d4c8eb1.tar.gz vmod-basicauth-08a7915aaf08e9d2187fd3f26e0326673d4c8eb1.tar.bz2 |
Implement SHA1 passwords.
* src/sha1.c: New file.
* src/sha1.h: New file.
* src/Makefile.am: Add new files.
* src/vmod_basicauth.c (base64_decode): Fix bound checking.
(sha1_match): New function.
(match_tab): Add SHA1 method.
* tests/test03.vtc: New test.
* tests/Makefile.am: Add new file.
* tests/htpasswd: Add SHA1 password.
* README: Update.
* src/vmod_basicauth.3: Update.
-rw-r--r-- | README | 4 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/sha1.c | 418 | ||||
-rw-r--r-- | src/sha1.h | 98 | ||||
-rw-r--r-- | src/vmod_basicauth.3 | 5 | ||||
-rw-r--r-- | src/vmod_basicauth.c | 27 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rw-r--r-- | tests/htpasswd | 1 | ||||
-rw-r--r-- | tests/test03.vtc | 23 |
9 files changed, 575 insertions, 6 deletions
@@ -3,4 +3,4 @@ | |||
3 | This module implements basic HTTP authentication against the password file | 3 | This module implements basic HTTP authentication against the password file |
4 | created with the htpasswd(1) utility. Three kinds of password hashes are | 4 | created with the htpasswd(1) utility. The following password hashes are |
5 | supported: Apache MD5, crypt(3), and plaintext. | 5 | supported: Apache MD5, crypt(3), SHA1, and plaintext. |
6 | 6 | ||
diff --git a/src/Makefile.am b/src/Makefile.am index 92f15ca..e4fdb51 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
@@ -13,2 +13,4 @@ libvmod_basicauth_la_SOURCES = \ | |||
13 | md5.c\ | 13 | md5.c\ |
14 | sha1.c\ | ||
15 | sha1.h\ | ||
14 | vcc_if.c \ | 16 | vcc_if.c \ |
diff --git a/src/sha1.c b/src/sha1.c new file mode 100644 index 0000000..a4380cb --- /dev/null +++ b/src/sha1.c | |||
@@ -0,0 +1,418 @@ | |||
1 | /* sha1.c - Functions to compute SHA1 message digest of files or | ||
2 | memory blocks according to the NIST specification FIPS-180-1. | ||
3 | |||
4 | Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006 Free Software | ||
5 | Foundation, Inc. | ||
6 | |||
7 | This program is free software; you can redistribute it and/or modify it | ||
8 | under the terms of the GNU General Public License as published by the | ||
9 | Free Software Foundation; either version 2, or (at your option) any | ||
10 | later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program; if not, write to the Free Software Foundation, | ||
19 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
20 | |||
21 | /* Written by Scott G. Miller | ||
22 | Credits: | ||
23 | Robert Klep <robert@ilse.nl> -- Expansion function fix | ||
24 | */ | ||
25 | |||
26 | #ifdef HAVE_CONFIG_H | ||
27 | # include <config.h> | ||
28 | #endif | ||
29 | |||
30 | #include <sha1.h> | ||
31 | |||
32 | #include <stddef.h> | ||
33 | #include <string.h> | ||
34 | |||
35 | #if USE_UNLOCKED_IO | ||
36 | # include "unlocked-io.h" | ||
37 | #endif | ||
38 | |||
39 | #ifdef WORDS_BIGENDIAN | ||
40 | # define SWAP(n) (n) | ||
41 | #else | ||
42 | # define SWAP(n) \ | ||
43 | (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) | ||
44 | #endif | ||
45 | |||
46 | #define BLOCKSIZE 4096 | ||
47 | #if BLOCKSIZE % 64 != 0 | ||
48 | # error "invalid BLOCKSIZE" | ||
49 | #endif | ||
50 | |||
51 | /* This array contains the bytes used to pad the buffer to the next | ||
52 | 64-byte boundary. (RFC 1321, 3.1: Step 1) */ | ||
53 | static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; | ||
54 | |||
55 | |||
56 | /* Take a pointer to a 160 bit block of data (five 32 bit ints) and | ||
57 | initialize it to the start constants of the SHA1 algorithm. This | ||
58 | must be called before using hash in the call to sha1_hash. */ | ||
59 | void | ||
60 | sha1_init_ctx (struct sha1_ctx *ctx) | ||
61 | { | ||
62 | ctx->A = 0x67452301; | ||
63 | ctx->B = 0xefcdab89; | ||
64 | ctx->C = 0x98badcfe; | ||
65 | ctx->D = 0x10325476; | ||
66 | ctx->E = 0xc3d2e1f0; | ||
67 | |||
68 | ctx->total[0] = ctx->total[1] = 0; | ||
69 | ctx->buflen = 0; | ||
70 | } | ||
71 | |||
72 | /* Put result from CTX in first 20 bytes following RESBUF. The result | ||
73 | must be in little endian byte order. | ||
74 | |||
75 | IMPORTANT: On some systems it is required that RESBUF is correctly | ||
76 | aligned for a 32-bit value. */ | ||
77 | void * | ||
78 | sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf) | ||
79 | { | ||
80 | ((uint32_t *) resbuf)[0] = SWAP (ctx->A); | ||
81 | ((uint32_t *) resbuf)[1] = SWAP (ctx->B); | ||
82 | ((uint32_t *) resbuf)[2] = SWAP (ctx->C); | ||
83 | ((uint32_t *) resbuf)[3] = SWAP (ctx->D); | ||
84 | ((uint32_t *) resbuf)[4] = SWAP (ctx->E); | ||
85 | |||
86 | return resbuf; | ||
87 | } | ||
88 | |||
89 | /* Process the remaining bytes in the internal buffer and the usual | ||
90 | prolog according to the standard and write the result to RESBUF. | ||
91 | |||
92 | IMPORTANT: On some systems it is required that RESBUF is correctly | ||
93 | aligned for a 32-bit value. */ | ||
94 | void * | ||
95 | sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf) | ||
96 | { | ||
97 | /* Take yet unprocessed bytes into account. */ | ||
98 | uint32_t bytes = ctx->buflen; | ||
99 | size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; | ||
100 | |||
101 | /* Now count remaining bytes. */ | ||
102 | ctx->total[0] += bytes; | ||
103 | if (ctx->total[0] < bytes) | ||
104 | ++ctx->total[1]; | ||
105 | |||
106 | /* Put the 64-bit file length in *bits* at the end of the buffer. */ | ||
107 | ctx->buffer[size - 2] = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); | ||
108 | ctx->buffer[size - 1] = SWAP (ctx->total[0] << 3); | ||
109 | |||
110 | memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes); | ||
111 | |||
112 | /* Process last bytes. */ | ||
113 | sha1_process_block (ctx->buffer, size * 4, ctx); | ||
114 | |||
115 | return sha1_read_ctx (ctx, resbuf); | ||
116 | } | ||
117 | |||
118 | /* Compute SHA1 message digest for bytes read from STREAM. The | ||
119 | resulting message digest number will be written into the 16 bytes | ||
120 | beginning at RESBLOCK. */ | ||
121 | int | ||
122 | sha1_stream (FILE *stream, void *resblock) | ||
123 | { | ||
124 | struct sha1_ctx ctx; | ||
125 | char buffer[BLOCKSIZE + 72]; | ||
126 | size_t sum; | ||
127 | |||
128 | /* Initialize the computation context. */ | ||
129 | sha1_init_ctx (&ctx); | ||
130 | |||
131 | /* Iterate over full file contents. */ | ||
132 | while (1) | ||
133 | { | ||
134 | /* We read the file in blocks of BLOCKSIZE bytes. One call of the | ||
135 | computation function processes the whole buffer so that with the | ||
136 | next round of the loop another block can be read. */ | ||
137 | size_t n; | ||
138 | sum = 0; | ||
139 | |||
140 | /* Read block. Take care for partial reads. */ | ||
141 | while (1) | ||
142 | { | ||
143 | n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); | ||
144 | |||
145 | sum += n; | ||
146 | |||
147 | if (sum == BLOCKSIZE) | ||
148 | break; | ||
149 | |||
150 | if (n == 0) | ||
151 | { | ||
152 | /* Check for the error flag IFF N == 0, so that we don't | ||
153 | exit the loop after a partial read due to e.g., EAGAIN | ||
154 | or EWOULDBLOCK. */ | ||
155 | if (ferror (stream)) | ||
156 | return 1; | ||
157 | goto process_partial_block; | ||
158 | } | ||
159 | |||
160 | /* We've read at least one byte, so ignore errors. But always | ||
161 | check for EOF, since feof may be true even though N > 0. | ||
162 | Otherwise, we could end up calling fread after EOF. */ | ||
163 | if (feof (stream)) | ||
164 | goto process_partial_block; | ||
165 | } | ||
166 | |||
167 | /* Process buffer with BLOCKSIZE bytes. Note that | ||
168 | BLOCKSIZE % 64 == 0 | ||
169 | */ | ||
170 | sha1_process_block (buffer, BLOCKSIZE, &ctx); | ||
171 | } | ||
172 | |||
173 | process_partial_block:; | ||
174 | |||
175 | /* Process any remaining bytes. */ | ||
176 | if (sum > 0) | ||
177 | sha1_process_bytes (buffer, sum, &ctx); | ||
178 | |||
179 | /* Construct result in desired memory. */ | ||
180 | sha1_finish_ctx (&ctx, resblock); | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | /* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The | ||
185 | result is always in little endian byte order, so that a byte-wise | ||
186 | output yields to the wanted ASCII representation of the message | ||
187 | digest. */ | ||
188 | void * | ||
189 | sha1_buffer (const char *buffer, size_t len, void *resblock) | ||
190 | { | ||
191 | struct sha1_ctx ctx; | ||
192 | |||
193 | /* Initialize the computation context. */ | ||
194 | sha1_init_ctx (&ctx); | ||
195 | |||
196 | /* Process whole buffer but last len % 64 bytes. */ | ||
197 | sha1_process_bytes (buffer, len, &ctx); | ||
198 | |||
199 | /* Put result in desired memory area. */ | ||
200 | return sha1_finish_ctx (&ctx, resblock); | ||
201 | } | ||
202 | |||
203 | void | ||
204 | sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx) | ||