summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--list.c39
-rw-r--r--list.h3
-rw-r--r--radmsg.c51
-rw-r--r--radmsg.h5
-rw-r--r--radsecproxy.c18
6 files changed, 102 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 0e24da7..3bbefa3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -19,6 +19,8 @@ Changes between 1.6.2 and the master branch
Mauchle.
- Timing out on TLS clients not closing the connection properly.
Patch by Fabian Mauchle.
+ - Keeping Proxy-State attributes in all replies to clients
+ (RADSECPROXY-52). Reported by Stefan Winter.
2012-10-25 1.6.2
Bug fixes (security):
diff --git a/list.c b/list.c
index 0a193ef..d9612b8 100644
--- a/list.c
+++ b/list.c
@@ -5,29 +5,46 @@
#include <string.h>
#include "list.h"
-/* allocates and initialises list structure; returns NULL if malloc fails */
-struct list *list_create() {
- struct list *list = malloc(sizeof(struct list));
- if (list)
- memset(list, 0, sizeof(struct list));
- return list;
-}
-
-/* frees all memory associated with the list */
-void list_destroy(struct list *list) {
+/* Private helper functions. */
+static void list_free_helper_(struct list *list, int free_data_flag) {
struct list_node *node, *next;
if (!list)
return;
for (node = list->first; node; node = next) {
- free(node->data);
+ if (free_data_flag)
+ free(node->data);
next = node->next;
free(node);
}
free(list);
}
+/* Public functions. */
+
+/* allocates and initialises list structure; returns NULL if malloc fails */
+struct list *list_create() {
+ struct list *list = malloc(sizeof(struct list));
+ if (list)
+ memset(list, 0, sizeof(struct list));
+ return list;
+}
+
+/* frees all memory associated with the list
+ note that the data pointed at from each node is also freed
+ use list_free() to free only the memory used by the list itself */
+void list_destroy(struct list *list) {
+ list_free_helper_(list, 1);
+}
+
+/* frees the meory used by the list itself
+ note that the data pointed at from each node is not freed
+ use list_destroy() to free all the data associated with the list */
+void list_free(struct list *list) {
+ list_free_helper_(list, 0);
+}
+
/* appends entry to list; returns 1 if ok, 0 if malloc fails */
int list_push(struct list *list, void *data) {
struct list_node *node;
diff --git a/list.h b/list.h
index d9c5199..38169c7 100644
--- a/list.h
+++ b/list.h
@@ -23,6 +23,9 @@ struct list *list_create();
/* frees all memory associated with the list */
void list_destroy(struct list *list);
+/* frees memory allocated for the list itself */
+void list_free(struct list *list);
+
/* appends entry to list; returns 1 if ok, 0 if malloc fails */
int list_push(struct list *list, void *data);
diff --git a/radmsg.c b/radmsg.c
index 432f88d..0289bba 100644
--- a/radmsg.c
+++ b/radmsg.c
@@ -57,6 +57,30 @@ int radmsg_add(struct radmsg *msg, struct tlv *attr) {
return list_push(msg->attrs, attr);
}
+/** Return a new list with all tlv's in \a msg of type \a type. The
+ * caller is responsible for freeing the list by calling \a
+ * list_free(). */
+struct list *
+radmsg_getalltype(const struct radmsg *msg, uint8_t type)
+{
+ struct list *list = NULL;
+ struct list_node *node = NULL;
+
+ if (!msg || !msg->attrs)
+ return NULL;
+ list = list_create();
+ if (!list)
+ return NULL;
+
+ for (node = list_first(msg->attrs); node; node = list_next(node))
+ if (((struct tlv *) node->data)->t == type)
+ if (list_push(list, node->data) != 1) {
+ list_free(list);
+ return NULL;
+ }
+ return list;
+}
+
/* returns first tlv of the given type */
struct tlv *radmsg_gettype(struct radmsg *msg, uint8_t type) {
struct list_node *node;
@@ -72,6 +96,33 @@ struct tlv *radmsg_gettype(struct radmsg *msg, uint8_t type) {
return NULL;
}
+/** Copy all attributes of type \a type from \a src to \a dst.
+ *
+ * If all attributes were copied successfully, the number of
+ * attributes copied is returned.
+ *
+ * If copying failed, a negative number is returned. The number
+ * returned is 0 minus the number of attributes successfully copied
+ * before the failure. */
+int radmsg_copy_attrs(struct radmsg *dst,
+ const struct radmsg *src,
+ uint8_t type)
+{
+ struct list_node *node = NULL;
+ struct list *list = radmsg_getalltype(src, type);
+ int n = 0;
+
+ for (node = list_first(list); node; node = list_next(node)) {
+ if (radmsg_add(dst, (struct tlv *) node->data) != 1) {
+ n = -n;
+ break;
+ }
+ n++;
+ }
+ list_free(list);
+ return n;
+}
+
int _checkmsgauth(unsigned char *rad, uint8_t *authattr, uint8_t *secret) {
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static unsigned char first = 1;
diff --git a/radmsg.h b/radmsg.h
index 1bef59b..7cfcc75 100644
--- a/radmsg.h
+++ b/radmsg.h
@@ -15,6 +15,7 @@
#define RAD_Attr_Reply_Message 18
#define RAD_Attr_Vendor_Specific 26
#define RAD_Attr_Calling_Station_Id 31
+#define RAD_Proxy_State 33
#define RAD_Attr_Tunnel_Password 69
#define RAD_Attr_Message_Authenticator 80
@@ -32,6 +33,10 @@ void radmsg_free(struct radmsg *);
struct radmsg *radmsg_init(uint8_t, uint8_t, uint8_t *);
int radmsg_add(struct radmsg *, struct tlv *);
struct tlv *radmsg_gettype(struct radmsg *, uint8_t);
+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 *radmsg2buf(struct radmsg *msg, uint8_t *);
struct radmsg *buf2radmsg(uint8_t *, uint8_t *, uint8_t *);
diff --git a/radsecproxy.c b/radsecproxy.c
index 5dfe241..563c4a8 100644
--- a/radsecproxy.c
+++ b/radsecproxy.c
@@ -1274,7 +1274,9 @@ void acclog(struct radmsg *msg, struct client *from) {
}
}
-void respond(struct request *rq, uint8_t code, char *message) {
+void respond(struct request *rq, uint8_t code, char *message,
+ int copy_proxystate_flag)
+{
struct radmsg *msg;
struct tlv *attr;
@@ -1292,6 +1294,12 @@ void respond(struct request *rq, uint8_t code, char *message) {
return;
}
}
+ if (copy_proxystate_flag) {
+ if (radmsg_copy_attrs(msg, rq->msg, RAD_Proxy_State) < 0) {
+ debug(DBG_ERR, "%s: unable to copy all Proxy-State attributes",
+ __func__);
+ }
+ }
radmsg_free(rq->msg);
rq->msg = msg;
@@ -1461,7 +1469,7 @@ int radsrv(struct request *rq) {
goto exit;
if (msg->code == RAD_Status_Server) {
- respond(rq, RAD_Access_Accept, NULL);
+ respond(rq, RAD_Access_Accept, NULL, 0);
goto exit;
}
@@ -1480,7 +1488,7 @@ int radsrv(struct request *rq) {
if (!attr) {
if (msg->code == RAD_Accounting_Request) {
acclog(msg, from);
- respond(rq, RAD_Accounting_Response, NULL);
+ respond(rq, RAD_Accounting_Response, NULL, 1);
} else
debug(DBG_INFO, "radsrv: ignoring access request, no username attribute");
goto exit;
@@ -1506,10 +1514,10 @@ int radsrv(struct request *rq) {
if (!to) {
if (realm->message && msg->code == RAD_Access_Request) {
debug(DBG_INFO, "radsrv: sending reject to %s (%s) for %s", from->conf->name, addr2string(from->addr), userascii);
- respond(rq, RAD_Access_Reject, realm->message);
+ respond(rq, RAD_Access_Reject, realm->message, 1);
} else if (realm->accresp && msg->code == RAD_Accounting_Request) {
acclog(msg, from);
- respond(rq, RAD_Accounting_Response, NULL);
+ respond(rq, RAD_Accounting_Response, NULL, 1);
}
goto exit;
}