Confusion about delegation

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Confusion about delegation

John Byrne
Hi,

I'm confused about a couple of points regarding delegation - could anyone
help to educate me please?

I am trying to perform a constrained delegation authentication with a web
application. The user authenticates to a web application (principal HTTP/
www.example.com) and that web application then authenticates to another web
app (HTTP/datastore.examle.com).

Based on the information here (
https://web.mit.edu/kerberos/krb5-devel/doc/appdev/gssapi.html) I think I
need the first web app to get proxy credentials for the user from the KDC,
then initialize a security context using those creds, and then use the
token it gets from that security context to authenticate against second web
app as that user. Have I read that correctly?

With this in mind, I'm using the following code on the intermediate server.
It's using the python-gssapi library, which uses MIT krb5 underneath (v
1.15.1). Hopefully it's clear what's happening here in pure gssapi terms:

    name = gssapi.Name('HTTP/www.example.com',) #the principal for this
service
    creds = gssapi.Credentials(name=name, usage='initiate')
    username = gssapi.Name('kerbtestjohn') # the user that this service
wants to impersonate
    proxy_creds = creds.impersonate(username, usage='initiate')
    target_name = gssapi.Name('HTTP/datastore.example.com') # the service
that this service wants to access as the impersonated user
    client_ctx = gssapi.SecurityContext(name=target_name,
creds=proxy_creds, usage='initiate')
    initial_client_token = client_ctx.step()
    t = base64.b64encode(initial_client_token)
    headers = {'Authorization': 'Negotiate ' + t}
    r = requests.get('http://datastore.example.com/', headers=headers)

The client_ctx.step() call returns this error: gssapi.raw.misc.GSSError:
Major (851968): Unspecified GSS failure.  Minor code may provide more
information, Minor (2529639053): Matching credential not found

I've made sure that the target_name principal is in the default keytab, but
honestly I'm not even sure why it's looking for a credential for this
principal at this point. In any case, having it in the keytab doesn't seem
to help.

The surprising thing is that if I initialize the context with the other
name instead (HTTP/www.example.com), then this code works perfectly, and
authenticates me as 'kerbtestjohn' to www.datastore.com. I didn't think
that should work. Even stranger, if I omit the proxy_creds from the
SecurityContext, then it also works, using either of the 2 service names.
So I can impersonate users without the proxy creds!? Shouldn't that be
rejected?

The final confusing thing is that I don't have the 'ok_to_auth_as_delegate'
bit set on any of my principals. Shouldn't I have to set that for HTTP/
www.example.com  in order for that service to be able to impersonate a user?

The datastore.example.com service is using nginx +
spnego-http-auth-nginx-module. Again, this uses MIT krb5 (same version,
1.15.1). I don't see any signs that this component is not working
correctly. It's definitely enforcing authentication.

Can anyone explain what I'm doing wrong here? Thanks in advance for any
insight you can provide!

-John
________________________________________________
Kerberos mailing list           [hidden email]
https://mailman.mit.edu/mailman/listinfo/kerberos
Reply | Threaded
Open this post in threaded view
|

Re: Confusion about delegation

Greg Hudson
On 1/31/19 1:32 PM, John Byrne wrote:
> The client_ctx.step() call returns this error: gssapi.raw.misc.GSSError:
> Major (851968): Unspecified GSS failure.  Minor code may provide more
> information, Minor (2529639053): Matching credential not found

This is a bad error message, and we have an open ticket noting the need
to improve it:

  http://krbdev.mit.edu/rt/Ticket/Display.html?id=8586

Because you haven't set the ok_to_auth_as_delegate bit on
HTTP/www.example.com, the KDC issues a non-forwardable service ticket in
the creds.impersonate() step.  The GSSAPI layer stores this as a regular
cred object containing a user -> HTTP/www.example.com service ticket,
not an impersonator cred.  Such a credential can be interrogated for
name attributes to get PAC information (if it came from a KDC supporting
PACs) or to authenticate to the intermediate service itself, but it
can't be used to authenticate to any other service.

When gss_init_sec_context() tries to authenticate with this credential,
it can't find either a client -> target or client -> krbtgt/REALM
credential, so it fails with the uninformative error message.

Release 1.16 added the ability to query a credential for whether it is
an impersonator credential, as noted in the documentation page you
referenced.

> I've made sure that the target_name principal is in the default keytab

Only the target service should have a target_name keytab entry.  Giving
out that keytab to other parties poses a security issue, allowing those
parties to impersonate (in the attacker sense, not the S4U2Proxy sense)
the target service.

> The surprising thing is that if I initialize the context with the other
> name instead (HTTP/www.example.com), then this code works perfectly, and
> authenticates me as 'kerbtestjohn' to www.datastore.com.

I would expect this to authenticate from kerbtestjohn to
HTTP/www.example.com.  How would it authenticate to www.datastore.com if
you didn't ask gss_init_sec_context() to do so?

> Even stranger, if I omit the proxy_creds from the
> SecurityContext, then it also works, using either of the 2 service names.
> So I can impersonate users without the proxy creds!? Shouldn't that be
> rejected?

If you omit proxy_creds, then it should authenticate from whatever
client is in the default ccache (probably HTTP/www.example.com) to the
target service.  It shouldn't authenticate as krbtestjohn.
________________________________________________
Kerberos mailing list           [hidden email]
https://mailman.mit.edu/mailman/listinfo/kerberos
Reply | Threaded
Open this post in threaded view
|

Re: Confusion about delegation

John Byrne
Thanks, this helps a lot.

I think the reason it appeared to be working for me when I used the wrong
name HTTP/www.example.com is because I incorrectly had that principal in
the keytab of the other service. An in the second case, where I omitted the
creds altogether, you are correct, it just authenticated as HTTP/
www.example.com and not kerbtestjohn.

So, I have set ok_to_auth_as_delegate in my KDC for the intermediate
service principal HTTP/www.example.com, but now I'm getting this error on
the step() call:

Feb 01 14:47:14 localhost.localdomain krb5kdc[6376](info): TGS_REQ (8
etypes {18 17 20 19 16 23 25 26}) 192.168.0.22: NOT_ALLOWED_TO_DELEGATE:
authtime 0,  HTTP/[hidden email] for HTTP/
[hidden email], Plugin does not support the operation

I couldn't find any info on this, but I did some reading in the source code
and it looks like the necessary function 'check_allowed_to_delegate' is
only defined for the ldap plugin. Have I got that right - I have to use
ldap to get this feature to work with the krb5 server? Or is there another
way?

Thanks again for the info on this!

-John


On Fri, Feb 1, 2019 at 12:26 PM Greg Hudson <[hidden email]> wrote:

> On 1/31/19 1:32 PM, John Byrne wrote:
> > The client_ctx.step() call returns this error: gssapi.raw.misc.GSSError:
> > Major (851968): Unspecified GSS failure.  Minor code may provide more
> > information, Minor (2529639053): Matching credential not found
>
> This is a bad error message, and we have an open ticket noting the need
> to improve it:
>
>   http://krbdev.mit.edu/rt/Ticket/Display.html?id=8586
>
> Because you haven't set the ok_to_auth_as_delegate bit on
> HTTP/www.example.com, the KDC issues a non-forwardable service ticket in
> the creds.impersonate() step.  The GSSAPI layer stores this as a regular
> cred object containing a user -> HTTP/www.example.com service ticket,
> not an impersonator cred.  Such a credential can be interrogated for
> name attributes to get PAC information (if it came from a KDC supporting
> PACs) or to authenticate to the intermediate service itself, but it
> can't be used to authenticate to any other service.
>
> When gss_init_sec_context() tries to authenticate with this credential,
> it can't find either a client -> target or client -> krbtgt/REALM
> credential, so it fails with the uninformative error message.
>
> Release 1.16 added the ability to query a credential for whether it is
> an impersonator credential, as noted in the documentation page you
> referenced.
>
> > I've made sure that the target_name principal is in the default keytab
>
> Only the target service should have a target_name keytab entry.  Giving
> out that keytab to other parties poses a security issue, allowing those
> parties to impersonate (in the attacker sense, not the S4U2Proxy sense)
> the target service.
>
> > The surprising thing is that if I initialize the context with the other
> > name instead (HTTP/www.example.com), then this code works perfectly, and
> > authenticates me as 'kerbtestjohn' to www.datastore.com.
>
> I would expect this to authenticate from kerbtestjohn to
> HTTP/www.example.com.  How would it authenticate to www.datastore.com if
> you didn't ask gss_init_sec_context() to do so?
>
> > Even stranger, if I omit the proxy_creds from the
> > SecurityContext, then it also works, using either of the 2 service names.
> > So I can impersonate users without the proxy creds!? Shouldn't that be
> > rejected?
>
> If you omit proxy_creds, then it should authenticate from whatever
> client is in the default ccache (probably HTTP/www.example.com) to the
> target service.  It shouldn't authenticate as krbtestjohn.
>
________________________________________________
Kerberos mailing list           [hidden email]
https://mailman.mit.edu/mailman/listinfo/kerberos
Reply | Threaded
Open this post in threaded view
|

Re: Confusion about delegation

Benjamin Kaduk-2
On Fri, Feb 01, 2019 at 02:54:39PM -0500, John Byrne wrote:

> Thanks, this helps a lot.
>
> I think the reason it appeared to be working for me when I used the wrong
> name HTTP/www.example.com is because I incorrectly had that principal in
> the keytab of the other service. An in the second case, where I omitted the
> creds altogether, you are correct, it just authenticated as HTTP/
> www.example.com and not kerbtestjohn.
>
> So, I have set ok_to_auth_as_delegate in my KDC for the intermediate
> service principal HTTP/www.example.com, but now I'm getting this error on
> the step() call:
>
> Feb 01 14:47:14 localhost.localdomain krb5kdc[6376](info): TGS_REQ (8
> etypes {18 17 20 19 16 23 25 26}) 192.168.0.22: NOT_ALLOWED_TO_DELEGATE:
> authtime 0,  HTTP/[hidden email] for HTTP/
> [hidden email], Plugin does not support the operation
>
> I couldn't find any info on this, but I did some reading in the source code
> and it looks like the necessary function 'check_allowed_to_delegate' is
> only defined for the ldap plugin. Have I got that right - I have to use
> ldap to get this feature to work with the krb5 server? Or is there another
> way?

The only in-tree module that supports constrained elegation, yes.  (At
least one out-of-tree module also exists, though presumably you would
already know if that was one you wanted.)

-Ben
________________________________________________
Kerberos mailing list           [hidden email]
https://mailman.mit.edu/mailman/listinfo/kerberos