瀏覽代碼

new package: tacacs 4.4b2 (TACACS+ Server)

Ralf S. Engelschall 22 年之前
父節點
當前提交
0186abb31b
共有 5 個文件被更改,包括 675 次插入0 次删除
  1. 16 0
      tacacs/fsl.tacacs
  2. 54 0
      tacacs/rc.tacacs
  3. 70 0
      tacacs/tacacs.patch
  4. 309 0
      tacacs/tacacs.patch.radius
  5. 226 0
      tacacs/tacacs.spec

+ 16 - 0
tacacs/fsl.tacacs

@@ -0,0 +1,16 @@
+##
+##  fsl.tacacs -- OSSP fsl configuration
+##
+
+ident (tac_plus)/.+ q{
+    prefix(
+        prefix="%b %d %H:%M:%S %N <%L> $1[%P]: "
+    )
+    -> {
+        debug: file(
+            path="@l_prefix@/var/tacacs/tacacs.log",
+            perm=0644
+        )
+    }
+};
+

+ 54 - 0
tacacs/rc.tacacs

@@ -0,0 +1,54 @@
+#!@l_prefix@/lib/openpkg/bash @l_prefix@/etc/rc
+##
+##  rc.tacacs -- Run-Commands
+##
+
+%config
+    tacacs_enable="$openpkg_rc_def"
+    tacacs_log_prolog="true"
+    tacacs_log_epilog="true"
+    tacacs_log_numfiles="10"
+    tacacs_log_minsize="1M"
+    tacacs_log_complevel="9"
+
+%common
+    tacacs_pidfile="@l_prefix@/var/tacacs/tac_plus.pid"
+    tacacsr_signal () {
+        [ -f $tacacs_pidfile ] && kill -$1 `cat $tacacs_pidfile`
+    }
+
+%status -u @l_susr@ -o
+    tacacs_usable="unknown"
+    tacacs_active="no"
+    rcService tacacs enable yes && \
+        tacacs_signal 0 && tacacs_active="yes"
+    echo "tacacs_enable=\"$tacacs_enable\""
+    echo "tacacs_usable=\"$tacacs_usable\""
+    echo "tacacs_active=\"$tacacs_active\""
+
+%start -p 100 -u @l_susr@
+    rcService tacacs enable yes || exit 0
+    rcService tacacs active yes && exit 0
+    @l_prefix@/sbin/tac_plus
+
+%stop -p 100 -u @l_susr@
+    rcService tacacs enable yes || exit 0
+    rcService tacacs active no  && exit 0
+    tacacs_signal TERM
+    sleep 2
+    rm -f $tacacs_pidfile >/dev/null 2>&1 || true
+
+%restart -p 100 -u @l_susr@
+    rcService tacacs enable yes || exit 0
+    rcService tacacs active no  && exit 0
+    rc tacacs stop start
+
+%daily
+    rcService tacacs enable yes || exit 0
+    shtool rotate -f \
+        -n ${tacacs_log_numfiles} -s ${tacacs_log_minsize} -d \
+        -z ${tacacs_log_complevel} -m 644 -o @l_susr@ -g @l_mgrp@ \
+        -P "${tacacs_log_prolog}" \
+        -E "${tacacs_log_epilog} && rc tacacs restart" \
+        @l_prefix@/var/tacacs/tacacs.log
+

+ 70 - 0
tacacs/tacacs.patch

@@ -0,0 +1,70 @@
+Index: configure
+--- configure.orig	2003-09-21 05:00:43.000000000 +0200
++++ configure	2003-10-24 17:28:20.000000000 +0200
+@@ -1241,7 +1241,7 @@
+ 
+ 
+ case $host_os in 
+-	*linux-gnu)
++	*linux*)
+ 		cat >> confdefs.h <<\EOF
+ #define LINUX 1
+ EOF
+@@ -1257,7 +1257,7 @@
+ EOF
+ 
+ 		;;
+-	*freebsd)
++	*freebsd*)
+ 		cat >> confdefs.h <<\EOF
+ #define FREEBSD 1
+ EOF
+@@ -2886,8 +2886,8 @@
+ fi
+ 
+ 	
+-	ac_safe=`echo "PGSQL_INCLUDE_DIR/libpq-fe.h" | sed 'y%./+-%__p_%'`
+-echo $ac_n "checking for PGSQL_INCLUDE_DIR/libpq-fe.h""... $ac_c" 1>&6
++	ac_safe=`echo "$PGSQL_INCLUDE_DIR/libpq-fe.h" | sed 'y%./+-%__p_%'`
++echo $ac_n "checking for $PGSQL_INCLUDE_DIR/libpq-fe.h""... $ac_c" 1>&6
+ echo "configure:2892: checking for PGSQL_INCLUDE_DIR/libpq-fe.h" >&5
+ if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+   echo $ac_n "(cached) $ac_c" 1>&6
+@@ -2895,7 +2895,7 @@
+   cat > conftest.$ac_ext <<EOF
+ #line 2897 "configure"
+ #include "confdefs.h"
+-#include <PGSQL_INCLUDE_DIR/libpq-fe.h>
++#include <$PGSQL_INCLUDE_DIR/libpq-fe.h>
+ EOF
+ ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+ { (eval echo configure:2902: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+Index: skey_fn.c
+--- skey_fn.c.orig	2002-10-08 22:49:51.000000000 +0200
++++ skey_fn.c	2003-10-24 17:28:20.000000000 +0200
+@@ -17,6 +17,8 @@
+    FITNESS FOR A PARTICULAR PURPOSE.
+ */
+ 
++#include "config.h"
++
+ #ifdef SKEY
+ #include "tac_plus.h"
+ #include "expire.h"
+Index: db_pgsql.c
+--- db_pgsql.c.orig	2003-09-20 06:05:54.000000000 +0200
++++ db_pgsql.c	2003-10-24 17:28:20.000000000 +0200
+@@ -1,3 +1,5 @@
++#include "config.h"
++#include "tac_plus.h"
+ #if defined(DB_PGSQL) && defined(USE_DB)
+ 
+ /*
+@@ -11,7 +13,6 @@
+ 
+ */
+ 
+-#include "tac_plus.h"
+ #include <stdio.h>
+ #include <libpq-fe.h> 
+ #include "db.h" 

+ 309 - 0
tacacs/tacacs.patch.radius

@@ -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 */

+ 226 - 0
tacacs/tacacs.spec

@@ -0,0 +1,226 @@
+##
+##  tacacs.spec -- OpenPKG RPM Specification
+##  Copyright (c) 2000-2003 The OpenPKG Project <http://www.openpkg.org/>
+##  Copyright (c) 2000-2003 Ralf S. Engelschall <rse@engelschall.com>
+##  Copyright (c) 2000-2003 Cable & Wireless <http://www.cw.com/>
+##
+##  Permission to use, copy, modify, and distribute this software for
+##  any purpose with or without fee is hereby granted, provided that
+##  the above copyright notice and this permission notice appear in all
+##  copies.
+##
+##  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+##  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+##  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+##  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
+##  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+##  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+##  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+##  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+##  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+##  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+##  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+##  SUCH DAMAGE.
+##
+
+#   package version
+%define       V_dist  4.4beta2
+%define       V_opkg  4.4b2
+
+#   package information
+Name:         tacacs
+Summary:      TACACS+ Server
+URL:          http://www.networkforums.net/
+Vendor:       Cisco et al.
+Packager:     The OpenPKG Project
+Distribution: OpenPKG [EVAL]
+Group:        Network
+License:      BSD
+Version:      %{V_opkg}
+Release:      20031024
+
+#   package options
+%option       with_fsl     yes
+%option       with_pam     no
+%option       with_skey    no
+%option       with_mysql   no
+%option       with_pgsql   no
+%option       with_radius  no
+
+#   list of sources
+Source0:      http://www.networkforums.net/downloads/tac_plus-%{V_dist}.tar.gz
+Source1:      rc.tacacs
+Source2:      fsl.tacacs
+Patch0:       tacacs.patch
+Patch1:       tacacs.patch.radius
+
+#   build information
+Prefix:       %{l_prefix}
+BuildRoot:    %{l_buildroot}
+BuildPreReq:  OpenPKG, openpkg >= 20030103
+PreReq:       OpenPKG, openpkg >= 20030103
+%if "%{with_fsl}" == "yes"
+BuildPreReq:  fsl >= 1.2.0
+PreReq:       fsl >= 1.2.0
+%endif
+%if "%{with_pam}" == "yes"
+BuildPreReq:  PAM
+PreReq:       PAM
+%endif
+%if "%{with_skey}" == "yes"
+BuildPreReq:  skey
+PreReq:       skey
+%endif
+%if "%{with_mysql}" == "yes"
+BuildPreReq:  mysql
+PreReq:       mysql
+%endif
+%if "%{with_pgsql}" == "yes"
+BuildPreReq:  postgresql, openssl
+PreReq:       postgresql, openssl
+%endif
+%if "%{with_radius}" == "yes"
+BuildPreReq:  libradius
+PreReq:       libradius
+%endif
+AutoReq:      no
+AutoReqProv:  no
+
+%description
+    This is a TACACS+ authentication server, derived from the original
+    Cisco TACACS+ server implementation.
+
+%prep
+    %setup -q -n tac_plus-%{V_dist}
+    %patch -p0 -P 0
+    %patch -p0 -P 1
+
+%build
+    #   configure package
+    export CC="%{l_cc}"
+    export CFLAGS="%{l_cflags -O}"
+    export CPPFLAGS="%{l_cppflags}"
+    export LDFLAGS="%{l_ldflags}"
+    export LIBS=""
+%if "%{with_fsl}" == "yes"
+    LDFLAGS="$LDFLAGS %{l_fsl_ldflags}"
+    LIBS="$LIBS %{l_fsl_libs}"
+%endif
+%if "%{with_pam}" == "yes"
+    CFLAGS="$CFLAGS -I`%{l_prefix}/etc/rc --query pam_incdir`"
+    LDFLAGS="$LDFLAGS -L`%{l_prefix}/etc/rc --query pam_libdir`"
+%endif
+%if "%{with_pgsql}" == "yes"
+    LIBS="$LIBS -lssl -lcrypto"
+%endif
+%if "%{with_radius}" == "yes"
+    CFLAGS="$CFLAGS -DUSE_RADIUS"
+    LIBS="$LIBS -lradius"
+%endif
+    ./configure \
+        --prefix=%{l_prefix} \
+%if "%{with_pam}" == "yes"
+        --with-pam \
+%else
+        --without-pam \
+%endif
+%if "%{with_skey}" == "yes"
+        --with-skey=%{l_prefix}/lib/libskey.a \
+%else
+        --without-skey \
+%endif
+%if "%{with_mysql}" == "yes" || "%{with_pgsql}" == "yes"
+        --with-db \
+%else
+        --without-db \
+%endif
+%if "%{with_mysql}" == "yes"
+        --with-mysql \
+        --with-mysql-prefix=%{l_prefix} \
+%else
+        --without-mysql \
+%endif
+%if "%{with_pgsql}" == "yes"
+        --with-pgsql \
+        --with-pgsql-prefix=%{l_prefix} \
+        --with-pgsql-include-dir=%{l_prefix}/include/postgresql \
+        --with-pgsql-lib-dir=%{l_prefix}/lib \
+%else
+        --without-pgsql \
+%endif
+        --with-tacplus_pid=%{l_prefix}/var/tacacs/tac_plus.pid
+
+    #   build package
+    %{l_make} %{l_mflags -O}
+
+%install
+    #   install package
+    rm -rf $RPM_BUILD_ROOT
+    %{l_make} %{l_mflags} install AM_MAKEFLAGS="DESTDIR=$RPM_BUILD_ROOT"
+
+    #   post-adjust installation
+    mv  $RPM_BUILD_ROOT%{l_prefix}/bin/generate_passwd \
+        $RPM_BUILD_ROOT%{l_prefix}/bin/tacas_generate_passwd
+    mv  $RPM_BUILD_ROOT%{l_prefix}/etc/tacacs/sample-tac_plus.cfg \
+        $RPM_BUILD_ROOT%{l_prefix}/etc/tacacs/tac_plus.cfg
+    strip $RPM_BUILD_ROOT%{l_prefix}/bin/* >/dev/null 2>&1 || true
+
+%if "%{with_mysql}" == "yes" || "%{with_pgsql}" == "yes"
+    #   install SQL database schema
+    %{l_shtool} mkdir -f -p -m 755 \
+        $RPM_BUILD_ROOT%{l_prefix}/share/tacacs
+    %{l_shtool} install -c -m 644 \
+        tac_plus.sql $RPM_BUILD_ROOT%{l_prefix}/share/tacacs/
+%endif
+
+    #   create pidfile and logfile directory
+    %{l_shtool} mkdir -f -p -m 755 \
+        $RPM_BUILD_ROOT%{l_prefix}/var/tacacs
+
+    #   install run-command script
+    %{l_shtool} mkdir -f -p -m 755 \
+        $RPM_BUILD_ROOT%{l_prefix}/etc/rc.d
+    %{l_shtool} install -c -m 755 %{l_value -s -a} \
+        %{SOURCE rc.tacacs} $RPM_BUILD_ROOT%{l_prefix}/etc/rc.d/
+
+    #   install OSSP fsl configuration
+    %{l_shtool} mkdir -f -p -m 755 \
+        $RPM_BUILD_ROOT%{l_prefix}/etc/fsl
+    %{l_shtool} install -c -m 644 %{l_value -s -a} \
+        %{SOURCE fsl.tacacs} \
+        $RPM_BUILD_ROOT%{l_prefix}/etc/fsl/
+
+    #   determine installation files
+    %{l_rpmtool} files -v -ofiles -r$RPM_BUILD_ROOT \
+        %{l_files_std} \
+        '%config %{l_prefix}/etc/tacacs/tac_plus.cfg' \
+        '%not %dir %{l_prefix}/etc/fsl'
+
+%files -f files
+
+%clean
+    rm -rf $RPM_BUILD_ROOT
+
+%post
+%if "%{with_pam}" == "yes"
+    #   add PAM configuration entry
+    if [ $1 -eq 1 ]; then
+        $RPM_INSTALL_PREFIX/sbin/pamtool --add --smart --name=tac_plus
+    fi
+%endif
+    #   after upgrade, restart service
+    [ $1 -eq 2 ] || exit 0
+    eval `%{l_rc} tacacs status 2>/dev/null`
+    [ ".$tacacs_active" = .yes ] && %{l_rc} tacacs restart
+    exit 0
+
+%preun
+    [ $1 -eq 0 ] || exit 0
+    #   before erase, stop service
+    %{l_rc} tacacs stop 2>/dev/null
+%if "%{with_pam}" == "yes"
+    #   remove PAM configuration entry
+    $RPM_INSTALL_PREFIX/sbin/pamtool --remove --smart --name=tac_plus
+%endif
+    exit 0
+