#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);
return NULL;
}
fclose(in);
return conf;
}
void free_keyfile_config(KeyfileConfig *conf) {
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));
entry->name = cx_strdup_a(mp, tk[
0]);
cxstring hash = cx_strtrim(tk[
1]);
if(hash.length <
4) {
return 1;
}
if(hash.ptr[
0] !=
'{') {
return 1;
}
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 {
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);
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);
}
}
CFG_KEYFILE_ADD(&conf->users_begin, &conf->users_end, entry);
cxFree(mp, tk);
return 0;
}