From c0c1ea40c674cd6c4d1f6ba4859348cce86cb523 Mon Sep 17 00:00:00 2001 From: Fabian Mauchle Date: Thu, 18 Apr 2019 06:46:42 +0200 Subject: [PATCH] implement whitelist mode for attribute rewrite --- rewrite.c | 15 +++---- rewrite.h | 1 + tests/t_rewrite.c | 101 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 109 insertions(+), 8 deletions(-) diff --git a/rewrite.c b/rewrite.c index 13921db..4e41cf7 100644 --- a/rewrite.c +++ b/rewrite.c @@ -289,7 +289,7 @@ int findvendorsubattr(uint32_t *attrs, uint32_t vendor, uint32_t subattr) { } /* returns 1 if entire element is to be removed, else 0 */ -int dovendorrewriterm(struct tlv *attr, uint32_t *removevendorattrs) { +int dovendorrewriterm(struct tlv *attr, uint32_t *removevendorattrs, int inverted) { uint8_t alen, sublen; uint32_t vendor; uint8_t *subattrs; @@ -318,18 +318,19 @@ int dovendorrewriterm(struct tlv *attr, uint32_t *removevendorattrs) { while (sublen > 1) { alen = ATTRLEN(subattrs); sublen -= alen; - if (findvendorsubattr(removevendorattrs, vendor, ATTRTYPE(subattrs))) { + if (!!findvendorsubattr(removevendorattrs, vendor, ATTRTYPE(subattrs)) != !!inverted) { memmove(subattrs, subattrs + alen, sublen); attr->l -= alen; } else subattrs += alen; } - if (attr->l <= 4) + if ((attr->l <= 4) != !!inverted) return 1; return 0; } -void dorewriterm(struct radmsg *msg, uint8_t *rmattrs, uint32_t *rmvattrs) { +/*if inverted is true, remove all attributes except those listed */ +void dorewriterm(struct radmsg *msg, uint8_t *rmattrs, uint32_t *rmvattrs, int inverted) { struct list_node *n, *p; struct tlv *attr; @@ -337,8 +338,8 @@ void dorewriterm(struct radmsg *msg, uint8_t *rmattrs, uint32_t *rmvattrs) { n = list_first(msg->attrs); while (n) { attr = (struct tlv *)n->data; - if ((rmattrs && strchr((char *)rmattrs, attr->t)) || - (rmvattrs && attr->t == RAD_Attr_Vendor_Specific && dovendorrewriterm(attr, rmvattrs))) { + if (((rmattrs && strchr((char *)rmattrs, attr->t)) || + (rmvattrs && attr->t == RAD_Attr_Vendor_Specific && dovendorrewriterm(attr, rmvattrs, inverted))) != !!inverted) { list_removedata(msg->attrs, attr); freetlv(attr); n = p ? list_next(p) : list_first(msg->attrs); @@ -478,7 +479,7 @@ int dorewrite(struct radmsg *msg, struct rewrite *rewrite) { if (rewrite) { if (rewrite->removeattrs || rewrite->removevendorattrs) - dorewriterm(msg, rewrite->removeattrs, rewrite->removevendorattrs); + dorewriterm(msg, rewrite->removeattrs, rewrite->removevendorattrs, rewrite->whitelist_mode); if (rewrite->modattrs) if (!dorewritemod(msg, rewrite->modattrs)) rv = 0; diff --git a/rewrite.h b/rewrite.h index 7176898..3b2b62d 100644 --- a/rewrite.h +++ b/rewrite.h @@ -15,6 +15,7 @@ struct modattr { }; struct rewrite { + uint8_t whitelist_mode; uint8_t *removeattrs; /*NULL terminated*/ uint32_t *removevendorattrs; /*NULL terminated*/ struct list *addattrs; /*struct tlv*/ diff --git a/tests/t_rewrite.c b/tests/t_rewrite.c index 6becac1..bc4fd33 100644 --- a/tests/t_rewrite.c +++ b/tests/t_rewrite.c @@ -47,6 +47,7 @@ void _list_clear(struct list *list) { } void _reset_rewrite(struct rewrite *rewrite) { + rewrite->whitelist_mode = 0; rewrite->removeattrs = NULL; rewrite->removevendorattrs = NULL; _list_clear(rewrite->addattrs); @@ -57,7 +58,7 @@ void _reset_rewrite(struct rewrite *rewrite) { int main (int argc, char *argv[]) { - int testcount = 18; + int testcount = 22; struct list *origattrs, *expectedattrs; struct rewrite rewrite; char *username = "user@realm"; @@ -67,6 +68,7 @@ main (int argc, char *argv[]) origattrs=list_create(); expectedattrs=list_create(); + rewrite.whitelist_mode=0; rewrite.removeattrs = NULL; rewrite.removevendorattrs = NULL; rewrite.addattrs = list_create(); @@ -449,6 +451,103 @@ main (int argc, char *argv[]) _reset_rewrite(&rewrite); } + /* test whitelist rewrite */ + { + uint8_t whitelistattrs[] = {1,0}; + rewrite.whitelist_mode=1; + rewrite.removeattrs = whitelistattrs; + + list_push(origattrs, maketlv(1, strlen(username), username)); + list_push(origattrs, maketlv(3, strlen(username), username)); + list_push(origattrs, makevendortlv(42, maketlv(1, strlen(username), username))); + + list_push(expectedattrs, maketlv(1, strlen(username), username)); + + if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) + printf("not "); + printf("ok %d - whitelistattrs\n", testcount++); + _list_clear(origattrs); + _list_clear(expectedattrs); + _reset_rewrite(&rewrite); + + } + + /* test whitelist vendor rewrite */ + { + uint32_t whitelistvendorattrs[] = {42,256,0}; + uint8_t value = 42; + uint8_t vendor_nonrfc_in[] = {0,0,0,42,1,2,3,4}; + + rewrite.whitelist_mode=1; + rewrite.removevendorattrs = whitelistvendorattrs; + list_push(origattrs, maketlv(1, strlen(username), username)); + list_push(origattrs, makevendortlv(42, maketlv(1, 1, &value))); + list_push(origattrs, makevendortlv(43, maketlv(1, 1, &value))); + list_push(origattrs, maketlv(26, sizeof(vendor_nonrfc_in), vendor_nonrfc_in)); + + list_push(expectedattrs, makevendortlv(42, maketlv(1, 1, &value))); + list_push(expectedattrs, maketlv(26, sizeof(vendor_nonrfc_in), vendor_nonrfc_in)); + + if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) + printf("not "); + printf("ok %d - whitelistvendorattrs\n", testcount++); + _list_clear(origattrs); + _list_clear(expectedattrs); + _reset_rewrite(&rewrite); + } + + /* test whitelist vendor rewrite subattribute*/ + { + uint32_t whitelistvendorattrs[] = {42,1,0}; + uint8_t value = 42; + uint8_t vendor_long1_in[] = {0,0,0,42,2,3,0,1,3,0}; + uint8_t vendor_long1_out[] = {0,0,0,42,1,3,0}; + uint8_t vendor_nonrfc_in[] = {0,0,0,42,1,2,3,4}; + + rewrite.whitelist_mode=1; + rewrite.removevendorattrs = whitelistvendorattrs; + list_push(origattrs, makevendortlv(42, maketlv(1, 1, &value))); + list_push(origattrs, makevendortlv(43, maketlv(1, 1, &value))); + list_push(origattrs, makevendortlv(42, maketlv(2, 1, &value))); + list_push(origattrs, maketlv(26, sizeof(vendor_long1_in), vendor_long1_in)); + list_push(origattrs, maketlv(26, sizeof(vendor_nonrfc_in), vendor_nonrfc_in)); + + list_push(expectedattrs, makevendortlv(42, maketlv(1, 1, &value))); + list_push(expectedattrs, maketlv(26, sizeof(vendor_long1_out), vendor_long1_out)); + + if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) + printf("not "); + printf("ok %d - whitelistvendorattrs\n", testcount++); + _list_clear(origattrs); + _list_clear(expectedattrs); + _reset_rewrite(&rewrite); + } + + /* test whitelist vendor rewrite combined*/ + { + uint32_t whitelistvendorattrs[] = {42,1,0}; + uint8_t whitelistattrs[] = {1,0}; + uint8_t value = 42; + + rewrite.whitelist_mode=1; + rewrite.removeattrs = whitelistattrs; + rewrite.removevendorattrs = whitelistvendorattrs; + list_push(origattrs, maketlv(1, strlen(username), username)); + list_push(origattrs, maketlv(3, strlen(username), username)); + list_push(origattrs, makevendortlv(42, maketlv(1, 1, &value))); + list_push(origattrs, makevendortlv(43, maketlv(1, 1, &value))); + list_push(origattrs, makevendortlv(43, maketlv(2, 1, &value))); + + list_push(expectedattrs, maketlv(1, strlen(username), username)); + list_push(expectedattrs, makevendortlv(42, maketlv(1, 1, &value))); + + if (_check_rewrite(origattrs, &rewrite, expectedattrs, 0)) + printf("not "); + printf("ok %d - whitelistvendorattrs\n", testcount++); + _list_clear(origattrs); + _list_clear(expectedattrs); + _reset_rewrite(&rewrite); + } return 0;