You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
309 lines
8.8 KiB
309 lines
8.8 KiB
This patch adds RADIUS authentication support, allowing the |
|
TACACS+ server to authenticate against a RADIUS server. It is |
|
derived from an original "TACACS to RADIUS" patch from Martin |
|
Mersberger <gremlin@portal-to-web.de> which can be found under |
|
http://www.portal-to-web.de/tacacs/. It was cleaned up and ported to the |
|
latest TACACS+ 4.4b1 version by Ralf S. Engelschal <rse@engelschall.com> |
|
for inclusion into the OpenPKG "tacacs" package. |
|
|
|
Index: config.c |
|
--- config.c.orig 2003-04-08 03:37:02.000000000 +0200 |
|
+++ config.c 2003-10-24 17:01:35.000000000 +0200 |
|
@@ -77,6 +77,7 @@ |
|
pam <pam_service> | *** if USE_PAM defined |
|
db <string> | *** if USE_DB defined |
|
ldap <string> | *** if USE_LDAP defined |
|
+ radius <string> | *** if USE_RADIUS defined |
|
nopassword |
|
|
|
*<login_spec> for host and default only allow external lists |
|
@@ -89,6 +90,7 @@ |
|
pam <pam_service> | *** if USE_PAM defined |
|
db <string> | *** if USE_DB defined |
|
ldap <string> | *** if USE_LDAP defined |
|
+ radius <string> | *** if USE_RADIUS defined |
|
login *** use the same method as the login |
|
|
|
*** Added acct_spec 6/12/02 JRM |
|
@@ -964,6 +966,9 @@ |
|
#ifdef USE_PAM |
|
case S_pam: |
|
#endif |
|
+#ifdef USE_RADIUS |
|
+ case S_radius: |
|
+#endif |
|
sym_get(0); |
|
authen_default = tac_strdup(sym_buf); |
|
break; |
|
@@ -1431,6 +1436,9 @@ |
|
#ifdef USE_PAM |
|
case S_pam: |
|
#endif /* USE_PAM */ |
|
+#ifdef USE_RADIUS |
|
+ case S_radius: |
|
+#endif |
|
sym_get(0); |
|
host->login = tac_strdup(sym_buf); |
|
break; |
|
@@ -1494,6 +1502,9 @@ |
|
#ifdef USE_PAM |
|
case S_pam: |
|
#endif /* USE_PAM */ |
|
+#ifdef USE_RADIUS |
|
+ case S_radius: |
|
+#endif |
|
sym_get(0); |
|
host->enable = tac_strdup(sym_buf); |
|
break; |
|
@@ -1743,6 +1754,9 @@ |
|
#ifdef USE_PAM |
|
case S_pam: |
|
#endif /* USE_PAM */ |
|
+#ifdef USE_RADIUS |
|
+ case S_radius: |
|
+#endif |
|
sym_get(0); |
|
user->login = tac_strdup(sym_buf); |
|
break; |
|
@@ -1830,6 +1844,9 @@ |
|
#ifdef USE_PAM |
|
case S_pam: |
|
#endif /* USE_PAM */ |
|
+#ifdef USE_RADIUS |
|
+ case S_radius: |
|
+#endif |
|
sym_get(0); |
|
user->enable = tac_strdup(sym_buf); |
|
break; |
|
Index: parse.c |
|
--- parse.c.orig 2003-03-03 15:30:26.000000000 +0100 |
|
+++ parse.c 2003-10-24 17:03:51.000000000 +0200 |
|
@@ -101,6 +101,9 @@ |
|
#ifdef USE_LDAP |
|
declare ("ldap", S_ldap); |
|
#endif |
|
+#ifdef USE_RADIUS |
|
+ declare("radius", S_radius); |
|
+#endif |
|
declare("member", S_member); |
|
declare("message", S_message); |
|
declare("name", S_name); |
|
@@ -301,5 +304,9 @@ |
|
return("enable_deny"); |
|
case S_unix: |
|
return("unix"); |
|
+#ifdef USE_RADIUS |
|
+ case S_radius: |
|
+ return ("radius"); |
|
+#endif /*USE_PAM */ |
|
} |
|
} |
|
Index: parse.h |
|
--- parse.h.orig 2003-03-03 15:28:07.000000000 +0100 |
|
+++ parse.h 2003-10-24 17:02:26.000000000 +0200 |
|
@@ -108,3 +108,6 @@ |
|
#define S_unix 62 |
|
#define S_motd 63 |
|
#define S_accesslog 64 |
|
+#ifdef USE_RADIUS |
|
+#define S_radius 65 |
|
+#endif |
|
Index: pwlib.c |
|
--- pwlib.c.orig 2003-04-01 00:13:10.000000000 +0200 |
|
+++ pwlib.c 2003-10-24 17:06:25.000000000 +0200 |
|
@@ -37,6 +37,10 @@ |
|
#include "ldap.h" |
|
#endif /* LDAP */ |
|
|
|
+#ifdef USE_RADIUS |
|
+#include "radius.h" |
|
+#endif |
|
+ |
|
/* Generic password verification routines for des, file and cleartext |
|
passwords */ |
|
|
|
@@ -47,7 +51,6 @@ |
|
static int |
|
unix_verify(char *user, char *supplied_passwd, struct authen_data *data); |
|
|
|
- |
|
void |
|
set_expiration_status(exp_date, data) |
|
char *exp_date; |
|
@@ -301,6 +304,17 @@ |
|
|
|
#endif /* USE_PAM */ |
|
|
|
+#ifdef USE_RADIUS |
|
+ case S_radius: |
|
+ if (radius_verify(name, passwd, cfg_login) == 1) { |
|
+ data->status = TAC_PLUS_AUTHEN_STATUS_FAIL; |
|
+ } else { |
|
+ data->status = TAC_PLUS_AUTHEN_STATUS_PASS; |
|
+ exp_date = NULL; /* no expire check for RADIUS */ |
|
+ } |
|
+ break; |
|
+#endif |
|
+ |
|
case S_des: |
|
/* try to verify this des password */ |
|
if (!des_verify(passwd, cfg_login)) { |
|
Index: radius.h |
|
--- radius.h.orig 2003-10-24 16:58:03.000000000 +0200 |
|
+++ radius.h 2003-10-24 16:58:03.000000000 +0200 |
|
@@ -0,0 +1,6 @@ |
|
+#ifndef __RADIUS_H__ |
|
+#define __RADIUS_H__ |
|
+ |
|
+extern radius_verify(char *, char *, char *); |
|
+ |
|
+#endif /* __RADIUS_H__ */ |
|
Index: Makefile.in |
|
--- Makefile.in.orig 2003-04-11 04:30:25.000000000 +0200 |
|
+++ Makefile.in 2003-10-24 17:16:45.000000000 +0200 |
|
@@ -158,7 +158,7 @@ |
|
# $(use_o) has to be BEFORE $(conf_LDADD)! (for library dependencies) |
|
tac_plus_LDADD = $(use_o) $(conf_LDADD) |
|
tac_plus_DEPENDENCIES = $(use_o) |
|
-use = @COND_USE@ |
|
+use = @COND_USE@ radius.c |
|
use_o = $(filter %.o,$(use:.c=.o)) |
|
|
|
cond_USE_DB = db.c db.h db_author.c |
|
@@ -166,6 +166,7 @@ |
|
cond_DB_NULL = db_null.c |
|
cond_DB_PGSQL = db_pgsql.c |
|
cond_USE_LDAP = ldap.c |
|
+cond_USE_RADIUS = radius.c |
|
cond_MAXSESS = maxsess.c |
|
cond_MSCHAP = md4.c md4.h |
|
cond_SKEY = skey_fn.c |
|
@@ -181,6 +182,7 @@ |
|
$(cond_DB_NULL) \ |
|
$(cond_DB_PGSQL) \ |
|
$(cond_USE_LDAP) \ |
|
+ $(cond_USE_RADIUS) \ |
|
$(cond_MAXSESS) \ |
|
$(cond_MSCHAP) \ |
|
$(cond_SKEY) \ |
|
Index: radius.c |
|
--- radius.c.orig 2003-10-24 16:58:03.000000000 +0200 |
|
+++ radius.c 2003-10-24 17:19:49.000000000 +0200 |
|
@@ -0,0 +1,117 @@ |
|
+/* |
|
+ * Verify that this user/password is valid per a RADIUS server database |
|
+ * Return 1 if verified, 0 otherwise. |
|
+ * |
|
+ * Format of connection string: |
|
+ * <radius key server1>,<radius server1>,<radius key server2>,<radius server2>, |
|
+ * ... ,<radius key server9>,<radius server9> |
|
+ * |
|
+ * Author: |
|
+ * Martin Mersberger <gremlin@portal-to-web.de> |
|
+ * http://www.portal-to-web.de/tacacs |
|
+ * |
|
+ * Dependencies: |
|
+ * You need to get the Juniper Networks libradius |
|
+ * (included in FreeBSD >= 4.x) |
|
+ * |
|
+ * License: |
|
+ * tac_radius is free software; you can redistribute it |
|
+ * and/or modify it under the terms of the BSD License |
|
+ */ |
|
+ |
|
+#include "config.h" |
|
+ |
|
+#if defined(USE_RADIUS) |
|
+ |
|
+#include <stdio.h> |
|
+#include <string.h> |
|
+ |
|
+#include "tac_plus.h" |
|
+#include "radius.h" |
|
+ |
|
+#include <sys/types.h> |
|
+#include <sys/socket.h> |
|
+#include <netinet/in.h> |
|
+#include <arpa/inet.h> |
|
+#include "radlib.h" |
|
+ |
|
+int radius_verify(char *user, char *users_passwd, char *str_conn) |
|
+{ |
|
+ struct rad_handle *rh; |
|
+ struct in_addr addr; |
|
+ int res; |
|
+ char *token, *cp; |
|
+ char *server[10]; |
|
+ char *key[10]; |
|
+ int i, j; |
|
+ char l_err[200]; |
|
+ int err; |
|
+ |
|
+ /* open the radius handle */ |
|
+ if ((rh = rad_auth_open()) == NULL ) { |
|
+ report(LOG_ERR,"Can't open rad_open"); |
|
+ return 1; |
|
+ } |
|
+ |
|
+ /* split the line from the config file into pairs with radiusserver and radius key */ |
|
+ cp = strdup(str_conn); |
|
+ i = 0; |
|
+ while ((token = strsep(&cp,",")) != NULL) { |
|
+ if ((i % 2) == 0) { /* 0,2,4,... are the radius keys */ |
|
+ key[i] = (char *)malloc(sizeof(token) + sizeof(char)); /* get some mem */ |
|
+ sprintf(key[i], "%s\0", token); /* add the value gotten into a array */ |
|
+ } else { |
|
+ server[i-1] = (char *)malloc(sizeof(token) + sizeof(char)); /* 1,3,5... are the radius hosts */ |
|
+ sprintf(server[i-1], "%s\0", token); /* malloc and add to array */ |
|
+ } |
|
+ i++; |
|
+ } |
|
+ |
|
+ /* for each server and key pair gotten from the config file, do a rad_add_server */ |
|
+ for (j = 0; j < i; j = j + 2) { |
|
+ report(LOG_INFO, "verify_radius: before ldap_init: radiusserver = %s, radiuskey = %s", server[j],key[j]); |
|
+ if ((rad_add_server(rh,server[j], 0, key[j], 2, 2)) != 0) { |
|
+ report (LOG_ERR, "Error in rad_add_server for %s", server[j]); |
|
+ return (1); |
|
+ } |
|
+ } |
|
+ |
|
+ /* create a radius request for ACCESS */ |
|
+ if ((rad_create_request(rh ,RAD_ACCESS_REQUEST)) != 0) { |
|
+ report (LOG_ERR, "Error in rad_create_request"); |
|
+ return (1); |
|
+ } |
|
+ |
|
+ /* prepare the radius request |
|
+ * 1. make a in_addr from the requesting peer ip address |
|
+ * 2. put in username |
|
+ * 3. put in password |
|
+ * 4. insert the in_addr into the rad_request |
|
+ * 5. set the RAD_CONNECT_INFO to "via tacacs+" |
|
+ */ |
|
+ inet_aton(session.peer, &addr); |
|
+ rad_put_string(rh, RAD_USER_NAME, user); |
|
+ rad_put_string(rh, RAD_USER_PASSWORD, users_passwd); |
|
+ rad_put_addr(rh, RAD_NAS_IP_ADDRESS,addr); |
|
+ rad_put_string(rh, RAD_CONNECT_INFO," via TACACS+ server"); |
|
+ |
|
+ /* some debug messages before sending the radius request */ |
|
+#if 0 |
|
+ report(LOG_INFO, "verify_radius: before rad_send: user = %s, passwd = %s", user, "********"); |
|
+ report(LOG_INFO, "verify_radius: before rad_send: peer %s", session.peer); |
|
+#endif |
|
+ |
|
+ /* send the radius request and hope, that libradius does a good job */ |
|
+ res = rad_send_request(rh); |
|
+ |
|
+ /* is the user authenticated? if yes, return 0, else 1 */ |
|
+ if (res == RAD_ACCESS_ACCEPT ) { |
|
+ report(LOG_INFO, "Request accepted\n"); |
|
+ return 0; |
|
+ } else { |
|
+ report(LOG_INFO, "Request denied %i\n",res); |
|
+ return 1; |
|
+ } |
|
+} |
|
+ |
|
+#endif /* RADIUS */
|
|
|