]>
Commit | Line | Data |
---|---|---|
26ac0430 AJ |
1 | /* The source in this file is derived from the reference implementation |
2 | * in RFC 2617. | |
2d70df72 | 3 | * RFC 2617 is Copyright (C) The Internet Society (1999). All Rights Reserved. |
4 | * | |
26ac0430 | 5 | * The following copyright and licence statement covers all changes made to the |
2d70df72 | 6 | * reference implementation. |
26ac0430 | 7 | * |
2d70df72 | 8 | * Key changes were: alteration to a plain C layout. |
9 | * Create CvtBin function | |
10 | * Allow CalcHA1 to make use of precaculated username:password:realm hash's | |
11 | * to prevent squid knowing the users password (idea suggested in RFC 2617). | |
12 | */ | |
13 | ||
2d70df72 | 14 | /* |
262a0e14 | 15 | * $Id$ |
2d70df72 | 16 | * |
17 | * DEBUG: | |
18 | * AUTHOR: RFC 2617 & Robert Collins | |
19 | * | |
20 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ | |
21 | * ---------------------------------------------------------- | |
22 | * | |
23 | * Squid is the result of efforts by numerous individuals from the | |
24 | * Internet community. Development is led by Duane Wessels of the | |
25 | * National Laboratory for Applied Network Research and funded by the | |
26 | * National Science Foundation. Squid is Copyrighted (C) 1998 by | |
27 | * the Regents of the University of California. Please see the | |
28 | * COPYRIGHT file for full details. Squid incorporates software | |
29 | * developed and/or copyrighted by other sources. Please see the | |
30 | * CREDITS file for full details. | |
31 | * | |
32 | * This program is free software; you can redistribute it and/or modify | |
33 | * it under the terms of the GNU General Public License as published by | |
34 | * the Free Software Foundation; either version 2 of the License, or | |
35 | * (at your option) any later version. | |
36 | * | |
37 | * This program is distributed in the hope that it will be useful, | |
38 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
39 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
40 | * GNU General Public License for more details. | |
41 | * | |
42 | * You should have received a copy of the GNU General Public License | |
43 | * along with this program; if not, write to the Free Software | |
44 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. | |
45 | * | |
46 | */ | |
47 | ||
f7f3304a | 48 | #include "squid.h" |
2d70df72 | 49 | #include <string.h> |
50 | #include "rfc2617.h" | |
1f7c9178 | 51 | #include "md5.h" |
2d70df72 | 52 | |
9bea1d5b | 53 | void |
2d70df72 | 54 | CvtHex(const HASH Bin, HASHHEX Hex) |
55 | { | |
56 | unsigned short i; | |
57 | unsigned char j; | |
58 | ||
59 | for (i = 0; i < HASHLEN; i++) { | |
26ac0430 AJ |
60 | j = (Bin[i] >> 4) & 0xf; |
61 | if (j <= 9) | |
62 | Hex[i * 2] = (j + '0'); | |
63 | else | |
64 | Hex[i * 2] = (j + 'a' - 10); | |
65 | j = Bin[i] & 0xf; | |
66 | if (j <= 9) | |
67 | Hex[i * 2 + 1] = (j + '0'); | |
68 | else | |
69 | Hex[i * 2 + 1] = (j + 'a' - 10); | |
a76e35b1 | 70 | } |
2d70df72 | 71 | Hex[HASHHEXLEN] = '\0'; |
a76e35b1 | 72 | } |
2d70df72 | 73 | |
9bea1d5b | 74 | void |
2d70df72 | 75 | CvtBin(const HASHHEX Hex, HASH Bin) |
76 | { | |
77 | unsigned short i; | |
78 | unsigned char j; | |
79 | ||
80 | for (i = 0; i < HASHHEXLEN; i++) { | |
26ac0430 AJ |
81 | unsigned char n; |
82 | j = Hex[i]; | |
83 | if (('0' <= j) && (j <= '9')) | |
84 | n = j - '0'; | |
85 | else if (('a' <= j) && (j <= 'f')) | |
86 | n = j - 'a' + 10; | |
87 | else if (('A' <= j) && (j <= 'F')) | |
88 | n = j - 'A' + 10; | |
89 | else | |
90 | continue; | |
91 | if (i % 2 == 0) | |
92 | Bin[i / 2] = n << 4; | |
93 | else | |
94 | Bin[i / 2] |= n; | |
a76e35b1 | 95 | } |
af6a12ee AJ |
96 | /* FIXME: Coverity detects the below as dead code. |
97 | Why? :: right here i == 32 | |
98 | which means the first step of the for loop makes i==16 | |
99 | and cannot be < HASHLEN (which is also 16) | |
100 | */ | |
9abb716f | 101 | for (i = i / 2; i < HASHLEN; i++) { |
26ac0430 | 102 | Bin[i] = '\0'; |
63a24aeb | 103 | } |
a76e35b1 | 104 | } |
2d70df72 | 105 | |
2d70df72 | 106 | /* calculate H(A1) as per spec */ |
9bea1d5b | 107 | void |
2d70df72 | 108 | DigestCalcHA1( |
109 | const char *pszAlg, | |
110 | const char *pszUserName, | |
111 | const char *pszRealm, | |
112 | const char *pszPassword, | |
113 | const char *pszNonce, | |
114 | const char *pszCNonce, | |
115 | HASH HA1, | |
116 | HASHHEX SessionKey | |
117 | ) | |
118 | { | |
c3031d67 | 119 | SquidMD5_CTX Md5Ctx; |
2d70df72 | 120 | |
121 | if (pszUserName) { | |
26ac0430 AJ |
122 | SquidMD5Init(&Md5Ctx); |
123 | SquidMD5Update(&Md5Ctx, pszUserName, strlen(pszUserName)); | |
124 | SquidMD5Update(&Md5Ctx, ":", 1); | |
125 | SquidMD5Update(&Md5Ctx, pszRealm, strlen(pszRealm)); | |
126 | SquidMD5Update(&Md5Ctx, ":", 1); | |
127 | SquidMD5Update(&Md5Ctx, pszPassword, strlen(pszPassword)); | |
128 | SquidMD5Final((unsigned char *) HA1, &Md5Ctx); | |
2d70df72 | 129 | } |
a8cb0f62 | 130 | if (strcasecmp(pszAlg, "md5-sess") == 0) { |
26ac0430 AJ |
131 | HASHHEX HA1Hex; |
132 | CvtHex(HA1, HA1Hex); /* RFC2617 errata */ | |
133 | SquidMD5Init(&Md5Ctx); | |
134 | SquidMD5Update(&Md5Ctx, HA1Hex, HASHHEXLEN); | |
135 | SquidMD5Update(&Md5Ctx, ":", 1); | |
136 | SquidMD5Update(&Md5Ctx, pszNonce, strlen(pszNonce)); | |
137 | SquidMD5Update(&Md5Ctx, ":", 1); | |
138 | SquidMD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce)); | |
139 | SquidMD5Final((unsigned char *) HA1, &Md5Ctx); | |
a76e35b1 | 140 | } |
2d70df72 | 141 | CvtHex(HA1, SessionKey); |
a76e35b1 | 142 | } |
2d70df72 | 143 | |
144 | /* calculate request-digest/response-digest as per HTTP Digest spec */ | |
9bea1d5b | 145 | void |
2d70df72 | 146 | DigestCalcResponse( |
147 | const HASHHEX HA1, /* H(A1) */ | |
148 | const char *pszNonce, /* nonce from server */ | |
149 | const char *pszNonceCount, /* 8 hex digits */ | |
150 | const char *pszCNonce, /* client nonce */ | |
151 | const char *pszQop, /* qop-value: "", "auth", "auth-int" */ | |
152 | const char *pszMethod, /* method from the request */ | |
153 | const char *pszDigestUri, /* requested URL */ | |
154 | const HASHHEX HEntity, /* H(entity body) if qop="auth-int" */ | |
155 | HASHHEX Response /* request-digest or response-digest */ | |
156 | ) | |
157 | { | |
c3031d67 | 158 | SquidMD5_CTX Md5Ctx; |
2d70df72 | 159 | HASH HA2; |
160 | HASH RespHash; | |
161 | HASHHEX HA2Hex; | |
162 | ||
163 | /* calculate H(A2) | |
164 | */ | |
c3031d67 | 165 | SquidMD5Init(&Md5Ctx); |
166 | SquidMD5Update(&Md5Ctx, pszMethod, strlen(pszMethod)); | |
167 | SquidMD5Update(&Md5Ctx, ":", 1); | |
168 | SquidMD5Update(&Md5Ctx, pszDigestUri, strlen(pszDigestUri)); | |
bbe0ed86 | 169 | if (pszQop && strcasecmp(pszQop, "auth-int") == 0) { |
26ac0430 AJ |
170 | SquidMD5Update(&Md5Ctx, ":", 1); |
171 | SquidMD5Update(&Md5Ctx, HEntity, HASHHEXLEN); | |
a76e35b1 | 172 | } |
c3031d67 | 173 | SquidMD5Final((unsigned char *) HA2, &Md5Ctx); |
2d70df72 | 174 | CvtHex(HA2, HA2Hex); |
175 | ||
176 | /* calculate response | |
177 | */ | |
c3031d67 | 178 | SquidMD5Init(&Md5Ctx); |
179 | SquidMD5Update(&Md5Ctx, HA1, HASHHEXLEN); | |
180 | SquidMD5Update(&Md5Ctx, ":", 1); | |
181 | SquidMD5Update(&Md5Ctx, pszNonce, strlen(pszNonce)); | |
182 | SquidMD5Update(&Md5Ctx, ":", 1); | |
bbe0ed86 | 183 | if (pszQop) { |
26ac0430 AJ |
184 | SquidMD5Update(&Md5Ctx, pszNonceCount, strlen(pszNonceCount)); |
185 | SquidMD5Update(&Md5Ctx, ":", 1); | |
186 | SquidMD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce)); | |
187 | SquidMD5Update(&Md5Ctx, ":", 1); | |
188 | SquidMD5Update(&Md5Ctx, pszQop, strlen(pszQop)); | |
189 | SquidMD5Update(&Md5Ctx, ":", 1); | |
a76e35b1 | 190 | } |
c3031d67 | 191 | SquidMD5Update(&Md5Ctx, HA2Hex, HASHHEXLEN); |
192 | SquidMD5Final((unsigned char *) RespHash, &Md5Ctx); | |
2d70df72 | 193 | CvtHex(RespHash, Response); |
a76e35b1 | 194 | } |