Skip to content
This repository has been archived by the owner on Feb 28, 2024. It is now read-only.

Commit

Permalink
Introduce libevent integration
Browse files Browse the repository at this point in the history
Let the connections to servers be event-driven by libevent.
  • Loading branch information
pprindeville committed Dec 21, 2016
1 parent c0a0c3d commit 898f17c
Show file tree
Hide file tree
Showing 8 changed files with 611 additions and 6 deletions.
18 changes: 18 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ libtac/include/libtac.h \
libtac/include/cdefs.h

lib_LTLIBRARIES = libtac.la
if WITH_LIBEVENT
lib_LTLIBRARIES += libtac-event.la
endif
libtac_la_SOURCES = \
libtac/lib/acct_r.c \
libtac/lib/acct_s.c \
Expand All @@ -46,6 +49,7 @@ libtac/lib/version.c \
libtac/lib/xalloc.c \
libtac/lib/xalloc.h \
libtac/lib/session.c \
libtac/lib/parse.c \
$(libtac_include_HEADERS)
if MY_MD5
libtac_la_SOURCES += \
Expand All @@ -55,6 +59,14 @@ endif
libtac_la_CFLAGS = $(AM_CFLAGS) -I $(top_srcdir)/libtac/include @rt_debug_defines@
libtac_la_LDFLAGS = -version-info 2:0:0 -shared

if WITH_LIBEVENT
libtac_event_la_SOURCES = \
libtac/lib/wrappers.c \
$(libtac_include_HEADERS)
libtac_event_la_CFLAGS = $(AM_CFLAGS) -Ilibtac/include
libtac_event_la_LDFLAGS = -version-info 1:0:0 -shared -levent
endif

moduledir = @pamdir@
module_LTLIBRARIES = pam_tacplus.la
pam_tacplus_la_SOURCES = pam_tacplus.h \
Expand All @@ -66,6 +78,9 @@ pam_tacplus_la_LDFLAGS = -module -avoid-version
pam_tacplus_la_LIBADD = libtac.la

EXTRA_DIST = pam_tacplus.spec libtac.pc.in
if WITH_LIBEVENT
EXTRA_DIST += libtac-event.pc.in
endif
if DOC
dist_doc_DATA = sample.pam README.md AUTHORS ChangeLog
endif
Expand All @@ -76,6 +91,9 @@ MAINTAINERCLEANFILES = Makefile.in config.h.in configure aclocal.m4 \

pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libtac.pc
if WITH_LIBEVENT
pkgconfig_DATA += libtac-event.pc
endif

coverity:
rm -rf cov-int
Expand Down
13 changes: 13 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,21 @@ AC_SUBST(rt_debug_defines)
AM_SUBST_NOTMAKE(rt_debug_defines)

dnl --------------------------------------------------------------------
dnl Switch for libevent support
AC_ARG_WITH(libevent,
[AS_HELP_STRING([--with-libevent], [build libevent support])],
AC_DEFINE([WITH_LIBEVENT], 1,
[Define to 1 if building with libevent])
[with_libevent=1]
)
AM_CONDITIONAL(WITH_LIBEVENT, [test -n "$with_libevent"])


dnl --------------------------------------------------------------------

dnl Generate made files
AC_CONFIG_FILES([Makefile
libtac.pc
libtac-event.pc
pam_tacplus.spec])
AC_OUTPUT
11 changes: 11 additions & 0 deletions libtac-event.pc.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@/libtac

Name: libtac-event
Description: A TACACS+ protocol implementation
URL: https://github.com/jeroennijhof/pam_tacplus
Version: @VERSION@
Libs: -L${libdir} -ltac-event
Cflags: -I${includedir}
52 changes: 52 additions & 0 deletions libtac/include/libtac.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,24 @@ extern int tac_ver_minor;
extern int tac_ver_patch;

/* session.c */
struct bufferevent;
struct tac_session;

struct cb_ctx {
struct tac_session *sess;
void *user_ctx;
const char *login;
const char *pass;
};

typedef void (*response_cb_t)(struct tac_session *, struct cb_ctx *,
int, uint8_t, struct areply *);

typedef enum { UNINITIALIZED, CONNECTED, CLOSED, ERROR, TIMEOUT } session_event_t;

typedef void (*oob_cb_t)(struct tac_session *, struct cb_ctx *,
session_event_t);

struct tac_session {
unsigned tac_timeout;
const char *tac_secret;
Expand All @@ -149,6 +167,13 @@ struct tac_session {
uint8_t seq_no;
int fd;

struct bufferevent *bufev;
void *cookie;

response_cb_t response_cb;
oob_cb_t oob_cb;
struct cb_ctx context;

/* user defined stuff */
uint8_t user_data[0];
};
Expand All @@ -158,6 +183,9 @@ struct tac_session *tac_session_alloc_extra(unsigned);
void tac_session_set_authen_type(struct tac_session *, uint8_t);
void tac_session_set_secret(struct tac_session *, const char *);
void tac_session_set_timeout(struct tac_session *, unsigned);
void tac_session_set_response(struct tac_session *, response_cb_t);
void tac_session_set_oob(struct tac_session *, oob_cb_t);
struct cb_ctx *tac_session_get_context(struct tac_session *);
void tac_session_new_session_id(struct tac_session *);
void tac_session_reset_seq(struct tac_session *);
void *tac_session_get_user_data(struct tac_session *);
Expand Down Expand Up @@ -246,6 +274,30 @@ u_int32_t magic(void);
/* read_wait.c */
int tac_read_wait(int, int, int, int *);

/* parser.c */
void tac_parse_pkt(struct tac_session *, struct cb_ctx *, u_char *, unsigned);

/* wrappers.c */
void *tac_event_loop_initialize(void);
int tac_event_loop(void *tac_event);
void tac_event_loop_end(void *tac_event);
void tac_event_loop_shutdown(void *tac_event);
void tac_event_loop_global_shutdown(void);

bool tac_connect_single_ev(struct tac_session *,
void *, struct addrinfo *server, struct addrinfo *srcaddr, unsigned timeout);
bool tac_authen_send_ev(struct tac_session *sess,
const char *user, const char *pass, const char *tty,
const char *r_addr, u_char action);
bool tac_author_send_ev(struct tac_session *sess,
const char *user, const char *tty, const char *r_addr,
struct tac_attrib *attr);
bool tac_acct_send_ev(struct tac_session *sess,
u_char type, const char *user, const char *tty,
const char *r_addr, struct tac_attrib *attr);
bool tac_cont_send_ev(struct tac_session *sess,
const char *pass);

#ifdef __cplusplus
}
#endif
Expand Down
17 changes: 12 additions & 5 deletions libtac/lib/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ int tac_connect(struct tac_session *sess,
unsigned tries;
int retval = -1;

TACDEBUG(LOG_DEBUG, "session %p connect (%u addrs)", sess, servers);

if(servers == 0 || server == NULL) {
TACSYSLOG(LOG_ERR, "%s: no TACACS+ servers defined", __FUNCTION__);
} else {
Expand All @@ -58,7 +60,7 @@ int tac_connect(struct tac_session *sess,
}

/* all attempts failed if fd is still < 0 */
TACDEBUG(LOG_DEBUG, "%s: exit status=%d",__FUNCTION__, retval);
TACDEBUG(LOG_DEBUG, "%s: exit status=%d: %m", __FUNCTION__, retval);
return retval;
} /* tac_connect */

Expand All @@ -78,6 +80,8 @@ int tac_connect_single(struct tac_session *sess,
struct sockaddr_storage addr;
char *ip;

TACDEBUG(LOG_DEBUG, "session %p connect", sess);

if(server == NULL) {
TACSYSLOG(LOG_ERR, "%s: no TACACS+ server defined", __FUNCTION__);
goto bomb;
Expand All @@ -87,7 +91,7 @@ int tac_connect_single(struct tac_session *sess,
ip = tac_ntop(server->ai_addr);

if((fd=socket(server->ai_family, server->ai_socktype, server->ai_protocol)) < 0) {
TACSYSLOG(LOG_ERR,"%s: socket creation error: %s", __FUNCTION__,
TACSYSLOG(LOG_ERR,"%s: socket creation error: %s", __FUNCTION__,\
strerror(errno));
goto bomb;
}
Expand All @@ -105,7 +109,7 @@ int tac_connect_single(struct tac_session *sess,
/* bind if source address got explicity defined */
if (srcaddr) {
if (bind(fd, srcaddr->ai_addr, srcaddr->ai_addrlen) < 0) {
TACSYSLOG(LOG_ERR, "%s: Failed to bind source address: %s",
TACSYSLOG(LOG_ERR, "%s: Failed to bind source address: %s",\
__FUNCTION__, strerror(errno));
goto bomb;
}
Expand Down Expand Up @@ -134,6 +138,7 @@ int tac_connect_single(struct tac_session *sess,

/* timeout */
if ( rc == 0 ) {
TACDEBUG(LOG_ERR, "%s: timeout", __FUNCTION__);
retval = LIBTAC_STATUS_CONN_TIMEOUT;
goto bomb;
}
Expand Down Expand Up @@ -173,14 +178,16 @@ int tac_connect_single(struct tac_session *sess,
if (retval < 0 && fd != -1)
close(fd);

TACDEBUG(LOG_DEBUG, "%s: exit status=%d",\
__FUNCTION__, retval);
TACDEBUG(LOG_DEBUG, "%s: exit status=%d (fd=%d)",\
__FUNCTION__, retval, fd);
return retval;
} /* tac_connect_single */

void
tac_close(struct tac_session *sess)
{
TACDEBUG(LOG_DEBUG, "closing %p", sess);

if (sess->fd >= 0) {
close(sess->fd);
sess->fd = -1;
Expand Down
64 changes: 64 additions & 0 deletions libtac/lib/parse.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* parse.c - Callback for dispatching received packets
*
* Copyright (C) 2016, Philip Prindeville <[email protected]>
* Copyright (C) 2016, Brocade Communications Systems, Inc.
*
* 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 - see the file COPYING.
*
* See `CHANGES' file for revision history.
*/

#include <stdio.h>

#include "libtac.h"

void tac_parse_pkt(struct tac_session *sess, struct cb_ctx *ctx, u_char *pkt, unsigned len)
{
HDR *th = (HDR *)pkt;
int status = -1;
struct areply re = { 0 };

switch (th->type) {
case TAC_PLUS_AUTHEN:
TACDEBUG(LOG_DEBUG, "session %p got authen %u bytes", sess, len);
status = tac_authen_parse(sess, &re, pkt, len);
break;

case TAC_PLUS_AUTHOR:
TACDEBUG(LOG_DEBUG, "session %p got author %u bytes", sess, len);
status = tac_author_parse(sess, pkt, len, &re);
break;

case TAC_PLUS_ACCT:
TACDEBUG(LOG_DEBUG, "session %p got account %u bytes", sess, len);
status = tac_acct_parse(sess, pkt, len, &re);
break;

default:
TACDEBUG(LOG_INFO, "session %p got %u byte packet of %02x type; ignoring", \
sess, len, th->type);

break;
}

if (sess->response_cb) {
TACDEBUG(LOG_DEBUG, "session %p user callback", sess);
sess->response_cb(sess, ctx, status, th->type, &re);
}

tac_free_attrib(&re.attr);
free(re.msg);
free(re.data);
}

29 changes: 28 additions & 1 deletion libtac/lib/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ tac_session_alloc_extra(unsigned n)
{
struct tac_session *sess = (struct tac_session *)xcalloc(1, sizeof(*sess) + n);

TACDEBUG(LOG_DEBUG, "session %p constructed (%u extra)", sess, n);

sess->tac_timeout = 5;
sess->tac_secret = NULL;
sess->tac_session_id = magic();
Expand All @@ -41,6 +43,7 @@ tac_session_alloc_extra(unsigned n)
sess->tac_authen_type = TAC_PLUS_AUTHEN_TYPE_PAP;
sess->seq_no = 0;
sess->fd = -1;
sess->context.sess = sess;

return sess;
}
Expand All @@ -55,9 +58,11 @@ void
tac_session_set_secret(struct tac_session *sess, const char *secret)
{
if (secret == NULL || !*secret) {
TACDEBUG(LOG_DEBUG, "session %p clearing session secret", sess);
sess->tac_encryption = false;
sess->tac_secret = NULL;
} else {
TACDEBUG(LOG_DEBUG, "session %p setting session secret", sess);
sess->tac_encryption = true;
sess->tac_secret = secret;
}
Expand All @@ -75,10 +80,31 @@ tac_session_set_timeout(struct tac_session *sess, unsigned timeout)
sess->tac_timeout = timeout;
}

void
tac_session_set_response(struct tac_session *sess, response_cb_t cb)
{
sess->response_cb = cb;
}

void
tac_session_set_oob(struct tac_session *sess, oob_cb_t cb)
{
sess->oob_cb = cb;
}

struct cb_ctx *
tac_session_get_context(struct tac_session *sess)
{
return &sess->context;
}

void
tac_session_new_session_id(struct tac_session *sess)
{
sess->tac_session_id = magic();
uint32_t id = magic();

TACDEBUG(LOG_DEBUG, "session %p new id %#08x", sess, id);
sess->tac_session_id = id;
}

void
Expand All @@ -96,6 +122,7 @@ tac_session_get_user_data(struct tac_session *sess)
void
tac_session_free(struct tac_session *sess)
{
TACDEBUG(LOG_DEBUG, "session %p destroy", sess);
tac_close(sess);
free(sess);
}
Expand Down
Loading

0 comments on commit 898f17c

Please sign in to comment.