8 #include "crypto/crypto.h"
11 digest_md5_to_hex(const unsigned char *md5buf
, char *md5hex
)
14 for (i
=0; i
<MD5_SIZE
*2; i
++) {
15 int val
= (i
%2) ? md5buf
[i
/2]&0x0f : (md5buf
[i
/2]&0xf0)>>4;
16 md5hex
[i
] = (val
<10) ? '0'+val
: 'a'+(val
-10);
21 digest_get_response(const char *username
, const char *realm
,
22 const char *password
, const char *nonce
,
23 const char *method
, const char *uri
,
27 unsigned char md5buf
[MD5_SIZE
];
28 char md5hex
[MD5_SIZE
*2];
30 /* Calculate first inner MD5 hash */
32 MD5_Update(&md5ctx
, (const unsigned char *)username
, strlen(username
));
33 MD5_Update(&md5ctx
, (const unsigned char *)":", 1);
34 MD5_Update(&md5ctx
, (const unsigned char *)realm
, strlen(realm
));
35 MD5_Update(&md5ctx
, (const unsigned char *)":", 1);
36 MD5_Update(&md5ctx
, (const unsigned char *)password
, strlen(password
));
37 MD5_Final(md5buf
, &md5ctx
);
38 digest_md5_to_hex(md5buf
, md5hex
);
40 /* Calculate second inner MD5 hash */
42 MD5_Update(&md5ctx
, (const unsigned char *)method
, strlen(method
));
43 MD5_Update(&md5ctx
, (const unsigned char *)":", 1);
44 MD5_Update(&md5ctx
, (const unsigned char *)uri
, strlen(uri
));
45 MD5_Final(md5buf
, &md5ctx
);
47 /* Calculate outer MD5 hash */
49 MD5_Update(&md5ctx
, (const unsigned char *)md5hex
, sizeof(md5hex
));
50 MD5_Update(&md5ctx
, (const unsigned char *)":", 1);
51 MD5_Update(&md5ctx
, (const unsigned char *)nonce
, strlen(nonce
));
52 MD5_Update(&md5ctx
, (const unsigned char *)":", 1);
53 digest_md5_to_hex(md5buf
, md5hex
);
54 MD5_Update(&md5ctx
, (const unsigned char *)md5hex
, sizeof(md5hex
));
55 MD5_Final(md5buf
, &md5ctx
);
57 /* Store the final result to response */
58 digest_md5_to_hex(md5buf
, response
);
62 digest_generate_nonce(char *result
, int resultlen
)
65 unsigned char md5buf
[MD5_SIZE
];
66 char md5hex
[MD5_SIZE
*2];
69 SYSTEM_GET_TIME(time
);
72 MD5_Update(&md5ctx
, (unsigned char *)&time
, sizeof(time
));
73 MD5_Final(md5buf
, &md5ctx
);
74 digest_md5_to_hex(md5buf
, md5hex
);
76 memset(result
, 0, resultlen
);
77 strncpy(result
, md5hex
, resultlen
-1);
81 digest_is_valid(const char *our_realm
, const char *password
,
82 const char *our_nonce
, const char *method
,
83 const char *our_uri
, const char *authorization
)
90 /* Get values from authorization */
91 char *username
= NULL
;
95 char *response
= NULL
;
97 /* Buffer for our response */
98 char our_response
[MD5_SIZE
*2+1];
100 if (!authorization
) {
103 current
= auth
= strdup(authorization
);
108 /* Check that the type is digest */
109 if (strncmp("Digest", current
, 6)) {
115 while ((value
= utils_strsep(¤t
, ",")) != NULL
) {
118 /* Find first and last characters */
120 last
= value
+strlen(value
)-1;
122 /* Trim spaces from the value */
123 while (*first
== ' ' && first
< last
) first
++;
124 while (*last
== ' ' && last
> first
) last
--;
126 /* Validate the last character */
127 if (*last
!= '"') continue;
130 /* Store value if it is relevant */
131 if (!strncmp("username=\"", first
, 10))
133 if (!strncmp("realm=\"", first
, 7))
135 if (!strncmp("nonce=\"", first
, 7))
137 if (!strncmp("uri=\"", first
, 5))
139 if (!strncmp("response=\"", first
, 10))
143 if (!username
|| !realm
|| !nonce
|| !uri
|| !response
) {
146 if (strcmp(realm
, our_realm
) || strcmp(nonce
, our_nonce
) || strcmp(uri
, our_uri
)) {
150 /* Calculate our response */
151 memset(our_response
, 0, sizeof(our_response
));
152 digest_get_response(username
, realm
, password
, nonce
,
153 method
, uri
, our_response
);
154 success
= !strcmp(response
, our_response
);