OpenVPN
httpdigest.c
Go to the documentation of this file.
1 /*
2  * OpenVPN -- An application to securely tunnel IP networks
3  * over a single TCP/UDP port, with support for SSL/TLS-based
4  * session authentication and key exchange,
5  * packet encryption, packet authentication, and
6  * packet compression.
7  *
8  * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2
12  * as published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #elif defined(_MSC_VER)
27 #include "config-msvc.h"
28 #endif
29 
30 #include "syshead.h"
31 
32 #if PROXY_DIGEST_AUTH
33 
34 #include "crypto.h"
35 #include "httpdigest.h"
36 
37 static void
39  IN HASH Bin,
40  OUT HASHHEX Hex
41  )
42 {
43  unsigned short i;
44  unsigned char j;
45 
46  for (i = 0; i < HASHLEN; i++)
47  {
48  j = (Bin[i] >> 4) & 0xf;
49  if (j <= 9)
50  {
51  Hex[i*2] = (j + '0');
52  }
53  else
54  {
55  Hex[i*2] = (j + 'a' - 10);
56  }
57  j = Bin[i] & 0xf;
58  if (j <= 9)
59  {
60  Hex[i*2+1] = (j + '0');
61  }
62  else
63  {
64  Hex[i*2+1] = (j + 'a' - 10);
65  }
66  }
67  Hex[HASHHEXLEN] = '\0';
68 }
69 
70 /* calculate H(A1) as per spec */
71 void
73  IN char *pszAlg,
74  IN char *pszUserName,
75  IN char *pszRealm,
76  IN char *pszPassword,
77  IN char *pszNonce,
78  IN char *pszCNonce,
79  OUT HASHHEX SessionKey
80  )
81 {
82  HASH HA1;
83  md_ctx_t *md5_ctx = md_ctx_new();
84  const md_kt_t *md5_kt = md_kt_get("MD5");
85 
86  md_ctx_init(md5_ctx, md5_kt);
87  md_ctx_update(md5_ctx, (const uint8_t *) pszUserName, strlen(pszUserName));
88  md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
89  md_ctx_update(md5_ctx, (const uint8_t *) pszRealm, strlen(pszRealm));
90  md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
91  md_ctx_update(md5_ctx, (const uint8_t *) pszPassword, strlen(pszPassword));
92  md_ctx_final(md5_ctx, HA1);
93  if (pszAlg && strcasecmp(pszAlg, "md5-sess") == 0)
94  {
95  md_ctx_init(md5_ctx, md5_kt);
96  md_ctx_update(md5_ctx, HA1, HASHLEN);
97  md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
98  md_ctx_update(md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce));
99  md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
100  md_ctx_update(md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce));
101  md_ctx_final(md5_ctx, HA1);
102  }
103  md_ctx_cleanup(md5_ctx);
104  md_ctx_free(md5_ctx);
105  CvtHex(HA1, SessionKey);
106 }
107 
108 /* calculate request-digest/response-digest as per HTTP Digest spec */
109 void
111  IN HASHHEX HA1, /* H(A1) */
112  IN char *pszNonce, /* nonce from server */
113  IN char *pszNonceCount, /* 8 hex digits */
114  IN char *pszCNonce, /* client nonce */
115  IN char *pszQop, /* qop-value: "", "auth", "auth-int" */
116  IN char *pszMethod, /* method from the request */
117  IN char *pszDigestUri, /* requested URL */
118  IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */
119  OUT HASHHEX Response /* request-digest or response-digest */
120  )
121 {
122  HASH HA2;
123  HASH RespHash;
124  HASHHEX HA2Hex;
125 
126  md_ctx_t *md5_ctx = md_ctx_new();
127  const md_kt_t *md5_kt = md_kt_get("MD5");
128 
129  /* calculate H(A2) */
130  md_ctx_init(md5_ctx, md5_kt);
131  md_ctx_update(md5_ctx, (const uint8_t *) pszMethod, strlen(pszMethod));
132  md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
133  md_ctx_update(md5_ctx, (const uint8_t *) pszDigestUri, strlen(pszDigestUri));
134  if (strcasecmp(pszQop, "auth-int") == 0)
135  {
136  md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
137  md_ctx_update(md5_ctx, HEntity, HASHHEXLEN);
138  }
139  md_ctx_final(md5_ctx, HA2);
140  CvtHex(HA2, HA2Hex);
141 
142  /* calculate response */
143  md_ctx_init(md5_ctx, md5_kt);
144  md_ctx_update(md5_ctx, HA1, HASHHEXLEN);
145  md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
146  md_ctx_update(md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce));
147  md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
148  if (*pszQop)
149  {
150  md_ctx_update(md5_ctx, (const uint8_t *) pszNonceCount, strlen(pszNonceCount));
151  md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
152  md_ctx_update(md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce));
153  md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
154  md_ctx_update(md5_ctx, (const uint8_t *) pszQop, strlen(pszQop));
155  md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
156  }
157  md_ctx_update(md5_ctx, HA2Hex, HASHHEXLEN);
158  md_ctx_final(md5_ctx, RespHash);
159  md_ctx_cleanup(md5_ctx);
160  md_ctx_free(md5_ctx);
161  CvtHex(RespHash, Response);
162 }
163 
164 #endif /* if PROXY_DIGEST_AUTH */
md_ctx_t * md_ctx_new(void)
void md_ctx_free(md_ctx_t *ctx)
#define strcasecmp
Definition: config-msvc.h:94
void md_ctx_final(md_ctx_t *ctx, uint8_t *dst)
void md_ctx_update(md_ctx_t *ctx, const uint8_t *src, int src_len)
mbedtls_md_info_t md_kt_t
Generic message digest key type context.
void DigestCalcHA1(IN char *pszAlg, IN char *pszUserName, IN char *pszRealm, IN char *pszPassword, IN char *pszNonce, IN char *pszCNonce, OUT HASHHEX SessionKey)
Definition: httpdigest.c:72
const md_kt_t * md_kt_get(const char *digest)
Return message digest parameters, based on the given digest name.
static void CvtHex(IN HASH Bin, OUT HASHHEX Hex)
Definition: httpdigest.c:38
void md_ctx_cleanup(md_ctx_t *ctx)
unsigned __int8 uint8_t
Definition: config-msvc.h:123
void md_ctx_init(md_ctx_t *ctx, const md_kt_t *kt)
void DigestCalcResponse(IN HASHHEX HA1, IN char *pszNonce, IN char *pszNonceCount, IN char *pszCNonce, IN char *pszQop, IN char *pszMethod, IN char *pszDigestUri, IN HASHHEX HEntity, OUT HASHHEX Response)
Definition: httpdigest.c:110
mbedtls_md_context_t md_ctx_t
Generic message digest context.