From 34b3d8a4025bc1c8ace4b1035597970ddf9d8a8d Mon Sep 17 00:00:00 2001 From: venaas Date: Thu, 29 May 2008 11:02:26 +0000 Subject: rewritten gconfig to not exit on errors git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@263 e88ac4ed-0b26-0410-9574-a7f39faa03bf --- gconfig.c | 218 ++++++++++++++++++++++++++++++++++++++-------------------- gconfig.h | 4 +- radsecproxy.c | 68 +++++++++--------- 3 files changed, 183 insertions(+), 107 deletions(-) diff --git a/gconfig.c b/gconfig.c index 7a367e7..6f9da4e 100644 --- a/gconfig.c +++ b/gconfig.c @@ -18,14 +18,6 @@ #include "util.h" #include "gconfig.h" -char *mystringcopyx(const char *s) { - char *t; - t = stringcopy(s, 0); - if (!t) - debugx(1, DBG_ERR, "malloc failed"); - return t; -} - /* returns NULL on error, where to continue parsing if token and ok. E.g. "" will return token with empty string */ char *strtokenquote(char *s, char **token, char *del, char *quote, char *comment) { char *t = s, *q, *r; @@ -60,6 +52,7 @@ char *strtokenquote(char *s, char **token, char *del, char *quote, char *comment FILE *pushgconffile(struct gconffile **cf, const char *path) { int i; struct gconffile *newcf; + char *pathcopy; FILE *f; f = fopen(path, "r"); @@ -68,28 +61,39 @@ FILE *pushgconffile(struct gconffile **cf, const char *path) { return NULL; } debug(DBG_DBG, "opened config file %s", path); + + pathcopy = stringcopy(path, 0); + if (!pathcopy) + goto errmalloc; + if (!*cf) { newcf = malloc(sizeof(struct gconffile) * 2); if (!newcf) - debugx(1, DBG_ERR, "malloc failed"); + goto errmalloc; newcf[1].file = NULL; newcf[1].path = NULL; } else { for (i = 0; (*cf)[i].path; i++); newcf = realloc(*cf, sizeof(struct gconffile) * (i + 2)); if (!newcf) - debugx(1, DBG_ERR, "malloc failed"); + goto errmalloc; memmove(newcf + 1, newcf, sizeof(struct gconffile) * (i + 1)); } newcf[0].file = f; - newcf[0].path = mystringcopyx(path); + newcf[0].path = pathcopy; *cf = newcf; return f; + + errmalloc: + free(pathcopy); + fclose(f); + debug(DBG_ERR, "malloc failed"); + return NULL; } FILE *pushgconffiles(struct gconffile **cf, const char *cfgpath) { int i; - FILE *f; + FILE *f = NULL; glob_t globbuf; char *path, *curfile = NULL, *dir; @@ -98,11 +102,17 @@ FILE *pushgconffiles(struct gconffile **cf, const char *cfgpath) { path = (char *)cfgpath; else { /* dirname may modify its argument */ - curfile = mystringcopyx((*cf)->path); + curfile = stringcopy((*cf)->path, 0); + if (!curfile) { + debug(DBG_ERR, "malloc failed"); + goto exit; + } dir = dirname(curfile); path = malloc(strlen(dir) + strlen(cfgpath) + 2); - if (!path) - debugx(1, DBG_ERR, "malloc failed"); + if (!path) { + debug(DBG_ERR, "malloc failed"); + goto exit; + } strcpy(path, dir); path[strlen(dir)] = '/'; strcpy(path + strlen(dir) + 1, cfgpath); @@ -110,15 +120,17 @@ FILE *pushgconffiles(struct gconffile **cf, const char *cfgpath) { memset(&globbuf, 0, sizeof(glob_t)); if (glob(path, 0, NULL, &globbuf)) { debug(DBG_INFO, "could not glob %s", path); - f = NULL; - } else { - for (i = globbuf.gl_pathc - 1; i >= 0; i--) { - f = pushgconffile(cf, globbuf.gl_pathv[i]); - if (!f) - break; - } - globfree(&globbuf); + goto exit; } + + for (i = globbuf.gl_pathc - 1; i >= 0; i--) { + f = pushgconffile(cf, globbuf.gl_pathv[i]); + if (!f) + break; + } + globfree(&globbuf); + + exit: if (curfile) { free(curfile); free(path); @@ -149,8 +161,10 @@ FILE *popgconffile(struct gconffile **cf) { struct gconffile *openconfigfile(const char *file) { struct gconffile *cf = NULL; - if (!pushgconffile(&cf, file)) - debugx(1, DBG_ERR, "could not read config file %s\n%s", file, strerror(errno)); + if (!pushgconffile(&cf, file)) { + debug(DBG_ERR, "could not read config file %s\n%s", file, strerror(errno)); + return NULL; + } debug(DBG_DBG, "reading config file %s", file); return cf; } @@ -166,7 +180,7 @@ struct gconffile *openconfigfile(const char *file) { * } */ -void getconfigline(struct gconffile **cf, char *block, char **opt, char **val, int *conftype) { +int getconfigline(struct gconffile **cf, char *block, char **opt, char **val, int *conftype) { char line[1024]; char *tokens[3], *s; int tcount; @@ -176,19 +190,21 @@ void getconfigline(struct gconffile **cf, char *block, char **opt, char **val, i *conftype = 0; if (!cf || !*cf || !(*cf)->file) - return; + return 1; for (;;) { if (!fgets(line, 1024, (*cf)->file)) { if (popgconffile(cf)) continue; - return; + return 1; } s = line; for (tcount = 0; tcount < 3; tcount++) { s = strtokenquote(s, &tokens[tcount], " \t\r\n", "\"'", tcount ? NULL : "#"); - if (!s) - debugx(1, DBG_ERR, "Syntax error in line starting with: %s", line); + if (!s) { + debug(DBG_ERR, "Syntax error in line starting with: %s", line); + return 0; + } if (!tokens[tcount]) break; } @@ -197,59 +213,91 @@ void getconfigline(struct gconffile **cf, char *block, char **opt, char **val, i if (**tokens == '}') { if (block) - return; - debugx(1, DBG_ERR, "configuration error, found } with no matching {"); + return 1; + debug(DBG_ERR, "configuration error, found } with no matching {"); + return 0; } break; } switch (tcount) { case 2: - *opt = mystringcopyx(tokens[0]); - *val = mystringcopyx(tokens[1]); + *opt = stringcopy(tokens[0], 0); + if (!*opt) + goto errmalloc; + *val = stringcopy(tokens[1], 0); + if (!*val) + goto errmalloc; *conftype = CONF_STR; break; case 3: if (tokens[1][0] == '=' && tokens[1][1] == '\0') { - *opt = mystringcopyx(tokens[0]); - *val = mystringcopyx(tokens[2]); + *opt = stringcopy(tokens[0], 0); + if (!*opt) + goto errmalloc; + *val = stringcopy(tokens[2], 0); + if (!*val) + goto errmalloc; *conftype = CONF_STR; break; } if (tokens[2][0] == '{' && tokens[2][1] == '\0') { - *opt = mystringcopyx(tokens[0]); - *val = mystringcopyx(tokens[1]); + *opt = stringcopy(tokens[0], 0); + if (!*opt) + goto errmalloc; + *val = stringcopy(tokens[1], 0); + if (!*val) + goto errmalloc; *conftype = CONF_CBK; break; } /* fall through */ default: if (block) - debugx(1, DBG_ERR, "configuration error in block %s, line starting with %s", block, tokens[0]); - debugx(1, DBG_ERR, "configuration error, syntax error in line starting with %s", tokens[0]); + debug(DBG_ERR, "configuration error in block %s, line starting with %s", block, tokens[0]); + else + debug(DBG_ERR, "configuration error, syntax error in line starting with %s", tokens[0]); + return 0; } - if (!**val) - debugx(1, DBG_ERR, "configuration error, option %s needs a non-empty value", *opt); - return; + if (**val) + return 1; + + debug(DBG_ERR, "configuration error, option %s needs a non-empty value", *opt); + goto errexit; + + errmalloc: + debug(DBG_ERR, "malloc failed"); + errexit: + free(*opt); + *opt = NULL; + free(*val); + *val = NULL; + return 0; } -void getgenericconfig(struct gconffile **cf, char *block, ...) { +/* returns 1 if ok, 0 on error */ +/* caller must free returned values also on error */ +int getgenericconfig(struct gconffile **cf, char *block, ...) { va_list ap; - char *opt = NULL, *val, *word, *optval, **str = NULL, ***mstr = NULL; + char *opt = NULL, *val, *word, *optval, **str = NULL, ***mstr = NULL, **newmstr; uint8_t *bln; int type = 0, conftype = 0, n; - void (*cbk)(struct gconffile **, char *, char *, char *) = NULL; + void (*cbk)(struct gconffile **, void *, char *, char *, char *) = NULL; + void *cbkarg = NULL; for (;;) { free(opt); - getconfigline(cf, block, &opt, &val, &conftype); + if (!getconfigline(cf, block, &opt, &val, &conftype)) + return 0; if (!opt) - return; + return 1; if (conftype == CONF_STR && !strcasecmp(opt, "include")) { - if (!pushgconffiles(cf, val)) - debugx(1, DBG_ERR, "failed to include config file %s", val); + if (!pushgconffiles(cf, val)) { + debug(DBG_ERR, "failed to include config file %s", val); + goto errexit; + } free(val); continue; } @@ -261,23 +309,26 @@ void getgenericconfig(struct gconffile **cf, char *block, ...) { case CONF_STR: str = va_arg(ap, char **); if (!str) - debugx(1, DBG_ERR, "getgenericconfig: internal parameter error"); + goto errparam; break; case CONF_MSTR: mstr = va_arg(ap, char ***); if (!mstr) - debugx(1, DBG_ERR, "getgenericconfig: internal parameter error"); + goto errparam; break; case CONF_BLN: bln = va_arg(ap, uint8_t *); if (!bln) - debugx(1, DBG_ERR, "getgenericconfig: internal parameter error"); + goto errparam; break; case CONF_CBK: - cbk = va_arg(ap, void (*)(struct gconffile **, char *, char *, char *)); + cbk = va_arg(ap, void (*)(struct gconffile **, void *, char *, char *, char *)); + if (!cbk) + goto errparam; + cbkarg = va_arg(ap, void *); break; default: - debugx(1, DBG_ERR, "getgenericconfig: internal parameter error"); + goto errparam; } if (!strcasecmp(opt, word)) break; @@ -286,21 +337,25 @@ void getgenericconfig(struct gconffile **cf, char *block, ...) { if (!word) { if (block) - debugx(1, DBG_ERR, "configuration error in block %s, unknown option %s", block, opt); - debugx(1, DBG_ERR, "configuration error, unknown option %s", opt); + debug(DBG_ERR, "configuration error in block %s, unknown option %s", block, opt); + debug(DBG_ERR, "configuration error, unknown option %s", opt); + goto errexit; } if (((type == CONF_STR || type == CONF_MSTR || type == CONF_BLN) && conftype != CONF_STR) || (type == CONF_CBK && conftype != CONF_CBK)) { if (block) - debugx(1, DBG_ERR, "configuration error in block %s, wrong syntax for option %s", block, opt); - debugx(1, DBG_ERR, "configuration error, wrong syntax for option %s", opt); + debug(DBG_ERR, "configuration error in block %s, wrong syntax for option %s", block, opt); + debug(DBG_ERR, "configuration error, wrong syntax for option %s", opt); + goto errexit; } switch (type) { case CONF_STR: - if (*str) - debugx(1, DBG_ERR, "configuration error, option %s already set to %s", opt, *str); + if (*str) { + debug(DBG_ERR, "configuration error, option %s already set to %s", opt, *str); + goto errexit; + } *str = val; break; case CONF_MSTR: @@ -308,33 +363,41 @@ void getgenericconfig(struct gconffile **cf, char *block, ...) { for (n = 0; (*mstr)[n]; n++); else n = 0; - *mstr = realloc(*mstr, sizeof(char *) * (n + 2)); - if (!*mstr) - debugx(1, DBG_ERR, "malloc failed"); - (*mstr)[n] = val; - (*mstr)[n + 1] = NULL; + newmstr = realloc(*mstr, sizeof(char *) * (n + 2)); + if (!newmstr) { + debug(DBG_ERR, "malloc failed"); + goto errexit; + } + newmstr[n] = val; + newmstr[n + 1] = NULL; + *mstr = newmstr; break; case CONF_BLN: if (!strcasecmp(val, "on")) *bln = 1; else if (!strcasecmp(val, "off")) *bln = 0; - else if (block) - debugx(1, DBG_ERR, "configuration error in block %s, value for option %s must be on or off, not %s", block, opt, val); - else - debugx(1, DBG_ERR, "configuration error, value for option %s must be on or off, not %s", opt, val); + else { + if (block) + debug(DBG_ERR, "configuration error in block %s, value for option %s must be on or off, not %s", block, opt, val); + else + debug(DBG_ERR, "configuration error, value for option %s must be on or off, not %s", opt, val); + goto errexit; + } break; case CONF_CBK: optval = malloc(strlen(opt) + strlen(val) + 2); - if (!optval) - debugx(1, DBG_ERR, "malloc failed"); + if (!optval) { + debug(DBG_ERR, "malloc failed"); + goto errexit; + } sprintf(optval, "%s %s", opt, val); - cbk(cf, optval, opt, val); + cbk(cf, cbkarg, optval, opt, val); free(val); free(optval); continue; default: - debugx(1, DBG_ERR, "getgenericconfig: internal parameter error"); + goto errparam; } if (block) debug(DBG_DBG, "getgenericconfig: block %s: %s = %s", block, opt, val); @@ -343,4 +406,11 @@ void getgenericconfig(struct gconffile **cf, char *block, ...) { if (type == CONF_BLN) free(val); } + + errparam: + debug(DBG_ERR, "getgenericconfig: internal parameter error"); + errexit: + free(opt); + free(val); + return 0; } diff --git a/gconfig.h b/gconfig.h index af44dac..55e8efe 100644 --- a/gconfig.h +++ b/gconfig.h @@ -8,8 +8,8 @@ struct gconffile { FILE *file; }; -void getconfigline(struct gconffile **cf, char *block, char **opt, char **val, int *conftype); -void getgenericconfig(struct gconffile **cf, char *block, ...); +int getconfigline(struct gconffile **cf, char *block, char **opt, char **val, int *conftype); +int getgenericconfig(struct gconffile **cf, char *block, ...); FILE *pushgconffile(struct gconffile **cf, const char *path); FILE *pushgconffiles(struct gconffile **cf, const char *path); FILE *popgconffile(struct gconffile **cf); diff --git a/radsecproxy.c b/radsecproxy.c index 5f18086..4833897 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -3159,7 +3159,7 @@ void addrewrite(char *value, char **attrs, char **vattrs) { debug(DBG_DBG, "addrewrite: added rewrite block %s", value); } -void confclient_cb(struct gconffile **cf, char *block, char *opt, char *val) { +void confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { char *type = NULL, *tls = NULL, *matchcertattr = NULL, *rewrite = NULL, *rewriteattr = NULL; struct clsrvconf *conf; @@ -3171,7 +3171,7 @@ void confclient_cb(struct gconffile **cf, char *block, char *opt, char *val) { memset(conf, 0, sizeof(struct clsrvconf)); conf->certnamecheck = 1; - getgenericconfig(cf, block, + if (!getgenericconfig(cf, block, "type", CONF_STR, &type, "host", CONF_STR, &conf->host, "secret", CONF_STR, &conf->secret, @@ -3181,8 +3181,9 @@ void confclient_cb(struct gconffile **cf, char *block, char *opt, char *val) { "rewrite", CONF_STR, &rewrite, "rewriteattribute", CONF_STR, &rewriteattr, NULL - ); - + )) + debugx(1, DBG_ERR, "configuration error"); + conf->name = stringcopy(val, 0); if (!conf->host) conf->host = stringcopy(val, 0); @@ -3224,7 +3225,7 @@ void confclient_cb(struct gconffile **cf, char *block, char *opt, char *val) { } } -void confserver_cb(struct gconffile **cf, char *block, char *opt, char *val) { +void confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { char *type = NULL, *tls = NULL, *matchcertattr = NULL, *rewrite = NULL; struct clsrvconf *conf; @@ -3236,7 +3237,7 @@ void confserver_cb(struct gconffile **cf, char *block, char *opt, char *val) { memset(conf, 0, sizeof(struct clsrvconf)); conf->certnamecheck = 1; - getgenericconfig(cf, block, + if (!getgenericconfig(cf, block, "type", CONF_STR, &type, "host", CONF_STR, &conf->host, "port", CONF_STR, &conf->port, @@ -3248,7 +3249,8 @@ void confserver_cb(struct gconffile **cf, char *block, char *opt, char *val) { "CertificateNameCheck", CONF_BLN, &conf->certnamecheck, "DynamicLookupCommand", CONF_STR, &conf->dynamiclookupcommand, NULL - ); + )) + debugx(1, DBG_ERR, "configuration error"); conf->name = stringcopy(val, 0); if (!conf->host) @@ -3289,34 +3291,36 @@ void confserver_cb(struct gconffile **cf, char *block, char *opt, char *val) { } } -void confrealm_cb(struct gconffile **cf, char *block, char *opt, char *val) { +void confrealm_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { char **servers = NULL, **accservers = NULL, *msg = NULL; debug(DBG_DBG, "confrealm_cb called for %s", block); - getgenericconfig(cf, block, + if (!getgenericconfig(cf, block, "server", CONF_MSTR, &servers, "accountingServer", CONF_MSTR, &accservers, "ReplyMessage", CONF_STR, &msg, NULL - ); + )) + debugx(1, DBG_ERR, "configuration error"); addrealm(realms, val, servers, accservers, msg); } -void conftls_cb(struct gconffile **cf, char *block, char *opt, char *val) { +void conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { char *cacertfile = NULL, *cacertpath = NULL, *certfile = NULL, *certkeyfile = NULL, *certkeypwd = NULL; debug(DBG_DBG, "conftls_cb called for %s", block); - getgenericconfig(cf, block, + if (!getgenericconfig(cf, block, "CACertificateFile", CONF_STR, &cacertfile, "CACertificatePath", CONF_STR, &cacertpath, "CertificateFile", CONF_STR, &certfile, "CertificateKeyFile", CONF_STR, &certkeyfile, "CertificateKeyPassword", CONF_STR, &certkeypwd, NULL - ); + )) + debugx(1, DBG_ERR, "configuration error"); tlsadd(val, cacertfile, cacertpath, certfile, certkeyfile, certkeypwd); free(cacertfile); @@ -3326,16 +3330,17 @@ void conftls_cb(struct gconffile **cf, char *block, char *opt, char *val) { free(certkeypwd); } -void confrewrite_cb(struct gconffile **cf, char *block, char *opt, char *val) { +void confrewrite_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { char **attrs = NULL, **vattrs = NULL; debug(DBG_DBG, "confrewrite_cb called for %s", block); - getgenericconfig(cf, block, + if (!getgenericconfig(cf, block, "removeAttribute", CONF_MSTR, &attrs, "removeVendorAttribute", CONF_MSTR, &vattrs, NULL - ); + )) + debugx(1, DBG_ERR, "configuration error"); addrewrite(val, attrs, vattrs); } @@ -3366,21 +3371,22 @@ void getmainconfig(const char *configfile) { if (!rewriteconfs) debugx(1, DBG_ERR, "malloc failed"); - getgenericconfig(&cfs, NULL, - "ListenUDP", CONF_STR, &options.listenudp, - "ListenTCP", CONF_STR, &options.listentcp, - "ListenAccountingUDP", CONF_STR, &options.listenaccudp, - "SourceUDP", CONF_STR, &options.sourceudp, - "SourceTCP", CONF_STR, &options.sourcetcp, - "LogLevel", CONF_STR, &loglevel, - "LogDestination", CONF_STR, &options.logdestination, - "Client", CONF_CBK, confclient_cb, - "Server", CONF_CBK, confserver_cb, - "Realm", CONF_CBK, confrealm_cb, - "TLS", CONF_CBK, conftls_cb, - "Rewrite", CONF_CBK, confrewrite_cb, - NULL - ); + if (!getgenericconfig(&cfs, NULL, + "ListenUDP", CONF_STR, &options.listenudp, + "ListenTCP", CONF_STR, &options.listentcp, + "ListenAccountingUDP", CONF_STR, &options.listenaccudp, + "SourceUDP", CONF_STR, &options.sourceudp, + "SourceTCP", CONF_STR, &options.sourcetcp, + "LogLevel", CONF_STR, &loglevel, + "LogDestination", CONF_STR, &options.logdestination, + "Client", CONF_CBK, confclient_cb, NULL, + "Server", CONF_CBK, confserver_cb, NULL, + "Realm", CONF_CBK, confrealm_cb, NULL, + "TLS", CONF_CBK, conftls_cb, NULL, + "Rewrite", CONF_CBK, confrewrite_cb, NULL, + NULL + )) + debugx(1, DBG_ERR, "configuration error"); tlsfree(); rewritefree(); -- cgit v1.2.3