RFC 8907

The Terminal Access Controller Access-Control System Plus (TACACS+) Protocol

๐Ÿ“… published September 2020, from ietf

RFC 8907: The Terminal Access Controller Access-Control System Plus (TACACS+) Protocol ๐ŸŽ€

  • RFC number: 8907 ๐Ÿ”ข
  • Category: Informational. It's published for information, not as a standard ๐Ÿ“š
  • Date: September 2020 ๐Ÿ—“๏ธ
  • ISSN: 2070-1721
  • Authors: T. Dahm, A. Ota, D.C. Medway Gash, D. Carrel and L. Grant ๐Ÿซถ
  • Affiliations in the header: Google Inc., Cisco Systems, Inc. and IPsec Research ๐Ÿข
  • Obsoletes / Updates: the header lists nothing here, so this RFC doesn't replace or update any earlier document ๐Ÿ™…โ€โ™€๏ธ

Abstract โœจ

okay so this doc describes TACACS+ ๐Ÿ’…, which is still everywhere. It's used for Device Administration, meaning routers, network access servers and other networked gadgets can all ask one or more centralized servers to handle their access control ๐Ÿ–ฅ๏ธ๐Ÿ”. It's giving "one brain, many devices" energy ๐Ÿง .

Status of This Memo โœจ

bestie, this is not an Internet Standards Track spec. It's published for information only ๐Ÿ“–.

It is still a product of the IETF ๐ŸŒ. It represents what the IETF community agreed on, got public review, and was approved for publication by the Internet Engineering Steering Group (IESG). Not everything the IESG approves can become an Internet Standard, though, so see Section 2 of RFC 7841 for the details ๐Ÿค“.

For the latest status, errata, and how to send feedback, go to https://www.rfc-editor.org/info/rfc8907 ๐Ÿ”—.

Copyright (c) 2020 IETF Trust and the persons identified as the document authors. All rights reserved ๐Ÿ›ก๏ธ.

This doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents, which you can find at https://trustee.ietf.org/license-info and which apply on the publication date. Please actually read those, because they spell out your rights and restrictions ๐Ÿ“œ. Any Code Components pulled out of this document must include the Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come with no warranty, as the Simplified BSD License explains ๐Ÿงพ.

This document may include material from IETF Documents or IETF Contributions published or made publicly available before November 10, 2008. The people who control the copyright in some of that material may not have given the IETF Trust permission to allow modifications outside the IETF Standards Process ๐Ÿง. So without an adequate license from those copyright holders, this document may not be modified outside the IETF Standards Process, and derivative works of it may not be made outside that process. The only exceptions are formatting it for publication as an RFC or translating it into languages other than English ๐ŸŒ.

Table of Contents ๐Ÿ“‘

1.  Introduction
2.  Conventions
3.  Technical Definitions
  3.1.  Client
  3.2.  Server
  3.3.  Packet
  3.4.  Connection
  3.5.  Session
  3.6.  Treatment of Enumerated Protocol Values
  3.7.  Treatment of Text Strings
4.  TACACS+ Packets and Sessions
  4.1.  The TACACS+ Packet Header
  4.2.  The TACACS+ Packet Body
  4.3.  Single Connection Mode
  4.4.  Session Completion
  4.5.  Data Obfuscation
5.  Authentication
  5.1.  The Authentication START Packet Body
  5.2.  The Authentication REPLY Packet Body
  5.3.  The Authentication CONTINUE Packet Body
  5.4.  Description of Authentication Process
    5.4.1.  Version Behavior
    5.4.2.  Common Authentication Flows
    5.4.3.  Aborting an Authentication Session
6.  Authorization
  6.1.  The Authorization REQUEST Packet Body
  6.2.  The Authorization REPLY Packet Body
7.  Accounting
  7.1.  The Account REQUEST Packet Body
  7.2.  The Accounting REPLY Packet Body
8.  Argument-Value Pairs
  8.1.  Value Encoding
  8.2.  Authorization Arguments
  8.3.  Accounting Arguments
9.  Privilege Levels
10. Security Considerations
  10.1.  General Security of the Protocol
  10.2.  Security of Authentication Sessions
  10.3.  Security of Authorization Sessions
  10.4.  Security of Accounting Sessions
  10.5.  TACACS+ Best Practices
    10.5.1.  Shared Secrets
    10.5.2.  Connections and Obfuscation
    10.5.3.  Authentication
    10.5.4.  Authorization
    10.5.5.  Redirection Mechanism
11. IANA Considerations
12. References
  12.1.  Normative References
  12.2.  Informative References
Acknowledgements
Authors' Addresses

1. Introduction โœจ

okay bestie, this doc is all about the TACACS+ protocol ๐ŸŽ€. It started out as a general Authentication, Authorization, and Accounting (AAA) protocol, but it's mostly used now for Device Administration ๐Ÿ–ฅ๏ธ. That covers logging in to network devices, central authorization of what people are allowed to do, and auditing all of it afterwards ๐Ÿ•ต๏ธโ€โ™€๏ธ.

There are tons of TACACS+ clients and servers out in the wild already ๐ŸŒ. They're all built on a protocol that was defined in a document meant for IETF publication, but it never got standardized. That document is known as "The Draft" [THE-DRAFT] ๐Ÿ“„.

The Draft was very much a product of its time ๐Ÿ•ฐ๏ธ. It didn't cover all the key security concerns we'd expect from modern standards, so deployments need to be handled with care ๐Ÿง. Those concerns are dealt with in Section 10 ๐Ÿ’–.

The main goal of this informational doc is to pin down the part of "The Draft" that's shared by implementations doing Device Administration ๐Ÿ“Œ. Anything that conforms to this document will also conform to "The Draft" ๐Ÿ’ฏ. The reverse isn't true though, because not everything that conforms to "The Draft" will conform to this doc ๐Ÿ™ƒ. These features from "The Draft" are gone:

  • This document officially removes SENDPASS for security reasons. ๐Ÿšซ
  • The normative description of legacy features such as the Apple Remote Access Protocol (ARAP) and outbound authentication has been removed. ๐ŸŽ
  • The support for forwarding to an alternative daemon (TAC_PLUS_AUTHEN_STATUS_FOLLOW) has been deprecated. ๐Ÿชฆ

TACACS+ lets authentication exchanges be any length and have any content, so you can use different auth mechanisms ๐Ÿ”‘. It's extensible for site customization and future features โœจ, and it runs over TCP so delivery is reliable ๐Ÿšš. The client can ask for fine-grained access control, and the server can answer every piece of that request separately ๐ŸŽฏ.

Splitting authentication, authorization, and accounting apart is a key part of the TACACS+ design ๐Ÿ’…. Basically, TACACS+ is three protocols in a trench coat ๐Ÿงฅ. This doc covers each one in its own section. TACACS+ defines all three, but an implementation or deployment doesn't have to use all three ๐ŸŒˆ. Keeping them separate is really useful for Device Administration, especially for authorizing and auditing individual commands in a session ๐Ÿ‘‘. Also note that the protocol has no provision for linking authentication requests to authorization requests ๐Ÿ™ˆ.

2. Conventions ๐Ÿ’œ

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" are the BCP 14 [RFC2119] [RFC8174] words, and they only mean that in this document when they appear in all capitals, as shown here ๐Ÿ” . Lowercase versions are just regular English ๐Ÿ˜Œ.

3. Technical Definitions ๐Ÿงš

This section gives some basic definitions that apply throughout the doc ๐Ÿ“š.

3.1. Client ๐Ÿ“ฑ

The client is any device that starts TACACS+ protocol requests to mediate access, mainly for the Device Administration use case ๐Ÿ™‹โ€โ™€๏ธ.

3.2. Server ๐Ÿ–ฅ๏ธ

The server takes in TACACS+ protocol requests and replies based on its own business model, following the flows defined in this document ๐Ÿงพ.

3.3. Packet ๐Ÿ“ฆ

Every time this document says "packet," it means a TACACS+ protocol data unit, unless it says otherwise ๐Ÿ”. The informal term "packet" has become an established part of the definition, so it's officially a thing now ๐ŸŽ€.

3.4. Connection ๐Ÿ”Œ

TACACS+ uses TCP for transport ๐Ÿš›. IANA has allocated TCP server port 49 for TACACS+ traffic ๐ŸŽŸ๏ธ.

3.5. Session ๐ŸŽฌ

A session shows up all over this doc ๐Ÿ‘€. A TACACS+ session is one authentication sequence, one authorization exchange, or one accounting exchange ๐Ÿ”.

An accounting or authorization session is just one pair of packets: the request and its reply โœŒ๏ธ. An authentication session can involve any number of packets going back and forth ๐Ÿ“. The session is an operational concept kept between the TACACS+ client and server, so it doesn't necessarily line up with a particular user or user action ๐Ÿซ .

3.6. Treatment of Enumerated Protocol Values ๐Ÿ”ข

This doc describes a bunch of enumerated values in the packet header and in the headers for specific packet types ๐Ÿ—‚๏ธ. For example, in the authentication start packet type, the action field has three values: TAC_PLUS_AUTHEN_LOGIN, TAC_PLUS_AUTHEN_CHPASS, and TAC_PLUS_AUTHEN_SENDAUTH ๐Ÿ”‘.

If the server doesn't implement one of the defined options in a packet it receives, or it runs into an option that this document doesn't list for a header field, then it should reply with an ERROR and end the session ๐Ÿ™…โ€โ™€๏ธ. That lets the client try a different option ๐Ÿ”„.

If an error happens and the type of the incoming packet can't be figured out, a packet with the identical cleartext header must be sent back to signal the error. The only changes are that its sequence number goes up by one and its length is set to zero ๐Ÿšจ.

Wait, I need to be precise: the RFC requires that exact packet, so the line above is the important bit. Here it is verbatim in spirit: the reply MUST be a packet with the identical cleartext header, with the sequence number incremented by one and the length set to zero, returned to indicate an error ๐Ÿšจ.

3.7. Treatment of Text Strings โœ๏ธ

TACACS+ uses text strings a LOT ๐Ÿ“. "The Draft" meant for these strings to be treated as byte arrays where each byte is one US-ASCII character ๐Ÿ”ค. But server implementations now work with external identity services, so we need a more nuanced approach ๐ŸŒ.

Usernames MUST be encoded and handled using the UsernameCasePreserved Profile specified in [RFC8265] ๐Ÿง‘โ€๐Ÿ’ป. The security considerations in Section 8 of [RFC8265] apply too ๐Ÿ›ก๏ธ.

Where it's specifically mentioned, data fields contain arrays of arbitrary bytes as needed for protocol processing ๐Ÿงฉ. These aren't meant to be shown to users through any user interface ๐Ÿ™ˆ.

All other text fields in TACACS+ MUST be treated as printable byte arrays of US-ASCII, as defined by [RFC0020] ๐Ÿ’…. "Printable" here means the fields MUST exclude the "Control Characters" defined in Section 5.2 of [RFC0020] ๐Ÿšซ.

4. TACACS+ Packets and Sessions ๐ŸŽ€

4.1. The TACACS+ Packet Header โœจ

okay bestie, every TACACS+ packet starts with the same 12-byte header ๐ŸŽ€ and the header tells you how long the rest of the packet is. here's the layout:

 1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8
+----------------+----------------+----------------+----------------+
|major  | minor  |                |                |                |
|version| version|      type      |     seq_no     |   flags        |
+----------------+----------------+----------------+----------------+
|                                                                   |
|                            session_id                             |
+----------------+----------------+----------------+----------------+
|                                                                   |
|                              length                               |
+----------------+----------------+----------------+----------------+

and a few general rules apply to every single packet type ๐Ÿ’…

  • If a variable-length data field is unused, its length value is set to zero. Those fields MUST be ignored, and treated as if they're not even there ๐Ÿ™ˆ
  • The lengths of the data and message fields are given by their length fields. They are NOT null terminated, so don't go looking for a terminator ๐Ÿ’€
  • All length values are unsigned and go in network byte order ๐ŸŒˆ

now let's look at each header field ๐Ÿ‘‘

major_version

this is the major TACACS+ version number ๐Ÿฆ‹

TAC_PLUS_MAJOR_VER := 0xc

minor_version

this is the minor TACACS+ version number ๐ŸŒธ

TAC_PLUS_MINOR_VER_DEFAULT := 0x0
TAC_PLUS_MINOR_VER_ONE := 0x1

type

this is the packet type ๐Ÿ“ the options are:

TAC_PLUS_AUTHEN := 0x01 (Authentication)
TAC_PLUS_AUTHOR := 0x02 (Authorization)
TAC_PLUS_ACCT := 0x03 (Accounting)

seq_no

this is the sequence number of the current packet, and it's giving order โœจ the first packet in a session MUST have the sequence number 1, and then every packet after that goes up by one. TACACS+ clients only send packets with odd sequence numbers, and TACACS+ servers only send packets with even sequence numbers. so it's a whole call-and-response thing ๐Ÿซถ

the sequence number must never wrap. like, if the sequence number 2^(8)-1 is ever reached, that session has to terminate and restart with a sequence number of 1 ๐Ÿ˜ญ

flags

this field holds a bunch of bitmapped flags ๐Ÿงš the flag bit:

TAC_PLUS_UNENCRYPTED_FLAG := 0x01

this flag says the sender did NOT obfuscate the body of the packet. this option MUST NOT be used in production, no exceptions, bestie ๐Ÿšซ the way this flag gets applied is covered in "Security Considerations" (Section 10) so go read that ๐Ÿ’œ

this flag SHOULD be clear in all deployments. modern network traffic tools can handle encrypted traffic when they're configured with the shared secret (see "Shared Secrets" (Section 10.5.1)), so obfuscated mode can and SHOULD be used even during testing ๐Ÿ”ฅ

the single-connection flag:

TAC_PLUS_SINGLE_CONNECT_FLAG := 0x04

this flag lets a client and server negotiate "Single Connection Mode" (Section 4.3) ๐Ÿฆ‹

all other bits MUST be ignored when reading, and SHOULD be set to zero when writing ๐ŸŒˆ

session_id

the Id for this TACACS+ session ๐ŸŽ€ this field doesn't change for the whole session. this number MUST be generated by a cryptographically strong random number generation method, because if it isn't, the security of the session is compromised ๐Ÿ’€ for more details, check [RFC4086] โœจ

length

this is the total length of the packet body, NOT including the header ๐Ÿ“ implementations MUST allow control over the maximum packet sizes accepted by TACACS+ Servers ๐Ÿ‘‘ the recommended maximum packet size is 2^(16) ๐ŸŒธ


4.2. The TACACS+ Packet Body ๐Ÿงš

the body types are defined in the packet header ๐Ÿ’… the next sections of this document dig into what's inside each of the different TACACS+ bodies. no spoilers, we're getting there ๐Ÿซถ


4.3. Single Connection Mode ๐Ÿฆ‹

okay this one is lowkey iconic. Single Connection Mode is meant to boost performance when there's a LOT of traffic between a client and a server. it lets the client multiplex multiple sessions over one TCP connection, so it's not opening a new connection every time ๐Ÿ”ฅ

the packet header has the TAC_PLUS_SINGLE_CONNECT_FLAG, and the client and server use it to negotiate whether Single Connection Mode gets used ๐ŸŒˆ

the client sets this flag to say it supports multiplexing TACACS+ sessions over a single TCP connection. the client MUST NOT send a second packet on a connection until single-connect status has been established. wait for it, bestie โณ

to say it'll support Single Connection Mode, the server sets this flag in the first reply packet, which answers the first request from a client โœจ the server may set this flag even if the client didn't set it, but the client may ignore the flag and close the connection after the session completes ๐Ÿ™ˆ

the flag only matters for the first two packets on a connection, so the client and server can get Single Connection Mode set up. there's no provision for changing Single Connection Mode after those first two packets. the client and server MUST ignore the flag after the second packet on a connection. no takebacks ๐Ÿ’…

if Single Connection Mode hasn't been established in the first two packets of a TCP connection, then both the client and the server close the connection at the end of the first session ๐Ÿ’€

the client negotiates Single Connection Mode to be more efficient ๐Ÿ“ but the server may refuse to allow it for the client. for example, it might not be appropriate to hold a long-lasting TCP connection open for one specific client in some deployments ๐ŸŒธ and even if the server is configured to allow Single Connection Mode for a specific client, the server may still close the connection. like, a server MUST be configured to time out a Single Connection Mode TCP connection after a set period of inactivity so it doesn't waste its resources ๐Ÿ‘‘ the client MUST accommodate such closures on a TCP session, even after Single Connection Mode has been established. the server's allowed to be ghosty, and the client has to be chill about it ๐Ÿซถ

the TCP connection under Single Connection Mode will eventually close, either because the server timed it out or because of some intermediate link ๐Ÿฆ‹ if a session is in progress when the client detects the disconnect, the client should handle it as described in "Session Completion" (Section 4.4) โœจ if no session is in progress, the client will need to detect that, and restart Single Connection Mode when it starts the next session ๐ŸŒˆ


4.4. Session Completion ๐Ÿ’œ

the REPLY packets for the packet types in the sections below (Authentication, Authorization, and Accounting) have a status field ๐ŸŽ€ the full set of options for this field depends on the packet type, but all three REPLY packet types define values for PASS, ERROR, and FAIL. those show up on the last packet of a regular session (one that wasn't aborted) ๐Ÿ”ฅ

the server responds with a PASS or a FAIL to say the request was processed and the client can apply the result (PASS or FAIL) to control whatever action prompted the request in the first place โœจ

the server responds with an ERROR to say the request did NOT get processed. the client can't apply the result, and it MUST behave as if the server could not be connected to ๐Ÿ˜ญ for example, the client tries alternative methods if they're available, like sending the request to a backup server, or using local configuration to decide whether the action that prompted the request should go ahead ๐Ÿซถ

for details on handling the additional status options, check "Aborting an Authentication Session" (Section 5.4.3) ๐ŸŒธ

when the session is complete, the TCP connection should be handled like this, depending on whether Single Connection Mode was negotiated:

  • if Single Connection Mode was not negotiated, the connection should be closed. ๐Ÿ‘‹
  • if Single Connection Mode was enabled, the connection SHOULD be left open (see "Single Connection Mode" (Section 4.3)), but it may still be closed after a timeout period to save deployment resources ๐ŸŒˆ
  • if Single Connection Mode was enabled, but an ERROR happened because of connection issues (like an incorrect secret, see Section 4.5), then any further new sessions MUST NOT be accepted on the connection. if there are any sessions that already got established, they MAY be completed. once all the active sessions are done, the connection MUST be closed ๐Ÿ’€

it is recommended that client implementations have robust schemes for dealing with servers that can't be connected to ๐Ÿงš options include a list of servers for redundancy and an option for a local fallback configuration if no servers can be reached. the details are implementation specific, so it's up to each implementation to figure out its own vibe ๐Ÿ“

the client should manage connections and handle the case where a server establishes a connection but doesn't respond. the exact behavior is implementation specific. it is recommended that the client close the connection after a configurable timeout โฐ๐ŸŽ€

4.5. Data Obfuscation ๐Ÿซฃ

The body of packets may be obfuscated ๐Ÿ”. The next bits explain the obfuscation method the protocol supports. In "The Draft", this process was actually called Encryption ๐Ÿ™ˆ, but the algorithm wouldn't meet modern standards, so this document will not call it encryption. Not gonna be the one who calls it that ๐Ÿ’€

The obfuscation mechanism relies on a secret key, a shared secret value that both the client and the server know ๐Ÿ—๏ธ. The secret keys MUST remain secret.

Server implementations MUST allow a unique secret key to be associated with each client. Whether separate keys make sense is a site-dependent decision โœจ.

The flag field MUST be configured with TAC_PLUS_UNENCRYPTED_FLAG set to 0 so that the packet body gets obfuscated by XORing it bytewise with a pseudo-random pad ๐ŸŽ€:

ENCRYPTED {data} = data ^(pseudo_pad)

The packet body can then be de-obfuscated by XORing it bytewise with a pseudo-random pad ๐Ÿฆ‹:

data = ENCRYPTED {data} ^(pseudo_pad)

The pad is generated by concatenating a series of MD5 hashes (each 16 bytes long) and truncating the result to the length of the input data ๐Ÿงฉ. Whenever this document says MD5, it means the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" as specified in [RFC1321] ๐Ÿ’œ.

pseudo_pad = {MD5_1 [,MD5_2 [ ... ,MD5_n]]} truncated to len(data)

The first MD5 hash is generated by concatenating the session_id, the secret key, the version number, and the sequence number, then running MD5 over that stream ๐ŸŒธ. Every one of those inputs lives in the packet header except the secret key, which is a shared secret between the TACACS+ client and server ๐Ÿคซ.

The version number and session_id are extracted from the header ๐Ÿ“ฆ.

Subsequent hashes use the same input stream, but with the previous hash value tacked onto the end ๐Ÿ”:

MD5_1 = MD5{session_id, key, version, seq_no} MD5_2 =
MD5{session_id, key, version, seq_no, MD5_1} ....  MD5_n =
MD5{session_id, key, version, seq_no, MD5_n-1}

When a server detects that the secrets it has configured for the device don't match, it MUST return ERROR ๐Ÿšจ. For details on how TCP connection handling works on ERROR, check out "Session Completion" (Section 4.4) ๐Ÿ”—.

TAC_PLUS_UNENCRYPTED_FLAG == 0x1

This option is deprecated and MUST NOT be used in production ๐Ÿ™…โ€โ™€๏ธ. In this case the entire packet body is in cleartext ๐Ÿ‘€.

A request MUST be dropped if TAC_PLUS_UNENCRYPTED_FLAG is set to true. No exceptions, bestie ๐Ÿšซ

After a packet body is de-obfuscated, the lengths of the component values in the packet get summed โž•. If that sum isn't identical to the cleartext datalength value from the header, the packet MUST be discarded and an ERROR signaled ๐Ÿ—‘๏ธ. For details on TCP connection handling on ERROR, see "Session Completion" (Section 4.4).

Commonly, these failures show up when the keys are mismatched between the client and the TACACS+ server ๐Ÿ˜ญ.


5. Authentication ๐Ÿชช

Authentication is the action of determining who a user (or entity) is ๐Ÿ‘ค. It can take lots of forms. Traditional authentication uses a name and a fixed password. However, fixed passwords are vulnerable security ๐Ÿ™ƒ, so a lot of modern mechanisms use "one-time" passwords or a challenge-response query โณ. TACACS+ is designed to support all of these and be flexible enough to handle any future mechanisms ๐ŸŒˆ. Authentication generally happens when the user first logs in to a machine or requests a service from it ๐Ÿšช.

Authentication is not mandatory; it's a site-configured option โš™๏ธ. Some sites don't require it. Others require it only for certain services (see "Authorization" (Section 6)) ๐Ÿ”‘. Authentication may also happen when a user tries to gain extra privileges and must identify himself or herself as someone who holds the required information (passwords, etc.) for those privileges ๐Ÿ‘‘.

5.1. The Authentication START Packet Body ๐Ÿš€

 1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8
+----------------+----------------+----------------+----------------+
|    action      |    priv_lvl    |  authen_type   | authen_service |
+----------------+----------------+----------------+----------------+
|    user_len    |    port_len    |  rem_addr_len  |    data_len    |
+----------------+----------------+----------------+----------------+
|    user ...
+----------------+----------------+----------------+----------------+
|    port ...
+----------------+----------------+----------------+----------------+
|    rem_addr ...
+----------------+----------------+----------------+----------------+
|    data...
+----------------+----------------+----------------+----------------+

Here's the rundown on the packet fields ๐Ÿ“:

action ๐ŸŽฌ

This indicates the authentication action.

Valid values are:

TAC_PLUS_AUTHEN_LOGIN := 0x01

TAC_PLUS_AUTHEN_CHPASS := 0x02

TAC_PLUS_AUTHEN_SENDAUTH := 0x04

priv_lvl ๐Ÿ‘‘

This indicates the privilege level that the user is authenticating as. Please refer to "Privilege Levels" (Section 9) ๐Ÿ“–.

authen_type ๐Ÿงพ

The type of authentication. Please see "Common Authentication Flows" (Section 5.4.2) ๐Ÿ”.

Valid values are:

TAC_PLUS_AUTHEN_TYPE_ASCII := 0x01

TAC_PLUS_AUTHEN_TYPE_PAP := 0x02

TAC_PLUS_AUTHEN_TYPE_CHAP := 0x03

TAC_PLUS_AUTHEN_TYPE_MSCHAP := 0x05

TAC_PLUS_AUTHEN_TYPE_MSCHAPV2 := 0x06

authen_service ๐Ÿ›Ž๏ธ

This is the service that is requesting the authentication.

Valid values are:

TAC_PLUS_AUTHEN_SVC_NONE := 0x00

TAC_PLUS_AUTHEN_SVC_LOGIN := 0x01

TAC_PLUS_AUTHEN_SVC_ENABLE := 0x02

TAC_PLUS_AUTHEN_SVC_PPP := 0x03

TAC_PLUS_AUTHEN_SVC_PT := 0x05

TAC_PLUS_AUTHEN_SVC_RCMD := 0x06

TAC_PLUS_AUTHEN_SVC_X25 := 0x07

TAC_PLUS_AUTHEN_SVC_NASI := 0x08

TAC_PLUS_AUTHEN_SVC_FWPROXY := 0x09

The TAC_PLUS_AUTHEN_SVC_NONE option is meant for the authorization application of this field, indicating that the device didn't perform any authentication ๐Ÿ™….

The TAC_PLUS_AUTHEN_SVC_LOGIN option means regular login (as opposed to ENABLE) to a client device ๐Ÿ”.

The TAC_PLUS_AUTHEN_SVC_ENABLE option identifies the ENABLE authen_service, which is a service requesting authentication in order to grant the user different privileges ๐Ÿ”“. It's comparable to the Unix "su(1)" command, which swaps the current user's identity for another one ๐Ÿ”„. An authen_service value of NONE should only be used when none of the other authen_service values fit ๐Ÿ™‹โ€โ™€๏ธ. ENABLE may be requested independently; the protocol doesn't impose any requirements for previous authentications or authorizations ๐Ÿฆ‹.

Other options are included for legacy/backwards compatibility ๐Ÿ•ฐ๏ธ.

user, user_len ๐Ÿ™‹

The username is optional in this packet, depending on the class of authentication. If it's absent, the client MUST set user_len to 0. If it's included, user_len gives the length of the user field, in bytes ๐Ÿ“.

port, port_len ๐Ÿ”Œ

The name of the client port where the authentication is happening. The value is free-format text and is client specific โœ๏ธ. Examples include "tty10" to denote the tenth tty line, and "async10" to denote the tenth async interface ๐Ÿงต. The client documentation SHOULD define the values and their meanings for this field. For details on text encoding, see "Treatment of Text Strings" (Section 3.7) ๐Ÿ”ค. The port_len gives the length of the port field, in bytes ๐Ÿ“.

rem_addr, rem_addr_len ๐ŸŒ

A string indicating the remote location from which the user connected to the client ๐Ÿ›ฐ๏ธ. For details on text encoding, see "Treatment of Text Strings" (Section 3.7) ๐Ÿ”ค.

When TACACS+ was used for dial-up services, this value held the caller ID ๐Ÿ“ž.

When TACACS+ is used for Device Administration, the user is normally connected via a network. In that case the value is meant to hold a network address, IPv4 or IPv6 ๐ŸŒ. For the IPv6 address text representation, please see [RFC5952] ๐Ÿ’….

This field is optional (since the information may not be available). The rem_addr_len gives the length of the user field, in bytes ๐Ÿ“.

data, data_len ๐Ÿ“ฆ

The data field carries data that's appropriate for the action and authen_type. It's described in more detail in "Common Authentication Flows" (Section 5.4.2) ๐Ÿ”. The data_len field gives the length of the data field, in bytes ๐Ÿ“.

5.2. The Authentication REPLY Packet Body ๐Ÿ’Œ

The TACACS+ server sends only one type of authentication packet to the client: a REPLY packet ๐Ÿ“ฌ.

 1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8
+----------------+----------------+----------------+----------------+
|     status     |      flags     |        server_msg_len           |
+----------------+----------------+----------------+----------------+
|           data_len              |        server_msg ...
+----------------+----------------+----------------+----------------+
|           data ...
+----------------+----------------+

status ๐Ÿšฆ

The current status of the authentication.

Valid values are:

TAC_PLUS_AUTHEN_STATUS_PASS := 0x01

TAC_PLUS_AUTHEN_STATUS_FAIL := 0x02

TAC_PLUS_AUTHEN_STATUS_GETDATA := 0x03

TAC_PLUS_AUTHEN_STATUS_GETUSER := 0x04

TAC_PLUS_AUTHEN_STATUS_GETPASS := 0x05

TAC_PLUS_AUTHEN_STATUS_RESTART := 0x06

TAC_PLUS_AUTHEN_STATUS_ERROR := 0x07

TAC_PLUS_AUTHEN_STATUS_FOLLOW := 0x21

flags ๐Ÿณ๏ธ

Bitmapped flags that modify the action to be taken ๐ŸŽ›๏ธ.

The following values are defined:

TAC_PLUS_REPLY_FLAG_NOECHO := 0x01

server_msg, server_msg_len ๐Ÿ’ฌ

A message to be displayed to the user. This field is optional. The server_msg_len gives the length of the server_msg field, in bytes. For details on text encoding, see "Treatment of Text Strings" (Section 3.7) ๐Ÿ”ค.

data, data_len ๐Ÿงƒ

A field that holds data which is part of the authentication exchange and is intended for client processing, not the user ๐Ÿค–. It is not a printable text encoding. Examples of its use are shown in "Common Authentication Flows" (Section 5.4.2) ๐Ÿ”. The data_len gives the length of the data field, in bytes ๐Ÿ“.

5.3. The Authentication CONTINUE Packet Body โœจ

okay so this packet is the client's reply ๐Ÿ’… It gets sent from the client to the server after the client has received a REPLY packet ๐Ÿฆ‹

    1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8
   +----------------+----------------+----------------+----------------+
   |          user_msg len           |            data_len             |
   +----------------+----------------+----------------+----------------+
   |     flags      |  user_msg ...
   +----------------+----------------+----------------+----------------+
   |    data ...
   +----------------+

user_msg, user_msg_len ๐Ÿ’ฌ This is the string the user typed in, or the string the client typed in on the user's behalf, as an answer to the server_msg from a REPLY packet. The user_len tells you how long the user field is, in bytes.

data, data_len ๐ŸŽ€ This field carries info that's specific to the action and the authen_type for this session. The valid uses are described below. It is NOT a printable text encoding, so don't treat it like text ๐Ÿ™ˆ The data_len tells you how long the data field is, in bytes.

flags โœจ This holds the bitmapped flags that modify the action to be taken. The following values are defined:

TAC_PLUS_CONTINUE_FLAG_ABORT := 0x01

5.4. Description of Authentication Process ๐Ÿ”ฅ

So the action, authen_type, and authen_service fields (we just went over those ๐Ÿ’–) all team up to say what kind of authentication is happening. Every START, REPLY, and CONTINUE packet has a data field, and what goes in it depends on the kind of authentication.

This document defines a core set of authentication flows that TACACS+ is supposed to support. Each flow starts with a START packet. The server then answers with either a request for more info (TAC_PLUS_AUTHEN_STATUS_GETDATA, TAC_PLUS_AUTHEN_STATUS_GETUSER, or TAC_PLUS_AUTHEN_STATUS_GETPASS) or a final verdict: PASS, FAIL, ERROR, or RESTART. The RESTART and ERROR actions (and what they mean) are the same across flows, and we'll get into those more below ๐Ÿ‘‘

When the REPLY status is TAC_PLUS_AUTHEN_STATUS_GETDATA, TAC_PLUS_AUTHEN_STATUS_GETUSER, or TAC_PLUS_AUTHEN_STATUS_GETPASS, the authentication keeps going. The server SHOULD send server_msg content so the client can prompt the user for whatever it needs ๐ŸŒธ Then the client MUST send back a CONTINUE packet with the requested info in the user_msg field.

The client should read TAC_PLUS_AUTHEN_STATUS_GETUSER as "hey, I need a username" and TAC_PLUS_AUTHEN_STATUS_GETPASS as "hey, I need a password" ๐Ÿ”‘ TAC_PLUS_AUTHEN_STATUS_GETDATA is the generic ask for more info, which is how the protocol stays flexible for future needs ๐Ÿงš

If the info the server is asking for is sensitive, the server should set the TAC_PLUS_REPLY_FLAG_NOECHO flag. When the client asks the user for that info, the response MUST NOT show up in the user interface as it's typed. Nobody's shoulder-surfing this bestie ๐Ÿ™ˆ

The data field is ONLY used in the REPLY packets where it's explicitly defined below.

5.4.1. Version Behavior

TACACS+ is versioned so it can get revisions while staying backwards compatible ๐Ÿฆ‹ The version number lives in every packet header. The only differences between minor_version 0 and 1 are in the authentication process, and they all have to do with how Challenge Handshake Authentication Protocol (CHAP) and Password Authentication Protocol (PAP) authentications get handled. minor_version 1 may only be used for the authentication kinds that explicitly call for it in the table below ๐Ÿ’…

            +-------------+-------+--------+----------+
            |             | LOGIN | CHPASS | SENDAUTH |
            +-------------+-------+--------+----------+
            | ASCII       | v0    | v0     | -        |
            +-------------+-------+--------+----------+
            | PAP         | v1    | -      | v1       |
            +-------------+-------+--------+----------+
            | CHAP        | v1    | -      | v1       |
            +-------------+-------+--------+----------+
            | MS-CHAPv1/2 | v1    | -      | v1       |
            +-------------+-------+--------+----------+

                Table 1: TACACS+ Protocol Versioning

The '-' symbol means that option is not valid, so no vibes there ๐Ÿšซ

All authorization, all accounting, and ASCII authentication use minor_version 0 ๐Ÿ“

PAP, CHAP, and MS-CHAP login use minor_version 1. The normal exchange is one START packet from the client and one REPLY from the server ๐ŸŽ€

โš ๏ธ The removal of SENDPASS happened because of security concerns, and it is no longer considered part of the TACACS+ protocol. Bye bye, SENDPASS ๐Ÿ˜ญ

5.4.2. Common Authentication Flows

This section walks through the common authentication flows. If the server doesn't implement an option, it MUST respond with TAC_PLUS_AUTHEN_STATUS_FAIL ๐Ÿ’€

5.4.2.1. ASCII Login

   action = TAC_PLUS_AUTHEN_LOGIN
   authen_type = TAC_PLUS_AUTHEN_TYPE_ASCII
   minor_version = 0x0

This is a standard ASCII authentication ๐Ÿงพ The START packet MAY include the username. If the user doesn't include the username, the server MUST get it from the client with a CONTINUE TAC_PLUS_AUTHEN_STATUS_GETUSER. If the user doesn't give a username, the server can send another TAC_PLUS_AUTHEN_STATUS_GETUSER request, BUT the server MUST limit how many retries are allowed, and the recommended limit is three attempts ๐Ÿ™ƒ Once the server has the username, it gets the password with a continue using TAC_PLUS_AUTHEN_STATUS_GETPASS. ASCII login uses the user_msg field for BOTH the username and the password. The data fields in both the START and CONTINUE packets aren't used for ASCII logins, and any content there MUST be ignored. The session is one START, then zero or more pairs of REPLYs and CONTINUEs, then a final REPLY saying PASS, FAIL, or ERROR โœจ

5.4.2.2. PAP Login

   action = TAC_PLUS_AUTHEN_LOGIN
   authen_type = TAC_PLUS_AUTHEN_TYPE_PAP
   minor_version = 0x1

The entire exchange MUST be one START packet and one REPLY, no extra drama ๐ŸŽฌ The START packet MUST contain a username, and the data field MUST contain the PAP ASCII password. A PAP authentication only has a username and password [RFC1334] (Obsolete) ๐Ÿชฆ The REPLY from the server MUST be either a PASS, FAIL, or ERROR.

5.4.2.3. CHAP Login

   action = TAC_PLUS_AUTHEN_LOGIN
   authen_type = TAC_PLUS_AUTHEN_TYPE_CHAP
   minor_version = 0x1

The entire exchange MUST be one START packet and one REPLY. The START packet MUST contain the username in the user field, and the data field is a mashup of the PPP id, the challenge, and the response ๐Ÿงฉ

You can figure out the challenge length from the data field length, minus the id (always 1 octet) and minus the response field (always 16 octets) ๐Ÿงฎ

To do the authentication, the server works out the PPP hash as defined in PPP Authentication [RFC1334], then compares that to the response. The MD5 algorithm option is always used ๐Ÿ” The REPLY from the server MUST be a PASS, FAIL, or ERROR.

Picking the challenge and how long it is isn't part of the TACACS+ protocol. BUT it's strongly recommended that the client/endstation setup use a secure challenge ๐Ÿซถ The TACACS+ server can help out by rejecting authentications where the challenge is shorter than a minimum length (the minimum recommended is 8 bytes) ๐Ÿ›ก๏ธ

5.4.2.4. MS-CHAP v1 Login

   action = TAC_PLUS_AUTHEN_LOGIN
   authen_type = TAC_PLUS_AUTHEN_TYPE_MSCHAP
   minor_version = 0x1

The entire exchange MUST be one START packet and one REPLY. The START packet MUST contain the username in the user field, and the data field is a concatenation of the PPP id, the MS-CHAP challenge, and the MS-CHAP response ๐Ÿช„

The challenge length can be figured out from the data field length, minus the id (always 1 octet) and minus the response field (always 49 octets) ๐Ÿง 

For the authentication, the server uses a combo of MD4 and DES on the user's secret and the challenge, as defined in [RFC2433], then compares the result with the response. The REPLY from the server MUST be a PASS or FAIL ๐Ÿ”

For best practices, check out [RFC2433] ๐Ÿ“š The TACACS+ server MUST reject authentications where the challenge deviates from 8 bytes, as defined in the RFC.

5.4.2.5. MS-CHAP v2 Login

   action = TAC_PLUS_AUTHEN_LOGIN
   authen_type = TAC_PLUS_AUTHEN_TYPE_MSCHAPV2
   minor_version = 0x1

The entire exchange MUST be one START packet and one REPLY. The START packet MUST contain the username in the user field, and the data field is a concatenation of the PPP id, the MS-CHAP challenge, and the MS-CHAP response ๐ŸŒˆ

The challenge length can be figured out from the data field length, minus the id (always 1 octet) and minus the response field (always 49 octets) ๐Ÿงฎ

To do the authentication, the server uses the algorithm specified in [RFC2759] on the user's secret and challenge, then compares the result with the response. The REPLY from the server MUST be a PASS or FAIL ๐Ÿ’…

For best practices for MS-CHAP v2, check out [RFC2759] ๐Ÿ“– The TACACS+ server MUST reject authentications where the challenge deviates from 16 bytes, as defined in the RFC.

5.4.2.6. Enable Requests

   action = TAC_PLUS_AUTHEN_LOGIN
   priv_lvl = implementation dependent
   authen_type = not used
   service = TAC_PLUS_AUTHEN_SVC_ENABLE

This is an "ENABLE" request, used to change the current running privilege level of a user ๐Ÿ”“ The exchange MAY be several messages while the server collects the info it needs to let the principal change their privilege level. It's super similar to an ASCII login (Section 5.4.2.1) ๐Ÿ‘ฏ

So ENABLE requests are easy to tell apart from other requests, the authen_service field MUST be set to TAC_PLUS_AUTHEN_SVC_ENABLE when requesting an ENABLE. It MUST NOT be set to that value when requesting any other operation ๐Ÿšฆ

5.4.2.7. ASCII Change Password Request

   action = TAC_PLUS_AUTHEN_CHPASS
   authen_type = TAC_PLUS_AUTHEN_TYPE_ASCII

This exchange is several messages while the server collects what it needs to change the user's password ๐Ÿ” It's very similar to an ASCII login. The status value TAC_PLUS_AUTHEN_STATUS_GETPASS MUST only be used when asking for the "new" password, and it MAY be sent multiple times. When asking for the "old" password, the status value MUST be set to TAC_PLUS_AUTHEN_STATUS_GETDATA ๐Ÿซ 

5.4.3. Aborting an Authentication Session ๐Ÿ›‘

okay so the client can bail early ๐Ÿ™…โ€โ™€๏ธ by setting the TAC_PLUS_CONTINUE_FLAG_ABORT flag in the CONTINUE message. when that flag is on, the data part of the message may hold some text explaining why it bailed. the server handles that text however the deployment says to, so bestie, check your setup ๐Ÿ’…. for text encoding deets, peep "Treatment of Text Strings" (Section 3.7). and for more on wrapping up a session, see "Session Completion" (Section 4.4) โœจ.

in cases of PASS, FAIL, or ERROR, the server can drop a message into server_msg for the user to see ๐Ÿ’Œ.

"The Draft" [THE-DRAFT] came up with a way to send auth requests to a different server. this is considered insecure and deprecated, so we're not covering it here ๐Ÿšซ. the client should treat TAC_PLUS_AUTHEN_STATUS_FOLLOW as TAC_PLUS_AUTHEN_STATUS_FAIL ๐Ÿ’€.

if the status is TAC_PLUS_AUTHEN_STATUS_ERROR, the host is basically saying it hit an unrecoverable error ๐Ÿ˜ญ. the authentication then goes on as if that host couldn't be reached at all. the data field may contain a message for an admin console or log ๐Ÿ“‹.

if the status is TAC_PLUS_AUTHEN_STATUS_RESTART, the auth sequence starts over with a fresh START packet from the client, with a new session Id and seq_no set to 1 ๐Ÿ”„. this REPLY is saying the current authen_type (from the START packet) isn't acceptable for this session, so the client may try a different authen_type ๐Ÿฆ‹.

if a client doesn't implement the TAC_PLUS_AUTHEN_STATUS_RESTART option, it MUST process the response as if the status was TAC_PLUS_AUTHEN_STATUS_FAIL. no exceptions, periodt ๐Ÿšจ

6. Authorization ๐Ÿ‘‘

okay authorization is the part where the server decides what a user is allowed to do ๐Ÿ”‘. generally, authentication comes first, though it's not mandatory that a client use the same service for authentication that it uses for authorization ๐Ÿคทโ€โ™€๏ธ. an authorization request might say the user isn't authenticated (we don't know who they are) ๐Ÿซฅ. in that case, it's up to the server, based on its configuration, to decide whether an unauthenticated user gets the services in question.

authorization isn't just yes or no, either. it can also customize the service for the particular user โœจ. a super common example is provisioning a shell session when someone first logs into a device to administer it ๐Ÿ’ป. the TACACS+ server might say yes to the service but put a time limit on that login shell โฐ. for a list of common arguments used in authorization, see "Authorization Arguments" (Section 8.2) ๐ŸŽ€.

in the TACACS+ protocol, an authorization is always a single pair of messages: a REQUEST from the client, then a REPLY from the server ๐Ÿ’Œ.

the authorization REQUEST message has a fixed set of fields that show how the user was authenticated, plus a variable set of arguments that describe the services and options being requested ๐Ÿงพ.

the REPLY has a variable set of response arguments (argument-value pairs) that can restrict or modify what the client does ๐Ÿ”’.


6.1. The Authorization REQUEST Packet Body ๐Ÿ’–

  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8
+----------------+----------------+----------------+----------------+
|  authen_method |    priv_lvl    |  authen_type   | authen_service |
+----------------+----------------+----------------+----------------+
|    user_len    |    port_len    |  rem_addr_len  |    arg_cnt     |
+----------------+----------------+----------------+----------------+
|   arg_1_len    |   arg_2_len    |      ...       |   arg_N_len    |
+----------------+----------------+----------------+----------------+
|   user ...
+----------------+----------------+----------------+----------------+
|   port ...
+----------------+----------------+----------------+----------------+
|   rem_addr ...
+----------------+----------------+----------------+----------------+
|   arg_1 ...
+----------------+----------------+----------------+----------------+
|   arg_2 ...
+----------------+----------------+----------------+----------------+
|   ...
+----------------+----------------+----------------+----------------+
|   arg_N ...
+----------------+----------------+----------------+----------------+

authen_method ๐Ÿงฉ

this lets the client say which authentication method it used to get the user's info ๐Ÿชช.

TAC_PLUS_AUTHEN_METH_NOT_SET := 0x00

TAC_PLUS_AUTHEN_METH_NONE := 0x01

TAC_PLUS_AUTHEN_METH_KRB5 := 0x02

TAC_PLUS_AUTHEN_METH_LINE := 0x03

TAC_PLUS_AUTHEN_METH_ENABLE := 0x04

TAC_PLUS_AUTHEN_METH_LOCAL := 0x05

TAC_PLUS_AUTHEN_METH_TACACSPLUS := 0x06

TAC_PLUS_AUTHEN_METH_GUEST := 0x08

TAC_PLUS_AUTHEN_METH_RADIUS := 0x10

TAC_PLUS_AUTHEN_METH_KRB4 := 0x11

TAC_PLUS_AUTHEN_METH_RCMD := 0x20

since this info isn't always verifiable, it MUST NOT be used in policy evaluation ๐Ÿ™…โ€โ™€๏ธ. LINE means a fixed password tied to the terminal line used to get access. LOCAL is a client-local user database. ENABLE is a command that authenticates to grant new privileges. TACACSPLUS is, of course, TACACS+ ๐Ÿฅฐ. GUEST is an unqualified guest authentication. RADIUS is the RADIUS authentication protocol. RCMD is auth through the Berkeley Unix R-command protocols. KRB5 [RFC4120] and KRB4 [KRB4] are Kerberos versions 5 and 4 ๐Ÿ”.

like we said, the client uses this field to show how it did the authentication. one option (TAC_PLUS_AUTHEN_METH_TACACSPLUS := 0x06) is TACACS+ itself, so the details of how the client did that one are in "Authentication" (Section 5) ๐Ÿ“–. for everything else, like KRB and RADIUS, TACACS+ wasn't involved in the authentication phase, and since those weren't done over TACACS+, they won't be documented here ๐Ÿ™ˆ. if you're a client implementer who needs details on those other protocols, check the respective Kerberos [RFC4120] and RADIUS [RFC3579] RFCs ๐Ÿ“š.

priv_lvl ๐Ÿ‘‘

this is used the same way as the priv_lvl field in the authentication request, and it's described in "Privilege Levels" (Section 9). it shows the user's current privilege level โญ.

authen_type ๐Ÿช„

this corresponds to the authen_type field in "Authentication" (Section 5). it says what kind of authentication was performed. if that info isn't available, the client sets authen_type to TAC_PLUS_AUTHEN_TYPE_NOT_SET := 0x00. this value is only valid in authorization and accounting requests ๐Ÿซง.

authen_service ๐Ÿ›Ž๏ธ

this is the same as the authen_service field in "Authentication" (Section 5). it shows which service the user authenticated through ๐ŸŽŸ๏ธ.

user, user_len ๐Ÿ™‹โ€โ™€๏ธ

this holds the user's account name. the user_len MUST indicate the length of the user field, in bytes ๐Ÿ“.

port, port_len ๐Ÿ”Œ

this matches the port field in "Authentication" (Section 5). the port_len shows how long the port field is, in bytes ๐Ÿงต.

rem_addr, rem_addr_len ๐ŸŒ

this matches the rem_addr field in "Authentication" (Section 5). the rem_addr_len indicates the length of the port field, in bytes ๐Ÿงญ.

arg_cnt ๐Ÿ”ข

this is the number of authorization arguments coming up next ๐ŸŽฏ.

arg_1 ... arg_N, arg_1_len .... arg_N_len ๐Ÿง

these arguments are the main stars of the authorization interaction ๐ŸŒŸ. in the request, they spell out exactly what's being requested. each argument is packed in as a single arg field (arg_1...arg_N) with its own length field, which tells you how many bytes that argument is ๐Ÿ“ฆ.

the authorization arguments in both the REQUEST and the REPLY are argument-value pairs. the argument and value live in one string, split by either a "=" (0X3D) or a "*" (0X2A) ๐Ÿ’ซ. the equals sign marks a mandatory argument, and the asterisk marks an optional one ๐Ÿซถ. for text encoding details, see "Treatment of Text Strings" (Section 3.7).

an argument name MUST NOT contain either separator ๐Ÿšซ. an argument value MAY contain the separators, though ๐Ÿช„. so you parse the argument until you hit the first separator, and everything after that is the value ๐Ÿง .

optional arguments are ones either side can ignore ๐Ÿคทโ€โ™€๏ธ. mandatory arguments mean the receiving side has to be able to handle them, so its implementation and config need to know how to act on them ๐Ÿ› ๏ธ. if the client gets a mandatory argument it can't handle, it MUST consider the authorization to have failed ๐Ÿ’€. the value part of an argument-value pair can be empty, so its length can be zero ๐Ÿซ™.

argument-value strings aren't NULL terminated. their length value is what marks where they end ๐Ÿ“. the max length of an argument-value string is 255 characters, and the min is two characters (one name-value character and the separator) ๐Ÿ“.

the arguments are super extensible, but a common core set of authorization arguments SHOULD be supported by clients and servers, and they're listed in "Authorization Arguments" (Section 8.2) ๐ŸŒˆ๐Ÿ’œ

6.2. The Authorization REPLY Packet Body

Okay bestie, this is the packet the server sends back after an authorization request ๐Ÿ’… The layout is the vibe here, so here it is in full ๐ŸŽ€

    1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8
   +----------------+----------------+----------------+----------------+
   |    status      |     arg_cnt    |         server_msg len          |
   +----------------+----------------+----------------+----------------+
   +            data_len             |    arg_1_len   |    arg_2_len   |
   +----------------+----------------+----------------+----------------+
   |      ...       |   arg_N_len    |         server_msg ...
   +----------------+----------------+----------------+----------------+
   |   data ...
   +----------------+----------------+----------------+----------------+
   |   arg_1 ...
   +----------------+----------------+----------------+----------------+
   |   arg_2 ...
   +----------------+----------------+----------------+----------------+
   |   ...
   +----------------+----------------+----------------+----------------+
   |   arg_N ...
   +----------------+----------------+----------------+----------------+

status โœจ

This field is the authorization verdict, the whole main character moment ๐Ÿ‘‘

  • TAC_PLUS_AUTHOR_STATUS_PASS_ADD := 0x01
    • If the status equals TAC_PLUS_AUTHOR_STATUS_PASS_ADD, then the arguments specified in the request are authorized and the arguments in the response MUST be applied according to the rules described above.
    • To approve the authorization with no modifications, the server sets the status to TAC_PLUS_AUTHOR_STATUS_PASS_ADD and the arg_cnt to 0.
  • TAC_PLUS_AUTHOR_STATUS_PASS_REPL := 0x02
    • If the status equals TAC_PLUS_AUTHOR_STATUS_PASS_REPL, then the client MUST use the authorization argument-value pairs (if any) in the response instead of the authorization argument-value pairs from the request.
  • TAC_PLUS_AUTHOR_STATUS_FAIL := 0x10
    • If the status equals TAC_PLUS_AUTHOR_STATUS_FAIL, then the requested authorization MUST be denied. ๐Ÿ™…โ€โ™€๏ธ
  • TAC_PLUS_AUTHOR_STATUS_ERROR := 0x11
    • A status of TAC_PLUS_AUTHOR_STATUS_ERROR indicates an error occurred on the server. For the differences between ERROR and FAIL, refer to "Session Completion" (Section 4.4). None of the arg values have any relevance if an ERROR is set and must be ignored. ๐Ÿ’€
  • TAC_PLUS_AUTHOR_STATUS_FOLLOW := 0x21
    • When the status equals TAC_PLUS_AUTHOR_STATUS_FOLLOW, the arg_cnt MUST be 0. In that case, the actions to be taken and the contents of the data field are identical to the TAC_PLUS_AUTHEN_STATUS_FOLLOW status for authentication. ๐Ÿฆ‹

server_msg, server_msg_len ๐Ÿ’ฌ

This is a string that may be presented to the user. The server_msg_len indicates the length of the server_msg field, in bytes. For details of text encoding, see "Treatment of Text Strings" (Section 3.7). ๐ŸŒธ

data, data_len ๐Ÿ—‚๏ธ

This is a string that may be presented on an administrative display, console, or log. The decision to present this message is client specific. The data_len indicates the length of the data field, in bytes. For details of text encoding, see "Treatment of Text Strings" (Section 3.7). ๐Ÿ“

arg_cnt ๐Ÿ”ข

This represents the number of authorization arguments to follow.

arg_1 ... arg_N, arg_1_len .... arg_N_len ๐Ÿงฉ

The arguments describe the specifics of the authorization that is being requested. For details of the content of the args, refer to "Authorization Arguments" (Section 8.2). Each argument is encoded in the packet as a single arg field (arg_1 ... arg_N) with a corresponding length field (which indicates the length of each argument in bytes). โœจ


7. Accounting ๐Ÿ“’

Accounting is typically the third action after authentication and authorization. But again, neither authentication nor authorization is required. Accounting is the action of recording what a user is doing and/or has done. Accounting in TACACS+ can serve two purposes: it may be used as an auditing tool for security services, and it may also be used to account for services used such as in a billing environment. To this end, TACACS+ supports three types of accounting records: Start records indicate that a service is about to begin, Stop records indicate that a service has just terminated, and Update records are intermediate notices that indicate that a service is still being performed. TACACS+ accounting records contain all the information used in the authorization records and also contain accounting-specific information such as start and stop times (when appropriate) and resource usage information. A list of accounting arguments is defined in "Accounting Arguments" (Section 8.3). ๐Ÿงพ

7.1. The Account REQUEST Packet Body ๐Ÿ“จ

    1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8
   +----------------+----------------+----------------+----------------+
   |      flags     |  authen_method |    priv_lvl    |  authen_type   |
   +----------------+----------------+----------------+----------------+
   | authen_service |    user_len    |    port_len    |  rem_addr_len  |
   +----------------+----------------+----------------+----------------+
   |    arg_cnt     |   arg_1_len    |   arg_2_len    |      ...       |
   +----------------+----------------+----------------+----------------+
   |   arg_N_len    |    user ...
   +----------------+----------------+----------------+----------------+
   |   port ...
   +----------------+----------------+----------------+----------------+
   |   rem_addr ...
   +----------------+----------------+----------------+----------------+
   |   arg_1 ...
   +----------------+----------------+----------------+----------------+
   |   arg_2 ...
   +----------------+----------------+----------------+----------------+
   |   ...
   +----------------+----------------+----------------+----------------+
   |   arg_N ...
   +----------------+----------------+----------------+----------------+

flags ๐Ÿšฉ

This holds bitmapped flags.

Valid values are:

  • TAC_PLUS_ACCT_FLAG_START := 0x02
  • TAC_PLUS_ACCT_FLAG_STOP := 0x04
  • TAC_PLUS_ACCT_FLAG_WATCHDOG := 0x08

All other fields are defined in "Authentication" (Section 5) and "Authorization" (Section 6) and have the same semantics. They provide details for the conditions on the client, and authentication context, so that these details may be logged for accounting purposes. ๐Ÿ“

See "Accounting Arguments" (Section 8.3) for the dictionary of arguments relevant to accounting. ๐Ÿ“–

7.2. The Accounting REPLY Packet Body ๐Ÿ“ฌ

The purpose of accounting is to record the action that has occurred on the client. The server MUST reply with success only when the accounting request has been recorded. If the server did not record the accounting request, then it MUST reply with ERROR. ๐Ÿซถ

    1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8
   +----------------+----------------+----------------+----------------+
   |         server_msg len          |            data_len             |
   +----------------+----------------+----------------+----------------+
   |     status     |         server_msg ...
   +----------------+----------------+----------------+----------------+
   |     data ...
   +----------------+

status ๐Ÿ

This is the return status.

Values are:

  • TAC_PLUS_ACCT_STATUS_SUCCESS := 0x01
  • TAC_PLUS_ACCT_STATUS_ERROR := 0x02
  • TAC_PLUS_ACCT_STATUS_FOLLOW := 0x21
    • When the status equals TAC_PLUS_ACCT_STATUS_FOLLOW, the actions to be taken and the contents of the data field are identical to the TAC_PLUS_AUTHEN_STATUS_FOLLOW status for authentication. ๐Ÿฆ‹

server_msg, server_msg_len ๐Ÿ’ฌ

This is a string that may be presented to the user. The server_msg_len indicates the length of the server_msg field, in bytes. For details of text encoding, see "Treatment of Text Strings" (Section 3.7). ๐ŸŒธ

data, data_len ๐Ÿ—‚๏ธ

This is a string that may be presented on an administrative display, console, or log. The decision to present this message is client specific. The data_len indicates the length of the data field, in bytes. For details of text encoding, see "Treatment of Text Strings" (Section 3.7). ๐Ÿ“

TACACS+ accounting is intended to record various types of events on clients, for example: login sessions, command entry, and others as required by the client implementation. These events are collectively referred to in "The Draft" [THE-DRAFT] as "tasks". ๐ŸŽฏ

The TAC_PLUS_ACCT_FLAG_START flag indicates that this is a start accounting message. Start messages will only be sent once when a task is started. The TAC_PLUS_ACCT_FLAG_STOP indicates that this is a stop record and that the task has terminated. The TAC_PLUS_ACCT_FLAG_WATCHDOG flag means that this is an update record. ๐Ÿถ

    +==========+======+=======+=============+=========================+
    | Watchdog | Stop | Start | Flags & 0xE | Meaning                 |
    +==========+======+=======+=============+=========================+
    | 0        | 0    | 0     | 0           | INVALID                 |
    +----------+------+-------+-------------+-------------------------+
    | 0        | 0    | 1     | 2           | Start Accounting Record |
    +----------+------+-------+-------------+-------------------------+
    | 0        | 1    | 0     | 4           | Stop Accounting Record  |
    +----------+------+-------+-------------+-------------------------+
    | 0        | 1    | 1     | 6           | INVALID                 |
    +----------+------+-------+-------------+-------------------------+
    | 1        | 0    | 0     | 8           | Watchdog, no update     |
    +----------+------+-------+-------------+-------------------------+
    | 1        | 0    | 1     | A           | Watchdog, with update   |
    +----------+------+-------+-------------+-------------------------+
    | 1        | 1    | 0     | C           | INVALID                 |
    +----------+------+-------+-------------+-------------------------+
    | 1        | 1    | 1     | E           | INVALID                 |
    +----------+------+-------+-------------+-------------------------+

                   Table 2: Summary of Accounting Packets

The START and STOP flags are mutually exclusive. โŒ

The WATCHDOG flag is used by the client to communicate ongoing status of a long-running task. Update records are sent at the client's discretion. The frequency of the update depends upon the intended application: a watchdog to provide progress indication will require higher frequency than a daily keep-alive. When the WATCHDOG flag is set along with the START flag, it indicates that the update record provides additional or updated arguments from the original START record. If the START flag is not set, then this indicates only that task is still running, and no new information is provided (servers MUST ignore any arguments). The STOP flag MUST NOT be set in conjunction with the WATCHDOG flag. โฑ๏ธ

The server MUST respond with TAC_PLUS_ACCT_STATUS_ERROR if the client requests an INVALID option. ๐Ÿšจ


8. Argument-Value Pairs ๐Ÿง

TACACS+ is intended to be an extensible protocol. The arguments used in Authorization and Accounting are not limited by this document. Some arguments are defined below for common use cases. Clients MUST use these arguments when supporting the corresponding use cases. ๐ŸŒˆ

8.1. Value Encoding

Okay bestie, so every argument value gets encoded as a string ๐Ÿ’–. For the text-encoding details, peep "Treatment of Text Strings" (Section 3.7) โœจ. The following type representations SHOULD be followed ๐ŸŽ€.

Numeric

All numeric values in an argument-value string are written as decimal numbers, unless otherwise stated ๐Ÿ”ข. Every argument carries a length field, so TACACS+ implementations MUST verify that they can accommodate the lengths of numeric arguments before they try to process them ๐Ÿซถ. If the length can't be accommodated, the argument MUST be regarded as not handled, and the logic in "Authorization" (Section 6.1) about processing arguments MUST be applied ๐Ÿ˜ญ.

Boolean

All Boolean arguments are encoded with the values "true" or "false" โœจ.

IP-Address

It is recommended that hosts be specified as an IP address so as to avoid any ambiguities ๐ŸŒธ. For text encoding details, see "Treatment of Text Strings" (Section 3.7) again ๐Ÿ’…. IPv4 addresses are written as octet numerics separated by dots ('.') ๐Ÿงš. The IPv6 text representation is defined in [RFC5952] ๐Ÿฆ‹.

Date Time

Absolute date/times are specified in seconds since the epoch, 12:00am, January 1, 1970 ๐Ÿ•›. The time zone MUST be UTC unless a time zone argument is specified ๐ŸŒ.

String

Lots of values have no specific type representation, so they're just interpreted as plain strings ๐Ÿ“.

Empty Values

Arguments can be submitted with no value. In that case they consist of the name plus the mandatory or optional separator ๐Ÿ’œ. For example, the argument cmd, which has no value, is sent as the four-character string cmd= ๐Ÿ™ˆ.


8.2. Authorization Arguments

service (String)

The primary service. Specifying a service argument indicates that this is a request for authorization or accounting of that service ๐ŸŽฏ. For example: "shell", "tty-server", "connection", "system" and "firewall"; others may be chosen for the required application ๐ŸŒˆ. This argument MUST always be included ๐Ÿ‘‘.

protocol (String)

A field that may be used to indicate a subset of a service ๐Ÿฆ‹.

cmd (String)

A shell (exec) command. This is the command name of the command that is to be run ๐Ÿ’ป. The cmd argument MUST be specified if service equals "shell" ๐Ÿ”ฅ.

Authorization of shell commands is a super common use case for the TACACS+ protocol ๐Ÿ’…. Command Authorization generally takes one of two forms: session based or command based ๐Ÿซถ.

For session-based shell authorization, the cmd argument will have an empty value ๐ŸŒธ. The client figures out which commands are allowed in a session based on the arguments present in the authorization โœจ.

In command-based authorization, the client asks the server to decide whether a command is allowed by making an authorization request for each command ๐Ÿงš. The cmd argument will have the command name as its value ๐Ÿ’–.

cmd-arg (String)

An argument to a shell (exec) command. This is an argument for the shell command that is to be run ๐ŸŽ€. Multiple cmd-arg arguments may be specified, and they are order dependent ๐Ÿ”ข.

acl (Numeric)

A number representing a connection access list. Only applicable to session-based shell authorization ๐ŸŒ. For details of text encoding, see "Treatment of Text Strings" (Section 3.7) ๐Ÿ’….

inacl (String)

The identifier (name) of an interface input access list ๐Ÿฆ‹. For details of text encoding, see "Treatment of Text Strings" (Section 3.7) โœจ.

outacl (String)

The identifier (name) of an interface output access list ๐ŸŒˆ. For details of text encoding, see "Treatment of Text Strings" (Section 3.7) ๐Ÿซถ.

addr (IP-Address)

A network address ๐Ÿ“.

addr-pool (String)

The identifier of an address pool that the client can assign an address from ๐ŸŠ.

timeout (Numeric)

An absolute timer for the connection (in minutes). A value of zero indicates no timeout โฐ.

idletime (Numeric)

An idle-timeout for the connection (in minutes). A value of zero indicates no timeout ๐Ÿ˜ด.

autocmd (String)

An auto-command to run. Only applicable to session-based shell authorization โšก.

noescape (Boolean)

Stops the user from using an escape character. Only applicable to session-based shell authorization ๐Ÿšซ.

nohangup (Boolean)

Boolean. Do not disconnect after an automatic command. Only applicable to session-based shell authorization ๐Ÿ™…โ€โ™€๏ธ.

priv-lvl (Numeric)

The privilege level to be assigned. Please refer to "Privilege Levels" (Section 9) ๐Ÿ‘‘.


8.3. Accounting Arguments

The following arguments are defined for TACACS+ accounting only ๐Ÿ“Š. They MUST precede any argument-value pairs that are defined in "Authorization" (Section 6) ๐ŸŽ€.

task_id (String)

Start and stop records for the same event MUST have matching task_id argument values ๐Ÿ”—. The client MUST ensure that active task_ids are not duplicated ๐Ÿ˜ค. A client MUST NOT reuse a task_id in a start record until it has sent a stop record for that task_id ๐Ÿ›‘. Servers MUST NOT make assumptions about the format of a task_id ๐Ÿ™ˆ.

Heads up: getting task_id right is what lets start and stop records line up, so don't wing it ๐Ÿ’€.

start_time (Date Time)

The time the action started (in seconds since the epoch) ๐Ÿ•ฐ๏ธ.

stop_time (Date Time)

The time the action stopped (in seconds since the epoch) โน๏ธ.

elapsed_time (Numeric)

The elapsed time in seconds for the action โŒ›.

timezone (String)

The time zone abbreviation for all timestamps included in this packet ๐ŸŒ. A database of time zones is maintained in [TZDB] ๐Ÿ—บ๏ธ.

event (String)

Used only when service=system ๐Ÿ–ฅ๏ธ. Current values are "net_acct", "cmd_acct", "conn_acct", "shell_acct", "sys_acct", and "clock_change" โœจ. These indicate system-level changes ๐Ÿ”ง. The flags field SHOULD indicate whether the service started or stopped ๐Ÿšฆ.

reason (String)

Comes with an event argument. It describes why the event occurred ๐Ÿค”.

bytes (Numeric)

The number of bytes transferred by this action ๐Ÿ“ฆ.

bytes_in (Numeric)

The number of bytes transferred by this action from the endstation to the client port โฌ‡๏ธ.

bytes_out (Numeric)

The number of bytes transferred by this action from the client to the endstation port โฌ†๏ธ.

paks (Numeric)

The number of packets transferred by this action ๐Ÿ“จ.

paks_in (Numeric)

The number of input packets transferred by this action from the endstation to the client port ๐Ÿ“ฅ.

paks_out (Numeric)

The number of output packets transferred by this action from the client port to the endstation ๐Ÿ“ค.

err_msg (String)

A string describing the status of the action ๐Ÿšจ. For details of text encoding, see "Treatment of Text Strings" (Section 3.7) ๐Ÿ’….

Where the TACACS+ deployment is used to support the Device Administration use case, it's often required to log all commands entered into client devices ๐Ÿ“. To make this work, TACACS+ client devices MUST be configured to send an accounting start packet for every command entered, no matter how the commands were authorized ๐Ÿงพ. These "Command Accounting" packets MUST include the "service" and "cmd" arguments, plus the "cmd-arg" arguments detailed in Section 8.2 if needed ๐Ÿ’œ.


9. Privilege Levels

The TACACS+ protocol supports flexible authorization schemes through the extensible arguments ๐ŸŒŸ.

The privilege levels scheme is built into the protocol, and it has been extensively used as an option for session-based shell authorization ๐Ÿ‘‘. Privilege levels are ordered values from 0 to 15, with each level being a superset of the next lower value ๐Ÿชœ. The client's configuration and implementation map actions (like the permission to run specific commands) to different privilege levels ๐Ÿ—‚๏ธ. How commands get allocated to privilege levels is highly dependent on the deployment ๐Ÿ—๏ธ. Common allocations are as follows ๐Ÿ’…:

  • TAC_PLUS_PRIV_LVL_MIN := 0x00. The level normally allocated to an unauthenticated session ๐Ÿ™‹โ€โ™€๏ธ.
  • TAC_PLUS_PRIV_LVL_USER := 0x01. The level normally allocated to a regular authenticated session ๐Ÿง‘โ€๐Ÿ’ป.
  • TAC_PLUS_PRIV_LVL_ROOT := 0x0f. The level normally allocated to a session authenticated by a highly privileged user, to allow commands with significant system impact ๐Ÿงจ.
  • TAC_PLUS_PRIV_LVL_MAX := 0x0f. The highest privilege level ๐Ÿ†.

A privilege level can be assigned to a shell (exec) session when it starts ๐Ÿš€. The client will permit the actions associated with this level to be executed โœ…. The server returns this privilege level in a session-based shell authorization (when "service" equals "shell" and "cmd" is empty) ๐Ÿ“ฌ. When a user needs to perform actions mapped to a higher privilege level, the client can start an ENABLE-type reauthentication ๐Ÿ”. The client will insert the required privilege level into the authentication header for ENABLE authentication requests ๐ŸŽซ.

The use of privilege levels to determine session-based access to commands and resources is not mandatory for clients ๐Ÿ™Œ. Although the privilege-level scheme is widely supported, its lack of flexibility, in requiring a single monotonic hierarchy of permissions, means that other session-based command authorization schemes have evolved ๐ŸŒฑ. However, it's still common enough that it SHOULD be supported by servers ๐Ÿซถ.


10. Security Considerations

"The Draft" [THE-DRAFT] from 1998 did not address all of the key security concerns that are considered when designing modern standards ๐Ÿ˜ฌ. This section addresses known limitations and concerns that will impact the overall security of the protocol, and of the systems where this protocol is deployed to manage central authentication, authorization, or accounting for network Device Administration ๐Ÿšจ. Please take this part seriously, bestie ๐Ÿ”’.

Multiple implementations of the protocol described in "The Draft" [THE-DRAFT] have been deployed ๐Ÿงฉ. Because the protocol was never standardized, current implementations may be incompatible in non-obvious ways, and that gives rise to additional security risks ๐Ÿ’€. This section does not claim to enumerate all possible security vulnerabilities โš ๏ธ.

10.1. General Security of the Protocol

okay bestie, this section is the reality check ๐Ÿ’€ TACACS+ does NOT have a security mechanism that meets modern standards. Real talk, the stuff it has should be called "obfuscation," not "encryption," because it gives you no meaningful integrity, privacy, or replay protection ๐Ÿ™ˆ Assume that anyone who can see the data stream can read and modify every TACACS+ packet. No cap. If you don't mitigate, these risks are on the table:

  • Accounting information may be modified by the man-in-the-middle attacker, making such logs unsuitable and not trustable for auditing purposes.
  • Invalid or misleading values may be inserted by the man-in-the-middle attacker in various fields at known offsets to try and circumvent the authentication or authorization checks even inside the obfuscated body.

Even though the protocol gives you some transport privacy, it's still vulnerable to at least these attacks ๐Ÿ˜ญ

  • Brute-force attacks exploiting increased efficiency of MD5 digest computation.
  • Known plaintext attacks that may decrease the cost of brute-force attacks.
  • Chosen plaintext attacks that may decrease the cost of a brute-force attacks.
  • No forward secrecy.

Even though, to the best knowledge of the authors, this method of encryption wasn't rigorously tested, there's enough info out there that it's best called "obfuscation" and not "encryption" ๐Ÿฆ‹

So, for these reasons, anyone deploying TACACS+ MUST limit access to known clients and MUST control the security of the entire transmission path. ๐Ÿšจ If an attacker can guess the key or otherwise break the obfuscation, they get unrestricted and undetected access to all TACACS+ traffic. Deploying a centralized AAA system like TACACS+ on a secured transport is essential to managing that risk, periodt ๐Ÿ‘‘

The following parts of this section list only the session-specific risks on top of the general risk from bare obfuscation and lack of integrity checking โœจ

10.2. Security of Authentication Sessions

Authentication sessions SHOULD be run over a secure transport (see "TACACS+ Best Practices" (Section 10.5)), because a man-in-the-middle attack may completely subvert them ๐Ÿ˜ฑ Even CHAP, which may be considered resistant to password interception, is unsafe, because it doesn't protect the username from a trivial man-in-the-middle attack ๐Ÿซถ

This document deprecates the redirection mechanism using the TAC_PLUS_AUTHEN_STATUS_FOLLOW option, which was included in "The Draft." ๐Ÿ’… As part of that process, the secret key for a new server was sent to the client. Sending secret keys out in the open means that once one session is broken, the attacker might be able to use that key to attack connections to other servers. Literally scary. This mechanism MUST NOT be used in modern deployments. It MUST NOT be used outside a secured deployment.

10.3. Security of Authorization Sessions

Authorization sessions SHOULD be run over a secure transport (see "TACACS+ Best Practices" (Section 10.5)), since it's trivial to run a successful man-in-the-middle attack that changes well-known plaintext in either requests or responses ๐ŸŒธ

Here's an example, bestie. It's not unusual in real deployments to authorize all commands entered on the device's local serial port (a console port), since that port is usually considered secure because the device sits in a physically secure location ๐Ÿข Now imagine an admin sets up authorization to allow every command typed on a local console so they can troubleshoot. That would give full command access to any attacker who could change authen_method from TAC_PLUS_AUTHEN_METH_TACACSPLUS to TAC_PLUS_AUTHEN_METH_LINE ๐Ÿšจ The protocol's own obfuscation wouldn't help much here, because:

  • A lack of integrity means that any byte in the payload may be changed without either side detecting the change.
  • Known plaintext means that an attacker would know with certainty which octet is the target of the attack (in this case, first octet after the header).
  • In combination with known plaintext, the attacker can determine with certainty the value of the crypto-pad octet used to obfuscate the original octet.

10.4. Security of Accounting Sessions

Accounting sessions SHOULD be run over a secure transport (see "TACACS+ Best Practices" (Section 10.5)) ๐Ÿงพ Accounting isn't directly involved in authentication or authorization decisions on the device, but man-in-the-middle attackers can still do any of the following:

  • Replace accounting data with new valid values or garbage that can confuse auditors or hide information related to their authentication and/or authorization attack attempts.
  • Try and poison an accounting log with entries designed to make systems behave in unintended ways (these systems could be TACACS+ servers and any other systems that would manage accounting entries).

On top of these direct manipulations, different client implementations pass along different fidelity of accounting data. Some vendors have been observed in the wild passing sensitive data like passwords, encryption keys, and the like into the accounting log ๐Ÿ˜ญ Because there's no strong encryption with perfect forward secrecy, that data may be revealed later, leading to a security incident. Yikes.

10.5. TACACS+ Best Practices

Based on the security issues described above, a network administrator MUST NOT rely on the obfuscation of the TACACS+ protocol ๐Ÿ™…โ€โ™€๏ธ TACACS+ MUST be used within a secure deployment. TACACS+ MUST be deployed over networks that ensure privacy and integrity of the communication, and MUST be deployed over a network that is separated from other traffic. If you don't do this, your overall network security takes the hit ๐Ÿ’”

The following recommendations restrict how the protocol is applied. These restrictions were not imposed in "The Draft." New implementations, and upgrades of current implementations, MUST implement these recommendations. Vendors SHOULD provide mechanisms to help administrators hit these best practices ๐ŸŽ€

10.5.1. Shared Secrets

TACACS+ servers and clients MUST treat shared secrets as sensitive data to be managed securely, the same way you'd treat other sensitive data like identity credential information ๐Ÿ” TACACS+ servers MUST NOT leak sensitive data.

For example:

  • TACACS+ servers MUST NOT expose shared secrets in logs.
  • TACACS+ servers MUST allow a dedicated secret key to be defined for each client.
  • TACACS+ server management systems MUST provide a mechanism to track secret key lifetimes and notify administrators to update them periodically. TACACS+ server administrators SHOULD change secret keys at regular intervals.
  • TACACS+ servers SHOULD warn administrators if secret keys are not unique per client.
  • TACACS+ server administrators SHOULD always define a secret for each client.
  • TACACS+ servers and clients MUST support shared keys that are at least 32 characters long.
  • TACACS+ servers MUST support policy to define minimum complexity for shared keys.
  • TACACS+ clients SHOULD NOT allow servers to be configured without a shared secret key or shared key that is less than 16 characters long.
  • TACACS+ server administrators SHOULD configure secret keys of a minimum of 16 characters in length.

10.5.2. Connections and Obfuscation

TACACS+ servers MUST allow the definition of individual clients. The servers MUST only accept network connection attempts from these defined known clients ๐Ÿšช

TACACS+ servers MUST reject connections that have TAC_PLUS_UNENCRYPTED_FLAG set. There MUST always be a shared secret set on the server for the client requesting the connection.

If an invalid shared secret is detected when processing packets for a client, TACACS+ servers MUST NOT accept any new sessions on that connection. TACACS+ servers MUST terminate the connection once any sessions that were previously established with a valid shared secret on that connection have completed ๐Ÿงน

TACACS+ clients MUST NOT set TAC_PLUS_UNENCRYPTED_FLAG. Clients MUST be implemented in a way that requires explicit configuration to enable the use of TAC_PLUS_UNENCRYPTED_FLAG. This option MUST NOT be used when the client is in production ๐Ÿšซ

When a TACACS+ client receives responses from servers where:

  • the response packet was received from the server configured with a shared key, but the packet has TAC_PLUS_UNENCRYPTED_FLAG set, and
  • the response packet was received from the server configured not to use obfuscation, but the packet has TAC_PLUS_UNENCRYPTED_FLAG not set,

the TACACS+ client MUST close the TCP session, and process the response the same way it would process a TAC_PLUS_AUTHEN_STATUS_FAIL (authentication sessions) or TAC_PLUS_AUTHOR_STATUS_FAIL (authorization sessions) ๐Ÿ’ฅ

10.5.3. Authentication

To help TACACS+ admins pick stronger authentication options, TACACS+ servers MUST allow the administrator to configure the server to only accept challenge/response options for authentication (TAC_PLUS_AUTHEN_TYPE_CHAP or TAC_PLUS_AUTHEN_TYPE_MSCHAP or TAC_PLUS_AUTHEN_TYPE_MSCHAPV2 for authen_type) ๐Ÿ”’

TACACS+ server administrators SHOULD enable the option mentioned in the previous paragraph. TACACS+ server deployments SHOULD only enable other options (such as TAC_PLUS_AUTHEN_TYPE_ASCII or TAC_PLUS_AUTHEN_TYPE_PAP) when it's unavoidable due to requirements of identity/password systems.

TACACS+ server administrators SHOULD NOT allow the same credentials to be applied in challenge-based (TAC_PLUS_AUTHEN_TYPE_CHAP or TAC_PLUS_AUTHEN_TYPE_MSCHAP or TAC_PLUS_AUTHEN_TYPE_MSCHAPV2) and non-challenge-based authen_type options. The insecurity of the latter will compromise the security of the former, so keep them separate ๐Ÿ™…โ€โ™€๏ธ

TAC_PLUS_AUTHEN_SENDAUTH and TAC_PLUS_AUTHEN_SENDPASS options mentioned in "The Draft" SHOULD NOT be used due to their security implications. TACACS+ servers SHOULD NOT implement them. If they must be implemented, the servers MUST default to the options being disabled and MUST warn the administrator that these options are not secure โš ๏ธ

10.5.4. Authorization

The authorization and accounting features are meant to be extensible and flexible โœจ There's a base dictionary defined in this document, but deployments can extend it by using new argument names. The cost of that flexibility is that administrators and implementers MUST ensure that the argument and value pairs shared between clients and servers have consistent interpretation. Mismatched interpretations are a recipe for chaos ๐ŸŒ€

TACACS+ clients that receive an unrecognized mandatory argument MUST evaluate the server response as if they had received TAC_PLUS_AUTHOR_STATUS_FAIL ๐Ÿซฃ

10.5.5. Redirection Mechanism ๐Ÿฆ‹

okay so bestie, this one is a whole drama ๐Ÿ˜ญ "The Draft" (that's what the original calls it, in quotes ๐Ÿ’…) described a redirection mechanism, TAC_PLUS_AUTHEN_STATUS_FOLLOW. And it's giving insecure. It's really hard to secure ๐Ÿ’€ The option to send secret keys in the server list is especially risky, because it can reveal client shared secrets. Not it. ๐Ÿ™ˆ

TACACS+ servers MUST deprecate the redirection mechanism. ๐Ÿšซ

If the redirection mechanism is implemented, then TACACS+ servers MUST disable it by default and MUST warn TACACS+ server administrators that it must only be enabled within a secure deployment due to the risks of revealing shared secrets. ๐Ÿ”

TACACS+ clients SHOULD deprecate this feature by treating TAC_PLUS_AUTHEN_STATUS_FOLLOW as TAC_PLUS_AUTHEN_STATUS_FAIL. ๐Ÿงนโœจ


11. IANA Considerations ๐ŸŒธ

No IANA stuff in this one, bestie ๐ŸŽ€ This document has no IANA actions.

12. References ๐Ÿ“š

12.1. Normative References

12.2. Informative References

  • [KRB4] Miller, S., Neuman, C., Schiller, J., and J. Saltzer, "Section E.2.1: Kerberos Authentication and Authorization System", MIT Project Athena, Cambridge, Massachusetts, December 1987.
  • [THE-DRAFT] Carrel, D. and L. Grant, "The TACACS+ Protocol Version 1.78", Work in Progress, Internet-Draft, draft-grant-tacacs-02, January 1997, https://tools.ietf.org/html/draft-grant-tacacs-02.
  • [TZDB] Eggert, P. and A. Olson, "Sources for Time Zone and Daylight Saving Time Data", 1987, https://www.iana.org/time-zones.

Acknowledgements ๐Ÿซถ

The authors want to give a big thank-you to these reviewers, whose comments and contributions made this document so much better โœจ Alan DeKok, Alexander Clouter, Chris Janicki, Tom Petch, Robert Drake, and John Heasley, among many others ๐Ÿ’œ

The authors especially want to thank Alan DeKok ๐Ÿ‘‘ He brought significant insights and recommendations on all aspects of the document and the protocol. Alan has put in a ton of time and effort to help improve the document, spotting weaknesses and suggesting fixes. Legend ๐Ÿ”ฅ

The authors also want to thank the support from the OPSAWG Chairs and advisors, especially Joe Clarke ๐ŸŒˆ

Authors' Addresses ๐Ÿงš

Thorsten Dahm Google Inc. 1600 Amphitheatre Parkway Mountain View, CA 94043 United States of America

Email: thorstendlux@google.com

Andrej Ota Google Inc. 1600 Amphitheatre Parkway Mountain View, CA 94043 United States of America

Email: andrej@ota.si

Douglas C. Medway Gash Cisco Systems, Inc. 170 West Tasman Dr. San Jose, CA 95134 United States of America

Email: dcmgash@cisco.com

David Carrel IPsec Research

Email: carrel@ipsec.org

Lol Grant

Email: lol.grant@gmail.com ๐ŸŽ€

๐Ÿ“ฆ where this page comes from