add utilities for calculating http digest hashes
authorFelix Fietkau <nbd@openwrt.org>
Sat, 22 Mar 2014 13:23:33 +0000 (14:23 +0100)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 22 Mar 2014 14:07:47 +0000 (15:07 +0100)
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
uclient-utils.c
uclient-utils.h

index 0d0997427986389b8c9dad6c4dd245eb99a89d5b..66a4f15fcf2a423d99b798c13ef3a6196a8a9763 100644 (file)
@@ -1,7 +1,11 @@
 #include <stdint.h>
 #include <stdlib.h>
+#include <string.h>
 #include <ctype.h>
 
+#include <libubox/md5.h>
+#include <libubox/utils.h>
+
 #include "uclient-utils.h"
 
 static const char *b64 =
@@ -75,3 +79,67 @@ int uclient_urldecode(const char *in, char *out, bool decode_plus)
        *out = 0;
        return ret;
 }
+
+static char hex_digit(char val)
+{
+       val += val > 9 ? 'a' - 10 : '0';
+       return val;
+}
+
+void bin_to_hex(char *dest, const void *buf, int len)
+{
+       const uint8_t *data = buf;
+       int i;
+
+       for (i = 0; i < len; i++) {
+               *(dest++) = hex_digit(data[i] >> 4);
+               *(dest++) = hex_digit(data[i] & 0xf);
+       }
+       *dest = 0;
+}
+
+static void http_create_hash(char *dest, const char * const * str, int n_str)
+{
+       uint32_t hash[4];
+       md5_ctx_t md5;
+       int i;
+
+       md5_begin(&md5);
+       for (i = 0; i < n_str; i++) {
+               if (i)
+                       md5_hash(":", 1, &md5);
+               md5_hash(str[i], strlen(str[i]), &md5);
+       }
+       md5_end(hash, &md5);
+       bin_to_hex(dest, &hash, sizeof(hash));
+}
+
+void http_digest_calculate_auth_hash(char *dest, const char *user, const char *realm, const char *password)
+{
+       const char *hash_str[] = {
+               user,
+               realm,
+               password
+       };
+
+       http_create_hash(dest, hash_str, ARRAY_SIZE(hash_str));
+}
+
+void http_digest_calculate_response(char *dest, const struct http_digest_data *data)
+{
+       const char *h_a2_strings[] = {
+               data->method,
+               data->uri,
+       };
+       const char *resp_strings[] = {
+               data->auth_hash,
+               data->nonce,
+               data->nc,
+               data->cnonce,
+               data->qop,
+               dest, /* initialized to H(A2) first */
+       };
+
+       http_create_hash(dest, h_a2_strings, ARRAY_SIZE(h_a2_strings));
+       http_create_hash(dest, resp_strings, ARRAY_SIZE(resp_strings));
+}
index a7eaf1cabac0a9ce2c5c2c6de2c9bc315accfef4..83ab09ae1df1393ab8139b8764bd59aac703a635 100644 (file)
@@ -3,14 +3,28 @@
 
 #include <stdbool.h>
 
+struct http_digest_data {
+       const char *uri;
+       const char *method;
+
+       const char *auth_hash; /* H(A1) */
+       const char *qop;
+       const char *nc;
+       const char *nonce;
+       const char *cnonce;
+};
+
 static inline int base64_len(int len)
 {
        return ((len + 2) / 3) * 4;
 }
 
 void base64_encode(const void *inbuf, unsigned int len, void *out);
+void bin_to_hex(char *dest, const void *buf, int len);
 
 int uclient_urldecode(const char *in, char *out, bool decode_plus);
 
+void http_digest_calculate_auth_hash(char *dest, const char *user, const char *realm, const char *password);
+void http_digest_calculate_response(char *dest, const struct http_digest_data *data);
 
 #endif