|
|
@@ -0,0 +1,309 @@
|
|
|
+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 */
|