From 37b1281f0d41afb6bd79d7d937d14c348426f891 Mon Sep 17 00:00:00 2001 From: Nicolas Favre-Felix Date: Thu, 30 Dec 2010 18:17:26 +0100 Subject: [PATCH] Base64 encode of user:password for HTTP Basic Auth. --- Makefile | 2 +- conf.c | 20 ++++++++- libb64/cencode.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++ libb64/cencode.h | 31 ++++++++++++++ webdis.json | 4 +- 5 files changed, 161 insertions(+), 5 deletions(-) create mode 100644 libb64/cencode.c create mode 100644 libb64/cencode.h diff --git a/Makefile b/Makefile index 760bf31..981763e 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ OUT=webdis HIREDIS_OBJ=hiredis/hiredis.o hiredis/sds.o hiredis/net.o hiredis/async.o JANSSON_OBJ=jansson/src/dump.o jansson/src/error.o jansson/src/hashtable.o jansson/src/load.o jansson/src/strbuffer.o jansson/src/utf.o jansson/src/value.o jansson/src/variadic.o FORMAT_OBJS=formats/json.o formats/raw.o -OBJS=webdis.o conf.o $(FORMAT_OBJS) cmd.o server.o $(HIREDIS_OBJ) $(JANSSON_OBJ) +OBJS=webdis.o conf.o $(FORMAT_OBJS) cmd.o server.o $(HIREDIS_OBJ) $(JANSSON_OBJ) libb64/cencode.o CFLAGS=-O3 -Wall -Wextra -I. -Ijansson/src LDFLAGS=-levent diff --git a/conf.c b/conf.c index c83777a..e98eda3 100644 --- a/conf.c +++ b/conf.c @@ -5,6 +5,7 @@ #include #include +#include #include "conf.h" static struct acl * @@ -118,8 +119,23 @@ conf_parse_acl(json_t *j) { /* parse basic_auth */ if((jbasic = json_object_get(j, "http_basic_auth")) && json_typeof(jbasic) == JSON_STRING) { - a->http_basic_auth = strdup(json_string_value(jbasic)); - /* TODO: base64 encode */ + + /* base64 encode */ + base64_encodestate b64; + int pos; + char *p; + const char *plain = json_string_value(jbasic); + size_t len, plain_len = strlen(plain) + 0; + len = (plain_len + 8) * 8 / 6; + a->http_basic_auth = calloc(len, 1); + + base64_init_encodestate(&b64); + pos = base64_encode_block(plain, (int)plain_len, a->http_basic_auth, &b64); /* FIXME: check return value */ + base64_encode_blockend(a->http_basic_auth + pos, &b64); + + if((p = strchr(a->http_basic_auth + pos, '\n'))) { + *p = 0; + } } /* parse enabled commands */ diff --git a/libb64/cencode.c b/libb64/cencode.c new file mode 100644 index 0000000..a8c8fee --- /dev/null +++ b/libb64/cencode.c @@ -0,0 +1,109 @@ +/* +cencoder.c - c source to a base64 encoding algorithm implementation + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#include "cencode.h" + +const int CHARS_PER_LINE = 72; + +void base64_init_encodestate(base64_encodestate* state_in) +{ + state_in->step = step_A; + state_in->result = 0; + state_in->stepcount = 0; +} + +char base64_encode_value(char value_in) +{ + static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + if (value_in > 63) return '='; + return encoding[(int)value_in]; +} + +int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) +{ + const char* plainchar = plaintext_in; + const char* const plaintextend = plaintext_in + length_in; + char* codechar = code_out; + char result; + char fragment; + + result = state_in->result; + + switch (state_in->step) + { + while (1) + { + case step_A: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_A; + return codechar - code_out; + } + fragment = *plainchar++; + result = (fragment & 0x0fc) >> 2; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x003) << 4; + case step_B: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_B; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0f0) >> 4; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x00f) << 2; + case step_C: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_C; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0c0) >> 6; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x03f) >> 0; + *codechar++ = base64_encode_value(result); + + ++(state_in->stepcount); + if (state_in->stepcount == CHARS_PER_LINE/4) + { + *codechar++ = '\n'; + state_in->stepcount = 0; + } + } + } + /* control should not reach here */ + return codechar - code_out; +} + +int base64_encode_blockend(char* code_out, base64_encodestate* state_in) +{ + char* codechar = code_out; + + switch (state_in->step) + { + case step_B: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + *codechar++ = '='; + break; + case step_C: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + break; + case step_A: + break; + } + *codechar++ = '\n'; + + return codechar - code_out; +} + diff --git a/libb64/cencode.h b/libb64/cencode.h new file mode 100644 index 0000000..c1e3464 --- /dev/null +++ b/libb64/cencode.h @@ -0,0 +1,31 @@ +/* +cencode.h - c header for a base64 encoding algorithm + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#ifndef BASE64_CENCODE_H +#define BASE64_CENCODE_H + +typedef enum +{ + step_A, step_B, step_C +} base64_encodestep; + +typedef struct +{ + base64_encodestep step; + char result; + int stepcount; +} base64_encodestate; + +void base64_init_encodestate(base64_encodestate* state_in); + +char base64_encode_value(char value_in); + +int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in); + +int base64_encode_blockend(char* code_out, base64_encodestate* state_in); + +#endif /* BASE64_CENCODE_H */ diff --git a/webdis.json b/webdis.json index e5cc112..10051dc 100644 --- a/webdis.json +++ b/webdis.json @@ -10,7 +10,7 @@ "acl": [ { - "basic_auth": "user:password", + "http_basic_auth": "user:password", "disabled": ["DEBUG", "FLUSHDB", "FLUSHALL"], "enabled": ["SET"] }, @@ -22,7 +22,7 @@ }, { - "basic_auth": "user:password", + "http_basic_auth": "user:password", "ip": "192.168.10.0/24", "disabled": ["FLUSHDB", "FLUSHALL"], "enabled": ["SET", "*"]