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

Add libevent support #83

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ config.status
libtool
pam_tacplus.spec
stamp-h1
libtac.pc
libtac-event.pc
*.o
*.lo
*.la
Expand Down
19 changes: 19 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 @@ -45,6 +48,8 @@ libtac/lib/read_wait.c \
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 @@ -54,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 @@ -65,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 @@ -75,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
14 changes: 14 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ dnl --------------------------------------------------------------------
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/socket.h sys/time.h ])
AC_CHECK_HEADERS([stdbool.h limits.h assert.h])
AC_CHECK_HEADERS([syslog.h unistd.h openssl/md5.h openssl/rand.h linux/random.h sys/random.h])
AC_CHECK_HEADER(security/pam_appl.h, [], [AC_MSG_ERROR([PAM libraries missing. Install with "yum install pam-devel" or "apt-get install libpam-dev".])] )
AM_CONDITIONAL(MY_MD5, [test "$ac_cv_header_openssl_md5_h" = "no" ])
Expand Down Expand Up @@ -102,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}
178 changes: 152 additions & 26 deletions libtac/include/libtac.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ extern "C" {
#else
#include "cdefs.h"
#endif
#include <assert.h>
#include <stdbool.h>
#include <limits.h>
#include "tacplus.h"

#if defined(DEBUGTAC) && !defined(TACDEBUG)
Expand Down Expand Up @@ -87,6 +90,7 @@ struct tac_attrib {
struct areply {
struct tac_attrib *attr;
char *msg;
char *data;
int status :8;
int flags :8;
int seq_no :8;
Expand Down Expand Up @@ -132,50 +136,172 @@ extern int tac_ver_major;
extern int tac_ver_minor;
extern int tac_ver_patch;

/* header.c */
extern int session_id;
extern int tac_encryption;
extern const char *tac_secret;
extern char tac_login[64];
extern int tac_priv_lvl;
extern int tac_authen_method;
extern int tac_authen_service;
/* 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;
uint32_t tac_session_id;
bool tac_encryption;
bool tac_multiplex;
bool tac_idle; /* not exposed via API */
uint8_t tac_priv_lvl;
uint8_t tac_authen_method;
uint8_t tac_authen_service;
uint8_t tac_authen_type;
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];
};

struct tac_session *tac_session_alloc(void);
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_multiplex(struct tac_session *, bool);
void tac_session_reset_timeouts(struct tac_session *, bool);
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 *);
void tac_session_free(struct tac_session *);

/* header.c */
extern int tac_debug_enable;
extern int tac_readtimeout_enable;

/* we return a void * because there are different types of bodies */
static inline void *tac_hdr_to_body(HDR *th)
{
return (void *)((u_char *)th + TAC_PLUS_HDR_SIZE);
}

HDR *_tac_req_header(struct tac_session *, u_char, bool);

/* connect.c */
extern int tac_timeout;

int tac_connect(struct addrinfo **, char **, int);
int tac_connect_single(const struct addrinfo *, const char *, struct addrinfo *,
int);
int tac_connect(struct tac_session *, struct addrinfo **, unsigned);
int tac_connect_single(struct tac_session *, const struct addrinfo *, struct addrinfo *, int);
void tac_close(struct tac_session *);
char *tac_ntop(const struct sockaddr *);

int tac_authen_send(int, const char *, const char *, const char *, const char *,
u_char);
int tac_authen_read(int, struct areply *);
int tac_cont_send_seq(int, const char *, int);
#define tac_cont_send(fd, pass) tac_cont_send_seq((fd), (pass), 3)
HDR *_tac_req_header(u_char, int);
void _tac_crypt(u_char *, const HDR *);
/* authen_s.c */
u_char tac_get_authen_type(const char *);
const char *tag_get_authen_string(uint8_t);

void tac_authen_send_pkt(struct tac_session *,
const char *, const char *, const char *, const char *, u_char,
u_char **, unsigned *);
int tac_authen_send(struct tac_session *,
const char *, const char *, const char *, const char *, u_char);

/* authen_r.c */
int tac_authen_parse(struct tac_session *, struct areply *, u_char *, unsigned);
int tac_authen_read(struct tac_session *, struct areply *);

/* cont_s.c */
void tac_cont_send_pkt(struct tac_session *, const char *,
u_char **, unsigned *);
int tac_cont_send(struct tac_session *, const char *);

/* crypt.c */
void _tac_crypt(const struct tac_session *, u_char *, const HDR *);

/* author_r.c */
int tac_author_parse(struct tac_session *, u_char *, unsigned, struct areply *);
int tac_author_read(struct tac_session *, struct areply *);

/* author_s.c */
void tac_author_send_pkt(struct tac_session *, const char *, const char *,
const char *, struct tac_attrib *, u_char **, unsigned *);
int tac_author_send(struct tac_session *, const char *, const char *,
const char *, struct tac_attrib *);

/* attrib.c */
void tac_add_attrib(struct tac_attrib **, char *, char *);
void tac_add_attrib_pair(struct tac_attrib **, char *, char, char *);
void tac_free_attrib(struct tac_attrib **);
char *tac_acct_flag2str(int);
int tac_acct_send(int, int, const char *, char *, char *, struct tac_attrib *);
int tac_acct_read(int, struct areply *);

/* acct_s.c */
char *tac_acct_flag2str(u_char);
void tac_acct_send_pkt(struct tac_session *, u_char, const char *,
const char *, const char *, struct tac_attrib *, u_char **, unsigned *);
int tac_acct_send(struct tac_session *, u_char, const char *,
const char *, const char *, struct tac_attrib *);

/* acct_r.c */
int tac_acct_parse(struct tac_session *, u_char *, unsigned,
struct areply *);
int tac_acct_read(struct tac_session *, struct areply *);

/* xalloc.c */
void *xcalloc(size_t, size_t);
void *xrealloc(void *, size_t);
char *xstrcpy(char *, const char *, size_t);
char *_tac_check_header(HDR *, int);
int tac_author_send(int, const char *, char *, char *, struct tac_attrib *);
int tac_author_read(int, struct areply *);
void tac_add_attrib_pair(struct tac_attrib **, char *, char, char *);
int tac_read_wait(int, int, int, int *);

/* hdr_check.c */
char *_tac_check_header(struct tac_session *, HDR *, uint8_t);

/* magic.c */
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
5 changes: 5 additions & 0 deletions libtac/include/tacplus.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ struct authen_cont {
u_short user_msg_len;
u_short user_data_len;
u_char flags;
u_char msg[0];

#define TAC_PLUS_CONTINUE_FLAG_ABORT 0x01

Expand All @@ -133,6 +134,7 @@ struct authen_reply {

u_short msg_len;
u_short data_len;
u_char msg[0];
};

#define TAC_AUTHEN_REPLY_FIXED_FIELDS_SIZE 6
Expand Down Expand Up @@ -173,6 +175,7 @@ struct acct {
u_char port_len;
u_char r_addr_len;
u_char arg_cnt; /* the number of cmd args */
u_char arg_len[0];
};

#define TAC_ACCT_REQ_FIXED_FIELDS_SIZE 9
Expand Down Expand Up @@ -201,6 +204,7 @@ struct author {
u_char port_len;
u_char r_addr_len;
u_char arg_cnt; /* the number of args */
u_char arg_len[0];
};

#define TAC_AUTHOR_REQ_FIXED_FIELDS_SIZE 8
Expand All @@ -211,6 +215,7 @@ struct author_reply {
u_char arg_cnt;
u_short msg_len;
u_short data_len;
u_char arg_len[0];

#define TAC_PLUS_AUTHOR_STATUS_PASS_ADD 0x01
#define TAC_PLUS_AUTHOR_STATUS_PASS_REPL 0x02
Expand Down
Loading