diff --git a/.gitignore b/.gitignore index c53f184..fa95497 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ radsecproxy-hash build-aux/* tests/t_fticks tests/t_rewrite +tests/t_rewrite_config tests/t_resizeattr tests/*.log tests/*.trs diff --git a/gconfig.c b/gconfig.c index 6a5d26b..81fe63e 100644 --- a/gconfig.c +++ b/gconfig.c @@ -366,16 +366,20 @@ uint8_t hexdigit2int(char d) { return 0; } -void unhex(char *s) { +int unhex(char *s, uint8_t process_null) { + int len = 0; char *t; for (t = s; *t; s++) { - if (*t == '%' && isxdigit((int)t[1]) && isxdigit((int)t[2])) { - *s = 16 * hexdigit2int(t[1]) + hexdigit2int(t[2]); - t += 3; - } else - *s = *t++; + if (*t == '%' && isxdigit((int)t[1]) && isxdigit((int)t[2]) && + (process_null || !(t[1]=='0' && t[2]=='0'))) { + *s = 16 * hexdigit2int(t[1]) + hexdigit2int(t[2]); + t += 3; + } else + *s = *t++; + len++; } *s = '\0'; + return len; } typedef int (*t_fptr)(struct gconffile **, void *, char *, char *, char *); @@ -466,7 +470,7 @@ int getgenericconfig(struct gconffile **cf, char *block, ...) { debug(DBG_ERR, "configuration error, option %s already set to %s", opt, *str); goto errexit; } - unhex(val); + unhex(val,0); *str = val; break; case CONF_MSTR: @@ -479,7 +483,7 @@ int getgenericconfig(struct gconffile **cf, char *block, ...) { debug(DBG_ERR, "malloc failed"); goto errexit; } - unhex(val); + unhex(val,0); newmstr[n] = val; newmstr[n + 1] = NULL; *mstr = newmstr; diff --git a/gconfig.h b/gconfig.h index 3cb34b3..a5276f1 100644 --- a/gconfig.h +++ b/gconfig.h @@ -26,6 +26,7 @@ int popgconf(struct gconffile **cf); void freegconfmstr(char **mstr); void freegconf(struct gconffile **cf); struct gconffile *openconfigfile(const char *file); +int unhex(char *s, uint8_t process_null); /* Local Variables: */ /* c-file-style: "stroustrup" */ diff --git a/radsecproxy.conf.5 b/radsecproxy.conf.5 index 1916f1e..6ff97a9 100644 --- a/radsecproxy.conf.5 +++ b/radsecproxy.conf.5 @@ -61,11 +61,13 @@ blocktype name { .fi .RE -Option value characters can also be written in hex. This is done by writing the -character % followed by two hexadecimal digits. If a % is used without two -following hexadecimal digits, the % and the following characters are used as -written. If you want to write a % and not use this decoding, you may of course -write % in hex; i.e., %25. +Option value characters can also be written in hex for options requiring a +string type value. This is done by writing the character % followed by two +hexadecimal digits. If a % is used without two following hexadecimal digits, the +% and the following characters are used as written. If you want to write a % and +not use this decoding, you may of course write % in hex; i.e., %25. As %00 would +terminate a string, this value is not converted in most cases, except when used +with rewrite statements. Some options allow or require the use of regular expressions, denoted as \fIregex\fR. The POSIX extended RE system is used, see @@ -808,8 +810,11 @@ block are: .RS Add an \fIattribute\fR to the radius mesage and set it to \fIvalue\fR. The \fIattribute\fR must be specified using the numerical attribute id. The -\fIvalue\fR can either be numerical, a string, or a hex value. See the -\fBCONFIGURATION SYNTAX\fR section for details. +\fIvalue\fR can either be numerical, a string, or a hex value. If the value +starts with a number, it is interpreted as a 32bit unsigned integer. Use the ' +character at the start of the value to force string interpretation. When using +hex value, it is recommended to also lead with ' to avoid unintended numeric +interpretation. See the \fBCONFIGURATION SYNTAX\fR section for further details. .RE .BI "AddVendorAttribute " vendor \fR: subattribute \fR: value diff --git a/rewrite.c b/rewrite.c index 0072a66..58e6aff 100644 --- a/rewrite.c +++ b/rewrite.c @@ -1,7 +1,7 @@ /* Copyright (c) 2019, SWITCH */ /* See LICENSE for licensing information. */ -#include +#include #include #include #include @@ -25,6 +25,7 @@ static struct hash *rewriteconfs; struct tlv *extractattr(char *nameval, char vendor_flag) { int len, name = 0; int vendor = 0; /* Vendor 0 is reserved, see RFC 1700. */ + uint32_t ival=0; char *s, *s2; struct tlv *a; @@ -41,9 +42,21 @@ struct tlv *extractattr(char *nameval, char vendor_flag) { name = atoi(s + 1); s = s2; } - len = strlen(s + 1); - if (len > 253) - return NULL; + + s++; + if (isdigit(*s)) { + ival = atoi(s); + ival = htonl(ival); + len = 4; + s = (char *)&ival; + } else { + if (*s == '\'') + s++; + + len = unhex(s,1); + if (len > 253) + return NULL; + } if (name < 1 || name > 255) return NULL; @@ -51,7 +64,7 @@ struct tlv *extractattr(char *nameval, char vendor_flag) { if (!a) return NULL; - a->v = (uint8_t *)stringcopy(s + 1, 0); + a->v = (uint8_t *)stringcopy(s, len); if (!a->v) { free(a); return NULL; diff --git a/tests/Makefile.am b/tests/Makefile.am index 4254574..a795140 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,7 +4,7 @@ AUTOMAKE_OPTIONS = foreign LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \ $(top_srcdir)/build-aux/tap-driver.sh -check_PROGRAMS = t_fticks t_rewrite t_resizeattr +check_PROGRAMS = t_fticks t_rewrite t_resizeattr t_rewrite_config AM_CFLAGS = -g -Wall -Werror @SSL_CFLAGS@ @TARGET_CFLAGS@ LDADD = $(top_builddir)/librsp.a @SSL_LIBS@ diff --git a/tests/t_rewrite_config.c b/tests/t_rewrite_config.c new file mode 100644 index 0000000..2c79331 --- /dev/null +++ b/tests/t_rewrite_config.c @@ -0,0 +1,53 @@ +/* Copyright (C) 2019, SWITCH */ +/* See LICENSE for licensing information. */ + +#include +#include +#include +#include "../rewrite.h" +#include "../radmsg.h" +#include "../debug.h" +#include "../util.h" + +int +main (int argc, char *argv[]) +{ + struct rewrite *result; + char *rewritename = "rewrite"; + char **addattrs; + int numtests = 1, i; + struct tlv *tlv, *expected; + uint8_t expectedvalue[] = {'1',0,0,'1','A'}; + + printf("1..%d\n", numtests); + numtests = 1; + + addattrs = malloc(2); + addattrs[0] = stringcopy("1:'1%00%001%41", 0); + addattrs[1] = NULL; + + expected = maketlv(1,5,expectedvalue); + + addrewrite(rewritename, NULL, NULL, addattrs, + NULL, NULL, NULL, NULL); + + result = getrewrite(rewritename, NULL); + + if (result->addattrs->first) { + tlv = (struct tlv *)result->addattrs->first->data; + if (!eqtlv(tlv, expected)) { + printf ("tlv value was: 0x"); + for (i = 0; i < tlv->l; i++) { + printf ("%x", *((tlv->v)+i)); + } + printf ("\n"); + printf ("not "); + } + printf("ok %d - rewrite config\n", numtests++); + } else { + printf("not ok %d - rewrite ocnfig\n", numtests++); + } + + + return 0; +}