From: jcarneal Date: Wed, 8 Nov 2000 17:07:20 +0000 (+0000) Subject: Jeff Carneal X-Git-Tag: release_0_1_0~517 X-Git-Url: http://www.project-moonshot.org/gitweb/?a=commitdiff_plain;h=454718d5fb6e07f3bac56ea3e3fc9be4cc9c6b84;p=freeradius.git Jeff Carneal o Added function rad_cleandir() to sanitize directory input o Added function rad_mkdir() to create all needed directories --- diff --git a/src/modules/rlm_detail/rlm_detail.c b/src/modules/rlm_detail/rlm_detail.c index a78902c..95f09e5 100644 --- a/src/modules/rlm_detail/rlm_detail.c +++ b/src/modules/rlm_detail/rlm_detail.c @@ -22,13 +22,14 @@ static const char rcsid[] = "$Id$"; #include "radiusd.h" #include "modules.h" +#define DIRLEN 8192 struct detail_instance { /* detail file */ const char *detailfile; - /* detail file permissions */ - int detailperm; + /* detail file permissions */ + int detailperm; /* directory permissions */ int dirperm; @@ -45,50 +46,120 @@ static struct detail_instance config; static CONF_PARSER module_config[] = { { "detailfile", PW_TYPE_STRING_PTR, &config.detailfile, "%A/%n/detail" }, - { "detailperm", PW_TYPE_INTEGER, &config.detailperm, "0600" }, + { "detailperm", PW_TYPE_INTEGER, &config.detailperm, "0600" }, { "dirperm", PW_TYPE_INTEGER, &config.dirperm, "0755" }, { NULL, -1, NULL, NULL } }; /* - * (Re-)read radiusd.conf into memory. + * Sanitize the name for security! Only permit letters, numbers, + * -, _, / and \. Anything else will be rejected. */ -static int detail_instantiate(CONF_SECTION *conf, void **instance) -{ - struct detail_instance *inst; +static int rad_cleandir(const char *dirbuf, int length) { + size_t p=0; - inst = malloc(sizeof *inst); - if (!inst) { - radlog(L_ERR|L_CONS, "rlm_detail: Out of memory\n"); - return -1; - } + DEBUG2("HERE: %s", dirbuf); + if (strstr(dirbuf, "..")) { + radlog(L_ERR, "rlm_detail: Directory \"%s\" contains \"..\" which is not valid.", + dirbuf); + return -1; + } - if (cf_section_parse(conf, module_config) < 0) { - free(inst); - return -1; - } + p = strspn(dirbuf, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_/%."); + + if (p != length) { + radlog(L_ERR|L_CONS, "rlm_detail: Illegal character in detail filename."); + return -1; + } + + return 0; +} + +/* + * Make non-existant directories + * This function is admitedly ugly + */ +static char *rad_mkdir(const char *dirbuf, int perm) { + char *tmpbuf=0, *cur=0, *last=0; + int madeone = 0; + struct stat st; + + /* + * We need a copy we can play with + * so we make one here + */ + tmpbuf = strdup(dirbuf); /* - * Sanitize the name for security! Only permit letters, numbers, - * -, _, / and \. Anything else will be rejected. + * We have to skip the first char if + * it's a '/' */ + cur = tmpbuf; + if(*cur == '/') + cur++; - p = strspn(config.detailfile, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_/%."); + while((cur = strchr(cur, '/')) != NULL) { + *cur = '\0'; - if (p != strlen(config.detailfile)) { - radlog(L_ERR|L_CONS, "rlm_detail: Illegal character in detail filename."); + /* + * If the dir doesn't exist, make it + */ + if((stat(tmpbuf, &st) < 0)) { + DEBUG2("rad_mkdir: Making %s", tmpbuf); + if ((mkdir(tmpbuf, perm) < 0) && + (errno != EEXIST)) { + radlog(L_ERR, "rlm_mkdir: Couldn't create %s: %s", + tmpbuf, strerror(errno)); + return NULL; + } else { + madeone++; + DEBUG2("rad_mkdir: Made %s", tmpbuf); + } + } + + *cur = '/'; + last = cur; + cur++; + } + if(madeone) { + *last = '\0'; + return tmpbuf; + } else { + return NULL; + } +} + +/* + * (Re-)read radiusd.conf into memory. + */ +static int detail_instantiate(CONF_SECTION *conf, void **instance) +{ + struct detail_instance *inst; + + inst = malloc(sizeof *inst); + if (!inst) { + radlog(L_ERR|L_CONS, "rlm_detail: Out of memory\n"); return -1; } - - inst->detailfile = config.detailfile; - inst->detailperm = config.detailperm; + + if (cf_section_parse(conf, module_config) < 0) { + free(inst); + return -1; + } + + inst->detailfile = config.detailfile; + inst->detailperm = config.detailperm; inst->dirperm = config.dirperm; inst->last_made_directory = NULL; config.detailfile = NULL; - *instance = inst; - return 0; + if(rad_cleandir(inst->detailfile, strlen(inst->detailfile)) < 0) { + return -1; + } + + *instance = inst; + return 0; } /* @@ -98,9 +169,8 @@ static int detail_accounting(void *instance, REQUEST *request) { int outfd; FILE *outfp; - char buffer[8192]; - char *p; - size_t l; + char buffer[DIRLEN]; + char *p, *lastdir; VALUE_PAIR *pair; int ret = RLM_MODULE_OK; struct stat st; @@ -118,22 +188,7 @@ static int detail_accounting(void *instance, REQUEST *request) radius_xlat2(buffer, sizeof(buffer), inst->detailfile, request, request->reply->vps); - /* - * Sanitize the name for security! Only permit letters, numbers, - * -, _, / and \. Anything else will be rejected. - */ - - if (strstr(buffer, "..")) { - radlog(L_ERR, "rlm_detail: Directory \"%s\" contains \"..\" which is not valid.", - buffer); - return RLM_MODULE_FAIL; - } - - l = strspn(buffer, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_/."); - - if (l != strlen(buffer)) { - radlog(L_ERR, "rlm_detail: Directory \"%s\" contains an invalid character.", - buffer); + if(rad_cleandir(buffer, strlen(buffer)) < 0) { return RLM_MODULE_FAIL; } @@ -143,11 +198,11 @@ static int detail_accounting(void *instance, REQUEST *request) p = strrchr(buffer,'/'); /* - * There WAS a directory delimiter there, so let's - * go create the relevant directories. + * There WAS a directory delimiter there, and + * the dir doesn't exist, so + * we create it (them) */ - if (p) { - *p = '\0'; + if ((p) && (stat(buffer, &st) < 0)) { /* * NO previously cached directory name, so we've @@ -160,8 +215,7 @@ static int detail_accounting(void *instance, REQUEST *request) * so we've got to create a new one. */ if ((inst->last_made_directory == NULL) || - (strcmp(inst->last_made_directory, buffer) != 0) || - (stat(buffer, &st) == -1)) { + (strcmp(inst->last_made_directory, buffer) != 0)) { /* * Free any previously cached name. @@ -174,26 +228,15 @@ static int detail_accounting(void *instance, REQUEST *request) /* * Try to create the new directory. */ - if ((mkdir(buffer, inst->dirperm) == -1) && - (errno != EEXIST)) { - radlog(L_ERR, "rlm_detail: Couldn't create %s: %s", - buffer, strerror(errno)); - - return RLM_MODULE_FAIL; + if((lastdir = rad_mkdir(buffer, inst->dirperm)) != NULL) { + /* + * Save a copy of the directory name that + * we just created. + */ + inst->last_made_directory = strdup(lastdir); } - - /* - * Save a copy of the directory name that - * we just created. - */ - inst->last_made_directory = strdup(buffer); } - /* - * Re-create the file name, by replacing the - * directory delimiter that we removed above. - */ - *p = '/'; } /* else there was no directory delimiter. */ /*