# HG changeset patch # User Olaf Wintermann # Date 1368121271 -7200 # Node ID c47e081b6c0ff7b9fbc41b46e084ba88410c3b69 # Parent c858850f3d3a38642489346328e90fb71f211baa added keyfile based authentication diff -r c858850f3d3a -r c47e081b6c0f configure --- a/configure Thu May 09 13:19:51 2013 +0200 +++ b/configure Thu May 09 19:41:11 2013 +0200 @@ -35,6 +35,9 @@ HOST=`uname -n` INSTALL_DIR=`pwd`/work +OPENSSL_CFLAGS=`pkg-config --cflags openssl` +OPENSSL_LDFLAGS=`pkg-config --libs openssl` + # create config.mk echo "generate config.mk" @@ -68,6 +71,10 @@ echo " include \$(BUILD_ROOT)/make/$CCONF include \$(BUILD_ROOT)/make/$PLATFORM + +CFLAGS += $OPENSSL_CFLAGS +LDFLAGS += $OPENSSL_LDFLAGS + " >> config.mk diff -r c858850f3d3a -r c47e081b6c0f make/linux.mk --- a/make/linux.mk Thu May 09 13:19:51 2013 +0200 +++ b/make/linux.mk Thu May 09 19:41:11 2013 +0200 @@ -28,9 +28,8 @@ # compiler and linker flags - -LDFLAGS = -CFLAGS += -DLINUX +CFLAGS += -DLINUX +LDFLAGS = -lpthread -ldl -lnsl -lm -lxerces-c -lldap # platform dependend source files diff -r c858850f3d3a -r c47e081b6c0f make/solaris.mk --- a/make/solaris.mk Thu May 09 13:19:51 2013 +0200 +++ b/make/solaris.mk Thu May 09 19:41:11 2013 +0200 @@ -29,7 +29,7 @@ # compiler and linker flags -LDFLAGS = -lsocket -lsendfile -lposix4 +LDFLAGS += -lsendfile -lposix4 -lpthread -ldl -lm -lxerces-c -lldap # platform dependend source files diff -r c858850f3d3a -r c47e081b6c0f make/suncc.mk --- a/make/suncc.mk Thu May 09 13:19:51 2013 +0200 +++ b/make/suncc.mk Thu May 09 19:41:11 2013 +0200 @@ -26,7 +26,8 @@ # POSSIBILITY OF SUCH DAMAGE. # -CFLAGS = -xc99 -g -D_REENTRANT +CFLAGS += -xc99 -g -D_REENTRANT +LDFLAGS += -lpthread -ldl -lm -lxerces-c -lldap CC = cc CXX = CC diff -r c858850f3d3a -r c47e081b6c0f src/server/Makefile --- a/src/server/Makefile Thu May 09 13:19:51 2013 +0200 +++ b/src/server/Makefile Thu May 09 19:41:11 2013 +0200 @@ -29,7 +29,7 @@ BUILD_ROOT = ../.. include $(BUILD_ROOT)/config.mk -LDFLAGS += -lpthread -ldl -lnsl -lm -lxerces-c -lldap +# LDFLAGS += -lpthread -ldl -lnsl -lm -lxerces-c -lldap OBJ_DIR = $(BUILD_ROOT)/build/ diff -r c858850f3d3a -r c47e081b6c0f src/server/config/acl.c --- a/src/server/config/acl.c Thu May 09 13:19:51 2013 +0200 +++ b/src/server/config/acl.c Thu May 09 19:41:11 2013 +0200 @@ -49,6 +49,8 @@ free_acl_file(conf); return NULL; } + + fclose(in); return conf; } diff -r c858850f3d3a -r c47e081b6c0f src/server/config/initconf.c --- a/src/server/config/initconf.c Thu May 09 13:19:51 2013 +0200 +++ b/src/server/config/initconf.c Thu May 09 19:41:11 2013 +0200 @@ -48,6 +48,8 @@ // TODO: free return NULL; } + + fclose(in); return conf; } diff -r c858850f3d3a -r c47e081b6c0f src/server/config/keyfile.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/config/keyfile.c Thu May 09 19:41:11 2013 +0200 @@ -0,0 +1,137 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "keyfile.h" + +KeyfileConfig *load_keyfile_config(char *file) { + FILE *in = fopen(file, "r"); + if(in == NULL) { + return NULL; + } + + KeyfileConfig *conf = malloc(sizeof(KeyfileConfig)); + conf->parser.parse = keyfile_parse; + conf->file = file; + conf->users = NULL; + + int r = cfg_parse_basic_file((ConfigParser*)conf, in); + if(r != 0) { + // TODO: free + return NULL; + } + + fclose(in); + + return conf; +} + +void free_keyfile_config(KeyfileConfig *conf) { + if(conf->users) { + ucx_list_free(conf->users); + } + ucx_mempool_free(conf->parser.mp); + free(conf); +} + +int keyfile_parse(void *p, ConfigLine *begin, ConfigLine *end, sstr_t line) { + KeyfileConfig *conf = p; + UcxMempool *mp = conf->parser.mp; + + size_t tkn = 0; + sstr_t *tk = sstrsplit(line, sstrn(";", 1), &tkn); + + if(tkn < 2) { + return 1; + } + + KeyfileEntry *entry = OBJ_NEW(mp, KeyfileEntry); + entry->groups = NULL; + entry->numgroups = 0; + + // get user name + entry->name = sstrdup_mp(mp, tk[0]); + + // get hash + sstr_t hash = sstrtrim(tk[1]); + if(hash.length < 4) { + // to short + return 1; + } + if(hash.ptr[0] != '{') { + // missing hash type specification + return 1; + } + + // get hash type and data + sstr_t hash_type; + sstr_t hash_data; + for(int i=1;ihashtype = KEYFILE_SSHA; + } else { + // unkown hash type + fprintf(stderr, "unknown hash type: %s\n", sstrdup(hash_type).ptr); + return 1; + } + + entry->hashdata = sstrdup_mp(mp, hash_data); + + // get groups + if(tkn == 3) { + sstr_t groups_str = sstrtrim(tk[2]); + size_t ngroups = 0; + sstr_t *groups = sstrsplit(groups_str, sstrn(",", 1), &ngroups); + entry->groups = calloc(ngroups, sizeof(sstr_t)); + entry->numgroups = ngroups; + for(int i=0;igroups[i] = sstrdup_mp(mp, sstrtrim(groups[i])); + free(groups[i].ptr); + } + free(groups); + } + + // add user + conf->users = ucx_list_append(conf->users, entry); + + // free tokens + for(int i=0;idirectives, + sstr("File")); + if(file.length == 0) { + log_ereport( + LOG_MISCONFIG, + "missing File parameter for keyfile authdb"); + return 1; + } + + // load keyfile + ConfigFile *f = cfgmgr_get_file(file); + if(f == NULL) { + f = malloc(sizeof(ConfigFile)); + f->data = NULL; + f->file = sstrdup(file); + f->reload = keyfile_reload; + //f->reload(f, cfg); + if(cfgmgr_reload_file(f, cfg, NULL)) { + free(f->file.ptr); + free(f); + return -1; + } + cfgmgr_attach_file(f); + } + + // add keyfile authdb + Keyfile *keyfile = f->data; + keyfile->authdb.name = sstrdup(name).ptr; + printf("authdb: %d\n", keyfile); + ucx_map_sstr_put(cfg->authdbs, name, keyfile); } return 0; @@ -833,3 +866,33 @@ return &acllist->acl; } + +int keyfile_reload(ConfigFile *file, ServerConfiguration *cfg) { + KeyfileConfig *conf = load_keyfile_config(file->file.ptr); + if(!conf) { + return 1; + } + + Keyfile *keyfile = keyfile_new(); + + UCX_FOREACH(UcxList*, conf->users, elm) { + KeyfileEntry *user = elm->data; + keyfile_add_user( + keyfile, + user->name, + user->hashtype, + user->hashdata, + user->groups, + user->numgroups); + } + + free_keyfile_config(conf); + + Keyfile *old_data = file->data; + file->data = keyfile; + if(old_data) { + keyfile_unref(old_data); + } + + return 0; +} diff -r c858850f3d3a -r c47e081b6c0f src/server/daemon/config.h --- a/src/server/daemon/config.h Thu May 09 13:19:51 2013 +0200 +++ b/src/server/daemon/config.h Thu May 09 19:41:11 2013 +0200 @@ -38,8 +38,10 @@ #include "../config/serverconf.h" #include "../config/mimeconf.h" #include "../config/acl.h" +#include "../config/keyfile.h" #include "acldata.h" +#include "keyfile_auth.h" #include "../ucx/list.h" #include "../ucx/dlist.h" @@ -116,6 +118,7 @@ void mime_conf_unref(MimeMap *conf); int acl_conf_reload(ConfigFile *file, ServerConfiguration *cfg); ACLList* acl_config_convert(ServerConfiguration *cfg, ACLConfig *acl); +int keyfile_reload(ConfigFile *file, ServerConfiguration *cfg); diff -r c858850f3d3a -r c47e081b6c0f src/server/daemon/configmanager.c --- a/src/server/daemon/configmanager.c Thu May 09 13:19:51 2013 +0200 +++ b/src/server/daemon/configmanager.c Thu May 09 19:41:11 2013 +0200 @@ -140,7 +140,8 @@ } ServerConfiguration *config; - if(sc_last_modified != s.st_mtim.tv_sec) { + //if(sc_last_modified != s.st_mtim.tv_sec) { + if(cfgreload || !current_config) { printf("cfgmgr load server.conf\n"); config = load_server_conf( current_config, @@ -152,7 +153,7 @@ } sc_last_modified = s.st_mtim.tv_sec; - } else if(cfgreload) { + } else if(0) { /* copy configuration */ printf("cfgmgr copy server.conf\n"); diff -r c858850f3d3a -r c47e081b6c0f src/server/daemon/keyfile_auth.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/daemon/keyfile_auth.c Thu May 09 19:41:11 2013 +0200 @@ -0,0 +1,158 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "../util/atomic.h" +#include "../util/util.h" + +#include "keyfile_auth.h" + +Keyfile* keyfile_new() { + Keyfile *keyfile = malloc(sizeof(Keyfile)); + keyfile->authdb.get_user = keyfile_get_user; + keyfile->users = ucx_map_new(16); + keyfile->ref = 1; + return keyfile; +} + +void keyfile_ref(Keyfile *keyfile) { + ws_atomic_inc32(&keyfile->ref); +} + +void keyfile_unref(Keyfile *keyfile) { + uint32_t ref = ws_atomic_dec32(&keyfile->ref); + if(ref == 0) { + UcxMapIterator i = ucx_map_iterator(keyfile->users); + KeyfileUser *user; + UCX_MAP_FOREACH(user, i) { + free(user->user.name); + free(user->hash); + for(int i=0;inumgroups;i++) { + free(user->groups[i].ptr); + } + free(user->groups); + } + ucx_map_free(keyfile->users); + + free(keyfile->authdb.name); + free(keyfile); + } +} + +void keyfile_add_user( + Keyfile *keyfile, + sstr_t name, + enum KeyfileHashType hash_type, + sstr_t hash, + sstr_t *groups, + size_t ngroups) +{ + if(hash.length < 12) { + // hash too short + // TODO: log + return; + } + + KeyfileUser *user = malloc(sizeof(KeyfileUser)); + user->user.name = sstrdup(name).ptr; + user->user.verify_password = keyfile_user_verify_password; + user->user.check_group = keyfile_user_check_group; + user->user.free = keyfile_user_free; + + user->hash_type = hash_type; + user->hash = malloc(hash.length + 1); + user->hashlen = util_base64decode(hash.ptr, hash.length, user->hash); + + user->groups = calloc(ngroups, sizeof(sstr_t)); + for(int i=0;igroups[i] = sstrdup(groups[i]); + sstrdup(groups[i]); + } + + // add to keyfile + ucx_map_sstr_put(keyfile->users, name, user); +} + +// authdb functions + +User* keyfile_get_user(AuthDB *db, char *user) { + Keyfile *keyfile = (Keyfile*)db; + return ucx_map_cstr_get(keyfile->users, user); +} + +int keyfile_user_verify_password(User *user, char *password) { + KeyfileUser *usr = (KeyfileUser*)user; + switch(usr->hash_type) { + case KEYFILE_SSHA: return ssha_verify(usr, password); + } + return 0; +} + +int keyfile_user_check_group(User *user, char *group) { + KeyfileUser *usr = (KeyfileUser*)user; + sstr_t grp = sstr(group); + for(int i=0;inumgroups;i++) { + if(!sstrcmp(usr->groups[i], grp)) { + return 1; + } + } + return 0; +} + +void keyfile_user_free(User *user) { + // don't free, it will be freed by keyfile_unref +} + + +int ssha_verify(KeyfileUser *user, char *password) { + /* + * SSHA: SHA1(pw + salt) + 8 bytes salt + * the SSHA hash is already base64 decoded + */ + + char *salt = user->hash + user->hashlen - 8; // last 8 bytes are salt + size_t pwlen = strlen(password); + + size_t saltpwlen = pwlen + 8; + char *saltpw = malloc(saltpwlen); + memcpy(saltpw, password, pwlen); + memcpy(saltpw + pwlen, salt, 8); + + unsigned char pwhash[20]; + SHA1((const unsigned char*)saltpw, saltpwlen, pwhash); + + if(!memcmp(user->hash, pwhash, 20)) { + return 1; + } + + return 0; +} diff -r c858850f3d3a -r c47e081b6c0f src/server/daemon/keyfile_auth.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/daemon/keyfile_auth.h Thu May 09 19:41:11 2013 +0200 @@ -0,0 +1,86 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef KEYFILE_AUTH_H +#define KEYFILE_AUTH_H + +#include "../public/auth.h" +#include "../ucx/map.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct keyfile Keyfile; +typedef struct keyfile_user KeyfileUser; + +enum KeyfileHashType { + KEYFILE_SSHA = 0 +}; + +struct keyfile { + AuthDB authdb; + UcxMap *users; + uint32_t ref; +}; + +struct keyfile_user { + User user; + sstr_t *groups; + size_t numgroups; + enum KeyfileHashType hash_type; + char *hash; + size_t hashlen; +}; + +Keyfile* keyfile_new(); +void keyfile_ref(Keyfile *keyfile); +void keyfile_unref(Keyfile *keyfile); + +void keyfile_add_user( + Keyfile *keyfile, + sstr_t user, + enum KeyfileHashType hash_type, + sstr_t hash, + sstr_t *groups, + size_t ngroups); + +User* keyfile_get_user(AuthDB *db, char *user); +int keyfile_user_verify_password(User *user, char *password); +int keyfile_user_check_group(User *user, char *group); +void keyfile_user_free(User *user); + +// SSHA password compare +int ssha_verify(KeyfileUser *user, char *password); + +#ifdef __cplusplus +} +#endif + +#endif /* KEYFILE_AUTH_H */ + diff -r c858850f3d3a -r c47e081b6c0f src/server/daemon/objs.mk --- a/src/server/daemon/objs.mk Thu May 09 13:19:51 2013 +0200 +++ b/src/server/daemon/objs.mk Thu May 09 19:41:11 2013 +0200 @@ -49,6 +49,7 @@ DAEMONOBJ += threadpools.o DAEMONOBJ += authdb.o DAEMONOBJ += ldap_auth.o +DAEMONOBJ += keyfile_auth.o DAEMONOBJ += error.o DAEMONOBJ += acl.o DAEMONOBJ += acldata.o diff -r c858850f3d3a -r c47e081b6c0f src/server/public/auth.h --- a/src/server/public/auth.h Thu May 09 13:19:51 2013 +0200 +++ b/src/server/public/auth.h Thu May 09 19:41:11 2013 +0200 @@ -52,6 +52,7 @@ /* * verify the users password + * returns 1 if the password is correct, otherwise 0 * * param1: user * param2: password diff -r c858850f3d3a -r c47e081b6c0f src/server/safs/auth.c --- a/src/server/safs/auth.c Thu May 09 13:19:51 2013 +0200 +++ b/src/server/safs/auth.c Thu May 09 19:41:11 2013 +0200 @@ -42,7 +42,7 @@ /* ------------------------------ _uudecode ------------------------------- */ -const unsigned char pr2six[256] = { +static const unsigned char pr2six[256] = { 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63, 52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9, diff -r c858850f3d3a -r c47e081b6c0f src/server/ucx/Makefile --- a/src/server/ucx/Makefile Thu May 09 13:19:51 2013 +0200 +++ b/src/server/ucx/Makefile Thu May 09 19:41:11 2013 +0200 @@ -27,5 +27,5 @@ # $(UCX_OBJPRE)%.o: ucx/%.c - $(CC) -o $@ -c -g $(CFLAGS) $< + $(CC) -o $@ -c $(CFLAGS) $< diff -r c858850f3d3a -r c47e081b6c0f src/server/util/util.c --- a/src/server/util/util.c Thu May 09 13:19:51 2013 +0200 +++ b/src/server/util/util.c Thu May 09 19:41:11 2013 +0200 @@ -56,6 +56,58 @@ #include "util.h" + + +/* ------------------------------ _uudecode ------------------------------- */ + +static const unsigned char pr2six[256] = { + 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63, + 52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9, + 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27, + 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51, + 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64, + 64,64,64,64,64,64,64,64,64,64,64,64,64 +}; + +/** you MUST reserve at least 2 additional bytes for bufout */ +size_t util_base64decode(char *bufcoded, size_t codedbytes, char *bufout) { + register char *bufin = bufcoded; + register int nprbytes; + size_t nbytesdecoded; + + /* Find the length */ + nprbytes = (int) codedbytes; + while(pr2six[(int)(bufin[nprbytes-1])] >= 64) { + nprbytes--; + } + nbytesdecoded = ((nprbytes+3)/4) * 3; + + while (nprbytes > 0) { + *(bufout++) = (unsigned char) + (pr2six[(int)(*bufin)] << 2 | pr2six[(int)bufin[1]] >> 4); + *(bufout++) = (unsigned char) + (pr2six[(int)bufin[1]] << 4 | pr2six[(int)bufin[2]] >> 2); + *(bufout++) = (unsigned char) + (pr2six[(int)bufin[2]] << 6 | pr2six[(int)bufin[3]]); + bufin += 4; + nprbytes -= 4; + } + + if(nprbytes & 03) { + if(pr2six[(int)bufin[-2]] > 63) + nbytesdecoded -= 2; + else + nbytesdecoded -= 1; + } + + return nbytesdecoded; +} + /* NSAPI_PUBLIC int util_getboolean(const char *v, int def) { if(v[0] == 'T' || v[0] == 't') { diff -r c858850f3d3a -r c47e081b6c0f src/server/util/util.h --- a/src/server/util/util.h Thu May 09 13:19:51 2013 +0200 +++ b/src/server/util/util.h Thu May 09 19:41:11 2013 +0200 @@ -77,6 +77,8 @@ extern "C" { #endif +size_t util_base64decode(char *bufcoded, size_t codedbytes, char *bufout); + NSAPI_PUBLIC int INTutil_init_PRNetAddr(PRNetAddr * naddr, char * ipstr, int iplen, int type);