summaryrefslogtreecommitdiff
path: root/libtac
diff options
context:
space:
mode:
Diffstat (limited to 'libtac')
-rw-r--r--libtac/include/cdefs.h32
-rw-r--r--libtac/include/libtac.h95
-rw-r--r--libtac/include/tacplus.h197
-rw-r--r--libtac/lib/acct_r.c198
-rw-r--r--libtac/lib/acct_s.c255
-rw-r--r--libtac/lib/attrib.c96
-rw-r--r--libtac/lib/authen_r.c157
-rw-r--r--libtac/lib/authen_s.c252
-rw-r--r--libtac/lib/author_r.c365
-rw-r--r--libtac/lib/author_s.c252
-rw-r--r--libtac/lib/connect.c267
-rw-r--r--libtac/lib/cont_s.c142
-rw-r--r--libtac/lib/crypt.c116
-rw-r--r--libtac/lib/hdr_check.c38
-rw-r--r--libtac/lib/header.c41
-rw-r--r--libtac/lib/magic.c35
-rw-r--r--libtac/lib/magic.h8
-rw-r--r--libtac/lib/md5.c331
-rw-r--r--libtac/lib/md5.h16
-rw-r--r--libtac/lib/messages.c16
-rw-r--r--libtac/lib/messages.h13
-rw-r--r--libtac/lib/read_wait.c119
-rw-r--r--libtac/lib/version.c6
-rw-r--r--libtac/lib/xalloc.c42
-rw-r--r--libtac/lib/xalloc.h10
25 files changed, 1765 insertions, 1334 deletions
diff --git a/libtac/include/cdefs.h b/libtac/include/cdefs.h
index 148f3d7..2297d93 100644
--- a/libtac/include/cdefs.h
+++ b/libtac/include/cdefs.h
@@ -1,6 +1,6 @@
/* cdefs.h
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -19,23 +19,26 @@
* See `CHANGES' file for revision history.
*/
+#ifndef _CDEFS_H
+#define _CDEFS_H
+
#undef __P
#if defined(__STDC__) || defined(__cplusplus)
#define __P(p) p
#else
#define __P(p)
#endif
-#define _PTR void *
-#define _AND ,
-#define _NOARGS void
-#define _CONST const
-#define _VOLATILE volatile
-#define _SIGNED signed
-#define _DOTS , ...
-#define _VOID void
-#define _EXFUN(name, proto) name proto
-#define _DEFUN(name, arglist, args) name(args)
-#define _DEFUN_VOID(name) name(_NOARGS)
+#define _PTR void *
+#define _ANDi ,
+#define _NOARGS void
+#define _CONST const
+#define _VOLATILE volatile
+#define _SIGNED signed
+#define _DOTS , ...
+#define _VOID void
+#define _EXFUN(name, proto) name proto
+#define _DEFUN(name, arglist, args) name(args)
+#define _DEFUN_VOID(name) name(_NOARGS)
#define _CAST_VOID (void)
#ifndef _LONG_DOUBLE
#define _LONG_DOUBLE long double
@@ -49,10 +52,11 @@
#define _ATTRIBUTE(attrs) __attribute__ ((attrs))
#if defined(__cplusplus)
-#define __BEGIN_DECLS extern "C" {
-#define __END_DECLS }
+#define __BEGIN_DECLS extern "C" {
+#define __END_DECLS }
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif
+#endif
diff --git a/libtac/include/libtac.h b/libtac/include/libtac.h
index dfa5ca0..fbe16ba 100644
--- a/libtac/include/libtac.h
+++ b/libtac/include/libtac.h
@@ -1,6 +1,6 @@
/* libtac.h
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -19,8 +19,14 @@
* See `CHANGES' file for revision history.
*/
-#ifndef _AUTH_TAC_H
-#define _AUTH_TAC_H
+#ifndef _LIB_TAC_H
+#define _LIB_TAC_H
+
+#include "tacplus.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
#include <stdarg.h>
#include <stdlib.h>
@@ -34,9 +40,20 @@
#include <unistd.h>
#if defined(DEBUGTAC) && !defined(TACDEBUG)
-#define TACDEBUG(x) syslog x;
+#define TACDEBUG(x) syslog x;
#else
-#define TACDEBUG(x)
+#define TACDEBUG(x) syslog x;
+// #define TACDEBUG(x)
+#endif
+
+#define TACSYSLOG(x) syslog x;
+
+#if defined(TACDEBUG_AT_RUNTIME)
+#undef TACDEBUG
+#undef TACSYSLOG
+#define TACDEBUG(x) if (tac_debug_enable) (void)logmsg x;
+#define TACSYSLOG(x) (void)logmsg x;
+extern int logmsg __P((int, const char*, ...));
#endif
/* u_int32_t support for sun */
@@ -44,6 +61,45 @@
typedef unsigned int u_int32_t;
#endif
+struct tac_attrib {
+ char *attr;
+ u_char attr_len;
+ struct tac_attrib *next;
+};
+
+struct areply {
+ struct tac_attrib *attr;
+ char *msg;
+ int status;
+};
+
+#ifndef TAC_PLUS_MAXSERVERS
+#define TAC_PLUS_MAXSERVERS 4
+#endif
+
+#ifndef TAC_PLUS_PORT
+#define TAC_PLUS_PORT 49
+#endif
+
+#define TAC_PLUS_READ_TIMEOUT 180 /* seconds */
+#define TAC_PLUS_WRITE_TIMEOUT 180 /* seconds */
+
+/* Internal status codes
+ * all negative, tacplus status codes are >= 0
+ */
+
+#define LIBTAC_STATUS_ASSEMBLY_ERR -1
+#define LIBTAC_STATUS_PROTOCOL_ERR -2
+#define LIBTAC_STATUS_READ_TIMEOUT -3
+#define LIBTAC_STATUS_WRITE_TIMEOUT -4
+#define LIBTAC_STATUS_WRITE_ERR -5
+#define LIBTAC_STATUS_SHORT_HDR -6
+#define LIBTAC_STATUS_SHORT_BODY -7
+#define LIBTAC_STATUS_CONN_TIMEOUT -8
+#define LIBTAC_STATUS_CONN_ERR -9
+
+/* Runtime flags */
+
/* version.c */
extern int tac_ver_major;
extern int tac_ver_minor;
@@ -54,6 +110,12 @@ extern int session_id;
extern int tac_encryption;
extern char *tac_secret;
extern char *tac_login;
+extern int tac_priv_lvl;
+extern int tac_authen_method;
+extern int tac_authen_service;
+
+extern int tac_debug_enable;
+extern int tac_readtimeout_enable;
/* connect.c */
extern int tac_timeout;
@@ -61,23 +123,30 @@ extern int tac_connect(struct addrinfo **server, char **key, int servers);
extern int tac_connect_single(struct addrinfo *server, char *key);
extern char *tac_ntop(const struct sockaddr *sa, size_t ai_addrlen);
-extern int tac_authen_send(int fd, const char *user, char *pass, char *tty);
+extern int tac_authen_send(int fd, const char *user, char *pass, char *tty,
+ char *rem_addr);
extern int tac_authen_read(int fd);
extern int tac_cont_send(int fd, char *pass);
-extern HDR *_tac_req_header(u_char type);
+extern HDR *_tac_req_header(u_char type, int cont_session);
extern void _tac_crypt(u_char *buf, HDR *th, int length);
extern u_char *_tac_md5_pad(int len, HDR *hdr);
extern void tac_add_attrib(struct tac_attrib **attr, char *name, char *value);
extern void tac_free_attrib(struct tac_attrib **attr);
-extern int tac_account_send(int fd, int type, const char *user, char *tty,
- struct tac_attrib *attr);
-extern char *tac_account_read(int fd);
+extern int tac_account_send(int fd, int type, const char *user, char *tty, char *rem_addr,
+ struct tac_attrib *attr);
+extern int tac_account_read(int fd, struct areply *arep);
extern void *xcalloc(size_t nmemb, size_t size);
extern void *xrealloc(void *ptr, size_t size);
extern char *_tac_check_header(HDR *th, int type);
-extern int tac_author_send(int fd, const char *user, char *tty,
- struct tac_attrib *attr);
-extern void tac_author_read(int fd, struct areply *arep);
+extern int tac_author_send(int fd, const char *user, char *tty, char *rem_addr,
+ struct tac_attrib *attr);
+extern int tac_author_read(int fd, struct areply *arep);
+extern void tac_add_attrib_pair(struct tac_attrib **attr, char *name, char sep,
+ char *value);
+extern int tac_read_wait(int fd, int timeout, int size, int *time_left);
+#ifdef __cplusplus
+}
#endif
+#endif
diff --git a/libtac/include/tacplus.h b/libtac/include/tacplus.h
index d43e563..0838325 100644
--- a/libtac/include/tacplus.h
+++ b/libtac/include/tacplus.h
@@ -1,6 +1,6 @@
/* tacplus.h
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -24,64 +24,40 @@
#include <sys/types.h>
#ifdef sun
- #include "cdefs.h"
+ #include "cdefs.h"
#else
- #include <sys/cdefs.h>
+ #include <sys/cdefs.h>
#endif
-struct tac_attrib {
- char *attr;
- u_char attr_len;
- struct tac_attrib *next;
-};
-
-struct areply {
- struct tac_attrib *attr;
- char *msg;
- int status;
-};
-
-#ifndef TAC_PLUS_MAXSERVERS
-#define TAC_PLUS_MAXSERVERS 4
-#endif
-
-#ifndef TAC_PLUS_PORT
-#define TAC_PLUS_PORT 49
-#endif
-
-#define TAC_PLUS_READ_TIMEOUT 180 /* seconds */
-#define TAC_PLUS_WRITE_TIMEOUT 180 /* seconds */
-
/* All tacacs+ packets have the same header format */
-
struct tac_plus_pak_hdr {
u_char version;
#define TAC_PLUS_MAJOR_VER_MASK 0xf0
#define TAC_PLUS_MAJOR_VER 0xc0
-#define TAC_PLUS_MINOR_VER_0 0x0
+#define TAC_PLUS_MINOR_VER_0 0x00
#define TAC_PLUS_VER_0 (TAC_PLUS_MAJOR_VER | TAC_PLUS_MINOR_VER_0)
-#define TAC_PLUS_MINOR_VER_1 0x01
+#define TAC_PLUS_MINOR_VER_1 0x01
#define TAC_PLUS_VER_1 (TAC_PLUS_MAJOR_VER | TAC_PLUS_MINOR_VER_1)
u_char type;
-#define TAC_PLUS_AUTHEN 1
-#define TAC_PLUS_AUTHOR 2
-#define TAC_PLUS_ACCT 3
+#define TAC_PLUS_AUTHEN 0x01
+#define TAC_PLUS_AUTHOR 0x02
+#define TAC_PLUS_ACCT 0x03
- u_char seq_no; /* packet sequence number */
- u_char encryption; /* packet is encrypted or cleartext */
+ u_char seq_no; /* packet sequence number */
+ u_char encryption; /* packet is encrypted or cleartext */
-#define TAC_PLUS_ENCRYPTED 0x0 /* packet is encrypted */
-#define TAC_PLUS_CLEAR 0x1 /* packet is not encrypted */
+#define TAC_PLUS_ENCRYPTED_FLAG 0x00 /* packet is encrypted */
+#define TAC_PLUS_UNENCRYPTED_FLAG 0x01 /* packet is unencrypted */
+#define TAC_PLUS_SINGLE_CONNECT_FLAG 0x04 /* multiplexing supported */
- int session_id; /* session identifier FIXME: Is this needed? */
- int datalength; /* length of encrypted data following this
- * header */
- /* datalength bytes of encrypted data */
+ int session_id; /* session identifier FIXME: Is this needed? */
+ int datalength; /* length of encrypted data following this
+ header datalength bytes of encrypted data */
};
#define TAC_PLUS_HDR_SIZE 12
@@ -89,46 +65,46 @@ struct tac_plus_pak_hdr {
typedef struct tac_plus_pak_hdr HDR;
/* Authentication packet NAS sends to us */
-
struct authen_start {
u_char action;
-#define TAC_PLUS_AUTHEN_LOGIN 0x1
-#define TAC_PLUS_AUTHEN_CHPASS 0x2
-#define TAC_PLUS_AUTHEN_SENDPASS 0x3 /* deprecated */
-#define TAC_PLUS_AUTHEN_SENDAUTH 0x4
+#define TAC_PLUS_AUTHEN_LOGIN 0x01
+#define TAC_PLUS_AUTHEN_CHPASS 0x02
+#define TAC_PLUS_AUTHEN_SENDPASS 0x03 /* deprecated */
+#define TAC_PLUS_AUTHEN_SENDAUTH 0x04
u_char priv_lvl;
-#define TAC_PLUS_PRIV_LVL_MIN 0x0
-#define TAC_PLUS_PRIV_LVL_MAX 0xf
+#define TAC_PLUS_PRIV_LVL_MIN 0x00
+#define TAC_PLUS_PRIV_LVL_MAX 0x0f
+#define TAC_PLUS_PRIV_LVL_USER 0x01
+#define TAC_PLUS_PRIV_LVL_ROOT 0x0f
u_char authen_type;
-#define TAC_PLUS_AUTHEN_TYPE_ASCII 1
-#define TAC_PLUS_AUTHEN_TYPE_PAP 2
-#define TAC_PLUS_AUTHEN_TYPE_CHAP 3
-#define TAC_PLUS_AUTHEN_TYPE_ARAP 4
+#define TAC_PLUS_AUTHEN_TYPE_ASCII 0x01
+#define TAC_PLUS_AUTHEN_TYPE_PAP 0x02
+#define TAC_PLUS_AUTHEN_TYPE_CHAP 0x03
+#define TAC_PLUS_AUTHEN_TYPE_ARAP 0x04
+#define TAC_PLUS_AUTHEN_TYPE_MSCHAP 0x05
u_char service;
-#define TAC_PLUS_AUTHEN_SVC_LOGIN 1
-#define TAC_PLUS_AUTHEN_SVC_ENABLE 2
-#define TAC_PLUS_AUTHEN_SVC_PPP 3
-#define TAC_PLUS_AUTHEN_SVC_ARAP 4
-#define TAC_PLUS_AUTHEN_SVC_PT 5
-#define TAC_PLUS_AUTHEN_SVC_RCMD 6
-#define TAC_PLUS_AUTHEN_SVC_X25 7
-#define TAC_PLUS_AUTHEN_SVC_NASI 8
+#define TAC_PLUS_AUTHEN_SVC_NONE 0x00
+#define TAC_PLUS_AUTHEN_SVC_LOGIN 0x01
+#define TAC_PLUS_AUTHEN_SVC_ENABLE 0x02
+#define TAC_PLUS_AUTHEN_SVC_PPP 0x03
+#define TAC_PLUS_AUTHEN_SVC_ARAP 0x04
+#define TAC_PLUS_AUTHEN_SVC_PT 0x05
+#define TAC_PLUS_AUTHEN_SVC_RCMD 0x06
+#define TAC_PLUS_AUTHEN_SVC_X25 0x07
+#define TAC_PLUS_AUTHEN_SVC_NASI 0x08
+#define TAC_PLUS_AUTHEN_SVC_FWPROXY 0x09
u_char user_len;
u_char port_len;
u_char rem_addr_len;
u_char data_len;
- /* <user_len bytes of char data> */
- /* <port_len bytes of char data> */
- /* <rem_addr_len bytes of u_char data> */
- /* <data_len bytes of u_char data> */
};
#define TAC_AUTHEN_START_FIXED_FIELDS_SIZE 8
@@ -139,10 +115,8 @@ struct authen_cont {
u_short user_data_len;
u_char flags;
-#define TAC_PLUS_CONTINUE_FLAG_ABORT 0x1
+#define TAC_PLUS_CONTINUE_FLAG_ABORT 0x01
- /* <user_msg_len bytes of u_char data> */
- /* <user_data_len bytes of u_char data> */
};
#define TAC_AUTHEN_CONT_FIXED_FIELDS_SIZE 5
@@ -151,43 +125,52 @@ struct authen_cont {
struct authen_reply {
u_char status;
-#define TAC_PLUS_AUTHEN_STATUS_PASS 1
-#define TAC_PLUS_AUTHEN_STATUS_FAIL 2
-#define TAC_PLUS_AUTHEN_STATUS_GETDATA 3
-#define TAC_PLUS_AUTHEN_STATUS_GETUSER 4
-#define TAC_PLUS_AUTHEN_STATUS_GETPASS 5
-#define TAC_PLUS_AUTHEN_STATUS_RESTART 6
-#define TAC_PLUS_AUTHEN_STATUS_ERROR 7
-#define TAC_PLUS_AUTHEN_STATUS_FOLLOW 0x21
+#define TAC_PLUS_AUTHEN_STATUS_PASS 0x01
+#define TAC_PLUS_AUTHEN_STATUS_FAIL 0x02
+#define TAC_PLUS_AUTHEN_STATUS_GETDATA 0x03
+#define TAC_PLUS_AUTHEN_STATUS_GETUSER 0x04
+#define TAC_PLUS_AUTHEN_STATUS_GETPASS 0x05
+#define TAC_PLUS_AUTHEN_STATUS_RESTART 0x06
+#define TAC_PLUS_AUTHEN_STATUS_ERROR 0x07
+#define TAC_PLUS_AUTHEN_STATUS_FOLLOW 0x21
u_char flags;
-#define TAC_PLUS_AUTHEN_FLAG_NOECHO 0x1
+#define TAC_PLUS_AUTHEN_FLAG_NOECHO 0x01
u_short msg_len;
u_short data_len;
-
- /* <msg_len bytes of char data> */
- /* <data_len bytes of u_char data> */
};
#define TAC_AUTHEN_REPLY_FIXED_FIELDS_SIZE 6
-#define AUTHEN_METH_NONE 0x01
-#define AUTHEN_METH_KRB5 0x02
-#define AUTHEN_METH_LINE 0x03
-#define AUTHEN_METH_ENABLE 0x04
-#define AUTHEN_METH_LOCAL 0x05
-#define AUTHEN_METH_TACACSPLUS 0x06
-#define AUTHEN_METH_RCMD 0x20
+#define TAC_PLUS_AUTHEN_METH_NOT_SET 0x00
+#define TAC_PLUS_AUTHEN_METH_NONE 0x01
+#define TAC_PLUS_AUTHEN_METH_KRB5 0x02
+#define TAC_PLUS_AUTHEN_METH_LINE 0x03
+#define TAC_PLUS_AUTHEN_METH_ENABLE 0x04
+#define TAC_PLUS_AUTHEN_METH_LOCAL 0x05
+#define TAC_PLUS_AUTHEN_METH_TACACSPLUS 0x06
+#define TAC_PLUS_AUTHEN_METH_GUEST 0x08
+#define TAC_PLUS_AUTHEN_METH_RADIUS 0x10
+#define TAC_PLUS_AUTHEN_METH_KRB4 0x11
+#define TAC_PLUS_AUTHEN_METH_RCMD 0x20
+
+#define AUTHEN_METH_NONE TAC_PLUS_AUTHEN_METH_NONE
+#define AUTHEN_METH_KRB5 TAC_PLUS_AUTHEN_METH_KRB5
+#define AUTHEN_METH_LINE TAC_PLUS_AUTHEN_METH_LINE
+#define AUTHEN_METH_ENABLE TAC_PLUS_AUTHEN_METH_ENABLE
+#define AUTHEN_METH_LOCAL TAC_PLUS_AUTHEN_METH_LOCAL
+#define AUTHEN_METH_TACACSPLUS TAC_PLUS_AUTHEN_METH_TACACSPLUS
+#define AUTHEN_METH_RCMD TAC_PLUS_AUTHEN_METH_RCMD
struct acct {
u_char flags;
-#define TAC_PLUS_ACCT_FLAG_MORE 0x1
-#define TAC_PLUS_ACCT_FLAG_START 0x2
-#define TAC_PLUS_ACCT_FLAG_STOP 0x4
-#define TAC_PLUS_ACCT_FLAG_WATCHDOG 0x8
+#define TAC_PLUS_ACCT_FLAG_MORE 0x01
+#define TAC_PLUS_ACCT_FLAG_START 0x02
+#define TAC_PLUS_ACCT_FLAG_STOP 0x04
+#define TAC_PLUS_ACCT_FLAG_WATCHDOG 0x08
u_char authen_method;
u_char priv_lvl;
@@ -196,12 +179,7 @@ struct acct {
u_char user_len;
u_char port_len;
u_char rem_addr_len;
- u_char arg_cnt; /* the number of cmd args */
- /* one u_char containing size for each arg */
- /* <user_len bytes of char data> */
- /* <port_len bytes of char data> */
- /* <rem_addr_len bytes of u_char data> */
- /* char data for args 1 ... n */
+ u_char arg_cnt; /* the number of cmd args */
};
#define TAC_ACCT_REQ_FIXED_FIELDS_SIZE 9
@@ -229,13 +207,7 @@ struct author {
u_char user_len;
u_char port_len;
u_char rem_addr_len;
- u_char arg_cnt; /* the number of args */
-
- /* <arg_cnt u_chars containing the lengths of args 1 to arg n> */
- /* <user_len bytes of char data> */
- /* <port_len bytes of char data> */
- /* <rem_addr_len bytes of u_char data> */
- /* <char data for each arg> */
+ u_char arg_cnt; /* the number of args */
};
#define TAC_AUTHOR_REQ_FIXED_FIELDS_SIZE 8
@@ -247,19 +219,20 @@ struct author_reply {
u_short msg_len;
u_short data_len;
-#define AUTHOR_STATUS_PASS_ADD 0x01
-#define AUTHOR_STATUS_PASS_REPL 0x02
-#define AUTHOR_STATUS_FAIL 0x10
-#define AUTHOR_STATUS_ERROR 0x11
-#define AUTHOR_STATUS_FOLLOW 0x21
+#define TAC_PLUS_AUTHOR_STATUS_PASS_ADD 0x01
+#define TAC_PLUS_AUTHOR_STATUS_PASS_REPL 0x02
+#define TAC_PLUS_AUTHOR_STATUS_FAIL 0x10
+#define TAC_PLUS_AUTHOR_STATUS_ERROR 0x11
+#define TAC_PLUS_AUTHOR_STATUS_FOLLOW 0x21
+
+#define AUTHOR_STATUS_PASS_ADD TAC_PLUS_AUTHOR_STATUS_PASS_ADD
+#define AUTHOR_STATUS_PASS_REPL TAC_PLUS_AUTHOR_STATUS_PASS_REPL
+#define AUTHOR_STATUS_FAIL TAC_PLUS_AUTHOR_STATUS_FAIL
+#define AUTHOR_STATUS_ERROR TAC_PLUS_AUTHOR_STATUS_ERROR
+#define AUTHOR_STATUS_FOLLOW TAC_PLUS_AUTHOR_STATUS_FOLLOW
- /* <arg_cnt u_chars containing the lengths of arg 1 to arg n> */
- /* <msg_len bytes of char data> */
- /* <data_len bytes of char data> */
- /* <char data for each arg> */
};
#define TAC_AUTHOR_REPLY_FIXED_FIELDS_SIZE 6
-
#endif
diff --git a/libtac/lib/acct_r.c b/libtac/lib/acct_r.c
index d30d18f..0f23d04 100644
--- a/libtac/lib/acct_r.c
+++ b/libtac/lib/acct_r.c
@@ -1,6 +1,6 @@
/* acct_r.c - Read accounting reply from server.
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -20,78 +20,134 @@
*/
#include "tacplus.h"
+#include "xalloc.h"
#include "libtac.h"
#include "messages.h"
-char *tac_account_read(int fd) {
- HDR th;
- struct acct_reply *tb;
- int len_from_header, r, len_from_body;
- char *msg = NULL;
-
- r=read(fd, &th, TAC_PLUS_HDR_SIZE);
- if(r < TAC_PLUS_HDR_SIZE) {
- syslog(LOG_ERR,
- "%s: short acct header, %d of %d: %m", __FUNCTION__,
- r, TAC_PLUS_HDR_SIZE);
- return(system_err_msg);
- }
-
- /* check the reply fields in header */
- msg = _tac_check_header(&th, TAC_PLUS_ACCT);
- if(msg != NULL)
- return(msg);
-
- len_from_header=ntohl(th.datalength);
- tb=(struct acct_reply *) xcalloc(1, len_from_header);
-
- /* read reply packet body */
- r=read(fd, tb, len_from_header);
- if(r < len_from_header) {
- syslog(LOG_ERR,
- "%s: incomplete message body, %d bytes, expected %d: %m",
- __FUNCTION__,
- r, len_from_header);
- return(system_err_msg);
- }
-
- /* decrypt the body */
- _tac_crypt((u_char *) tb, &th, len_from_header);
-
- /* Convert network byte order to host byte order */
- tb->msg_len = ntohs(tb->msg_len);
- tb->data_len = ntohs(tb->data_len);
-
- /* check the length fields */
- len_from_body=sizeof(tb->msg_len) + sizeof(tb->data_len) +
- sizeof(tb->status) + tb->msg_len + tb->data_len;
-
- if(len_from_header != len_from_body) {
- syslog(LOG_ERR,
- "%s: invalid reply content, incorrect key?",
- __FUNCTION__);
- return(system_err_msg);
- }
-
- /* save status and clean up */
- r=tb->status;
- if(tb->msg_len) {
- msg=(char *) xcalloc(1, tb->msg_len);
- bcopy((u_char *) tb+TAC_ACCT_REPLY_FIXED_FIELDS_SIZE, msg, tb->msg_len);
- } else
- msg="Accounting failed";
-
- free(tb);
-
- /* server logged our request successfully */
- if(r == TAC_PLUS_ACCT_STATUS_SUCCESS) {
- TACDEBUG((LOG_DEBUG, "%s: accounted ok", __FUNCTION__))
- msg=NULL;
- return(NULL);
- }
- /* return pointer to server message */
- syslog(LOG_DEBUG, "%s: accounting failed, server reply was %d (%s)",
- __FUNCTION__, r, msg);
- return(msg);
+/*
+ * return value:
+ * < 0 : error status code, see LIBTAC_STATUS_...
+ * LIBTAC_STATUS_READ_TIMEOUT
+ * LIBTAC_STATUS_SHORT_HDR
+ * LIBTAC_STATUS_SHORT_BODY
+ * LIBTAC_STATUS_PROTOCOL_ERR
+ * >= 0 : server response, see TAC_PLUS_AUTHEN_STATUS_...
+ */
+int tac_account_read(int fd, struct areply *re) {
+ HDR th;
+ struct acct_reply *tb = NULL;
+ int len_from_header, r, len_from_body;
+ char *msg = NULL;
+ int timeleft;
+ re->attr = NULL; /* unused */
+ re->msg = NULL;
+
+ if (tac_readtimeout_enable &&
+ tac_read_wait(fd,tac_timeout*1000, TAC_PLUS_HDR_SIZE,&timeleft) < 0 ) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: reply timeout after %d secs", __FUNCTION__, tac_timeout))
+ re->msg = xstrdup(acct_syserr_msg);
+ re->status = LIBTAC_STATUS_READ_TIMEOUT;
+ goto AcctExit;
+ }
+
+ r=read(fd, &th, TAC_PLUS_HDR_SIZE);
+ if(r < TAC_PLUS_HDR_SIZE) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: short reply header, read %d of %d: %m", __FUNCTION__,\
+ r, TAC_PLUS_HDR_SIZE))
+ re->msg = xstrdup(acct_syserr_msg);
+ re->status = LIBTAC_STATUS_SHORT_HDR;
+ goto AcctExit;
+ }
+
+ /* check the reply fields in header */
+ msg = _tac_check_header(&th, TAC_PLUS_ACCT);
+ if(msg != NULL) {
+ re->msg = xstrdup(msg);
+ re->status = LIBTAC_STATUS_PROTOCOL_ERR;
+ goto AcctExit;
+ }
+
+ len_from_header=ntohl(th.datalength);
+ tb=(struct acct_reply *) xcalloc(1, len_from_header);
+
+ /* read reply packet body */
+ if (tac_readtimeout_enable &&
+ tac_read_wait(fd,timeleft,len_from_header,NULL) < 0 ) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: reply timeout after %d secs", __FUNCTION__, tac_timeout))
+ re->msg = xstrdup(acct_syserr_msg);
+ re->status = LIBTAC_STATUS_READ_TIMEOUT;
+ goto AcctExit;
+ }
+
+ r=read(fd, tb, len_from_header);
+ if(r < len_from_header) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: short reply body, read %d of %d: %m",\
+ __FUNCTION__,\
+ r, len_from_header))
+ re->msg = xstrdup(acct_syserr_msg);
+ re->status = LIBTAC_STATUS_SHORT_BODY;
+ goto AcctExit;
+ }
+
+ /* decrypt the body */
+ _tac_crypt((u_char *) tb, &th, len_from_header);
+
+ /* Convert network byte order to host byte order */
+ tb->msg_len = ntohs(tb->msg_len);
+ tb->data_len = ntohs(tb->data_len);
+
+ /* check the length fields */
+ len_from_body=sizeof(tb->msg_len) + sizeof(tb->data_len) +
+ sizeof(tb->status) + tb->msg_len + tb->data_len;
+
+ if(len_from_header != len_from_body) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: inconsistent reply body, incorrect key?",\
+ __FUNCTION__))
+ re->msg = xstrdup(acct_syserr_msg);
+ re->status = LIBTAC_STATUS_PROTOCOL_ERR;
+ goto AcctExit;
+ }
+
+ /* save status and clean up */
+ r=tb->status;
+ if(tb->msg_len) {
+ msg=(char *) xcalloc(1, tb->msg_len+1);
+ bcopy((u_char *) tb+TAC_ACCT_REPLY_FIXED_FIELDS_SIZE, msg, tb->msg_len);
+ msg[(int)tb->msg_len] = '\0';
+ re->msg = msg; // Freed by caller
+ }
+
+ /* server logged our request successfully */
+ if (tb->status == TAC_PLUS_ACCT_STATUS_SUCCESS) {
+ TACDEBUG((LOG_DEBUG, "%s: accounted ok", __FUNCTION__))
+ if (!re->msg) re->msg=xstrdup(acct_ok_msg);
+ re->status = tb->status;
+ goto AcctExit;
+ }
+
+ TACDEBUG((LOG_DEBUG, "%s: accounting failed, server reply status=%d",\
+ __FUNCTION__, tb->status))
+ switch(tb->status) {
+ case TAC_PLUS_ACCT_STATUS_FOLLOW:
+ re->status = tb->status;
+ if (!re->msg) re->msg=xstrdup(acct_fail_msg);
+ break;
+
+ case TAC_PLUS_ACCT_STATUS_ERROR:
+ default:
+ re->status = tb->status;
+ if (!re->msg) re->msg=xstrdup(acct_err_msg);
+ break;
+ }
+AcctExit:
+ free(tb);
+ TACDEBUG((LOG_DEBUG, "%s: exit status=%d, status message \"%s\"",\
+ __FUNCTION__, re->status, re->msg != NULL ? re->msg : ""))
+ return(re->status);
}
diff --git a/libtac/lib/acct_s.c b/libtac/lib/acct_s.c
index 5ca07c3..dd3dff9 100644
--- a/libtac/lib/acct_s.c
+++ b/libtac/lib/acct_s.c
@@ -1,6 +1,6 @@
/* acct_s.c - Send accounting event information to server.
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -23,129 +23,138 @@
#include "libtac.h"
#include "xalloc.h"
+/*
+ * return value:
+ * 0 : success
+ * < 0 : error status code, see LIBTAC_STATUS_...
+ * LIBTAC_STATUS_WRITE_ERR
+ * LIBTAC_STATUS_WRITE_TIMEOUT (pending impl)
+ * LIBTAC_STATUS_ASSEMBLY_ERR (pending impl)
+ */
int tac_account_send(int fd, int type, const char *user, char *tty,
- struct tac_attrib *attr) {
- HDR *th;
- struct acct tb;
- u_char user_len, port_len;
- struct tac_attrib *a;
- int i = 0; /* arg count */
- int pkt_len = 0;
- int pktl = 0;
- int w; /* write count */
- u_char *pkt;
- /* u_char *pktp; */ /* obsolute */
- int ret = 0;
-
- th=_tac_req_header(TAC_PLUS_ACCT);
-
- /* set header options */
- th->version=TAC_PLUS_VER_0;
- th->encryption=tac_encryption ? TAC_PLUS_ENCRYPTED : TAC_PLUS_CLEAR;
-
- TACDEBUG((LOG_DEBUG, "%s: user '%s', tty '%s', encrypt: %s, type: %s", \
- __FUNCTION__, user, tty, \
- (tac_encryption) ? "yes" : "no", \
- (type == TAC_PLUS_ACCT_FLAG_START) ? "START" : "STOP"))
-
- user_len=(u_char) strlen(user);
- port_len=(u_char) strlen(tty);
-
- tb.flags=(u_char) type;
- tb.authen_method=AUTHEN_METH_TACACSPLUS;
- tb.priv_lvl=TAC_PLUS_PRIV_LVL_MIN;
- if(strcmp(tac_login,"chap") == 0) {
- tb.authen_type=TAC_PLUS_AUTHEN_TYPE_CHAP;
- } else if(strcmp(tac_login,"login") == 0) {
- tb.authen_type=TAC_PLUS_AUTHEN_TYPE_ASCII;
- } else {
- tb.authen_type=TAC_PLUS_AUTHEN_TYPE_PAP;
- }
- tb.authen_service=TAC_PLUS_AUTHEN_SVC_PPP;
- tb.user_len=user_len;
- tb.port_len=port_len;
- tb.rem_addr_len=0;
-
- /* allocate packet */
- pkt=(u_char *) xcalloc(1, TAC_ACCT_REQ_FIXED_FIELDS_SIZE);
- pkt_len=sizeof(tb);
-
- /* fill attribute length fields */
- a = attr;
- while(a) {
-
- pktl = pkt_len;
- pkt_len += sizeof(a->attr_len);
- pkt = xrealloc(pkt, pkt_len);
-
- /* see comments in author_s.c
- pktp=pkt + pkt_len;
- pkt_len += sizeof(a->attr_len);
- pkt = xrealloc(pkt, pkt_len);
- */
-
- bcopy(&a->attr_len, pkt + pktl, sizeof(a->attr_len));
- i++;
-
- a = a->next;
- }
-
- /* fill the arg count field and add the fixed fields to packet */
- tb.arg_cnt = i;
- bcopy(&tb, pkt, TAC_ACCT_REQ_FIXED_FIELDS_SIZE);
-
- /*
+ char *rem_addr, struct tac_attrib *attr) {
+
+ HDR *th;
+ struct acct tb;
+ u_char user_len, port_len, rem_addr_len;
+ struct tac_attrib *a;
+ int i = 0; /* arg count */
+ int pkt_len = 0;
+ int pktl = 0;
+ int w; /* write count */
+ u_char *pkt=NULL;
+ /* u_char *pktp; */ /* obsolute */
+ int ret = 0;
+
+ th=_tac_req_header(TAC_PLUS_ACCT, 0);
+
+ /* set header options */
+ th->version=TAC_PLUS_VER_0;
+ th->encryption=tac_encryption ? TAC_PLUS_ENCRYPTED_FLAG : TAC_PLUS_UNENCRYPTED_FLAG;
+
+ TACDEBUG((LOG_DEBUG, "%s: user '%s', tty '%s', rem_addr '%s', encrypt: %s, type: %s", \
+ __FUNCTION__, user, tty, rem_addr, \
+ (tac_encryption) ? "yes" : "no", \
+ (type == TAC_PLUS_ACCT_FLAG_START) ? "START" : "STOP"))
+
+ user_len=(u_char) strlen(user);
+ port_len=(u_char) strlen(tty);
+ rem_addr_len=(u_char) strlen(rem_addr);
+
+ tb.flags=(u_char) type;
+ tb.authen_method=tac_authen_method;
+ tb.priv_lvl=tac_priv_lvl;
+ if(strcmp(tac_login,"chap") == 0) {
+ tb.authen_type=TAC_PLUS_AUTHEN_TYPE_CHAP;
+ } else if(strcmp(tac_login,"login") == 0) {
+ tb.authen_type=TAC_PLUS_AUTHEN_TYPE_ASCII;
+ } else {
+ tb.authen_type=TAC_PLUS_AUTHEN_TYPE_PAP;
+ }
+ tb.authen_service=tac_authen_service;
+ tb.user_len=user_len;
+ tb.port_len=port_len;
+ tb.rem_addr_len=rem_addr_len;
+
+ /* allocate packet */
+ pkt=(u_char *) xcalloc(1, TAC_ACCT_REQ_FIXED_FIELDS_SIZE);
+ pkt_len=sizeof(tb);
+
+ /* fill attribute length fields */
+ a = attr;
+ while(a) {
+ pktl = pkt_len;
+ pkt_len += sizeof(a->attr_len);
+ pkt = (u_char*) xrealloc(pkt, pkt_len);
+
+ /* see comments in author_s.c
+ pktp=pkt + pkt_len;
+ pkt_len += sizeof(a->attr_len);
+ pkt = xrealloc(pkt, pkt_len);
+ */
+
+ bcopy(&a->attr_len, pkt + pktl, sizeof(a->attr_len));
+ i++;
+
+ a = a->next;
+ }
+
+ /* fill the arg count field and add the fixed fields to packet */
+ tb.arg_cnt = i;
+ bcopy(&tb, pkt, TAC_ACCT_REQ_FIXED_FIELDS_SIZE);
+
+ /*
#define PUTATTR(data, len) \
- pktp = pkt + pkt_len; \
- pkt_len += len; \
- pkt = xrealloc(pkt, pkt_len); \
- bcopy(data, pktp, len);
-*/
+ pktp = pkt + pkt_len; \
+ pkt_len += len; \
+ pkt = xrealloc(pkt, pkt_len); \
+ bcopy(data, pktp, len);
+ */
#define PUTATTR(data, len) \
- pktl = pkt_len; \
- pkt_len += len; \
- pkt = xrealloc(pkt, pkt_len); \
- bcopy(data, pkt + pktl, len);
-
- /* fill user and port fields */
- PUTATTR(user, user_len)
- PUTATTR(tty, port_len)
-
- /* fill attributes */
- a = attr;
- while(a) {
- PUTATTR(a->attr, a->attr_len)
-
- a = a->next;
- }
-
- /* finished building packet, fill len_from_header in header */
- th->datalength = htonl(pkt_len);
-
- /* write header */
- w=write(fd, th, TAC_PLUS_HDR_SIZE);
-
- if(w < TAC_PLUS_HDR_SIZE) {
- syslog(LOG_ERR, "%s: acct hdr send failed: wrote %d of %d",
- __FUNCTION__, w,
- TAC_PLUS_HDR_SIZE);
- ret = -1;
- }
-
- /* encrypt packet body */
- _tac_crypt(pkt, th, pkt_len);
-
- /* write body */
- w=write(fd, pkt, pkt_len);
- if(w < pkt_len) {
- syslog(LOG_ERR, "%s: acct body send failed: wrote %d of %d",
- __FUNCTION__, w,
- pkt_len);
- ret = -1;
- }
-
- free(pkt);
- free(th);
-
- return(ret);
+ pktl = pkt_len; \
+ pkt_len += len; \
+ pkt = (u_char*) xrealloc(pkt, pkt_len); \
+ bcopy(data, pkt + pktl, len);
+
+ /* fill user and port fields */
+ PUTATTR(user, user_len)
+ PUTATTR(tty, port_len)
+ PUTATTR(rem_addr, rem_addr_len)
+
+ /* fill attributes */
+ a = attr;
+ while(a) {
+ PUTATTR(a->attr, a->attr_len)
+ a = a->next;
+ }
+
+ /* finished building packet, fill len_from_header in header */
+ th->datalength = htonl(pkt_len);
+
+ /* write header */
+ w=write(fd, th, TAC_PLUS_HDR_SIZE);
+
+ if(w < TAC_PLUS_HDR_SIZE) {
+ TACSYSLOG((LOG_ERR, "%s: short write on header, wrote %d of %d: %m",\
+ __FUNCTION__, w, TAC_PLUS_HDR_SIZE))
+ ret = LIBTAC_STATUS_WRITE_ERR;
+ goto AcctExit;
+ }
+
+ /* encrypt packet body */
+ _tac_crypt(pkt, th, pkt_len);
+
+ /* write body */
+ w=write(fd, pkt, pkt_len);
+ if(w < pkt_len) {
+ TACSYSLOG((LOG_ERR, "%s: short write on body, wrote %d of %d: %m",\
+ __FUNCTION__, w, pkt_len))
+ ret = LIBTAC_STATUS_WRITE_ERR;
+ }
+
+AcctExit:
+ free(pkt);
+ free(th);
+ TACDEBUG((LOG_DEBUG, "%s: exit status=%d", __FUNCTION__, ret))
+ return(ret);
}
diff --git a/libtac/lib/attrib.c b/libtac/lib/attrib.c
index 761cde0..f409796 100644
--- a/libtac/lib/attrib.c
+++ b/libtac/lib/attrib.c
@@ -1,7 +1,7 @@
/* attrib.c - Procedures for handling internal list of attributes
- * for accounting and authorization functions.
+ * for accounting and authorization functions.
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -25,56 +25,64 @@
#include "xalloc.h"
void tac_add_attrib(struct tac_attrib **attr, char *name, char *value) {
- struct tac_attrib *a;
- u_char l1 = (u_char) strlen(name);
- u_char l2 = (u_char) strlen(value);
- int total_len = l1 + l2 + 1; /* "name" + "=" + "value" */
+ tac_add_attrib_pair(attr, name, '=', value);
+}
- if(total_len > 255) {
- syslog(LOG_WARNING, "%s: attribute `%s' total length exceeds 255 characters, skipping", __FUNCTION__, name);
- return;
- }
-
- /* initialize the list if application passed us a null pointer */
- if(*attr == NULL) {
- *attr = (struct tac_attrib *) xcalloc(1, sizeof(struct tac_attrib));
- a = *attr;
- } else {
- /* find the last allocated block */
- a = *attr;
- while(a->next != NULL)
- a = a->next; /* a holds last allocated block */
+void tac_add_attrib_pair(struct tac_attrib **attr, char *name, char sep, char *value) {
+ struct tac_attrib *a;
+ u_char l1 = (u_char) strlen(name);
+ u_char l2 = (u_char) strlen(value);
+ int total_len = l1 + l2 + 1; /* "name" + "=" + "value" */
- a->next = (struct tac_attrib *) xcalloc(1, sizeof(struct tac_attrib));
- a = a->next; /* set current block pointer to the new one */
- }
+ if (total_len > 255) {
+ TACSYSLOG((LOG_WARNING,\
+ "%s: attribute `%s' total length exceeds 255 characters, skipping",\
+ __FUNCTION__, name))
+ return;
+ }
+
+ /* initialize the list if application passed us a null pointer */
+ if(*attr == NULL) {
+ *attr = (struct tac_attrib *) xcalloc(1, sizeof(struct tac_attrib));
+ a = *attr;
+ } else {
+ /* find the last allocated block */
+ a = *attr;
+ while(a->next != NULL)
+ a = a->next; /* a holds last allocated block */
- /* fill the block */
- a->attr_len=total_len;
- a->attr = (char *) xcalloc(1, total_len);
- bcopy(name, a->attr, l1); /* paste name */
- *(a->attr+l1)='='; /* insert "=" */
- bcopy(value, (a->attr+l1+1), l2); /* paste value */
+ a->next = (struct tac_attrib *) xcalloc(1, sizeof(struct tac_attrib));
+ a = a->next; /* set current block pointer to the new one */
+ }
- a->next = NULL; /* make sure it's null */
+ if ( sep != '=' && sep != '*' ) {
+ sep = '=';
+ }
+ /* fill the block */
+ a->attr_len=total_len;
+ a->attr = (char *) xcalloc(1, total_len+1);
+ bcopy(name, a->attr, l1); /* paste name */
+ *(a->attr+l1)=sep; /* insert seperator "[=*]" */
+ bcopy(value, (a->attr+l1+1), l2); /* paste value */
+ *(a->attr+total_len) = '\0'; /* add 0 for safety */
+ a->next = NULL; /* make sure it's null */
}
void tac_free_attrib(struct tac_attrib **attr) {
- struct tac_attrib *a;
- struct tac_attrib *b;
-
- if(*attr == NULL)
- return;
+ struct tac_attrib *a;
+ struct tac_attrib *b;
- a = b = *attr;
-
- /* find last allocated block */
- do {
- a = b;
- b = a->next;
- free(a->attr);
- free(a);
- } while (b != NULL);
+ if(*attr == NULL)
+ return;
+ a = b = *attr;
+
+ /* find last allocated block */
+ do {
+ a = b;
+ b = a->next;
+ free(a->attr);
+ free(a);
+ } while (b != NULL);
}
diff --git a/libtac/lib/authen_r.c b/libtac/lib/authen_r.c
index 55acac5..cd2ab2a 100644
--- a/libtac/lib/authen_r.c
+++ b/libtac/lib/authen_r.c
@@ -1,6 +1,6 @@
/* authen_r.c - Read authentication reply from server.
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -26,79 +26,110 @@
/* reads packet from TACACS+ server; returns:
* TAC_PLUS_AUTHEN_STATUS_PASS if the authentication succeded
* an other integer if failed. Check tacplus.h for all possible values
+ *
+ * return value:
+ * < 0 : error status code, see LIBTAC_STATUS_...
+ * LIBTAC_STATUS_READ_TIMEOUT
+ * LIBTAC_STATUS_SHORT_HDR
+ * LIBTAC_STATUS_SHORT_BODY
+ * LIBTAC_STATUS_PROTOCOL_ERR
+ * >= 0 : server response, see TAC_PLUS_AUTHEN_STATUS_...
*/
int tac_authen_read(int fd) {
- HDR th;
- struct authen_reply *tb;
- int len_from_header, r, len_from_body;
- char *msg = NULL;
+ HDR th;
+ struct authen_reply *tb = NULL;
+ int len_from_header, r, len_from_body;
+ char *msg = NULL;
+ int timeleft;
+ int status;
- /* read the reply header */
- r=read(fd, &th, TAC_PLUS_HDR_SIZE);
- if(r < TAC_PLUS_HDR_SIZE) {
- syslog(LOG_ERR,
- "%s: error reading authen header, read %d of %d: %m",
- __FUNCTION__,
- r, TAC_PLUS_HDR_SIZE);
- return(TAC_PLUS_AUTHEN_STATUS_FAIL);
- }
+ /* read the reply header */
+ if (tac_readtimeout_enable &&
+ tac_read_wait(fd,tac_timeout*1000,TAC_PLUS_HDR_SIZE,&timeleft) < 0 ) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: reply timeout after %d secs", __FUNCTION__, tac_timeout))
+ status=LIBTAC_STATUS_READ_TIMEOUT;
+ goto AuthenExit;
+ }
+ r = read(fd, &th, TAC_PLUS_HDR_SIZE);
+ if (r < TAC_PLUS_HDR_SIZE) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: short reply header, read %d of %d: %m",\
+ __FUNCTION__,\
+ r, TAC_PLUS_HDR_SIZE))
+ status=LIBTAC_STATUS_SHORT_HDR;
+ goto AuthenExit;
+ }
- /* check the reply fields in header */
- msg = _tac_check_header(&th, TAC_PLUS_AUTHEN);
- if(msg != NULL)
- return(TAC_PLUS_AUTHEN_STATUS_FAIL);
+ /* check the reply fields in header */
+ msg = _tac_check_header(&th, TAC_PLUS_AUTHEN);
+ if(msg != NULL) {
+ status = LIBTAC_STATUS_PROTOCOL_ERR;
+ goto AuthenExit;
+ }
- len_from_header=ntohl(th.datalength);
- tb=(struct authen_reply *) xcalloc(1, len_from_header);
+ len_from_header = ntohl(th.datalength);
+ tb = (struct authen_reply *) xcalloc(1, len_from_header);
- /* read reply packet body */
- r=read(fd, tb, len_from_header);
- if(r < len_from_header) {
- syslog(LOG_ERR,
- "%s: incomplete message body, %d bytes, expected %d: %m",
- __FUNCTION__,
- r, len_from_header);
- return(TAC_PLUS_AUTHEN_STATUS_FAIL);
- }
+ /* read reply packet body */
+ if (tac_readtimeout_enable &&
+ tac_read_wait(fd,timeleft,len_from_header,NULL) < 0 ) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: reply timeout after %d secs", __FUNCTION__, tac_timeout))
+ status=LIBTAC_STATUS_READ_TIMEOUT;
+ }
+ r = read(fd, tb, len_from_header);
+ if (r < len_from_header) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: short reply body, read %d of %d: %m",\
+ __FUNCTION__,\
+ r, len_from_header))
+ status=LIBTAC_STATUS_SHORT_BODY;
+ goto AuthenExit;
+ }
- /* decrypt the body */
- _tac_crypt((u_char *) tb, &th, len_from_header);
+ /* decrypt the body */
+ _tac_crypt((u_char *) tb, &th, len_from_header);
- /* Convert network byte order to host byte order */
- tb->msg_len = ntohs(tb->msg_len);
- tb->data_len = ntohs(tb->data_len);
+ /* Convert network byte order to host byte order */
+ tb->msg_len = ntohs(tb->msg_len);
+ tb->data_len = ntohs(tb->data_len);
- /* check the length fields */
- len_from_body=sizeof(tb->status) + sizeof(tb->flags) +
- sizeof(tb->msg_len) + sizeof(tb->data_len) +
- tb->msg_len + tb->data_len;
+ /* check the length fields */
+ len_from_body = sizeof(tb->status) + sizeof(tb->flags) +
+ sizeof(tb->msg_len) + sizeof(tb->data_len) +
+ tb->msg_len + tb->data_len;
- if(len_from_header != len_from_body) {
- syslog(LOG_ERR,
- "%s: invalid reply content, incorrect key?",
- __FUNCTION__);
- return(TAC_PLUS_AUTHEN_STATUS_FAIL);
- }
+ if(len_from_header != len_from_body) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: inconsistent reply body, incorrect key?",\
+ __FUNCTION__))
+ status=LIBTAC_STATUS_PROTOCOL_ERR;
+ goto AuthenExit;
+ }
- /* save status and clean up */
- r=tb->status;
- free(tb);
+ /* save status and clean up */
+ r = tb->status;
+ status = r;
- /* server authenticated username and password successfully */
- if(r == TAC_PLUS_AUTHEN_STATUS_PASS) {
- TACDEBUG((LOG_DEBUG, "%s: authentication ok", __FUNCTION__))
- return(r);
- }
-
- /* server ask for continue packet with password */
- if(r == TAC_PLUS_AUTHEN_STATUS_GETPASS) {
- TACDEBUG((LOG_DEBUG, "%s: continue packet with password needed", __FUNCTION__))
- return(r);
- }
+ /* server authenticated username and password successfully */
+ if (r == TAC_PLUS_AUTHEN_STATUS_PASS) {
+ TACDEBUG((LOG_DEBUG, "%s: authentication ok", __FUNCTION__))
+ goto AuthenExit;
+ }
+
+ /* server ask for continue packet with password */
+ if (r == TAC_PLUS_AUTHEN_STATUS_GETPASS) {
+ TACDEBUG((LOG_DEBUG, "%s: continue packet with password needed", __FUNCTION__))
+ goto AuthenExit;
+ }
- /* return pointer to server message */
- syslog(LOG_DEBUG, "%s: authentication failed, server reply was %d",
- __FUNCTION__, r);
- return(r);
+ TACDEBUG((LOG_DEBUG, "%s: authentication failed, server reply status=%d",\
+ __FUNCTION__, r))
-} /* tac_authen_read */
+AuthenExit:
+ free(tb);
+ TACDEBUG((LOG_DEBUG, "%s: exit status=%d",\
+ __FUNCTION__, status))
+ return(status);
+} /* tac_authen_read */
diff --git a/libtac/lib/authen_s.c b/libtac/lib/authen_s.c
index 4a7e55a..d241839 100644
--- a/libtac/lib/authen_s.c
+++ b/libtac/lib/authen_s.c
@@ -1,6 +1,6 @@
/* authen_s.c - Send authentication request to the server.
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -21,123 +21,143 @@
#include "tacplus.h"
#include "libtac.h"
+#include "xalloc.h"
#include "md5.h"
/* this function sends a packet do TACACS+ server, asking
* for validation of given username and password
+ *
+ * return value:
+ * 0 : success
+ * < 0 : error status code, see LIBTAC_STATUS_...
+ * LIBTAC_STATUS_WRITE_ERR
+ * LIBTAC_STATUS_WRITE_TIMEOUT
+ * LIBTAC_STATUS_ASSEMBLY_ERR
*/
-int tac_authen_send(int fd, const char *user, char *pass, char *tty)
-{
- HDR *th; /* TACACS+ packet header */
- struct authen_start tb; /* message body */
- int user_len, port_len, chal_len, mdp_len, token_len, bodylength, w;
- int pkt_len=0;
- int ret=0;
- char *chal = "1234123412341234";
- char digest[MD5_LEN];
- char *token;
- u_char *pkt, *mdp;
- MD5_CTX mdcontext;
-
- th=_tac_req_header(TAC_PLUS_AUTHEN);
-
- /* set some header options */
- if(strcmp(tac_login,"login") == 0) {
- th->version=TAC_PLUS_VER_0;
- } else {
- th->version=TAC_PLUS_VER_1;
- }
- th->encryption=tac_encryption ? TAC_PLUS_ENCRYPTED : TAC_PLUS_CLEAR;
-
- TACDEBUG((LOG_DEBUG, "%s: user '%s', tty '%s', encrypt: %s", \
- __FUNCTION__, user, tty, \
- (tac_encryption) ? "yes" : "no"))
-
- if(strcmp(tac_login,"chap") == 0) {
- chal_len = strlen(chal);
- mdp_len = sizeof(u_char) + strlen(pass) + chal_len;
- mdp = (u_char *) xcalloc(1, mdp_len);
- mdp[0] = 5;
- memcpy(&mdp[1], pass, strlen(pass));
- memcpy(mdp + strlen(pass) + 1, chal, chal_len);
- MD5Init(&mdcontext);
- MD5Update(&mdcontext, mdp, mdp_len);
- MD5Final((u_char *) digest, &mdcontext);
- free(mdp);
- token = xcalloc(1, sizeof(u_char) + 1 + chal_len + MD5_LEN);
- token[0] = 5;
- memcpy(&token[1], chal, chal_len);
- memcpy(token + chal_len + 1, digest, MD5_LEN);
- } else {
- token = pass;
- }
-
- /* get size of submitted data */
- user_len=strlen(user);
- port_len=strlen(tty);
- token_len=strlen(token);
-
- /* fill the body of message */
- tb.action=TAC_PLUS_AUTHEN_LOGIN;
- tb.priv_lvl=TAC_PLUS_PRIV_LVL_MIN;
- if(strcmp(tac_login,"chap") == 0) {
- tb.authen_type=TAC_PLUS_AUTHEN_TYPE_CHAP;
- } else if(strcmp(tac_login,"login") == 0) {
- tb.authen_type=TAC_PLUS_AUTHEN_TYPE_ASCII;
- } else {
- tb.authen_type=TAC_PLUS_AUTHEN_TYPE_PAP;
- }
- tb.service=TAC_PLUS_AUTHEN_SVC_PPP;
- tb.user_len=user_len;
- tb.port_len=port_len;
- tb.rem_addr_len=0; /* may be e.g Caller-ID in future */
- tb.data_len=token_len;
-
- /* fill body length in header */
- bodylength=sizeof(tb) + user_len
- + port_len + token_len; /* + rem_addr_len */
-
- th->datalength= htonl(bodylength);
-
- /* we can now write the header */
- w=write(fd, th, TAC_PLUS_HDR_SIZE);
- if(w < 0 || w < TAC_PLUS_HDR_SIZE) {
- syslog(LOG_ERR, "%s: short write on header: wrote %d of %d: %m",
- __FUNCTION__, w, TAC_PLUS_HDR_SIZE);
- ret=-1;
- }
-
- /* build the packet */
- pkt=(u_char *) xcalloc(1, bodylength+10);
-
- bcopy(&tb, pkt+pkt_len, sizeof(tb)); /* packet body beginning */
- pkt_len+=sizeof(tb);
- bcopy(user, pkt+pkt_len, user_len); /* user */
- pkt_len+=user_len;
- bcopy(tty, pkt+pkt_len, port_len); /* tty */
- pkt_len+=port_len;
- bcopy(token, pkt+pkt_len, token_len); /* password */
- pkt_len+=token_len;
-
- /* pkt_len == bodylength ? */
- if(pkt_len != bodylength) {
- syslog(LOG_ERR, "%s: bodylength %d != pkt_len %d",
- __FUNCTION__, bodylength, pkt_len);
- ret=-1;
- }
-
- /* encrypt the body */
- _tac_crypt(pkt, th, bodylength);
-
- w=write(fd, pkt, pkt_len);
- if(w < 0 || w < pkt_len) {
- syslog(LOG_ERR, "%s: short write on body: wrote %d of %d: %m",
- __FUNCTION__, w, pkt_len);
- ret=-1;
- }
-
- free(pkt);
- free(th);
-
- return(ret);
-} /* tac_authen_send */
+int tac_authen_send(int fd, const char *user, char *pass, char *tty,
+ char *rem_addr) {
+
+ HDR *th; /* TACACS+ packet header */
+ struct authen_start tb; /* message body */
+ int user_len, port_len, chal_len, mdp_len, token_len, bodylength, w;
+ int rem_addr_len;
+ int pkt_len = 0;
+ int ret = 0;
+ char *chal = "1234123412341234";
+ char digest[MD5_LEN];
+ char *token = NULL;
+ u_char *pkt = NULL, *mdp = NULL;
+ MD5_CTX mdcontext;
+
+ th=_tac_req_header(TAC_PLUS_AUTHEN, 0);
+
+ /* set some header options */
+ if(strcmp(tac_login,"login") == 0) {
+ th->version = TAC_PLUS_VER_0;
+ } else {
+ th->version = TAC_PLUS_VER_1;
+ }
+ th->encryption = tac_encryption ? TAC_PLUS_ENCRYPTED_FLAG : TAC_PLUS_UNENCRYPTED_FLAG;
+
+ TACDEBUG((LOG_DEBUG, "%s: user '%s', tty '%s', rem_addr '%s', encrypt: %s", \
+ __FUNCTION__, user, tty, rem_addr, \
+ (tac_encryption) ? "yes" : "no"))
+
+ if(strcmp(tac_login,"chap") == 0) {
+ chal_len = strlen(chal);
+ mdp_len = sizeof(u_char) + strlen(pass) + chal_len;
+ mdp = (u_char *) xcalloc(1, mdp_len);
+ mdp[0] = 5;
+ memcpy(&mdp[1], pass, strlen(pass));
+ memcpy(mdp + strlen(pass) + 1, chal, chal_len);
+ MD5Init(&mdcontext);
+ MD5Update(&mdcontext, mdp, mdp_len);
+ MD5Final((u_char *) digest, &mdcontext);
+ free(mdp);
+ token = (char*) xcalloc(1, sizeof(u_char) + 1 + chal_len + MD5_LEN);
+ token[0] = 5;
+ memcpy(&token[1], chal, chal_len);
+ memcpy(token + chal_len + 1, digest, MD5_LEN);
+ } else {
+ token = xstrdup(pass);
+ }
+
+ /* get size of submitted data */
+ user_len = strlen(user);
+ port_len = strlen(tty);
+ rem_addr_len = strlen(rem_addr);
+ token_len = strlen(token);
+
+ /* fill the body of message */
+ tb.action = TAC_PLUS_AUTHEN_LOGIN;
+ tb.priv_lvl = tac_priv_lvl;
+ if (strcmp(tac_login,"chap") == 0) {
+ tb.authen_type = TAC_PLUS_AUTHEN_TYPE_CHAP;
+ } else if (strcmp(tac_login,"login") == 0) {
+ tb.authen_type = TAC_PLUS_AUTHEN_TYPE_ASCII;
+ } else {
+ tb.authen_type = TAC_PLUS_AUTHEN_TYPE_PAP;
+ }
+ tb.service = tac_authen_service;
+ tb.user_len = user_len;
+ tb.port_len = port_len;
+ tb.rem_addr_len = rem_addr_len; /* may be e.g Caller-ID in future */
+ tb.data_len = token_len;
+
+ /* fill body length in header */
+ bodylength = sizeof(tb) + user_len
+ + port_len + rem_addr_len + token_len;
+
+ th->datalength = htonl(bodylength);
+
+ /* we can now write the header */
+ w = write(fd, th, TAC_PLUS_HDR_SIZE);
+ if (w < 0 || w < TAC_PLUS_HDR_SIZE) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: short write on header, wrote %d of %d: %m",\
+ __FUNCTION__, w, TAC_PLUS_HDR_SIZE))
+ ret = LIBTAC_STATUS_WRITE_ERR;
+ goto AuthenExit;
+ }
+
+ /* build the packet */
+ pkt = (u_char *) xcalloc(1, bodylength+10);
+
+ bcopy(&tb, pkt+pkt_len, sizeof(tb)); /* packet body beginning */
+ pkt_len += sizeof(tb);
+ bcopy(user, pkt+pkt_len, user_len); /* user */
+ pkt_len += user_len;
+ bcopy(tty, pkt+pkt_len, port_len); /* tty */
+ pkt_len += port_len;
+ bcopy(rem_addr, pkt+pkt_len, rem_addr_len); /* rem addr */
+ pkt_len += rem_addr_len;
+
+ bcopy(token, pkt+pkt_len, token_len); /* password */
+ pkt_len += token_len;
+
+ /* pkt_len == bodylength ? */
+ if (pkt_len != bodylength) {
+ TACSYSLOG((LOG_ERR, "%s: bodylength %d != pkt_len %d",\
+ __FUNCTION__, bodylength, pkt_len))
+ ret = LIBTAC_STATUS_ASSEMBLY_ERR;
+ goto AuthenExit;
+ }
+
+ /* encrypt the body */
+ _tac_crypt(pkt, th, bodylength);
+
+ w = write(fd, pkt, pkt_len);
+ if (w < 0 || w < pkt_len) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: short write on body, wrote %d of %d: %m",\
+ __FUNCTION__, w, pkt_len))
+ ret = LIBTAC_STATUS_WRITE_ERR;
+ }
+
+AuthenExit:
+ free(token);
+ free(pkt);
+ free(th);
+ TACDEBUG((LOG_DEBUG, "%s: exit status=%d", __FUNCTION__, ret))
+ return(ret);
+} /* tac_authen_send */
diff --git a/libtac/lib/author_r.c b/libtac/lib/author_r.c
index 3740e6c..8d52c0a 100644
--- a/libtac/lib/author_r.c
+++ b/libtac/lib/author_r.c
@@ -1,6 +1,6 @@
/* author_r.c - Reads authorization reply from the server.
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -29,166 +29,209 @@
2. message for the user
3. list of attributes returned by server
The attributes should be applied to service authorization
- is requested for, but actually the aren't. Attributes are
- discarded.
-*/
-void tac_author_read(int fd, struct areply *re) {
- HDR th;
- struct author_reply *tb = NULL;
- int len_from_header, r, len_from_body;
- char *pktp;
- char *msg = NULL;
-
- bzero(re, sizeof(struct areply));
-
- r=read(fd, &th, TAC_PLUS_HDR_SIZE);
- if(r < TAC_PLUS_HDR_SIZE) {
- syslog(LOG_ERR,
- "%s: short author header, %d of %d: %m", __FUNCTION__,
- r, TAC_PLUS_HDR_SIZE);
- re->msg = system_err_msg;
- re->status = AUTHOR_STATUS_ERROR;
- goto AuthorExit;
- }
-
- /* check header consistency */
- msg = _tac_check_header(&th, TAC_PLUS_AUTHOR);
- if(msg != NULL) {
- /* no need to process body if header is broken */
- re->msg = msg;
- re->status = AUTHOR_STATUS_ERROR;
- goto AuthorExit;
- }
-
- len_from_header=ntohl(th.datalength);
- tb=(struct author_reply *) xcalloc(1, len_from_header);
-
- /* read reply packet body */
- r=read(fd, tb, len_from_header);
- if(r < len_from_header) {
- syslog(LOG_ERR,
- "%s: short author body, %d of %d: %m", __FUNCTION__,
- r, len_from_header);
- re->msg = system_err_msg;
- re->status = AUTHOR_STATUS_ERROR;
- goto AuthorExit;
- }
-
- /* decrypt the body */
- _tac_crypt((u_char *) tb, &th, len_from_header);
-
- /* Convert network byte order to host byte order */
- tb->msg_len = ntohs(tb->msg_len);
- tb->data_len = ntohs(tb->data_len);
-
- /* check consistency of the reply body
- * len_from_header = declared in header
- * len_from_body = value computed from body fields
- */
- len_from_body = TAC_AUTHOR_REPLY_FIXED_FIELDS_SIZE +
- tb->msg_len + tb->data_len;
-
- pktp = (char *) tb + TAC_AUTHOR_REPLY_FIXED_FIELDS_SIZE;
-
- for(r = 0; r < tb->arg_cnt; r++) {
- len_from_body += sizeof(u_char); /* add arg length field's size*/
- len_from_body += *pktp; /* add arg length itself */
- pktp++;
- }
-
- if(len_from_header != len_from_body) {
- syslog(LOG_ERR,
- "%s: inconsistent author reply body, incorrect key?",
- __FUNCTION__);
- re->msg = system_err_msg;
- re->status = AUTHOR_STATUS_ERROR;
- goto AuthorExit;
- }
-
- /* packet seems to be consistent, prepare return messages */
- /* server message for user */
- if(tb->msg_len) {
- char *msg = (char *) xcalloc(1, tb->msg_len+1);
- bcopy((u_char *) tb+TAC_AUTHOR_REPLY_FIXED_FIELDS_SIZE
- + (tb->arg_cnt)*sizeof(u_char),
- msg, tb->msg_len);
- re->msg = msg;
- }
-
- /* server message to syslog */
- if(tb->data_len) {
- char *smsg=(char *) xcalloc(1, tb->data_len+1);
- bcopy((u_char *) tb + TAC_AUTHOR_REPLY_FIXED_FIELDS_SIZE
- + (tb->arg_cnt)*sizeof(u_char)
- + tb->msg_len, smsg,
- tb->data_len);
- syslog(LOG_ERR, "%s: author failed: %s", __FUNCTION__,smsg);
- free(smsg);
- }
-
- /* prepare status */
- switch(tb->status) {
- /* success conditions */
- /* XXX support optional vs mandatory arguments */
- case AUTHOR_STATUS_PASS_ADD:
- case AUTHOR_STATUS_PASS_REPL:
- {
- char *argp;
-
- if(!re->msg) re->msg=author_ok_msg;
- re->status=tb->status;
-
- /* add attributes received to attribute list returned to
- the client */
- pktp = (char *) tb + TAC_AUTHOR_REPLY_FIXED_FIELDS_SIZE;
- argp = pktp + (tb->arg_cnt * sizeof(u_char)) + tb->msg_len +
- tb->data_len;
- /* argp points to current argument string
- pktp holds current argument length */
- for(r=0; r < tb->arg_cnt; r++) {
- char buff[256];
- char *sep;
- char *value;
-
- bcopy(argp, buff, *pktp);
- buff[(int)*pktp] = '\0';
- sep=index(buff, '=');
- if(sep == NULL)
- sep=index(buff, '*');
- if(sep == NULL)
- syslog(LOG_WARNING, "AUTHOR_STATUS_PASS_REPL: attribute contains no separator: %s", buff);
- *sep = '\0';
- value = ++sep;
- /* now buff points to attribute name,
- value to the attribute value */
- tac_add_attrib(&re->attr, buff, value);
-
- argp += *pktp;
- pktp++;
- }
- }
-
- break;
-
- /* authorization failure conditions */
- /* failing to follow is allowed by RFC, page 23 */
- case AUTHOR_STATUS_FOLLOW:
- case AUTHOR_STATUS_FAIL:
- if(!re->msg) re->msg=author_fail_msg;
- re->status=AUTHOR_STATUS_FAIL;
- break;
-
- /* error conditions */
- case AUTHOR_STATUS_ERROR:
- default:
- if(!re->msg) re->msg=author_err_msg;
- re->status=AUTHOR_STATUS_ERROR;
- }
+ is requested for.
+ *
+ * return value:
+ * < 0 : error status code, see LIBTAC_STATUS_...
+ * LIBTAC_STATUS_READ_TIMEOUT
+ * LIBTAC_STATUS_SHORT_HDR
+ * LIBTAC_STATUS_SHORT_BODY
+ * LIBTAC_STATUS_PROTOCOL_ERR
+ * >= 0 : server response, see TAC_PLUS_AUTHOR_STATUS_...
+ */
+int tac_author_read(int fd, struct areply *re) {
+ HDR th;
+ struct author_reply *tb = NULL;
+ int len_from_header, r, len_from_body;
+ u_char *pktp = NULL;
+ char *msg = NULL;
+ int timeleft;
+ re->msg = NULL;
+
+ bzero(re, sizeof(struct areply));
+ if (tac_readtimeout_enable &&
+ tac_read_wait(fd,tac_timeout*1000,TAC_PLUS_HDR_SIZE,&timeleft) < 0 ) {
+
+ TACSYSLOG((LOG_ERR,\
+ "%s: reply timeout after %d secs", __FUNCTION__, tac_timeout))
+ re->msg = xstrdup(author_syserr_msg);
+ re->status = LIBTAC_STATUS_READ_TIMEOUT;
+ goto AuthorExit;
+ }
+
+ r = read(fd, &th, TAC_PLUS_HDR_SIZE);
+ if(r < TAC_PLUS_HDR_SIZE) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: short reply header, read %d of %d: %m", __FUNCTION__,\
+ r, TAC_PLUS_HDR_SIZE))
+ re->msg = xstrdup(author_syserr_msg);
+ re->status = LIBTAC_STATUS_SHORT_HDR;
+ goto AuthorExit;
+ }
+
+ /* check header consistency */
+ msg = _tac_check_header(&th, TAC_PLUS_AUTHOR);
+ if (msg != NULL) {
+ /* no need to process body if header is broken */
+ re->msg = xstrdup(msg);
+ re->status = LIBTAC_STATUS_PROTOCOL_ERR;
+ goto AuthorExit;
+ }
+
+ len_from_header = ntohl(th.datalength);
+ tb = (struct author_reply *) xcalloc(1, len_from_header);
+
+ /* read reply packet body */
+ if (tac_readtimeout_enable &&
+ tac_read_wait(fd,timeleft,len_from_header,NULL) < 0 ) {
+
+ TACSYSLOG((LOG_ERR,\
+ "%s: reply timeout after %d secs", __FUNCTION__, tac_timeout))
+ re->msg = xstrdup(author_syserr_msg);
+ re->status = LIBTAC_STATUS_READ_TIMEOUT;
+ goto AuthorExit;
+ }
+ r = read(fd, tb, len_from_header);
+ if (r < len_from_header) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: short reply body, read %d of %d: %m", __FUNCTION__,\
+ r, len_from_header))
+ re->msg = xstrdup(author_syserr_msg);
+ re->status = LIBTAC_STATUS_SHORT_BODY;
+ goto AuthorExit;
+ }
+
+ /* decrypt the body */
+ _tac_crypt((u_char *) tb, &th, len_from_header);
+
+ /* Convert network byte order to host byte order */
+ tb->msg_len = ntohs(tb->msg_len);
+ tb->data_len = ntohs(tb->data_len);
+
+ /* check consistency of the reply body
+ * len_from_header = declared in header
+ * len_from_body = value computed from body fields
+ */
+ len_from_body = TAC_AUTHOR_REPLY_FIXED_FIELDS_SIZE +
+ tb->msg_len + tb->data_len;
+
+ pktp = (u_char *) tb + TAC_AUTHOR_REPLY_FIXED_FIELDS_SIZE;
+
+ for (r = 0; r < tb->arg_cnt; r++) {
+ len_from_body += sizeof(u_char); /* add arg length field's size*/
+ len_from_body += *pktp; /* add arg length itself */
+ pktp++;
+ }
+
+ if(len_from_header != len_from_body) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: inconsistent reply body, incorrect key?",\
+ __FUNCTION__))
+ re->msg = xstrdup(protocol_err_msg);
+ re->status = LIBTAC_STATUS_PROTOCOL_ERR;
+ goto AuthorExit;
+ }
+
+ /* packet seems to be consistent, prepare return messages */
+ /* server message for user */
+ if(tb->msg_len) {
+ char *msg = (char *) xcalloc(1, tb->msg_len+1);
+ bcopy((u_char *) tb+TAC_AUTHOR_REPLY_FIXED_FIELDS_SIZE
+ + (tb->arg_cnt)*sizeof(u_char),
+ msg, tb->msg_len);
+ msg[(int) tb->msg_len] = '\0';
+ re->msg = msg; /* freed by caller */
+ }
+
+ /* server message to syslog */
+ if(tb->data_len) {
+ char *smsg=(char *) xcalloc(1, tb->data_len+1);
+ bcopy((u_char *) tb + TAC_AUTHOR_REPLY_FIXED_FIELDS_SIZE
+ + (tb->arg_cnt)*sizeof(u_char)
+ + tb->msg_len, smsg,
+ tb->data_len);
+ smsg[(int) tb->data_len] = '\0';
+ TACSYSLOG((LOG_ERR, "%s: reply message: %s", __FUNCTION__,smsg))
+ free(smsg);
+ }
+
+ /* prepare status */
+ switch(tb->status) {
+ /* success conditions */
+ /* XXX support optional vs mandatory arguments */
+ case TAC_PLUS_AUTHOR_STATUS_PASS_REPL:
+ tac_free_attrib(&re->attr);
+
+ case TAC_PLUS_AUTHOR_STATUS_PASS_ADD:
+ {
+ u_char *argp;
+
+ if(!re->msg) re->msg=xstrdup(author_ok_msg);
+ re->status=tb->status;
+
+ /* add attributes received to attribute list returned to
+ the client */
+ pktp = (u_char *) tb + TAC_AUTHOR_REPLY_FIXED_FIELDS_SIZE;
+ argp = pktp + (tb->arg_cnt * sizeof(u_char)) + tb->msg_len +
+ tb->data_len;
+ /* argp points to current argument string
+ pktp points to current argument length */
+ for(r=0; r < tb->arg_cnt; r++) {
+ char buff[256];
+ char *sep;
+ char *value;
+ char sepchar = '=';
+
+ bcopy(argp, buff, (int)*pktp);
+ buff[(int)*pktp] = '\0';
+ sep = strchr(buff, '=');
+ if ( sep == NULL ) {
+ sep = strchr(buff, '*');
+ }
+ if(sep == NULL) {
+ TACSYSLOG((LOG_WARNING,\
+ "AUTHOR_STATUS_PASS_ADD/REPL: av pair does not contain a separator: %s",\
+ buff))
+ /* now buff points to attribute name, make value ""
+ treat as "name=" */
+ value = "";
+ } else {
+ sepchar = *sep;
+ *sep = '\0';
+ value = ++sep;
+ /* now buff points to attribute name,
+ value to the attribute value */
+ }
+ tac_add_attrib_pair(&re->attr, buff, sepchar, value);
+ argp += *pktp;
+ pktp++;
+ }
+ }
+
+ goto AuthorExit;
+ break;
+ }
+
+ TACDEBUG((LOG_DEBUG, "%s: authorization failed, server reply status=%d",\
+ __FUNCTION__, tb->status))
+ switch (tb->status) {
+ /* authorization failure conditions */
+ /* failing to follow is allowed by RFC, page 23 */
+ case TAC_PLUS_AUTHOR_STATUS_FOLLOW:
+ case TAC_PLUS_AUTHOR_STATUS_FAIL:
+ if(!re->msg) re->msg = xstrdup(author_fail_msg);
+ re->status=TAC_PLUS_AUTHOR_STATUS_FAIL;
+ break;
+ /* error conditions */
+ case TAC_PLUS_AUTHOR_STATUS_ERROR:
+ default:
+ if(!re->msg) re->msg = xstrdup(author_err_msg);
+ re->status=TAC_PLUS_AUTHOR_STATUS_ERROR;
+ }
AuthorExit:
-
- free(tb);
- TACDEBUG((LOG_DEBUG, "%s: server replied '%s'", __FUNCTION__, \
- re->msg))
-
+ free(tb);
+ TACDEBUG((LOG_DEBUG, "%s: exit status=%d, status message \"%s\"",\
+ __FUNCTION__, re->status, re->msg != NULL ? re->msg : ""))
+ return(re->status);
}
diff --git a/libtac/lib/author_s.c b/libtac/lib/author_s.c
index 0bf6518..53b7c89 100644
--- a/libtac/lib/author_s.c
+++ b/libtac/lib/author_s.c
@@ -1,6 +1,6 @@
/* author_s.c - Send authorization request to the server.
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -25,128 +25,140 @@
/* Send authorization request to the server, along with attributes
specified in attribute list prepared with tac_add_attrib.
-*/
-int tac_author_send(int fd, const char *user, char *tty, struct tac_attrib *attr) {
- HDR *th;
- struct author tb;
- u_char user_len, port_len;
- struct tac_attrib *a;
- int i = 0; /* attributes count */
- int pkt_len = 0; /* current packet length */
- int pktl = 0; /* temporary storage for previous pkt_len values */
- int w; /* write() return value */
- u_char *pkt; /* packet building pointer */
- /* u_char *pktp; */ /* obsolete */
- int ret = 0;
-
- th=_tac_req_header(TAC_PLUS_AUTHOR);
-
- /* set header options */
- th->version=TAC_PLUS_VER_0;
- th->encryption=tac_encryption ? TAC_PLUS_ENCRYPTED : TAC_PLUS_CLEAR;
-
- TACDEBUG((LOG_DEBUG, "%s: user '%s', tty '%s', encrypt: %s", \
- __FUNCTION__, user, \
- tty, tac_encryption ? "yes" : "no"))
-
- user_len=(u_char) strlen(user);
- port_len=(u_char) strlen(tty);
-
- tb.authen_method=AUTHEN_METH_TACACSPLUS;
- tb.priv_lvl=TAC_PLUS_PRIV_LVL_MIN;
- if(strcmp(tac_login,"chap") == 0) {
- tb.authen_type=TAC_PLUS_AUTHEN_TYPE_CHAP;
- } else if(strcmp(tac_login,"login") == 0) {
- tb.authen_type=TAC_PLUS_AUTHEN_TYPE_ASCII;
- } else {
- tb.authen_type=TAC_PLUS_AUTHEN_TYPE_PAP;
- }
- tb.service=TAC_PLUS_AUTHEN_SVC_PPP;
- tb.user_len=user_len;
- tb.port_len=port_len;
- tb.rem_addr_len=0;
-
- /* allocate packet */
- pkt=(u_char *) xcalloc(1, TAC_AUTHOR_REQ_FIXED_FIELDS_SIZE);
- pkt_len=sizeof(tb);
-
- /* fill attribute length fields */
- a = attr;
- while(a) {
-
- pktl = pkt_len;
- pkt_len += sizeof(a->attr_len);
- pkt = xrealloc(pkt, pkt_len);
-
- /* bad method: realloc() is allowed to return different pointer
- with each call
- pktp=pkt + pkt_len;
- pkt_len += sizeof(a->attr_len);
- pkt = xrealloc(pkt, pkt_len);
- */
-
- bcopy(&a->attr_len, pkt + pktl, sizeof(a->attr_len));
- i++;
-
- a = a->next;
- }
-
- /* fill the arg count field and add the fixed fields to packet */
- tb.arg_cnt = i;
- bcopy(&tb, pkt, TAC_AUTHOR_REQ_FIXED_FIELDS_SIZE);
+ *
+ * return value:
+ * 0 : success
+ * < 0 : error status code, see LIBTAC_STATUS_...
+ * LIBTAC_STATUS_WRITE_ERR
+ * LIBTAC_STATUS_WRITE_TIMEOUT (pending impl)
+ * LIBTAC_STATUS_ASSEMBLY_ERR (pending impl)
+ */
+int tac_author_send(int fd, const char *user, char *tty, char *rem_addr,
+ struct tac_attrib *attr) {
+
+ HDR *th;
+ struct author tb;
+ u_char user_len, port_len, rem_addr_len;
+ struct tac_attrib *a;
+ int i = 0; /* attributes count */
+ int pkt_len = 0; /* current packet length */
+ int pktl = 0; /* temporary storage for previous pkt_len values */
+ int w; /* write() return value */
+ u_char *pkt = NULL; /* packet building pointer */
+ /* u_char *pktp; */ /* obsolete */
+ int ret = 0;
+
+ th=_tac_req_header(TAC_PLUS_AUTHOR, 0);
+
+ /* set header options */
+ th->version=TAC_PLUS_VER_0;
+ th->encryption=tac_encryption ? TAC_PLUS_ENCRYPTED_FLAG : TAC_PLUS_UNENCRYPTED_FLAG;
+
+ TACDEBUG((LOG_DEBUG, "%s: user '%s', tty '%s', rem_addr '%s', encrypt: %s", \
+ __FUNCTION__, user, \
+ tty, rem_addr, tac_encryption ? "yes" : "no"))
+
+ user_len = (u_char) strlen(user);
+ port_len = (u_char) strlen(tty);
+ rem_addr_len = (u_char) strlen(rem_addr);
+
+ tb.authen_method = tac_authen_method;
+ tb.priv_lvl = tac_priv_lvl;
+ if (strcmp(tac_login,"chap") == 0) {
+ tb.authen_type = TAC_PLUS_AUTHEN_TYPE_CHAP;
+ } else if (strcmp(tac_login,"login") == 0) {
+ tb.authen_type = TAC_PLUS_AUTHEN_TYPE_ASCII;
+ } else {
+ tb.authen_type = TAC_PLUS_AUTHEN_TYPE_PAP;
+ }
+ tb.service = tac_authen_service;
+ tb.user_len = user_len;
+ tb.port_len = port_len;
+ tb.rem_addr_len = rem_addr_len;
+
+ /* allocate packet */
+ pkt = (u_char *) xcalloc(1, TAC_AUTHOR_REQ_FIXED_FIELDS_SIZE);
+ pkt_len = sizeof(tb);
+
+ /* fill attribute length fields */
+ a = attr;
+ while (a) {
+ pktl = pkt_len;
+ pkt_len += sizeof(a->attr_len);
+ pkt = (u_char*) xrealloc(pkt, pkt_len);
+
+ /* bad method: realloc() is allowed to return different pointer
+ with each call
+ pktp=pkt + pkt_len;
+ pkt_len += sizeof(a->attr_len);
+ pkt = xrealloc(pkt, pkt_len);
+ */
+
+ bcopy(&a->attr_len, pkt + pktl, sizeof(a->attr_len));
+ i++;
+
+ a = a->next;
+ }
+
+ /* fill the arg count field and add the fixed fields to packet */
+ tb.arg_cnt = i;
+ bcopy(&tb, pkt, TAC_AUTHOR_REQ_FIXED_FIELDS_SIZE);
/*
#define PUTATTR(data, len) \
- pktp = pkt + pkt_len; \
- pkt_len += len; \
- pkt = xrealloc(pkt, pkt_len); \
- bcopy(data, pktp, len);
+ pktp = pkt + pkt_len; \
+ pkt_len += len; \
+ pkt = xrealloc(pkt, pkt_len); \
+ bcopy(data, pktp, len);
*/
#define PUTATTR(data, len) \
- pktl = pkt_len; \
- pkt_len += len; \
- pkt = xrealloc(pkt, pkt_len); \
- bcopy(data, pkt + pktl, len);
-
- /* fill user and port fields */
- PUTATTR(user, user_len)
- PUTATTR(tty, port_len)
-
- /* fill attributes */
- a = attr;
- while(a) {
- PUTATTR(a->attr, a->attr_len)
-
- a = a->next;
- }
-
- /* finished building packet, fill len_from_header in header */
- th->datalength = htonl(pkt_len);
-
- /* write header */
- w=write(fd, th, TAC_PLUS_HDR_SIZE);
-
- if(w < TAC_PLUS_HDR_SIZE) {
- syslog(LOG_ERR, "%s: author hdr send failed: wrote %d of %d",
- __FUNCTION__, w,
- TAC_PLUS_HDR_SIZE);
- ret = -1;
- }
-
- /* encrypt packet body */
- _tac_crypt(pkt, th, pkt_len);
-
- /* write body */
- w=write(fd, pkt, pkt_len);
- if(w < pkt_len) {
- syslog(LOG_ERR, "%s: author body send failed: wrote %d of %d",
- __FUNCTION__, w,
- pkt_len);
- ret = -1;
- }
-
- free(pkt);
- free(th);
-
- return(ret);
+ pktl = pkt_len; \
+ pkt_len += len; \
+ pkt = (u_char*) xrealloc(pkt, pkt_len); \
+ bcopy(data, pkt + pktl, len);
+
+ /* fill user and port fields */
+ PUTATTR(user, user_len)
+ PUTATTR(tty, port_len)
+ PUTATTR(rem_addr, rem_addr_len)
+
+ /* fill attributes */
+ a = attr;
+ while (a) {
+ PUTATTR(a->attr, a->attr_len)
+
+ a = a->next;
+ }
+
+ /* finished building packet, fill len_from_header in header */
+ th->datalength = htonl(pkt_len);
+
+ /* write header */
+ w = write(fd, th, TAC_PLUS_HDR_SIZE);
+
+ if (w < TAC_PLUS_HDR_SIZE) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: short write on header, wrote %d of %d: %m",\
+ __FUNCTION__, w, TAC_PLUS_HDR_SIZE))
+ ret = LIBTAC_STATUS_WRITE_ERR;
+ goto AuthorExit;
+ }
+
+ /* encrypt packet body */
+ _tac_crypt(pkt, th, pkt_len);
+
+ /* write body */
+ w = write(fd, pkt, pkt_len);
+ if (w < pkt_len) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: short write on body, wrote %d of %d: %m",\
+ __FUNCTION__, w, pkt_len))
+ ret = LIBTAC_STATUS_WRITE_ERR;
+ }
+
+AuthorExit:
+ free(pkt);
+ free(th);
+ TACDEBUG((LOG_DEBUG, "%s: exit status=%d", __FUNCTION__, ret))
+ return(ret);
}
diff --git a/libtac/lib/connect.c b/libtac/lib/connect.c
index c65edf8..bbbb270 100644
--- a/libtac/lib/connect.c
+++ b/libtac/lib/connect.c
@@ -1,6 +1,6 @@
/* connect.c - Open connection to server.
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@
#include <errno.h>
#ifdef _AIX
- #include <sys/socket.h>
+ #include <sys/socket.h>
#endif
#include "tacplus.h"
@@ -38,126 +38,161 @@ int tac_timeout = 5;
/* Returns file descriptor of open connection
to the first available server from list passed
in server table.
-*/
+
+ * return value:
+ * >= 0 : valid fd
+ * < 0 : error status code, see LIBTAC_STATUS_...
+ */
int tac_connect(struct addrinfo **server, char **key, int servers) {
- int tries = 0;
- int fd, flags, retval;
- fd_set readfds, writefds;
- struct timeval tv;
- socklen_t len;
- struct sockaddr_storage addr;
-
- if(!servers) {
- syslog(LOG_ERR, "%s: no TACACS+ servers defined", __FUNCTION__);
- return(-1);
- }
-
- while(tries < servers) {
- if((fd=socket(server[tries]->ai_family, server[tries]->ai_socktype, server[tries]->ai_protocol)) == -1) {
- syslog(LOG_WARNING,
- "%s: socket creation error", __FUNCTION__);
- tries++;
- continue;
- }
-
- /* put socket in non blocking mode for timeout support */
- flags = fcntl(fd, F_GETFL, 0);
- if(fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
- syslog(LOG_WARNING, "%s: cannot set socket non blocking",
- __FUNCTION__);
- tries++;
- continue;
- }
-
- retval = connect(fd, server[tries]->ai_addr, server[tries]->ai_addrlen);
- if((retval == -1) && (errno != EINPROGRESS)) {
- syslog(LOG_WARNING,
- "%s: connection to %s failed: %m", __FUNCTION__,
- tac_ntop(server[tries]->ai_addr, server[tries]->ai_addrlen));
- if(fcntl(fd, F_SETFL, flags)) {
- syslog(LOG_WARNING, "%s: cannot restore socket flags",
- __FUNCTION__);
- }
- tries++;
- continue;
- }
-
- /* set fds for select */
- FD_ZERO(&readfds);
- FD_SET(fd, &readfds);
- writefds = readfds;
-
- /* set timeout seconds */
- tv.tv_sec = tac_timeout;
- tv.tv_usec = 0;
-
- /* check if socket is ready for read and write */
- if(select(fd+1, &readfds, &writefds, NULL, &tv) < 1) {
- syslog(LOG_WARNING,
- "%s: connection failed with %s : %m", __FUNCTION__,
- tac_ntop(server[tries]->ai_addr, server[tries]->ai_addrlen));
- if(fcntl(fd, F_SETFL, flags)) {
- syslog(LOG_WARNING, "%s: cannot restore socket flags",
- __FUNCTION__);
- }
- tries++;
- continue;
- } else {
- /* check with getpeername if we have a valid connection */
- len = sizeof addr;
- if(getpeername(fd, (struct sockaddr*)&addr, &len) == -1) {
- syslog(LOG_WARNING,
- "%s: connection failed with %s : %m", __FUNCTION__,
- tac_ntop(server[tries]->ai_addr, server[tries]->ai_addrlen));
- if(fcntl(fd, F_SETFL, flags)) {
- syslog(LOG_WARNING, "%s: cannot restore socket flags",
- __FUNCTION__);
- }
- tries++;
- continue;
- }
- }
-
- /* connected ok */
- if(fcntl(fd, F_SETFL, flags)) {
- syslog(LOG_WARNING, "%s: cannot restore socket flags",
- __FUNCTION__);
- }
- TACDEBUG((LOG_DEBUG, "%s: connected to %s", __FUNCTION__, \
- tac_ntop(server[tries]->ai_addr, server[tries]->ai_addrlen)));
-
- /* set current tac_secret */
- tac_secret = key[tries];
- return(fd);
- }
-
- /* all attempts failed */
- return(-1);
+ int tries;
+ int fd=-1;
+
+ if(servers == 0 || server == NULL) {
+ TACSYSLOG((LOG_ERR, "%s: no TACACS+ servers defined", __FUNCTION__))
+ } else {
+ for ( tries = 0; tries < servers; tries++ ) {
+ if((fd=tac_connect_single(server[tries], key[tries])) >= 0 ) {
+ /* tac_secret was set in tac_connect_single on success */
+ break;
+ }
+ }
+ }
+
+ /* all attempts failed if fd is still < 0 */
+ TACDEBUG((LOG_DEBUG, "%s: exit status=%d",__FUNCTION__, fd))
+ return(fd);
} /* tac_connect */
+/* return value:
+ * >= 0 : valid fd
+ * < 0 : error status code, see LIBTAC_STATUS_...
+ */
int tac_connect_single(struct addrinfo *server, char *key) {
- struct addrinfo *tmpaddr[1];
- tmpaddr[0] = server;
- char *tmpkey[1];
- tmpkey[0] = key;
- return(tac_connect(tmpaddr, tmpkey, 1));
+ int retval = LIBTAC_STATUS_CONN_ERR; /* default retval */
+ int fd = -1;
+ int flags, rc;
+ fd_set readfds, writefds;
+ struct timeval tv;
+ socklen_t len;
+ struct sockaddr_storage addr;
+ char *ip = NULL;
+
+ if(server == NULL) {
+ TACSYSLOG((LOG_ERR, "%s: no TACACS+ server defined", __FUNCTION__))
+ return LIBTAC_STATUS_CONN_ERR;
+ }
+
+ /* format server address into a string for use in messages */
+ ip = tac_ntop(server->ai_addr, 0);
+
+ if((fd=socket(server->ai_family, server->ai_socktype, server->ai_protocol)) < 0) {
+ TACSYSLOG((LOG_ERR,"%s: socket creation error", __FUNCTION__))
+ return LIBTAC_STATUS_CONN_ERR;
+ }
+
+ /* get flags for restoration later */
+ flags = fcntl(fd, F_GETFL, 0);
+
+ /* put socket in non blocking mode for timeout support */
+ if( fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ) {
+ TACSYSLOG((LOG_ERR, "%s: cannot set socket non blocking",\
+ __FUNCTION__))
+ return LIBTAC_STATUS_CONN_ERR;
+ }
+
+ rc = connect(fd, server->ai_addr, server->ai_addrlen);
+ if((rc == -1) && (errno != EINPROGRESS)) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: connection to %s failed: %m", __FUNCTION__, ip))
+ return LIBTAC_STATUS_CONN_ERR;
+ }
+
+ /* set fds for select */
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_SET(fd, &readfds);
+ FD_SET(fd, &writefds);
+
+ /* set timeout seconds */
+ tv.tv_sec = tac_timeout;
+ tv.tv_usec = 0;
+
+ /* check if socket is ready for read and write */
+ rc = select(fd+1, &readfds, &writefds, NULL, &tv);
+
+ /* timeout */
+ if ( rc == 0 ) {
+ return LIBTAC_STATUS_CONN_TIMEOUT;
+ }
+
+ /* some other error or interrupt before timeout */
+ if ( rc < 0 ) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: connection failed with %s: %m", __FUNCTION__, ip))
+ return LIBTAC_STATUS_CONN_ERR;
+ }
+
+ /* check with getpeername if we have a valid connection */
+ len = sizeof addr;
+ if(getpeername(fd, (struct sockaddr*)&addr, &len) == -1) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: connection failed with %s: %m", __FUNCTION__, ip))
+ return LIBTAC_STATUS_CONN_ERR;
+ }
+
+ /* restore flags on socket - flags was set only when fd >= 0 */
+ if(fcntl(fd, F_SETFL, flags) == -1) {
+ TACSYSLOG((LOG_ERR, "%s: cannot restore socket flags: %m",\
+ __FUNCTION__))
+ return LIBTAC_STATUS_CONN_ERR;
+ }
+
+ /* connected ok */
+ TACDEBUG((LOG_DEBUG, "%s: connected to %s", __FUNCTION__, ip))
+ retval = fd;
+
+ /* set current tac_secret */
+ tac_secret = key;
+
+ free(ip);
+
+ /* if valid fd, but error experienced after open, close fd */
+ if ( fd >= 0 && retval < 0 ) {
+ close(fd);
+ }
+
+ TACDEBUG((LOG_DEBUG, "%s: exit status=%d (fd=%d)",\
+ __FUNCTION__, retval < 0 ? retval:0, fd))
+ return(retval);
} /* tac_connect_single */
-char *tac_ntop(const struct sockaddr *sa, size_t ai_addrlen) {
- char *str = (char *) xcalloc(1, ai_addrlen);
- switch(sa->sa_family) {
- case AF_INET:
- inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr),
- str, ai_addrlen);
- break;
- case AF_INET6:
- inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr),
- str, ai_addrlen);
- break;
- default:
- strncpy(str, "Unknown AF", ai_addrlen);
- }
- return str;
+/* return value:
+ * ptr to char* with format IP address
+ * must be freed by caller
+ */
+char *tac_ntop(const struct sockaddr *sa, size_t unused) {
+ char portstr[7];
+ char *str = (char *) xcalloc(1, INET6_ADDRSTRLEN+sizeof(portstr));
+
+ switch(sa->sa_family) {
+ case AF_INET:
+ inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr),
+ str, INET_ADDRSTRLEN);
+ snprintf(portstr, sizeof(portstr), ":%hu",
+ htons(((struct sockaddr_in *)sa)->sin_port));
+ strncat(str, portstr, sizeof(portstr));
+ break;
+ case AF_INET6:
+ inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr),
+ str, INET6_ADDRSTRLEN);
+ snprintf(portstr, sizeof(portstr), ":%hu",
+ htons(((struct sockaddr_in6 *)sa)->sin6_port));
+ strncat(str, portstr, sizeof(portstr));
+ break;
+ default:
+ strncpy(str, "Unknown AF", INET6_ADDRSTRLEN);
+ }
+ return str;
} /* tac_ntop */
diff --git a/libtac/lib/cont_s.c b/libtac/lib/cont_s.c
index 17894cf..a438a63 100644
--- a/libtac/lib/cont_s.c
+++ b/libtac/lib/cont_s.c
@@ -24,69 +24,83 @@
/* this function sends a continue packet do TACACS+ server, asking
* for validation of given password
+ *
+ * return value:
+ * 0 : success
+ * < 0 : error status code, see LIBTAC_STATUS_...
+ * LIBTAC_STATUS_WRITE_ERR
+ * LIBTAC_STATUS_WRITE_TIMEOUT (pending impl)
+ * LIBTAC_STATUS_ASSEMBLY_ERR
*/
-int tac_cont_send(int fd, char *pass)
-{
- HDR *th; /* TACACS+ packet header */
- struct authen_cont tb; /* continue body */
- int pass_len, bodylength, w;
- int pkt_len=0;
- int ret=0;
- u_char *pkt;
-
- th=_tac_req_header(TAC_PLUS_AUTHEN);
-
- /* set some header options */
- th->version=TAC_PLUS_VER_0;
- th->seq_no=3; /* 1 = request, 2 = reply, 3 = continue, 4 = reply */
- th->encryption=tac_encryption ? TAC_PLUS_ENCRYPTED : TAC_PLUS_CLEAR;
-
- /* get size of submitted data */
- pass_len=strlen(pass);
-
- /* fill the body of message */
- tb.user_msg_len=htons(pass_len);
- tb.user_data_len=tb.flags=0;
-
- /* fill body length in header */
- bodylength=TAC_AUTHEN_CONT_FIXED_FIELDS_SIZE+0+pass_len;
-
- th->datalength=htonl(bodylength);
-
- /* we can now write the header */
- w=write(fd, th, TAC_PLUS_HDR_SIZE);
- if(w < 0 || w < TAC_PLUS_HDR_SIZE) {
- syslog(LOG_ERR, "%s: short write on header: wrote %d of %d: %m",
- __FUNCTION__, w, TAC_PLUS_HDR_SIZE);
- ret=-1;
- }
-
- /* build the packet */
- pkt=(u_char *) xcalloc(1, bodylength);
-
- bcopy(&tb, pkt+pkt_len, TAC_AUTHEN_CONT_FIXED_FIELDS_SIZE); /* packet body beginning */
- pkt_len+=TAC_AUTHEN_CONT_FIXED_FIELDS_SIZE;
- bcopy(pass, pkt+pkt_len, pass_len); /* password */
- pkt_len+=pass_len;
-
- /* pkt_len == bodylength ? */
- if(pkt_len != bodylength) {
- syslog(LOG_ERR, "%s: bodylength %d != pkt_len %d", __FUNCTION__, bodylength, pkt_len);
- ret=-1;
- }
-
- /* encrypt the body */
- _tac_crypt(pkt, th, bodylength);
-
- w=write(fd, pkt, pkt_len);
- if(w < 0 || w < pkt_len) {
- syslog(LOG_ERR, "%s: short write on body: wrote %d of %d: %m",
- __FUNCTION__, w, pkt_len);
- ret=-1;
- }
-
- free(pkt);
- free(th);
-
- return(ret);
+int tac_cont_send(int fd, char *pass) {
+ HDR *th; /* TACACS+ packet header */
+ struct authen_cont tb; /* continue body */
+ int pass_len, bodylength, w;
+ int pkt_len = 0;
+ int ret = 0;
+ u_char *pkt = NULL;
+
+ th = _tac_req_header(TAC_PLUS_AUTHEN, 1);
+
+ /* set some header options */
+ th->version = TAC_PLUS_VER_0;
+ th->seq_no = 3; /* 1 = request, 2 = reply, 3 = continue, 4 = reply */
+ th->encryption = tac_encryption ? TAC_PLUS_ENCRYPTED_FLAG : TAC_PLUS_UNENCRYPTED_FLAG;
+
+ /* get size of submitted data */
+ pass_len = strlen(pass);
+
+ /* fill the body of message */
+ tb.user_msg_len = htons(pass_len);
+ tb.user_data_len = tb.flags = 0;
+
+ /* fill body length in header */
+ bodylength = TAC_AUTHEN_CONT_FIXED_FIELDS_SIZE+0+pass_len;
+
+ th->datalength = htonl(bodylength);
+
+ /* we can now write the header */
+ w = write(fd, th, TAC_PLUS_HDR_SIZE);
+ if (w < 0 || w < TAC_PLUS_HDR_SIZE) {
+ TACSYSLOG((LOG_ERR, "%s: short write on header, wrote %d of %d: %m",\
+ __FUNCTION__, w, TAC_PLUS_HDR_SIZE))
+ ret=LIBTAC_STATUS_WRITE_ERR;
+ goto ContExit;
+ }
+
+ /* build the packet */
+ pkt = (u_char *) xcalloc(1, bodylength);
+
+ bcopy(&tb, pkt+pkt_len, TAC_AUTHEN_CONT_FIXED_FIELDS_SIZE); /* packet body beginning */
+ pkt_len += TAC_AUTHEN_CONT_FIXED_FIELDS_SIZE;
+ bcopy(pass, pkt+pkt_len, pass_len); /* password */
+ pkt_len += pass_len;
+
+ /* pkt_len == bodylength ? */
+ if (pkt_len != bodylength) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: bodylength %d != pkt_len %d",\
+ __FUNCTION__, bodylength, pkt_len))
+ ret=LIBTAC_STATUS_ASSEMBLY_ERR;
+ goto ContExit;
+ }
+
+ /* encrypt the body */
+ _tac_crypt(pkt, th, bodylength);
+
+ w = write(fd, pkt, pkt_len);
+ if (w < 0 || w < pkt_len) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: short write on body, wrote %d of %d: %m",\
+ __FUNCTION__, w, pkt_len))
+ ret=LIBTAC_STATUS_WRITE_ERR;
+ }
+
+ContExit:
+
+ free(pkt);
+ free(th);
+
+ TACDEBUG((LOG_DEBUG, "%s: exit status=%d", __FUNCTION__, ret))
+ return(ret);
} /* tac_cont_send */
diff --git a/libtac/lib/crypt.c b/libtac/lib/crypt.c
index ae726fc..645cf8e 100644
--- a/libtac/lib/crypt.c
+++ b/libtac/lib/crypt.c
@@ -1,6 +1,6 @@
/* crypt.c - TACACS+ encryption related functions
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -28,80 +28,78 @@
Use data from packet header and secret, which
should be a global variable */
u_char *_tac_md5_pad(int len, HDR *hdr) {
- int n, i, bufsize;
- int bp=0; /* buffer pointer */
- int pp=0; /* pad pointer */
- u_char *pad;
- u_char *buf;
- MD5_CTX mdcontext;
+ int n, i, bufsize;
+ int bp = 0; /* buffer pointer */
+ int pp = 0; /* pad pointer */
+ u_char *pad;
+ u_char *buf;
+ MD5_CTX mdcontext;
- /* make pseudo pad */
- n=(int)(len/16)+1; /* number of MD5 runs */
- bufsize=sizeof(hdr->session_id) + strlen(tac_secret) + sizeof(hdr->version)
- + sizeof(hdr->seq_no) + MD5_LEN + 10;
- buf= (u_char *) xcalloc(1, bufsize);
- pad= (u_char *) xcalloc(n, MD5_LEN);
+ /* make pseudo pad */
+ n = (int)(len/16)+1; /* number of MD5 runs */
+ bufsize = sizeof(hdr->session_id) + strlen(tac_secret) + sizeof(hdr->version)
+ + sizeof(hdr->seq_no) + MD5_LEN + 10;
+ buf = (u_char *) xcalloc(1, bufsize);
+ pad = (u_char *) xcalloc(n, MD5_LEN);
- for(i=0; i<n; i++) {
- /* MD5_1 = MD5{session_id, secret, version, seq_no}
- MD5_2 = MD5{session_id, secret, version, seq_no, MD5_1} */
+ for (i=0; i<n; i++) {
+ /* MD5_1 = MD5{session_id, secret, version, seq_no}
+ MD5_2 = MD5{session_id, secret, version, seq_no, MD5_1} */
- /* place session_id, key, version and seq_no in buffer */
- bp=0;
- bcopy(&hdr->session_id, buf, sizeof(session_id));
- bp+=sizeof(session_id);
- bcopy(tac_secret, buf+bp, strlen(tac_secret));
- bp+=strlen(tac_secret);
- bcopy(&hdr->version, buf+bp, sizeof(hdr->version));
- bp+=sizeof(hdr->version);
- bcopy(&hdr->seq_no, buf+bp, sizeof(hdr->seq_no));
- bp+=sizeof(hdr->seq_no);
+ /* place session_id, key, version and seq_no in buffer */
+ bp = 0;
+ bcopy(&hdr->session_id, buf, sizeof(session_id));
+ bp += sizeof(session_id);
+ bcopy(tac_secret, buf+bp, strlen(tac_secret));
+ bp += strlen(tac_secret);
+ bcopy(&hdr->version, buf+bp, sizeof(hdr->version));
+ bp += sizeof(hdr->version);
+ bcopy(&hdr->seq_no, buf+bp, sizeof(hdr->seq_no));
+ bp += sizeof(hdr->seq_no);
- /* append previous pad if this is not the first run */
- if(i) {
- bcopy(pad+((i-1)*MD5_LEN), buf+bp, MD5_LEN);
- bp+=MD5_LEN;
- }
+ /* append previous pad if this is not the first run */
+ if (i) {
+ bcopy(pad+((i-1)*MD5_LEN), buf+bp, MD5_LEN);
+ bp+=MD5_LEN;
+ }
- MD5Init(&mdcontext);
- MD5Update(&mdcontext, buf, bp);
- /* this is because MD5 implementation has changed between
- * pppd versions 2.2.0g and 2.3.4
- */
+ MD5Init(&mdcontext);
+ MD5Update(&mdcontext, buf, bp);
+ /* this is because MD5 implementation has changed between
+ * pppd versions 2.2.0g and 2.3.4
+ */
#if 1
- MD5Final(pad+pp, &mdcontext); /* correct for pppd-2.3.4 */
+ MD5Final(pad+pp, &mdcontext); /* correct for pppd-2.3.4 */
#else
- MD5Final(&mdcontext); /* correct for pppd-2.2.0g */
- bcopy(&mdcontext.digest, pad+pp, MD5_LEN);
+ MD5Final(&mdcontext); /* correct for pppd-2.2.0g */
+ bcopy(&mdcontext.digest, pad+pp, MD5_LEN);
#endif
- pp+=MD5_LEN;
- }
+ pp += MD5_LEN;
+ }
- free(buf);
- return(pad);
+ free(buf);
+ return(pad);
-} /* _tac_md5_pad */
+} /* _tac_md5_pad */
/* Perform encryption/decryption on buffer. This means simply XORing
each byte from buffer with according byte from pseudo-random
pad. */
void _tac_crypt(u_char *buf, HDR *th, int length) {
- int i;
- u_char *pad;
+ int i;
+ u_char *pad;
- /* null operation if no encryption requested */
- if(th->encryption == TAC_PLUS_ENCRYPTED) {
+ /* null operation if no encryption requested */
+ if(th->encryption == TAC_PLUS_ENCRYPTED_FLAG) {
+ pad = _tac_md5_pad(length, th);
- pad=_tac_md5_pad(length, th);
-
- for(i=0; i<length; i++) {
- *(buf+i) ^= pad[i];
- }
+ for (i=0; i<length; i++) {
+ *(buf+i) ^= pad[i];
+ }
- free(pad);
-
- } else {
- syslog(LOG_WARNING, "%s: using no TACACS+ encryption", __FUNCTION__);
- }
-} /* _tac_crypt */
+ free(pad);
+ } else {
+ TACSYSLOG((LOG_WARNING, "%s: using no TACACS+ encryption", __FUNCTION__))
+ }
+} /* _tac_crypt */
diff --git a/libtac/lib/hdr_check.c b/libtac/lib/hdr_check.c
index 048a5e6..f0f0583 100644
--- a/libtac/lib/hdr_check.c
+++ b/libtac/lib/hdr_check.c
@@ -1,6 +1,6 @@
/* hdr_check.c - Perform basic sanity checks on received packet.
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -31,23 +31,21 @@
* or NULL when the header seems to be correct
*/
char *_tac_check_header(HDR *th, int type) {
-
- if(th->type != type) {
- syslog(LOG_ERR,
- "%s: unrelated reply, type %d, expected %d",
- __FUNCTION__, th->type, type);
- return(protocol_err_msg);
- } else if((th->seq_no != 2) && (th->seq_no != 4)) {
- syslog(LOG_ERR, "%s: not a reply - seq_no %d != 2",
- __FUNCTION__, th->seq_no);
- return(protocol_err_msg);
- } /* else if(ntohl(th->session_id) != session_id) {
- syslog(LOG_ERR,
- "%s: unrelated reply, received session_id %d != sent %d",
- __FUNCTION__, ntohl(th->session_id), session_id);
- return(protocol_err_msg);
- } */
-
- return(NULL); /* header is ok */
-
+ if(th->type != type) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: unrelated reply, type %d, expected %d",\
+ __FUNCTION__, th->type, type))
+ return(protocol_err_msg);
+ } else if((th->seq_no != 2) && (th->seq_no != 4)) {
+ TACSYSLOG((LOG_ERR, "%s: not a reply - seq_no %d != {2,4}",\
+ __FUNCTION__, th->seq_no))
+ return(protocol_err_msg);
+ } /* else if(ntohl(th->session_id) != session_id) {
+ TACSYSLOG((LOG_ERR,\
+ "%s: unrelated reply, received session_id %d != sent %d",\
+ __FUNCTION__, ntohl(th->session_id), session_id))
+ return(protocol_err_msg);
+ } */
+
+ return(NULL); /* header is ok */
} /* check header */
diff --git a/libtac/lib/header.c b/libtac/lib/header.c
index 5fdd8f2..bb24918 100644
--- a/libtac/lib/header.c
+++ b/libtac/lib/header.c
@@ -1,6 +1,6 @@
/* header.c - Create pre-filled header for TACACS+ request.
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -31,7 +31,7 @@
int session_id;
/* Encryption flag. */
-int tac_encryption;
+int tac_encryption = 0;
/* Pointer to TACACS+ shared secret string. */
char *tac_secret = "";
@@ -39,6 +39,20 @@ char *tac_secret = "";
/* Pointer to TACACS+ shared login string. */
char *tac_login = "pap";
+/* priv_lvl */
+int tac_priv_lvl = TAC_PLUS_PRIV_LVL_MIN;
+
+/* Authentication Method */
+int tac_authen_method = TAC_PLUS_AUTHEN_METH_TACACSPLUS;
+
+/* Service requesting authentication */
+int tac_authen_service = TAC_PLUS_AUTHEN_SVC_PPP;
+
+/* additional runtime flags */
+
+int tac_debug_enable = 0;
+int tac_readtimeout_enable = 0;
+
/* Returns pre-filled TACACS+ packet header of given type.
* 1. you MUST fill th->datalength and th->version
* 2. you MAY fill th->encryption
@@ -47,19 +61,20 @@ char *tac_login = "pap";
* field depends on the TACACS+ request type and thus it
* cannot be predefined.
*/
-HDR *_tac_req_header(u_char type) {
- HDR *th;
+HDR *_tac_req_header(u_char type, int cont_session) {
+ HDR *th;
- th=(HDR *) xcalloc(1, TAC_PLUS_HDR_SIZE);
+ th=(HDR *) xcalloc(1, TAC_PLUS_HDR_SIZE);
- /* preset some packet options in header */
- th->type=type;
- th->seq_no=1; /* always 1 for request */
- th->encryption=TAC_PLUS_ENCRYPTED;
+ /* preset some packet options in header */
+ th->type=type;
+ th->seq_no=1; /* always 1 for request */
+ th->encryption=TAC_PLUS_ENCRYPTED_FLAG;
- /* make session_id from pseudo-random number */
- session_id = magic();
- th->session_id = htonl(session_id);
+ /* make session_id from pseudo-random number */
+ if (!cont_session)
+ session_id = magic();
+ th->session_id = htonl(session_id);
- return(th);
+ return(th);
}
diff --git a/libtac/lib/magic.c b/libtac/lib/magic.c
index 7ac5621..3b809eb 100644
--- a/libtac/lib/magic.c
+++ b/libtac/lib/magic.c
@@ -40,7 +40,8 @@ extern void srand48 __P((long));
/* on Linux we use /dev/urandom as random numbers source
I find it really cool :) */
-int rfd = 0; /* /dev/urandom */
+int rfd = -1; /* /dev/urandom */
+int magic_inited = 0;
#endif
/*
@@ -56,20 +57,16 @@ magic_init()
long seed;
struct timeval t;
+ magic_inited = 1;
#ifdef __linux__
- rfd = open("/dev/urandom", O_RDONLY);
- if(rfd != -1)
- return;
- else {
- rfd = 0;
+ rfd = open("/dev/urandom", O_RDONLY);
+ if(rfd != -1)
+ return;
#endif
- /* if /dev/urandom fails, we try traditional method */
+ /* if /dev/urandom fails, we try traditional method */
gettimeofday(&t, NULL);
seed = gethostid() ^ t.tv_sec ^ t.tv_usec ^ getpid();
srand48(seed);
-#ifdef __linux__
- }
-#endif
}
/*
@@ -79,16 +76,18 @@ u_int32_t
magic()
{
#ifdef __linux__
- u_int32_t ret = 0;
- int bytes = 0;
+ u_int32_t ret = 0;
+ int bytes = 0;
+
+ if (magic_inited == 0 )
+ magic_init();
- if(rfd)
- {
- bytes = read(rfd, &ret, sizeof(ret));
- return(ret);
- }
+ if(rfd > -1) {
+ bytes = read(rfd, &ret, sizeof(ret));
+ return(ret);
+ }
else
- return (u_int32_t) mrand48();
+ return (u_int32_t) mrand48();
#else
return (u_int32_t) mrand48();
#endif
diff --git a/libtac/lib/magic.h b/libtac/lib/magic.h
index ac626b3..44a8de9 100644
--- a/libtac/lib/magic.h
+++ b/libtac/lib/magic.h
@@ -18,9 +18,15 @@
* See `CHANGES' file for revision history.
*/
+#ifndef _MAGIC_H
+#define _MAGIC_H
#ifndef __linux__
- #include "cdefs.h"
+ #include "cdefs.h"
#endif
+__BEGIN_DECLS
void magic_init __P((void)); /* Initialize the magic number generator */
u_int32_t magic __P((void)); /* Returns the next magic number */
+__END_DECLS
+
+#endif
diff --git a/libtac/lib/md5.c b/libtac/lib/md5.c
index cf6799c..7ae59ff 100644
--- a/libtac/lib/md5.c
+++ b/libtac/lib/md5.c
@@ -22,17 +22,17 @@
#include "md5.h"
/* forward declaration */
-static void Transform ();
+static void Transform __P((UINT4 *buf, UINT4 *in));
static unsigned char PADDING[64] = {
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* F, G, H and I are basic MD5 functions */
@@ -47,25 +47,25 @@ static unsigned char PADDING[64] = {
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */
/* Rotation is separate from addition to prevent recomputation */
#define FF(a, b, c, d, x, s, ac) \
- {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
+ {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
#define GG(a, b, c, d, x, s, ac) \
- {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
+ {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
#define HH(a, b, c, d, x, s, ac) \
- {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
+ {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
#define II(a, b, c, d, x, s, ac) \
- {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
+ {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
#ifdef __STDC__
#define UL(x) x##U
@@ -76,201 +76,190 @@ static unsigned char PADDING[64] = {
/* The routine MD5Init initializes the message-digest context
mdContext. All fields are set to zero.
*/
-void MD5Init (mdContext)
-MD5_CTX *mdContext;
-{
- mdContext->i[0] = mdContext->i[1] = (UINT4)0;
+void MD5Init (MD5_CTX *mdContext) {
+ mdContext->i[0] = mdContext->i[1] = (UINT4)0;
- /* Load magic initialization constants.
- */
- mdContext->buf[0] = (UINT4)0x67452301;
- mdContext->buf[1] = (UINT4)0xefcdab89;
- mdContext->buf[2] = (UINT4)0x98badcfe;
- mdContext->buf[3] = (UINT4)0x10325476;
+ /* Load magic initialization constants. */
+ mdContext->buf[0] = (UINT4)0x67452301;
+ mdContext->buf[1] = (UINT4)0xefcdab89;
+ mdContext->buf[2] = (UINT4)0x98badcfe;
+ mdContext->buf[3] = (UINT4)0x10325476;
}
/* The routine MD5Update updates the message-digest context to
account for the presence of each of the characters inBuf[0..inLen-1]
in the message whose digest is being computed.
*/
-void MD5Update (mdContext, inBuf, inLen)
-MD5_CTX *mdContext;
-unsigned char *inBuf;
-unsigned int inLen;
-{
- UINT4 in[16];
- int mdi;
- unsigned int i, ii;
+void MD5Update ( MD5_CTX *mdContext, unsigned char *inBuf,
+ unsigned int inLen) {
- /* compute number of bytes mod 64 */
- mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+ UINT4 in[16];
+ int mdi;
+ unsigned int i, ii;
- /* update number of bits */
- if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
- mdContext->i[1]++;
- mdContext->i[0] += ((UINT4)inLen << 3);
- mdContext->i[1] += ((UINT4)inLen >> 29);
+ /* compute number of bytes mod 64 */
+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
- while (inLen--) {
- /* add new character to buffer, increment mdi */
- mdContext->in[mdi++] = *inBuf++;
+ /* update number of bits */
+ if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0])
+ mdContext->i[1]++;
+ mdContext->i[0] += ((UINT4)inLen << 3);
+ mdContext->i[1] += ((UINT4)inLen >> 29);
- /* transform if necessary */
- if (mdi == 0x40) {
- for (i = 0, ii = 0; i < 16; i++, ii += 4)
- in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
- (((UINT4)mdContext->in[ii+2]) << 16) |
- (((UINT4)mdContext->in[ii+1]) << 8) |
- ((UINT4)mdContext->in[ii]);
- Transform (mdContext->buf, in);
- mdi = 0;
+ while (inLen--) {
+ /* add new character to buffer, increment mdi */
+ mdContext->in[mdi++] = *inBuf++;
+
+ /* transform if necessary */
+ if (mdi == 0x40) {
+ for (i = 0, ii = 0; i < 16; i++, ii += 4)
+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+ (((UINT4)mdContext->in[ii+2]) << 16) |
+ (((UINT4)mdContext->in[ii+1]) << 8) |
+ ((UINT4)mdContext->in[ii]);
+ Transform (mdContext->buf, in);
+ mdi = 0;
+ }
}
- }
}
/* The routine MD5Final terminates the message-digest computation and
ends with the desired message digest in mdContext->digest[0...15].
*/
-void MD5Final (hash, mdContext)
-unsigned char hash[];
-MD5_CTX *mdContext;
-{
- UINT4 in[16];
- int mdi;
- unsigned int i, ii;
- unsigned int padLen;
+void MD5Final (unsigned char hash[], MD5_CTX *mdContext) {
+ UINT4 in[16];
+ int mdi;
+ unsigned int i, ii;
+ unsigned int padLen;
- /* save number of bits */
- in[14] = mdContext->i[0];
- in[15] = mdContext->i[1];
+ /* save number of bits */
+ in[14] = mdContext->i[0];
+ in[15] = mdContext->i[1];
- /* compute number of bytes mod 64 */
- mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
+ /* compute number of bytes mod 64 */
+ mdi = (int)((mdContext->i[0] >> 3) & 0x3F);
- /* pad out to 56 mod 64 */
- padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
- MD5Update (mdContext, PADDING, padLen);
+ /* pad out to 56 mod 64 */
+ padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi);
+ MD5Update (mdContext, PADDING, padLen);
- /* append length in bits and transform */
- for (i = 0, ii = 0; i < 14; i++, ii += 4)
- in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
+ /* append length in bits and transform */
+ for (i = 0, ii = 0; i < 14; i++, ii += 4)
+ in[i] = (((UINT4)mdContext->in[ii+3]) << 24) |
(((UINT4)mdContext->in[ii+2]) << 16) |
(((UINT4)mdContext->in[ii+1]) << 8) |
((UINT4)mdContext->in[ii]);
- Transform (mdContext->buf, in);
+ Transform (mdContext->buf, in);
- /* store buffer in digest */
- for (i = 0, ii = 0; i < 4; i++, ii += 4) {
- mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
- mdContext->digest[ii+1] =
- (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
- mdContext->digest[ii+2] =
- (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
- mdContext->digest[ii+3] =
- (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
- }
- memcpy(hash, mdContext->digest, 16);
+ /* store buffer in digest */
+ for (i = 0, ii = 0; i < 4; i++, ii += 4) {
+ mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF);
+ mdContext->digest[ii+1] =
+ (unsigned char)((mdContext->buf[i] >> 8) & 0xFF);
+ mdContext->digest[ii+2] =
+ (unsigned char)((mdContext->buf[i] >> 16) & 0xFF);
+ mdContext->digest[ii+3] =
+ (unsigned char)((mdContext->buf[i] >> 24) & 0xFF);
+ }
+ memcpy(hash, mdContext->digest, 16);
}
/* Basic MD5 step. Transforms buf based on in.
*/
-static void Transform (buf, in)
-UINT4 *buf;
-UINT4 *in;
-{
- UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+static void Transform ( UINT4 *buf, UINT4 *in) {
+ UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
- /* Round 1 */
+ /* Round 1 */
#define S11 7
#define S12 12
#define S13 17
#define S14 22
- FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
- FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
- FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
- FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
- FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
- FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
- FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
- FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
- FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
- FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
- FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
- FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
- FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
- FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
- FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
- FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
+ FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */
+ FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */
+ FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */
+ FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */
+ FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */
+ FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */
+ FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */
+ FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */
+ FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */
+ FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */
+ FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */
+ FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */
+ FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */
+ FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */
+ FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */
+ FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */
- /* Round 2 */
+ /* Round 2 */
#define S21 5
#define S22 9
#define S23 14
#define S24 20
- GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
- GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
- GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
- GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
- GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
- GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */
- GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
- GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
- GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
- GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
- GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
- GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
- GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
- GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
- GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
- GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
+ GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */
+ GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */
+ GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */
+ GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */
+ GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */
+ GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */
+ GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */
+ GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */
+ GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */
+ GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */
+ GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */
+ GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */
+ GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */
+ GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */
+ GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */
+ GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */
- /* Round 3 */
+ /* Round 3 */
#define S31 4
#define S32 11
#define S33 16
#define S34 23
- HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
- HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
- HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
- HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
- HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
- HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
- HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
- HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
- HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
- HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
- HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
- HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */
- HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
- HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
- HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
- HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
+ HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */
+ HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */
+ HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */
+ HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */
+ HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */
+ HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */
+ HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */
+ HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */
+ HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */
+ HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */
+ HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */
+ HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */
+ HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */
+ HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */
+ HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */
+ HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */
- /* Round 4 */
+ /* Round 4 */
#define S41 6
#define S42 10
#define S43 15
#define S44 21
- II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
- II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
- II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
- II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
- II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
- II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
- II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
- II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
- II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
- II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
- II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
- II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
- II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
- II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
- II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
- II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
+ II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */
+ II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */
+ II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */
+ II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */
+ II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */
+ II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */
+ II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */
+ II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */
+ II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */
+ II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */
+ II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */
+ II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */
+ II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */
+ II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */
+ II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */
+ II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
}
diff --git a/libtac/lib/md5.h b/libtac/lib/md5.h
index fc314ed..a1cbfbd 100644
--- a/libtac/lib/md5.h
+++ b/libtac/lib/md5.h
@@ -25,15 +25,17 @@ typedef unsigned int UINT4;
/* Data structure for MD5 (Message-Digest) computation */
typedef struct {
- UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
- UINT4 buf[4]; /* scratch buffer */
- unsigned char in[64]; /* input buffer */
- unsigned char digest[16]; /* actual digest after MD5Final call */
+ UINT4 i[2]; /* number of _bits_ handled mod 2^64 */
+ UINT4 buf[4]; /* scratch buffer */
+ unsigned char in[64]; /* input buffer */
+ unsigned char digest[16]; /* actual digest after MD5Final call */
} MD5_CTX;
-void MD5Init ();
-void MD5Update ();
-void MD5Final ();
+__BEGIN_DECLS
+void MD5Init __P((MD5_CTX*));
+void MD5Update __P((MD5_CTX*, unsigned char*, UINT4));
+void MD5Final __P((unsigned char[], MD5_CTX*));
+__END_DECLS
#define MD5_LEN 16
diff --git a/libtac/lib/messages.c b/libtac/lib/messages.c
index 8a1ae3e..d24a809 100644
--- a/libtac/lib/messages.c
+++ b/libtac/lib/messages.c
@@ -1,6 +1,6 @@
/* messages.c - Various messages returned to user.
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -19,8 +19,12 @@
* See `CHANGES' file for revision history.
*/
-char *system_err_msg="Authentication error, please contact administrator.";
-char *protocol_err_msg="Protocol error.";
-char *author_ok_msg="Service granted.";
-char *author_fail_msg="Service not allowed.";
-char *author_err_msg="Protocol error.";
+char *protocol_err_msg = "(Protocol error)";
+char *author_ok_msg = "(Service granted)";
+char *author_fail_msg = "(Service not allowed)";
+char *author_err_msg = "(Service not allowed. Server error)";
+char *author_syserr_msg = "(Authorization system error)";
+char *acct_ok_msg = "(Accounted ok)";
+char *acct_fail_msg = "(Accounting failed)";
+char *acct_err_msg = "(Accounting failed. Server error)";
+char *acct_syserr_msg = "(Accounting system error)";
diff --git a/libtac/lib/messages.h b/libtac/lib/messages.h
index 37f2402..041195f 100644
--- a/libtac/lib/messages.h
+++ b/libtac/lib/messages.h
@@ -1,6 +1,6 @@
/* messages.h
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -19,8 +19,17 @@
* See `CHANGES' file for revision history.
*/
-extern char *system_err_msg;
+#ifndef _MESSAGES_H
+#define _MESSAGES_H
+
extern char *protocol_err_msg;
extern char *author_ok_msg;
extern char *author_fail_msg;
extern char *author_err_msg;
+extern char *author_syserr_msg;
+extern char *acct_ok_msg;
+extern char *acct_fail_msg;
+extern char *acct_err_msg;
+extern char *acct_syserr_msg;
+
+#endif
diff --git a/libtac/lib/read_wait.c b/libtac/lib/read_wait.c
new file mode 100644
index 0000000..e855ac9
--- /dev/null
+++ b/libtac/lib/read_wait.c
@@ -0,0 +1,119 @@
+/* read_wait.c - Wait for data to read on a fd.
+ *
+ * Copyright (C) 2011, Darren Besler (dbesler@beehive.mb.ca)
+ *
+ * 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 <sys/time.h>
+#include <poll.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include "tacplus.h"
+#include "libtac.h"
+
+static int delta_msecs(struct timeval *newer, struct timeval *older) {
+ long deltasecs, deltausecs;
+ struct timeval now;
+
+ if (newer == NULL) {
+ gettimeofday(&now, NULL);
+ newer = &now;
+ }
+
+ deltasecs = newer->tv_sec - older->tv_sec;
+ deltausecs = newer->tv_usec - older->tv_usec;
+ if ( newer->tv_usec < older->tv_usec ) {
+ deltasecs--;
+ deltausecs = (1000000+newer->tv_usec) - older->tv_usec;
+ } else {
+ deltausecs = newer->tv_usec - older->tv_usec;
+ }
+ return (deltasecs*1000)+(deltausecs/1000);
+}
+
+
+/*
+ * tac_read_wait
+ *
+ * Parms:
+ * fd - open fd to wait on till data avail, or timeout
+ * timeout - maximum time to wait in milliseconds
+ * size - amount of data to wait for
+ * 0 : any amount of data
+ * >0 : amount of data to wait for
+ * timeleft - return of time left from timeout
+ *
+ * Returns:
+ * 0 - data avail, no timeout
+ * -1 - timeout
+ * n - errno
+ */
+
+int tac_read_wait(int fd, int timeout, int size, int *time_left) {
+ int retval = 0;
+ int remaining;
+ struct pollfd fds[1];
+
+ struct timeval start;
+
+ gettimeofday(&start, NULL);
+
+ /* setup for read timeout.
+ * will use poll() as it provides greatest compatibility
+ * vs setsockopt(SO_RCVTIMEO) which isn't supported on Solaris
+ */
+
+ remaining = timeout; /* in msecs */
+
+ fds[0].fd = fd;
+ fds[0].events = POLLIN;
+
+ while (remaining > 0) {
+ int rc;
+ int avail = 0;
+ rc = poll(fds, 1, remaining);
+ remaining -= delta_msecs(NULL, &start);
+ if ( time_left != NULL ) {
+ *time_left = remaining > 0 ? remaining : 0;
+ }
+
+ /* why did poll return */
+ if (rc == 0) { /* Receive timeout */
+ retval = -1;
+ break;
+ }
+
+ if (rc > 0) { /* there is data available */
+ if (size > 0 && /* check for enuf available? */
+ ioctl(fd,FIONREAD,(char*)&avail) == 0 && avail < size) {
+ continue; /* not enuf yet, wait for more */
+ } else {
+ break;
+ }
+ }
+
+ if (rc < 0 && errno == EINTR) { // interrupt
+ continue;
+ }
+
+ /* all other conditions is an error */
+ retval = errno;
+ break;
+ }
+ return retval;
+} /* read_wait */
diff --git a/libtac/lib/version.c b/libtac/lib/version.c
index ccf20ee..16c8c7b 100644
--- a/libtac/lib/version.c
+++ b/libtac/lib/version.c
@@ -1,6 +1,6 @@
/* version.c - TACACS+ library version.
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -20,5 +20,5 @@
*/
int tac_ver_major = 1;
-int tac_ver_minor = 6;
-int tac_ver_patch = 5; /* patchlevel */
+int tac_ver_minor = 7;
+int tac_ver_patch = 1; /* patchlevel */
diff --git a/libtac/lib/xalloc.c b/libtac/lib/xalloc.c
index 88bbb28..a8e8302 100644
--- a/libtac/lib/xalloc.c
+++ b/libtac/lib/xalloc.c
@@ -1,7 +1,7 @@
/* xalloc.c - Failsafe memory allocation functions.
* Taken from excellent glibc.info ;)
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -20,24 +20,34 @@
* See `CHANGES' file for revision history.
*/
-#include <syslog.h>
-#include <stdlib.h>
+#include "libtac.h"
void *xcalloc(size_t nmemb, size_t size) {
- register void *val = calloc(nmemb, size);
- if(val == 0) {
- syslog(LOG_ERR, "%s: calloc(%u,%u) failed", __FUNCTION__,
- (unsigned) nmemb, (unsigned) size);
- exit(1);
- }
- return val;
+ register void *val = calloc(nmemb, size);
+ if(val == 0) {
+ TACSYSLOG((LOG_ERR, "%s: calloc(%u,%u) failed", __FUNCTION__,\
+ (unsigned) nmemb, (unsigned) size))
+ exit(1);
+ }
+ return val;
}
void *xrealloc(void *ptr, size_t size) {
- register void *val = realloc(ptr, size);
- if(val == 0) {
- syslog(LOG_ERR, "%s: realloc(%u) failed", __FUNCTION__, (unsigned) size);
- exit(1);
- }
- return val;
+ register void *val = realloc(ptr, size);
+ if(val == 0) {
+ TACSYSLOG((LOG_ERR, "%s: realloc(%u) failed", __FUNCTION__, (unsigned) size))
+ exit(1);
+ }
+ return val;
+}
+
+char *xstrdup(char *s) {
+ char *p;
+ if (s == NULL) return NULL;
+
+ if ( (p = strdup(s)) == NULL ) {
+ TACSYSLOG((LOG_ERR, "%s: strdup(%s) failed: %m", __FUNCTION__, s))
+ exit(1);
+ }
+ return p;
}
diff --git a/libtac/lib/xalloc.h b/libtac/lib/xalloc.h
index da02dfa..3573567 100644
--- a/libtac/lib/xalloc.h
+++ b/libtac/lib/xalloc.h
@@ -1,6 +1,6 @@
/* xalloc.h
*
- * Copyright (C) 2010, Pawel Krawczyk <kravietz@ceti.pl> and
+ * Copyright (C) 2010, Pawel Krawczyk <pawel.krawczyk@hush.com> and
* Jeroen Nijhof <jeroen@nijhofnet.nl>
*
* This program is free software; you can redistribute it and/or modify
@@ -19,5 +19,13 @@
* See `CHANGES' file for revision history.
*/
+#ifndef _XALLOC_H
+#define _XALLOC_H
+
+__BEGIN_DECLS
extern void *xcalloc(size_t nmemb, size_t size);
extern void *xrealloc(void *ptr, size_t size);
+extern char *xstrdup(char *s);
+__END_DECLS
+
+#endif