doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
http_digest.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at http://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * $Id: http_digest.c,v 1.8 2004/03/08 12:37:11 bagder Exp $
22  ***************************************************************************/
23 #include "setup.h"
24 
25 #ifndef CURL_DISABLE_HTTP
26 /* -- WIN32 approved -- */
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdarg.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 
33 #include "urldata.h"
34 #include "sendf.h"
35 #include "strequal.h"
36 
37 #include "md5.h"
38 #include "http_digest.h"
39 
40 #define _MPRINTF_REPLACE /* use our functions only */
41 #include <curl/mprintf.h>
42 
43 /* The last #include file should be: */
44 #ifdef CURLDEBUG
45 #include "memdebug.h"
46 #endif
47 
48 /* Test example header:
49 
50 WWW-Authenticate: Digest realm="testrealm", nonce="1053604598"
51 
52 */
53 
55  char *header) /* rest of the www-authenticate:
56  header */
57 {
58  bool more = TRUE;
59  struct SessionHandle *data=conn->data;
60 
61  /* skip initial whitespaces */
62  while(*header && isspace((int)*header))
63  header++;
64 
65  if(checkprefix("Digest", header)) {
66  header += strlen("Digest");
67 
68  /* clear off any former leftovers and init to defaults */
69  Curl_digest_cleanup(data);
70 
71  while(more) {
72  char value[32];
73  char content[128];
74  size_t totlen=0;
75 
76  while(*header && isspace((int)*header))
77  header++;
78 
79  /* how big can these strings be? */
80  if(2 == sscanf(header, "%31[^=]=\"%127[^\"]\"",
81  value, content)) {
82  if(strequal(value, "nonce")) {
83  data->state.digest.nonce = strdup(content);
84  }
85  else if(strequal(value, "cnonce")) {
86  data->state.digest.cnonce = strdup(content);
87  }
88  else if(strequal(value, "realm")) {
89  data->state.digest.realm = strdup(content);
90  }
91  else if(strequal(value, "algorithm")) {
92  if(strequal(content, "MD5-sess"))
94  /* else, remain using the default md5 */
95  }
96  else {
97  /* unknown specifier, ignore it! */
98  }
99  totlen = strlen(value)+strlen(content)+3;
100  }
101  else
102  break; /* we're done here */
103 
104  header += totlen;
105  if(',' == *header)
106  /* allow the list to be comma-separated */
107  header++;
108  }
109 
110  if(!data->state.digest.nonce)
111  return CURLDIGEST_BAD;
112  }
113  else
114  /* else not a digest, get out */
115  return CURLDIGEST_NONE;
116 
117  return CURLDIGEST_FINE;
118 }
119 
120 /* convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/
121 static void md5_to_ascii(unsigned char *source, /* 16 bytes */
122  unsigned char *dest) /* 33 bytes */
123 {
124  int i;
125  for(i=0; i<16; i++)
126  sprintf((char *)&dest[i*2], "%02x", source[i]);
127 }
128 
130  unsigned char *request,
131  unsigned char *uripath)
132 {
133  /* We have a Digest setup for this, use it! Now, to get all the details for
134  this sorted out, I must urge you dear friend to read up on the RFC2617
135  section 3.2.2, */
136  unsigned char md5buf[16]; /* 16 bytes/128 bits */
137  unsigned char ha1[33]; /* 32 digits and 1 zero byte */
138  unsigned char ha2[33];
139  unsigned char request_digest[33];
140  unsigned char *md5this;
141 
142  struct SessionHandle *data = conn->data;
143 
144  /*
145  if the algorithm is "MD5" or unspecified (which then defaults to MD5):
146 
147  A1 = unq(username-value) ":" unq(realm-value) ":" passwd
148 
149  if the algorithm is "MD5-sess" then:
150 
151  A1 = H( unq(username-value) ":" unq(realm-value) ":" passwd )
152  ":" unq(nonce-value) ":" unq(cnonce-value)
153  */
154  if(data->state.digest.algo == CURLDIGESTALGO_MD5SESS) {
155  md5this = (unsigned char *)
156  aprintf("%s:%s:%s:%s:%s",
157  conn->user,
158  data->state.digest.realm,
159  conn->passwd,
160  data->state.digest.nonce,
161  data->state.digest.cnonce);
162  }
163  else {
164  md5this = (unsigned char *)
165  aprintf("%s:%s:%s",
166  conn->user,
167  data->state.digest.realm,
168  conn->passwd);
169  }
170  Curl_md5it(md5buf, md5this);
171  free(md5this); /* free this again */
172  md5_to_ascii(md5buf, ha1);
173 
174  /*
175  A2 = Method ":" digest-uri-value
176 
177  (The "Method" value is the HTTP request method as specified in section
178  5.1.1 of RFC 2616)
179  */
180 
181  md5this = (unsigned char *)aprintf("%s:%s", request, uripath);
182  Curl_md5it(md5buf, md5this);
183  free(md5this); /* free this again */
184  md5_to_ascii(md5buf, ha2);
185 
186  md5this = (unsigned char *)aprintf("%s:%s:%s", ha1, data->state.digest.nonce,
187  ha2);
188  Curl_md5it(md5buf, md5this);
189  free(md5this); /* free this again */
190  md5_to_ascii(md5buf, request_digest);
191 
192  /* for test case 64 (snooped from a Mozilla 1.3a request)
193 
194  Authorization: Digest username="testuser", realm="testrealm", \
195  nonce="1053604145", uri="/64", response="c55f7f30d83d774a3d2dcacf725abaca"
196  */
197 
198  conn->allocptr.userpwd =
199  aprintf( "Authorization: Digest "
200  "username=\"%s\", "
201  "realm=\"%s\", "
202  "nonce=\"%s\", "
203  "uri=\"%s\", "
204  "response=\"%s\"\r\n",
205  conn->user,
206  data->state.digest.realm,
207  data->state.digest.nonce,
208  uripath, /* this is the PATH part of the URL */
209  request_digest );
210 
211  return CURLE_OK;
212 }
213 
215 {
216  if(data->state.digest.nonce)
217  free(data->state.digest.nonce);
218  data->state.digest.nonce = NULL;
219 
220  if(data->state.digest.cnonce)
221  free(data->state.digest.cnonce);
222  data->state.digest.cnonce = NULL;
223 
224  if(data->state.digest.realm)
225  free(data->state.digest.realm);
226  data->state.digest.realm = NULL;
227 
228  data->state.digest.algo = CURLDIGESTALGO_MD5; /* default algorithm */
229 }
230 
231 #endif
void Curl_md5it(unsigned char *outbuffer, unsigned char *input)
Definition: md5.c:341
GLsizei const GLfloat * value
Definition: glext.h:3614
#define strequal(a, b)
Definition: strequal.h:32
int algo
Definition: urldata.h:175
CURLcode
Definition: curl.h:209
CURLdigest
Definition: http_digest.h:26
struct UrlState state
Definition: urldata.h:903
struct digestdata digest
Definition: urldata.h:706
int i
Definition: process.py:33
char * nonce
Definition: urldata.h:172
GLsizei GLsizei GLcharARB * source
Definition: glext.h:3633
char * passwd
Definition: urldata.h:447
#define NULL
Definition: Lib.h:88
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:2853
CURLdigest Curl_input_digest(struct connectdata *conn, char *header)
Definition: http_digest.c:54
Definition: curl.h:210
struct SessionHandle * data
Definition: urldata.h:403
#define checkprefix(a, b)
Definition: strequal.h:37
char * strdup(char *s1)
Definition: main.c:183
CURLcode Curl_output_digest(struct connectdata *conn, unsigned char *request, unsigned char *uripath)
Definition: http_digest.c:129
void Curl_digest_cleanup(struct SessionHandle *data)
Definition: http_digest.c:214
char * cnonce
Definition: urldata.h:173
#define TRUE
Definition: mprintf.c:69
struct connectdata::dynamically_allocated_data allocptr
char * realm
Definition: urldata.h:174
int sprintf(idStr &string, const char *fmt,...)
Definition: Str.cpp:1528
char * user
Definition: urldata.h:446