]>
Commit | Line | Data |
---|---|---|
0545caaa | 1 | /* |
4ac4a490 | 2 | * Copyright (C) 1996-2017 The Squid Software Foundation and contributors |
0545caaa AJ |
3 | * |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
26ac0430 AJ |
9 | /* The source in this file is derived from the reference implementation |
10 | * in RFC 2617. | |
2d70df72 | 11 | * RFC 2617 is Copyright (C) The Internet Society (1999). All Rights Reserved. |
12 | * | |
0545caaa | 13 | * The Squid copyright and licence statement covers all changes made to the |
2d70df72 | 14 | * reference implementation. |
26ac0430 | 15 | * |
2d70df72 | 16 | * Key changes were: alteration to a plain C layout. |
17 | * Create CvtBin function | |
18 | * Allow CalcHA1 to make use of precaculated username:password:realm hash's | |
19 | * to prevent squid knowing the users password (idea suggested in RFC 2617). | |
20 | */ | |
21 | ||
f7f3304a | 22 | #include "squid.h" |
2d70df72 | 23 | #include <string.h> |
1f7c9178 | 24 | #include "md5.h" |
602d9612 | 25 | #include "rfc2617.h" |
2d70df72 | 26 | |
9bea1d5b | 27 | void |
2d70df72 | 28 | CvtHex(const HASH Bin, HASHHEX Hex) |
29 | { | |
30 | unsigned short i; | |
31 | unsigned char j; | |
32 | ||
33 | for (i = 0; i < HASHLEN; i++) { | |
26ac0430 AJ |
34 | j = (Bin[i] >> 4) & 0xf; |
35 | if (j <= 9) | |
36 | Hex[i * 2] = (j + '0'); | |
37 | else | |
38 | Hex[i * 2] = (j + 'a' - 10); | |
39 | j = Bin[i] & 0xf; | |
40 | if (j <= 9) | |
41 | Hex[i * 2 + 1] = (j + '0'); | |
42 | else | |
43 | Hex[i * 2 + 1] = (j + 'a' - 10); | |
a76e35b1 | 44 | } |
2d70df72 | 45 | Hex[HASHHEXLEN] = '\0'; |
a76e35b1 | 46 | } |
2d70df72 | 47 | |
9bea1d5b | 48 | void |
2d70df72 | 49 | CvtBin(const HASHHEX Hex, HASH Bin) |
50 | { | |
51 | unsigned short i; | |
52 | unsigned char j; | |
53 | ||
54 | for (i = 0; i < HASHHEXLEN; i++) { | |
26ac0430 AJ |
55 | unsigned char n; |
56 | j = Hex[i]; | |
57 | if (('0' <= j) && (j <= '9')) | |
58 | n = j - '0'; | |
59 | else if (('a' <= j) && (j <= 'f')) | |
60 | n = j - 'a' + 10; | |
61 | else if (('A' <= j) && (j <= 'F')) | |
62 | n = j - 'A' + 10; | |
63 | else | |
64 | continue; | |
65 | if (i % 2 == 0) | |
66 | Bin[i / 2] = n << 4; | |
67 | else | |
68 | Bin[i / 2] |= n; | |
a76e35b1 | 69 | } |
cfd861ab AJ |
70 | |
71 | #if HASHHEXLEN != (2*HASHLEN) | |
72 | /* | |
af6a12ee AJ |
73 | Why? :: right here i == 32 |
74 | which means the first step of the for loop makes i==16 | |
75 | and cannot be < HASHLEN (which is also 16) | |
cfd861ab AJ |
76 | |
77 | But only guaranteed if HASHHEXLEN == 2*HASHLEN | |
78 | This will ensure correct 0-ing of bins no matter what. | |
af6a12ee | 79 | */ |
9abb716f | 80 | for (i = i / 2; i < HASHLEN; i++) { |
26ac0430 | 81 | Bin[i] = '\0'; |
63a24aeb | 82 | } |
cfd861ab | 83 | #endif |
a76e35b1 | 84 | } |
2d70df72 | 85 | |
2d70df72 | 86 | /* calculate H(A1) as per spec */ |
9bea1d5b | 87 | void |
2d70df72 | 88 | DigestCalcHA1( |
89 | const char *pszAlg, | |
90 | const char *pszUserName, | |
91 | const char *pszRealm, | |
92 | const char *pszPassword, | |
93 | const char *pszNonce, | |
94 | const char *pszCNonce, | |
95 | HASH HA1, | |
96 | HASHHEX SessionKey | |
97 | ) | |
98 | { | |
c3031d67 | 99 | SquidMD5_CTX Md5Ctx; |
2d70df72 | 100 | |
101 | if (pszUserName) { | |
26ac0430 AJ |
102 | SquidMD5Init(&Md5Ctx); |
103 | SquidMD5Update(&Md5Ctx, pszUserName, strlen(pszUserName)); | |
104 | SquidMD5Update(&Md5Ctx, ":", 1); | |
105 | SquidMD5Update(&Md5Ctx, pszRealm, strlen(pszRealm)); | |
106 | SquidMD5Update(&Md5Ctx, ":", 1); | |
107 | SquidMD5Update(&Md5Ctx, pszPassword, strlen(pszPassword)); | |
108 | SquidMD5Final((unsigned char *) HA1, &Md5Ctx); | |
2d70df72 | 109 | } |
a8cb0f62 | 110 | if (strcasecmp(pszAlg, "md5-sess") == 0) { |
26ac0430 | 111 | HASHHEX HA1Hex; |
f53969cc | 112 | CvtHex(HA1, HA1Hex); /* RFC2617 errata */ |
26ac0430 AJ |
113 | SquidMD5Init(&Md5Ctx); |
114 | SquidMD5Update(&Md5Ctx, HA1Hex, HASHHEXLEN); | |
115 | SquidMD5Update(&Md5Ctx, ":", 1); | |
116 | SquidMD5Update(&Md5Ctx, pszNonce, strlen(pszNonce)); | |
117 | SquidMD5Update(&Md5Ctx, ":", 1); | |
118 | SquidMD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce)); | |
119 | SquidMD5Final((unsigned char *) HA1, &Md5Ctx); | |
a76e35b1 | 120 | } |
2d70df72 | 121 | CvtHex(HA1, SessionKey); |
a76e35b1 | 122 | } |
2d70df72 | 123 | |
124 | /* calculate request-digest/response-digest as per HTTP Digest spec */ | |
9bea1d5b | 125 | void |
2d70df72 | 126 | DigestCalcResponse( |
f53969cc SM |
127 | const HASHHEX HA1, /* H(A1) */ |
128 | const char *pszNonce, /* nonce from server */ | |
129 | const char *pszNonceCount, /* 8 hex digits */ | |
130 | const char *pszCNonce, /* client nonce */ | |
131 | const char *pszQop, /* qop-value: "", "auth", "auth-int" */ | |
132 | const char *pszMethod, /* method from the request */ | |
133 | const char *pszDigestUri, /* requested URL */ | |
134 | const HASHHEX HEntity, /* H(entity body) if qop="auth-int" */ | |
135 | HASHHEX Response /* request-digest or response-digest */ | |
2d70df72 | 136 | ) |
137 | { | |
c3031d67 | 138 | SquidMD5_CTX Md5Ctx; |
2d70df72 | 139 | HASH HA2; |
140 | HASH RespHash; | |
141 | HASHHEX HA2Hex; | |
142 | ||
143 | /* calculate H(A2) | |
144 | */ | |
c3031d67 | 145 | SquidMD5Init(&Md5Ctx); |
146 | SquidMD5Update(&Md5Ctx, pszMethod, strlen(pszMethod)); | |
147 | SquidMD5Update(&Md5Ctx, ":", 1); | |
148 | SquidMD5Update(&Md5Ctx, pszDigestUri, strlen(pszDigestUri)); | |
bbe0ed86 | 149 | if (pszQop && strcasecmp(pszQop, "auth-int") == 0) { |
26ac0430 AJ |
150 | SquidMD5Update(&Md5Ctx, ":", 1); |
151 | SquidMD5Update(&Md5Ctx, HEntity, HASHHEXLEN); | |
a76e35b1 | 152 | } |
c3031d67 | 153 | SquidMD5Final((unsigned char *) HA2, &Md5Ctx); |
2d70df72 | 154 | CvtHex(HA2, HA2Hex); |
155 | ||
156 | /* calculate response | |
157 | */ | |
c3031d67 | 158 | SquidMD5Init(&Md5Ctx); |
159 | SquidMD5Update(&Md5Ctx, HA1, HASHHEXLEN); | |
160 | SquidMD5Update(&Md5Ctx, ":", 1); | |
161 | SquidMD5Update(&Md5Ctx, pszNonce, strlen(pszNonce)); | |
162 | SquidMD5Update(&Md5Ctx, ":", 1); | |
bbe0ed86 | 163 | if (pszQop) { |
26ac0430 AJ |
164 | SquidMD5Update(&Md5Ctx, pszNonceCount, strlen(pszNonceCount)); |
165 | SquidMD5Update(&Md5Ctx, ":", 1); | |
166 | SquidMD5Update(&Md5Ctx, pszCNonce, strlen(pszCNonce)); | |
167 | SquidMD5Update(&Md5Ctx, ":", 1); | |
168 | SquidMD5Update(&Md5Ctx, pszQop, strlen(pszQop)); | |
169 | SquidMD5Update(&Md5Ctx, ":", 1); | |
a76e35b1 | 170 | } |
c3031d67 | 171 | SquidMD5Update(&Md5Ctx, HA2Hex, HASHHEXLEN); |
172 | SquidMD5Final((unsigned char *) RespHash, &Md5Ctx); | |
2d70df72 | 173 | CvtHex(RespHash, Response); |
a76e35b1 | 174 | } |
f53969cc | 175 |