From 51630d48e815c99128683bc4d2282d8f89a0fa14 Mon Sep 17 00:00:00 2001 From: Fabian Mauchle Date: Wed, 24 Apr 2019 07:11:33 +0200 Subject: [PATCH] implement rewritevendorattribute --- radmsg.h | 1 + rewrite.c | 83 ++++++++++++++++++++++++++++++++++++++++++----- rewrite.h | 2 ++ tests/t_rewrite.c | 62 ++++++++++++++++++++++++++++++++++- 4 files changed, 138 insertions(+), 10 deletions(-) diff --git a/radmsg.h b/radmsg.h index 77ce8e5..8999bc0 100644 --- a/radmsg.h +++ b/radmsg.h @@ -52,6 +52,7 @@ struct list *radmsg_getalltype(const struct radmsg *msg, uint8_t type); int radmsg_copy_attrs(struct radmsg *dst, const struct radmsg *src, uint8_t type); +uint8_t *tlv2buf(uint8_t *p, const struct tlv *tlv); uint8_t *radmsg2buf(struct radmsg *msg, uint8_t *, int); struct radmsg *buf2radmsg(uint8_t *, uint8_t *, int, uint8_t *); uint8_t attrname2val(char *attrname); diff --git a/rewrite.c b/rewrite.c index 925e22c..1afe26b 100644 --- a/rewrite.c +++ b/rewrite.c @@ -257,6 +257,7 @@ void addrewrite(char *value, uint8_t whitelist_mode, char **rmattrs, char **rmva rewrite->removevendorattrs = rmva; rewrite->addattrs = adda; rewrite->modattrs = moda; + rewrite->modvattrs = NULL; rewrite->supattrs = supa; } @@ -406,14 +407,78 @@ int dorewritemodattr(struct tlv *attr, struct modattr *modattr) { return 1; } -int dorewritemod(struct radmsg *msg, struct list *modattrs) { - struct list_node *n, *m; +int replacesubtlv(struct tlv *vendortlv, uint8_t *p, struct tlv *newtlv) { + int size_diff; + uint8_t rem_size, *next_attr; + + size_diff = newtlv->l - ATTRLEN(p); + next_attr = p+ATTRLEN(p); + rem_size = (vendortlv->v + vendortlv->l) - next_attr; + + if (size_diff < 0) + memmove(next_attr + size_diff, next_attr, rem_size); + if (!resizeattr(vendortlv, vendortlv->l+size_diff)) + return 0; + if (size_diff > 0) + memmove(next_attr + size_diff, next_attr, rem_size); + + tlv2buf(p, newtlv); + return 1; +} - for (n = list_first(msg->attrs); n; n = list_next(n)) - for (m = list_first(modattrs); m; m = list_next(m)) - if (((struct tlv *)n->data)->t == ((struct modattr *)m->data)->t && - !dorewritemodattr((struct tlv *)n->data, (struct modattr *)m->data)) +int dorewritemodvattr(struct tlv *vendortlv, struct modattr *modvattr) { + uint8_t *p; + struct tlv *tmpattr; + + if (vendortlv->l <= 4 || !attrvalidate(vendortlv->v+4, vendortlv->l-4)) + return 0; + for (p = vendortlv->v+4; p < (vendortlv->v + vendortlv->l); p = p+ATTRLEN(p)) { + if (ATTRTYPE(p) == modvattr->t) { + tmpattr = maketlv(ATTRTYPE(p), ATTRVALLEN(p), ATTRVAL(p)); + if (dorewritemodattr(tmpattr, modvattr)) { + int size_diff = tmpattr->l - ATTRVALLEN(p); + uint8_t *next_attr = p+ATTRLEN(p); + uint8_t rem_size = (vendortlv->v + vendortlv->l) - next_attr; + + if (size_diff < 0) + memmove(next_attr + size_diff, next_attr, rem_size); + if (!resizeattr(vendortlv, vendortlv->l+size_diff)) + return 0; + if (size_diff > 0) + memmove(next_attr + size_diff, next_attr, rem_size); + + tlv2buf(p, tmpattr); + } else { + freetlv(tmpattr); return 0; + } + freetlv(tmpattr); + } + } + return 1; +} + +int dorewritemod(struct radmsg *msg, struct list *modattrs, struct list *modvattrs) { + struct list_node *n, *m; + uint32_t vendor; + + for (n = list_first(msg->attrs); n; n = list_next(n)) { + struct tlv *attr = (struct tlv *)n->data; + if (attr->t == RAD_Attr_Vendor_Specific) { + memcpy(&vendor, attr->v, 4); + vendor = ntohl(vendor); + for (m = list_first(modvattrs); m; m = list_next(m)) { + if (vendor == ((struct modattr *)m->data)->vendor && + !dorewritemodvattr(attr, (struct modattr*)m->data)) + return 0; + } + } else { + for (m = list_first(modattrs); m; m = list_next(m)) + if (((struct tlv *)n->data)->t == ((struct modattr *)m->data)->t && + !dorewritemodattr((struct tlv *)n->data, (struct modattr *)m->data)) + return 0; + } + } return 1; } @@ -480,9 +545,9 @@ int dorewrite(struct radmsg *msg, struct rewrite *rewrite) { if (rewrite) { if (rewrite->removeattrs || rewrite->removevendorattrs) - dorewriterm(msg, rewrite->removeattrs, rewrite->removevendorattrs, rewrite->whitelist_mode); - if (rewrite->modattrs) - if (!dorewritemod(msg, rewrite->modattrs)) + dorewriterm(msg, rewrite->removeattrs, rewrite->removevendorattrs, rewrite->whitelist_mode); + if (rewrite->modattrs || rewrite->modvattrs) + if (!dorewritemod(msg, rewrite->modattrs, rewrite->modvattrs)) rv = 0; if (rewrite->supattrs) if (!dorewritesup(msg, rewrite->supattrs)) diff --git a/rewrite.h b/rewrite.h index d8edecf..ae8e93f 100644 --- a/rewrite.h +++ b/rewrite.h @@ -10,6 +10,7 @@ struct modattr { uint8_t t; + uint32_t vendor; char *replacement; regex_t *regex; }; @@ -20,6 +21,7 @@ struct rewrite { uint32_t *removevendorattrs; /*NULL terminated*/ struct list *addattrs; /*struct tlv*/ struct list *modattrs; /*struct modattr*/ + struct list *modvattrs; /*struct modattr*/ struct list *supattrs; /*struct tlv*/ }; diff --git a/tests/t_rewrite.c b/tests/t_rewrite.c index 05ea72f..fe67fd5 100644 --- a/tests/t_rewrite.c +++ b/tests/t_rewrite.c @@ -52,13 +52,14 @@ void _reset_rewrite(struct rewrite *rewrite) { rewrite->removevendorattrs = NULL; _list_clear(rewrite->addattrs); _list_clear(rewrite->modattrs); + _list_clear(rewrite->modvattrs); _list_clear(rewrite->supattrs); } int main (int argc, char *argv[]) { - int testcount = 23; + int testcount = 25; struct list *origattrs, *expectedattrs; struct rewrite rewrite; char *username = "user@realm"; @@ -73,6 +74,7 @@ main (int argc, char *argv[]) rewrite.removevendorattrs = NULL; rewrite.addattrs = list_create(); rewrite.modattrs = list_create(); + rewrite.modvattrs = list_create(); rewrite.supattrs = list_create(); printf("1..%d\n", testcount); @@ -471,6 +473,64 @@ main (int argc, char *argv[]) _reset_rewrite(&rewrite); } + /* test modify vendor*/ + { + struct modattr *mod = malloc(sizeof(struct modattr)); + regex_t regex; + uint8_t vendorattrin[] = {0,0,0,42,1,3,'b',1,3,'a',2,3,0,1,3,'a'}; + uint8_t vendorattrout[] = {0,0,0,42,1,3,'b',1,4,'b','b',2,3,0,1,4,'b','b'}; + + mod->t = 1; + mod->vendor = 42; + mod->regex = ®ex; + mod->replacement = "bb"; + regcomp(mod->regex, "a", REG_ICASE | REG_EXTENDED); + + list_push(rewrite.modvattrs, mod); + list_push(origattrs, maketlv(RAD_Attr_Vendor_Specific,sizeof(vendorattrin), vendorattrin)); + list_push(expectedattrs, maketlv(RAD_Attr_Vendor_Specific,sizeof(vendorattrout), vendorattrout)); + + if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) + printf("not "); + printf("ok %d - modify vendor\n", testcount++); + + _list_clear(origattrs); + _list_clear(expectedattrs); + _reset_rewrite(&rewrite); + } + + /* test modify vendor too long (total vendor attribute too long) */ + { + struct modattr *mod = malloc(sizeof(struct modattr)); + regex_t regex; + uint8_t vendorattrin[RAD_Max_Attr_Value_Length]; + + memset(vendorattrin, 0, RAD_Max_Attr_Value_Length); + vendorattrin[3] = 42; + vendorattrin[4] = 1; + vendorattrin[5] = 3; + vendorattrin[6] = 'a'; + vendorattrin[7] = 2; + vendorattrin[8] = RAD_Max_Attr_Value_Length - 7; + + mod->t = 1; + mod->vendor = 42; + mod->regex = ®ex; + mod->replacement = "bb"; + regcomp(mod->regex, "a", REG_ICASE | REG_EXTENDED); + + list_push(rewrite.modvattrs, mod); + list_push(origattrs, maketlv(RAD_Attr_Vendor_Specific,sizeof(vendorattrin), vendorattrin)); + + if (_check_rewrite(origattrs, &rewrite, origattrs, 1)) + printf("not "); + printf("ok %d - modify vendor too long\n", testcount++); + + _list_clear(origattrs); + _list_clear(expectedattrs); + _reset_rewrite(&rewrite); + } + /* test whitelist rewrite */ { uint8_t whitelistattrs[] = {1,0};