Commit 506b4eea authored by Linus Nordberg's avatar Linus Nordberg

Keep Proxy-State attributes in all replies to clients.

Closes RADSECPROXY-52.
parent b1a17ab1
2013-09-05 1.6.4
Bug fixes:
- Keeping Proxy-State attributes in all replies to clients
(RADSECPROXY-52). Reported by Stefan Winter.
2013-09-05 1.6.3 2013-09-05 1.6.3
Enhancements: Enhancements:
- Threads are allocated with a 32 KB stack rather than what - Threads are allocated with a 32 KB stack rather than what
......
...@@ -10,29 +10,46 @@ ...@@ -10,29 +10,46 @@
#include <string.h> #include <string.h>
#include "list.h" #include "list.h"
/* allocates and initialises list structure; returns NULL if malloc fails */ /* Private helper functions. */
struct list *list_create() { static void list_free_helper_(struct list *list, int free_data_flag) {
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) {
struct list_node *node, *next; struct list_node *node, *next;
if (!list) if (!list)
return; return;
for (node = list->first; node; node = next) { for (node = list->first; node; node = next) {
free(node->data); if (free_data_flag)
free(node->data);
next = node->next; next = node->next;
free(node); free(node);
} }
free(list); 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 */ /* appends entry to list; returns 1 if ok, 0 if malloc fails */
int list_push(struct list *list, void *data) { int list_push(struct list *list, void *data) {
struct list_node *node; struct list_node *node;
......
...@@ -28,6 +28,9 @@ struct list *list_create(); ...@@ -28,6 +28,9 @@ struct list *list_create();
/* frees all memory associated with the list */ /* frees all memory associated with the list */
void list_destroy(struct list *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 */ /* appends entry to list; returns 1 if ok, 0 if malloc fails */
int list_push(struct list *list, void *data); int list_push(struct list *list, void *data);
......
...@@ -62,6 +62,30 @@ int radmsg_add(struct radmsg *msg, struct tlv *attr) { ...@@ -62,6 +62,30 @@ int radmsg_add(struct radmsg *msg, struct tlv *attr) {
return list_push(msg->attrs, 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 */ /* returns first tlv of the given type */
struct tlv *radmsg_gettype(struct radmsg *msg, uint8_t type) { struct tlv *radmsg_gettype(struct radmsg *msg, uint8_t type) {
struct list_node *node; struct list_node *node;
...@@ -77,6 +101,33 @@ struct tlv *radmsg_gettype(struct radmsg *msg, uint8_t type) { ...@@ -77,6 +101,33 @@ struct tlv *radmsg_gettype(struct radmsg *msg, uint8_t type) {
return NULL; 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) { int _checkmsgauth(unsigned char *rad, uint8_t *authattr, uint8_t *secret) {
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static unsigned char first = 1; static unsigned char first = 1;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#define RAD_Attr_Reply_Message 18 #define RAD_Attr_Reply_Message 18
#define RAD_Attr_Vendor_Specific 26 #define RAD_Attr_Vendor_Specific 26
#define RAD_Attr_Calling_Station_Id 31 #define RAD_Attr_Calling_Station_Id 31
#define RAD_Proxy_State 33
#define RAD_Attr_Tunnel_Password 69 #define RAD_Attr_Tunnel_Password 69
#define RAD_Attr_Message_Authenticator 80 #define RAD_Attr_Message_Authenticator 80
...@@ -37,6 +38,10 @@ void radmsg_free(struct radmsg *); ...@@ -37,6 +38,10 @@ void radmsg_free(struct radmsg *);
struct radmsg *radmsg_init(uint8_t, uint8_t, uint8_t *); struct radmsg *radmsg_init(uint8_t, uint8_t, uint8_t *);
int radmsg_add(struct radmsg *, struct tlv *); int radmsg_add(struct radmsg *, struct tlv *);
struct tlv *radmsg_gettype(struct radmsg *, uint8_t); 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 *); uint8_t *radmsg2buf(struct radmsg *msg, uint8_t *);
struct radmsg *buf2radmsg(uint8_t *, uint8_t *, uint8_t *); struct radmsg *buf2radmsg(uint8_t *, uint8_t *, uint8_t *);
......
...@@ -1287,7 +1287,9 @@ void acclog(struct radmsg *msg, struct client *from) { ...@@ -1287,7 +1287,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 radmsg *msg;
struct tlv *attr; struct tlv *attr;
...@@ -1305,6 +1307,12 @@ void respond(struct request *rq, uint8_t code, char *message) { ...@@ -1305,6 +1307,12 @@ void respond(struct request *rq, uint8_t code, char *message) {
return; 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); radmsg_free(rq->msg);
rq->msg = msg; rq->msg = msg;
...@@ -1474,7 +1482,7 @@ int radsrv(struct request *rq) { ...@@ -1474,7 +1482,7 @@ int radsrv(struct request *rq) {
goto exit; goto exit;
if (msg->code == RAD_Status_Server) { if (msg->code == RAD_Status_Server) {
respond(rq, RAD_Access_Accept, NULL); respond(rq, RAD_Access_Accept, NULL, 0);
goto exit; goto exit;
} }
...@@ -1493,7 +1501,7 @@ int radsrv(struct request *rq) { ...@@ -1493,7 +1501,7 @@ int radsrv(struct request *rq) {
if (!attr) { if (!attr) {
if (msg->code == RAD_Accounting_Request) { if (msg->code == RAD_Accounting_Request) {
acclog(msg, from); acclog(msg, from);
respond(rq, RAD_Accounting_Response, NULL); respond(rq, RAD_Accounting_Response, NULL, 1);
} else } else
debug(DBG_INFO, "radsrv: ignoring access request, no username attribute"); debug(DBG_INFO, "radsrv: ignoring access request, no username attribute");
goto exit; goto exit;
...@@ -1519,10 +1527,10 @@ int radsrv(struct request *rq) { ...@@ -1519,10 +1527,10 @@ int radsrv(struct request *rq) {
if (!to) { if (!to) {
if (realm->message && msg->code == RAD_Access_Request) { 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); 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) { } else if (realm->accresp && msg->code == RAD_Accounting_Request) {
acclog(msg, from); acclog(msg, from);
respond(rq, RAD_Accounting_Response, NULL); respond(rq, RAD_Accounting_Response, NULL, 1);
} }
goto exit; goto exit;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment