skip to content

A TACACS+ server answers a device's login with a REPLY status of ERROR rather than FAIL - what must the device do next?

level: seniorimportance: must knowfreq 46%

answer

  1. not every non-acceptance is a denial
  2. did the server finish deciding?
  3. ERROR is handled as unreachable
  4. FAIL ends the list, ERROR continues it
  5. same pair in the authorization exchange

basics

~20 s

An ERROR reply is not a denial: the server did not complete its processing, so RFC 8907 has the device behave as if that server could not be connected to and move to the next method. Only FAIL denies.

solid answer

~50 s

RFC 8907 Section 4.4 separates the two outcomes, and the distinction is what makes a method list work at all. `TAC_PLUS_AUTHEN_STATUS_FAIL` means the server completed its processing and the answer is no: the device applies the denial and stops walking the list. `TAC_PLUS_AUTHEN_STATUS_ERROR` means processing did not complete - a back-end lookup broke, the server is out of resources, something is wrong - so there is no result to apply, and the device must behave exactly as if it could not connect to that server, which is what sends it on to the next host or the next method. The authorization exchange carries the same pair. Collapsing the two is how a transient server fault presents as a rejected login to every engineer at once, or how a genuine denial quietly gets a second opinion from another method.

code

pseudocode · 17 lines
pseudocode
for each method in login_method_list, in order:

    reply := ask(method)          # may be silence

    if reply is none after timeout:
        continue                  # no decision -> next method

    if reply.status is PASS:
        grant; stop               # decided

    if reply.status is FAIL:
        deny; stop                # decided, and the answer is no

    if reply.status is ERROR:
        continue                  # processing did not complete -> next method

# list exhausted: no method returned a decision

go deeper

for a junior

Remember that a reply which is not an acceptance is not automatically a refusal - the protocol distinguishes a server that decided no from a server that could not decide at all.

for a middle

Explain that FAIL means processing completed and the denial is applied, while ERROR means it did not, so the device behaves as though that server were unreachable and moves on.

for a senior

Diagnose both collapses: a transient back-end fault presenting as a rejected login estate-wide, and a genuine refusal falling through to another method and never being enforced.

for a principal

Judge how much of an estate's administrative access should rest on a single decision plane, and what a standards-track statement of this rule is worth across a mixed fleet.

## Two outcomes that are not two shades of the same thing A TACACS+ REPLY that is not an acceptance can mean two entirely different things, and RFC 8907 Section 4.4 is explicit about which is which. - **FAIL** means the device-administration server **completed its processing** and the answer is no. There is a decision, the device applies it, and the walk down the method list ends there. - **ERROR** means processing **did not complete**. The server is not saying no; it is saying it has nothing to say. RFC 8907 has the client behave as if the server could not be connected to at all, which is what carries the request on to the next host or the next method. Everything a method list does depends on this. A list of methods is only meaningful if there is a rule for when to move down it, and this is that rule. ## What the device does with each outcome | Outcome | Did the server decide? | What the device applies | Next method tried? | |---|---|---|---| | REPLY status PASS | yes | the acceptance | no | | REPLY status FAIL | yes | the denial | no | | REPLY status ERROR | no | nothing | yes | | no reply before the entry's timeout | no | nothing | yes | The last two rows are deliberately identical in their consequence. An errored reply and silence are the same event as far as the list walk is concerned, which is precisely the rule: an ERROR is handled as unreachability. They are *not* identical in the statistics - an errored reply is a message received and raises `errors-received`, while silence raises `connection-timeouts` - and that is how an operator tells them apart after the fact. ## The two ways a deployment collapses the distinction 1. **ERROR treated as FAIL.** A dependency of the device-administration server breaks - an identity back end, a disk, a resource limit - and every device that asks receives what it reads as a completed denial. It stops walking its list. Nothing later in the list is reached, and every engineer at every unstaffed site sees a rejected login while the servers appear to be up and answering. The device's own counters show connections opening and messages arriving, so the shape of the failure argues against the correct diagnosis. 2. **FAIL treated as ERROR.** A genuine denial is read as no-decision, so the device falls through to a later method and asks something else. The refusal the central server issued is never enforced, and the audit record of the decision and the outcome on the device disagree. Both failures are silent, both look like configuration working as intended, and both are the direct consequence of one word. ## Where the distinction appears Each of the three TACACS+ exchanges has its own status enumeration, and each of them has an ERROR member: - authentication REPLY status carries `TAC_PLUS_AUTHEN_STATUS_FAIL` and `TAC_PLUS_AUTHEN_STATUS_ERROR` among its values; - authorization REPLY status carries `TAC_PLUS_AUTHOR_STATUS_FAIL` and `TAC_PLUS_AUTHOR_STATUS_ERROR` alongside its two PASS variants; - the accounting exchange has its own status set with an error member of its own. Because the three are separate exchanges, they fall through separately. A server can be answering authentication cleanly and erroring on authorization, in which case logins succeed and command authorization walks on to whatever the command list names next. An engineer reporting *"I can log in but nothing I type is accepted"*, or the reverse, is describing one exchange erroring while another does not. ## What the rule settles, and what it does not - It settles **whether the next method is tried at all**. That is a protocol rule, not local policy, and it is the same on every conforming device. - It does not settle **what the next method should be**. The contents and order of the list are a configuration decision made per estate. - It does not settle what happens when the list runs out with nobody having decided; the exchange has ended and the device is on its own. - It is unchanged by transport. RFC 9887's TLS 1.3 transport protects the body differently; it does not alter what an ERROR reply means or what the device does with it. The practical grip on it is a single question asked of every non-acceptance: *did the server finish deciding?* If it did, the answer is binding and the walk is over. If it did not, there is no answer to be bound by, and the device is entitled - required, in fact - to look elsewhere.

  • How does a device tell an ERROR reply apart from a server that never answered at all?
    For walking the list it does not need to - RFC 8907 has it treat an ERROR exactly as it treats an unreachable server. The difference shows up afterwards in the statistics: an errored reply is a message received and raises `errors-received`, while silence raises `connection-timeouts` on that entry.
  • Does the same distinction apply to the authorization exchange?
    Yes. Authorization REPLY status carries `TAC_PLUS_AUTHOR_STATUS_FAIL` and `TAC_PLUS_AUTHOR_STATUS_ERROR` alongside its two PASS variants, with the same meaning: FAIL is a completed refusal the device applies, ERROR is no decision, so the device falls through to the next method named for that service.
  • What goes wrong if a broken back-end lookup is reported as FAIL instead of ERROR?
    Every device that asks receives a completed denial and stops walking its list, so one dependency's fault presents to every engineer as a rejected login. Nothing later in the list is reached, and the device's counters show messages arriving normally, which argues against the true diagnosis.

A phone that rings out and a phone answered with "no" are not the same event. ERROR is the ring-out - nobody decided, so trying another number is reasonable; FAIL is the answer, and redialling to get a nicer one is not diligence.

saying these in an interview costs you the question

  • Says any reply that is not an acceptance denies the login.
  • Treats ERROR as a server-side denial the device applies.
  • Thinks the device tries the next method after a FAIL.
  • Believes a timeout and a FAIL are handled the same way.
  • Assumes the three exchanges fall through together.