diff options
-rw-r--r-- | radsecproxy.c | 302 | ||||
-rw-r--r-- | radsecproxy.h | 12 |
2 files changed, 212 insertions, 102 deletions
diff --git a/radsecproxy.c b/radsecproxy.c index 948541e..bbd2635 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -1551,67 +1551,52 @@ int dorewriteadd(uint8_t **buf, struct list *addattrs) { return 1; } -int dorewrite(uint8_t **buf, struct rewrite *rewrite) { - if (!rewrite) - return 1; - if (rewrite->removeattrs || rewrite->removevendorattrs) - dorewriterm(*buf, rewrite->removeattrs, rewrite->removevendorattrs); - if (rewrite->addattrs) - return dorewriteadd(buf, rewrite->addattrs); - return 1; -} - /* returns a pointer to the resized attribute value */ -uint8_t *resizeattr(uint8_t **buf, uint8_t newvallen, uint8_t type) { - uint8_t *attrs, *attr, vallen; +uint8_t *resizeattr2(uint8_t **buf, uint8_t **attr, uint8_t newvallen) { + uint8_t vallen; uint16_t len; unsigned char *new; - len = RADLEN(*buf) - 20; - attrs = *buf + 20; - - attr = attrget(attrs, len, type); - if (!attr) - return NULL; - - vallen = ATTRVALLEN(attr); + vallen = ATTRVALLEN(*attr); if (vallen == newvallen) - return attr + 2; + return *attr + 2; + + len = RADLEN(*buf) + newvallen - vallen; - len += newvallen - vallen; if (newvallen > vallen) { - new = realloc(*buf, len + 20); + new = realloc(*buf, len); if (!new) { - debug(DBG_ERR, "resizeattr: malloc failed"); + debug(DBG_ERR, "resizeattr2: malloc failed"); return NULL; } if (new != *buf) { - attr += new - *buf; - attrs = new + 20; + *attr += new - *buf; *buf = new; } } - memmove(attr + 2 + newvallen, attr + 2 + vallen, len - (attr - attrs + newvallen)); - attr[1] = newvallen + 2; - ((uint16_t *)*buf)[1] = htons(len + 20); - return attr + 2; + memmove(*attr + 2 + newvallen, *attr + 2 + vallen, len - (*attr - *buf + newvallen)); + (*attr)[1] = newvallen + 2; + ((uint16_t *)*buf)[1] = htons(len); + return *attr + 2; } - -int rewriteusername(struct request *rq, char *in) { + +int dorewritemodattr(uint8_t **buf, uint8_t **attr, struct modattr *modattr) { size_t nmatch = 10, reslen = 0, start = 0; regmatch_t pmatch[10], *pfield; int i; unsigned char *result; - char *out = rq->from->conf->rewriteusernamereplacement; + char *in, *out; + + in = stringcopy((char *)ATTRVAL(*attr), ATTRVALLEN(*attr)); + if (!in) + return 0; - if (regexec(rq->from->conf->rewriteusernameregex, in, nmatch, pmatch, 0)) { - debug(DBG_DBG, "rewriteattr: username not matching, no rewrite"); + if (regexec(modattr->regex, in, nmatch, pmatch, 0)) { + free(in); return 1; } - rq->origusername = stringcopy(in, 0); - if (!rq->origusername) - return 0; + out = modattr->replacement; for (i = start; out[i]; i++) { if (out[i] == '\\' && out[i + 1] >= '1' && out[i + 1] <= '9') { @@ -1625,9 +1610,11 @@ int rewriteusername(struct request *rq, char *in) { } reslen += i - start; - result = resizeattr(&rq->buf, reslen, RAD_Attr_User_Name); - if (!result) + result = resizeattr2(buf, attr, reslen); + if (!result) { + free(in); return 0; + } start = 0; reslen = 0; @@ -1646,9 +1633,86 @@ int rewriteusername(struct request *rq, char *in) { } memcpy(result + reslen, out + start, i - start); - reslen += i - start; - memcpy(in, result, reslen); - in[reslen] = '\0'; + return 1; +} + +int dorewritemod(uint8_t **buf, struct list *modattrs) { + uint8_t *attr; + uint16_t len = 0; + struct list_node *n; + + attr = *buf + 20; + while (RADLEN(*buf) - 22 >= len) { + for (n = list_first(modattrs); n; n = list_next(n)) + if (ATTRTYPE(attr) == ((struct modattr *)n->data)->t) + if (!dorewritemodattr(buf, &attr, (struct modattr *)n->data)) + return 0; + len += ATTRLEN(attr); + attr += ATTRLEN(attr); + } + return 1; +} + +int dorewrite(uint8_t **buf, struct rewrite *rewrite) { + if (!rewrite) + return 1; + if (rewrite->removeattrs || rewrite->removevendorattrs) + dorewriterm(*buf, rewrite->removeattrs, rewrite->removevendorattrs); + if (rewrite->addattrs && !dorewriteadd(buf, rewrite->addattrs)) + return 0; + if (rewrite->modattrs && !dorewritemod(buf, rewrite->modattrs)) + return 0; + return 1; +} + +/* returns a pointer to the resized attribute value */ +uint8_t *resizeattr(uint8_t **buf, uint8_t newvallen, uint8_t type) { + uint8_t *attrs, *attr, vallen; + uint16_t len; + unsigned char *new; + + len = RADLEN(*buf) - 20; + attrs = *buf + 20; + + attr = attrget(attrs, len, type); + if (!attr) + return NULL; + + vallen = ATTRVALLEN(attr); + if (vallen == newvallen) + return attr + 2; + + len += newvallen - vallen; + if (newvallen > vallen) { + new = realloc(*buf, len + 20); + if (!new) { + debug(DBG_ERR, "resizeattr: malloc failed"); + return NULL; + } + if (new != *buf) { + attr += new - *buf; + attrs = new + 20; + *buf = new; + } + } + memmove(attr + 2 + newvallen, attr + 2 + vallen, len - (attr - attrs + newvallen)); + attr[1] = newvallen + 2; + ((uint16_t *)*buf)[1] = htons(len + 20); + return attr + 2; +} + +int rewriteusername(struct request *rq, uint8_t *attr, char *in) { + if (!dorewritemodattr(&rq->buf, &attr, rq->from->conf->rewriteusername)) + return 0; + if (strlen(in) == ATTRVALLEN(attr) && !memcmp(in, ATTRVAL(attr), ATTRVALLEN(attr))) + return 1; + + rq->origusername = stringcopy(in, 0); + if (!rq->origusername) + return 0; + + memcpy(in, ATTRVAL(attr), ATTRVALLEN(attr)); + in[ATTRVALLEN(attr)] = '\0'; return 1; } @@ -1880,8 +1944,8 @@ int radsrv(struct request *rq) { username[ATTRVALLEN(attr)] = '\0'; radattr2ascii(userascii, sizeof(userascii), attr); - if (rq->from->conf->rewriteusernameregex) { - if (!rewriteusername(rq, username)) { + if (rq->from->conf->rewriteusername) { + if (!rewriteusername(rq, attr, username)) { debug(DBG_WARN, "radsrv: username malloc failed, ignoring request"); goto exit; } @@ -2860,47 +2924,6 @@ int addmatchcertattr(struct clsrvconf *conf) { return 1; } -int addrewriteattr(struct clsrvconf *conf) { - char *v, *w; - - v = conf->rewriteusername + 11; - if (strncasecmp(conf->rewriteusername, "User-Name:/", 11) || !*v) - return 0; - /* regexp, remove optional trailing / if present */ - if (v[strlen(v) - 1] == '/') - v[strlen(v) - 1] = '\0'; - - w = strchr(v, '/'); - if (!*w) - return 0; - *w = '\0'; - w++; - - conf->rewriteusernameregex = malloc(sizeof(regex_t)); - if (!conf->rewriteusernameregex) { - debug(DBG_ERR, "malloc failed"); - return 0; - } - - conf->rewriteusernamereplacement = stringcopy(w, 0); - if (!conf->rewriteusernamereplacement) { - free(conf->rewriteusernameregex); - conf->rewriteusernameregex = NULL; - return 0; - } - - if (regcomp(conf->rewriteusernameregex, v, REG_ICASE | REG_EXTENDED)) { - free(conf->rewriteusernameregex); - conf->rewriteusernameregex = NULL; - free(conf->rewriteusernamereplacement); - conf->rewriteusernamereplacement = NULL; - debug(DBG_ERR, "failed to compile regular expression %s", v); - return 0; - } - - return 1; -} - /* should accept both names and numeric values, only numeric right now */ uint8_t attrname2val(char *attrname) { int val = 0; @@ -2949,6 +2972,66 @@ struct attribute *extractattr(char *nameval) { return a; } +/* should accept both names and numeric values, only numeric right now */ +/* this should be used instead of addrewriteattr */ +struct modattr *extractmodattr(char *nameval) { + int name = 0; + char *s, *t; + struct modattr *m; + + if (!strncasecmp(nameval, "User-Name:/", 11)) { + s = nameval + 11; + name = 1; + } else { + s = strchr(nameval, ':'); + name = atoi(nameval); + if (!s || name < 1 || name > 255 || s[1] != '/') + return NULL; + s += 2; + } + /* regexp, remove optional trailing / if present */ + if (s[strlen(s) - 1] == '/') + s[strlen(s) - 1] = '\0'; + + t = strchr(s, '/'); + if (!t) + return NULL; + *t = '\0'; + t++; + + m = malloc(sizeof(struct modattr)); + if (!m) { + debug(DBG_ERR, "malloc failed"); + return NULL; + } + m->t = name; + + m->replacement = stringcopy(t, 0); + if (!m->replacement) { + free(m); + debug(DBG_ERR, "malloc failed"); + return NULL; + } + + m->regex = malloc(sizeof(regex_t)); + if (!m->regex) { + free(m->replacement); + free(m); + debug(DBG_ERR, "malloc failed"); + return NULL; + } + + if (regcomp(m->regex, s, REG_ICASE | REG_EXTENDED)) { + free(m->regex); + free(m->replacement); + free(m); + debug(DBG_ERR, "failed to compile regular expression %s", s); + return NULL; + } + + return m; +} + struct rewrite *getrewrite(char *alt1, char *alt2) { struct rewrite *r; @@ -2959,13 +3042,14 @@ struct rewrite *getrewrite(char *alt1, char *alt2) { return NULL; } -void addrewrite(char *value, char **rmattrs, char **rmvattrs, char **addattrs) { +void addrewrite(char *value, char **rmattrs, char **rmvattrs, char **addattrs, char **modattrs) { struct rewrite *rewrite = NULL; int i, n; uint8_t *rma = NULL; uint32_t *p, *rmva = NULL; - struct list *adda = NULL; + struct list *adda = NULL, *moda = NULL; struct attribute *a; + struct modattr *m; if (rmattrs) { for (n = 0; rmattrs[n]; n++); @@ -3011,14 +3095,30 @@ void addrewrite(char *value, char **rmattrs, char **rmvattrs, char **addattrs) { } free(addattrs); } - - if (rma || rmva || adda) { + + if (modattrs) { + moda = list_create(); + if (!moda) + debugx(1, DBG_ERR, "malloc failed"); + for (i = 0; modattrs[i]; i++) { + m = extractmodattr(modattrs[i]); + if (!m) + debugx(1, DBG_ERR, "addrewrite: invalid attribute %s", modattrs[i]); + free(modattrs[i]); + if (!list_push(moda, m)) + debugx(1, DBG_ERR, "malloc failed"); + } + free(modattrs); + } + + if (rma || rmva || adda || moda) { rewrite = malloc(sizeof(struct rewrite)); if (!rewrite) debugx(1, DBG_ERR, "malloc failed"); rewrite->removeattrs = rma; rewrite->removevendorattrs = rmva; rewrite->addattrs = adda; + rewrite->modattrs = moda; } if (!hash_insert(rewriteconfs, value, strlen(value), rewrite)) @@ -3039,10 +3139,12 @@ void freeclsrvconf(struct clsrvconf *conf) { regfree(conf->certuriregex); free(conf->confrewritein); free(conf->confrewriteout); - free(conf->rewriteusername); - if (conf->rewriteusernameregex) - regfree(conf->rewriteusernameregex); - free(conf->rewriteusernamereplacement); + if (conf->rewriteusername) { + if (conf->rewriteusername->regex) + regfree(conf->rewriteusername->regex); + free(conf->rewriteusername->replacement); + free(conf->rewriteusername); + } free(conf->dynamiclookupcommand); free(conf->rewritein); free(conf->rewriteout); @@ -3116,7 +3218,7 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char "rewrite", CONF_STR, &rewriteinalias, "rewriteIn", CONF_STR, &conf->confrewritein, "rewriteOut", CONF_STR, &conf->confrewriteout, - "rewriteattribute", CONF_STR, &conf->rewriteusername, + "rewriteattribute", CONF_STR, &conf->confrewriteusername, NULL )) debugx(1, DBG_ERR, "configuration error"); @@ -3151,8 +3253,9 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char if (conf->confrewriteout) conf->rewriteout = getrewrite(conf->confrewriteout, NULL); - if (conf->rewriteusername) { - if (!addrewriteattr(conf)) + if (conf->confrewriteusername) { + conf->rewriteusername = extractmodattr(conf->confrewriteusername); + if (!conf->rewriteusername) debugx(1, DBG_ERR, "error in block %s, invalid RewriteAttributeValue", block); } @@ -3416,7 +3519,7 @@ int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *v } int confrewrite_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) { - char **rmattrs = NULL, **rmvattrs = NULL, **addattrs = NULL; + char **rmattrs = NULL, **rmvattrs = NULL, **addattrs = NULL, **modattrs = NULL; debug(DBG_DBG, "confrewrite_cb called for %s", block); @@ -3424,10 +3527,11 @@ int confrewrite_cb(struct gconffile **cf, void *arg, char *block, char *opt, cha "removeAttribute", CONF_MSTR, &rmattrs, "removeVendorAttribute", CONF_MSTR, &rmvattrs, "addAttribute", CONF_MSTR, &addattrs, + "modifyAttribute", CONF_MSTR, &modattrs, NULL )) debugx(1, DBG_ERR, "configuration error"); - addrewrite(val, rmattrs, rmvattrs, addattrs); + addrewrite(val, rmattrs, rmvattrs, addattrs, modattrs); return 1; } diff --git a/radsecproxy.h b/radsecproxy.h index 11eebf8..f14e232 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -97,9 +97,8 @@ struct clsrvconf { regex_t *certuriregex; char *confrewritein; char *confrewriteout; - char *rewriteusername; - regex_t *rewriteusernameregex; - char *rewriteusernamereplacement; + char *confrewriteusername; + struct modattr *rewriteusername; char *dynamiclookupcommand; uint8_t statusserver; uint8_t retryinterval; @@ -173,10 +172,17 @@ struct attribute { uint8_t *v; }; +struct modattr { + uint8_t t; + char *replacement; + regex_t *regex; +}; + struct rewrite { uint8_t *removeattrs; uint32_t *removevendorattrs; struct list *addattrs; + struct list *modattrs; }; struct protodefs { |