123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511 |
- /*
- * LDAP module - Configuration file parser
- *
- * Copyright (C) 2001-2003 FhG FOKUS
- * Copyright (C) 2004,2005 Free Software Foundation, Inc.
- * Copyright (C) 2005,2006 iptelorg GmbH
- *
- * This file is part of ser, a free SIP server.
- *
- * SER is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- *
- * SER is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #include "ld_cfg.h"
- #include "ld_mod.h"
- #include "ld_uri.h"
- #include "../../cfg_parser.h"
- #include "../../mem/mem.h"
- #include "../../dprint.h"
- #include "../../trim.h"
- #include "../../ut.h"
- #include "../../resolve.h"
- #include <ldap.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <libgen.h>
- enum section_type {
- LDAP_CON_SECTION = 0,
- LDAP_TABLE_SECTION
- };
- static struct ld_cfg* cfg = NULL;
- static struct ld_con_info* con = NULL;
- void ld_cfg_free(void)
- {
- struct ld_con_info* c;
- struct ld_cfg* ptr;
- int i;
- while (cfg) {
- ptr = cfg;
- cfg = cfg->next;
- if (ptr->table.s) pkg_free(ptr->table.s);
- if (ptr->base.s) pkg_free(ptr->base.s);
- if (ptr->filter.s) pkg_free(ptr->filter.s);
- for(i = 0; i < ptr->n; i++) {
- if (ptr->field[i].s) pkg_free(ptr->field[i].s);
- if (ptr->attr[i].s) pkg_free(ptr->attr[i].s);
- }
- if (ptr->field) pkg_free(ptr->field);
- if (ptr->attr) pkg_free(ptr->attr);
- if (ptr->syntax) pkg_free(ptr->syntax);
- }
- while (con) {
- c = con;
- con = con->next;
- if (c->id.s) pkg_free(c->id.s);
- if (c->host.s) pkg_free(c->host.s);
- if (c->username.s) pkg_free(c->username.s);
- if (c->password.s) pkg_free(c->password.s);
- pkg_free(c);
- }
- }
- static int parse_field_map(void* param, cfg_parser_t* st, unsigned int flags)
- {
- int ret;
- cfg_token_t t;
- void* ptr;
- static cfg_option_t syntaxes[] = {
- {"GeneralizedTime", .val = LD_SYNTAX_GENTIME},
- {"Integer", .val = LD_SYNTAX_INT },
- {"BitString", .val = LD_SYNTAX_BIT },
- {"Boolean", .val = LD_SYNTAX_BOOL },
- {"String", .val = LD_SYNTAX_STRING },
- {"Binary", .val = LD_SYNTAX_BIN },
- {"Float", .val = LD_SYNTAX_FLOAT },
- {0}
- };
- cfg_option_t* syntax;
- if (cfg_eat_equal(st, flags)) return -1;
- if (!(ptr = pkg_realloc(cfg->field, sizeof(str) * (cfg->n + 1)))) {
- ERR("ldap:%s:%d:%d Out of memory\n", st->file, st->line, st->col);
- return -1;
- }
- cfg->field = (str*)ptr;
- cfg->field[cfg->n].s = NULL;
- if (!(ptr = pkg_realloc(cfg->attr, sizeof(str) * (cfg->n + 1)))) {
- ERR("ldap:%s:%d:%d: Out of memory\n", st->file, st->line, st->col);
- return -1;
- }
- cfg->attr = (str*)ptr;
- cfg->attr[cfg->n].s = NULL;
- if (!(ptr = pkg_realloc(cfg->syntax, sizeof(enum ld_syntax)*(cfg->n+1)))) {
- ERR("ldap:%s:%d:%d: Out of memory\n", st->file, st->line, st->col);
- return -1;
- }
- cfg->syntax = (enum ld_syntax*)ptr;
- cfg->syntax[cfg->n] = LD_SYNTAX_STRING;
- cfg->n++;
- ret = cfg_get_token(&t, st, 0);
- if (ret < 0) return -1;
- if (ret > 0) {
- ERR("ldap:%s:%d:%d: Database field name expected\n",
- st->file, st->line, st->col);
- return -1;
- }
- if (t.type != CFG_TOKEN_ALPHA) {
- ERR("ldap:%s:%d:%d: Invalid field name format %d:'%.*s'\n",
- st->file, t.start.line, t.start.col,
- t.type, STR_FMT(&t.val));
- return -1;
- }
- if ((cfg->field[cfg->n - 1].s = as_asciiz(&t.val)) == NULL) {
- ERR("ldap:%s:%d:%d: Out of memory\n", st->file,
- t.start.line, t.start.col);
- return -1;
- }
- cfg->field[cfg->n - 1].len = t.val.len;
- ret = cfg_get_token(&t, st, 0);
- if (ret < 0) return -1;
- if (ret > 0) {
- ERR("ldap:%s:%d:%d: Delimiter ':' missing\n",
- st->file, st->line, st->col);
- return -1;
- }
- if (t.type != ':') {
- ERR("ldap:%s:%d:%d: Syntax error, ':' expected\n",
- st->file, t.start.line, t.start.col);
- return -1;
- }
- ret = cfg_get_token(&t, st, 0);
- if (ret < 0) return -1;
- if (ret > 0) {
- ERR("ldap:%s:%d:%d: LDAP Attribute syntax or name expected\n",
- st->file, st->line, st->col);
- return -1;
- }
- if (t.type == '(') {
- ret = cfg_get_token(&t, st, 0);
- if (ret < 0) return -1;
- if (ret > 0) {
- ERR("ldap:%s:%d:%d: LDAP Attribute Syntax expected\n",
- st->file, st->line, st->col);
- return -1;
- }
- if (t.type != CFG_TOKEN_ALPHA) {
- ERR("ldap:%s:%d:%d: Invalid LDAP attribute syntax format %d:'%.*s'\n",
- st->file, t.start.line, t.start.col,
- t.type, STR_FMT(&t.val));
- return -1;
- }
- if ((syntax = cfg_lookup_token(syntaxes, &t.val)) == NULL) {
- ERR("ldap:%s:%d:%d: Invalid syntaxt value '%.*s'\n",
- st->file, t.start.line, t.start.col, STR_FMT(&t.val));
- return -1;
- }
- cfg->syntax[cfg->n - 1] = syntax->val;
- ret = cfg_get_token(&t, st, 0);
- if (ret < 0) return -1;
- if (ret > 0) {
- ERR("ldap:%s:%d:%d: Closing ')' missing in attribute syntax\n",
- st->file, st->line, st->col);
- return -1;
- }
- if (t.type != ')') {
- ERR("ldap:%s:%d:%d: Syntax error, ')' expected\n",
- st->file, st->line, st->col);
- return -1;
- }
- ret = cfg_get_token(&t, st, 0);
- if (ret < 0) return -1;
- if (ret > 0) {
- ERR("ldap:%s:%d:%d: LDAP Attribute name expected\n",
- st->file, st->line, st->col);
- return -1;
- }
- }
- if (t.type != CFG_TOKEN_ALPHA) {
- ERR("ldap:%s:%d:%d: Invalid LDAP attribute name format %d:'%.*s'\n",
- st->file, t.start.line, t.start.col, t.type, STR_FMT(&t.val));
- return -1;
- }
- if ((cfg->attr[cfg->n - 1].s = as_asciiz(&t.val)) == NULL) {
- ERR("ldap:%s:%d:%d: Out of memory\n",
- st->file, t.start.line, t.start.col);
- return -1;
- }
- cfg->attr[cfg->n - 1].len = t.val.len;
- if (cfg_eat_eol(st, flags)) return -1;
- return 0;
- }
- static cfg_option_t scope_values[] = {
- {"base", .val = LDAP_SCOPE_BASE },
- {"onelevel", .val = LDAP_SCOPE_ONELEVEL},
- {"one", .val = LDAP_SCOPE_ONELEVEL},
- {"subtree", .val = LDAP_SCOPE_SUBTREE },
- {"sub", .val = LDAP_SCOPE_SUBTREE },
- #if defined HAVE_SCOPE_CHILDREN
- {"children", .val = LDAP_SCOPE_CHILDREN},
- #endif
- {0}
- };
- static cfg_option_t deref_values[] = {
- {"never", .val = LDAP_DEREF_NEVER }, /* default, 0x00 */
- {"searching", .val = LDAP_DEREF_SEARCHING},
- {"finding", .val = LDAP_DEREF_FINDING },
- {"always", .val = LDAP_DEREF_ALWAYS },
- {0}
- };
- static cfg_option_t ldap_tab_options[] = {
- {"scope", .param = scope_values, .f = cfg_parse_enum_opt},
- {"field_map", .f = parse_field_map},
- {"filter", .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
- {"base", .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
- {"timelimit", .f = cfg_parse_int_opt},
- {"sizelimit", .f = cfg_parse_int_opt},
- {"chase_references", .param = deref_values, .f = cfg_parse_enum_opt},
- {"chase_referrals", .f = cfg_parse_bool_opt},
- {0}
- };
- static cfg_option_t auth_values[] = {
- {"none", .val = LDAP_AUTHMECH_NONE},
- {"simple", .val = LDAP_AUTHMECH_SIMPLE},
- {"digest-md5", .val = LDAP_AUTHMECH_DIGESTMD5},
- {"external", .val = LDAP_AUTHMECH_EXTERNAL},
- {0}
- };
- static cfg_option_t ldap_con_options[] = {
- {"host", .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
- {"port", .f = cfg_parse_int_opt},
- {"username", .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
- {"password", .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
- {"authtype", .param = auth_values, .f = cfg_parse_enum_opt},
- {"tls", .f = cfg_parse_bool_opt},
- {"ca_list", .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
- {"require_certificate", .f = cfg_parse_str_opt, .flags = CFG_STR_PKGMEM},
- {0}
- };
- static cfg_option_t section_types[] = {
- {"connection", .val = LDAP_CON_SECTION},
- {"con", .val = LDAP_CON_SECTION},
- {"table", .val = LDAP_TABLE_SECTION},
- {0}
- };
- static int parse_section(void* param, cfg_parser_t* st, unsigned int flags)
- {
- cfg_token_t t;
- int ret, type, i;
- cfg_option_t* opt;
- str* id = NULL;
- struct ld_cfg* tab;
- struct ld_con_info* cinfo;
- ret = cfg_get_token(&t, st, 0);
- if (ret < 0) return -1;
- if (ret > 0) {
- ERR("%s:%d:%d: Section type missing\n",
- st->file, st->line, st->col);
- return -1;
- }
- if (t.type != CFG_TOKEN_ALPHA ||
- ((opt = cfg_lookup_token(section_types, &t.val)) == NULL)) {
- ERR("%s:%d:%d: Invalid section type %d:'%.*s'\n",
- st->file, t.start.line, t.start.col, t.type, STR_FMT(&t.val));
- return -1;
- }
- type = opt->val;
- if (type == LDAP_TABLE_SECTION) {
- if ((tab = pkg_malloc(sizeof(*tab))) == NULL) {
- ERR("ldap:%s:%d: Out of memory\n", st->file, st->line);
- return -1;
- }
- memset(tab, '\0', sizeof(*tab));
- tab->next = cfg;
- cfg = tab;
- cfg_set_options(st, ldap_tab_options);
- ldap_tab_options[2].param = &cfg->filter;
- ldap_tab_options[3].param = &cfg->base;
- for(i = 0; scope_values[i].name; i++) {
- scope_values[i].param = &cfg->scope;
- }
- ldap_tab_options[4].param = &cfg->timelimit;
- ldap_tab_options[5].param = &cfg->sizelimit;
- for(i = 0; deref_values[i].name; i++) {
- deref_values[i].param = &cfg->chase_references;
- }
- ldap_tab_options[7].param = &cfg->chase_referrals;
- } else if (type == LDAP_CON_SECTION) {
- if ((cinfo = pkg_malloc(sizeof(*cinfo))) == NULL) {
- ERR("ldap:%s:%d: Out of memory\n", st->file, st->line);
- return -1;
- }
- memset(cinfo, '\0', sizeof(*cinfo));
- cinfo->next = con;
- con = cinfo;
- cfg_set_options(st, ldap_con_options);
- ldap_con_options[0].param = &con->host;
- ldap_con_options[1].param = &con->port;
- ldap_con_options[2].param = &con->username;
- ldap_con_options[3].param = &con->password;
- for(i = 0; auth_values[i].name; i++) {
- auth_values[i].param = &con->authmech;
- }
- ldap_con_options[5].param = &con->tls;
- ldap_con_options[6].param = &con->ca_list;
- ldap_con_options[7].param = &con->req_cert;
- } else {
- BUG("%s:%d:%d: Unsupported section type %c\n",
- st->file, t.start.line, t.start.col, t.type);
- return -1;
- }
- ret = cfg_get_token(&t, st, 0);
- if (ret < 0) return -1;
- if (ret > 0) {
- ERR("%s:%d:%d: Delimiter ':' expected.\n",
- st->file, st->line, st->col);
- return -1;
- }
- if (type == LDAP_TABLE_SECTION) {
- id = &cfg->table;
- } else if (type == LDAP_CON_SECTION) {
- id = &con->id;
- } else {
- BUG("%s:%d:%d: Invalid section type %d\n", st->file,
- st->line, st->col, type);
- }
- ret = cfg_parse_str(id, st, CFG_STR_PKGMEM);
- if (ret < 0) return -1;
- if (ret > 0) {
- ERR("%s:%d:%d: Section identifier expected\n",
- st->file, st->line, st->col);
- return -1;
- }
- ret = cfg_get_token(&t, st, 0);
- if (ret < 0) return ret;
- if (ret > 0) {
- ERR("%s:%d:%d: Missing closing ']'.\n",
- st->file, st->line, st->col);
- return -1;
- }
- if (t. type != ']') {
- ERR("%s:%d:%d: Syntax error, ']' expected.\n",
- st->file, t.start.line, t.start.col);
- return -1;
- }
- if (cfg_eat_eol(st, flags)) return -1;
- return 0;
- }
- struct ld_cfg* ld_find_cfg(str* table)
- {
- struct ld_cfg* ptr;
- ptr = cfg;
- while(ptr) {
- if (ptr->table.len == table->len &&
- !strncmp(ptr->table.s, table->s, table->len))
- return ptr;
- ptr = ptr->next;
- }
- return NULL;
- }
- char* ld_find_attr_name(enum ld_syntax* syntax, struct ld_cfg* cfg, char* fld_name)
- {
- int i;
- for(i = 0; i < cfg->n; i++) {
- if (!strcmp(fld_name, cfg->field[i].s)) {
- *syntax = cfg->syntax[i];
- return cfg->attr[i].s;
- }
- }
- return NULL;
- }
- struct ld_con_info* ld_find_conn_info(str* conn_id)
- {
- struct ld_con_info* ptr;
- ptr = con;
- while(ptr) {
- if (ptr->id.len == conn_id->len &&
- !memcmp(ptr->id.s, conn_id->s, conn_id->len)) {
- return ptr;
- }
- ptr = ptr->next;
- }
- return NULL;
- }
- static int ld_cfg_validity_check(struct ld_cfg *cfg)
- {
- struct ld_cfg *pcfg;
- for (pcfg = cfg; pcfg; pcfg = pcfg->next) {
- if (pcfg->sizelimit < 0 || pcfg->sizelimit > LD_MAXINT) {
- ERR("ldap: invalid sizelimit (%d) specified\n", pcfg->sizelimit);
- return -1;
- }
- if (pcfg->timelimit < 0 || pcfg->timelimit > LD_MAXINT) {
- ERR("ldap: invalid timelimit (%d) specified\n", pcfg->timelimit);
- return -1;
- }
- }
- return 0;
- }
- int ld_load_cfg(str* filename)
- {
- cfg_parser_t* parser;
- cfg = NULL;
- if ((parser = cfg_parser_init(0, filename)) == NULL) {
- ERR("ldap: Error while initializing configuration file parser.\n");
- return -1;
- }
- cfg_section_parser(parser, parse_section, NULL);
- if (sr_cfg_parse(parser)) {
- if (cfg == NULL) {
- ERR("ldap: A table name (i.e. [table_name]) is missing in the "
- "configuration file.\n");
- }
- cfg_parser_close(parser);
- ld_cfg_free();
- return -1;
- }
- cfg_parser_close(parser);
- if (ld_cfg_validity_check(cfg)) {
- ld_cfg_free();
- return -1;
- }
- return 0;
- }
|