summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvenaas <venaas>2008-03-03 13:57:21 +0000
committervenaas <venaas@e88ac4ed-0b26-0410-9574-a7f39faa03bf>2008-03-03 13:57:21 +0000
commit1225cb37a7f22156fae9998882bcd561376ae7f0 (patch)
tree3c86ec408194c3fcc1c80e59e5981178e4be7dae
parent3f96acb665602773de20f9e03ca1cb44e4d82f0d (diff)
support for rewrite and fixing attr resize
git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@220 e88ac4ed-0b26-0410-9574-a7f39faa03bf
-rw-r--r--radsecproxy.c145
-rw-r--r--radsecproxy.h9
2 files changed, 146 insertions, 8 deletions
diff --git a/radsecproxy.c b/radsecproxy.c
index c0e5422..d7bf838 100644
--- a/radsecproxy.c
+++ b/radsecproxy.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Stig Venaas <venaas@uninett.no>
+ * Copyright (C) 2006-2008 Stig Venaas <venaas@uninett.no>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -56,7 +56,7 @@
#include "radsecproxy.h"
static struct options options;
-struct list *clconfs, *srvconfs, *realms, *tlsconfs;
+struct list *clconfs, *srvconfs, *realms, *tlsconfs, *rewriteconfs;
static int client_udp_count = 0;
static int client_tls_count = 0;
@@ -1377,6 +1377,28 @@ int msmppe(unsigned char *attrs, int length, uint8_t type, char *attrtxt, struct
return 1;
}
+void removeattrs(uint8_t *buf, uint8_t *rmattrs) {
+ uint8_t *attrs, alen;
+ uint16_t len, rmlen = 0;
+
+ if (!rmattrs)
+ return;
+
+ len = RADLEN(buf) - 20;
+ attrs = buf + 20;
+ while (len > 1) {
+ alen = ATTRLEN(attrs);
+ len -= alen;
+ if (strchr((char *)rmattrs, ATTRTYPE(attrs))) {
+ memmove(attrs, attrs + alen, len);
+ rmlen += alen;
+ } else
+ attrs += alen;
+ }
+ if (rmlen)
+ ((uint16_t *)buf)[1] = htons(RADLEN(buf) - rmlen);
+}
+
/* 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;
@@ -1396,7 +1418,7 @@ uint8_t *resizeattr(uint8_t **buf, uint8_t newvallen, uint8_t type) {
len += newvallen - vallen;
if (newvallen > vallen) {
- new = realloc(*buf, len);
+ new = realloc(*buf, len + 20);
if (!new) {
debug(DBG_ERR, "resizeattr: malloc failed");
return NULL;
@@ -1597,6 +1619,7 @@ void radsrv(struct request *rq) {
if (code != RAD_Access_Request) {
switch (code) {
case RAD_Accounting_Request:
+ /* when forwarding accounting, also filter attributes, call removeattrs(rq) */
acclog(attrs, len, rq->from->conf->host);
respondaccounting(rq);
break;
@@ -1609,6 +1632,11 @@ void radsrv(struct request *rq) {
}
/* code == RAD_Access_Request */
+ if (rq->from->conf->removeattrs) {
+ removeattrs(rq->buf, rq->from->conf->removeattrs);
+ len = RADLEN(rq->buf) - 20;
+ }
+
attr = attrget(attrs, len, RAD_Attr_User_Name);
if (!attr) {
debug(DBG_WARN, "radsrv: ignoring request, no username attribute");
@@ -1776,6 +1804,11 @@ int replyh(struct server *server, unsigned char *buf) {
return 0;
}
+ if (server->conf->removeattrs) {
+ removeattrs(buf, server->conf->removeattrs);
+ len = RADLEN(buf) - 20;
+ }
+
/* MS MPPE */
for (attr = attrs; (attr = attrget(attr, len - (attr - attrs), RAD_Attr_Vendor_Specific)); attr += ATTRLEN(attr)) {
if (ATTRVALLEN(attr) <= 4)
@@ -2526,8 +2559,81 @@ int addrewriteattr(struct clsrvconf *conf, char *rewriteattr) {
return 1;
}
+/* should accept both names and numeric values, only numeric right now */
+uint8_t attrname2val(char *attrname) {
+ int val = 0;
+
+ val = atoi(attrname);
+ return val > 0 && val < 256 ? val : 0;
+}
+
+void rewritefree() {
+ struct list_node *entry;
+ struct rewrite *r;
+
+ for (entry = list_first(rewriteconfs); entry; entry = list_next(entry)) {
+ r = (struct rewrite *)entry->data;
+ if (r->name)
+ free(r->name);
+ if (!r->count)
+ free(r->removeattrs);
+ }
+ list_destroy(rewriteconfs);
+ rewriteconfs = NULL;
+}
+
+uint8_t *getrewrite(char *alt1, char *alt2) {
+ struct list_node *entry;
+ struct rewrite *r, *r1 = NULL, *r2 = NULL;
+
+ for (entry = list_first(rewriteconfs); entry; entry = list_next(entry)) {
+ r = (struct rewrite *)entry->data;
+ if (!strcasecmp(r->name, alt1)) {
+ r1 = r;
+ break;
+ }
+ if (!r2 && alt2 && !strcasecmp(r->name, alt2))
+ r2 = r;
+ }
+
+ r = (r1 ? r1 : r2);
+ if (!r)
+ return NULL;
+ r->count++;
+ return r->removeattrs;
+}
+
+void addrewrite(char *value, char **attrs) {
+ struct rewrite *new;
+ int i, n;
+ uint8_t *a;
+
+ n = 0;
+ if (attrs)
+ for (; attrs[n]; n++);
+ a = malloc((n + 1) * sizeof(uint8_t));
+ if (!a)
+ 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]);
+ a[i] = 0;
+
+ new = malloc(sizeof(struct rewrite));
+ if (!new || !list_push(rewriteconfs, new))
+ debugx(1, DBG_ERR, "malloc failed");
+
+ memset(new, 0, sizeof(struct rewrite));
+ new->name = stringcopy(value, 0);
+ if (!new->name)
+ debugx(1, DBG_ERR, "malloc failed");
+ new->removeattrs = a;
+ debug(DBG_DBG, "addrewrite: added rewrite block %s", value);
+}
+
void confclient_cb(struct gconffile **cf, char *block, char *opt, char *val) {
- char *type = NULL, *tls = NULL, *matchcertattr = NULL, *rewriteattr = NULL;
+ char *type = NULL, *tls = NULL, *matchcertattr = NULL, *rewrite = NULL, *rewriteattr = NULL;
struct clsrvconf *conf;
debug(DBG_DBG, "confclient_cb called for %s", block);
@@ -2543,6 +2649,7 @@ void confclient_cb(struct gconffile **cf, char *block, char *opt, char *val) {
"secret", CONF_STR, &conf->secret,
"tls", CONF_STR, &tls,
"matchcertificateattribute", CONF_STR, &matchcertattr,
+ "rewrite", CONF_STR, &rewrite,
"rewriteattribute", CONF_STR, &rewriteattr,
NULL
);
@@ -2569,6 +2676,8 @@ void confclient_cb(struct gconffile **cf, char *block, char *opt, char *val) {
free(tls);
if (matchcertattr)
free(matchcertattr);
+
+ conf->removeattrs = rewrite ? getrewrite(rewrite, NULL) : getrewrite("defaultclient", "default");
if (rewriteattr) {
if (!addrewriteattr(conf, rewriteattr))
@@ -2587,7 +2696,7 @@ void confclient_cb(struct gconffile **cf, char *block, char *opt, char *val) {
}
void confserver_cb(struct gconffile **cf, char *block, char *opt, char *val) {
- char *type = NULL, *tls = NULL, *matchcertattr = NULL, *statusserver = NULL;
+ char *type = NULL, *tls = NULL, *matchcertattr = NULL, *statusserver = NULL, *rewrite = NULL;
struct clsrvconf *conf;
debug(DBG_DBG, "confserver_cb called for %s", block);
@@ -2604,6 +2713,7 @@ void confserver_cb(struct gconffile **cf, char *block, char *opt, char *val) {
"secret", CONF_STR, &conf->secret,
"tls", CONF_STR, &tls,
"matchcertificateattribute", CONF_STR, &matchcertattr,
+ "rewrite", CONF_STR, &rewrite,
"StatusServer", CONF_STR, &statusserver,
NULL
);
@@ -2635,6 +2745,8 @@ void confserver_cb(struct gconffile **cf, char *block, char *opt, char *val) {
if (matchcertattr)
free(matchcertattr);
+ conf->removeattrs = rewrite ? getrewrite(rewrite, NULL) : getrewrite("defaultserver", "default");
+
if (!resolvepeer(conf, 0))
debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)");
@@ -2690,6 +2802,19 @@ void conftls_cb(struct gconffile **cf, char *block, char *opt, char *val) {
free(certkeypwd);
}
+void confrewrite_cb(struct gconffile **cf, char *block, char *opt, char *val) {
+ char **attrs = NULL;
+
+ debug(DBG_DBG, "confrewrite_cb called for %s", block);
+
+ getgenericconfig(cf, block,
+ "removeAttribute", CONF_MSTR, &attrs,
+ NULL
+ );
+ addrewrite(val, attrs);
+ free(attrs);
+}
+
void getmainconfig(const char *configfile) {
char *loglevel = NULL;
struct gconffile *cfs;
@@ -2712,7 +2837,11 @@ void getmainconfig(const char *configfile) {
tlsconfs = list_create();
if (!tlsconfs)
debugx(1, DBG_ERR, "malloc failed");
-
+
+ rewriteconfs = list_create();
+ if (!rewriteconfs)
+ debugx(1, DBG_ERR, "malloc failed");
+
getgenericconfig(&cfs, NULL,
"ListenUDP", CONF_STR, &options.listenudp,
"ListenTCP", CONF_STR, &options.listentcp,
@@ -2725,11 +2854,13 @@ void getmainconfig(const char *configfile) {
"Server", CONF_CBK, confserver_cb,
"Realm", CONF_CBK, confrealm_cb,
"TLS", CONF_CBK, conftls_cb,
+ "Rewrite", CONF_CBK, confrewrite_cb,
NULL
);
popgconffile(&cfs);
tlsfree();
-
+ rewritefree();
+
if (loglevel) {
if (strlen(loglevel) != 1 || *loglevel < '1' || *loglevel > '4')
debugx(1, DBG_ERR, "error in %s, value of option LogLevel is %s, must be 1, 2, 3 or 4", configfile, loglevel);
diff --git a/radsecproxy.h b/radsecproxy.h
index ee321f8..9400a6f 100644
--- a/radsecproxy.h
+++ b/radsecproxy.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Stig Venaas <venaas@uninett.no>
+ * Copyright (C) 2006-2008 Stig Venaas <venaas@uninett.no>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -84,6 +84,7 @@ struct clsrvconf {
char *rewriteattrreplacement;
uint8_t statusserver;
SSL_CTX *ssl_ctx;
+ uint8_t *removeattrs;
struct addrinfo *addrinfo;
uint8_t prefixlen;
struct list *clients;
@@ -126,6 +127,12 @@ struct tls {
int count;
};
+struct rewrite {
+ char *name;
+ uint8_t *removeattrs;
+ int count;
+};
+
#define RADLEN(x) ntohs(((uint16_t *)(x))[1])
#define ATTRTYPE(x) ((x)[0])