Re: Avoiding PAM checks - Whoops

Karl Schopmeyer <[email protected]> Fri, 01 Aug 2014 10:04:26 -0500
Newsgroups gmane.network.open-pegasus.general
Message-ID <[email protected]>
Whoops, I sent out a reply to this yesterday that was really still an 
early draft and was both incomplete and incorrect.

Will complete and resend today.

Karl
On 07/31/2014 02:40 AM, Jan Safranek wrote:
> On 07/30/2014 04:34 PM, Andreas Maier wrote:
>> Karl, Jan, I have discussed the issue with a number of folks, and
>> that helped me to better understand how Jan's proposal works.
>>
>> I'd like to make the following comments, before I leave for vacation
>> (back at home from 8/16 on, back in the office from 8/25 on):
>>
>> Just to recap the overall approach: Upon successful authentication of
>> a CIM request, if the server supports the new feature, it invents a
>> session ID and sends that back with the CIM response. If the client
>> supports the new feature, it uses that session ID on subsequent CIM
>> requests. Upon receipt of a CIM request with such a session ID, the
>> server can decide whether it trusts the session ID sufficiently at
>> that moment to bypass the authentication check.
>>
>> I'm fine with that overall approach, but I kept the description
>> deliberately high level, because there are some considerations and
>> requirements:
>>
>> - It depends very much on the data that makes up the session ID. A
>> suggestion from one of our security folks was that the session ID be
>> a hash of (userid, timestamp, randon number, underlying SSL session
>> ID). It is definitely a requirement that the session ID cannot be
>> calculated by an intruder. For example, just using timestamp and
>> userid would probably be not sufficient. Keep in mind that the code
>> is open source, so the algorithm how exactly the hash is calculated
>> will be known, and the secret must be in the data, not in the
>> algorithm. Using the underlying SSL session ID for example ensures
>> that the same SSL session is still in place. Maybe that is too much
>> of a requirement, but it is something that needs to be carefully
>> considered.
>>
> Currently, the session ID is just cryptographically strong* random
> number, nothing else. Timestamp, source IP address and client user name
> are stored (and checked) in Pegasus memory, but are *not* transmitted in
> the session id.
>
> *) 15 bytes (120 bits), generated by RAND_bytes() call from
> openssl/rand.h. I've chose 15 as 'long enough' and divisible by 3, so it
> can be base64-encoded without padding. It can be longer, it's just one
> #define.
>
> I think that adding anything else to the session ID won't improve
> security in any way, it will just make it more predictable. We may store
> (and check) something on server, if we want. I would explicitly avoid
> checking SSL session ID, as the client may use different TCP connection
> (and thus SSL session) for subsequent request - that's very common in
> HTTP world, clients (e.g. pywbem) don't use Keep-Alive that much.
>
>> - The server must be able to determine the lifetime of the session
>> ID. The proposed cookie based approach would probably use the cookie
>> lifetime for that, but that could also be done otherwise. Can cookie
>> lifetimes be modified by a client? That would be bad. I would have a
>> better feeling if the lifetime was encoded in the session ID instead
>> of being a separate piece of clear data. Even if the session ID is a
>> hash (which cannot be unpacked), the server could remember (in
>> memory) which session IDs it has handed out at any point in time, and
>> match the session ID with an internal record of it that shows the
>> lifetime.
> The cookie lifetime is stored on server, client cannot influence it in
> any way. As I wrote above, it's not part of session ID, as it would make
> the ID more predictable.
>
>> - The server must be allowed to decide at any point that a normally
>> valid session ID is nevertheless dismissed, and that a new session ID
>> is created. The server can make that determination based upon nearly
>> everything, including suspicuous client behavior with otherwise
>> valid requests. If the server dismisses an incoming session ID, it
>> performs the normal authentication as if no session ID had been
>> provided by the client, and returns a new session ID.
> Well, there is no code for that, but if someone implements such
> detection logic, it's just one HashTable.remove() call to forget a
> session. which implies that the next request will go through proper
> authentication.
>
>> - As a result, the client must always use the session ID returned by
>> the last response, because the server could have recalculated it.
> Sure, that's how HTTP and my client patches work.
>
>> - how the session ID is transported between client and server, has a
>> number of options. It would certainly be some HTTP header. I have
>> seen extension headers used for that purpose, it does not necessarily
>> have to be a cookie. I find cookies generally suspicious, and don't
>> fully understand to what extent HTTP infrastructure (e.g. proxies)
>> can have a policy to not allow them, in which case a cookie based
>> approach would be limiting in such environments.
> Cookie is described as HTTP 1.0 extension in RFC 2109: HTTP State
> Management Mechanism, released in 1997. It has been revised several
> times and it is part of any decent HTTP implementation for ages. To be
> honest, I haven't looked for any other RFC for session management over
> HTTP, the cookie is really used everywhere.
>
> RFC 2616 (HTTP 1.1) says: Unrecognized header fields SHOULD be ignored
> by the recipient and MUST be forwarded by transparent proxies.
>
> So, client who do not support cookies SHOULD survive just with Basic
> authentication in every request, just like now. And proxies MUST forward
> the cookie.
>
>> - Obviously, it must be optional to support for both client and
>> server. Just to have it mentioned.
> The server is configurable.
>
> What benefit it has to turn it off on _client_ side? If a client
> receives a cookie, it indicates that the server supports it. The client
> just sends it back in subsequent requests. If the server decides that
> the cookie is not enough, the client processed 401 Unauthorized response
> as usual.
>
>> - One important consideration is whether we want it to work with both
>> HTTP and HTTPS, and with all HTTP authentication mechanisms. Someone
>> needs to draw the matrix of HTTP/HTTPS with supported authentication
>> mechanisms, and state for which ones the session ID approach would be
>> supported. That may shape the design significantly. For example, if
>> we supported it only for HTTPS, the session ID would not need to be
>> encrypted. If we also wanted to support it for HTTP, we maybe want to
>> see it encrypted.
> As the session ID is just a random number, encrypting it on HTTP won't
> help much, especially without proper handshake protocol to exchange
> keys, which you don't have on HTTP.
>
> In addition, it looks quite funny that cookie should be encrypted, while
> Basic authentication (the only one that Pegasus supports now) sends user
> password unencrypted in a HTTP header.
>
>
>> - There are sufficient screws and decisions in that whole approach,
>> so that we cannot assume this is just an OpenPegasus addition.
>> DSP0200 documents all standard HTTP headers that play a role in
>> CIM-XML, and it would need to describe this new ability as well. Karl
>> and I are in the CIM-XML WG, and it should not take very long, once
>> we have agreed upon the details on how to do it.
>>
>> To me, the open points are: - how to calculate the session ID. This
>> could be a recommendation for servers to keep them secure, because it
>> is opaque for clients. - which mechanism to use to transport the
>> session ID between client and server.
> I hope I explained my design and implementation above, feel free to ask
> anything.
>
> Jan
>