---
name: "libtacplus"
section: "3"
platform: "freebsd"
package: "base"
version: "16.0-CURRENT-20261027-61c70dc16a79"
release: "FreeBSD 16.0-CURRENT (2026-10-27)"
platforms: ["freebsd"]
url: "https://new.carta.tech/libtacplus"
---

# libtacplus(3)

TACACS+ client library

## NAME

**libtacplus** – TACACS+ client library

## 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

The **libtacplus** library implements the client side of the TACACS+ network access control protocol. TACACS+ allows clients to perform authentication, authorization, and accounting by means of network requests to remote servers. This library currently supports only the authentication and authorization portion of the protocol.

## INITIALIZATION

To use the library, an application must first call **tac\_open**() to obtain a *struct* *tac\_handle* *\**, which provides context for subsequent operations. Calls to **tac\_open**() always succeed unless insufficient virtual memory is available. If the necessary memory cannot be allocated, **tac\_open**() returns NULL.

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)](/tacplus.conf/5.md). 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**(). The *host* parameter specifies the server host, either as a fully qualified domain name or as a dotted-quad IP address in text form. The *port* parameter specifies the TCP port to contact on the server. If *port* is given as 0, the library uses port 49, the standard TACACS+ port. The shared secret for the server host is passed to the *secret* parameter. It may be any null-terminated string of bytes. The timeout for receiving replies from the server is passed to the *timeout* parameter, in units of seconds. The *flags* parameter is 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. Older servers do not support this mode, and some of them become confused if the client attempts to negotiate it.

**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. 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.

## 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.

## 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.

## 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 that it is not necessary for the caller to preserve them. 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 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.

## 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. 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. 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.

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**().

## 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

## EXTRACTING INFORMATION FROM THE SERVER'S AUTHORIZATION RESPONSE

Like an authentication response packet, an authorization response packet from the server may contain a server message, a data string, or both. Refer to EXTRACTING INFORMATION FROM THE SERVER'S AUTHENTICATION RESPONSE for instruction on extraction of those values.

An authorization response packet from the server may also contain attribute value (AV) pairs. To extract these, use **tac\_get\_av**() or **tac\_get\_av\_value**(). **tac\_get\_av**() takes the index of the AV pair as it is 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). Alternatively, **tac\_get\_av\_value**() can be used. **tac\_get\_av\_value**() takes the attribute name and returns the corresponding value only, not the AV pair. 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. The data returned from these functions is guaranteed to be terminated by a null byte.

## OBTAINING ERROR MESSAGES

Those functions which accept a *struct* *tac\_handle* *\** argument record an error message if they fail. The error message can be retrieved by calling **tac\_strerror**(). The message text is overwritten on each new error for the given *struct* *tac\_handle* *\**. Thus the message must be copied if it is to be preserved through subsequent library calls using the same handle.

## CLEANUP

To free the resources used by the TACACS+ library, call **tac\_close**().

## 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.

-

  **tac\_open**()

## FILES

- */etc/tacplus.conf*

  ## SEE ALSO

[tacplus.conf(5)](/tacplus.conf/5.md) 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.
