src/server/config/keyfile.c

Mon, 06 Mar 2017 17:32:26 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 06 Mar 2017 17:32:26 +0100
changeset 179
ef6827505bd2
parent 174
8f2a834d1d68
child 255
b5d15a4a19f5
permissions
-rw-r--r--

merge srvctrl into default branch

/*
 * 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"

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) {
        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, sstr_t line) {
    KeyfileConfig *conf = p;
    UcxAllocator *mp = conf->parser.mp;
    
    ssize_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_a(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;i<hash.length;i++) {
        if(hash.ptr[i] == '}') {
            hash_type = sstrsubsl(hash, 1, i-1);
            hash_data = sstrsubs(hash, i+1);
        }
    }
    
    if(!sstrcmp(hash_type, sstr("SSHA"))) {
        entry->hashtype = KEYFILE_SSHA;
    } else if(!sstrcmp(hash_type, sstr("SSHA256"))) {
        entry->hashtype = KEYFILE_SSHA256;
    } else if(!sstrcmp(hash_type, sstr("SSHA512"))) {
        entry->hashtype = KEYFILE_SSHA512;
    } else {
        // unkown hash type
        log_ereport(
                LOG_FAILURE,
                "keyfile_parse: unknown hash type: %s",
                sstrdup_a(mp, hash_type).ptr);
        return 1;
    }
    
    entry->hashdata = sstrdup_a(mp, hash_data);
    
    // get groups
    if(tkn == 3) {
        sstr_t groups_str = sstrtrim(tk[2]);
        ssize_t ngroups = 0;
        sstr_t *groups = sstrsplit(groups_str, sstrn(",", 1), &ngroups);
        if(ngroups > 0) {
            entry->groups = mp->calloc(mp->pool, ngroups, sizeof(sstr_t));
            entry->numgroups = ngroups;
            for(int i=0;i<ngroups;i++) {
                entry->groups[i] = sstrdup_a(mp, sstrtrim(groups[i]));
                free(groups[i].ptr);
            }
            free(groups);
        }
    }
    
    // add user
    conf->users = ucx_list_append_a(mp, conf->users, entry);
    
    // free tokens
    for(int i=0;i<tkn;i++) {
        free(tk[i].ptr);
    }
    free(tk);
    
    return 0;
}

mercurial