@@ -89,8 +89,8 @@ func crypt(secret []byte, p *Packet) error {
8989}
9090
9191// newCrypter makes a new crypter
92- func newCrypter (secret []byte , c net.Conn , proxy bool ) * crypter {
93- return & crypter {secret : secret , Conn : c , Reader : bufio .NewReaderSize (c , 107 ), proxy : proxy }
92+ func newCrypter (secret []byte , c net.Conn , proxy , tls bool ) * crypter {
93+ return & crypter {secret : secret , Conn : c , Reader : bufio .NewReaderSize (c , 107 ), proxy : proxy , tls : tls }
9494}
9595
9696// crypter wraps the net.Conn and performs reads and writes and crypt ops
@@ -106,6 +106,10 @@ type crypter struct {
106106 secret []byte
107107 // proxy if set, will strip the ha-proxy style ascii header
108108 proxy bool
109+
110+ // setting the tls parameters enables RFC 9887 specific handling
111+ // within the crypter
112+ tls bool
109113}
110114
111115// read will read a packet from the underlying net.Conn and decyrpt it
@@ -154,22 +158,43 @@ func (c *crypter) read() (*Packet, error) {
154158 crypterUnmarshalError .Inc ()
155159 return nil , err
156160 }
157- // run crypt first before we look for bad secrets
158- if err := crypt (c .secret , & p ); err != nil {
159- crypterCryptError .Inc ()
160- return nil , err
161- }
162- // if err is != nil, we hit a bug
163- // if reply is != nil, we found a bad secret.
164- // if both are non nil, we only inspect the error as that
165- // is a higher error condition in the server than a bad secret is
166- if reply , err := c .detectBadSecret (& p ); err != nil {
167- return nil , err
168- } else if reply != nil {
169- if _ , err := c .write (reply ); err != nil {
170- return nil , fmt .Errorf ("bad secret, crypt write fail for ip [%s]: %v" , c .RemoteAddr ().String (), err )
161+
162+ if ! c .tls {
163+ // obfuscation mechanism only applies to non-tls connections
164+ // run crypt first before we look for bad secrets
165+ if err := crypt (c .secret , & p ); err != nil {
166+ crypterCryptError .Inc ()
167+ return nil , err
168+ }
169+ // if err is != nil, we hit a bug
170+ // if reply is != nil, we found a bad secret.
171+ // if both are non nil, we only inspect the error as that
172+ // is a higher error condition in the server than a bad secret is
173+ if reply , err := c .detectBadSecret (& p ); err != nil {
174+ return nil , err
175+ } else if reply != nil {
176+ if _ , err := c .write (reply ); err != nil {
177+ return nil , fmt .Errorf ("bad secret, crypt write fail for ip [%s]: %w" , c .RemoteAddr ().String (), err )
178+ }
179+ return nil , fmt .Errorf ("bad secret detected for ip [%s]" , c .RemoteAddr ().String ())
180+ }
181+ } else {
182+ /*
183+ A TLS TACACS+ server that receives a packet with the TAC_PLUS_UNENCRYPTED_FLAG bit
184+ not set to 1 over a TLS connection, MUST return an error of TAC_PLUS_AUTHEN_STATUS_ERROR,
185+ TAC_PLUS_AUTHOR_STATUS_ERROR, or TAC_PLUS_ACCT_STATUS_ERROR as appropriate for the
186+ TACACS+ message type, with the TAC_PLUS_UNENCRYPTED_FLAG bit set to 1, and terminate the session
187+ */
188+ if ! p .Header .Flags .Has (UnencryptedFlag ) {
189+ reply , err := c .unsetFlagReply (p .Header )
190+ if err != nil {
191+ return nil , err
192+ }
193+ if _ , err := c .write (reply ); err != nil {
194+ return nil , fmt .Errorf ("unencrypted flag not set, crypt write fail for ip [%s]: %w" , c .RemoteAddr ().String (), err )
195+ }
196+ return nil , fmt .Errorf ("unencrypted flag not set for ip [%s]" , c .RemoteAddr ().String ())
171197 }
172- return nil , fmt .Errorf ("bad secret detected for ip [%s]" , c .RemoteAddr ().String ())
173198 }
174199
175200 crypterRead .Inc ()
@@ -185,10 +210,17 @@ func (c *crypter) write(p *Packet) (int, error) {
185210 return 0 , fmt .Errorf ("handler error, packet.Body cannot be nil" )
186211 }
187212 p .Header .Length = uint32 (len (p .Body ))
188- if err := crypt (c .secret , p ); err != nil {
189- crypterCryptError .Inc ()
190- return 0 , err
213+ if ! c .tls {
214+ if err := crypt (c .secret , p ); err != nil {
215+ crypterCryptError .Inc ()
216+ return 0 , err
217+ }
218+ } else {
219+ // before we marshal, we need to set the unencrypted flag
220+ // on packets when tls is enabled
221+ p .Header .Flags .Set (UnencryptedFlag )
191222 }
223+
192224 b , err := p .MarshalBinary ()
193225 if err != nil {
194226 crypterMarshalError .Inc ()
@@ -266,6 +298,53 @@ func (c crypter) detectBadSecret(p *Packet) (*Packet, error) {
266298 return nil , nil
267299}
268300
301+ func (c crypter ) unsetFlagReply (h * Header ) (* Packet , error ) {
302+ var b []byte
303+ var err error
304+ switch h .Type {
305+ case Authenticate :
306+ b , err = NewAuthenReply (
307+ SetAuthenReplyStatus (AuthenStatusError ),
308+ SetAuthenReplyServerMsg ("unencrypted flag not set" ),
309+ ).MarshalBinary ()
310+ if err != nil {
311+ crypterMarshalError .Inc ()
312+ return nil , err
313+ }
314+ case Authorize :
315+ b , err = NewAuthorReply (
316+ SetAuthorReplyStatus (AuthorStatusError ),
317+ SetAuthorReplyServerMsg ("unencrypted flag not set" ),
318+ ).MarshalBinary ()
319+ if err != nil {
320+ crypterMarshalError .Inc ()
321+ return nil , err
322+ }
323+ case Accounting :
324+ b , err = NewAcctReply (
325+ SetAcctReplyStatus (AcctReplyStatusError ),
326+ SetAcctReplyServerMsg ("unencrypted flag not set" ),
327+ ).MarshalBinary ()
328+ if err != nil {
329+ crypterMarshalError .Inc ()
330+ return nil , err
331+ }
332+ default :
333+ return nil , fmt .Errorf ("unknown header type [%v]" , h .Type )
334+ }
335+ // reset some flags and state for this error reply.
336+ // under error conditions it can be common in the rfc to reset the sequence to 1
337+ // if the error is particularly egregious. an unset encrypted flag on a TLS connection seems like it fits and
338+ // the rfc is unclear for this particular condition on what to do
339+ h .SeqNo = SequenceNumber (1 )
340+ h .Flags .Set (UnencryptedFlag )
341+
342+ return NewPacket (
343+ SetPacketHeader (h ),
344+ SetPacketBody (b ),
345+ ), nil
346+ }
347+
269348func (c crypter ) badSecretReply (h * Header ) (* Packet , error ) {
270349 var b []byte
271350 var err error
0 commit comments