Add support for TACACS+ accounting to libtacplus(3).

Submitted by:	Michael Pounov misho@aitbg.com
OKed by:	emaste
This commit is contained in:
Shteryana Shopova 2009-12-11 07:53:44 +00:00
parent 57467e5933
commit db3a20a518
4 changed files with 142 additions and 0 deletions

View File

@ -44,6 +44,8 @@
.Fn tac_create_authen "struct tac_handle *h" "int action" "int type" "int service"
.Ft int
.Fn tac_create_author "struct tac_handle *h" "int method" "int type" "int service"
.Ft int
.Fn tac_create_acct "struct tac_handle *h" "int acct" "int action" "int type" "int service"
.Ft char *
.Fn tac_get_av "struct tac_handle *h" "u_int index"
.Ft char *
@ -59,6 +61,8 @@
.Ft int
.Fn tac_send_author "struct tac_handle *h"
.Ft int
.Fn tac_send_acct "struct tac_handle *h"
.Ft int
.Fn tac_set_av "struct tac_handle *h" "u_int index" "const char *av_pair"
.Ft int
.Fn tac_set_data "struct tac_handle *h" "const void *data" "size_t data_len"
@ -193,6 +197,20 @@ TACACS+ protocol specification.
The
.In taclib.h
header file contains symbolic constants for these values.
.Sh CREATING A TACACS+ ACCOUNTING REQUEST
To begin constructing a new accounting request, call
.Fn tac_create_acct .
The
.Va acct ,
.Va action ,
.Va type ,
and
.Va service
arguments must be set to appropriate values as defined in the
TACACS+ protocol specification.
The
.In taclib.h
header file contains symbolic constants for these values.
.Sh SETTING OPTIONAL PARAMETERS ON A REQUEST
After creating a request,
various optional parameters may be attached to it through calls to
@ -354,6 +372,29 @@ include:
.Pp
The number of AV pairs received is obtained using
.Fn TAC_AUTHEN_AV_COUNT .
.Sh SENDING THE ACCOUNTING REQUEST AND RECEIVING THE RESPONSE
After the TACACS+ authorization request has been constructed, it
is sent by means of
.Fn tac_send_acct .
This function connects to a server if not already connected, sends
the request, and waits for a reply.
On failure,
.Fn tac_send_acct
returns \-1.
Otherwise, it returns the TACACS+ status code
Possible status codes, defined in
.In taclib.h ,
include:
.Pp
.Bl -item -compact -offset indent
.It
.Dv TAC_ACCT_STATUS_SUCCESS
.It
.Dv TAC_ACCT_STATUS_ERROR
.It
.Dv TAC_ACCT_STATUS_FOLLOW
.El
.Pp
.Sh EXTRACTING INFORMATION FROM THE SERVER'S AUTHORIZATION RESPONSE
Like an authentication response packet, an authorization
response packet from the
@ -418,10 +459,14 @@ which can be retrieved using
.It
.Fn tac_create_author
.It
.Fn tac_create_acct
.It
.Fn tac_send_authen
.It
.Fn tac_send_author
.It
.Fn tac_send_acct
.It
.Fn tac_set_av
.It
.Fn tac_set_data

View File

@ -211,6 +211,8 @@ protocol_version(int msg_type, int var, int type)
}
break;
case TAC_ACCT:
default:
minor = 0;
break;
@ -967,6 +969,23 @@ tac_create_author(struct tac_handle *h, int method, int type, int service)
return 0;
}
int
tac_create_acct(struct tac_handle *h, int acct, int action, int type, int service)
{
struct tac_acct_start *as;
create_msg(h, TAC_ACCT, action, type);
as = &h->request.u.acct_start;
as->action = acct;
as->authen_action = action;
as->priv_lvl = TAC_PRIV_LVL_USER;
as->authen_type = type;
as->authen_service = service;
return 0;
}
static void
create_msg(struct tac_handle *h, int msg_type, int var, int type)
{
@ -1157,6 +1176,49 @@ tac_send_author(struct tac_handle *h)
return ares->av_cnt << 8 | ares->status;
}
int
tac_send_acct(struct tac_handle *h)
{
register int i, current;
struct tac_acct_start *as = &h->request.u.acct_start;
struct tac_acct_reply *ar = &h->response.u.acct_reply;
/* start */
as = &h->request.u.acct_start;
h->request.length = htonl(offsetof(struct tac_acct_start, rest[0]));
for (as->av_cnt = 0, i = 0; i < MAXAVPAIRS; i++)
if (h->avs[i].len && h->avs[i].data)
as->av_cnt++;
h->request.length = ntohl(htonl(h->request.length) + as->av_cnt);
if (add_str_8(h, &as->user_len, &h->user) == -1 ||
add_str_8(h, &as->port_len, &h->port) == -1 ||
add_str_8(h, &as->rem_addr_len, &h->rem_addr) == -1)
return -1;
for (i = current = 0; i < MAXAVPAIRS; i++)
if (h->avs[i].len && h->avs[i].data)
if (add_str_8(h, &as->rest[current++], &(h->avs[i])) == -1)
return -1;
/* send */
if (send_msg(h) == -1 || recv_msg(h) == -1)
return -1;
/* reply */
h->srvr_pos = offsetof(struct tac_acct_reply, rest[0]);
if (get_srvr_str(h, "msg", &h->srvr_msg, ntohs(ar->msg_len)) == -1 ||
get_srvr_str(h, "data", &h->srvr_data, ntohs(ar->data_len)) == -1 ||
get_srvr_end(h) == -1)
return -1;
/* Sanity checks */
if (!h->single_connect)
close_connection(h);
return ar->status;
}
int
tac_set_rem_addr(struct tac_handle *h, const char *addr)
{

View File

@ -103,6 +103,17 @@ struct tac_handle;
#define TAC_AUTHOR_STATUS_FAIL 0x10
#define TAC_AUTHOR_STATUS_ERROR 0x11
/* Accounting actions */
#define TAC_ACCT_MORE 0x1
#define TAC_ACCT_START 0x2
#define TAC_ACCT_STOP 0x4
#define TAC_ACCT_WATCHDOG 0x8
/* Accounting status */
#define TAC_ACCT_STATUS_SUCCESS 0x1
#define TAC_ACCT_STATUS_ERROR 0x2
#define TAC_ACCT_STATUS_FOLLOW 0x21
__BEGIN_DECLS
int tac_add_server(struct tac_handle *,
const char *, int, const char *, int, int);
@ -127,6 +138,8 @@ int tac_set_av(struct tac_handle *, u_int, const char *);
char *tac_get_av(struct tac_handle *, u_int);
char *tac_get_av_value(struct tac_handle *, const char *);
void tac_clear_avs(struct tac_handle *);
int tac_create_acct(struct tac_handle *, int, int, int, int);
int tac_send_acct(struct tac_handle *);
__END_DECLS
#endif /* _TACLIB_H_ */

View File

@ -132,6 +132,26 @@ struct tac_author_response {
unsigned char rest[1];
};
struct tac_acct_start {
u_int8_t action;
u_int8_t authen_action;
u_int8_t priv_lvl;
u_int8_t authen_type;
u_int8_t authen_service;
u_int8_t user_len;
u_int8_t port_len;
u_int8_t rem_addr_len;
u_int8_t av_cnt;
unsigned char rest[1];
};
struct tac_acct_reply {
u_int16_t msg_len;
u_int16_t data_len;
u_int8_t status;
unsigned char rest[1];
};
struct tac_msg {
u_int8_t version;
u_int8_t type;
@ -145,6 +165,8 @@ struct tac_msg {
struct tac_authen_cont authen_cont;
struct tac_author_request author_request;
struct tac_author_response author_response;
struct tac_acct_start acct_start;
struct tac_acct_reply acct_reply;
unsigned char body[BODYSIZE];
} u;
};