]> git.ipfire.org Git - thirdparty/squid.git/blame - lib/rfc2617.c
SourceFormat Enforcement
[thirdparty/squid.git] / lib / rfc2617.c
CommitLineData
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 27void
2d70df72 28CvtHex(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 48void
2d70df72 49CvtBin(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 87void
2d70df72 88DigestCalcHA1(
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 125void
2d70df72 126DigestCalcResponse(
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