Bug 2056508 - Ipa server ignores max ticket lifetime when using spake preauth, issues ticket with 24h lifetime
Summary: Ipa server ignores max ticket lifetime when using spake preauth, issues ticke...
Keywords:
Status: CLOSED EOL
Alias: None
Product: Fedora
Classification: Fedora
Component: freeipa
Version: 37
Hardware: x86_64
OS: Linux
unspecified
high
Target Milestone: ---
Assignee: IPA Maintainers
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2022-02-21 12:10 UTC by Miguel Oliveira
Modified: 2025-12-26 12:49 UTC (History)
13 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2023-12-05 21:04:40 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)
prototype fix (3.00 KB, patch)
2022-02-23 07:24 UTC, Alexander Bokovoy
no flags Details | Diff


Links
System ID Private Priority Status Summary Last Updated
Fedora Pagure freeipa issue 9121 0 None None None 2022-03-03 18:18:41 UTC
Red Hat Issue Tracker FREEIPA-7865 0 None None None 2022-02-21 12:13:56 UTC

Description Miguel Oliveira 2022-02-21 12:10:15 UTC
Description of problem:

We have an infrastructure composed of ubuntu 18 and ubuntu 20 machines, with free ipa providing centralized authentication. On the client machines, we use plain kerberos to request the tickets. Due to AFS constraints, I need to issue kerberos tickets with long lifetimes (e.g. 15days).

The settings on the server side were set to allow for those lifetimes (via the Kerberos Ticket Policy tab), and are explicitly set to more than 15d for all auth types. 

Ubuntu 18 has kerberos 1.16 installed and works as expected, when issued the command "kinit -l 15d" it can get a ticket with 15days lifetime. 
However, when doing the same in ubuntu 20, with kerberos 1.17, the ticket only has ~24h lifetime (the life varies, I suppose due to the jitter feature of ipa). 
I inspected the exchanged network packets and the only difference is that krb 1.17 uses SPAKE by default, so I ensured that hardened auth is enabled for all users (selecting both password and hardened in the web UI). However the erratic behavior persists. I can confirm that in krb 1.17 the request is correctly made,  with the lifetime parameter set to the 15days.


Version-Release number of selected component (if applicable):
ipa server: 4.9.8
krb: 1.16 (working) and 1.17 (not working)

How reproducible:
Have a ipa realm and client machines with kerberos 1.17 (and 1.16 to test correct behavior).


Steps to Reproduce:
1. Create a ipa domain, set the maximum ticket lifetimes to more than 1day. 
2. Set the user auth methods to both password and hardened password.
3. Try to authenticate using kerberos 1.16 on the client (e.g. kinit -l 15d), and verify the ticket has the correct lifetime.
4. Try to authenticate using kerberos 1.17 on the client (e.g. kinit -l 15d), and verify the ticket has only ~24h of lifetime.

Actual results:
Using krb 1.17 (that has SPAKE) the ticket only has ~24h lifetime.

Expected results:
The ticket should have as lifetime the biggest value between what is requested via kinit and the policy setting on ipa server.

Additional info:

ipa user-show output:

[root@idm01 ~]# ipa user-show testuser
  User login: testuser
  First name: Test
  Last name: Tester
  Home directory: /afs/example.com/home/testuser
  Login shell: /bin/bash
  Principal name: testuser
  Principal alias: testuser
  Email address: testuser
  UID: 50034
  GID: 100
  User authentication types: hardened, password
  Account disabled: False
  Password: True
  Member of groups: users
  Kerberos keys available: True


ipa krbtpolicy-show output:

[root@idm01 ~]# ipa krbtpolicy-show
  Max life: 2678400
  Max renew: 2678400
  Hardened max life: 2678401
  Hardened max renew: 2678401


I don't know what logs can be useful but I'm available to provide any if needed.

Comment 1 Alexander Bokovoy 2022-02-21 13:23:50 UTC
Thanks for the bug filed. I wonder if you are seeing difference in the reported life times also for the same authentication type, like for password-based one. Since some time we have lifetime jitter support which randomizes the lifetime within the allowed by the policy.


Could you please provide two traces:

 1. A trace from the client side:
   date
   KRB5_TRACE=/dev/stderr kinit testuser

 2. A /var/log/krb5kdc.log snippet for the timeframe you tried the kinit from the KDC server you have seen in the trace (1) in case you have multiple KDCs.

Comment 2 Alexander Bokovoy 2022-02-21 13:37:54 UTC
We have had one bug about SPAKE handling fixed recently: https://pagure.io/freeipa/issue/9065. You might want to try to rebuild FreeIPA with that fix to test if that addresses your problem.

Comment 3 Miguel Oliveira 2022-02-21 13:56:44 UTC
(In reply to Alexander Bokovoy from comment #1)
> Thanks for the bug filed. I wonder if you are seeing difference in the
> reported life times also for the same authentication type, like for
> password-based one. Since some time we have lifetime jitter support which
> randomizes the lifetime within the allowed by the policy.

For the password (not hardened login) the jitter seems to not have any effect (the tickets have always the exact requested lifetime) but that is not a problem in this case.
For the hardened login I can verify that the jitter is always applied (the tickets have always different lifetimes, but always aprox 24h), the problem is that I am requesting the ticket with 15days lifetime, and it returns a ticket with the ~24h lifetime.

> 
> Could you please provide two traces:
> 
>  1. A trace from the client side:
>    date
>    KRB5_TRACE=/dev/stderr kinit testuser
> 

krb 1.16:

moliveira@x01:~$ KRB5_TRACE=/dev/stderr kinit
[957785] 1645451475.714158: Getting initial credentials for moliveira
[957785] 1645451475.714160: Sending unauthenticated request
[957785] 1645451475.714161: Sending request (200 bytes) to VOICEINTERACTION.PT
[957785] 1645451475.714162: Resolving hostname idm01.voiceinteraction.pt
[957785] 1645451475.714163: Sending initial UDP request to dgram 172.18.254.2:88
[957785] 1645451475.714164: Received answer (497 bytes) from dgram 172.18.254.2:88
[957785] 1645451475.714165: Sending DNS URI query for _kerberos.VOICEINTERACTION.PT.
[957785] 1645451475.714166: URI answer: 0 100 "krb5srv:m:udp:idm02.voiceinteraction.pt."
[957785] 1645451475.714167: URI answer: 0 100 "krb5srv:m:tcp:idm01.voiceinteraction.pt."
[957785] 1645451475.714168: URI answer: 0 100 "krb5srv:m:tcp:idm02.voiceinteraction.pt."
[957785] 1645451475.714169: URI answer: 0 100 "krb5srv:m:udp:idm01.voiceinteraction.pt."
[957785] 1645451475.714170: Response was not from master KDC
[957785] 1645451475.714171: Received error from KDC: -1765328359/Additional pre-authentication required
[957785] 1645451475.714174: Preauthenticating using KDC method data
[957785] 1645451475.714175: Processing preauth types: 16, 136, 19, 147, 151, 2, 133
[957785] 1645451475.714176: Selected etype info: etype aes256-cts, salt "QM3^.Sz8-3=5)|b?", params ""
[957785] 1645451475.714177: Received cookie: MIT1\x00\x00\x00\x01\xb2}\xb5\x80`\xc679\xf3\xc3\xb4\x03\xaa\xf8\x13\xa3T\x80&J\xafW\x9a\x08_\xaf\xe0\xc7\x9e\xb9\xc2\xdcm\xc9\x1f(\xd0\xd1\xf2m\xc1\x11\x00\xe2\x89y\xca\xeeP\x0a\xffj\xb5+^*H\xea\x8e\x0d`\xfb]\xb7\x7f\x09\xb3\x0c\xa3\xbb2\xceu\x85\xe6`\xd4]N%&\xca\xcb\x1cx\x88\xd6\xf4G\x13\x07:^-\xad~\xa1\xf3\x05\xdb\x18z\xf5\x11\x02O\xc8\x95\xb9\x85pG\xec,e:n$T\x85Y\x8a\xccj\xee\x01p+\xe3\xb1
Password for moliveira:
[957785] 1645451482.400339: AS key obtained for encrypted timestamp: aes256-cts/1995
[957785] 1645451482.400341: Encrypted timestamp (for 1645451481.700036): plain 301AA011180F32303232303232313133353132315AA10502030AAE84, encrypted 2E0CBB1DDA53EE6E9C88C8C94B4CE6F25BEBEDF2250582B2A6E4FEF795A106EFF1A7B03D2B370239D7FA7C5F2BAAAC8EA45AC65EE77E05EE
[957785] 1645451482.400342: Preauth module encrypted_timestamp (2) (real) returned: 0/Success
[957785] 1645451482.400343: Produced preauth for next request: 133, 2
[957785] 1645451482.400344: Sending request (435 bytes) to VOICEINTERACTION.PT
[957785] 1645451482.400345: Resolving hostname idm01.voiceinteraction.pt
[957785] 1645451482.400346: Sending initial UDP request to dgram 172.18.254.2:88
[957785] 1645451482.400347: Received answer (784 bytes) from dgram 172.18.254.2:88
[957785] 1645451482.400348: Sending DNS URI query for _kerberos.VOICEINTERACTION.PT.
[957785] 1645451482.400349: URI answer: 0 100 "krb5srv:m:udp:idm02.voiceinteraction.pt."
[957785] 1645451482.400350: URI answer: 0 100 "krb5srv:m:tcp:idm01.voiceinteraction.pt."
[957785] 1645451482.400351: URI answer: 0 100 "krb5srv:m:tcp:idm02.voiceinteraction.pt."
[957785] 1645451482.400352: URI answer: 0 100 "krb5srv:m:udp:idm01.voiceinteraction.pt."
[957785] 1645451482.400353: Response was not from master KDC
[957785] 1645451482.400354: Processing preauth types: 19
[957785] 1645451482.400355: Selected etype info: etype aes256-cts, salt "QM3^.Sz8-3=5)|b?", params ""
[957785] 1645451482.400356: Produced preauth for next request: (empty)
[957785] 1645451482.400357: AS key determined by preauth: aes256-cts/1995
[957785] 1645451482.400358: Decrypted AS reply; session key is: aes256-cts/5DC2
[957785] 1645451482.400359: FAST negotiation: available
[957785] 1645451482.400360: Initializing FILE:/tmp/krb5cc_50034_Fx7xOc with default princ moliveira
[957785] 1645451482.400361: Storing moliveira -> krbtgt/VOICEINTERACTION.PT in FILE:/tmp/krb5cc_50034_Fx7xOc
[957785] 1645451482.400362: Storing config in FILE:/tmp/krb5cc_50034_Fx7xOc for krbtgt/VOICEINTERACTION.PT: fast_avail: yes
[957785] 1645451482.400363: Storing moliveira -> krb5_ccache_conf_data/fast_avail/krbtgt\/VOICEINTERACTION.PT\@VOICEINTERACTION.PT@X-CACHECONF: in FILE:/tmp/krb5cc_50034_Fx7xOc
[957785] 1645451482.400364: Storing config in FILE:/tmp/krb5cc_50034_Fx7xOc for krbtgt/VOICEINTERACTION.PT: pa_type: 2
[957785] 1645451482.400365: Storing moliveira -> krb5_ccache_conf_data/pa_type/krbtgt\/VOICEINTERACTION.PT\@VOICEINTERACTION.PT@X-CACHECONF: in FILE:/tmp/krb5cc_50034_Fx7xOc
moliveira@x01:~$
moliveira@x01:~$
moliveira@x01:~$
moliveira@x01:~$
moliveira@x01:~$ KRB5_TRACE=/dev/stderr kinit -l 30d
[957936] 1645451502.456122: Getting initial credentials for moliveira
[957936] 1645451502.456124: Sending unauthenticated request
[957936] 1645451502.456125: Sending request (200 bytes) to VOICEINTERACTION.PT
[957936] 1645451502.456126: Resolving hostname idm01.voiceinteraction.pt
[957936] 1645451502.456127: Sending initial UDP request to dgram 172.18.254.2:88
[957936] 1645451502.456128: Received answer (498 bytes) from dgram 172.18.254.2:88
[957936] 1645451502.456129: Sending DNS URI query for _kerberos.VOICEINTERACTION.PT.
[957936] 1645451502.456130: URI answer: 0 100 "krb5srv:m:udp:idm02.voiceinteraction.pt."
[957936] 1645451502.456131: URI answer: 0 100 "krb5srv:m:tcp:idm01.voiceinteraction.pt."
[957936] 1645451502.456132: URI answer: 0 100 "krb5srv:m:tcp:idm02.voiceinteraction.pt."
[957936] 1645451502.456133: URI answer: 0 100 "krb5srv:m:udp:idm01.voiceinteraction.pt."
[957936] 1645451502.456134: Response was not from master KDC
[957936] 1645451502.456135: Received error from KDC: -1765328359/Additional pre-authentication required
[957936] 1645451502.456138: Preauthenticating using KDC method data
[957936] 1645451502.456139: Processing preauth types: 16, 136, 19, 147, 151, 2, 133
[957936] 1645451502.456140: Selected etype info: etype aes256-cts, salt "QM3^.Sz8-3=5)|b?", params ""
[957936] 1645451502.456141: Received cookie: MIT1\x00\x00\x00\x01\x9d&\xf9\x9c\xb7\x1bX_\xbe#kX\xca\xd5&r\xfbML!\x13\x17\xaf\xd2\xfa\xf4x]0o\x9e\xb7$\xd1\xff\xf5\x1c\x17\x07\xb9/\xdd\xe3\xdba\xc8\xeagI\x1c0\xb7\xec\xd4y\x90\xae\x85e`\xd1\xf7T\x16)\xa2a\xbf\xd9%\xa2\x0a\xea\x85\xeb\xd2T\xcc\xa0\x91\xf2\xca\xa3t\xb9\xb7\x8fX\xc4=\x13\xb1\xc0\x96$\x9c\xe7\x90\xc7\xa2E\xd5\xa2\x8f\x16RM\x0d\x98\xa5bt$\xe8\x0bd\xffK\xb7\xdc\x8d-\x10\xb0%\xd4\xeeEyr
Password for moliveira:
[957936] 1645451505.596134: AS key obtained for encrypted timestamp: aes256-cts/1995
[957936] 1645451505.596136: Encrypted timestamp (for 1645451505.360760): plain 301AA011180F32303232303232313133353134355AA1050203058138, encrypted 6176DA25A0E8835AFA1A999D0AC646A88020D471B44BC578AC2D2F16A8DF292C92173F93C879D0331F3F2ED89895E55C1CE4E99937076D93
[957936] 1645451505.596137: Preauth module encrypted_timestamp (2) (real) returned: 0/Success
[957936] 1645451505.596138: Produced preauth for next request: 133, 2
[957936] 1645451505.596139: Sending request (435 bytes) to VOICEINTERACTION.PT
[957936] 1645451505.596140: Resolving hostname idm01.voiceinteraction.pt
[957936] 1645451505.596141: Sending initial UDP request to dgram 172.18.254.2:88
[957936] 1645451505.596142: Received answer (784 bytes) from dgram 172.18.254.2:88
[957936] 1645451505.596143: Sending DNS URI query for _kerberos.VOICEINTERACTION.PT.
[957936] 1645451505.596144: URI answer: 0 100 "krb5srv:m:udp:idm02.voiceinteraction.pt."
[957936] 1645451505.596145: URI answer: 0 100 "krb5srv:m:tcp:idm01.voiceinteraction.pt."
[957936] 1645451505.596146: URI answer: 0 100 "krb5srv:m:tcp:idm02.voiceinteraction.pt."
[957936] 1645451505.596147: URI answer: 0 100 "krb5srv:m:udp:idm01.voiceinteraction.pt."
[957936] 1645451505.596148: Response was not from master KDC
[957936] 1645451505.596149: Processing preauth types: 19
[957936] 1645451505.596150: Selected etype info: etype aes256-cts, salt "QM3^.Sz8-3=5)|b?", params ""
[957936] 1645451505.596151: Produced preauth for next request: (empty)
[957936] 1645451505.596152: AS key determined by preauth: aes256-cts/1995
[957936] 1645451505.596153: Decrypted AS reply; session key is: aes256-cts/7D45
[957936] 1645451505.596154: FAST negotiation: available
[957936] 1645451505.596155: Initializing FILE:/tmp/krb5cc_50034_Fx7xOc with default princ moliveira
[957936] 1645451505.596156: Storing moliveira -> krbtgt/VOICEINTERACTION.PT in FILE:/tmp/krb5cc_50034_Fx7xOc
[957936] 1645451505.596157: Storing config in FILE:/tmp/krb5cc_50034_Fx7xOc for krbtgt/VOICEINTERACTION.PT: fast_avail: yes
[957936] 1645451505.596158: Storing moliveira -> krb5_ccache_conf_data/fast_avail/krbtgt\/VOICEINTERACTION.PT\@VOICEINTERACTION.PT@X-CACHECONF: in FILE:/tmp/krb5cc_50034_Fx7xOc
[957936] 1645451505.596159: Storing config in FILE:/tmp/krb5cc_50034_Fx7xOc for krbtgt/VOICEINTERACTION.PT: pa_type: 2
[957936] 1645451505.596160: Storing moliveira -> krb5_ccache_conf_data/pa_type/krbtgt\/VOICEINTERACTION.PT\@VOICEINTERACTION.PT@X-CACHECONF: in FILE:/tmp/krb5cc_50034_Fx7xOc



krb 1.17:

moliveira@afs-test:~$ KRB5_TRACE=/dev/stderr kinit
[109371] 1645451513.441805: Getting initial credentials for moliveira
[109371] 1645451513.441807: Sending unauthenticated request
[109371] 1645451513.441808: Sending request (203 bytes) to VOICEINTERACTION.PT
[109371] 1645451513.441809: Resolving hostname idm01.voiceinteraction.pt
[109371] 1645451513.441810: Sending initial UDP request to dgram 172.18.254.2:88
[109371] 1645451513.441811: Received answer (530 bytes) from dgram 172.18.254.2:88
[109371] 1645451513.441812: Sending DNS URI query for _kerberos.VOICEINTERACTION.PT.
[109371] 1645451513.441813: URI answer: 0 100 "krb5srv:m:udp:idm02.voiceinteraction.pt."
[109371] 1645451513.441814: URI answer: 0 100 "krb5srv:m:tcp:idm02.voiceinteraction.pt."
[109371] 1645451513.441815: URI answer: 0 100 "krb5srv:m:tcp:idm01.voiceinteraction.pt."
[109371] 1645451513.441816: URI answer: 0 100 "krb5srv:m:udp:idm01.voiceinteraction.pt."
[109371] 1645451513.441817: Response was not from master KDC
[109371] 1645451513.441818: Received error from KDC: -1765328359/Additional pre-authentication required
[109371] 1645451513.441821: Preauthenticating using KDC method data
[109371] 1645451513.441822: Processing preauth types: PA-PK-AS-REQ (16), PA-FX-FAST (136), PA-ETYPE-INFO2 (19), PA-PKINIT-KX (147), PA-SPAKE (151), PA-ENC-TIMESTAMP (2), PA_AS_FRESHNESS (150), PA-FX-COOKIE (133)
[109371] 1645451513.441823: Selected etype info: etype aes256-cts, salt "QM3^.Sz8-3=5)|b?", params ""
[109371] 1645451513.441824: Received cookie: MIT1\x00\x00\x00\x01\x13q\x1e\xfcY\xe7w\x7f8\xca\xec\x89\xc4\xc1\xf6x/\x03>uz\x18\x19\xd9\xd7\x06\xbek\xf1\xde\x1a\xecB\x07\x92I\x13\x96G\xe3Z\xef\xbd\xfa@+7_\xa3U\xbc\xde;\xe5\xd6#\xce\xc0\x07g\xd9\xcf\xaa\x83N\x14\x9c\xbft\xaaN\xd8\xe6\x9a>\x14\xd31\xfaI\xe9\x09jvS\xfa%%[\x15\xe1\xe2\xf8\x99,\x169N[[\x8b\xcd(h\x05%\x1a'wMse\xd4\xac\xa0>CG\x95p\x12o\x00E\xe9\xdf1r\x8f'
[109371] 1645451513.441825: SPAKE challenge received with group 1, pubkey AFD5650C45B4900FE5E4980E5E901DD9F0FA768DE7670CC8ADCFAE35B06D59A2
Password for moliveira:
[109371] 1645451515.935236: SPAKE key generated with pubkey 5F890786EF348B1C1F54583EEFE3DA85973AABE24C58C680B628E7AC3B90144C
[109371] 1645451515.935237: SPAKE algorithm result: 9E6BAA748B360AD271F354514F05037C92DDD088AA3D2AC940F5C90E8752DF02
[109371] 1645451515.935238: SPAKE final transcript hash: B40157A7EE45F7D75D2E20D2E67D79ED2B29D85E7EB1180BA2F57542767E83B3
[109371] 1645451515.935239: Sending SPAKE response
[109371] 1645451515.935240: Preauth module spake (151) (real) returned: 0/Success
[109371] 1645451515.935241: Produced preauth for next request: PA-FX-COOKIE (133), PA-SPAKE (151)
[109371] 1645451515.935242: Sending request (462 bytes) to VOICEINTERACTION.PT
[109371] 1645451515.935243: Resolving hostname idm01.voiceinteraction.pt
[109371] 1645451515.935244: Sending initial UDP request to dgram 172.18.254.2:88
[109371] 1645451515.935245: Received answer (862 bytes) from dgram 172.18.254.2:88
[109371] 1645451515.935246: Sending DNS URI query for _kerberos.VOICEINTERACTION.PT.
[109371] 1645451515.935247: URI answer: 0 100 "krb5srv:m:udp:idm02.voiceinteraction.pt."
[109371] 1645451515.935248: URI answer: 0 100 "krb5srv:m:tcp:idm02.voiceinteraction.pt."
[109371] 1645451515.935249: URI answer: 0 100 "krb5srv:m:tcp:idm01.voiceinteraction.pt."
[109371] 1645451515.935250: URI answer: 0 100 "krb5srv:m:udp:idm01.voiceinteraction.pt."
[109371] 1645451515.935251: Response was not from master KDC
[109371] 1645451515.935252: AS key determined by preauth: aes256-cts/9EE3
[109371] 1645451515.935253: Decrypted AS reply; session key is: aes256-cts/0244
[109371] 1645451515.935254: FAST negotiation: available
[109371] 1645451515.935255: Initializing FILE:/tmp/krb5cc_50034_Hzf1Y5 with default princ moliveira
[109371] 1645451515.935256: Storing moliveira -> krbtgt/VOICEINTERACTION.PT in FILE:/tmp/krb5cc_50034_Hzf1Y5
[109371] 1645451515.935257: Storing config in FILE:/tmp/krb5cc_50034_Hzf1Y5 for krbtgt/VOICEINTERACTION.PT: fast_avail: yes
[109371] 1645451515.935258: Storing moliveira -> krb5_ccache_conf_data/fast_avail/krbtgt\/VOICEINTERACTION.PT\@VOICEINTERACTION.PT@X-CACHECONF: in FILE:/tmp/krb5cc_50034_Hzf1Y5
[109371] 1645451515.935259: Storing config in FILE:/tmp/krb5cc_50034_Hzf1Y5 for krbtgt/VOICEINTERACTION.PT: pa_type: 151
[109371] 1645451515.935260: Storing moliveira -> krb5_ccache_conf_data/pa_type/krbtgt\/VOICEINTERACTION.PT\@VOICEINTERACTION.PT@X-CACHECONF: in FILE:/tmp/krb5cc_50034_Hzf1Y5
moliveira@afs-test:~$
moliveira@afs-test:~$
moliveira@afs-test:~$ KRB5_TRACE=/dev/stderr kinit -l 30d
[109372] 1645451521.44054: Getting initial credentials for moliveira
[109372] 1645451521.44056: Sending unauthenticated request
[109372] 1645451521.44057: Sending request (203 bytes) to VOICEINTERACTION.PT
[109372] 1645451521.44058: Resolving hostname idm01.voiceinteraction.pt
[109372] 1645451521.44059: Sending initial UDP request to dgram 172.18.254.2:88
[109372] 1645451521.44060: Received answer (530 bytes) from dgram 172.18.254.2:88
[109372] 1645451521.44061: Sending DNS URI query for _kerberos.VOICEINTERACTION.PT.
[109372] 1645451521.44062: URI answer: 0 100 "krb5srv:m:udp:idm02.voiceinteraction.pt."
[109372] 1645451521.44063: URI answer: 0 100 "krb5srv:m:tcp:idm02.voiceinteraction.pt."
[109372] 1645451521.44064: URI answer: 0 100 "krb5srv:m:tcp:idm01.voiceinteraction.pt."
[109372] 1645451521.44065: URI answer: 0 100 "krb5srv:m:udp:idm01.voiceinteraction.pt."
[109372] 1645451521.44066: Response was not from master KDC
[109372] 1645451521.44067: Received error from KDC: -1765328359/Additional pre-authentication required
[109372] 1645451521.44070: Preauthenticating using KDC method data
[109372] 1645451521.44071: Processing preauth types: PA-PK-AS-REQ (16), PA-FX-FAST (136), PA-ETYPE-INFO2 (19), PA-PKINIT-KX (147), PA-SPAKE (151), PA-ENC-TIMESTAMP (2), PA_AS_FRESHNESS (150), PA-FX-COOKIE (133)
[109372] 1645451521.44072: Selected etype info: etype aes256-cts, salt "QM3^.Sz8-3=5)|b?", params ""
[109372] 1645451521.44073: Received cookie: MIT1\x00\x00\x00\x01p\x88UQ\x10l{\xb4s\xe8W\x7ft\x1e\xc4\x82\xfb\xd0 \xb2\x9b\x01vcM\xd8|\x8a-\x84\x94\x95Fl\xef\x1e\x80\x8e\x86H,NZ\xf0\x8cE\xd6H14\xba~\x09~z9k\x18\x02uY\xa8g\x83\x06\xfc\xbas\x00YV\x81~;\xb1w\xca\x8b3\x0d\xdezl\x93;zqyI\xeeA\x9b\xb7\\xe9\p\x8ey\xb9\xa01=\xf9\xe3\xce\&q\xc1\x0a;\xd6$\xba\xb4\xb3\xca\xaa\x99e\x05\xd4\xdc\x8b\xc69D\xa2o
[109372] 1645451521.44074: SPAKE challenge received with group 1, pubkey 4BA0CC3B979DCF8FF0BA46DD92B2957DD20DC081FF2047D9857ED3BA667E495B
Password for moliveira:
[109372] 1645451523.387179: SPAKE key generated with pubkey 634EF2B884DE5C4D9928558CDFAA2C6CF97595DA00B27FAE9AF7C83C9F104FBC
[109372] 1645451523.387180: SPAKE algorithm result: ED08585F3A0424FAF5BE9B9D5863BE550CA7D93807118399F79CA79B6B476797
[109372] 1645451523.387181: SPAKE final transcript hash: AA735F772176A5A4E63F3EEF88EE17C8462CD03338A25A87808EB3D4D911DFDE
[109372] 1645451523.387182: Sending SPAKE response
[109372] 1645451523.387183: Preauth module spake (151) (real) returned: 0/Success
[109372] 1645451523.387184: Produced preauth for next request: PA-FX-COOKIE (133), PA-SPAKE (151)
[109372] 1645451523.387185: Sending request (462 bytes) to VOICEINTERACTION.PT
[109372] 1645451523.387186: Resolving hostname idm01.voiceinteraction.pt
[109372] 1645451523.387187: Sending initial UDP request to dgram 172.18.254.2:88
[109372] 1645451523.387188: Received answer (862 bytes) from dgram 172.18.254.2:88
[109372] 1645451523.387189: Sending DNS URI query for _kerberos.VOICEINTERACTION.PT.
[109372] 1645451523.387190: URI answer: 0 100 "krb5srv:m:udp:idm02.voiceinteraction.pt."
[109372] 1645451523.387191: URI answer: 0 100 "krb5srv:m:tcp:idm02.voiceinteraction.pt."
[109372] 1645451523.387192: URI answer: 0 100 "krb5srv:m:tcp:idm01.voiceinteraction.pt."
[109372] 1645451523.387193: URI answer: 0 100 "krb5srv:m:udp:idm01.voiceinteraction.pt."
[109372] 1645451523.387194: Response was not from master KDC
[109372] 1645451523.387195: AS key determined by preauth: aes256-cts/ADD6
[109372] 1645451523.387196: Decrypted AS reply; session key is: aes256-cts/10F4
[109372] 1645451523.387197: FAST negotiation: available
[109372] 1645451523.387198: Initializing FILE:/tmp/krb5cc_50034_Hzf1Y5 with default princ moliveira
[109372] 1645451523.387199: Storing moliveira -> krbtgt/VOICEINTERACTION.PT in FILE:/tmp/krb5cc_50034_Hzf1Y5
[109372] 1645451523.387200: Storing config in FILE:/tmp/krb5cc_50034_Hzf1Y5 for krbtgt/VOICEINTERACTION.PT: fast_avail: yes
[109372] 1645451523.387201: Storing moliveira -> krb5_ccache_conf_data/fast_avail/krbtgt\/VOICEINTERACTION.PT\@VOICEINTERACTION.PT@X-CACHECONF: in FILE:/tmp/krb5cc_50034_Hzf1Y5
[109372] 1645451523.387202: Storing config in FILE:/tmp/krb5cc_50034_Hzf1Y5 for krbtgt/VOICEINTERACTION.PT: pa_type: 151
[109372] 1645451523.387203: Storing moliveira -> krb5_ccache_conf_data/pa_type/krbtgt\/VOICEINTERACTION.PT\@VOICEINTERACTION.PT@X-CACHECONF: in FILE:/tmp/krb5cc_50034_Hzf1Y5





>  2. A /var/log/krb5kdc.log snippet for the timeframe you tried the kinit
> from the KDC server you have seen in the trace (1) in case you have multiple
> KDCs.

The first block are the requests from krb1.16 and the second block are the ones from krb1.17

[root@idm01 ~]# tail -f /var/log/krb5kdc.log
Feb 21 13:51:15 idm01.voiceinteraction.pt krb5kdc[3309](info): AS_REQ (11 etypes {aes256-cts-hmac-sha1-96(18), aes128-cts-hmac-sha1-96(17), aes256-cts-hmac-sha384-192(20), aes128-cts-hmac-sha256-128(19), UNSUPPORTED:des3-hmac-sha1(16), DEPRECATED:arcfour-hmac(23), camellia128-cts-cmac(25), camellia256-cts-cmac(26), UNSUPPORTED:des-cbc-crc(1), UNSUPPORTED:des-cbc-md5(3), UNSUPPORTED:des-cbc-md4(2)}) 172.18.2.1: NEEDED_PREAUTH: moliveira for krbtgt/VOICEINTERACTION.PT, Additional pre-authentication required
Feb 21 13:51:22 idm01.voiceinteraction.pt krb5kdc[3309](info): AS_REQ (11 etypes {aes256-cts-hmac-sha1-96(18), aes128-cts-hmac-sha1-96(17), aes256-cts-hmac-sha384-192(20), aes128-cts-hmac-sha256-128(19), UNSUPPORTED:des3-hmac-sha1(16), DEPRECATED:arcfour-hmac(23), camellia128-cts-cmac(25), camellia256-cts-cmac(26), UNSUPPORTED:des-cbc-crc(1), UNSUPPORTED:des-cbc-md5(3), UNSUPPORTED:des-cbc-md4(2)}) 172.18.2.1: ISSUE: authtime 1645451482, etypes {rep=aes256-cts-hmac-sha1-96(18), tkt=aes256-cts-hmac-sha1-96(18), ses=aes256-cts-hmac-sha1-96(18)}, moliveira for krbtgt/VOICEINTERACTION.PT
Feb 21 13:51:42 idm01.voiceinteraction.pt krb5kdc[3309](info): AS_REQ (11 etypes {aes256-cts-hmac-sha1-96(18), aes128-cts-hmac-sha1-96(17), aes256-cts-hmac-sha384-192(20), aes128-cts-hmac-sha256-128(19), UNSUPPORTED:des3-hmac-sha1(16), DEPRECATED:arcfour-hmac(23), camellia128-cts-cmac(25), camellia256-cts-cmac(26), UNSUPPORTED:des-cbc-crc(1), UNSUPPORTED:des-cbc-md5(3), UNSUPPORTED:des-cbc-md4(2)}) 172.18.2.1: NEEDED_PREAUTH: moliveira for krbtgt/VOICEINTERACTION.PT, Additional pre-authentication required
Feb 21 13:51:45 idm01.voiceinteraction.pt krb5kdc[3309](info): AS_REQ (11 etypes {aes256-cts-hmac-sha1-96(18), aes128-cts-hmac-sha1-96(17), aes256-cts-hmac-sha384-192(20), aes128-cts-hmac-sha256-128(19), UNSUPPORTED:des3-hmac-sha1(16), DEPRECATED:arcfour-hmac(23), camellia128-cts-cmac(25), camellia256-cts-cmac(26), UNSUPPORTED:des-cbc-crc(1), UNSUPPORTED:des-cbc-md5(3), UNSUPPORTED:des-cbc-md4(2)}) 172.18.2.1: ISSUE: authtime 1645451505, etypes {rep=aes256-cts-hmac-sha1-96(18), tkt=aes256-cts-hmac-sha1-96(18), ses=aes256-cts-hmac-sha1-96(18)}, moliveira for krbtgt/VOICEINTERACTION.PT




Feb 21 13:51:53 idm01.voiceinteraction.pt krb5kdc[3309](info): AS_REQ (8 etypes {aes256-cts-hmac-sha1-96(18), aes128-cts-hmac-sha1-96(17), aes256-cts-hmac-sha384-192(20), aes128-cts-hmac-sha256-128(19), UNSUPPORTED:des3-hmac-sha1(16), DEPRECATED:arcfour-hmac(23), camellia128-cts-cmac(25), camellia256-cts-cmac(26)}) 172.18.254.26: NEEDED_PREAUTH: moliveira for krbtgt/VOICEINTERACTION.PT, Additional pre-authentication required
Feb 21 13:51:55 idm01.voiceinteraction.pt krb5kdc[3309](info): AS_REQ (8 etypes {aes256-cts-hmac-sha1-96(18), aes128-cts-hmac-sha1-96(17), aes256-cts-hmac-sha384-192(20), aes128-cts-hmac-sha256-128(19), UNSUPPORTED:des3-hmac-sha1(16), DEPRECATED:arcfour-hmac(23), camellia128-cts-cmac(25), camellia256-cts-cmac(26)}) 172.18.254.26: ISSUE: authtime 1645451515, etypes {rep=aes256-cts-hmac-sha1-96(18), tkt=aes256-cts-hmac-sha1-96(18), ses=aes256-cts-hmac-sha1-96(18)},
moliveira for krbtgt/VOICEINTERACTION.PT
Feb 21 13:52:01 idm01.voiceinteraction.pt krb5kdc[3309](info): AS_REQ (8 etypes {aes256-cts-hmac-sha1-96(18), aes128-cts-hmac-sha1-96(17), aes256-cts-hmac-sha384-192(20), aes128-cts-hmac-sha256-128(19), UNSUPPORTED:des3-hmac-sha1(16), DEPRECATED:arcfour-hmac(23), camellia128-cts-cmac(25), camellia256-cts-cmac(26)}) 172.18.254.26: NEEDED_PREAUTH: moliveira for krbtgt/VOICEINTERACTION.PT, Additional pre-authentication required
Feb 21 13:52:03 idm01.voiceinteraction.pt krb5kdc[3309](info): AS_REQ (8 etypes {aes256-cts-hmac-sha1-96(18), aes128-cts-hmac-sha1-96(17), aes256-cts-hmac-sha384-192(20), aes128-cts-hmac-sha256-128(19), UNSUPPORTED:des3-hmac-sha1(16), DEPRECATED:arcfour-hmac(23), camellia128-cts-cmac(25), camellia256-cts-cmac(26)}) 172.18.254.26: ISSUE: authtime 1645451523, etypes {rep=aes256-cts-hmac-sha1-96(18), tkt=aes256-cts-hmac-sha1-96(18), ses=aes256-cts-hmac-sha1-96(18)},
moliveira for krbtgt/VOICEINTERACTION.PT


I will also try to rebuild FreeIPA with that fix and check if it solves the problem.

Thank you for the help!

Comment 4 Miguel Oliveira 2022-02-22 10:20:12 UTC
(In reply to Alexander Bokovoy from comment #2)
> We have had one bug about SPAKE handling fixed recently:
> https://pagure.io/freeipa/issue/9065. You might want to try to rebuild
> FreeIPA with that fix to test if that addresses your problem.

Just rebuilt FreeIPA from master (including the fix) and the problem persists. Anyway I think the version I was already using (4.9.8 already implemented that specific fix). 

From my limited understanding of the code, I am thinking that the problem is somewhere in ipa_kdcpolicy_check_as() in ipa_kdb_kdcpolicy.c, since there are some constants of 1 day in seconds being applied in certain conditions. However I don't have the knowledge to verify or fix that.

Comment 5 Miguel Oliveira 2022-02-22 11:33:06 UTC
For simple testing, I increased the ONE_DAY_SECONDS variable in ipa_kdb_kdcpolicy.c to 30days (30 * 24 * 60 * 60). The tickets (using spake) now have a lifetime of 7 days, even though i requested a ticket with 15 days lifetime and the max life is set to 30 days in the web UI policy page. No idea why this is happening.

Comment 6 Alexander Bokovoy 2022-02-22 11:43:40 UTC
thanks for this investigation. So, we have the following logic in the ipa_kdcpolicy_check_as():

- check if there are no indicators associated with the user (meaning none of the specific policy needs to apply), use hardcoded ONE_DAY_SECONDS interval jittered

otherwise,

- for each indicator in the list of associated authentication indicators, read individual policy values and

  - if individual policy limits max ticket life, apply it, jittered
  - if individual policy does not limit max ticket life, apply ONE_DAY_SECONDS interval, jittered
  - if individual policy defines max renewable life, apply it as well


For SPAKE case we should get 'hardened' authentication indicator and IPADB_USER_AUTH_HARDENED user authentication bit set. If this happened, then for the policy to be set to ON_DAY_SECONDS interval, it should have pol_limits->max_life set to 0.

The policy values read and filled in the ipadb_parse_authind_policies():

    ied = (struct ipadb_e_data *)entry->e_data;
    if (ied == NULL) {
        return;
    }

    for (size_t i = 0; life_authind_map[i].attribute != NULL; i++) {
        if (ua & life_authind_map[i].flag) {
            ret = ipadb_ldap_attr_to_int(lcontext, lentry,
                                         life_authind_map[i].attribute,
                                         &result);
            if (ret == 0) {
                ied->pol_limits[life_authind_map[i].idx].max_life = result;
            }

            ret = ipadb_ldap_attr_to_int(lcontext, lentry,
                                         age_authind_map[i].attribute,
                                         &result);
            if (ret == 0) {
                ied->pol_limits[age_authind_map[i].idx].max_renewable_life = result;
            }
        }
    }


max_life would set to 0 if ipadb_ldap_attr_to_int() has returned 0 and result was 0.

I think we need to add some debugging to the ipa_kdb_kdcpolicy.c to see what indicators we have and what policy is there. I'll look at this tonight or tomorrow, have a number of meetings before that.

Comment 7 Miguel Oliveira 2022-02-22 15:50:32 UTC
After some crude debugging, I could trace back the problem to the ipadb_ldap_attr_to_int() function. Basically ipadb_ldap_attr_to_int() called ipadb_ldap_attr_to_int() requesting the value for the attribute "krbAuthIndMaxTicketLife;hardened", and it returned ENOENT, which in turn made the life in ipadb_parse_authind_policies() be set as 0, explaining the policy being set to the ONE_DAY_SECONDS interval. From my understanding, this could mean that either the LDAPMessage passed to the function is not the right one, or that the attribute doesn't exist.

I can confirm though that, although according to the docs it shouldn't be needed, the specific Authentication indicators for all the options are populated. I could also verify that this behavior (ipadb_ldap_attr_to_int() returning ENOENT) also occurs for the attributes related to pkinit, and for both MaxTicketLife and MaxRenewableLife.

Comment 8 Alexander Bokovoy 2022-02-22 15:56:34 UTC
Wonderful. Could you please show the raw output of the policy:

ipa krbtpolicy-show --all --raw

Comment 9 Alexander Bokovoy 2022-02-22 16:28:01 UTC
Looking deeper, we also do not inherit default policy in case auth indicator-specific one is missing. That's why ONE_DAY_SECONDS gets used.

So a fix would be either:

 - to update ipadb_parse_authind_policies() to use default policy values in case indicator-specific ones are missing
 - use default policy values in the ipa_kdcpolicy_check_as() instead

I would prefer the former one, it gives a chance to put all the logic in the same place.

Comment 10 Alexander Bokovoy 2022-02-22 16:51:00 UTC
After more investigation, I think we should instead use the main policy's max ticket life:

diff --git a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
index a8ac88342..e73403293 100644
--- a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
+++ b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
@@ -152,7 +152,7 @@ ipa_kdcpolicy_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata,
         if (pol_limits->max_life != 0) {
             jitter(pol_limits->max_life, lifetime_out);
         } else {
-            jitter(ONE_DAY_SECONDS, lifetime_out);
+            jitter(ied->max_life, lifetime_out);
         }
 
         if (pol_limits->max_renewable_life != 0) {

Comment 11 Miguel Oliveira 2022-02-22 18:06:27 UTC
(In reply to Alexander Bokovoy from comment #8)
> Wonderful. Could you please show the raw output of the policy:
> 
> ipa krbtpolicy-show --all --raw

[root@ipa-test ~]# ipa krbtpolicy-show --all --raw
/usr/lib/python3.10/site-packages/ipalib/util.py:347: DeprecationWarning: ssl.PROTOCOL_TLS is deprecated
  ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
  dn: cn=TESTS.VOICEINTERACTION.PT,cn=kerberos,dc=tests,dc=voiceinteraction,dc=pt
  krbmaxticketlife: 2592000
  krbmaxrenewableage: 2592009
  aci: (targetattr = "createtimestamp || entryusn || krbauthindmaxrenewableage || krbauthindmaxticketlife || krbdefaultencsalttypes || krbmaxrenewableage || krbmaxticketlife || krbsupportedencsalttypes || modifytimestamp || objectclass")(targetfilter = "(objectclass=krbticketpolicyaux)")(version 3.0;acl "permission:System: Read Default Kerberos Ticket Policy";allow (compare,read,search) groupdn = "ldap:///cn=System: Read Default Kerberos Ticket Policy,cn=permissions,cn=pbac,dc=tests,dc=voiceinteraction,dc=pt";)
  aci: (targetfilter = "(|(objectclass=ipapwdpolicy)(objectclass=krbpwdpolicy))")(version 3.0;acl "permission:System: Add Group Password Policy";allow (add) groupdn = "ldap:///cn=System: Add Group Password Policy,cn=permissions,cn=pbac,dc=tests,dc=voiceinteraction,dc=pt";)
  aci: (targetfilter = "(|(objectclass=ipapwdpolicy)(objectclass=krbpwdpolicy))")(version 3.0;acl "permission:System: Delete Group Password Policy";allow (delete) groupdn = "ldap:///cn=System: Delete Group Password Policy,cn=permissions,cn=pbac,dc=tests,dc=voiceinteraction,dc=pt";)
  aci: (targetattr = "ipapwddictcheck || ipapwdmaxrepeat || ipapwdmaxsequence || ipapwdusercheck || krbmaxpwdlife || krbminpwdlife || krbpwdfailurecountinterval || krbpwdhistorylength || krbpwdlockoutduration || krbpwdmaxfailure || krbpwdmindiffchars || krbpwdminlength")(targetfilter = "(|(objectclass=ipapwdpolicy)(objectclass=krbpwdpolicy))")(version 3.0;acl "permission:System: Modify Group Password Policy";allow (write) groupdn = "ldap:///cn=System: Modify Group Password Policy,cn=permissions,cn=pbac,dc=tests,dc=voiceinteraction,dc=pt";)
  aci: (targetattr = "cn || cospriority || createtimestamp || entryusn || ipapwddictcheck || ipapwdmaxrepeat || ipapwdmaxsequence || ipapwdusercheck || krbmaxpwdlife || krbminpwdlife || krbpwdfailurecountinterval || krbpwdhistorylength || krbpwdlockoutduration || krbpwdmaxfailure || krbpwdmindiffchars || krbpwdminlength || modifytimestamp || objectclass")(targetfilter = "(|(objectclass=ipapwdpolicy)(objectclass=krbpwdpolicy))")(version 3.0;acl "permission:System: Read Group Password Policy";allow (compare,read,search) groupdn = "ldap:///cn=System: Read Group Password Policy,cn=permissions,cn=pbac,dc=tests,dc=voiceinteraction,dc=pt";)
  cn: TESTS.VOICEINTERACTION.PT
  krbAuthIndMaxRenewableAge;hardened: 2592008
  krbAuthIndMaxRenewableAge;hardened: 2592008
  krbAuthIndMaxRenewableAge;otp: 2592004
  krbAuthIndMaxRenewableAge;otp: 2592004
  krbAuthIndMaxRenewableAge;pkinit: 2592006
  krbAuthIndMaxRenewableAge;pkinit: 2592006
  krbAuthIndMaxRenewableAge;radius: 2592002
  krbAuthIndMaxRenewableAge;radius: 2592002
  krbAuthIndMaxTicketLife;hardened: 2592007
  krbAuthIndMaxTicketLife;hardened: 2592007
  krbAuthIndMaxTicketLife;otp: 2592003
  krbAuthIndMaxTicketLife;otp: 2592003
  krbAuthIndMaxTicketLife;pkinit: 2592005
  krbAuthIndMaxTicketLife;pkinit: 2592005
  krbAuthIndMaxTicketLife;radius: 2592001
  krbAuthIndMaxTicketLife;radius: 2592001
  krbDefaultEncSaltTypes: aes256-cts:special
  krbDefaultEncSaltTypes: aes128-cts:special
  krbPwdPolicyReference: cn=Default Kerberos Service Password Policy,cn=Kerberos Service Password Policy,cn=TESTS.VOICEINTERACTION.PT,cn=kerberos,dc=tests,dc=voiceinteraction,dc=pt
  krbSearchScope: 2
  krbSubTrees: dc=tests,dc=voiceinteraction,dc=pt
  krbSupportedEncSaltTypes: aes256-cts:normal
  krbSupportedEncSaltTypes: aes256-cts:special
  krbSupportedEncSaltTypes: aes128-cts:normal
  krbSupportedEncSaltTypes: aes128-cts:special
  krbSupportedEncSaltTypes: aes128-sha2:normal
  krbSupportedEncSaltTypes: aes128-sha2:special
  krbSupportedEncSaltTypes: aes256-sha2:normal
  krbSupportedEncSaltTypes: aes256-sha2:special
  krbSupportedEncSaltTypes: camellia128-cts-cmac:normal
  krbSupportedEncSaltTypes: camellia128-cts-cmac:special
  krbSupportedEncSaltTypes: camellia256-cts-cmac:normal
  krbSupportedEncSaltTypes: camellia256-cts-cmac:special
  objectClass: top
  objectClass: krbrealmcontainer
  objectClass: krbticketpolicyaux

[root@ipa-test ~]# ipa krbtpolicy-show test --raw
/usr/lib/python3.10/site-packages/ipalib/util.py:347: DeprecationWarning: ssl.PROTOCOL_TLS is deprecated
  ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
  krbmaxticketlife: 2592000
  krbmaxrenewableage: 2592009

It makes sense, the policies are set for the default policy, but for the individual users only the basic password policy is set.

Comment 12 Miguel Oliveira 2022-02-22 18:17:52 UTC
(In reply to Alexander Bokovoy from comment #9)
> Looking deeper, we also do not inherit default policy in case auth indicator-specific one is missing. That's why ONE_DAY_SECONDS gets used.
>
> So a fix would be either:
>
>  - to update ipadb_parse_authind_policies() to use default policy values in case indicator-specific ones are missing
>  - use default policy values in the ipa_kdcpolicy_check_as() instead
>
> I would prefer the former one, it gives a chance to put all the logic in the same place.
>

That makes sense, it only checks the specific user and ignores the default policies for the indicator-specific ones. And I agree on the approach, making ipadb_parse_authind_policies() get the default policies if the user-specific ones are not set.



(In reply to Alexander Bokovoy from comment #10)
> After more investigation, I think we should instead use the main policy's
> max ticket life:
> 
> diff --git a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
> b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
> index a8ac88342..e73403293 100644
> --- a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
> +++ b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
> @@ -152,7 +152,7 @@ ipa_kdcpolicy_check_as(krb5_context context,
> krb5_kdcpolicy_moddata moddata,
>          if (pol_limits->max_life != 0) {
>              jitter(pol_limits->max_life, lifetime_out);
>          } else {
> -            jitter(ONE_DAY_SECONDS, lifetime_out);
> +            jitter(ied->max_life, lifetime_out);
>          }
>  
>          if (pol_limits->max_renewable_life != 0) {

That would be an approach, but in that case if I explicitly set the parameters to one specific indicator for the entire realm, it would ignore it and use the default general policy, and make the specific indicators useless, or am I interpreting this approach wrongly?

Comment 13 Alexander Bokovoy 2022-02-23 07:23:55 UTC
(In reply to Miguel Oliveira from comment #12)
> (In reply to Alexander Bokovoy from comment #9)
> > Looking deeper, we also do not inherit default policy in case auth indicator-specific one is missing. That's why ONE_DAY_SECONDS gets used.
> >
> > So a fix would be either:
> >
> >  - to update ipadb_parse_authind_policies() to use default policy values in case indicator-specific ones are missing
> >  - use default policy values in the ipa_kdcpolicy_check_as() instead
> >
> > I would prefer the former one, it gives a chance to put all the logic in the same place.
> >
> 
> That makes sense, it only checks the specific user and ignores the default
> policies for the indicator-specific ones. And I agree on the approach,
> making ipadb_parse_authind_policies() get the default policies if the
> user-specific ones are not set.

After I wrote that, I checked that we only fill-in the default policies after we parsed user-specific authentication indicator policies. So we cannot use ied->max_life or ied->max_renewable_life in the ipadb_parse_authind_policies().

User/group-specific policies handled with class of service plugin in LDAP, so they automatically appear in a subentry of a user entry when requested.

> 
> 
> 
> (In reply to Alexander Bokovoy from comment #10)
> > After more investigation, I think we should instead use the main policy's
> > max ticket life:
> > 
> > diff --git a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
> > b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
> > index a8ac88342..e73403293 100644
> > --- a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
> > +++ b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
> > @@ -152,7 +152,7 @@ ipa_kdcpolicy_check_as(krb5_context context,
> > krb5_kdcpolicy_moddata moddata,
> >          if (pol_limits->max_life != 0) {
> >              jitter(pol_limits->max_life, lifetime_out);
> >          } else {
> > -            jitter(ONE_DAY_SECONDS, lifetime_out);
> > +            jitter(ied->max_life, lifetime_out);
> >          }
> >  
> >          if (pol_limits->max_renewable_life != 0) {
> 
> That would be an approach, but in that case if I explicitly set the
> parameters to one specific indicator for the entire realm, it would ignore
> it and use the default general policy, and make the specific indicators
> useless, or am I interpreting this approach wrongly?

The code in ipa_kdcpolicy_check_as() goes through all indicators associated with the ticket issued as part of AS-REP. It is typically one indicator, the one that corresponds to the pre-authentication method used to negotiate the TGT.
In IPA when you set a list of allowed methods (indicators) globally, they limit list of possible pre-authentication methods to be advertised by the KDC to the client but if any of those methods was negotiated between the client and KDC, the resulting ticket will have the indicator associated with the method. ipa_kdcpolicy_check_as() will see that (final) indicator. Theoretically, more than one final indicator could be in the ticket but in IPA it should always be at most one.

I think what we miss, perhaps, is parsing of the indicator-specific values from the default policy.

I have a prototype fix -- can you please test it?

Comment 14 Alexander Bokovoy 2022-02-23 07:24:24 UTC
Created attachment 1862811 [details]
prototype fix

Comment 15 Miguel Oliveira 2022-02-23 11:24:54 UTC
(In reply to Alexander Bokovoy from comment #14)
> Created attachment 1862811 [details]
> prototype fix

When I try to open the attachment it gives me permission denied, not authorized to see the attachment.

Comment 16 Alexander Bokovoy 2022-02-23 11:52:53 UTC
Please try again.

Comment 17 Miguel Oliveira 2022-02-23 17:25:53 UTC
(In reply to Alexander Bokovoy from comment #13)
> (In reply to Miguel Oliveira from comment #12)
> > (In reply to Alexander Bokovoy from comment #9)
> > > Looking deeper, we also do not inherit default policy in case auth indicator-specific one is missing. That's why ONE_DAY_SECONDS gets used.
> > >
> > > So a fix would be either:
> > >
> > >  - to update ipadb_parse_authind_policies() to use default policy values in case indicator-specific ones are missing
> > >  - use default policy values in the ipa_kdcpolicy_check_as() instead
> > >
> > > I would prefer the former one, it gives a chance to put all the logic in the same place.
> > >
> > 
> > That makes sense, it only checks the specific user and ignores the default
> > policies for the indicator-specific ones. And I agree on the approach,
> > making ipadb_parse_authind_policies() get the default policies if the
> > user-specific ones are not set.
> 
> After I wrote that, I checked that we only fill-in the default policies
> after we parsed user-specific authentication indicator policies. So we
> cannot use ied->max_life or ied->max_renewable_life in the
> ipadb_parse_authind_policies().
> 
> User/group-specific policies handled with class of service plugin in LDAP,
> so they automatically appear in a subentry of a user entry when requested.
> 
> > 
> > 
> > 
> > (In reply to Alexander Bokovoy from comment #10)
> > > After more investigation, I think we should instead use the main policy's
> > > max ticket life:
> > > 
> > > diff --git a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
> > > b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
> > > index a8ac88342..e73403293 100644
> > > --- a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
> > > +++ b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
> > > @@ -152,7 +152,7 @@ ipa_kdcpolicy_check_as(krb5_context context,
> > > krb5_kdcpolicy_moddata moddata,
> > >          if (pol_limits->max_life != 0) {
> > >              jitter(pol_limits->max_life, lifetime_out);
> > >          } else {
> > > -            jitter(ONE_DAY_SECONDS, lifetime_out);
> > > +            jitter(ied->max_life, lifetime_out);
> > >          }
> > >  
> > >          if (pol_limits->max_renewable_life != 0) {
> > 
> > That would be an approach, but in that case if I explicitly set the
> > parameters to one specific indicator for the entire realm, it would ignore
> > it and use the default general policy, and make the specific indicators
> > useless, or am I interpreting this approach wrongly?
> 
> The code in ipa_kdcpolicy_check_as() goes through all indicators associated
> with the ticket issued as part of AS-REP. It is typically one indicator, the
> one that corresponds to the pre-authentication method used to negotiate the
> TGT.
> In IPA when you set a list of allowed methods (indicators) globally, they
> limit list of possible pre-authentication methods to be advertised by the
> KDC to the client but if any of those methods was negotiated between the
> client and KDC, the resulting ticket will have the indicator associated with
> the method. ipa_kdcpolicy_check_as() will see that (final) indicator.
> Theoretically, more than one final indicator could be in the ticket but in
> IPA it should always be at most one.
> 
> I think what we miss, perhaps, is parsing of the indicator-specific values
> from the default policy.
> 
> I have a prototype fix -- can you please test it?

The fix you proposed solves the issue. There is another detail that must be noted though: the max ticket life and renewable life will always be limited by the life parameters for the krbtgt/EXAMPLE.COM principal in kerberos. Not sure if it needs to be changed or if the best course of action is to add a note in the docs advising that for life > 7days and renewable life > 14 days, the krbtgt principal must be modified in kadmin. No one should need tickets with larger that that lifetimes I suppose.

There is another small problem, not totally related to this one: when no indicators are set for a user, instead of assuming that password is set, it is just limiting the max life to 1day because of


    /* If no mechanisms are set, allow every auth method */
    if (ua == IPADB_USER_AUTH_NONE) {
        jitter(ONE_DAY_SECONDS, lifetime_out);
        kerr = 0;
        goto done;
    }

in ipa_kdcpolicy_check_as(). That ONE_DAY_SECONDS should be the max life for the default policy.

Apart from this detail when no specific indicators are set and the krbtgt principal life, that fix solves the issue. Thanks!

Comment 18 Miguel Oliveira 2022-02-23 18:07:31 UTC
Actually my bad, to increase the lifetime beyond 7days (and renewable life beyond 14days) it is actually needed to do 2 things (after applying your fix):

1-Increase the maxlife and maxrenewlife of the krbtgt/EXAMPLE.COM principal (the service principal that supplies the ticket)
2-Increase the max_life and max_renewable_life parameters in /etc/kerberos/krb5kdc/kdc.conf

For values lower than that, the fix solves all issues, making the web UI work as expected.

Comment 19 Alexander Bokovoy 2022-02-23 19:49:57 UTC
Thanks for the confirmation that the fix works. I'll add another client->max_life instead of ONE_DAY_SECONDS there.

As for overriding the global policies on the krbtgt and kdc.conf sides, this needs additional investigation. We might want to force those to be defined in LDAP as well as changing every single replica's kdc.conf is not really a viable solution.

So, steps left to do:

 - clone this bug to upstream tracker
 - modify the fix to account for 'any' authentication type instead of one day default
 - figure out how to get krbtgt defaults driven by KDB, not KDC

Comment 20 Rob Crittenden 2022-03-03 18:18:39 UTC
Upstream ticket:
https://pagure.io/freeipa/issue/9121

Comment 21 Rob Crittenden 2022-03-03 18:54:22 UTC
Alexander, I think we can extend the OTP test to cover this. It think if we update ticket policy that sets otp-maxlife then kinit -l<something> and check the resulting ticket that should do it.

I suspect extending the KDC default max may be something we have to add later. It would probably be best to pull Julien into that conversation.

Comment 22 Rob Crittenden 2022-03-23 17:40:45 UTC
Created RFE https://pagure.io/freeipa/issue/9132 to track better centralized control over the maximum values for ticket policy currently controlled by kdc.conf.

Comment 23 Rob Crittenden 2022-03-31 17:56:13 UTC
Upstream PR https://github.com/freeipa/freeipa/pull/6223 is tracking additional efforts we uncovered while testing the current patch.

Comment 25 Ben Cotton 2022-08-09 13:41:32 UTC
This bug appears to have been reported against 'rawhide' during the Fedora Linux 37 development cycle.
Changing version to 37.

Comment 28 Rob Crittenden 2022-10-20 14:18:59 UTC
This BZ is not completely solved, it just mitigates them. There remain issues setting the policy that I discovered trying to automate testing for the merged changes.

From my very fallible memory:

There remains a problem with setting max and min life on the tickets. This is due to to the way that the values are calculated within MIT Kerberos.

The client obtains one set of values prior to determining the authentication mechanism. The server then obtains a set with the authenticator. Then the minimum value for each life and renew_life is chosen between the client and server values.

If there are multiple indicator types each with their own limits it is difficult to know which will apply once the tickets are issued since the client values really mess things up.

The server determines the final ticket times in kdc/policy.py:update_ticket_times(). client->max_life and client->max_renewable_life are set in the KDB plugin in ipa_kdcpolicy_check_as()

Comment 29 Aoife Moloney 2023-11-23 00:09:19 UTC
This message is a reminder that Fedora Linux 37 is nearing its end of life.
Fedora will stop maintaining and issuing updates for Fedora Linux 37 on 2023-12-05.
It is Fedora's policy to close all bug reports from releases that are no longer
maintained. At that time this bug will be closed as EOL if it remains open with a
'version' of '37'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, change the 'version' 
to a later Fedora Linux version. Note that the version field may be hidden.
Click the "Show advanced fields" button if you do not see it.

Thank you for reporting this issue and we are sorry that we were not 
able to fix it before Fedora Linux 37 is end of life. If you would still like 
to see this bug fixed and are able to reproduce it against a later version 
of Fedora Linux, you are encouraged to change the 'version' to a later version
prior to this bug being closed.

Comment 30 Aoife Moloney 2023-12-05 21:04:40 UTC
Fedora Linux 37 entered end-of-life (EOL) status on None.

Fedora Linux 37 is no longer maintained, which means that it
will not receive any further security or bug fix updates. As a result we
are closing this bug.

If you can reproduce this bug against a currently maintained version of Fedora Linux
please feel free to reopen this bug against that version. Note that the version
field may be hidden. Click the "Show advanced fields" button if you do not see
the version field.

If you are unable to reopen this bug, please file a new report against an
active release.

Thank you for reporting this bug and we are sorry it could not be fixed.


Note You need to log in before you can comment on or make changes to this bug.