/*
* Error functions.
*/
-#ifdef _LIBRADIUS
void fr_strerror_printf(const char *, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 1, 2)))
#endif
;
-#endif
void fr_perror(const char *, ...)
#ifdef __GNUC__
__attribute__ ((format (printf, 1, 2)))
#include <freeradius-devel/stats.h>
#include <freeradius-devel/realms.h>
+typedef struct radclient_list RADCLIENT_LIST;
+
+#include <freeradius-devel/smodule.h>
+
/*
* See util.c
#endif
} RADCLIENT;
-/*
- * Types of listeners.
- *
- * Ordered by priority!
- */
-typedef enum RAD_LISTEN_TYPE {
- RAD_LISTEN_NONE = 0,
-#ifdef WITH_PROXY
- RAD_LISTEN_PROXY,
-#endif
- RAD_LISTEN_AUTH,
-#ifdef WITH_ACCOUNTING
- RAD_LISTEN_ACCT,
-#endif
-#ifdef WITH_DETAIL
- RAD_LISTEN_DETAIL,
-#endif
-#ifdef WITH_VMPS
- RAD_LISTEN_VQP,
-#endif
-#ifdef WITH_DHCP
- RAD_LISTEN_DHCP,
-#endif
-#ifdef WITH_COMMAND_SOCKET
- RAD_LISTEN_COMMAND,
-#endif
- RAD_LISTEN_MAX
-} RAD_LISTEN_TYPE;
-
/*
* For listening on multiple IP's and ports.
*/
-typedef struct rad_listen_t rad_listen_t;
typedef void (*radlog_func_t)(int, int, REQUEST *, const char *, ...);
#define REQUEST_DATA_REGEX (0xadbeef00)
const char *server;
REQUEST *parent;
radlog_func_t radlog; /* logging function, if set */
+ RAD_REQUEST_FUNP process;
}; /* REQUEST typedef */
#define RAD_REQUEST_OPTION_NONE (0)
#define REQUEST_CLEANUP_DELAY (5)
#define REQUEST_DONE (6)
-/*
- * Function handler for requests.
- */
-typedef int (*RAD_REQUEST_FUNP)(REQUEST *);
-
-typedef struct radclient_list RADCLIENT_LIST;
-
typedef struct pair_list {
const char *name;
VALUE_PAIR *check;
struct pair_list *lastdefault;
} PAIR_LIST;
-
-typedef int (*rad_listen_recv_t)(rad_listen_t *, RAD_REQUEST_FUNP *, REQUEST **);
-typedef int (*rad_listen_send_t)(rad_listen_t *, REQUEST *);
-typedef int (*rad_listen_print_t)(rad_listen_t *, char *, size_t);
-typedef int (*rad_listen_encode_t)(rad_listen_t *, REQUEST *);
-typedef int (*rad_listen_decode_t)(rad_listen_t *, REQUEST *);
-
-struct rad_listen_t {
- struct rad_listen_t *next; /* should be rbtree stuff */
-
- /*
- * For normal sockets.
- */
- RAD_LISTEN_TYPE type;
- int fd;
- const char *server;
- int status;
-
- rad_listen_recv_t recv;
- rad_listen_send_t send;
- rad_listen_encode_t encode;
- rad_listen_decode_t decode;
- rad_listen_print_t print;
-
- void *data;
-
-#ifdef WITH_STATS
- fr_stats_t stats;
-#endif
-};
-
-#define RAD_LISTEN_STATUS_INIT (0)
-#define RAD_LISTEN_STATUS_KNOWN (1)
-#define RAD_LISTEN_STATUS_CLOSED (2)
-#define RAD_LISTEN_STATUS_FINISH (3)
-
typedef enum radlog_dest_t {
RADLOG_STDOUT = 0,
RADLOG_FILES,
* Function prototypes.
*/
-/* acct.c */
-int rad_accounting(REQUEST *);
-
/* session.c */
int rad_check_ts(uint32_t nasaddr, unsigned int port, const char *user,
const char *sessionid);
/* auth.c */
char *auth_name(char *buf, size_t buflen, REQUEST *request, int do_cli);
-int rad_authenticate (REQUEST *);
int rad_postauth(REQUEST *);
/* exec.c */
rad_listen_t *proxy_new_listener(void);
RADCLIENT *client_listener_find(const rad_listen_t *listener,
const fr_ipaddr_t *ipaddr, int src_port);
-#ifdef WITH_STATS
-RADCLIENT_LIST *listener_find_client_list(const fr_ipaddr_t *ipaddr,
- int port);
-rad_listen_t *listener_find_byipaddr(const fr_ipaddr_t *ipaddr, int port);
-#endif
/* event.c */
int radius_event_init(CONF_SECTION *cs, int spawn_flag);
--- /dev/null
+/*
+ * smodule.h Interface to the server-side module system.
+ *
+ * Version: $Id$
+ *
+ */
+
+#ifndef FR_SMODULE_H
+#define FR_SMODULE_H
+
+#include <freeradius-devel/ident.h>
+RCSIDH(smodules_h, "$Id$")
+
+typedef struct rad_listen_t rad_listen_t;
+typedef int (*RAD_REQUEST_FUNP)(REQUEST *);
+typedef int (*rad_listen_recv_t)(rad_listen_t *, RAD_REQUEST_FUNP *, REQUEST **);
+typedef int (*rad_listen_send_t)(rad_listen_t *, REQUEST *);
+typedef int (*rad_listen_print_t)(rad_listen_t *, char *, size_t);
+typedef int (*rad_listen_encode_t)(rad_listen_t *, REQUEST *);
+typedef int (*rad_listen_decode_t)(rad_listen_t *, REQUEST *);
+typedef int (*rad_listen_parse_t)(CONF_SECTION *, rad_listen_t *);
+typedef void (*rad_listen_free_t)(rad_listen_t *);
+
+/*
+ * Types of listeners.
+ *
+ * Ordered by priority!
+ */
+typedef enum RAD_LISTEN_TYPE {
+ RAD_LISTEN_NONE = 0,
+#ifdef WITH_PROXY
+ RAD_LISTEN_PROXY,
+#endif
+ RAD_LISTEN_AUTH,
+#ifdef WITH_ACCOUNTING
+ RAD_LISTEN_ACCT,
+#endif
+#ifdef WITH_DETAIL
+ RAD_LISTEN_DETAIL,
+#endif
+#ifdef WITH_VMPS
+ RAD_LISTEN_VQP,
+#endif
+#ifdef WITH_DHCP
+ RAD_LISTEN_DHCP,
+#endif
+#ifdef WITH_COMMAND_SOCKET
+ RAD_LISTEN_COMMAND,
+#endif
+ RAD_LISTEN_MAX
+} RAD_LISTEN_TYPE;
+
+
+struct rad_listen_t {
+ struct rad_listen_t *next; /* should be rbtree stuff */
+
+ /*
+ * For normal sockets.
+ */
+ RAD_LISTEN_TYPE type;
+ int fd;
+ const char *server;
+ int status;
+
+ const struct frs_module_t *frs;
+ rad_listen_recv_t recv;
+ rad_listen_send_t send;
+ rad_listen_encode_t encode;
+ rad_listen_decode_t decode;
+ rad_listen_print_t print;
+
+ void *data;
+
+#ifdef WITH_STATS
+ fr_stats_t stats;
+#endif
+};
+
+#define RAD_LISTEN_STATUS_INIT (0)
+#define RAD_LISTEN_STATUS_KNOWN (1)
+#define RAD_LISTEN_STATUS_CLOSED (2)
+#define RAD_LISTEN_STATUS_FINISH (3)
+
+#define FRS_MODULE_MAGIC_NUMBER ((uint32_t) (0xf5ee4ad2))
+#define FRS_MODULE_INIT FRS_MODULE_MAGIC_NUMBER
+
+typedef struct frs_module_t {
+ uint32_t magic;
+ RAD_LISTEN_TYPE type;
+ /*
+ * FIXME: Add flag for TCP sockets
+ */
+ const char *name;
+ rad_listen_parse_t parse;
+ rad_listen_free_t free;
+ rad_listen_recv_t recv;
+ rad_listen_send_t send;
+ rad_listen_print_t print;
+ rad_listen_encode_t encode;
+ rad_listen_decode_t decode;
+} frs_module_t;
+
+extern rad_listen_t *listen_alloc(const char *name);
+extern int listen_socket_parse(CONF_SECTION *cs, rad_listen_t *this);
+
+/*
+ * FIXME: This should be done in the "parse" routine,
+ * and it should allocated a fixed buffer..
+ */
+extern int listen_socket_print(rad_listen_t *this,
+ char *buffer, size_t bufsize);
+
+extern int rad_status_server(REQUEST *request);
+
+/*
+ * This is pretty bad.
+ */
+typedef struct listen_socket_t {
+ /*
+ * For normal sockets.
+ */
+ fr_ipaddr_t ipaddr;
+ int port;
+#ifdef SO_BINDTODEVICE
+ const char *interface;
+#endif
+ RADCLIENT_LIST *clients;
+} listen_socket_t;
+
+#endif /* FR_SMODULE_H */
extern fr_stats_t proxy_acct_stats;
#endif
+extern struct timeval radius_start_time;
+extern struct timeval radius_hup_time;
+
void radius_stats_init(int flag);
void request_stats_final(REQUEST *request);
-void request_stats_reply(REQUEST *request);
void radius_stats_ema(fr_stats_ema_t *ema,
struct timeval *start, struct timeval *end);
+#define EMA_SCALE (100)
#define RAD_STATS_INC(_x) _x++
#ifdef WITH_ACCOUNTING
+++ /dev/null
-#ifndef VMPS_H
-#define VMPS_H
-/*
- * vmps.h Routines to handle VMPS sockets.
- *
- * Version: $Id$
- *
- */
-
-#include <freeradius-devel/ident.h>
-RCSIDH(vmps_h, "$Id$")
-
-int vqp_socket_recv(rad_listen_t *listener,
- RAD_REQUEST_FUNP *pfun, REQUEST **prequest);
-int vqp_socket_send(rad_listen_t *listener, REQUEST *request);
-int vqp_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request);
-int vqp_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request);
-int vmps_process(REQUEST *request);
-
-#endif /* VMPS_H */
SRCS = dict.c filters.c hash.c hmac.c hmacsha1.c isaac.c log.c \
misc.c missing.c md4.c md5.c print.c radius.c rbtree.c \
sha1.c snprintf.c strlcat.c strlcpy.c token.c udpfromto.c \
- valuepair.c fifo.c packet.c event.c getaddrinfo.c vqp.c \
- heap.c dhcp.c
+ valuepair.c fifo.c packet.c event.c getaddrinfo.c \
+ heap.c
LT_OBJS = $(SRCS:.c=.lo)
include ../../Make.inc
-SERVER_SRCS = acct.c auth.c client.c conffile.c crypt.c exec.c files.c \
+SERVER_SRCS = auth.c client.c conffile.c crypt.c exec.c files.c \
listen.c log.c mainconfig.c modules.c modcall.c \
radiusd.c stats.c \
session.c threads.c util.c valuepair.c version.c \
- xlat.c event.c realms.c evaluate.c vmps.c detail.c
+ xlat.c event.c realms.c evaluate.c
SERVER_OBJS += $(SERVER_SRCS:.c=.lo)
%.lo: %.c
$(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c $<
-acct.lo: acct.c ../include/modules.h
- $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c acct.c
-
auth.lo: auth.c ../include/modules.h
$(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c auth.c
session.lo: session.c ../include/modules.h
$(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c session.c
-# It's #include'd for simplicity. This should be fixed...
-listen.lo: dhcpd.c command.c
- $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(INCLTDL) -c listen.c
-
#
# Helper programs
#
}
-
-/*
- * Make sure user/pass are clean
- * and then log them
- */
-static int rad_authlog(const char *msg, REQUEST *request, int goodpass) {
-
- char clean_password[1024];
- char clean_username[1024];
- char buf[1024];
- VALUE_PAIR *username = NULL;
-
- if (!request->root->log_auth) {
- return 0;
- }
-
- /*
- * Get the correct username based on the configured value
- */
- if (log_stripped_names == 0) {
- username = pairfind(request->packet->vps, PW_USER_NAME);
- } else {
- username = request->username;
- }
-
- /*
- * Clean up the username
- */
- if (username == NULL) {
- strcpy(clean_username, "<no User-Name attribute>");
- } else {
- fr_print_string((char *)username->vp_strvalue,
- username->length,
- clean_username, sizeof(clean_username));
- }
-
- /*
- * Clean up the password
- */
- if (request->root->log_auth_badpass || request->root->log_auth_goodpass) {
- if (!request->password) {
- VALUE_PAIR *auth_type;
-
- auth_type = pairfind(request->config_items,
- PW_AUTH_TYPE);
- if (auth_type && (auth_type->vp_strvalue[0] != '\0')) {
- snprintf(clean_password, sizeof(clean_password),
- "<via Auth-Type = %s>",
- auth_type->vp_strvalue);
- } else {
- strcpy(clean_password, "<no User-Password attribute>");
- }
- } else if (pairfind(request->packet->vps, PW_CHAP_PASSWORD)) {
- strcpy(clean_password, "<CHAP-Password>");
- } else {
- fr_print_string((char *)request->password->vp_strvalue,
- request->password->length,
- clean_password, sizeof(clean_password));
- }
- }
-
- if (goodpass) {
- radlog_request(L_AUTH, 0, request, "%s: [%s%s%s] (%s)",
- msg,
- clean_username,
- request->root->log_auth_goodpass ? "/" : "",
- request->root->log_auth_goodpass ? clean_password : "",
- auth_name(buf, sizeof(buf), request, 1));
- } else {
- radlog_request(L_AUTH, 0, request, "%s: [%s%s%s] (%s)",
- msg,
- clean_username,
- request->root->log_auth_badpass ? "/" : "",
- request->root->log_auth_badpass ? clean_password : "",
- auth_name(buf, sizeof(buf), request, 1));
- }
-
- return 0;
-}
-
-/*
- * Check password.
- *
- * Returns: 0 OK
- * -1 Password fail
- * -2 Rejected (Auth-Type = Reject, send Port-Message back)
- * 1 End check & return, don't reply
- *
- * NOTE: NOT the same as the RLM_ values !
- */
-static int rad_check_password(REQUEST *request)
-{
- VALUE_PAIR *auth_type_pair;
- VALUE_PAIR *cur_config_item;
- VALUE_PAIR *password_pair;
- VALUE_PAIR *auth_item;
- uint8_t my_chap[MAX_STRING_LEN];
- int auth_type = -1;
- int result;
- int auth_type_count = 0;
- result = 0;
-
- /*
- * Look for matching check items. We skip the whole lot
- * if the authentication type is PW_AUTHTYPE_ACCEPT or
- * PW_AUTHTYPE_REJECT.
- */
- cur_config_item = request->config_items;
- while(((auth_type_pair = pairfind(cur_config_item, PW_AUTH_TYPE))) != NULL) {
- auth_type = auth_type_pair->vp_integer;
- auth_type_count++;
- DICT_VALUE *dv = dict_valbyattr(auth_type_pair->attribute,
- auth_type_pair->vp_integer);
-
- RDEBUG2("Found Auth-Type = %s",
- (dv != NULL) ? dv->name : "?");
- cur_config_item = auth_type_pair->next;
-
- if (auth_type == PW_AUTHTYPE_REJECT) {
- RDEBUG2("Auth-Type = Reject, rejecting user");
- return -2;
- }
- }
-
- if (( auth_type_count > 1) && (debug_flag)) {
- radlog_request(L_ERR, 0, request, "Warning: Found %d auth-types on request for user '%s'",
- auth_type_count, request->username->vp_strvalue);
- }
-
- /*
- * This means we have a proxy reply or an accept
- * and it wasn't rejected in the above loop. So
- * that means it is accepted and we do no further
- * authentication
- */
- if ((auth_type == PW_AUTHTYPE_ACCEPT)
-#ifdef WITH_PROXY
- || (request->proxy)
-#endif
- ) {
- RDEBUG2("Auth-Type = Accept, accepting the user");
- return 0;
- }
-
- password_pair = pairfind(request->config_items, PW_USER_PASSWORD);
- if (password_pair &&
- pairfind(request->config_items, PW_CLEARTEXT_PASSWORD)) {
- pairdelete(&request->config_items, PW_USER_PASSWORD);
- password_pair = NULL;
- }
-
- if (password_pair) {
- DICT_ATTR *da;
-
- RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
- RDEBUG("!!! Replacing User-Password in config items with Cleartext-Password. !!!");
- RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
- RDEBUG("!!! Please update your configuration so that the \"known good\" !!!");
- RDEBUG("!!! clear text password is in Cleartext-Password, and not in User-Password. !!!");
- RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
- password_pair->attribute = PW_CLEARTEXT_PASSWORD;
- da = dict_attrbyvalue(PW_CLEARTEXT_PASSWORD);
- if (!da) {
- radlog_request(L_ERR, 0, request, "FATAL: You broke the dictionaries. Please use the default dictionaries!");
- _exit(1);
- }
-
- password_pair->name = da->name;
- }
-
- /*
- * Find the "known good" password.
- *
- * FIXME: We should get rid of these hacks, and replace
- * them with a module.
- */
- if ((password_pair = pairfind(request->config_items, PW_CRYPT_PASSWORD)) != NULL) {
- /*
- * Re-write Auth-Type, but ONLY if it isn't already
- * set.
- */
- if (auth_type == -1) auth_type = PW_AUTHTYPE_CRYPT;
- } else {
- password_pair = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD);
- }
-
- if (auth_type < 0) {
- if (password_pair) {
- auth_type = PW_AUTHTYPE_LOCAL;
- } else {
- /*
- * The admin hasn't told us how to
- * authenticate the user, so we reject them!
- *
- * This is fail-safe.
- */
- RDEBUG2("No authenticate method (Auth-Type) configuration found for the request: Rejecting the user");
- return -2;
- }
- }
-
- switch(auth_type) {
- case PW_AUTHTYPE_CRYPT:
- RDEBUG2("WARNING: Please update your configuration, and remove 'Auth-Type = Crypt'");
- RDEBUG2("WARNING: Use the PAP module instead.");
-
- /*
- * Find the password sent by the user. It
- * SHOULD be there, if it's not
- * authentication fails.
- */
- auth_item = request->password;
- if (auth_item == NULL) {
- RDEBUG2("No User-Password or CHAP-Password attribute in the request");
- return -1;
- }
-
- if (password_pair == NULL) {
- RDEBUG2("No Crypt-Password configured for the user");
- rad_authlog("Login incorrect "
- "(No Crypt-Password configured for the user)", request, 0);
- return -1;
- }
-
- switch (fr_crypt_check((char *)auth_item->vp_strvalue,
- (char *)password_pair->vp_strvalue)) {
- case -1:
- rad_authlog("Login incorrect "
- "(system failed to supply an encrypted password for comparison)", request, 0);
- case 1:
- return -1;
- }
- break;
- case PW_AUTHTYPE_LOCAL:
- RDEBUG2("WARNING: Please update your configuration, and remove 'Auth-Type = Local'");
- RDEBUG2("WARNING: Use the PAP or CHAP modules instead.");
-
- /*
- * Find the password sent by the user. It
- * SHOULD be there, if it's not
- * authentication fails.
- */
- auth_item = request->password;
- if (!auth_item)
- auth_item = pairfind(request->packet->vps,
- PW_CHAP_PASSWORD);
- if (!auth_item) {
- RDEBUG2("No User-Password or CHAP-Password attribute in the request.");
- RDEBUG2("Cannot perform authentication.");
- return -1;
- }
-
- /*
- * Plain text password.
- */
- if (password_pair == NULL) {
- RDEBUG2("No \"known good\" password was configured for the user.");
- RDEBUG2("As a result, we cannot authenticate the user.");
- rad_authlog("Login incorrect "
- "(No password configured for the user)", request, 0);
- return -1;
- }
-
- /*
- * Local password is just plain text.
- */
- if (auth_item->attribute == PW_USER_PASSWORD) {
- if (strcmp((char *)password_pair->vp_strvalue,
- (char *)auth_item->vp_strvalue) != 0) {
- RDEBUG2("User-Password in the request does NOT match \"known good\" password.");
- return -1;
- }
- RDEBUG2("User-Password in the request is correct.");
- break;
-
- } else if (auth_item->attribute != PW_CHAP_PASSWORD) {
- RDEBUG2("The user did not supply a User-Password or a CHAP-Password attribute");
- rad_authlog("Login incorrect "
- "(no User-Password or CHAP-Password attribute)", request, 0);
- return -1;
- }
-
- rad_chap_encode(request->packet, my_chap,
- auth_item->vp_octets[0], password_pair);
-
- /*
- * Compare them
- */
- if (memcmp(my_chap + 1, auth_item->vp_strvalue + 1,
- CHAP_VALUE_LENGTH) != 0) {
- RDEBUG2("CHAP-Password is incorrect.");
- return -1;
- }
- RDEBUG2("CHAP-Password is correct.");
- break;
- default:
- /*
- * See if there is a module that handles
- * this type, and turn the RLM_ return
- * status into the values as defined at
- * the top of this function.
- */
- result = module_authenticate(auth_type, request);
- switch (result) {
- /*
- * An authentication module FAIL
- * return code, or any return code that
- * is not expected from authentication,
- * is the same as an explicit REJECT!
- */
- case RLM_MODULE_FAIL:
- case RLM_MODULE_INVALID:
- case RLM_MODULE_NOOP:
- case RLM_MODULE_NOTFOUND:
- case RLM_MODULE_REJECT:
- case RLM_MODULE_UPDATED:
- case RLM_MODULE_USERLOCK:
- default:
- result = -1;
- break;
- case RLM_MODULE_OK:
- result = 0;
- break;
- case RLM_MODULE_HANDLED:
- result = 1;
- break;
- }
- break;
- }
-
- return result;
-}
-
/*
* Post-authentication step processes the response before it is
* sent to the NAS. It can receive both Access-Accept and Access-Reject
}
return result;
}
-
-/*
- * Process and reply to an authentication request
- *
- * The return value of this function isn't actually used right now, so
- * it's not entirely clear if it is returning the right things. --Pac.
- */
-int rad_authenticate(REQUEST *request)
-{
- VALUE_PAIR *namepair;
-#ifdef WITH_SESSION_MGMT
- VALUE_PAIR *check_item;
-#endif
- VALUE_PAIR *auth_item = NULL;
- VALUE_PAIR *module_msg;
- VALUE_PAIR *tmp = NULL;
- int result;
- const char *password;
- char autz_retry = 0;
- int autz_type = 0;
-
- password = "";
-
-#ifdef WITH_PROXY
- /*
- * If this request got proxied to another server, we need
- * to check whether it authenticated the request or not.
- */
- if (request->proxy_reply) {
- switch (request->proxy_reply->code) {
- /*
- * Reply of ACCEPT means accept, thus set Auth-Type
- * accordingly.
- */
- case PW_AUTHENTICATION_ACK:
- tmp = radius_paircreate(request,
- &request->config_items,
- PW_AUTH_TYPE, PW_TYPE_INTEGER);
- if (tmp) tmp->vp_integer = PW_AUTHTYPE_ACCEPT;
- goto authenticate;
-
- /*
- * Challenges are punted back to the NAS without any
- * further processing.
- */
- case PW_ACCESS_CHALLENGE:
- request->reply->code = PW_ACCESS_CHALLENGE;
- return RLM_MODULE_OK;
- /*
- * ALL other replies mean reject. (this is fail-safe)
- *
- * Do NOT do any authorization or authentication. They
- * are being rejected, so we minimize the amount of work
- * done by the server, by rejecting them here.
- */
- case PW_AUTHENTICATION_REJECT:
- default:
- rad_authlog("Login incorrect (Home Server says so)",
- request, 0);
- request->reply->code = PW_AUTHENTICATION_REJECT;
- return RLM_MODULE_REJECT;
- }
- }
-#endif
-
- /*
- * Get the username from the request.
- *
- * Note that namepair MAY be NULL, in which case there
- * is no User-Name attribute in the request.
- */
- namepair = request->username;
-
- /*
- * Look for, and cache, passwords.
- */
- if (!request->password) {
- request->password = pairfind(request->packet->vps,
- PW_USER_PASSWORD);
- }
-
- /*
- * Discover which password we want to use.
- */
- auth_item = request->password;
- if (auth_item) {
- password = (const char *)auth_item->vp_strvalue;
-
- } else {
- /*
- * Maybe there's a CHAP-Password?
- */
- if ((auth_item = pairfind(request->packet->vps,
- PW_CHAP_PASSWORD)) != NULL) {
- password = "<CHAP-PASSWORD>";
-
- } else {
- /*
- * No password we recognize.
- */
- password = "<NO-PASSWORD>";
- }
- }
- request->password = auth_item;
-
- /*
- * Get the user's authorization information from the database
- */
-autz_redo:
- result = module_authorize(autz_type, request);
- switch (result) {
- case RLM_MODULE_NOOP:
- case RLM_MODULE_NOTFOUND:
- case RLM_MODULE_OK:
- case RLM_MODULE_UPDATED:
- break;
- case RLM_MODULE_HANDLED:
- return result;
- case RLM_MODULE_FAIL:
- case RLM_MODULE_INVALID:
- case RLM_MODULE_REJECT:
- case RLM_MODULE_USERLOCK:
- default:
- if ((module_msg = pairfind(request->packet->vps,
- PW_MODULE_FAILURE_MESSAGE)) != NULL) {
- char msg[MAX_STRING_LEN + 16];
- snprintf(msg, sizeof(msg), "Invalid user (%s)",
- module_msg->vp_strvalue);
- rad_authlog(msg,request,0);
- } else {
- rad_authlog("Invalid user", request, 0);
- }
- request->reply->code = PW_AUTHENTICATION_REJECT;
- return result;
- }
- if (!autz_retry) {
- tmp = pairfind(request->config_items, PW_AUTZ_TYPE);
- if (tmp) {
- RDEBUG2("Using Autz-Type %s", tmp->vp_strvalue);
- autz_type = tmp->vp_integer;
- autz_retry = 1;
- goto autz_redo;
- }
- }
-
- /*
- * If we haven't already proxied the packet, then check
- * to see if we should. Maybe one of the authorize
- * modules has decided that a proxy should be used. If
- * so, get out of here and send the packet.
- */
- if (
-#ifdef WITH_PROXY
- (request->proxy == NULL) &&
-#endif
- ((tmp = pairfind(request->config_items, PW_PROXY_TO_REALM)) != NULL)) {
- REALM *realm;
-
- realm = realm_find2(tmp->vp_strvalue);
-
- /*
- * Don't authenticate, as the request is going to
- * be proxied.
- */
- if (realm && realm->auth_pool) {
- return RLM_MODULE_OK;
- }
-
- /*
- * Catch users who set Proxy-To-Realm to a LOCAL
- * realm (sigh). But don't complain if it is
- * *the* LOCAL realm.
- */
- if (realm &&(strcmp(realm->name, "LOCAL") != 0)) {
- RDEBUG2("WARNING: You set Proxy-To-Realm = %s, but it is a LOCAL realm! Cancelling proxy request.", realm->name);
- }
-
- if (!realm) {
- RDEBUG2("WARNING: You set Proxy-To-Realm = %s, but the realm does not exist! Cancelling invalid proxy request.", tmp->vp_strvalue);
- }
- }
-
-#ifdef WITH_PROXY
- authenticate:
-#endif
-
- /*
- * Perhaps there is a Stripped-User-Name now.
- */
- namepair = request->username;
-
- /*
- * Validate the user
- */
- do {
- result = rad_check_password(request);
- if (result > 0) {
- /* don't reply! */
- return RLM_MODULE_HANDLED;
- }
- } while(0);
-
- /*
- * Failed to validate the user.
- *
- * We PRESUME that the code which failed will clean up
- * request->reply->vps, to be ONLY the reply items it
- * wants to send back.
- */
- if (result < 0) {
- RDEBUG2("Failed to authenticate the user.");
- request->reply->code = PW_AUTHENTICATION_REJECT;
-
- if ((module_msg = pairfind(request->packet->vps,PW_MODULE_FAILURE_MESSAGE)) != NULL){
- char msg[MAX_STRING_LEN+19];
-
- snprintf(msg, sizeof(msg), "Login incorrect (%s)",
- module_msg->vp_strvalue);
- rad_authlog(msg, request, 0);
- } else {
- rad_authlog("Login incorrect", request, 0);
- }
-
- /* double check: maybe the secret is wrong? */
- if ((debug_flag > 1) && (auth_item != NULL) &&
- (auth_item->attribute == PW_USER_PASSWORD)) {
- char *p;
-
- p = auth_item->vp_strvalue;
- while (*p != '\0') {
- if (!isprint((int) *p)) {
- log_debug(" WARNING: Unprintable characters in the password.\n\t Double-check the shared secret on the server and the NAS!");
- break;
- }
- p++;
- }
- }
- }
-
-#ifdef WITH_SESSION_MGMT
- if (result >= 0 &&
- (check_item = pairfind(request->config_items, PW_SIMULTANEOUS_USE)) != NULL) {
- int r, session_type = 0;
- char logstr[1024];
- char umsg[MAX_STRING_LEN + 1];
- const char *user_msg = NULL;
-
- tmp = pairfind(request->config_items, PW_SESSION_TYPE);
- if (tmp) {
- RDEBUG2("Using Session-Type %s", tmp->vp_strvalue);
- session_type = tmp->vp_integer;
- }
-
- /*
- * User authenticated O.K. Now we have to check
- * for the Simultaneous-Use parameter.
- */
- if (namepair &&
- (r = module_checksimul(session_type, request, check_item->vp_integer)) != 0) {
- char mpp_ok = 0;
-
- if (r == 2){
- /* Multilink attempt. Check if port-limit > simultaneous-use */
- VALUE_PAIR *port_limit;
-
- if ((port_limit = pairfind(request->reply->vps, PW_PORT_LIMIT)) != NULL &&
- port_limit->vp_integer > check_item->vp_integer){
- RDEBUG2("MPP is OK");
- mpp_ok = 1;
- }
- }
- if (!mpp_ok){
- if (check_item->vp_integer > 1) {
- snprintf(umsg, sizeof(umsg),
- "\r\nYou are already logged in %d times - access denied\r\n\n",
- (int)check_item->vp_integer);
- user_msg = umsg;
- } else {
- user_msg = "\r\nYou are already logged in - access denied\r\n\n";
- }
-
- request->reply->code = PW_AUTHENTICATION_REJECT;
-
- /*
- * They're trying to log in too many times.
- * Remove ALL reply attributes.
- */
- pairfree(&request->reply->vps);
- radius_pairmake(request, &request->reply->vps,
- "Reply-Message",
- user_msg, T_OP_SET);
-
- snprintf(logstr, sizeof(logstr), "Multiple logins (max %d) %s",
- check_item->vp_integer,
- r == 2 ? "[MPP attempt]" : "");
- rad_authlog(logstr, request, 1);
-
- result = -1;
- }
- }
- }
-#endif
-
- /*
- * Result should be >= 0 here - if not, it means the user
- * is rejected, so we just process post-auth and return.
- */
- if (result < 0) {
- return RLM_MODULE_REJECT;
- }
-
- /*
- * Add the port number to the Framed-IP-Address if
- * vp->addport is set.
- */
- if (((tmp = pairfind(request->reply->vps,
- PW_FRAMED_IP_ADDRESS)) != NULL) &&
- (tmp->flags.addport != 0)) {
- VALUE_PAIR *vpPortId;
-
- /*
- * Find the NAS port ID.
- */
- if ((vpPortId = pairfind(request->packet->vps,
- PW_NAS_PORT)) != NULL) {
- unsigned long tvalue = ntohl(tmp->vp_integer);
- tmp->vp_integer = htonl(tvalue + vpPortId->vp_integer);
- tmp->flags.addport = 0;
- ip_ntoa(tmp->vp_strvalue, tmp->vp_integer);
- } else {
- RDEBUG2("WARNING: No NAS-Port attribute in request. CANNOT return a Framed-IP-Address + NAS-Port.\n");
- pairdelete(&request->reply->vps, PW_FRAMED_IP_ADDRESS);
- }
- }
-
- /*
- * Set the reply to Access-Accept, if it hasn't already
- * been set to something. (i.e. Access-Challenge)
- */
- if (request->reply->code == 0)
- request->reply->code = PW_AUTHENTICATION_ACK;
-
- if ((module_msg = pairfind(request->packet->vps,PW_MODULE_SUCCESS_MESSAGE)) != NULL){
- char msg[MAX_STRING_LEN+12];
-
- snprintf(msg, sizeof(msg), "Login OK (%s)",
- module_msg->vp_strvalue);
- rad_authlog(msg, request, 1);
- } else {
- rad_authlog("Login OK", request, 1);
- }
-
- /*
- * Run the modules in the 'post-auth' section.
- */
- result = rad_postauth(request);
-
- return result;
-}
#define PTHREAD_MUTEX_UNLOCK(_x)
int thread_pool_addrequest(REQUEST *request, RAD_REQUEST_FUNP fun)
{
+ request->process = fun;
radius_handle_request(request, fun);
return 1;
}
const fr_ipaddr_t *ip;
int port;
- if (!packet) return;
+ if (!packet || (packet->code == 0)) return;
if (direction == 0) {
received = "Received";
static int proxy_to_virtual_server(REQUEST *request)
{
REQUEST *fake;
- RAD_REQUEST_FUNP fun;
if (!request->home_server || !request->home_server->server) return 0;
fake->packet->vps = paircopy(request->proxy->vps);
fake->server = request->home_server->server;
- if (request->proxy->code == PW_AUTHENTICATION_REQUEST) {
- fun = rad_authenticate;
-
+ if ((request->proxy->code != PW_AUTHENTICATION_REQUEST)
#ifdef WITH_ACCOUNTING
- } else if (request->proxy->code == PW_ACCOUNTING_REQUEST) {
- fun = rad_accounting;
+ && (request->proxy->code == PW_ACCOUNTING_REQUEST)
#endif
-
- } else {
+ ) {
RDEBUG2("Unknown packet type %d", request->proxy->code);
return 0;
}
+ rad_assert(request->process != NULL);
+
RDEBUG2(">>> Sending proxied request internally to virtual server.");
- radius_handle_request(fake, fun);
+ radius_handle_request(fake, request->process);
RDEBUG2("<<< Received proxied response from internal virtual server.");
request->proxy_reply = fake->reply;
request_free(&fake);
process_proxy_reply(request);
- fun(request);
+
+ /*
+ * And do all of this again...
+ */
+ request->process(request);
return 2; /* success, but NOT '1' !*/
}
break;
}
- /*
- * Suppress "no reply" packets here, unless we're reading
- * from the "detail" file. In that case, we've got to
- * tell the detail file handler that the request is dead,
- * and it should re-send it.
- * If configured, encode, sign, and send.
- */
- if ((request->reply->code != 0) ||
- (request->listener->type == RAD_LISTEN_DETAIL)) {
- DEBUG_PACKET(request, request->reply, 1);
- request->listener->send(request->listener, request);
- }
+ DEBUG_PACKET(request, request->reply, 1);
+ request->listener->send(request->listener, request);
/*
* Clean up. These are no longer needed.
home_server *home;
REQUEST *request;
- if (!home_server_find(&packet->src_ipaddr, packet->src_port)) {
- radlog(L_ERR, "Ignoring request from unknown home server %s port %d",
- inet_ntop(packet->src_ipaddr.af,
- &packet->src_ipaddr.ipaddr,
- buffer, sizeof(buffer)),
- packet->src_port);
- rad_free(&packet);
- return NULL;
- }
-
/*
* Also removes from the proxy hash if responses == requests
*/
if (this->type != RAD_LISTEN_DETAIL) continue;
- delay = detail_delay(this);
+ /*
+ * FIXME: HORRIBLE hack! We really need
+ * a separate callback for this!
+ */
+ delay = this->encode(this, NULL);
if (!delay) continue;
fr_event_now(el, &now);
#include <freeradius-devel/radiusd.h>
#include <freeradius-devel/modules.h>
+#include <freeradius-devel/modpriv.h>
#include <freeradius-devel/rad_assert.h>
-#include <freeradius-devel/vqp.h>
-#include <freeradius-devel/dhcp.h>
-
-#include <freeradius-devel/vmps.h>
-#include <freeradius-devel/detail.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#include <fcntl.h>
#endif
-
-/*
- * We'll use this below.
- */
-typedef int (*rad_listen_parse_t)(CONF_SECTION *, rad_listen_t *);
-typedef void (*rad_listen_free_t)(rad_listen_t *);
-
-typedef struct rad_listen_master_t {
- rad_listen_parse_t parse;
- rad_listen_free_t free;
- rad_listen_recv_t recv;
- rad_listen_send_t send;
- rad_listen_print_t print;
- rad_listen_encode_t encode;
- rad_listen_decode_t decode;
-} rad_listen_master_t;
-
-typedef struct listen_socket_t {
- /*
- * For normal sockets.
- */
- fr_ipaddr_t ipaddr;
- int port;
-#ifdef SO_BINDTODEVICE
- const char *interface;
-#endif
- RADCLIENT_LIST *clients;
-} listen_socket_t;
-
-static rad_listen_t *listen_alloc(RAD_LISTEN_TYPE type);
-
/*
* Find a per-socket client.
*/
/*
- * Process and reply to a server-status request.
- * Like rad_authenticate and rad_accounting this should
- * live in it's own file but it's so small we don't bother.
+ * Process and reply to a server-status request. This function
+ * should likely live in it's own file but it's so small we don't
+ * bother.
*/
-static int rad_status_server(REQUEST *request)
+int rad_status_server(REQUEST *request)
{
int rcode = RLM_MODULE_OK;
DICT_VALUE *dval;
return 0;
}
-#ifdef WITH_STATS
- /*
- * Full statistics are available only on a statistics
- * socket.
- */
- if (request->listener->type == RAD_LISTEN_NONE) {
- request_stats_reply(request);
- }
-#endif
-
return 0;
}
-static int socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
+int listen_socket_print(rad_listen_t *this, char *buffer, size_t bufsize)
{
size_t len;
listen_socket_t *sock = this->data;
/*
* Parse an authentication or accounting socket.
*/
-static int common_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
+int listen_socket_parse(CONF_SECTION *cs, rad_listen_t *this)
{
int rcode;
int listen_port;
return 0;
}
-/*
- * Send an authentication response packet
- */
-static int auth_socket_send(rad_listen_t *listener, REQUEST *request)
-{
- rad_assert(request->listener == listener);
- rad_assert(listener->send == auth_socket_send);
-
- return rad_send(request->reply, request->packet,
- request->client->secret);
-}
-
-
-#ifdef WITH_ACCOUNTING
-/*
- * Send an accounting response packet (or not)
- */
-static int acct_socket_send(rad_listen_t *listener, REQUEST *request)
-{
- rad_assert(request->listener == listener);
- rad_assert(listener->send == acct_socket_send);
-
- /*
- * Accounting reject's are silently dropped.
- *
- * We do it here to avoid polluting the rest of the
- * code with this knowledge
- */
- if (request->reply->code == 0) return 0;
-
- return rad_send(request->reply, request->packet,
- request->client->secret);
-}
-#endif
-
-#ifdef WITH_PROXY
-/*
- * Send a packet to a home server.
- *
- * FIXME: have different code for proxy auth & acct!
- */
-static int proxy_socket_send(rad_listen_t *listener, REQUEST *request)
-{
- listen_socket_t *sock = listener->data;
-
- rad_assert(request->proxy_listener == listener);
- rad_assert(listener->send == proxy_socket_send);
-
- request->proxy->src_ipaddr = sock->ipaddr;
- request->proxy->src_port = sock->port;
-
- return rad_send(request->proxy, request->packet,
- request->home_server->secret);
-}
-#endif
-
-#ifdef WITH_STATS
-/*
- * Check if an incoming request is "ok"
- *
- * It takes packets, not requests. It sees if the packet looks
- * OK. If so, it does a number of sanity checks on it.
- */
-static int stats_socket_recv(rad_listen_t *listener,
- RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
-{
- ssize_t rcode;
- int code, src_port;
- RADIUS_PACKET *packet;
- RADCLIENT *client;
- fr_ipaddr_t src_ipaddr;
-
- rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
- if (rcode < 0) return 0;
-
- RAD_STATS_TYPE_INC(listener, total_requests);
-
- if (rcode < 20) { /* AUTH_HDR_LEN */
- RAD_STATS_TYPE_INC(listener, total_malformed_requests);
- return 0;
- }
-
- if ((client = client_listener_find(listener,
- &src_ipaddr, src_port)) == NULL) {
- rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_invalid_requests);
- return 0;
- }
-
- /*
- * We only understand Status-Server on this socket.
- */
- if (code != PW_STATUS_SERVER) {
- DEBUG("Ignoring packet code %d sent to Status-Server port",
- code);
- rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_unknown_types);
- RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
- return 0;
- }
-
- /*
- * Now that we've sanity checked everything, receive the
- * packet.
- */
- packet = rad_recv(listener->fd, 1); /* require message authenticator */
- if (!packet) {
- RAD_STATS_TYPE_INC(listener, total_malformed_requests);
- DEBUG("%s", fr_strerror());
- return 0;
- }
-
- if (!received_request(listener, packet, prequest, client)) {
- RAD_STATS_TYPE_INC(listener, total_packets_dropped);
- RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
- rad_free(&packet);
- return 0;
- }
-
- *pfun = rad_status_server;
- return 1;
-}
-#endif
-
-
-/*
- * Check if an incoming request is "ok"
- *
- * It takes packets, not requests. It sees if the packet looks
- * OK. If so, it does a number of sanity checks on it.
- */
-static int auth_socket_recv(rad_listen_t *listener,
- RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
-{
- ssize_t rcode;
- int code, src_port;
- RADIUS_PACKET *packet;
- RAD_REQUEST_FUNP fun = NULL;
- RADCLIENT *client;
- fr_ipaddr_t src_ipaddr;
-
- rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
- if (rcode < 0) return 0;
-
- RAD_STATS_TYPE_INC(listener, total_requests);
-
- if (rcode < 20) { /* AUTH_HDR_LEN */
- RAD_STATS_TYPE_INC(listener, total_malformed_requests);
- return 0;
- }
-
- if ((client = client_listener_find(listener,
- &src_ipaddr, src_port)) == NULL) {
- rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_invalid_requests);
- return 0;
- }
-
- /*
- * Some sanity checks, based on the packet code.
- */
- switch(code) {
- case PW_AUTHENTICATION_REQUEST:
- RAD_STATS_CLIENT_INC(listener, client, total_requests);
- fun = rad_authenticate;
- break;
-
- case PW_STATUS_SERVER:
- if (!mainconfig.status_server) {
- rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_packets_dropped);
- RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
- DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
- return 0;
- }
- fun = rad_status_server;
- break;
-
- default:
- rad_recv_discard(listener->fd);
- RAD_STATS_INC(radius_auth_stats.total_unknown_types);
- RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
-
- DEBUG("Invalid packet code %d sent to authentication port from client %s port %d : IGNORED",
- code, client->shortname, src_port);
- return 0;
- break;
- } /* switch over packet types */
-
- /*
- * Now that we've sanity checked everything, receive the
- * packet.
- */
- packet = rad_recv(listener->fd, client->message_authenticator);
- if (!packet) {
- RAD_STATS_TYPE_INC(listener, total_malformed_requests);
- DEBUG("%s", fr_strerror());
- return 0;
- }
-
- if (!received_request(listener, packet, prequest, client)) {
- RAD_STATS_TYPE_INC(listener, total_packets_dropped);
- RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
- rad_free(&packet);
- return 0;
- }
-
- *pfun = fun;
- return 1;
-}
-
-
-#ifdef WITH_ACCOUNTING
-/*
- * Receive packets from an accounting socket
- */
-static int acct_socket_recv(rad_listen_t *listener,
- RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
-{
- ssize_t rcode;
- int code, src_port;
- RADIUS_PACKET *packet;
- RAD_REQUEST_FUNP fun = NULL;
- RADCLIENT *client;
- fr_ipaddr_t src_ipaddr;
-
- rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
- if (rcode < 0) return 0;
-
- RAD_STATS_TYPE_INC(listener, total_requests);
-
- if (rcode < 20) { /* AUTH_HDR_LEN */
- RAD_STATS_TYPE_INC(listener, total_malformed_requests);
- return 0;
- }
-
- if ((client = client_listener_find(listener,
- &src_ipaddr, src_port)) == NULL) {
- rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_invalid_requests);
- return 0;
- }
-
- /*
- * Some sanity checks, based on the packet code.
- */
- switch(code) {
- case PW_ACCOUNTING_REQUEST:
- RAD_STATS_CLIENT_INC(listener, client, total_requests);
- fun = rad_accounting;
- break;
-
- case PW_STATUS_SERVER:
- if (!mainconfig.status_server) {
- rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_packets_dropped);
- RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
-
- DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
- return 0;
- }
- fun = rad_status_server;
- break;
-
- default:
- rad_recv_discard(listener->fd);
- RAD_STATS_TYPE_INC(listener, total_unknown_types);
- RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
-
- DEBUG("Invalid packet code %d sent to a accounting port from client %s port %d : IGNORED",
- code, client->shortname, src_port);
- return 0;
- } /* switch over packet types */
-
- /*
- * Now that we've sanity checked everything, receive the
- * packet.
- */
- packet = rad_recv(listener->fd, 0);
- if (!packet) {
- RAD_STATS_TYPE_INC(listener, total_malformed_requests);
- radlog(L_ERR, "%s", fr_strerror());
- return 0;
- }
-
- /*
- * There can be no duplicate accounting packets.
- */
- if (!received_request(listener, packet, prequest, client)) {
- RAD_STATS_TYPE_INC(listener, total_packets_dropped);
- RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
- rad_free(&packet);
- return 0;
- }
-
- *pfun = fun;
- return 1;
-}
-#endif
-
-#ifdef WITH_PROXY
-/*
- * Recieve packets from a proxy socket.
- */
-static int proxy_socket_recv(rad_listen_t *listener,
- RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
-{
- REQUEST *request;
- RADIUS_PACKET *packet;
- RAD_REQUEST_FUNP fun = NULL;
- char buffer[128];
-
- packet = rad_recv(listener->fd, 0);
- if (!packet) {
- radlog(L_ERR, "%s", fr_strerror());
- return 0;
- }
-
- /*
- * FIXME: Client MIB updates?
- */
- switch(packet->code) {
- case PW_AUTHENTICATION_ACK:
- case PW_ACCESS_CHALLENGE:
- case PW_AUTHENTICATION_REJECT:
- fun = rad_authenticate;
- break;
-
-#ifdef WITH_ACCOUNTING
- case PW_ACCOUNTING_RESPONSE:
- fun = rad_accounting;
- break;
-#endif
-
- default:
- /*
- * FIXME: Update MIB for packet types?
- */
- radlog(L_ERR, "Invalid packet code %d sent to a proxy port "
- "from home server %s port %d - ID %d : IGNORED",
- packet->code,
- ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
- packet->src_port, packet->id);
- rad_free(&packet);
- return 0;
- }
-
- request = received_proxy_response(packet);
- if (!request) {
- return 0;
- }
-
- rad_assert(fun != NULL);
- *pfun = fun;
- *prequest = request;
-
- return 1;
-}
-#endif
-
-
-static int client_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
-{
- if (!request->reply->code) return 0;
-
- rad_encode(request->reply, request->packet,
- request->client->secret);
- rad_sign(request->reply, request->packet,
- request->client->secret);
-
- return 0;
-}
-
-
-static int client_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
-{
- if (rad_verify(request->packet, NULL,
- request->client->secret) < 0) {
- return -1;
- }
-
- return rad_decode(request->packet, NULL,
- request->client->secret);
-}
-
-#ifdef WITH_PROXY
-static int proxy_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
-{
- rad_encode(request->proxy, NULL, request->home_server->secret);
- rad_sign(request->proxy, NULL, request->home_server->secret);
-
- return 0;
-}
-
-
-static int proxy_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
-{
- if (rad_verify(request->proxy_reply, request->proxy,
- request->home_server->secret) < 0) {
- return -1;
- }
-
- return rad_decode(request->proxy_reply, request->proxy,
- request->home_server->secret);
-}
-#endif
-
-#include "dhcpd.c"
-
-#include "command.c"
-
-static const rad_listen_master_t master_listen[RAD_LISTEN_MAX] = {
-#ifdef WITH_STATS
- { common_socket_parse, NULL,
- stats_socket_recv, auth_socket_send,
- socket_print, client_socket_encode, client_socket_decode },
-#else
- /*
- * This always gets defined.
- */
- { NULL, NULL, NULL, NULL, NULL, NULL, NULL}, /* RAD_LISTEN_NONE */
-#endif
-
-#ifdef WITH_PROXY
- /* proxying */
- { common_socket_parse, NULL,
- proxy_socket_recv, proxy_socket_send,
- socket_print, proxy_socket_encode, proxy_socket_decode },
-#endif
-
- /* authentication */
- { common_socket_parse, NULL,
- auth_socket_recv, auth_socket_send,
- socket_print, client_socket_encode, client_socket_decode },
-
-#ifdef WITH_ACCOUNTING
- /* accounting */
- { common_socket_parse, NULL,
- acct_socket_recv, acct_socket_send,
- socket_print, client_socket_encode, client_socket_decode},
-#endif
-
-#ifdef WITH_DETAIL
- /* detail */
- { detail_parse, detail_free,
- detail_recv, detail_send,
- detail_print, detail_encode, detail_decode },
-#endif
-
-#ifdef WITH_VMPS
- /* vlan query protocol */
- { common_socket_parse, NULL,
- vqp_socket_recv, vqp_socket_send,
- socket_print, vqp_socket_encode, vqp_socket_decode },
-#endif
-
-#ifdef WITH_DHCP
- /* dhcp query protocol */
- { dhcp_socket_parse, NULL,
- dhcp_socket_recv, dhcp_socket_send,
- socket_print, dhcp_socket_encode, dhcp_socket_decode },
-#endif
-
-#ifdef WITH_COMMAND_SOCKET
- /* TCP command socket */
- { command_socket_parse, NULL,
- command_domain_accept, command_domain_send,
- command_socket_print, command_socket_encode, command_socket_decode },
-#endif
-
-};
-
-
/*
* Binds a listener to a socket.
/*
* Allocate & initialize a new listener.
*/
-static rad_listen_t *listen_alloc(RAD_LISTEN_TYPE type)
+rad_listen_t *listen_alloc(const char *type_name)
{
rad_listen_t *this;
+ const frs_module_t *frs;
+ lt_dlhandle handle;
+ char buffer[256];
this = rad_malloc(sizeof(*this));
memset(this, 0, sizeof(*this));
- this->type = type;
- this->recv = master_listen[this->type].recv;
- this->send = master_listen[this->type].send;
- this->print = master_listen[this->type].print;
- this->encode = master_listen[this->type].encode;
- this->decode = master_listen[this->type].decode;
+ snprintf(buffer, sizeof(buffer), "frs_%s", type_name);
+
+ handle = lt_dlopenext(buffer);
+ if (!handle) {
+ radlog(L_ERR, "Failed opening %s: %s",
+ type_name, lt_dlerror());
+ return NULL;
+ }
+
+ frs = lt_dlsym(handle, buffer);
+ if (!frs) {
+ radlog(L_ERR, "Failed linking to %s: %s",
+ type_name, lt_dlerror());
+ return NULL;
+ }
+
+ if (frs->magic != FRS_MODULE_MAGIC_NUMBER) {
+ radlog(L_ERR, "Invalid version in %s\n",
+ type_name);
+ return NULL;
+ }
+
+ /*
+ * FIXME: handle is leaked.
+ */
+
+ this->type = frs->type;
+ this->frs = frs;
+ this->recv = frs->recv;
+ this->send = frs->send;
+ this->print = frs->print;
+ this->encode = frs->encode;
+ this->decode = frs->decode;
- switch (type) {
+ switch (this->type) {
#ifdef WITH_STATS
case RAD_LISTEN_NONE:
#endif
#endif
#ifdef WITH_COMMAND_SOCKET
+ /*
+ * The data here is allocate in the "parse" section.
+ */
case RAD_LISTEN_COMMAND:
- this->data = rad_malloc(sizeof(fr_command_socket_t));
- memset(this->data, 0, sizeof(fr_command_socket_t));
break;
#endif
rad_listen_t *this, *tmp, **last;
listen_socket_t *sock, *old;
- this = listen_alloc(RAD_LISTEN_PROXY);
+ this = listen_alloc("proxy");
+ if (!this) return NULL;
/*
* Find an existing proxy socket to copy.
}
#endif
-static const FR_NAME_NUMBER listen_compare[] = {
-#ifdef WITH_STATS
- { "status", RAD_LISTEN_NONE },
-#endif
- { "auth", RAD_LISTEN_AUTH },
-#ifdef WITH_ACCOUNTING
- { "acct", RAD_LISTEN_ACCT },
-#endif
-#ifdef WITH_DETAIL
- { "detail", RAD_LISTEN_DETAIL },
-#endif
-#ifdef WITH_PROXY
- { "proxy", RAD_LISTEN_PROXY },
-#endif
-#ifdef WITH_VMPS
- { "vmps", RAD_LISTEN_VQP },
-#endif
-#ifdef WITH_DHCP
- { "dhcp", RAD_LISTEN_DHCP },
-#endif
-#ifdef WITH_COMMAND_SOCKET
- { "control", RAD_LISTEN_COMMAND },
-#endif
- { NULL, 0 },
-};
-
static rad_listen_t *listen_parse(CONF_SECTION *cs, const char *server)
{
- int type, rcode;
+ int rcode;
char *listen_type;
rad_listen_t *this;
return NULL;
}
- type = fr_str2int(listen_compare, listen_type, -1);
- if (type < 0) {
- cf_log_err(cf_sectiontoitem(cs),
- "Invalid type \"%s\" in listen section.",
- listen_type);
- free(listen_type);
- return NULL;
- }
- free(listen_type);
-
/*
* Allow listen sections in the default config to
* refer to a server.
rcode = cf_item_parse(cs, "server", PW_TYPE_STRING_PTR,
&server, NULL);
}
- if (rcode < 0) return NULL;
+ if (rcode < 0) {
+ free(listen_type);
+ return NULL;
+ }
}
/*
* Set up cross-type data.
*/
- this = listen_alloc(type);
+ this = listen_alloc(listen_type);
+ if (!this) return NULL;
+
+ free(listen_type);
this->server = server;
this->fd = -1;
/*
* Call per-type parser.
*/
- if (master_listen[type].parse(cs, this) < 0) {
+ if (this->frs->parse(cs, this) < 0) {
listen_free(&this);
return NULL;
}
bind_it:
#ifdef WITH_VMPS
if (strcmp(progname, "vmpsd") == 0) {
- this = listen_alloc(RAD_LISTEN_VQP);
+ this = listen_alloc("vmps");
+ if (!this) return 0; /* FIXME: memleak? */
if (!auth_port) auth_port = 1589;
} else
#endif
- this = listen_alloc(RAD_LISTEN_AUTH);
+ {
+ this = listen_alloc("auth");
+ if (!this) return 0; /* FIXME: memleak? */
+ }
sock = this->data;
* If we haven't already gotten acct_port from
* /etc/services, then make it auth_port + 1.
*/
- this = listen_alloc(RAD_LISTEN_ACCT);
+ this = listen_alloc("acct");
+ if (!this) return 0; /* FIXME: memleak? */
sock = this->data;
/*
server_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);
}
- this = listen_alloc(RAD_LISTEN_PROXY);
+ this = listen_alloc("proxy");
+ if (!this) return 0; /* FIXME: memleak? */
sock = this->data;
/*
*/
if (this->fd >= 0) close(this->fd);
- if (master_listen[this->type].free) {
- master_listen[this->type].free(this);
+ if (this->frs->free) {
+ this->frs->free(this);
}
free(this->data);
free(this);
*head = NULL;
}
-
-#ifdef WITH_STATS
-RADCLIENT_LIST *listener_find_client_list(const fr_ipaddr_t *ipaddr,
- int port)
-{
- rad_listen_t *this;
-
- for (this = mainconfig.listen; this != NULL; this = this->next) {
- listen_socket_t *sock;
-
- if ((this->type != RAD_LISTEN_AUTH) &&
- (this->type != RAD_LISTEN_ACCT)) continue;
-
- sock = this->data;
-
- if ((sock->port == port) &&
- (fr_ipaddr_cmp(ipaddr, &sock->ipaddr) == 0)) {
- return sock->clients;
- }
- }
-
- return NULL;
-}
-
-rad_listen_t *listener_find_byipaddr(const fr_ipaddr_t *ipaddr, int port)
-{
- rad_listen_t *this;
-
- for (this = mainconfig.listen; this != NULL; this = this->next) {
- listen_socket_t *sock;
-
- if ((this->type != RAD_LISTEN_AUTH) &&
- (this->type != RAD_LISTEN_ACCT)) continue;
-
- sock = this->data;
-
- if ((sock->port == port) &&
- (fr_ipaddr_cmp(ipaddr, &sock->ipaddr) == 0)) {
- return this;
- }
- }
-
- return NULL;
-}
-#endif
#ifdef WITH_SESSION_MGMT
/*
+ * Copied from rad_accounting, with edits. i.e. We don't proxy
+ * these packets.
+ */
+static int session_accounting(REQUEST *request)
+{
+ int result = RLM_MODULE_OK;
+ VALUE_PAIR *vp;
+ int acct_type = 0;
+
+ result = module_preacct(request);
+ switch (result) {
+ /*
+ * The module has a number of OK return codes.
+ */
+ case RLM_MODULE_NOOP:
+ case RLM_MODULE_OK:
+ case RLM_MODULE_UPDATED:
+ break;
+
+ /*
+ * Something went wrong: stop.
+ */
+ case RLM_MODULE_FAIL:
+ case RLM_MODULE_INVALID:
+ case RLM_MODULE_NOTFOUND:
+ case RLM_MODULE_REJECT:
+ case RLM_MODULE_USERLOCK:
+ case RLM_MODULE_HANDLED:
+ default:
+ return result;
+ }
+
+ /*
+ * Run Acct-Type.
+ */
+ vp = pairfind(request->config_items, PW_ACCT_TYPE);
+ if (vp) {
+ DEBUG2(" Found Acct-Type %s", vp->vp_strvalue);
+ acct_type = vp->vp_integer;
+ }
+ result = module_accounting(acct_type, request);
+
+ /*
+ * Don't bother setting reply code: it's a fake packet.
+ * Don't bother proxying it. It's a fake packet.
+ */
+
+ return result;
+}
+
+/*
* End a session by faking a Stop packet to all accounting modules.
*/
int session_zap(REQUEST *request, uint32_t nasaddr, unsigned int port,
stopreq->username = userpair;
stopreq->password = NULL;
- ret = rad_accounting(stopreq);
+ ret = session_accounting(stopreq);
/*
* We've got to clean it up by hand, because no one else will.
#ifdef WITH_STATS
#define USEC (1000000)
-#define EMA_SCALE (100)
#define PREC (USEC * EMA_SCALE)
#define F_EMA_SCALE (1000000)
-static struct timeval start_time;
-static struct timeval hup_time;
+struct timeval radius_start_time;
+struct timeval radius_hup_time;
fr_stats_t radius_auth_stats = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
#ifdef WITH_ACCOUNTING
request->master_state = REQUEST_COUNTED;
}
-typedef struct fr_stats2vp {
- int attribute;
- size_t offset;
-} fr_stats2vp;
-
-/*
- * Authentication
- */
-static fr_stats2vp authvp[] = {
- { 128, offsetof(fr_stats_t, total_requests) },
- { 129, offsetof(fr_stats_t, total_access_accepts) },
- { 130, offsetof(fr_stats_t, total_access_rejects) },
- { 131, offsetof(fr_stats_t, total_access_challenges) },
- { 132, offsetof(fr_stats_t, total_responses) },
- { 133, offsetof(fr_stats_t, total_dup_requests) },
- { 134, offsetof(fr_stats_t, total_malformed_requests) },
- { 135, offsetof(fr_stats_t, total_bad_authenticators) },
- { 136, offsetof(fr_stats_t, total_packets_dropped) },
- { 137, offsetof(fr_stats_t, total_unknown_types) },
- { 0, 0 }
-};
-
-
-#ifdef WITH_PROXY
-/*
- * Proxied authentication requests.
- */
-static fr_stats2vp proxy_authvp[] = {
- { 138, offsetof(fr_stats_t, total_requests) },
- { 139, offsetof(fr_stats_t, total_access_accepts) },
- { 140, offsetof(fr_stats_t, total_access_rejects) },
- { 141, offsetof(fr_stats_t, total_access_challenges) },
- { 142, offsetof(fr_stats_t, total_responses) },
- { 143, offsetof(fr_stats_t, total_dup_requests) },
- { 144, offsetof(fr_stats_t, total_malformed_requests) },
- { 145, offsetof(fr_stats_t, total_bad_authenticators) },
- { 146, offsetof(fr_stats_t, total_packets_dropped) },
- { 147, offsetof(fr_stats_t, total_unknown_types) },
- { 0, 0 }
-};
-#endif
-
-
-#ifdef WITH_ACCOUNTING
-/*
- * Accounting
- */
-static fr_stats2vp acctvp[] = {
- { 148, offsetof(fr_stats_t, total_requests) },
- { 149, offsetof(fr_stats_t, total_responses) },
- { 150, offsetof(fr_stats_t, total_dup_requests) },
- { 151, offsetof(fr_stats_t, total_malformed_requests) },
- { 152, offsetof(fr_stats_t, total_bad_authenticators) },
- { 153, offsetof(fr_stats_t, total_packets_dropped) },
- { 154, offsetof(fr_stats_t, total_unknown_types) },
- { 0, 0 }
-};
-
-#ifdef WITH_PROXY
-static fr_stats2vp proxy_acctvp[] = {
- { 155, offsetof(fr_stats_t, total_requests) },
- { 156, offsetof(fr_stats_t, total_responses) },
- { 157, offsetof(fr_stats_t, total_dup_requests) },
- { 158, offsetof(fr_stats_t, total_malformed_requests) },
- { 159, offsetof(fr_stats_t, total_bad_authenticators) },
- { 160, offsetof(fr_stats_t, total_packets_dropped) },
- { 161, offsetof(fr_stats_t, total_unknown_types) },
- { 0, 0 }
-};
-#endif
-#endif
-
-static fr_stats2vp client_authvp[] = {
- { 128, offsetof(fr_stats_t, total_requests) },
- { 129, offsetof(fr_stats_t, total_access_accepts) },
- { 130, offsetof(fr_stats_t, total_access_rejects) },
- { 131, offsetof(fr_stats_t, total_access_challenges) },
- { 132, offsetof(fr_stats_t, total_responses) },
- { 133, offsetof(fr_stats_t, total_dup_requests) },
- { 134, offsetof(fr_stats_t, total_malformed_requests) },
- { 135, offsetof(fr_stats_t, total_bad_authenticators) },
- { 136, offsetof(fr_stats_t, total_packets_dropped) },
- { 137, offsetof(fr_stats_t, total_unknown_types) },
- { 0, 0 }
-};
-
-#ifdef WITH_ACCOUNTING
-static fr_stats2vp client_acctvp[] = {
- { 155, offsetof(fr_stats_t, total_requests) },
- { 156, offsetof(fr_stats_t, total_responses) },
- { 157, offsetof(fr_stats_t, total_dup_requests) },
- { 158, offsetof(fr_stats_t, total_malformed_requests) },
- { 159, offsetof(fr_stats_t, total_bad_authenticators) },
- { 160, offsetof(fr_stats_t, total_packets_dropped) },
- { 161, offsetof(fr_stats_t, total_unknown_types) },
- { 0, 0 }
-};
-#endif
-
-#define FR2ATTR(x) ((11344 << 16) | (x))
-
-static void request_stats_addvp(REQUEST *request,
- fr_stats2vp *table, fr_stats_t *stats)
-{
- int i;
- VALUE_PAIR *vp;
-
- for (i = 0; table[i].attribute != 0; i++) {
- vp = radius_paircreate(request, &request->reply->vps,
- FR2ATTR(table[i].attribute),
- PW_TYPE_INTEGER);
- if (!vp) continue;
-
- vp->vp_integer = *(int *)(((char *) stats) + table[i].offset);
- }
-}
-
-
-void request_stats_reply(REQUEST *request)
-{
- VALUE_PAIR *flag, *vp;
-
- /*
- * Statistics are available ONLY on a "status" port.
- */
- rad_assert(request->packet->code == PW_STATUS_SERVER);
- rad_assert(request->listener->type == RAD_LISTEN_NONE);
-
- flag = pairfind(request->packet->vps, FR2ATTR(127));
- if (!flag || (flag->vp_integer == 0)) return;
-
- /*
- * Authentication.
- */
- if (((flag->vp_integer & 0x01) != 0) &&
- ((flag->vp_integer & 0xc0) == 0)) {
- request_stats_addvp(request, authvp, &radius_auth_stats);
- }
-
-#ifdef WITH_ACCOUNTING
- /*
- * Accounting
- */
- if (((flag->vp_integer & 0x02) != 0) &&
- ((flag->vp_integer & 0xc0) == 0)) {
- request_stats_addvp(request, acctvp, &radius_acct_stats);
- }
-#endif
-
-#ifdef WITH_PROXY
- /*
- * Proxied authentication requests.
- */
- if (((flag->vp_integer & 0x04) != 0) &&
- ((flag->vp_integer & 0x20) == 0)) {
- request_stats_addvp(request, proxy_authvp, &proxy_auth_stats);
- }
-
-#ifdef WITH_ACCOUNTING
- /*
- * Proxied accounting requests.
- */
- if (((flag->vp_integer & 0x08) != 0) &&
- ((flag->vp_integer & 0x20) == 0)) {
- request_stats_addvp(request, proxy_acctvp, &proxy_acct_stats);
- }
-#endif
-#endif
-
- /*
- * Internal server statistics
- */
- if ((flag->vp_integer & 0x10) != 0) {
- vp = radius_paircreate(request, &request->reply->vps,
- FR2ATTR(176), PW_TYPE_DATE);
- if (vp) vp->vp_date = start_time.tv_sec;
- vp = radius_paircreate(request, &request->reply->vps,
- FR2ATTR(177), PW_TYPE_DATE);
- if (vp) vp->vp_date = hup_time.tv_sec;
-
-#ifdef HAVE_PTHREAD_H
- int i, array[RAD_LISTEN_MAX];
-
- thread_pool_queue_stats(array);
-
- for (i = 0; i <= RAD_LISTEN_DETAIL; i++) {
- vp = radius_paircreate(request, &request->reply->vps,
- FR2ATTR(162 + i),
- PW_TYPE_INTEGER);
-
- if (!vp) continue;
- vp->vp_integer = array[i];
- }
-#endif
- }
-
- /*
- * For a particular client.
- */
- if ((flag->vp_integer & 0x20) != 0) {
- fr_ipaddr_t ipaddr;
- VALUE_PAIR *server_ip, *server_port = NULL;
- RADCLIENT *client = NULL;
- RADCLIENT_LIST *cl = NULL;
-
- /*
- * See if we need to look up the client by server
- * socket.
- */
- server_ip = pairfind(request->packet->vps, FR2ATTR(170));
- if (server_ip) {
- server_port = pairfind(request->packet->vps,
- FR2ATTR(171));
-
- if (server_port) {
- ipaddr.af = AF_INET;
- ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
- cl = listener_find_client_list(&ipaddr, server_port->vp_integer);
-
- /*
- * Not found: don't do anything
- */
- if (!cl) return;
- }
- }
-
-
- vp = pairfind(request->packet->vps, FR2ATTR(167));
- if (vp) {
- ipaddr.af = AF_INET;
- ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
- client = client_find(cl, &ipaddr);
-
- /*
- * Else look it up by number.
- */
- } else if ((vp = pairfind(request->packet->vps,
- FR2ATTR(168))) != NULL) {
- client = client_findbynumber(cl, vp->vp_integer);
- }
-
- if (client) {
- /*
- * If found, echo it back, along with
- * the requested statistics.
- */
- pairadd(&request->reply->vps, paircopyvp(vp));
-
- /*
- * When retrieving client by number, also
- * echo back it's IP address.
- */
- if ((vp->type == PW_TYPE_INTEGER) &&
- (client->ipaddr.af == AF_INET)) {
- vp = radius_paircreate(request,
- &request->reply->vps,
- FR2ATTR(167),
- PW_TYPE_IPADDR);
- if (vp) {
- vp->vp_ipaddr = client->ipaddr.ipaddr.ip4addr.s_addr;
- }
-
- if (client->prefix != 32) {
- vp = radius_paircreate(request,
- &request->reply->vps,
- FR2ATTR(169),
- PW_TYPE_INTEGER);
- if (vp) {
- vp->vp_integer = client->prefix;
- }
- }
- }
-
- if (server_ip) {
- pairadd(&request->reply->vps,
- paircopyvp(server_ip));
- pairadd(&request->reply->vps,
- paircopyvp(server_port));
- }
-
- if (client->auth &&
- ((flag->vp_integer & 0x01) != 0)) {
- request_stats_addvp(request, client_authvp,
- client->auth);
- }
-#ifdef WITH_ACCOUNTING
- if (client->acct &&
- ((flag->vp_integer & 0x01) != 0)) {
- request_stats_addvp(request, client_acctvp,
- client->acct);
- }
-#endif
- } /* else client wasn't found, don't echo it back */
- }
-
- /*
- * For a particular "listen" socket.
- */
- if (((flag->vp_integer & 0x40) != 0) &&
- ((flag->vp_integer & 0x03) != 0)) {
- rad_listen_t *this;
- VALUE_PAIR *server_ip, *server_port;
- fr_ipaddr_t ipaddr;
-
- /*
- * See if we need to look up the server by socket
- * socket.
- */
- server_ip = pairfind(request->packet->vps, FR2ATTR(170));
- if (!server_ip) return;
-
- server_port = pairfind(request->packet->vps,
- FR2ATTR(171));
- if (!server_port) return;
-
- ipaddr.af = AF_INET;
- ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
- this = listener_find_byipaddr(&ipaddr,
- server_port->vp_integer);
-
- /*
- * Not found: don't do anything
- */
- if (!this) return;
-
- pairadd(&request->reply->vps,
- paircopyvp(server_ip));
- pairadd(&request->reply->vps,
- paircopyvp(server_port));
-
- if (((flag->vp_integer & 0x01) != 0) &&
- ((request->listener->type == RAD_LISTEN_AUTH) ||
- (request->listener->type == RAD_LISTEN_NONE))) {
- request_stats_addvp(request, authvp, &this->stats);
- }
-
-#ifdef WITH_ACCOUNTING
- if (((flag->vp_integer & 0x02) != 0) &&
- ((request->listener->type == RAD_LISTEN_ACCT) ||
- (request->listener->type == RAD_LISTEN_NONE))) {
- request_stats_addvp(request, acctvp, &this->stats);
- }
-#endif
- }
-
- /*
- * Home servers.
- */
- if (((flag->vp_integer & 0x80) != 0) &&
- ((flag->vp_integer & 0x03) != 0)) {
- home_server *home;
- VALUE_PAIR *server_ip, *server_port;
- fr_ipaddr_t ipaddr;
-
- /*
- * See if we need to look up the server by socket
- * socket.
- */
- server_ip = pairfind(request->packet->vps, FR2ATTR(170));
- if (!server_ip) return;
-
- server_port = pairfind(request->packet->vps,
- FR2ATTR(171));
- if (!server_port) return;
-
- ipaddr.af = AF_INET;
- ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
- home = home_server_find(&ipaddr, server_port->vp_integer);
-
- /*
- * Not found: don't do anything
- */
- if (!home) return;
-
- pairadd(&request->reply->vps,
- paircopyvp(server_ip));
- pairadd(&request->reply->vps,
- paircopyvp(server_port));
-
- vp = radius_paircreate(request, &request->reply->vps,
- FR2ATTR(172), PW_TYPE_INTEGER);
- if (vp) vp->vp_integer = home->currently_outstanding;
-
- vp = radius_paircreate(request, &request->reply->vps,
- FR2ATTR(173), PW_TYPE_INTEGER);
- if (vp) vp->vp_integer = home->state;
-
- if ((home->state == HOME_STATE_ALIVE) &&
- (home->revive_time.tv_sec != 0)) {
- vp = radius_paircreate(request, &request->reply->vps,
- FR2ATTR(175), PW_TYPE_DATE);
- if (vp) vp->vp_date = home->revive_time.tv_sec;
- }
-
- if ((home->state == HOME_STATE_ALIVE) &&
- (home->ema.window > 0)) {
- vp = radius_paircreate(request,
- &request->reply->vps,
- FR2ATTR(178),
- PW_TYPE_INTEGER);
- if (vp) vp->vp_integer = home->ema.window;
- vp = radius_paircreate(request,
- &request->reply->vps,
- FR2ATTR(179),
- PW_TYPE_INTEGER);
- if (vp) vp->vp_integer = home->ema.ema1 / EMA_SCALE;
- vp = radius_paircreate(request,
- &request->reply->vps,
- FR2ATTR(180),
- PW_TYPE_INTEGER);
- if (vp) vp->vp_integer = home->ema.ema10 / EMA_SCALE;
-
- }
-
- if (home->state == HOME_STATE_IS_DEAD) {
- vp = radius_paircreate(request, &request->reply->vps,
- FR2ATTR(174), PW_TYPE_DATE);
- if (vp) vp->vp_date = home->zombie_period_start.tv_sec + home->zombie_period;
- }
-
- if (((flag->vp_integer & 0x01) != 0) &&
- (home->type == HOME_TYPE_AUTH)) {
- request_stats_addvp(request, proxy_authvp,
- &home->stats);
- }
-
-#ifdef WITH_ACCOUNTING
- if (((flag->vp_integer & 0x02) != 0) &&
- (home->type == HOME_TYPE_ACCT)) {
- request_stats_addvp(request, proxy_acctvp,
- &home->stats);
- }
-#endif
- }
-}
-
void radius_stats_init(int flag)
{
if (!flag) {
- gettimeofday(&start_time, NULL);
- hup_time = start_time; /* it's just nicer this way */
+ gettimeofday(&radius_start_time, NULL);
+ radius_hup_time = radius_start_time; /* it's just nicer this way */
} else {
- gettimeofday(&hup_time, NULL);
+ gettimeofday(&radius_hup_time, NULL);
}
}
REQUEST *request;
} THREAD_HANDLE;
-/*
- * For the request queue.
- */
-typedef struct request_queue_t {
- REQUEST *request;
- RAD_REQUEST_FUNP fun;
-} request_queue_t;
-
typedef struct thread_fork_t {
pid_t pid;
int status;
*/
static int request_enqueue(REQUEST *request, RAD_REQUEST_FUNP fun)
{
- request_queue_t *entry;
-
+ rad_assert(request->process == fun);
pthread_mutex_lock(&thread_pool.queue_mutex);
thread_pool.request_count++;
return 0;
}
- entry = rad_malloc(sizeof(*entry));
- entry->request = request;
- entry->fun = fun;
-
/*
* Push the request onto the appropriate fifo for that
*/
- if (!fr_fifo_push(thread_pool.fifo[request->priority],
- entry)) {
+ if (!fr_fifo_push(thread_pool.fifo[request->priority], request)) {
pthread_mutex_unlock(&thread_pool.queue_mutex);
radlog(L_ERR, "!!! ERROR !!! Failed inserting request %d into the queue", request->number);
request->child_state = REQUEST_DONE;
/*
* Remove a request from the queue.
*/
-static int request_dequeue(REQUEST **request, RAD_REQUEST_FUNP *fun)
+static int request_dequeue(REQUEST **prequest, RAD_REQUEST_FUNP *fun)
{
RAD_LISTEN_TYPE i, start;
- request_queue_t *entry;
+ REQUEST *request = NULL;
reap_children();
* requests will be quickly cleared.
*/
for (i = 0; i < RAD_LISTEN_MAX; i++) {
- entry = fr_fifo_peek(thread_pool.fifo[i]);
- if (!entry ||
- (entry->request->master_state != REQUEST_STOP_PROCESSING)) {
+ request = fr_fifo_peek(thread_pool.fifo[i]);
+ if (!request ||
+ (request->master_state != REQUEST_STOP_PROCESSING)) {
continue;
}
/*
* This entry was marked to be stopped. Acknowledge it.
*/
- entry = fr_fifo_pop(thread_pool.fifo[i]);
- rad_assert(entry != NULL);
- entry->request->child_state = REQUEST_DONE;
+ request = fr_fifo_pop(thread_pool.fifo[i]);
+ rad_assert(request != NULL);
+ request->child_state = REQUEST_DONE;
thread_pool.num_queued--;
- free(entry);
}
start = 0;
* Pop results from the top of the queue
*/
for (i = start; i < RAD_LISTEN_MAX; i++) {
- entry = fr_fifo_pop(thread_pool.fifo[i]);
- if (entry) {
+ request = fr_fifo_pop(thread_pool.fifo[i]);
+ if (request) {
start = i;
break;
}
}
- if (!entry) {
+ if (!request) {
pthread_mutex_unlock(&thread_pool.queue_mutex);
- *request = NULL;
+ *prequest = NULL;
*fun = NULL;
return 0;
}
rad_assert(thread_pool.num_queued > 0);
thread_pool.num_queued--;
- *request = entry->request;
- *fun = entry->fun;
- free(entry);
+ *prequest = request;
+ *fun = request->process;
- rad_assert(*request != NULL);
- rad_assert((*request)->magic == REQUEST_MAGIC);
+ rad_assert(request->magic == REQUEST_MAGIC);
rad_assert(*fun != NULL);
/*
* the queue, and therefore won't clean it up until we
* have acknowledged it as "done".
*/
- if ((*request)->master_state == REQUEST_STOP_PROCESSING) {
- (*request)->child_state = REQUEST_DONE;
+ if (request->master_state == REQUEST_STOP_PROCESSING) {
+ request->child_state = REQUEST_DONE;
goto retry;
}
{
time_t now = request->timestamp;
+ request->process = fun;
+
/*
* We've been told not to spawn threads, so don't.
*/
include ../../Make.inc
WHAT_TO_MAKE = all
+FRS_MODULES = $(shell echo frs_*/Makefile | sed 's,/Makefile,,g')
all:
@$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
common:
@[ -d lib/ ] || mkdir lib
- @for mod in $(MODULES); do \
+ @for mod in $(FRS_MODULES) $(MODULES); do \
if [ -d $$mod ] && [ -f $$mod/Makefile ]; then \
echo "Making $(WHAT_TO_MAKE) in $$mod..."; \
$(MAKE) $(MFLAGS) -C $$mod $(WHAT_TO_MAKE) || exit $$?; \
--- /dev/null
+TARGET = frs_acct
+SRCS = frs_acct.c
+HEADERS =
+RLM_CFLAGS =
+RLM_LIBS =
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
RCSID("$Id$")
#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/rad_assert.h>
#include <freeradius-devel/modules.h>
-#ifdef WITH_ACCOUNTING
+
/*
* rad_accounting: call modules.
*
* The return value of this function isn't actually used right now, so
* it's not entirely clear if it is returning the right things. --Pac.
*/
-int rad_accounting(REQUEST *request)
+static int rad_accounting(REQUEST *request)
{
int result = RLM_MODULE_OK;
}
return result;
}
-#endif
+
+
+/*
+ * Receive packets from an accounting socket
+ */
+static int acct_socket_recv(rad_listen_t *listener,
+ RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+{
+ ssize_t rcode;
+ int code, src_port;
+ RADIUS_PACKET *packet;
+ RAD_REQUEST_FUNP fun = NULL;
+ RADCLIENT *client;
+ fr_ipaddr_t src_ipaddr;
+
+ rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
+ if (rcode < 0) return 0;
+
+ RAD_STATS_TYPE_INC(listener, total_requests);
+
+ if (rcode < 20) { /* AUTH_HDR_LEN */
+ RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+ return 0;
+ }
+
+ if ((client = client_listener_find(listener,
+ &src_ipaddr, src_port)) == NULL) {
+ rad_recv_discard(listener->fd);
+ RAD_STATS_TYPE_INC(listener, total_invalid_requests);
+ return 0;
+ }
+
+ /*
+ * Some sanity checks, based on the packet code.
+ */
+ switch(code) {
+ case PW_ACCOUNTING_REQUEST:
+ RAD_STATS_CLIENT_INC(listener, client, total_requests);
+ fun = rad_accounting;
+ break;
+
+ case PW_STATUS_SERVER:
+ if (!mainconfig.status_server) {
+ rad_recv_discard(listener->fd);
+ RAD_STATS_TYPE_INC(listener, total_packets_dropped);
+ RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
+
+ DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
+ return 0;
+ }
+ fun = rad_status_server;
+ break;
+
+ default:
+ rad_recv_discard(listener->fd);
+ RAD_STATS_TYPE_INC(listener, total_unknown_types);
+ RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
+
+ DEBUG("Invalid packet code %d sent to a accounting port from client %s port %d : IGNORED",
+ code, client->shortname, src_port);
+ return 0;
+ } /* switch over packet types */
+
+ /*
+ * Now that we've sanity checked everything, receive the
+ * packet.
+ */
+ packet = rad_recv(listener->fd, 0);
+ if (!packet) {
+ RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+ radlog(L_ERR, "%s", fr_strerror());
+ return 0;
+ }
+
+ /*
+ * There can be no duplicate accounting packets.
+ */
+ if (!received_request(listener, packet, prequest, client)) {
+ RAD_STATS_TYPE_INC(listener, total_packets_dropped);
+ RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
+ rad_free(&packet);
+ return 0;
+ }
+
+ *pfun = fun;
+ return 1;
+}
+
+
+/*
+ * Send an accounting response packet (or not)
+ */
+static int acct_socket_send(rad_listen_t *listener, REQUEST *request)
+{
+ rad_assert(request->listener == listener);
+ rad_assert(listener->send == acct_socket_send);
+
+ /*
+ * Accounting reject's are silently dropped.
+ *
+ * We do it here to avoid polluting the rest of the
+ * code with this knowledge
+ */
+ if (request->reply->code == 0) return 0;
+
+ return rad_send(request->reply, request->packet,
+ request->client->secret);
+}
+
+
+static int acct_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+ if (!request->reply->code) return 0;
+
+ rad_encode(request->reply, request->packet,
+ request->client->secret);
+ rad_sign(request->reply, request->packet,
+ request->client->secret);
+
+ return 0;
+}
+
+
+static int acct_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+ if (rad_verify(request->packet, NULL,
+ request->client->secret) < 0) {
+ return -1;
+ }
+
+ return rad_decode(request->packet, NULL,
+ request->client->secret);
+}
+
+
+frs_module_t frs_acct = {
+ FRS_MODULE_INIT, RAD_LISTEN_ACCT, "acct",
+ listen_socket_parse, NULL,
+ acct_socket_recv, acct_socket_send,
+ listen_socket_print, acct_socket_encode, acct_socket_decode
+};
--- /dev/null
+TARGET = frs_auth
+SRCS = frs_auth.c
+HEADERS =
+RLM_CFLAGS =
+RLM_LIBS =
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
--- /dev/null
+/*
+ * auth.c User authentication.
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2000,2006 The FreeRADIUS server project
+ * Copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl>
+ * Copyright 2000 Jeff Carneal <jeff@apex.net>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/rad_assert.h>
+
+#include <ctype.h>
+
+
+/*
+ * Make sure user/pass are clean
+ * and then log them
+ */
+static int rad_authlog(const char *msg, REQUEST *request, int goodpass) {
+
+ char clean_password[1024];
+ char clean_username[1024];
+ char buf[1024];
+ VALUE_PAIR *username = NULL;
+
+ if (!request->root->log_auth) {
+ return 0;
+ }
+
+ /*
+ * Get the correct username based on the configured value
+ */
+ if (log_stripped_names == 0) {
+ username = pairfind(request->packet->vps, PW_USER_NAME);
+ } else {
+ username = request->username;
+ }
+
+ /*
+ * Clean up the username
+ */
+ if (username == NULL) {
+ strcpy(clean_username, "<no User-Name attribute>");
+ } else {
+ fr_print_string((char *)username->vp_strvalue,
+ username->length,
+ clean_username, sizeof(clean_username));
+ }
+
+ /*
+ * Clean up the password
+ */
+ if (request->root->log_auth_badpass || request->root->log_auth_goodpass) {
+ if (!request->password) {
+ VALUE_PAIR *auth_type;
+
+ auth_type = pairfind(request->config_items,
+ PW_AUTH_TYPE);
+ if (auth_type && (auth_type->vp_strvalue[0] != '\0')) {
+ snprintf(clean_password, sizeof(clean_password),
+ "<via Auth-Type = %s>",
+ auth_type->vp_strvalue);
+ } else {
+ strcpy(clean_password, "<no User-Password attribute>");
+ }
+ } else if (pairfind(request->packet->vps, PW_CHAP_PASSWORD)) {
+ strcpy(clean_password, "<CHAP-Password>");
+ } else {
+ fr_print_string((char *)request->password->vp_strvalue,
+ request->password->length,
+ clean_password, sizeof(clean_password));
+ }
+ }
+
+ if (goodpass) {
+ radlog_request(L_AUTH, 0, request, "%s: [%s%s%s] (%s)",
+ msg,
+ clean_username,
+ request->root->log_auth_goodpass ? "/" : "",
+ request->root->log_auth_goodpass ? clean_password : "",
+ auth_name(buf, sizeof(buf), request, 1));
+ } else {
+ radlog_request(L_AUTH, 0, request, "%s: [%s%s%s] (%s)",
+ msg,
+ clean_username,
+ request->root->log_auth_badpass ? "/" : "",
+ request->root->log_auth_badpass ? clean_password : "",
+ auth_name(buf, sizeof(buf), request, 1));
+ }
+
+ return 0;
+}
+
+/*
+ * Check password.
+ *
+ * Returns: 0 OK
+ * -1 Password fail
+ * -2 Rejected (Auth-Type = Reject, send Port-Message back)
+ * 1 End check & return, don't reply
+ *
+ * NOTE: NOT the same as the RLM_ values !
+ */
+static int rad_check_password(REQUEST *request)
+{
+ VALUE_PAIR *auth_type_pair;
+ VALUE_PAIR *cur_config_item;
+ VALUE_PAIR *password_pair;
+ VALUE_PAIR *auth_item;
+ uint8_t my_chap[MAX_STRING_LEN];
+ int auth_type = -1;
+ int result;
+ int auth_type_count = 0;
+ result = 0;
+
+ /*
+ * Look for matching check items. We skip the whole lot
+ * if the authentication type is PW_AUTHTYPE_ACCEPT or
+ * PW_AUTHTYPE_REJECT.
+ */
+ cur_config_item = request->config_items;
+ while(((auth_type_pair = pairfind(cur_config_item, PW_AUTH_TYPE))) != NULL) {
+ auth_type = auth_type_pair->vp_integer;
+ auth_type_count++;
+ DICT_VALUE *dv = dict_valbyattr(auth_type_pair->attribute,
+ auth_type_pair->vp_integer);
+
+ RDEBUG2("Found Auth-Type = %s",
+ (dv != NULL) ? dv->name : "?");
+ cur_config_item = auth_type_pair->next;
+
+ if (auth_type == PW_AUTHTYPE_REJECT) {
+ RDEBUG2("Auth-Type = Reject, rejecting user");
+ return -2;
+ }
+ }
+
+ if (( auth_type_count > 1) && (debug_flag)) {
+ radlog_request(L_ERR, 0, request, "Warning: Found %d auth-types on request for user '%s'",
+ auth_type_count, request->username->vp_strvalue);
+ }
+
+ /*
+ * This means we have a proxy reply or an accept
+ * and it wasn't rejected in the above loop. So
+ * that means it is accepted and we do no further
+ * authentication
+ */
+ if ((auth_type == PW_AUTHTYPE_ACCEPT)
+#ifdef WITH_PROXY
+ || (request->proxy)
+#endif
+ ) {
+ RDEBUG2("Auth-Type = Accept, accepting the user");
+ return 0;
+ }
+
+ password_pair = pairfind(request->config_items, PW_USER_PASSWORD);
+ if (password_pair &&
+ pairfind(request->config_items, PW_CLEARTEXT_PASSWORD)) {
+ pairdelete(&request->config_items, PW_USER_PASSWORD);
+ password_pair = NULL;
+ }
+
+ if (password_pair) {
+ DICT_ATTR *da;
+
+ RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+ RDEBUG("!!! Replacing User-Password in config items with Cleartext-Password. !!!");
+ RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+ RDEBUG("!!! Please update your configuration so that the \"known good\" !!!");
+ RDEBUG("!!! clear text password is in Cleartext-Password, and not in User-Password. !!!");
+ RDEBUG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+ password_pair->attribute = PW_CLEARTEXT_PASSWORD;
+ da = dict_attrbyvalue(PW_CLEARTEXT_PASSWORD);
+ if (!da) {
+ radlog_request(L_ERR, 0, request, "FATAL: You broke the dictionaries. Please use the default dictionaries!");
+ _exit(1);
+ }
+
+ password_pair->name = da->name;
+ }
+
+ /*
+ * Find the "known good" password.
+ *
+ * FIXME: We should get rid of these hacks, and replace
+ * them with a module.
+ */
+ if ((password_pair = pairfind(request->config_items, PW_CRYPT_PASSWORD)) != NULL) {
+ /*
+ * Re-write Auth-Type, but ONLY if it isn't already
+ * set.
+ */
+ if (auth_type == -1) auth_type = PW_AUTHTYPE_CRYPT;
+ } else {
+ password_pair = pairfind(request->config_items, PW_CLEARTEXT_PASSWORD);
+ }
+
+ if (auth_type < 0) {
+ if (password_pair) {
+ auth_type = PW_AUTHTYPE_LOCAL;
+ } else {
+ /*
+ * The admin hasn't told us how to
+ * authenticate the user, so we reject them!
+ *
+ * This is fail-safe.
+ */
+ RDEBUG2("No authenticate method (Auth-Type) configuration found for the request: Rejecting the user");
+ return -2;
+ }
+ }
+
+ switch(auth_type) {
+ case PW_AUTHTYPE_CRYPT:
+ RDEBUG2("WARNING: Please update your configuration, and remove 'Auth-Type = Crypt'");
+ RDEBUG2("WARNING: Use the PAP module instead.");
+
+ /*
+ * Find the password sent by the user. It
+ * SHOULD be there, if it's not
+ * authentication fails.
+ */
+ auth_item = request->password;
+ if (auth_item == NULL) {
+ RDEBUG2("No User-Password or CHAP-Password attribute in the request");
+ return -1;
+ }
+
+ if (password_pair == NULL) {
+ RDEBUG2("No Crypt-Password configured for the user");
+ rad_authlog("Login incorrect "
+ "(No Crypt-Password configured for the user)", request, 0);
+ return -1;
+ }
+
+ switch (fr_crypt_check((char *)auth_item->vp_strvalue,
+ (char *)password_pair->vp_strvalue)) {
+ case -1:
+ rad_authlog("Login incorrect "
+ "(system failed to supply an encrypted password for comparison)", request, 0);
+ case 1:
+ return -1;
+ }
+ break;
+ case PW_AUTHTYPE_LOCAL:
+ RDEBUG2("WARNING: Please update your configuration, and remove 'Auth-Type = Local'");
+ RDEBUG2("WARNING: Use the PAP or CHAP modules instead.");
+
+ /*
+ * Find the password sent by the user. It
+ * SHOULD be there, if it's not
+ * authentication fails.
+ */
+ auth_item = request->password;
+ if (!auth_item)
+ auth_item = pairfind(request->packet->vps,
+ PW_CHAP_PASSWORD);
+ if (!auth_item) {
+ RDEBUG2("No User-Password or CHAP-Password attribute in the request.");
+ RDEBUG2("Cannot perform authentication.");
+ return -1;
+ }
+
+ /*
+ * Plain text password.
+ */
+ if (password_pair == NULL) {
+ RDEBUG2("No \"known good\" password was configured for the user.");
+ RDEBUG2("As a result, we cannot authenticate the user.");
+ rad_authlog("Login incorrect "
+ "(No password configured for the user)", request, 0);
+ return -1;
+ }
+
+ /*
+ * Local password is just plain text.
+ */
+ if (auth_item->attribute == PW_USER_PASSWORD) {
+ if (strcmp((char *)password_pair->vp_strvalue,
+ (char *)auth_item->vp_strvalue) != 0) {
+ RDEBUG2("User-Password in the request does NOT match \"known good\" password.");
+ return -1;
+ }
+ RDEBUG2("User-Password in the request is correct.");
+ break;
+
+ } else if (auth_item->attribute != PW_CHAP_PASSWORD) {
+ RDEBUG2("The user did not supply a User-Password or a CHAP-Password attribute");
+ rad_authlog("Login incorrect "
+ "(no User-Password or CHAP-Password attribute)", request, 0);
+ return -1;
+ }
+
+ rad_chap_encode(request->packet, my_chap,
+ auth_item->vp_octets[0], password_pair);
+
+ /*
+ * Compare them
+ */
+ if (memcmp(my_chap + 1, auth_item->vp_strvalue + 1,
+ CHAP_VALUE_LENGTH) != 0) {
+ RDEBUG2("CHAP-Password is incorrect.");
+ return -1;
+ }
+ RDEBUG2("CHAP-Password is correct.");
+ break;
+ default:
+ /*
+ * See if there is a module that handles
+ * this type, and turn the RLM_ return
+ * status into the values as defined at
+ * the top of this function.
+ */
+ result = module_authenticate(auth_type, request);
+ switch (result) {
+ /*
+ * An authentication module FAIL
+ * return code, or any return code that
+ * is not expected from authentication,
+ * is the same as an explicit REJECT!
+ */
+ case RLM_MODULE_FAIL:
+ case RLM_MODULE_INVALID:
+ case RLM_MODULE_NOOP:
+ case RLM_MODULE_NOTFOUND:
+ case RLM_MODULE_REJECT:
+ case RLM_MODULE_UPDATED:
+ case RLM_MODULE_USERLOCK:
+ default:
+ result = -1;
+ break;
+ case RLM_MODULE_OK:
+ result = 0;
+ break;
+ case RLM_MODULE_HANDLED:
+ result = 1;
+ break;
+ }
+ break;
+ }
+
+ return result;
+}
+
+
+/*
+ * Process and reply to an authentication request
+ *
+ * The return value of this function isn't actually used right now, so
+ * it's not entirely clear if it is returning the right things. --Pac.
+ */
+static int rad_authenticate(REQUEST *request)
+{
+ VALUE_PAIR *namepair;
+#ifdef WITH_SESSION_MGMT
+ VALUE_PAIR *check_item;
+#endif
+ VALUE_PAIR *auth_item = NULL;
+ VALUE_PAIR *module_msg;
+ VALUE_PAIR *tmp = NULL;
+ int result;
+ const char *password;
+ char autz_retry = 0;
+ int autz_type = 0;
+
+ password = "";
+
+#ifdef WITH_PROXY
+ /*
+ * If this request got proxied to another server, we need
+ * to check whether it authenticated the request or not.
+ */
+ if (request->proxy_reply) {
+ switch (request->proxy_reply->code) {
+ /*
+ * Reply of ACCEPT means accept, thus set Auth-Type
+ * accordingly.
+ */
+ case PW_AUTHENTICATION_ACK:
+ tmp = radius_paircreate(request,
+ &request->config_items,
+ PW_AUTH_TYPE, PW_TYPE_INTEGER);
+ if (tmp) tmp->vp_integer = PW_AUTHTYPE_ACCEPT;
+ goto authenticate;
+
+ /*
+ * Challenges are punted back to the NAS without any
+ * further processing.
+ */
+ case PW_ACCESS_CHALLENGE:
+ request->reply->code = PW_ACCESS_CHALLENGE;
+ return RLM_MODULE_OK;
+ /*
+ * ALL other replies mean reject. (this is fail-safe)
+ *
+ * Do NOT do any authorization or authentication. They
+ * are being rejected, so we minimize the amount of work
+ * done by the server, by rejecting them here.
+ */
+ case PW_AUTHENTICATION_REJECT:
+ default:
+ rad_authlog("Login incorrect (Home Server says so)",
+ request, 0);
+ request->reply->code = PW_AUTHENTICATION_REJECT;
+ return RLM_MODULE_REJECT;
+ }
+ }
+#endif
+
+ /*
+ * Get the username from the request.
+ *
+ * Note that namepair MAY be NULL, in which case there
+ * is no User-Name attribute in the request.
+ */
+ namepair = request->username;
+
+ /*
+ * Look for, and cache, passwords.
+ */
+ if (!request->password) {
+ request->password = pairfind(request->packet->vps,
+ PW_USER_PASSWORD);
+ }
+
+ /*
+ * Discover which password we want to use.
+ */
+ auth_item = request->password;
+ if (auth_item) {
+ password = (const char *)auth_item->vp_strvalue;
+
+ } else {
+ /*
+ * Maybe there's a CHAP-Password?
+ */
+ if ((auth_item = pairfind(request->packet->vps,
+ PW_CHAP_PASSWORD)) != NULL) {
+ password = "<CHAP-PASSWORD>";
+
+ } else {
+ /*
+ * No password we recognize.
+ */
+ password = "<NO-PASSWORD>";
+ }
+ }
+ request->password = auth_item;
+
+ /*
+ * Get the user's authorization information from the database
+ */
+autz_redo:
+ result = module_authorize(autz_type, request);
+ switch (result) {
+ case RLM_MODULE_NOOP:
+ case RLM_MODULE_NOTFOUND:
+ case RLM_MODULE_OK:
+ case RLM_MODULE_UPDATED:
+ break;
+ case RLM_MODULE_HANDLED:
+ return result;
+ case RLM_MODULE_FAIL:
+ case RLM_MODULE_INVALID:
+ case RLM_MODULE_REJECT:
+ case RLM_MODULE_USERLOCK:
+ default:
+ if ((module_msg = pairfind(request->packet->vps,
+ PW_MODULE_FAILURE_MESSAGE)) != NULL) {
+ char msg[MAX_STRING_LEN + 16];
+ snprintf(msg, sizeof(msg), "Invalid user (%s)",
+ module_msg->vp_strvalue);
+ rad_authlog(msg,request,0);
+ } else {
+ rad_authlog("Invalid user", request, 0);
+ }
+ request->reply->code = PW_AUTHENTICATION_REJECT;
+ return result;
+ }
+ if (!autz_retry) {
+ tmp = pairfind(request->config_items, PW_AUTZ_TYPE);
+ if (tmp) {
+ RDEBUG2("Using Autz-Type %s", tmp->vp_strvalue);
+ autz_type = tmp->vp_integer;
+ autz_retry = 1;
+ goto autz_redo;
+ }
+ }
+
+ /*
+ * If we haven't already proxied the packet, then check
+ * to see if we should. Maybe one of the authorize
+ * modules has decided that a proxy should be used. If
+ * so, get out of here and send the packet.
+ */
+ if (
+#ifdef WITH_PROXY
+ (request->proxy == NULL) &&
+#endif
+ ((tmp = pairfind(request->config_items, PW_PROXY_TO_REALM)) != NULL)) {
+ REALM *realm;
+
+ realm = realm_find2(tmp->vp_strvalue);
+
+ /*
+ * Don't authenticate, as the request is going to
+ * be proxied.
+ */
+ if (realm && realm->auth_pool) {
+ return RLM_MODULE_OK;
+ }
+
+ /*
+ * Catch users who set Proxy-To-Realm to a LOCAL
+ * realm (sigh). But don't complain if it is
+ * *the* LOCAL realm.
+ */
+ if (realm &&(strcmp(realm->name, "LOCAL") != 0)) {
+ RDEBUG2("WARNING: You set Proxy-To-Realm = %s, but it is a LOCAL realm! Cancelling proxy request.", realm->name);
+ }
+
+ if (!realm) {
+ RDEBUG2("WARNING: You set Proxy-To-Realm = %s, but the realm does not exist! Cancelling invalid proxy request.", tmp->vp_strvalue);
+ }
+ }
+
+#ifdef WITH_PROXY
+ authenticate:
+#endif
+
+ /*
+ * Perhaps there is a Stripped-User-Name now.
+ */
+ namepair = request->username;
+
+ /*
+ * Validate the user
+ */
+ do {
+ result = rad_check_password(request);
+ if (result > 0) {
+ /* don't reply! */
+ return RLM_MODULE_HANDLED;
+ }
+ } while(0);
+
+ /*
+ * Failed to validate the user.
+ *
+ * We PRESUME that the code which failed will clean up
+ * request->reply->vps, to be ONLY the reply items it
+ * wants to send back.
+ */
+ if (result < 0) {
+ RDEBUG2("Failed to authenticate the user.");
+ request->reply->code = PW_AUTHENTICATION_REJECT;
+
+ if ((module_msg = pairfind(request->packet->vps,PW_MODULE_FAILURE_MESSAGE)) != NULL){
+ char msg[MAX_STRING_LEN+19];
+
+ snprintf(msg, sizeof(msg), "Login incorrect (%s)",
+ module_msg->vp_strvalue);
+ rad_authlog(msg, request, 0);
+ } else {
+ rad_authlog("Login incorrect", request, 0);
+ }
+
+ /* double check: maybe the secret is wrong? */
+ if ((debug_flag > 1) && (auth_item != NULL) &&
+ (auth_item->attribute == PW_USER_PASSWORD)) {
+ char *p;
+
+ p = auth_item->vp_strvalue;
+ while (*p != '\0') {
+ if (!isprint((int) *p)) {
+ log_debug(" WARNING: Unprintable characters in the password.\n\t Double-check the shared secret on the server and the NAS!");
+ break;
+ }
+ p++;
+ }
+ }
+ }
+
+#ifdef WITH_SESSION_MGMT
+ if (result >= 0 &&
+ (check_item = pairfind(request->config_items, PW_SIMULTANEOUS_USE)) != NULL) {
+ int r, session_type = 0;
+ char logstr[1024];
+ char umsg[MAX_STRING_LEN + 1];
+ const char *user_msg = NULL;
+
+ tmp = pairfind(request->config_items, PW_SESSION_TYPE);
+ if (tmp) {
+ RDEBUG2("Using Session-Type %s", tmp->vp_strvalue);
+ session_type = tmp->vp_integer;
+ }
+
+ /*
+ * User authenticated O.K. Now we have to check
+ * for the Simultaneous-Use parameter.
+ */
+ if (namepair &&
+ (r = module_checksimul(session_type, request, check_item->vp_integer)) != 0) {
+ char mpp_ok = 0;
+
+ if (r == 2){
+ /* Multilink attempt. Check if port-limit > simultaneous-use */
+ VALUE_PAIR *port_limit;
+
+ if ((port_limit = pairfind(request->reply->vps, PW_PORT_LIMIT)) != NULL &&
+ port_limit->vp_integer > check_item->vp_integer){
+ RDEBUG2("MPP is OK");
+ mpp_ok = 1;
+ }
+ }
+ if (!mpp_ok){
+ if (check_item->vp_integer > 1) {
+ snprintf(umsg, sizeof(umsg),
+ "\r\nYou are already logged in %d times - access denied\r\n\n",
+ (int)check_item->vp_integer);
+ user_msg = umsg;
+ } else {
+ user_msg = "\r\nYou are already logged in - access denied\r\n\n";
+ }
+
+ request->reply->code = PW_AUTHENTICATION_REJECT;
+
+ /*
+ * They're trying to log in too many times.
+ * Remove ALL reply attributes.
+ */
+ pairfree(&request->reply->vps);
+ radius_pairmake(request, &request->reply->vps,
+ "Reply-Message",
+ user_msg, T_OP_SET);
+
+ snprintf(logstr, sizeof(logstr), "Multiple logins (max %d) %s",
+ check_item->vp_integer,
+ r == 2 ? "[MPP attempt]" : "");
+ rad_authlog(logstr, request, 1);
+
+ result = -1;
+ }
+ }
+ }
+#endif
+
+ /*
+ * Result should be >= 0 here - if not, it means the user
+ * is rejected, so we just process post-auth and return.
+ */
+ if (result < 0) {
+ return RLM_MODULE_REJECT;
+ }
+
+ /*
+ * Add the port number to the Framed-IP-Address if
+ * vp->addport is set.
+ */
+ if (((tmp = pairfind(request->reply->vps,
+ PW_FRAMED_IP_ADDRESS)) != NULL) &&
+ (tmp->flags.addport != 0)) {
+ VALUE_PAIR *vpPortId;
+
+ /*
+ * Find the NAS port ID.
+ */
+ if ((vpPortId = pairfind(request->packet->vps,
+ PW_NAS_PORT)) != NULL) {
+ unsigned long tvalue = ntohl(tmp->vp_integer);
+ tmp->vp_integer = htonl(tvalue + vpPortId->vp_integer);
+ tmp->flags.addport = 0;
+ ip_ntoa(tmp->vp_strvalue, tmp->vp_integer);
+ } else {
+ RDEBUG2("WARNING: No NAS-Port attribute in request. CANNOT return a Framed-IP-Address + NAS-Port.\n");
+ pairdelete(&request->reply->vps, PW_FRAMED_IP_ADDRESS);
+ }
+ }
+
+ /*
+ * Set the reply to Access-Accept, if it hasn't already
+ * been set to something. (i.e. Access-Challenge)
+ */
+ if (request->reply->code == 0)
+ request->reply->code = PW_AUTHENTICATION_ACK;
+
+ if ((module_msg = pairfind(request->packet->vps,PW_MODULE_SUCCESS_MESSAGE)) != NULL){
+ char msg[MAX_STRING_LEN+12];
+
+ snprintf(msg, sizeof(msg), "Login OK (%s)",
+ module_msg->vp_strvalue);
+ rad_authlog(msg, request, 1);
+ } else {
+ rad_authlog("Login OK", request, 1);
+ }
+
+ /*
+ * Run the modules in the 'post-auth' section.
+ */
+ result = rad_postauth(request);
+
+ return result;
+}
+
+
+/*
+ * Send an authentication response packet
+ */
+static int auth_socket_send(rad_listen_t *listener, REQUEST *request)
+{
+ rad_assert(request->listener == listener);
+ rad_assert(listener->send == auth_socket_send);
+
+ return rad_send(request->reply, request->packet,
+ request->client->secret);
+}
+
+
+/*
+ * Check if an incoming request is "ok"
+ *
+ * It takes packets, not requests. It sees if the packet looks
+ * OK. If so, it does a number of sanity checks on it.
+ */
+static int auth_socket_recv(rad_listen_t *listener,
+ RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+{
+ ssize_t rcode;
+ int code, src_port;
+ RADIUS_PACKET *packet;
+ RAD_REQUEST_FUNP fun = NULL;
+ RADCLIENT *client;
+ fr_ipaddr_t src_ipaddr;
+
+ rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
+ if (rcode < 0) return 0;
+
+ RAD_STATS_TYPE_INC(listener, total_requests);
+
+ if (rcode < 20) { /* AUTH_HDR_LEN */
+ RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+ return 0;
+ }
+
+ if ((client = client_listener_find(listener,
+ &src_ipaddr, src_port)) == NULL) {
+ rad_recv_discard(listener->fd);
+ RAD_STATS_TYPE_INC(listener, total_invalid_requests);
+ return 0;
+ }
+
+ /*
+ * Some sanity checks, based on the packet code.
+ */
+ switch(code) {
+ case PW_AUTHENTICATION_REQUEST:
+ RAD_STATS_CLIENT_INC(listener, client, total_requests);
+ fun = rad_authenticate;
+ break;
+
+ case PW_STATUS_SERVER:
+ if (!mainconfig.status_server) {
+ rad_recv_discard(listener->fd);
+ RAD_STATS_TYPE_INC(listener, total_packets_dropped);
+ RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
+ DEBUG("WARNING: Ignoring Status-Server request due to security configuration");
+ return 0;
+ }
+ fun = rad_status_server;
+ break;
+
+ default:
+ rad_recv_discard(listener->fd);
+ RAD_STATS_INC(radius_auth_stats.total_unknown_types);
+ RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
+
+ DEBUG("Invalid packet code %d sent to authentication port from client %s port %d : IGNORED",
+ code, client->shortname, src_port);
+ return 0;
+ break;
+ } /* switch over packet types */
+
+ /*
+ * Now that we've sanity checked everything, receive the
+ * packet.
+ */
+ packet = rad_recv(listener->fd, client->message_authenticator);
+ if (!packet) {
+ RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+ DEBUG("%s", fr_strerror());
+ return 0;
+ }
+
+ if (!received_request(listener, packet, prequest, client)) {
+ RAD_STATS_TYPE_INC(listener, total_packets_dropped);
+ RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
+ rad_free(&packet);
+ return 0;
+ }
+
+ *pfun = fun;
+ return 1;
+}
+
+
+static int auth_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+ if (!request->reply->code) return 0;
+
+ rad_encode(request->reply, request->packet,
+ request->client->secret);
+ rad_sign(request->reply, request->packet,
+ request->client->secret);
+
+ return 0;
+}
+
+
+static int auth_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+ if (rad_verify(request->packet, NULL,
+ request->client->secret) < 0) {
+ return -1;
+ }
+
+ return rad_decode(request->packet, NULL,
+ request->client->secret);
+}
+
+frs_module_t frs_auth = {
+ FRS_MODULE_INIT, RAD_LISTEN_AUTH, "auth",
+ listen_socket_parse, NULL,
+ auth_socket_recv, auth_socket_send,
+ listen_socket_print, auth_socket_encode, auth_socket_decode
+};
--- /dev/null
+TARGET = frs_control
+SRCS = frs_control.c
+HEADERS =
+RLM_CFLAGS =
+RLM_LIBS =
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
* Copyright 2008 Alan DeKok <aland@deployingradius.com>
*/
-#ifdef WITH_COMMAND_SOCKET
-
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
#include <freeradius-devel/modpriv.h>
#include <freeradius-devel/conffile.h>
#include <freeradius-devel/stats.h>
{
fr_command_socket_t *sock;
+ this->data = rad_malloc(sizeof(fr_command_socket_t));
+ memset(this->data, 0, sizeof(fr_command_socket_t));
sock = this->data;
if (cf_section_parse(cs, sock, command_config) < 0) {
return 0;
}
-
static int command_domain_accept(rad_listen_t *listener,
UNUSED RAD_REQUEST_FUNP *pfun,
UNUSED REQUEST **prequest)
return -1;
}
-
/*
* Add the new listener.
*/
- this = listen_alloc(listener->type);
+ this = listen_alloc(listener->frs->name);
if (!this) return -1;
/*
* Copy everything, including the pointer to the socket
* information.
*/
+ this->data = rad_malloc(sizeof(fr_command_socket_t));
+ memset(this->data, 0, sizeof(fr_command_socket_t));
sock = this->data;
memcpy(this, listener, sizeof(*this));
this->status = RAD_LISTEN_STATUS_INIT;
return 0;
}
-#endif /* WITH_COMMAND_SOCKET */
+frs_module_t frs_control = {
+ FRS_MODULE_INIT, RAD_LISTEN_COMMAND, "control",
+ command_socket_parse, NULL,
+ command_domain_accept, command_domain_send,
+ command_socket_print, command_socket_encode, command_socket_decode
+};
--- /dev/null
+TARGET = frs_detail
+SRCS = frs_detail.c
+HEADERS =
+RLM_CFLAGS =
+RLM_LIBS =
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
#include <freeradius-devel/modules.h>
#include <freeradius-devel/detail.h>
#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/detail.h>
+
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#include <fcntl.h>
-#ifdef WITH_DETAIL
-
#define USEC (1000000)
typedef struct listen_detail_t {
#define STATE_REPLIED (7)
/*
+ * Copied from rad_accounting without any changes.
+ *
+ * This isn't perfect, but it helps with modularization
+ */
+static int detail_accounting(REQUEST *request)
+{
+ int result = RLM_MODULE_OK;
+
+
+#ifdef WITH_PROXY
+#define WAS_PROXIED (request->proxy)
+#else
+#define WAS_PROXIED (0)
+#endif
+
+ /*
+ * Run the modules only once, before proxying.
+ */
+ if (!WAS_PROXIED) {
+ VALUE_PAIR *vp;
+ int acct_type = 0;
+
+ result = module_preacct(request);
+ switch (result) {
+ /*
+ * The module has a number of OK return codes.
+ */
+ case RLM_MODULE_NOOP:
+ case RLM_MODULE_OK:
+ case RLM_MODULE_UPDATED:
+ break;
+ /*
+ * The module handled the request, stop here.
+ */
+ case RLM_MODULE_HANDLED:
+ return result;
+ /*
+ * The module failed, or said the request is
+ * invalid, therefore we stop here.
+ */
+ case RLM_MODULE_FAIL:
+ case RLM_MODULE_INVALID:
+ case RLM_MODULE_NOTFOUND:
+ case RLM_MODULE_REJECT:
+ case RLM_MODULE_USERLOCK:
+ default:
+ return result;
+ }
+
+ /*
+ * Do the data storage before proxying. This is to ensure
+ * that we log the packet, even if the proxy never does.
+ */
+ vp = pairfind(request->config_items, PW_ACCT_TYPE);
+ if (vp) {
+ DEBUG2(" Found Acct-Type %s", vp->vp_strvalue);
+ acct_type = vp->vp_integer;
+ }
+ result = module_accounting(acct_type, request);
+ switch (result) {
+ /*
+ * In case the accounting module returns FAIL,
+ * it's still useful to send the data to the
+ * proxy.
+ */
+ case RLM_MODULE_FAIL:
+ case RLM_MODULE_NOOP:
+ case RLM_MODULE_OK:
+ case RLM_MODULE_UPDATED:
+ break;
+ /*
+ * The module handled the request, don't reply.
+ */
+ case RLM_MODULE_HANDLED:
+ return result;
+ /*
+ * Neither proxy, nor reply to invalid requests.
+ */
+ case RLM_MODULE_INVALID:
+ case RLM_MODULE_NOTFOUND:
+ case RLM_MODULE_REJECT:
+ case RLM_MODULE_USERLOCK:
+ default:
+ return result;
+ }
+
+ /*
+ * Maybe one of the preacct modules has decided
+ * that a proxy should be used.
+ */
+ if ((vp = pairfind(request->config_items, PW_PROXY_TO_REALM))) {
+ REALM *realm;
+
+ /*
+ * Check whether Proxy-To-Realm is
+ * a LOCAL realm.
+ */
+ realm = realm_find2(vp->vp_strvalue);
+ if (realm && !realm->acct_pool) {
+ DEBUG("rad_accounting: Cancelling proxy to realm %s, as it is a LOCAL realm.", realm->name);
+ pairdelete(&request->config_items, PW_PROXY_TO_REALM);
+ } else {
+ /*
+ * Don't reply to the NAS now because
+ * we have to send the proxied packet
+ * before that.
+ */
+ return result;
+ }
+ }
+ }
+
+ /*
+ * We get here IF we're not proxying, OR if we've
+ * received the accounting reply from the end server,
+ * THEN we can reply to the NAS.
+ * If the accounting module returns NOOP, the data
+ * storage did not succeed, so radiusd should not send
+ * Accounting-Response.
+ */
+ switch (result) {
+ /*
+ * Send back an ACK to the NAS.
+ */
+ case RLM_MODULE_OK:
+ case RLM_MODULE_UPDATED:
+ request->reply->code = PW_ACCOUNTING_RESPONSE;
+ break;
+ /*
+ * The module handled the request, don't reply.
+ */
+ case RLM_MODULE_HANDLED:
+ break;
+ /*
+ * Failed to log or to proxy the accounting data,
+ * therefore don't reply to the NAS.
+ */
+ case RLM_MODULE_FAIL:
+ case RLM_MODULE_INVALID:
+ case RLM_MODULE_NOOP:
+ case RLM_MODULE_NOTFOUND:
+ case RLM_MODULE_REJECT:
+ case RLM_MODULE_USERLOCK:
+ default:
+ break;
+ }
+ return result;
+}
+
+
+/*
* If we're limiting outstanding packets, then mark the response
* as being sent.
*/
return 0;
}
-int detail_delay(rad_listen_t *listener)
-{
- listen_detail_t *data = listener->data;
-
- if (!data->signal) return 0;
-
- data->signal = 0;
-
- return data->delay_time;
-}
-
/*
* Open the detail file, if we can.
vp->vp_integer += time(NULL) - data->timestamp;
}
- *pfun = rad_accounting;
+ *pfun = detail_accounting;
if (debug_flag) {
fr_printf_log("detail_recv: Read packet from %s\n", data->filename_work);
this->server);
}
-int detail_encode(UNUSED rad_listen_t *this, UNUSED REQUEST *request)
+/*
+ * FIXME: src/main/event.c doesn't ever call encode, so
+ * we overload it here.
+ */
+int detail_encode(rad_listen_t *this, UNUSED REQUEST *request)
{
- /*
- * We never encode responses "sent to" the detail file.
- */
- return 0;
+ listen_detail_t *data = this->data;
+
+ if (!data->signal) return 0;
+
+ data->signal = 0;
+
+ return data->delay_time;
}
int detail_decode(UNUSED rad_listen_t *this, UNUSED REQUEST *request)
{
/*
- * We never decode responses read from the detail file.
+ * We never decode responses "sent to" the detail file.
*/
return 0;
}
return 0;
}
-#endif
+
+frs_module_t frs_detail = {
+ FRS_MODULE_INIT, RAD_LISTEN_DETAIL, "detail",
+ detail_parse, detail_free,
+ detail_recv, detail_send,
+ detail_print, detail_encode, detail_decode
+};
--- /dev/null
+TARGET = frs_dhcp
+SRCS = frs_dhcp.c dhcp.c
+HEADERS =
+RLM_CFLAGS =
+RLM_LIBS =
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
#include <freeradius-devel/ident.h>
RCSID("$Id$")
-#include <freeradius-devel/libradius.h>
+#include <freeradius-devel/radiusd.h>
#include <freeradius-devel/udpfromto.h>
-#include <freeradius-devel/dhcp.h>
+#include "dhcp.h"
#ifdef WITH_DHCP
#define DHCP_CHADDR_LEN (16)
* Copyright 2008 Alan DeKok <aland@deployingradius.com>
*/
-#ifdef WITH_DHCP
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/conffile.h>
+#include <freeradius-devel/rad_assert.h>
+#include "dhcp.h"
static int dhcp_process(REQUEST *request)
{
int on = 1;
listen_socket_t *sock;
- rcode = common_socket_parse(cs, this);
+ rcode = listen_socket_parse(cs, this);
if (rcode != 0) return rcode;
sock = this->data;
{
return fr_dhcp_decode(request->packet);
}
-#endif /* WITH_DCHP */
+
+
+frs_module_t frs_dhcp = {
+ FRS_MODULE_INIT, RAD_LISTEN_DHCP, "dhcp",
+ dhcp_socket_parse, NULL,
+ dhcp_socket_recv, dhcp_socket_send,
+ listen_socket_print, dhcp_socket_encode, dhcp_socket_decode
+};
--- /dev/null
+TARGET = frs_proxy
+SRCS = frs_proxy.c
+HEADERS =
+RLM_CFLAGS =
+RLM_LIBS =
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
--- /dev/null
+/*
+ * proxy.c Handle PROXY traffic.
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2007 The FreeRADIUS server project
+ * Copyright 2007 Alan DeKok <aland@deployingradius.com>
+ */
+
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/rad_assert.h>
+
+
+/*
+ * Send a packet to a home server.
+ *
+ * FIXME: have different code for proxy auth & acct!
+ */
+static int proxy_socket_send(rad_listen_t *listener, REQUEST *request)
+{
+ listen_socket_t *sock = listener->data;
+
+ rad_assert(request->proxy_listener == listener);
+ rad_assert(listener->send == proxy_socket_send);
+
+ request->proxy->src_ipaddr = sock->ipaddr;
+ request->proxy->src_port = sock->port;
+
+ return rad_send(request->proxy, request->packet,
+ request->home_server->secret);
+}
+
+/*
+ * Recieve packets from a proxy socket.
+ */
+static int proxy_socket_recv(rad_listen_t *listener,
+ RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+{
+ REQUEST *request;
+ RADIUS_PACKET *packet;
+ char buffer[128];
+
+ packet = rad_recv(listener->fd, 0);
+ if (!packet) {
+ radlog(L_ERR, "%s", fr_strerror());
+ return 0;
+ }
+
+ /*
+ * FIXME: Client MIB updates?
+ */
+ switch(packet->code) {
+ case PW_AUTHENTICATION_ACK:
+ case PW_ACCESS_CHALLENGE:
+ case PW_AUTHENTICATION_REJECT:
+#ifdef WITH_ACCOUNTING
+ case PW_ACCOUNTING_RESPONSE:
+#endif
+ break;
+
+ default:
+ /*
+ * FIXME: Update MIB for packet types?
+ */
+ radlog(L_ERR, "Invalid packet code %d sent to a proxy port "
+ "from home server %s port %d - ID %d : IGNORED",
+ packet->code,
+ ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)),
+ packet->src_port, packet->id);
+ rad_free(&packet);
+ return 0;
+ }
+
+ request = received_proxy_response(packet);
+ if (!request) {
+ return 0;
+ }
+
+ rad_assert(request->process != NULL);
+
+ *pfun = request->process;
+ *prequest = request;
+
+ return 1;
+}
+
+static int proxy_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+ rad_encode(request->proxy, NULL, request->home_server->secret);
+ rad_sign(request->proxy, NULL, request->home_server->secret);
+
+ return 0;
+}
+
+
+static int proxy_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+ if (rad_verify(request->proxy_reply, request->proxy,
+ request->home_server->secret) < 0) {
+ return -1;
+ }
+
+ return rad_decode(request->proxy_reply, request->proxy,
+ request->home_server->secret);
+}
+
+frs_module_t frs_proxy = {
+ FRS_MODULE_INIT, RAD_LISTEN_PROXY, "proxy",
+ listen_socket_parse, NULL,
+ proxy_socket_recv, proxy_socket_send,
+ listen_socket_print, proxy_socket_encode, proxy_socket_decode
+};
--- /dev/null
+TARGET = frs_status
+SRCS = frs_status.c
+HEADERS =
+RLM_CFLAGS =
+RLM_LIBS =
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
--- /dev/null
+/*
+ * status.c Statistics processing
+ *
+ * Version: $Id$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * Copyright 2008 The FreeRADIUS server project
+ * Copyright 2008 Alan DeKok <aland@deployingradius.com>
+ */
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/rad_assert.h>
+#include <freeradius-devel/stats.h>
+
+#ifdef WITH_STATS
+typedef struct fr_stats2vp {
+ int attribute;
+ size_t offset;
+} fr_stats2vp;
+
+/*
+ * Authentication
+ */
+static fr_stats2vp authvp[] = {
+ { 128, offsetof(fr_stats_t, total_requests) },
+ { 129, offsetof(fr_stats_t, total_access_accepts) },
+ { 130, offsetof(fr_stats_t, total_access_rejects) },
+ { 131, offsetof(fr_stats_t, total_access_challenges) },
+ { 132, offsetof(fr_stats_t, total_responses) },
+ { 133, offsetof(fr_stats_t, total_dup_requests) },
+ { 134, offsetof(fr_stats_t, total_malformed_requests) },
+ { 135, offsetof(fr_stats_t, total_bad_authenticators) },
+ { 136, offsetof(fr_stats_t, total_packets_dropped) },
+ { 137, offsetof(fr_stats_t, total_unknown_types) },
+ { 0, 0 }
+};
+
+
+#ifdef WITH_PROXY
+/*
+ * Proxied authentication requests.
+ */
+static fr_stats2vp proxy_authvp[] = {
+ { 138, offsetof(fr_stats_t, total_requests) },
+ { 139, offsetof(fr_stats_t, total_access_accepts) },
+ { 140, offsetof(fr_stats_t, total_access_rejects) },
+ { 141, offsetof(fr_stats_t, total_access_challenges) },
+ { 142, offsetof(fr_stats_t, total_responses) },
+ { 143, offsetof(fr_stats_t, total_dup_requests) },
+ { 144, offsetof(fr_stats_t, total_malformed_requests) },
+ { 145, offsetof(fr_stats_t, total_bad_authenticators) },
+ { 146, offsetof(fr_stats_t, total_packets_dropped) },
+ { 147, offsetof(fr_stats_t, total_unknown_types) },
+ { 0, 0 }
+};
+#endif
+
+
+#ifdef WITH_ACCOUNTING
+/*
+ * Accounting
+ */
+static fr_stats2vp acctvp[] = {
+ { 148, offsetof(fr_stats_t, total_requests) },
+ { 149, offsetof(fr_stats_t, total_responses) },
+ { 150, offsetof(fr_stats_t, total_dup_requests) },
+ { 151, offsetof(fr_stats_t, total_malformed_requests) },
+ { 152, offsetof(fr_stats_t, total_bad_authenticators) },
+ { 153, offsetof(fr_stats_t, total_packets_dropped) },
+ { 154, offsetof(fr_stats_t, total_unknown_types) },
+ { 0, 0 }
+};
+
+#ifdef WITH_PROXY
+static fr_stats2vp proxy_acctvp[] = {
+ { 155, offsetof(fr_stats_t, total_requests) },
+ { 156, offsetof(fr_stats_t, total_responses) },
+ { 157, offsetof(fr_stats_t, total_dup_requests) },
+ { 158, offsetof(fr_stats_t, total_malformed_requests) },
+ { 159, offsetof(fr_stats_t, total_bad_authenticators) },
+ { 160, offsetof(fr_stats_t, total_packets_dropped) },
+ { 161, offsetof(fr_stats_t, total_unknown_types) },
+ { 0, 0 }
+};
+#endif
+#endif
+
+static fr_stats2vp client_authvp[] = {
+ { 128, offsetof(fr_stats_t, total_requests) },
+ { 129, offsetof(fr_stats_t, total_access_accepts) },
+ { 130, offsetof(fr_stats_t, total_access_rejects) },
+ { 131, offsetof(fr_stats_t, total_access_challenges) },
+ { 132, offsetof(fr_stats_t, total_responses) },
+ { 133, offsetof(fr_stats_t, total_dup_requests) },
+ { 134, offsetof(fr_stats_t, total_malformed_requests) },
+ { 135, offsetof(fr_stats_t, total_bad_authenticators) },
+ { 136, offsetof(fr_stats_t, total_packets_dropped) },
+ { 137, offsetof(fr_stats_t, total_unknown_types) },
+ { 0, 0 }
+};
+
+#ifdef WITH_ACCOUNTING
+static fr_stats2vp client_acctvp[] = {
+ { 155, offsetof(fr_stats_t, total_requests) },
+ { 156, offsetof(fr_stats_t, total_responses) },
+ { 157, offsetof(fr_stats_t, total_dup_requests) },
+ { 158, offsetof(fr_stats_t, total_malformed_requests) },
+ { 159, offsetof(fr_stats_t, total_bad_authenticators) },
+ { 160, offsetof(fr_stats_t, total_packets_dropped) },
+ { 161, offsetof(fr_stats_t, total_unknown_types) },
+ { 0, 0 }
+};
+#endif
+
+#define FR2ATTR(x) ((11344 << 16) | (x))
+
+static void request_stats_addvp(REQUEST *request,
+ fr_stats2vp *table, fr_stats_t *stats)
+{
+ int i;
+ VALUE_PAIR *vp;
+
+ for (i = 0; table[i].attribute != 0; i++) {
+ vp = radius_paircreate(request, &request->reply->vps,
+ FR2ATTR(table[i].attribute),
+ PW_TYPE_INTEGER);
+ if (!vp) continue;
+
+ vp->vp_integer = *(int *)(((char *) stats) + table[i].offset);
+ }
+}
+
+
+/*
+ * Find a listener by IP address && port.
+ */
+static rad_listen_t *listener_find_byipaddr(const fr_ipaddr_t *ipaddr,
+ int port)
+{
+ rad_listen_t *this;
+
+ for (this = mainconfig.listen; this != NULL; this = this->next) {
+ listen_socket_t *sock;
+
+ if ((this->type != RAD_LISTEN_AUTH) &&
+ (this->type != RAD_LISTEN_ACCT)) continue;
+
+ sock = this->data;
+
+ if ((sock->port == port) &&
+ (fr_ipaddr_cmp(ipaddr, &sock->ipaddr) == 0)) {
+ return this;
+ }
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Find a RADCLIENT_LIST based on listening IP address && port
+ */
+static RADCLIENT_LIST *listener_find_client_list(const fr_ipaddr_t *ipaddr,
+ int port)
+{
+ listen_socket_t *sock;
+ rad_listen_t *this;
+
+ this = listener_find_byipaddr(ipaddr, port);
+ if (!this) return NULL;
+
+ sock = this->data;
+ return sock->clients;
+}
+
+static void request_stats_reply(REQUEST *request)
+{
+ VALUE_PAIR *flag, *vp;
+
+ /*
+ * Statistics are available ONLY on a "status" port.
+ */
+ rad_assert(request->packet->code == PW_STATUS_SERVER);
+ rad_assert(request->listener->type == RAD_LISTEN_NONE);
+
+ flag = pairfind(request->packet->vps, FR2ATTR(127));
+ if (!flag || (flag->vp_integer == 0)) return;
+
+ /*
+ * Authentication.
+ */
+ if (((flag->vp_integer & 0x01) != 0) &&
+ ((flag->vp_integer & 0xc0) == 0)) {
+ request_stats_addvp(request, authvp, &radius_auth_stats);
+ }
+
+#ifdef WITH_ACCOUNTING
+ /*
+ * Accounting
+ */
+ if (((flag->vp_integer & 0x02) != 0) &&
+ ((flag->vp_integer & 0xc0) == 0)) {
+ request_stats_addvp(request, acctvp, &radius_acct_stats);
+ }
+#endif
+
+#ifdef WITH_PROXY
+ /*
+ * Proxied authentication requests.
+ */
+ if (((flag->vp_integer & 0x04) != 0) &&
+ ((flag->vp_integer & 0x20) == 0)) {
+ request_stats_addvp(request, proxy_authvp, &proxy_auth_stats);
+ }
+
+#ifdef WITH_ACCOUNTING
+ /*
+ * Proxied accounting requests.
+ */
+ if (((flag->vp_integer & 0x08) != 0) &&
+ ((flag->vp_integer & 0x20) == 0)) {
+ request_stats_addvp(request, proxy_acctvp, &proxy_acct_stats);
+ }
+#endif
+#endif
+
+ /*
+ * Internal server statistics
+ */
+ if ((flag->vp_integer & 0x10) != 0) {
+ vp = radius_paircreate(request, &request->reply->vps,
+ FR2ATTR(176), PW_TYPE_DATE);
+ if (vp) vp->vp_date = radius_start_time.tv_sec;
+ vp = radius_paircreate(request, &request->reply->vps,
+ FR2ATTR(177), PW_TYPE_DATE);
+ if (vp) vp->vp_date = radius_hup_time.tv_sec;
+
+#ifdef HAVE_PTHREAD_H
+ int i, array[RAD_LISTEN_MAX];
+
+ thread_pool_queue_stats(array);
+
+ for (i = 0; i <= RAD_LISTEN_DETAIL; i++) {
+ vp = radius_paircreate(request, &request->reply->vps,
+ FR2ATTR(162 + i),
+ PW_TYPE_INTEGER);
+
+ if (!vp) continue;
+ vp->vp_integer = array[i];
+ }
+#endif
+ }
+
+ /*
+ * For a particular client.
+ */
+ if ((flag->vp_integer & 0x20) != 0) {
+ fr_ipaddr_t ipaddr;
+ VALUE_PAIR *server_ip, *server_port = NULL;
+ RADCLIENT *client = NULL;
+ RADCLIENT_LIST *cl = NULL;
+
+ /*
+ * See if we need to look up the client by server
+ * socket.
+ */
+ server_ip = pairfind(request->packet->vps, FR2ATTR(170));
+ if (server_ip) {
+ server_port = pairfind(request->packet->vps,
+ FR2ATTR(171));
+
+ if (server_port) {
+ ipaddr.af = AF_INET;
+ ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
+ cl = listener_find_client_list(&ipaddr, server_port->vp_integer);
+
+ /*
+ * Not found: don't do anything
+ */
+ if (!cl) return;
+ }
+ }
+
+
+ vp = pairfind(request->packet->vps, FR2ATTR(167));
+ if (vp) {
+ ipaddr.af = AF_INET;
+ ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr;
+ client = client_find(cl, &ipaddr);
+
+ /*
+ * Else look it up by number.
+ */
+ } else if ((vp = pairfind(request->packet->vps,
+ FR2ATTR(168))) != NULL) {
+ client = client_findbynumber(cl, vp->vp_integer);
+ }
+
+ if (client) {
+ /*
+ * If found, echo it back, along with
+ * the requested statistics.
+ */
+ pairadd(&request->reply->vps, paircopyvp(vp));
+
+ /*
+ * When retrieving client by number, also
+ * echo back it's IP address.
+ */
+ if ((vp->type == PW_TYPE_INTEGER) &&
+ (client->ipaddr.af == AF_INET)) {
+ vp = radius_paircreate(request,
+ &request->reply->vps,
+ FR2ATTR(167),
+ PW_TYPE_IPADDR);
+ if (vp) {
+ vp->vp_ipaddr = client->ipaddr.ipaddr.ip4addr.s_addr;
+ }
+
+ if (client->prefix != 32) {
+ vp = radius_paircreate(request,
+ &request->reply->vps,
+ FR2ATTR(169),
+ PW_TYPE_INTEGER);
+ if (vp) {
+ vp->vp_integer = client->prefix;
+ }
+ }
+ }
+
+ if (server_ip) {
+ pairadd(&request->reply->vps,
+ paircopyvp(server_ip));
+ pairadd(&request->reply->vps,
+ paircopyvp(server_port));
+ }
+
+ if (client->auth &&
+ ((flag->vp_integer & 0x01) != 0)) {
+ request_stats_addvp(request, client_authvp,
+ client->auth);
+ }
+#ifdef WITH_ACCOUNTING
+ if (client->acct &&
+ ((flag->vp_integer & 0x01) != 0)) {
+ request_stats_addvp(request, client_acctvp,
+ client->acct);
+ }
+#endif
+ } /* else client wasn't found, don't echo it back */
+ }
+
+ /*
+ * For a particular "listen" socket.
+ */
+ if (((flag->vp_integer & 0x40) != 0) &&
+ ((flag->vp_integer & 0x03) != 0)) {
+ rad_listen_t *this;
+ VALUE_PAIR *server_ip, *server_port;
+ fr_ipaddr_t ipaddr;
+
+ /*
+ * See if we need to look up the server by socket
+ * socket.
+ */
+ server_ip = pairfind(request->packet->vps, FR2ATTR(170));
+ if (!server_ip) return;
+
+ server_port = pairfind(request->packet->vps,
+ FR2ATTR(171));
+ if (!server_port) return;
+
+ ipaddr.af = AF_INET;
+ ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
+ this = listener_find_byipaddr(&ipaddr,
+ server_port->vp_integer);
+
+ /*
+ * Not found: don't do anything
+ */
+ if (!this) return;
+
+ pairadd(&request->reply->vps,
+ paircopyvp(server_ip));
+ pairadd(&request->reply->vps,
+ paircopyvp(server_port));
+
+ if (((flag->vp_integer & 0x01) != 0) &&
+ ((request->listener->type == RAD_LISTEN_AUTH) ||
+ (request->listener->type == RAD_LISTEN_NONE))) {
+ request_stats_addvp(request, authvp, &this->stats);
+ }
+
+#ifdef WITH_ACCOUNTING
+ if (((flag->vp_integer & 0x02) != 0) &&
+ ((request->listener->type == RAD_LISTEN_ACCT) ||
+ (request->listener->type == RAD_LISTEN_NONE))) {
+ request_stats_addvp(request, acctvp, &this->stats);
+ }
+#endif
+ }
+
+ /*
+ * Home servers.
+ */
+ if (((flag->vp_integer & 0x80) != 0) &&
+ ((flag->vp_integer & 0x03) != 0)) {
+ home_server *home;
+ VALUE_PAIR *server_ip, *server_port;
+ fr_ipaddr_t ipaddr;
+
+ /*
+ * See if we need to look up the server by socket
+ * socket.
+ */
+ server_ip = pairfind(request->packet->vps, FR2ATTR(170));
+ if (!server_ip) return;
+
+ server_port = pairfind(request->packet->vps,
+ FR2ATTR(171));
+ if (!server_port) return;
+
+ ipaddr.af = AF_INET;
+ ipaddr.ipaddr.ip4addr.s_addr = server_ip->vp_ipaddr;
+ home = home_server_find(&ipaddr, server_port->vp_integer);
+
+ /*
+ * Not found: don't do anything
+ */
+ if (!home) return;
+
+ pairadd(&request->reply->vps,
+ paircopyvp(server_ip));
+ pairadd(&request->reply->vps,
+ paircopyvp(server_port));
+
+ vp = radius_paircreate(request, &request->reply->vps,
+ FR2ATTR(172), PW_TYPE_INTEGER);
+ if (vp) vp->vp_integer = home->currently_outstanding;
+
+ vp = radius_paircreate(request, &request->reply->vps,
+ FR2ATTR(173), PW_TYPE_INTEGER);
+ if (vp) vp->vp_integer = home->state;
+
+ if ((home->state == HOME_STATE_ALIVE) &&
+ (home->revive_time.tv_sec != 0)) {
+ vp = radius_paircreate(request, &request->reply->vps,
+ FR2ATTR(175), PW_TYPE_DATE);
+ if (vp) vp->vp_date = home->revive_time.tv_sec;
+ }
+
+ if ((home->state == HOME_STATE_ALIVE) &&
+ (home->ema.window > 0)) {
+ vp = radius_paircreate(request,
+ &request->reply->vps,
+ FR2ATTR(178),
+ PW_TYPE_INTEGER);
+ if (vp) vp->vp_integer = home->ema.window;
+ vp = radius_paircreate(request,
+ &request->reply->vps,
+ FR2ATTR(179),
+ PW_TYPE_INTEGER);
+ if (vp) vp->vp_integer = home->ema.ema1 / EMA_SCALE;
+ vp = radius_paircreate(request,
+ &request->reply->vps,
+ FR2ATTR(180),
+ PW_TYPE_INTEGER);
+ if (vp) vp->vp_integer = home->ema.ema10 / EMA_SCALE;
+
+ }
+
+ if (home->state == HOME_STATE_IS_DEAD) {
+ vp = radius_paircreate(request, &request->reply->vps,
+ FR2ATTR(174), PW_TYPE_DATE);
+ if (vp) vp->vp_date = home->zombie_period_start.tv_sec + home->zombie_period;
+ }
+
+ if (((flag->vp_integer & 0x01) != 0) &&
+ (home->type == HOME_TYPE_AUTH)) {
+ request_stats_addvp(request, proxy_authvp,
+ &home->stats);
+ }
+
+#ifdef WITH_ACCOUNTING
+ if (((flag->vp_integer & 0x02) != 0) &&
+ (home->type == HOME_TYPE_ACCT)) {
+ request_stats_addvp(request, proxy_acctvp,
+ &home->stats);
+ }
+#endif
+ }
+}
+
+static int status_process(REQUEST *request)
+{
+ rad_status_server(request);
+
+ request_stats_reply(request);
+
+ return 0;
+}
+
+/*
+ * Check if an incoming request is "ok"
+ *
+ * It takes packets, not requests. It sees if the packet looks
+ * OK. If so, it does a number of sanity checks on it.
+ */
+static int status_socket_recv(rad_listen_t *listener,
+ RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+{
+ ssize_t rcode;
+ int code, src_port;
+ RADIUS_PACKET *packet;
+ RADCLIENT *client;
+ fr_ipaddr_t src_ipaddr;
+
+ rcode = rad_recv_header(listener->fd, &src_ipaddr, &src_port, &code);
+ if (rcode < 0) return 0;
+
+ RAD_STATS_TYPE_INC(listener, total_requests);
+
+ if (rcode < 20) { /* AUTH_HDR_LEN */
+ RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+ return 0;
+ }
+
+ if ((client = client_listener_find(listener,
+ &src_ipaddr, src_port)) == NULL) {
+ rad_recv_discard(listener->fd);
+ RAD_STATS_TYPE_INC(listener, total_invalid_requests);
+ return 0;
+ }
+
+ /*
+ * We only understand Status-Server on this socket.
+ */
+ if (code != PW_STATUS_SERVER) {
+ DEBUG("Ignoring packet code %d sent to Status-Server port",
+ code);
+ rad_recv_discard(listener->fd);
+ RAD_STATS_TYPE_INC(listener, total_unknown_types);
+ RAD_STATS_CLIENT_INC(listener, client, total_unknown_types);
+ return 0;
+ }
+
+ /*
+ * Now that we've sanity checked everything, receive the
+ * packet.
+ */
+ packet = rad_recv(listener->fd, 1); /* require message authenticator */
+ if (!packet) {
+ RAD_STATS_TYPE_INC(listener, total_malformed_requests);
+ DEBUG("%s", fr_strerror());
+ return 0;
+ }
+
+ if (!received_request(listener, packet, prequest, client)) {
+ RAD_STATS_TYPE_INC(listener, total_packets_dropped);
+ RAD_STATS_CLIENT_INC(listener, client, total_packets_dropped);
+ rad_free(&packet);
+ return 0;
+ }
+
+ *pfun = status_process;
+ return 1;
+}
+
+
+/*
+ * Send an authentication response packet
+ */
+static int status_socket_send(rad_listen_t *listener, REQUEST *request)
+{
+ rad_assert(request->listener == listener);
+ rad_assert(listener->send == status_socket_send);
+
+ return rad_send(request->reply, request->packet,
+ request->client->secret);
+}
+
+
+static int status_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+ if (!request->reply->code) return 0;
+
+ rad_encode(request->reply, request->packet,
+ request->client->secret);
+ rad_sign(request->reply, request->packet,
+ request->client->secret);
+
+ return 0;
+}
+
+
+static int status_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
+{
+ if (rad_verify(request->packet, NULL,
+ request->client->secret) < 0) {
+ return -1;
+ }
+
+ return rad_decode(request->packet, NULL,
+ request->client->secret);
+}
+
+
+frs_module_t frs_status = {
+ FRS_MODULE_INIT, RAD_LISTEN_NONE,
+ "status", listen_socket_parse, NULL,
+ status_socket_recv, status_socket_send,
+ listen_socket_print, status_socket_encode, status_socket_decode
+};
+#endif
--- /dev/null
+TARGET = frs_vmps
+SRCS = frs_vmps.c vqp.c
+HEADERS = vqp.h
+RLM_CFLAGS =
+RLM_LIBS =
+
+include ../rules.mak
+
+$(STATIC_OBJS): $(HEADERS)
+
+$(DYNAMIC_OBJS): $(HEADERS)
#include <freeradius-devel/radiusd.h>
#include <freeradius-devel/modules.h>
-#include <freeradius-devel/vqp.h>
-#include <freeradius-devel/vmps.h>
#include <freeradius-devel/rad_assert.h>
+#include "vqp.h"
#ifdef WITH_VMPS
+static int vmps_process(REQUEST *request)
+{
+ DEBUG2("Doing VMPS");
+ module_post_auth(0, request);
+ DEBUG2("Done VMPS");
+
+ request->reply->code = PW_AUTHENTICATION_ACK;
+
+ return 0;
+}
+
+
/*
* Check if an incoming request is "ok"
*
* It takes packets, not requests. It sees if the packet looks
* OK. If so, it does a number of sanity checks on it.
*/
-int vqp_socket_recv(rad_listen_t *listener,
- RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
+static int vqp_socket_recv(rad_listen_t *listener,
+ RAD_REQUEST_FUNP *pfun, REQUEST **prequest)
{
RADIUS_PACKET *packet;
RAD_REQUEST_FUNP fun = NULL;
/*
* Send an authentication response packet
*/
-int vqp_socket_send(rad_listen_t *listener, REQUEST *request)
+static int vqp_socket_send(rad_listen_t *listener, REQUEST *request)
{
rad_assert(request->listener == listener);
rad_assert(listener->send == vqp_socket_send);
}
-int vqp_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
+static int vqp_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
{
return vqp_encode(request->reply, request->packet);
}
-int vqp_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
+static int vqp_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
{
return vqp_decode(request->packet);
}
-int vmps_process(REQUEST *request)
-{
- DEBUG2("Doing VMPS");
- module_post_auth(0, request);
- DEBUG2("Done VMPS");
-
- request->reply->code = PW_AUTHENTICATION_ACK;
-
- return 0;
-}
-#endif
+frs_module_t frs_vmps = {
+ FRS_MODULE_INIT, RAD_LISTEN_VQP, "vmps",
+ listen_socket_parse, NULL,
+ vqp_socket_recv, vqp_socket_send,
+ listen_socket_print, vqp_socket_encode, vqp_socket_decode
+};
+#endif /* WITH_VMPS */
#include <freeradius-devel/ident.h>
RCSID("$Id$");
-#include <freeradius-devel/libradius.h>
+#include <freeradius-devel/radiusd.h>
#include <freeradius-devel/udpfromto.h>
-#include <freeradius-devel/vqp.h>
+#include "vqp.h"
#ifdef WITH_VMPS
+# define debug_pair(vp) do { if (fr_debug_flag && fr_log_fp) { \
+ fputc('\t', fr_log_fp); \
+ vp_print(fr_log_fp, vp); \
+ fputc('\n', fr_log_fp); \
+ } \
+ } while(0)
+
/*
* http://www.openbsd.org/cgi-bin/cvsweb/src/usr.sbin/tcpdump/print-vqp.c
*
* Call authentication recursively, which will
* do PAP, CHAP, MS-CHAP, etc.
*/
- rad_authenticate(fake);
+ request->process(fake);(fake);
/*
* Note that we don't do *anything* with the reply
* Call authentication recursively, which will
* do PAP, CHAP, MS-CHAP, etc.
*/
- rad_authenticate(fake);
+ request->process(fake);
/*
* Note that we don't do *anything* with the reply