LIBTACPLUS(3)

๐Ÿ“ฆ version 15.1, in freebsd 14.5, freebsd 15.1

okay bestie, listen up ๐Ÿ’… this is libtacplus(3), plucked straight from the Library Functions Manual, and it's literally the TACACS+ client library. she's giving network-access-control main character energy and we're gonna go through it together, no biggie ๐ŸŽ€


โœจ NAME โœจ

libtacplus โ€” the TACACS+ client library, periodt ๐Ÿ’–


๐ŸŒธ SYNOPSIS ๐ŸŒธ

#include <taclib.h>

int
tac_add_server(struct tac_handle *h, const char *host, int port,
    const char *secret, int timeout, int flags);

void
tac_clear_avs(struct tac_handle *h);

void
tac_close(struct tac_handle *h);

int
tac_config(struct tac_handle *h, const char *path);

int
tac_create_authen(struct tac_handle *h, int action, int type,
    int service);

int
tac_create_author(struct tac_handle *h, int method, int type,
    int service);

int
tac_create_acct(struct tac_handle *h, int acct, int action, int type,
    int service);

char *
tac_get_av(struct tac_handle *h, u_int index);

char *
tac_get_av_value(struct tac_handle *h, const char *attribute);

void *
tac_get_data(struct tac_handle *h, size_t *len);

char *
tac_get_msg(struct tac_handle *h);

struct tac_handle *
tac_open(void);

int
tac_send_authen(struct tac_handle *h);

int
tac_send_author(struct tac_handle *h);

int
tac_send_acct(struct tac_handle *h);

int
tac_set_av(struct tac_handle *h, u_int index, const char *av_pair);

int
tac_set_data(struct tac_handle *h, const void *data, size_t data_len);

int
tac_set_msg(struct tac_handle *h, const char *msg);

int
tac_set_port(struct tac_handle *h, const char *port);

int
tac_set_priv(struct tac_handle *h, int priv);

int
tac_set_rem_addr(struct tac_handle *h, const char *addr);

int
tac_set_user(struct tac_handle *h, const char *user);

const char *
tac_strerror(struct tac_handle *h);

๐Ÿ’– DESCRIPTION ๐Ÿ’–

so the libtacplus library implements the client side of the TACACS+ network access control protocol โ€” like, the side that asks, not the side that answers, iykyk. and TACACS+ lets clients perform authentication, authorization, and accounting by means of network requests to remote servers ๐ŸŒˆ

the tea though: this library currently supports only the authentication and authorization portion of the protocol. that's the whole vibe check, bestie โ€” don't come looking for full accounting coverage here ๐Ÿซถ


๐ŸŽ€ INITIALIZATION ๐ŸŽ€

to use this library, your application has to first call tac_open() to obtain a struct tac_handle *, which provides context for all the subsequent operations โ€” think of it as her little emotional support handle ๐Ÿ‘œ

calls to tac_open() always succeed unless insufficient virtual memory is available. if the necessary memory cannot be allocated, tac_open() returns NULL ๐Ÿ˜ญ (that's the only way she flops).

before issuing any TACACS+ requests, the library must be made aware of the servers it can contact. the easiest way to configure the library is to call tac_config() โœจ

tac_config() causes the library to read a configuration file whose format is described in tacplus.conf(5). the pathname of the configuration file is passed as the file argument to tac_config(). this argument may also be given as NULL, in which case the standard configuration file /etc/tacplus.conf is used ๐Ÿ—‚๏ธ

tac_config() returns 0 on success, or -1 if an error occurs.

the library can also be configured programmatically by calls to tac_add_server(), if you're feeling extra ๐Ÿ’…

  • host โ€” specifies the server host, either as a fully qualified domain name or as a dotted-quad IP address in text form
  • port โ€” specifies the TCP port to contact on the server. if port is given as 0, the library uses port 49, the standard TACACS+ port ๐Ÿ”Œ
  • secret โ€” the shared secret for the server host. it may be any null-terminated string of bytes ๐Ÿคซ
  • timeout โ€” the timeout for receiving replies from the server, in units of seconds โฑ๏ธ
  • flags โ€” a bit mask of flags to specify various characteristics of the server. it may contain:
    • TAC_SRVR_SINGLE_CONNECT โ€” causes the library to attempt to negotiate single connection mode when communicating with the server. in single connection mode, the original TCP connection is held open for multiple TACACS+ sessions ๐Ÿ”— warning bestie: older servers do not support this mode, and some of them become confused if the client attempts to negotiate it. so like, read the room ๐Ÿ˜ฌ

tac_add_server() returns 0 on success, or -1 if an error occurs.

tac_add_server() may be called multiple times, and it may be used together with tac_config(). at most 10 servers may be specified โ€” that's the cap, no negotiating ๐Ÿšซ

when multiple servers are given, they are tried in round-robin fashion until a working, accessible server is found. once the library finds such a server, it continues to use it as long as it works ๐Ÿ‘‘ (loyalty!!)


๐Ÿฆ‹ CREATING A TACACS+ AUTHENTICATION REQUEST ๐Ÿฆ‹

to begin constructing a new authentication request, call tac_create_authen().

the action, type, and service arguments must be set to appropriate values as defined in the TACACS+ protocol specification. the <taclib.h> header file contains symbolic constants for these values, so you don't have to memorize the magic numbers fr fr ๐Ÿ“–


๐Ÿ’œ CREATING A TACACS+ AUTHORIZATION REQUEST ๐Ÿ’œ

to begin constructing a new authorization request, call tac_create_author().

the method, type, and service arguments must be set to appropriate values as defined in the TACACS+ protocol specification. the <taclib.h> header file contains symbolic constants for these values โœจ


๐Ÿ“ CREATING A TACACS+ ACCOUNTING REQUEST ๐Ÿ“

to begin constructing a new accounting request, call tac_create_acct().

the acct, action, type, and service arguments must be set to appropriate values as defined in the TACACS+ protocol specification. the <taclib.h> header file contains symbolic constants for these values, bestie, they're right there ๐Ÿซถ


๐Ÿงš SETTING OPTIONAL PARAMETERS ON A REQUEST ๐Ÿงš

after creating a request, various optional parameters may be attached to it through calls to tac_set_av(), tac_set_data(), tac_set_port(), tac_set_priv(), tac_set_rem_addr(), and tac_set_user() ๐ŸŽ€

the library creates its own copies of any strings provided to these functions, so it is not necessary for the caller to preserve them โ€” she's not borrowing your stuff and giving it back, she's making her own, iconic ๐Ÿ’…

by default, each of these parameters is empty except for the privilege level, which defaults to โ€˜USERโ€™ privilege ๐Ÿ‘‘

tac_set_av() only applies to the context of an authorization request โ˜๏ธ the format for an attribute value pair is defined in the TACACS+ protocol specification. the index specified can be any value between 0 and 255 inclusive and indicates the position in the list to place the attribute value pair.

calling tac_set_av() with the same index twice effectively replaces the value at that position ๐Ÿ” use tac_clear_avs() to clear all attribute value pairs that may have been set, like a full reset button ๐Ÿงน


๐Ÿ”ฅ SENDING THE AUTHENTICATION REQUEST AND RECEIVING THE RESPONSE ๐Ÿ”ฅ

after the TACACS+ authentication request has been constructed, it is sent by means of tac_send_authen(). this function connects to a server if not already connected, sends the request, and waits for a reply ๐Ÿ“จ

on failure, tac_send_authen() returns -1. otherwise, it returns the TACACS+ status code and flags, packed into an integer value โ€” yes, packed, she's efficient like that ๐Ÿ˜Œ

the status can be extracted using the macro TAC_AUTHEN_STATUS(). possible status codes, defined in <taclib.h>, include:

  • TAC_AUTHEN_STATUS_PASS
  • TAC_AUTHEN_STATUS_FAIL
  • TAC_AUTHEN_STATUS_GETDATA
  • TAC_AUTHEN_STATUS_GETUSER
  • TAC_AUTHEN_STATUS_GETPASS
  • TAC_AUTHEN_STATUS_RESTART
  • TAC_AUTHEN_STATUS_ERROR
  • TAC_AUTHEN_STATUS_FOLLOW

the only flag is the no-echo flag, which can be tested using the macro TAC_AUTHEN_NOECHO() ๐Ÿคซ


โญ EXTRACTING INFORMATION FROM THE SERVER'S AUTHENTICATION RESPONSE โญ

an authentication response packet from the server may contain a server message, a data string, or both ๐ŸŽ

after a successful call to tac_send_authen(), this information may be retrieved from the response by calling tac_get_msg() and tac_get_data(). these functions return dynamically-allocated copies of the information from the packet ๐Ÿ“ฆ

the caller is responsible for freeing the copies when it no longer needs them. don't leave them hanging, bestie, that's a leak ๐Ÿ˜ญ

the data returned from these functions is guaranteed to be terminated by a null byte โœ…

in the case of tac_get_data(), the len argument points to a location into which the library will store the actual length of the received data โ€” not including the null terminator. this argument may be given as NULL if the caller is not interested in the length ๐Ÿ™ˆ


๐ŸŒŠ SENDING AUTHENTICATION CONTINUE PACKETS ๐ŸŒŠ

if tac_send_authen() returns a value containing one of the status codes TAC_AUTHEN_STATUS_GETDATA, TAC_AUTHEN_STATUS_GETUSER, or TAC_AUTHEN_STATUS_GETPASS, then the client must provide additional information to the server by means of a TACACS+ CONTINUE packet ๐Ÿ“ฌ

to do so, the application must first set the packet's user message and/or data fields using tac_set_msg() and tac_set_data(). the client then sends the CONTINUE packet with tac_send_authen().

N.B., tac_create_authen() should not be called to construct a CONTINUE packet; it is used only for the initial authentication request. like, read the label please, she has one job ๐Ÿ’€

when it receives the CONTINUE packet, the server may again request more information by returning TAC_AUTHEN_STATUS_GETDATA, TAC_AUTHEN_STATUS_GETUSER, or TAC_AUTHEN_STATUS_GETPASS. the application should send further CONTINUEs until some other status is received from the server ๐Ÿ”๐Ÿ”


๐Ÿ’€ SENDING THE AUTHORIZATION REQUEST AND RECEIVING THE RESPONSE ๐Ÿ’€

after the TACACS+ authorization request has been constructed, it is sent by means of tac_send_author(). this function connects to a server if not already connected, sends the request, and waits for a reply ๐Ÿ“จ

on failure, tac_send_author() returns -1. otherwise, it returns the TACACS+ status code and number of attribute value (AV) pairs received, packed into an integer value.

the status can be extracted using the macro TAC_AUTHOR_STATUS(). possible status codes, defined in <taclib.h>, include:

  • TAC_AUTHOR_STATUS_PASS_ADD
  • TAC_AUTHOR_STATUS_PASS_REPL
  • TAC_AUTHOR_STATUS_FAIL
  • TAC_AUTHOR_STATUS_ERROR

the number of AV pairs received is obtained using TAC_AUTHEN_AV_COUNT() ๐Ÿงฎ (yes, that's the macro name, don't come for me, I just report what's on the page ๐Ÿ’…)


๐ŸŒˆ SENDING THE ACCOUNTING REQUEST AND RECEIVING THE RESPONSE ๐ŸŒˆ

after the TACACS+ authorization request has been constructed, it is sent by means of tac_send_acct(). this function connects to a server if not already connected, sends the request, and waits for a reply ๐Ÿ“จ

on failure, tac_send_acct() returns -1. otherwise, it returns the TACACS+ status code. possible status codes, defined in <taclib.h>, include:

  • TAC_ACCT_STATUS_SUCCESS
  • TAC_ACCT_STATUS_ERROR
  • TAC_ACCT_STATUS_FOLLOW

okay and that's where part one of this little saga wraps โ€” but bestie we are so not done, there's more page coming, so don't go anywhere ๐Ÿ’–

๐ŸŽ€ EXTRACTING INFORMATION FROM THE SERVER'S AUTHORIZATION RESPONSE ๐ŸŽ€

Okay so bestie, an authorization response packet from the server can carry a server message, a data string, or literally both โ€” same energy as an authentication response packet. So if you wanna know how to pull those out, just go re-read EXTRACTING INFORMATION FROM THE SERVER'S AUTHENTICATION RESPONSE, it's the whole vibe, iykyk.

But here's the โœจextraโœจ part: an authorization response packet from the server may also contain attribute value (AV) pairs. Obsessed. To get those out you use tac_get_av() or tac_get_av_value().

  • tac_get_av() takes the index of the AV pair as it's positioned in the list. The indexes start at 0 (use TAC_AUTHEN_AV_COUNT() on the return value of tac_send_author() to get the total number of items in this list โ€” that's your count, no cap).
  • Alternatively, tac_get_av_value() can be used. It takes the attribute name and returns the corresponding value only, not the AV pair. Just the value, periodt.

These functions return dynamically-allocated copies of the information from the packet, so the caller is responsible for freeing the copies when it no longer needs them โ€” that's on you, bestie, don't ghost your memory ๐Ÿ˜ญ. The data returned from these functions is guaranteed to be terminated by a null byte. ๐Ÿซถ


๐Ÿ’… OBTAINING ERROR MESSAGES ๐Ÿ’…

Those functions that accept a struct tac_handle * argument record an error message if they fail. To go get that message, call tac_strerror(). Easy.

โš ๏ธ Heads up though: the message text is overwritten on each new error for the given struct tac_handle *. So the message must be copied if it's to be preserved through subsequent library calls using the same handle. Copy it or lose it, fr fr. ๐Ÿ’€

๐Ÿงผ CLEANUP ๐Ÿงผ

To free the resources used by the TACACS+ library, call tac_close(). That's it. Clean girl aesthetic, take your stuff and go โœจ


๐Ÿ‘‘ RETURN VALUES ๐Ÿ‘‘

The following functions return a non-negative value on success. If they detect an error, they return -1 and record an error message which can be retrieved using tac_strerror().

tac_add_server()
tac_config()
tac_create_authen()
tac_create_author()
tac_create_acct()
tac_send_authen()
tac_send_author()
tac_send_acct()
tac_set_av()
tac_set_data()
tac_set_msg()
tac_set_port()
tac_set_priv()
tac_set_rem_addr()
tac_set_user()

The following functions return a non-NULL pointer on success. If they are unable to allocate sufficient virtual memory, they return NULL and record an error message which can be retrieved using tac_strerror().

tac_get_av()
tac_get_av_value()
tac_get_data()
tac_get_msg()

The following functions return a non-NULL pointer on success. If they are unable to allocate sufficient virtual memory, they return NULL, without recording an error message. Rude, but okay ๐Ÿ™ˆ

tac_open()

๐Ÿ“ FILES ๐Ÿ“

  • /etc/tacplus.conf

๐ŸŒˆ SEE ALSO ๐ŸŒˆ

  • tacplus.conf(5)
  • D. Carrel and Lol Grant, The TACACS+ Protocol, Version 1.78, draft-grant-tacacs-02.txt (Internet Draft).

๐Ÿ’– AUTHORS ๐Ÿ’–

This software was written by John Polstra and Paul Fraley, and donated to the FreeBSD project by Juniper Networks, Inc. Kings, honestly ๐Ÿ‘‘๐Ÿซถ


โœจ that's the whole page bestie, go forth and TACACS+ responsibly โœจ

This page is from the Debian build, dated December 11, 2009, and it's LIBTACPLUS(3) โ€” mwah, ily, bye ๐Ÿ’…๐Ÿ’–

๐Ÿ“ฆ where this page comes from