src/server/config/keyfile.c

Wed, 27 Nov 2024 23:00:07 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 27 Nov 2024 23:00:07 +0100
changeset 563
6ca97c99173e
parent 453
4586d534f9b5
permissions
-rw-r--r--

add TODO to use a future ucx feature

/*
 * 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 <stdio.h>
#include <stdlib.h>

#include "keyfile.h"
#include "logging.h"

#define KEYFILE_MAX_TOKENS 4096

KeyfileConfig *load_keyfile_config(const char *file) {
    FILE *in = fopen(file, "r");
    if(in == NULL) {
        return NULL;
    }
    
    KeyfileConfig *conf = malloc(sizeof(KeyfileConfig));
    conf->parser.parse = keyfile_parse;
    conf->file = strdup(file);
    conf->users_begin = NULL;
    conf->users_end = NULL;

    int r = cfg_parse_basic_file((ConfigParser*)conf, in);
    if(r != 0) {
        fclose(in);
        free(conf);
        // TODO: free
        return NULL;
    }
    
    fclose(in);

    return conf;
}

void free_keyfile_config(KeyfileConfig *conf) {
    /*
    if(conf->users) {
        ucx_list_free_a(conf->parser.mp, conf->users);
    }
    ucx_mempool_destroy(conf->parser.mp->pool);
    */
    free(conf);
}

int keyfile_parse(void *p, ConfigLine *begin, ConfigLine *end, cxmutstr line) {
    KeyfileConfig *conf = p;
    CxAllocator *mp = conf->parser.mp;
    
    cxstring *tk = NULL;
    ssize_t tkn = cx_strsplit_a(mp, cx_strcast(line), cx_strn(";", 1), KEYFILE_MAX_TOKENS, &tk);
    
    if(tkn < 2) {
        return 1;
    }
    
    KeyfileEntry *entry = OBJ_NEW(mp, KeyfileEntry);
    ZERO(entry, sizeof(KeyfileEntry));
    
    // get user name
    entry->name = cx_strdup_a(mp, tk[0]);
    
    // get hash
    cxstring hash = cx_strtrim(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
    cxstring hash_type;
    cxstring hash_data;
    for(int i=1;i<hash.length;i++) {
        if(hash.ptr[i] == '}') {
            hash_type = cx_strsubsl(hash, 1, i-1);
            hash_data = cx_strsubs(hash, i+1);
        }
    }
    
    if(!cx_strcmp(hash_type, cx_str("SSHA"))) {
        entry->hashtype = KEYFILE_SSHA;
    } else if(!cx_strcmp(hash_type, cx_str("SSHA256"))) {
        entry->hashtype = KEYFILE_SSHA256;
    } else if(!cx_strcmp(hash_type, cx_str("SSHA512"))) {
        entry->hashtype = KEYFILE_SSHA512;
    } else {
        // unkown hash type
        ws_cfg_log(
                LOG_FAILURE,
                "keyfile_parse: unknown hash type: %s",
                cx_strdup_a(mp, hash_type).ptr);
        return 1;
    }
    
    entry->hashdata = cx_strdup_a(mp, hash_data);
    
    // get groups
    if(tkn == 3) {
        cxstring groups_str = cx_strtrim(tk[2]);
        cxstring *groups = NULL;
        ssize_t ngroups = cx_strsplit_a(mp, groups_str, cx_strn(",", 1), KEYFILE_MAX_TOKENS, &groups);
        if(ngroups > 0) {
            entry->groups = cxCalloc(mp, ngroups, sizeof(cxmutstr));
            entry->numgroups = ngroups;
            for(int i=0;i<ngroups;i++) {
                entry->groups[i] = cx_strdup_a(mp, cx_strtrim(groups[i]));
            }
            cxFree(mp, groups);
        }
    }
    
    // add user
    CFG_KEYFILE_ADD(&conf->users_begin, &conf->users_end, entry);
    
    // free tokens
    cxFree(mp, tk);
    
    return 0;
}

mercurial