Dillo v3.1.1-91-g6d5b3ee3
Loading...
Searching...
No Matches
digest.c
Go to the documentation of this file.
1/*
2 * File: digest.c
3 *
4 * Copyright 2009 Justus Winter <4winter@informatik.uni-hamburg.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <stdlib.h>
13#include "digest.h"
14#include "md5.h"
15#include "msg.h"
16#include "../dlib/dlib.h"
17
18static const char *ALGORITHM2STR[] = { NULL, "MD5", "MD5-sess" };
19static const char *QOP2STR[] = { NULL, "auth", "auth-int" };
20static const char hexchars[] = "0123456789abcdef";
21
22static Dstr *md5hexdigest(const Dstr *data)
23{
24 md5_state_t state;
25 md5_byte_t digest[16];
26 Dstr *result = dStr_sized_new(33);
27 int i;
28
29 md5_init(&state);
30 md5_append(&state, (const md5_byte_t *)data->str, data->len);
31 md5_finish(&state, digest);
32
33 for (i = 0; i < 16; i++)
34 dStr_sprintfa(result, "%02x", digest[i]);
35 return result;
36}
37
42{
43 int i;
44 char *result = dNew(char, 33);
45 for (i = 0; i < 32; i++)
46 result[i] = hexchars[rand() % 16];
47 result[32] = 0;
48 return result;
49}
50
54int a_Digest_compute_digest(AuthRealm_t *realm, const char *username,
55 const char *passwd)
56{
57 Dstr *a1;
58 Dstr *digest;
59
60 if (realm->algorithm == MD5 || realm->algorithm == ALGORITHMNOTSET) {
61 /* A1 = unq(username-value) ":" unq(realm-value) ":" passwd */
62 a1 = dStr_new(NULL);
63 dStr_sprintf(a1, "%s:%s:%s", username, realm->name, passwd);
64 } else if (realm->algorithm == MD5SESS) {
65 /* A1 = H( unq(username-value) ":" unq(realm-value)
66 ** ":" passwd )
67 ** ":" unq(nonce-value) ":" unq(cnonce-value)
68 */
69 Dstr *a0 = dStr_new(NULL);
70 dStr_sprintf(a0, "%s:%s:%s", username, realm->name, passwd);
71 Dstr *ha0 = md5hexdigest(a0);
72 a1 = dStr_new(NULL);
73 dStr_sprintf(a1, "%s:%s:%s", ha0, realm->nonce, realm->cnonce);
74 dStr_free(a0, 1);
75 dStr_free(ha0, 1);
76 } else {
77 MSG("a_Digest_create_auth: Unknown algorithm.\n");
78 return 0;
79 }
80
81 digest = md5hexdigest(a1);
82 realm->authorization = digest->str;
83 dStr_shred(a1);
84 dStr_free(a1, 1);
85 dStr_free(digest, 0);
86 return 1;
87}
88
92static Dstr *Digest_create_response(AuthRealm_t *realm, const char *method,
93 const char *digest_uri,
94 const Dstr *entity_body)
95{
96 Dstr *ha2;
97 Dstr *result;
98
99 if (realm->qop == QOPNOTSET || realm->qop == AUTH) {
100 /* A2 = Method ":" digest-uri-value */
101 Dstr *a2 = dStr_new(NULL);
102 dStr_sprintf(a2, "%s:%s", method, digest_uri);
103 ha2 = md5hexdigest(a2);
104 dStr_free(a2, 1);
105 } else if (realm->qop == AUTHINT) {
106 /* A2 = Method ":" digest-uri-value ":" H(entity-body) */
107 Dstr *hentity = md5hexdigest(entity_body);
108 Dstr *a2 = dStr_new(NULL);
109 dStr_sprintf(a2, "%s:%s:%s", method, digest_uri, hentity->str);
110 ha2 = md5hexdigest(a2);
111 dStr_free(hentity, 1);
112 dStr_free(a2, 1);
113 } else {
114 MSG("a_Digest_create_auth: Unknown qop value.\n");
115 return NULL;
116 }
117 result = dStr_new(NULL);
118
119 if (realm->qop == AUTH || realm->qop == AUTHINT) {
120 dStr_sprintf(result,
121 "%s:%s:%08x:%s:%s:%s",
122 realm->authorization,
123 realm->nonce,
124 realm->nonce_count,
125 realm->cnonce,
126 QOP2STR[realm->qop],
127 ha2->str);
128 } else {
129 dStr_sprintf(result,
130 "%s:%s:%s",
131 realm->authorization,
132 realm->nonce,
133 ha2->str);
134 }
135
136 Dstr *request_digest = md5hexdigest(result);
137 dStr_free(result, 1);
138 dStr_free(ha2, 1);
139 return request_digest;
140}
141
142static void Digest_Dstr_append_token_value(Dstr *str, int delimiter,
143 const char *token,
144 const char *value, int quoted)
145{
146 char c;
147 dStr_sprintfa(str, "%s%s=", (delimiter ? ", " : ""), token);
148 if (quoted) {
149 dStr_append_c(str, '"');
150 while ((c = *value++)) {
151 if (c == '"')
152 dStr_append_c(str, '\\');
153 dStr_append_c(str, c);
154 }
155 dStr_append_c(str, '"');
156 } else {
157 dStr_append(str, value);
158 }
159}
160
170 const char *digest_uri)
171{
172 char *ret;
173 Dstr *response, *result;
174 const char *method = URL_FLAGS(url) & URL_Post ? "POST" : "GET";
175
176 realm->nonce_count++;
177 response = Digest_create_response(realm, method, digest_uri, URL_DATA(url));
178 if (!response)
179 return NULL;
180 result = dStr_new("Authorization: Digest ");
181 Digest_Dstr_append_token_value(result, 0, "username", realm->username, 1);
182 Digest_Dstr_append_token_value(result, 1, "realm", realm->name, 1);
183 Digest_Dstr_append_token_value(result, 1, "nonce", realm->nonce, 1);
184 Digest_Dstr_append_token_value(result, 1, "uri", digest_uri, 1);
185 if (realm->qop != QOPNOTSET) {
186 Digest_Dstr_append_token_value(result, 1, "cnonce", realm->cnonce, 1);
187 dStr_sprintfa(result, ", nc=%08x", realm->nonce_count);
188 }
189 if (realm->algorithm != ALGORITHMNOTSET) {
190 Digest_Dstr_append_token_value(result, 1, "algorithm",
191 ALGORITHM2STR[realm->algorithm], 0);
192 }
193 Digest_Dstr_append_token_value(result, 1, "response", response->str, 1);
194 if (realm->opaque)
195 Digest_Dstr_append_token_value(result, 1, "opaque", realm->opaque, 1);
196 if (realm->qop != QOPNOTSET)
197 Digest_Dstr_append_token_value(result, 1, "qop", QOP2STR[realm->qop], 1);
198 dStr_sprintfa(result, "\r\n");
199
200 dStr_free(response, 1);
201 ret = result->str;
202 dStr_free(result, 0);
203 return ret;
204}
@ AUTHINT
Definition auth.h:12
@ AUTH
Definition auth.h:12
@ QOPNOTSET
Definition auth.h:12
@ MD5SESS
Definition auth.h:11
@ MD5
Definition auth.h:11
@ ALGORITHMNOTSET
Definition auth.h:11
#define MSG(...)
Definition bookmarks.c:46
static const char hexchars[]
Definition digest.c:20
static Dstr * md5hexdigest(const Dstr *data)
Definition digest.c:22
int a_Digest_compute_digest(AuthRealm_t *realm, const char *username, const char *passwd)
This portion only has to be calculated once.
Definition digest.c:54
static const char * QOP2STR[]
Definition digest.c:19
char * a_Digest_create_cnonce(void)
Returns a pointer to a newly allocated string containing a cnonce.
Definition digest.c:41
static const char * ALGORITHM2STR[]
Definition digest.c:18
static void Digest_Dstr_append_token_value(Dstr *str, int delimiter, const char *token, const char *value, int quoted)
Definition digest.c:142
char * a_Digest_authorization_hdr(AuthRealm_t *realm, const DilloUrl *url, const char *digest_uri)
Construct Digest Authorization header.
Definition digest.c:169
static Dstr * Digest_create_response(AuthRealm_t *realm, const char *method, const char *digest_uri, const Dstr *entity_body)
This portion is calculatd for each request.
Definition digest.c:92
void dStr_sprintfa(Dstr *ds, const char *format,...)
Printf-like function that appends.
Definition dlib.c:464
void dStr_append(Dstr *ds, const char *s)
Append a C string to a Dstr.
Definition dlib.c:316
Dstr * dStr_sized_new(int sz)
Create a new string with a given size.
Definition dlib.c:254
void dStr_free(Dstr *ds, int all)
Free a dillo string.
Definition dlib.c:337
void dStr_append_c(Dstr *ds, int c)
Append one character.
Definition dlib.c:349
void dStr_sprintf(Dstr *ds, const char *format,...)
Printf-like function.
Definition dlib.c:450
Dstr * dStr_new(const char *s)
Create a new string.
Definition dlib.c:325
void dStr_shred(Dstr *ds)
Clear a Dstr.
Definition dlib.c:379
#define dNew(type, count)
Definition dlib.h:49
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
Append a string to the message.
Definition md5.c:334
void md5_init(md5_state_t *pms)
Initialize the algorithm.
Definition md5.c:324
void md5_finish(md5_state_t *pms, md5_byte_t digest[16])
Finish the message and return the digest.
Definition md5.c:372
unsigned char md5_byte_t
Definition md5.h:72
unsigned int nonce_count
Definition auth.h:23
char * username
Definition auth.h:21
char * cnonce
Definition auth.h:22
enum AuthParseDigestQOP_t qop
Definition auth.h:28
char * opaque
Definition auth.h:25
char * nonce
Definition auth.h:24
char * name
Definition auth.h:16
char * authorization
Definition auth.h:18
enum AuthParseDigestAlgorithm_t algorithm
Definition auth.h:26
Definition url.h:88
Definition dlib.h:102
Dstr_char_t * str
Definition dlib.h:105
int len
Definition dlib.h:104
Define the state of the MD5 Algorithm.
Definition md5.h:76
#define URL_FLAGS(u)
Definition url.h:79
#define URL_DATA(u)
Definition url.h:77
#define URL_Post
Definition url.h:33