Commit c791194c authored by venaas's avatar venaas Committed by venaas

added reject support

git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@111 e88ac4ed-0b26-0410-9574-a7f39faa03bf
parent edb4444b
...@@ -995,15 +995,14 @@ int msmppdecrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen, ...@@ -995,15 +995,14 @@ int msmppdecrypt(uint8_t *text, uint8_t len, uint8_t *shared, uint8_t sharedlen,
return 1; return 1;
} }
int id2server(struct server **server, char *id, uint8_t len) { struct realm *id2realm(char *id, uint8_t len) {
int i; int i;
for (i = 0; i < realm_count; i++) for (i = 0; i < realm_count; i++)
if (!regexec(&realms[i].regex, id, 0, NULL, 0)) { if (!regexec(&realms[i].regex, id, 0, NULL, 0)) {
debug(DBG_DBG, "found matching realm: %s, host %s", realms[i].name, realms[i].server->peer.host); debug(DBG_DBG, "found matching realm: %s", realms[i].name);
*server = realms[i].server; return realms + i;
return 1;
} }
return 0; return NULL;
} }
int rqinqueue(struct server *to, struct client *from, uint8_t id) { int rqinqueue(struct server *to, struct client *from, uint8_t id) {
...@@ -1104,18 +1103,26 @@ void respondstatusserver(struct request *rq) { ...@@ -1104,18 +1103,26 @@ void respondstatusserver(struct request *rq) {
sendreply(rq->from, resp, rq->from->peer.type == 'U' ? &rq->fromsa : NULL); sendreply(rq->from, resp, rq->from->peer.type == 'U' ? &rq->fromsa : NULL);
} }
void respondreject(struct request *rq) { void respondreject(struct request *rq, char *message) {
unsigned char *resp; unsigned char *resp;
int len = 20;
resp = malloc(20); if (message)
len += 2 + strlen(message);
resp = malloc(len);
if (!resp) { if (!resp) {
debug(DBG_ERR, "respondreject: malloc failed"); debug(DBG_ERR, "respondreject: malloc failed");
return; return;
} }
memcpy(resp, rq->buf, 20); memcpy(resp, rq->buf, 20);
resp[0] = RAD_Access_Reject; resp[0] = RAD_Access_Reject;
resp[2] = 0; *(uint16_t *)(resp + 2) = htons(len);
resp[3] = 20; if (message) {
resp[20] = RAD_Attr_Reply_Message;
resp[21] = len - 20;
memcpy(resp + 22, message, len - 22);
}
sendreply(rq->from, resp, rq->from->peer.type == 'U' ? &rq->fromsa : NULL); sendreply(rq->from, resp, rq->from->peer.type == 'U' ? &rq->fromsa : NULL);
} }
...@@ -1125,7 +1132,8 @@ void radsrv(struct request *rq) { ...@@ -1125,7 +1132,8 @@ void radsrv(struct request *rq) {
struct server *to = NULL; struct server *to = NULL;
char username[256]; char username[256];
unsigned char *buf, newauth[16]; unsigned char *buf, newauth[16];
struct realm *realm = NULL;
buf = rq->buf; buf = rq->buf;
code = *(uint8_t *)buf; code = *(uint8_t *)buf;
id = *(uint8_t *)(buf + 1); id = *(uint8_t *)(buf + 1);
...@@ -1159,12 +1167,14 @@ void radsrv(struct request *rq) { ...@@ -1159,12 +1167,14 @@ void radsrv(struct request *rq) {
memcpy(username, ATTRVAL(attr), ATTRVALLEN(attr)); memcpy(username, ATTRVAL(attr), ATTRVALLEN(attr));
username[ATTRVALLEN(attr)] = '\0'; username[ATTRVALLEN(attr)] = '\0';
debug(DBG_DBG, "Access Request with username: %s", username); debug(DBG_DBG, "Access Request with username: %s", username);
if (!id2server(&to, username, strlen(username))) { realm = id2realm(username, strlen(username));
if (!realm) {
debug(DBG_INFO, "radsrv: ignoring request, don't know where to send it"); debug(DBG_INFO, "radsrv: ignoring request, don't know where to send it");
free(buf); free(buf);
return; return;
} }
to = realm->server;
if (to && rqinqueue(to, rq->from, id)) { if (to && rqinqueue(to, rq->from, id)) {
debug(DBG_INFO, "radsrv: already got request from host %s with id %d, ignoring", rq->from->peer.host, id); debug(DBG_INFO, "radsrv: already got request from host %s with id %d, ignoring", rq->from->peer.host, id);
...@@ -1187,7 +1197,7 @@ void radsrv(struct request *rq) { ...@@ -1187,7 +1197,7 @@ void radsrv(struct request *rq) {
if (!to) { if (!to) {
debug(DBG_INFO, "radsrv: sending reject to %s for %s", rq->from->peer.host, username); debug(DBG_INFO, "radsrv: sending reject to %s for %s", rq->from->peer.host, username);
respondreject(rq); respondreject(rq, realm->message);
return; return;
} }
...@@ -1707,7 +1717,7 @@ int tlslistener() { ...@@ -1707,7 +1717,7 @@ int tlslistener() {
return 0; return 0;
} }
void addrealm(char *value, char *server) { void addrealm(char *value, char *server, char *message) {
int i, n; int i, n;
struct realm *realm; struct realm *realm;
char *s, *regex = NULL; char *s, *regex = NULL;
...@@ -1754,6 +1764,9 @@ void addrealm(char *value, char *server) { ...@@ -1754,6 +1764,9 @@ void addrealm(char *value, char *server) {
realm->name = stringcopy(value, 0); realm->name = stringcopy(value, 0);
if (!realm->name) if (!realm->name)
debugx(1, DBG_ERR, "malloc failed"); debugx(1, DBG_ERR, "malloc failed");
if (message && strlen(message) > 253)
debugx(1, DBG_ERR, "ReplyMessage can be at most 253 bytes");
realm->message = message;
if (server) if (server)
realm->server = servers + i; realm->server = servers + i;
if (regcomp(&realm->regex, regex ? regex : value + 1, REG_ICASE | REG_NOSUB)) if (regcomp(&realm->regex, regex ? regex : value + 1, REG_ICASE | REG_NOSUB))
...@@ -2109,7 +2122,7 @@ void confclsrv_cb(FILE *f, char *opt, char *val) { ...@@ -2109,7 +2122,7 @@ void confclsrv_cb(FILE *f, char *opt, char *val) {
} }
void confrealm_cb(FILE *f, char *opt, char *val) { void confrealm_cb(FILE *f, char *opt, char *val) {
char *server = NULL; char *server = NULL, *msg = NULL;
char *block; char *block;
block = malloc(strlen(opt) + strlen(val) + 2); block = malloc(strlen(opt) + strlen(val) + 2);
...@@ -2120,13 +2133,11 @@ void confrealm_cb(FILE *f, char *opt, char *val) { ...@@ -2120,13 +2133,11 @@ void confrealm_cb(FILE *f, char *opt, char *val) {
getgeneralconfig(f, block, getgeneralconfig(f, block,
"server", CONF_STR, &server, "server", CONF_STR, &server,
"ReplyMessage", CONF_STR, &msg,
NULL NULL
); );
#if 0
if (!server) addrealm(val, server, msg);
debugx(1, DBG_ERR, "error in block %s, server must be specified", block);
#endif
addrealm(val, server);
free(server); free(server);
free(block); free(block);
} }
......
...@@ -79,8 +79,14 @@ server radius.example.com { ...@@ -79,8 +79,14 @@ server radius.example.com {
realm /@example\.com$ { realm /@example\.com$ {
server 2001:db8::1 server 2001:db8::1
} }
# One can define a realm without servers, the proxy will then reject
# and requests matching this. Optionally one can specify ReplyMessage
# attribute to be included in the reject message.
#
realm /\.com$ { realm /\.com$ {
server 2001:db8::1 }
realm /^anonymous$ {
replymessage "No Access"
} }
# The realm below is equivalent to /.* # The realm below is equivalent to /.*
realm * { realm * {
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#define RAD_Attr_User_Name 1 #define RAD_Attr_User_Name 1
#define RAD_Attr_User_Password 2 #define RAD_Attr_User_Password 2
#define RAD_Attr_Reply_Message 18
#define RAD_Attr_Vendor_Specific 26 #define RAD_Attr_Vendor_Specific 26
#define RAD_Attr_Tunnel_Password 69 #define RAD_Attr_Tunnel_Password 69
#define RAD_Attr_Message_Authenticator 80 #define RAD_Attr_Message_Authenticator 80
...@@ -111,6 +112,7 @@ struct server { ...@@ -111,6 +112,7 @@ struct server {
struct realm { struct realm {
char *name; char *name;
char *message;
regex_t regex; regex_t regex;
struct server *server; struct server *server;
}; };
......
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