From 5a4b1da66c333a59aaeb2fae8a1b025520b5f385 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Thu, 20 Sep 2012 13:55:08 +0100 Subject: [PATCH] Move string manipulation functions from xlat.c to rlm_expr --- src/main/xlat.c | 109 --------------------------- src/modules/rlm_expr/rlm_expr.c | 161 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 109 deletions(-) diff --git a/src/main/xlat.c b/src/main/xlat.c index 3d45a07..90081e7 100644 --- a/src/main/xlat.c +++ b/src/main/xlat.c @@ -26,7 +26,6 @@ RCSID("$Id$") #include -#include #include #include @@ -591,99 +590,6 @@ static size_t xlat_debug(UNUSED void *instance, REQUEST *request, return strlen(out); } - -/* - * Calculate the MD5 hash of a string. - */ -static size_t xlat_md5(UNUSED void *instance, REQUEST *request, - char *fmt, char *out, size_t outlen, - UNUSED RADIUS_ESCAPE_STRING func) -{ - int i; - uint8_t digest[16]; - FR_MD5_CTX ctx; - char buffer[1024]; - - if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) { - *out = '\0'; - return 0; - } - - fr_MD5Init(&ctx); - fr_MD5Update(&ctx, (void *) buffer, strlen(buffer)); - fr_MD5Final(digest, &ctx); - - if (outlen < 33) { - snprintf(out, outlen, "md5_overflow"); - return strlen(out); - } - - for (i = 0; i < 16; i++) { - snprintf(out + i * 2, 3, "%02x", digest[i]); - } - - return strlen(out); -} - - -/* - * Convert a string to lowercase - */ -static size_t xlat_lc(UNUSED void *instance, REQUEST *request, - char *fmt, char *out, size_t outlen, - UNUSED RADIUS_ESCAPE_STRING func) -{ - char *p, *q; - char buffer[1024]; - - if (outlen <= 1) return 0; - - if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) { - *out = '\0'; - return 0; - } - - for (p = buffer, q = out; *p != '\0'; p++, outlen--) { - if (outlen <= 1) break; - - *(q++) = tolower((int) *p); - } - - *q = '\0'; - - return strlen(out); -} - - -/* - * Convert a string to uppercase - */ -static size_t xlat_uc(UNUSED void *instance, REQUEST *request, - char *fmt, char *out, size_t outlen, - UNUSED RADIUS_ESCAPE_STRING func) -{ - char *p, *q; - char buffer[1024]; - - if (outlen <= 1) return 0; - - if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) { - *out = '\0'; - return 0; - } - - for (p = buffer, q = out; *p != '\0'; p++, outlen--) { - if (outlen <= 1) break; - - *(q++) = toupper((int) *p); - } - - *q = '\0'; - - return strlen(out); -} - - /* * Compare two xlat_t structs, based ONLY on the module name. */ @@ -791,21 +697,6 @@ int xlat_register(const char *module, RAD_XLAT_FUNC func, void *instance) c = xlat_find("debug"); rad_assert(c != NULL); c->internal = TRUE; - - xlat_register("md5", xlat_md5, &xlat_inst[0]); - c = xlat_find("md5"); - rad_assert(c != NULL); - c->internal = TRUE; - - xlat_register("tolower", xlat_lc, &xlat_inst[0]); - c = xlat_find("tolower"); - rad_assert(c != NULL); - c->internal = TRUE; - - xlat_register("toupper", xlat_uc, &xlat_inst[0]); - c = xlat_find("toupper"); - rad_assert(c != NULL); - c->internal = TRUE; } /* diff --git a/src/modules/rlm_expr/rlm_expr.c b/src/modules/rlm_expr/rlm_expr.c index 2e57110..10411d0 100644 --- a/src/modules/rlm_expr/rlm_expr.c +++ b/src/modules/rlm_expr/rlm_expr.c @@ -25,7 +25,11 @@ RCSID("$Id$") #include +#include #include + +#include + #include "rlm_expr.h" /* @@ -407,6 +411,159 @@ static size_t randstr_xlat(UNUSED void *instance, REQUEST *request, return outlen - freespace; } +/** + * @brief URLencode special characters + * + * Example: "%{urlquote:http://example.org/}" == "http%3A%47%47example.org%47" + */ +static size_t urlquote_xlat(UNUSED void *instance, REQUEST *request, + const char *fmt, char *out, size_t outlen, + UNUSED RADIUS_ESCAPE_STRING func) +{ + char *p; + char buffer[1024]; + size_t freespace = outlen; + size_t len; + + if (outlen <= 1) return 0; + + len = radius_xlat(buffer, sizeof(buffer), fmt, request, func); + if (!len) { + radlog(L_ERR, "rlm_expr: xlat failed."); + *out = '\0'; + return 0; + } + + p = buffer; + while ((len-- > 0) && (--freespace > 0)) { + if (isalnum(*p)) { + *out++ = *p++; + continue; + } + + switch (*p) { + case '-': + case '_': + case '.': + case '~': + *out++ = *p++; + break; + default: + if (freespace < 3) + break; + + snprintf(out, 4, "%%%02x", *p++); /* %xx */ + + /* Already decremented */ + freespace -= 2; + out += 3; + } + } + + *out = '\0'; + + return outlen - freespace; +} + +/** + * @brief Convert a string to lowercase + * + * Example "%{lc:Bar}" == "bar" + * + * Probably only works for ASCII + */ +static size_t lc_xlat(UNUSED void *instance, REQUEST *request, + const char *fmt, char *out, size_t outlen, + UNUSED RADIUS_ESCAPE_STRING func) +{ + char *p, *q; + char buffer[1024]; + + if (outlen <= 1) return 0; + + if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) { + *out = '\0'; + return 0; + } + + for (p = buffer, q = out; *p != '\0'; p++, outlen--) { + if (outlen <= 1) break; + + *(q++) = tolower((int) *p); + } + + *q = '\0'; + + return strlen(out); +} + +/** + * @brief Convert a string to uppercase + * + * Example: "%{uc:Foo}" == "FOO" + * + * Probably only works for ASCII + */ +static size_t uc_xlat(UNUSED void *instance, REQUEST *request, + const char *fmt, char *out, size_t outlen, + UNUSED RADIUS_ESCAPE_STRING func) +{ + char *p, *q; + char buffer[1024]; + + if (outlen <= 1) return 0; + + if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) { + *out = '\0'; + return 0; + } + + for (p = buffer, q = out; *p != '\0'; p++, outlen--) { + if (outlen <= 1) break; + + *(q++) = toupper((int) *p); + } + + *q = '\0'; + + return strlen(out); +} + +/** + * @brief Calculate the MD5 hash of a string. + * + * Example: "%{md5:foo}" == "acbd18db4cc2f85cedef654fccc4a4d8" + */ +static size_t md5_xlat(UNUSED void *instance, REQUEST *request, + const char *fmt, char *out, size_t outlen, + UNUSED RADIUS_ESCAPE_STRING func) +{ + char buffer[1024]; + uint8_t digest[16]; + int i; + FR_MD5_CTX ctx; + + if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) { + *out = '\0'; + return 0; + } + + fr_MD5Init(&ctx); + fr_MD5Update(&ctx, (void *) buffer, strlen(buffer)); + fr_MD5Final(digest, &ctx); + + if (outlen < 33) { + snprintf(out, outlen, "md5_overflow"); + return strlen(out); + } + + for (i = 0; i < 16; i++) { + snprintf(out + i * 2, 3, "%02x", digest[i]); + } + + return strlen(out); +} + /* * Do any per-module initialization that is separate to each * configured instance of the module. e.g. set up connections @@ -441,6 +598,10 @@ static int expr_instantiate(CONF_SECTION *conf, void **instance) xlat_register("rand", rand_xlat, inst); xlat_register("randstr", randstr_xlat, inst); + xlat_register("urlquote", urlquote_xlat, inst); + xlat_register("tolower", lc_xlat, inst); + xlat_register("toupper", uc_xlat, inst); + xlat_register("md5", md5_xlat, inst); /* * Initialize various paircompare functions -- 2.1.4