Subject: [kitten] GSS-API and timeouts

From: Simon Josefsson <[email-masked]>
Date: Wed, 04 Apr 2012 16:43:39 +0200

When implementing the GSS-API part of OPENID20/SAML20 I noticed that the
processes can hang waiting for a long time.  Server may want to wait one
minute or more to allow a user to finish the IdP authentication.

I think Nico discussed asynchronous GSS-API before.  However it is a
significant amount of work to specify and implement.  I think it is
simpler for applications to create a separate process or thread for the
GSS-API part, and to enforce its own timeouts.  Sometimes there are
other reasons for having separate processes/threads anyway.

Still, even an asynchronous interface may want to use some timeouts
where authentication is no longer expected to ever finish.  So it is not
clear that an asynchronous interface is the solution to this problem.

Does anyone have any thoughts on what a reasonable timeout should be?

Or should GSS-API initiators and acceptors never timeout, but just hang
indefinitely in case the authentication eventually completes?

Of course, we could have a new GSS-API interface to enforce a timeout.
For example:

     OM_uint32
     gss_sec_context_timeout (OM_uint32 *minor_status,
                              OM_uint32 timeout);

or something more general, in case there are similar concerns for other
functions:

     OM_uint32
     gss_set_timeouts (OM_uint32 *minor_status,
                       OM_uint32 sec_context_timeout,
                       OM_uint32 micwrap_timeout);

FWIW, in my implementation I'll probably use a 5 minute timeout or
something like that.

/Simon

---

From: William Mills <[email-masked]>
Date: Wed, 4 Apr 2012 08:41:23 -0700 (PDT)

As a result of the OpenID flow/redirect don't you get a complete credential that can be used to finish the process?  Can't you connect again, get a challenge perhaps, submit that completed credential and be done?  That's very similar to what I did in the OAUTH/SASL thing, so I'm replaying my one trick :)

>________________________________
> From: Simon Josefsson <[email-masked]>
>To: [email-masked] 
>Sent: Wednesday, April 4, 2012 7:43 AM
>Subject: [kitten] GSS-API and timeouts
> 
>_______________________________________________
>Kitten mailing list
>[email-masked]
>https://www.ietf.org/mailman/listinfo/kitten
>
>
>

---

From: Simo Sorce <[email-masked]>
Date: Wed, 04 Apr 2012 11:48:58 -0400

> FWIW, in my implementation I'll probably use a 5 minute timeout or

The problem I see with this kind of calls is that they affect the whole
process. What if you have 2 libraries with conflicting needs and both
use gssapi ?

Simo.

-- 
Simo Sorce * Red Hat, Inc * New York

---

From: Nico Williams <[email-masked]>
Date: Wed, 4 Apr 2012 11:31:17 -0500

If you don't want to tackle async init/accept_sec_context now then I
suggest that you use threads and thread cancellation.

Nico
--

---

From: Simon Josefsson <[email-masked]>
Date: Wed, 04 Apr 2012 19:15:54 +0200

William Mills <[email-masked]> writes:

> As a result of the OpenID flow/redirect don't you get a complete
> credential that can be used to finish the process?  Can't you connect
> again, get a challenge perhaps, submit that completed credential and
> be done?  That's very similar to what I did in the OAUTH/SASL thing,
> so I'm replaying my one trick :)

The problem is that the browser interaction in OPENID20/SAML20 can take
a long time because it is interactive, and the server doesn't know when
to stop waiting.

/Simon

---

From: Simon Josefsson <[email-masked]>
Date: Wed, 04 Apr 2012 19:19:27 +0200

> process. What if you have 2 libraries with conflicting needs and both

Yeah, it is not optimal.  We could make it take a 'gss_ctx_id_t'
parameter so the timeout is just for a particular context, but then
there is no way to specify a timeout for the initial call that generate
the gss_ctx_id_t.

Maybe this is a non-issue.  We'll see how it works in practice.

/Simon

---

From: Simon Josefsson <[email-masked]>
Date: Wed, 04 Apr 2012 19:20:52 +0200

> suggest that you use threads and thread cancellation.

And not have any timeout in the implementation of the mechanism itself?

/Simon

---

From: Martin Rex <[email-masked]>
Date: Wed, 4 Apr 2012 19:27:54 +0200 (MEST)

> suggest that you use threads and thread cancellation.

Without looking at the particular environment underlying this discussion,
I've seen problems with termination of blocking/synchronous network
communication.  While doing a shutdown() on a socket across threads
will normally wake blocking threads on Unix system (without invalidating
the socket handle that the thread was blocked on), this does not work
on Microsoft Windows and on some older versions of SunOS.

On Windows, the shutdown will cause network I/O, and if the peer
processes the close event and closes the socket, the blocking thread
will wake up almost instantly.  But if the peer does not process events
on the socket, then it will take 4 minutes 2*MSL (TCP retransmit timeout)
before the thread that is blocking on read will be woken up with a
timeout error on the socket.  While closesocket() does have an immediate
effect, it also invalidates the socket handle, which will require
additional synchronization, so that (a) the socket handle is not used
after closesocket() has been called and closesocket() is only called once.
(The problem is that on a busy multi-threaded server the socket handle
 may get reused by an accept() between the time when a watchdog thread
 forces a closesocket() and the originally blocking thread wakes up.)

-Martin

---

From: Martin Rex <[email-masked]>
Date: Wed, 4 Apr 2012 19:30:55 +0200 (MEST)

> minute or more to allow a user to finish the IdP authentication.

What kind of waiting are you thinking of here?

Isn't this waiting for the initiator to send outstanding context tokens,
which by itself is asynchronous, rather than the server blocking on
a gss_accept_sec_context() call?

-Martin

---

From: Nico Williams <[email-masked]>
Date: Wed, 4 Apr 2012 12:30:57 -0500

> And not have any timeout in the implementation of the mechanism itself?

Right.  Why not?  You'd have to have cancellation handlers and so on,
but then, proper pthread use requires it anyways.  Not that anyone
bores making libraries cancel-safe -- it's a lot of work, and
pthread_cacnel() is rarely ever used.

On the other hand, both MIT and Heimdal have added the sorts of
interfaces you proposed without any standardization effort, so nothing
should stop you from doing the same.

My problem with global settings is that they are global, but we know
we have apps that load libraries that load libraries that load
libraries that use GSS such that we end up having multiple GSS apps in
one process.  This is why I dislike global settings.  My solution,
when I get around to finishing it, will be a variant of the "pgss"
proposal... (if you'd like to review the design you can, it's in my
'pgss' branch of my github Heimdal fork).

Nico
--

---

From: Nico Williams <[email-masked]>
Date: Wed, 4 Apr 2012 12:32:18 -0500

> a gss_accept_sec_context() call?

No, Simon's talking about waiting for messages to infrastructure, like
Kerberos KDCs, OCSP responders / CRL servers, RADIUS, IdPs, ...
Things the GSS-API does not expose.

Nico
--

---

From: William Mills <[email-masked]>
Date: Wed, 4 Apr 2012 10:35:42 -0700 (PDT)

>To: William Mills <[email-masked]> 
>Cc: "[email-masked]" <[email-masked]> 
>Sent: Wednesday, April 4, 2012 10:15 AM
>Subject: Re: GSS-API and timeouts
> 

Yes, but if you can support an async style thing then you can just fail
the first auth, hold the connection open, and let the client do a second 

auth.  Server then limits the total number of allowed failed auth transactions.

---

From: Simon Josefsson <[email-masked]>
Date: Wed, 04 Apr 2012 19:46:36 +0200

> auth.  Server then limits the total number of allowed failed auth

I don't see how that works for OPENID20/SAML20 -- because the client
doesn't get any token that could be used for the next SASL session.  The
server still has to wait for the first authentication to complete
eventually (of course the client can close that connection to indicate
cancelation but that is rather brutal).

/Simon

---

From: Simon Josefsson <[email-masked]>
Date: Wed, 04 Apr 2012 19:47:40 +0200

> 'pgss' branch of my github Heimdal fork).

Ok.  Having no timeout is simpler to implement.  I'll try that and see
how it works.

Thanks,
/Simon

---

From: Russ Allbery <[email-masked]>
Date: Wed, 04 Apr 2012 15:18:51 -0700

> there is no way to specify a timeout for the initial call that generate

The lack of ability to set options on the initial call has been a problem
for a long time.  In a Kerberos context, it currently means that one has
to set a per-thread global for the ticket cache to use, for example,
rather than attaching some state to a specific GSS-API interaction.

-- 
Russ Allbery ([email-masked])             <http://www.eyrie.org/~eagle/>

---

From: Nico Williams <[email-masked]>
Date: Wed, 4 Apr 2012 17:27:14 -0500

> rather than attaching some state to a specific GSS-API interaction.

Maybe I should finish up my pgss work and write an I-D.  The API is
trivial, the changes to the mechs are trivial, the changes to the
mechglue are rote (but extensive, mostly in the form of a simple
addition to the preamble of most GSS functions).

---

From: Luke Howard <[email-masked]>
Date: Thu, 5 Apr 2012 08:33:49 +1000

> rather than attaching some state to a specific GSS-API interaction.

The non-standard extension gss_set_sec_context_option() can create a context handle which can be then passed to the first gss_init_sec_context().

-- Luke

---

From: Russ Allbery <[email-masked]>
Date: Wed, 04 Apr 2012 15:36:36 -0700

>> The lack of ability to set options on the initial call has been a
>> problem for a long time.  In a Kerberos context, it currently means
>> that one has to set a per-thread global for the ticket cache to use,
>> for example, rather than attaching some state to a specific GSS-API
>> interaction.

> The non-standard extension gss_set_sec_context_option() can create a
> context handle which can be then passed to the first
> gss_init_sec_context().

Ah, indeed!  I missed that.  Thank you.