diff options
Diffstat (limited to 'radsecproxy.c')
-rw-r--r-- | radsecproxy.c | 176 |
1 files changed, 132 insertions, 44 deletions
diff --git a/radsecproxy.c b/radsecproxy.c index 727698d..7de6897 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -1529,23 +1529,20 @@ int dovendorrewrite(uint8_t *attrs, uint16_t length, uint32_t *removevendorattrs return rmlen; } -void dorewrite(uint8_t *buf, struct rewrite *rewrite) { +void dorewriterm(uint8_t *buf, uint8_t *rmattrs, uint32_t *rmvattrs) { uint8_t *attrs, alen; uint16_t len, rmlen = 0; - if (!rewrite || (!rewrite->removeattrs && !rewrite->removevendorattrs)) - return; - len = RADLEN(buf) - 20; attrs = buf + 20; while (len > 1) { alen = ATTRLEN(attrs); len -= alen; - if (rewrite->removeattrs && strchr((char *)rewrite->removeattrs, ATTRTYPE(attrs))) { + if (rmattrs && strchr((char *)rmattrs, ATTRTYPE(attrs))) { memmove(attrs, attrs + alen, len); rmlen += alen; - } else if (ATTRTYPE(attrs) == RAD_Attr_Vendor_Specific && rewrite->removevendorattrs) - rmlen += dovendorrewrite(attrs, len, rewrite->removevendorattrs); + } else if (ATTRTYPE(attrs) == RAD_Attr_Vendor_Specific && rmvattrs) + rmlen += dovendorrewrite(attrs, len, rmvattrs); else attrs += alen; } @@ -1553,6 +1550,43 @@ void dorewrite(uint8_t *buf, struct rewrite *rewrite) { ((uint16_t *)buf)[1] = htons(RADLEN(buf) - rmlen); } +int dorewriteadd(uint8_t **buf, struct list *addattrs) { + struct list_node *n; + struct attribute *a; + uint16_t i, addlen = 0; + uint8_t *newbuf; + + for (n = list_first(addattrs); n; n = list_next(n)) + addlen += 2 + ((struct attribute *)n->data)->l; + if (!addlen) + return 1; + newbuf = realloc(*buf, RADLEN(*buf) + addlen); + if (!newbuf) + return 0; + + i = RADLEN(newbuf); + for (n = list_first(addattrs); n; n = list_next(n)) { + a = (struct attribute *)n->data; + newbuf[i++] = a->t; + newbuf[i++] = a->l + 2; + memcpy(newbuf + i, a->v, a->l); + i += a->l; + } + ((uint16_t *)newbuf)[1] = htons(RADLEN(newbuf) + addlen); + *buf = newbuf; + 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; @@ -1834,8 +1868,11 @@ void radsrv(struct request *rq) { } if (rq->from->conf->rewritein) { - dorewrite(rq->buf, rq->from->conf->rewritein); + if (!dorewrite(&rq->buf, rq->from->conf->rewritein)) + goto exit; len = RADLEN(rq->buf) - 20; + auth = (uint8_t *)(rq->buf + 4); + attrs = rq->buf + 20; } attr = attrget(attrs, len, RAD_Attr_User_Name); @@ -1923,7 +1960,9 @@ void radsrv(struct request *rq) { memcpy(auth, newauth, 16); if (to->conf->rewriteout) - dorewrite(rq->buf, to->conf->rewriteout); + if (!dorewrite(&rq->buf, to->conf->rewriteout)) + goto exit; + sendrq(to, rq); return; @@ -2015,8 +2054,12 @@ int replyh(struct server *server, unsigned char *buf) { } if (server->conf->rewritein) { - dorewrite(buf, server->conf->rewritein); + if (!dorewrite(&buf, server->conf->rewritein)) + return 0; len = RADLEN(buf) - 20; + attrs = buf + 20; + if (messageauth) + messageauth = attrget(attrs, len, RAD_Attr_Message_Authenticator); } /* MS MPPE */ @@ -2077,8 +2120,10 @@ int replyh(struct server *server, unsigned char *buf) { } if (from->conf->rewriteout) { - dorewrite(buf, from->conf->rewriteout); + if (!dorewrite(&buf, from->conf->rewriteout)) + return 0; len = RADLEN(buf) - 20; + attrs = buf + 20; if (messageauth) messageauth = attrget(attrs, len, RAD_Attr_Message_Authenticator); } @@ -2525,7 +2570,7 @@ void tlsadd(char *value, char *cacertfile, char *cacertpath, char *certfile, cha debugx(1, DBG_ERR, "CA Certificate file or path need to be specified in TLS context %s", value); if (!ssl_locks) { - ssl_locks = malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); + ssl_locks = calloc(CRYPTO_num_locks(), sizeof(pthread_mutex_t)); ssl_lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long)); for (i = 0; i < CRYPTO_num_locks(); i++) { ssl_lock_count[i] = 0; @@ -2821,6 +2866,32 @@ int vattrname2val(char *attrname, uint32_t *vendor, uint32_t *type) { return *type >= 0 && *type < 256; } +/* should accept both names and numeric values, only numeric right now */ +struct attribute *extractattr(char *nameval) { + int len, name = 0; + char *s; + struct attribute *a; + + s = strchr(nameval, ':'); + name = atoi(nameval); + if (!s || name < 1 || name > 255) + return NULL; + len = strlen(s + 1); + if (len > 253) + return NULL; + a = malloc(sizeof(struct attribute)); + if (!a) + return NULL; + a->v = (uint8_t *)stringcopy(s + 1, 0); + if (!a->v) { + free(a); + return NULL; + } + a->t = name; + a->l = len; + return a; +} + void rewritefree() { struct list_node *entry; struct rewriteconf *r; @@ -2857,51 +2928,67 @@ struct rewrite *getrewrite(char *alt1, char *alt2) { return r->rewrite; } -void addrewrite(char *value, char **attrs, char **vattrs) { +void addrewrite(char *value, char **rmattrs, char **rmvattrs, char **addattrs) { struct rewriteconf *new; struct rewrite *rewrite = NULL; int i, n; - uint8_t *a = NULL; - uint32_t *p, *va = NULL; - - if (attrs) { - n = 0; - for (; attrs[n]; n++); - a = malloc((n + 1) * sizeof(uint8_t)); - if (!a) + uint8_t *rma = NULL; + uint32_t *p, *rmva = NULL; + struct attribute *a; + struct list *adda = NULL; + + if (rmattrs) { + for (n = 0; rmattrs[n]; n++); + rma = calloc(n + 1, sizeof(uint8_t)); + if (!rma) debugx(1, DBG_ERR, "malloc failed"); for (i = 0; i < n; i++) { - if (!(a[i] = attrname2val(attrs[i]))) - debugx(1, DBG_ERR, "addrewrite: invalid attribute %s", attrs[i]); - free(attrs[i]); + if (!(rma[i] = attrname2val(rmattrs[i]))) + debugx(1, DBG_ERR, "addrewrite: invalid attribute %s", rmattrs[i]); + free(rmattrs[i]); } - free(attrs); - a[i] = 0; + free(rmattrs); + rma[i] = 0; } - if (vattrs) { - n = 0; - for (; vattrs[n]; n++); - va = malloc((2 * n + 1) * sizeof(uint32_t)); - if (!va) + if (rmvattrs) { + for (n = 0; rmvattrs[n]; n++); + rmva = calloc(2 * n + 1, sizeof(uint32_t)); + if (!rmva) debugx(1, DBG_ERR, "malloc failed"); - for (p = va, i = 0; i < n; i++, p += 2) { - if (!vattrname2val(vattrs[i], p, p + 1)) - debugx(1, DBG_ERR, "addrewrite: invalid vendor attribute %s", vattrs[i]); - free(vattrs[i]); + for (p = rmva, i = 0; i < n; i++, p += 2) { + if (!vattrname2val(rmvattrs[i], p, p + 1)) + debugx(1, DBG_ERR, "addrewrite: invalid vendor attribute %s", rmvattrs[i]); + free(rmvattrs[i]); } - free(vattrs); + free(rmvattrs); *p = 0; } - - if (a || va) { + + if (addattrs) { + adda = list_create(); + if (!adda) + debugx(1, DBG_ERR, "malloc failed"); + for (i = 0; addattrs[i]; i++) { + a = extractattr(addattrs[i]); + if (!a) + debugx(1, DBG_ERR, "addrewrite: invalid attribute %s", addattrs[i]); + free(addattrs[i]); + if (!list_push(adda, a)) + debugx(1, DBG_ERR, "malloc failed"); + } + free(addattrs); + } + + if (rma || rmva || adda) { rewrite = malloc(sizeof(struct rewrite)); if (!rewrite) debugx(1, DBG_ERR, "malloc failed"); - rewrite->removeattrs = a; - rewrite->removevendorattrs = va; + rewrite->removeattrs = rma; + rewrite->removevendorattrs = rmva; + rewrite->addattrs = adda; } new = malloc(sizeof(struct rewriteconf)); @@ -3126,16 +3213,17 @@ void conftls_cb(struct gconffile **cf, char *block, char *opt, char *val) { } void confrewrite_cb(struct gconffile **cf, char *block, char *opt, char *val) { - char **attrs = NULL, **vattrs = NULL; + char **rmattrs = NULL, **rmvattrs = NULL, **addattrs = NULL; debug(DBG_DBG, "confrewrite_cb called for %s", block); getgenericconfig(cf, block, - "removeAttribute", CONF_MSTR, &attrs, - "removeVendorAttribute", CONF_MSTR, &vattrs, + "removeAttribute", CONF_MSTR, &rmattrs, + "removeVendorAttribute", CONF_MSTR, &rmvattrs, + "addAttribute", CONF_MSTR, &addattrs, NULL ); - addrewrite(val, attrs, vattrs); + addrewrite(val, rmattrs, rmvattrs, addattrs); } void getmainconfig(const char *configfile) { |