Hello,
I have a question that is maybe a little too advanced for the usual list
so I'm hoping I can ask here.
I want to write an extension for Kerberos 5 Single Sign On using
GSSAPI. The problem is that GSSAPI is an iterative, multistep, statefull
exchange. The request response flow might look like the following:
C: GET /foo ---------->
<---------- S: 401 Unauthorized
WWW-Authenticate: Negotiate
C: GET /foo ---------->
Authorization: Negotiate <base64-token-1>
<---------- S: 401 Unauthorized
WWW-Authenticate: Negotiate <base64-token-2>
C: GET /foo ---------->
Authorization: Negotiate <base64-token-3>
<---------- S: 200
<data>
[Actually no state must be maintained for the initial request/response
and for the Kerberos mechanism there's usually only two tokens which
makes the whole exchange stateless. But for NTLMSSP there can be three
tokens exchanged as depicted above and GSSAPI places no limit on the
number of tokens exchanged for a given mechanism.]
I'm sure you can imagine the headaches involved with trying to perform
a stateful exchange over HTTP. In general the prevailing technique is
to use a session cookie to maintain the state during the exchange. For
example one might write this in PHP roughly like the following:
function authenticate() {
if (!isset($_SESSION["sso"])) {
$_SESSION["sso"] = sso_new();
}
$sso = $_SESSION["sso"];
$token = "";
$headers = apache_request_headers();
if (isset($headers["Authorization"])) {
$token = $headers["Authorization"];
$token = sso_do_gssapi($sso, $token);
switch (sso_status($sso)) {
case SSO_SUCCESS:
$_SESSION["auth"] = $sso;
case SSO_FAILURE:
unset($_SESSION["sso"]);
return $sso;
}
$token = " " . $token;
}
header("WWW-Authenticate: Negotiate" . $token);
header("HTTP/1.1 401 Unauthorized");
die("More processing required.");
}
I've read the tutorials and I have a working extension package but I
need a better understanding of ZE internals with respect to maintaining
state across requests. All of the examples register a dtor such that any
variable returned is garbage collected after the request completes. For
example, in the code above, if sso_new were to return a resource it is
automatically unset from $_SESSION. I need it to persist.
Ultimately I want to create one 'struct sso_context *' stored as a global
(or one per MINIT is ok) from which I will derive 'struct sso *' objects
in sso_new() that must persist for the life of the user's session. Can
someone recommend a good technique for this?
Thanks,
Mike
Just curious, why aren't you writing this as an apache module?
Is this of any use; it seems a bit dated, but could save you some effort:
http://meta.cesnet.cz/cms/opencms/en/docs/software/devel/negotiate.html
--Wez.
Hello,
I have a question that is maybe a little too advanced for the usual list
so I'm hoping I can ask here.I want to write an extension for Kerberos 5 Single Sign On using
GSSAPI. The problem is that GSSAPI is an iterative, multistep, statefull
exchange. The request response flow might look like the following:C: GET /foo ---------->
<---------- S: 401 Unauthorized
WWW-Authenticate: Negotiate
C: GET /foo ---------->
Authorization: Negotiate <base64-token-1>
<---------- S: 401 Unauthorized
WWW-Authenticate: Negotiate <base64-token-2>
C: GET /foo ---------->
Authorization: Negotiate <base64-token-3>
<---------- S: 200
<data>[Actually no state must be maintained for the initial request/response
and for the Kerberos mechanism there's usually only two tokens which
makes the whole exchange stateless. But for NTLMSSP there can be three
tokens exchanged as depicted above and GSSAPI places no limit on the
number of tokens exchanged for a given mechanism.]I'm sure you can imagine the headaches involved with trying to perform
a stateful exchange over HTTP. In general the prevailing technique is
to use a session cookie to maintain the state during the exchange. For
example one might write this in PHP roughly like the following:function authenticate() { if (!isset($_SESSION["sso"])) { $_SESSION["sso"] = sso_new(); } $sso = $_SESSION["sso"]; $token = ""; $headers = apache_request_headers(); if (isset($headers["Authorization"])) { $token = $headers["Authorization"]; $token = sso_do_gssapi($sso, $token); switch (sso_status($sso)) { case SSO_SUCCESS: $_SESSION["auth"] = $sso; case SSO_FAILURE: unset($_SESSION["sso"]); return $sso; } $token = " " . $token; } header("WWW-Authenticate: Negotiate" . $token); header("HTTP/1.1 401 Unauthorized"); die("More processing required."); }
I've read the tutorials and I have a working extension package but I
need a better understanding of ZE internals with respect to maintaining
state across requests. All of the examples register a dtor such that any
variable returned is garbage collected after the request completes. For
example, in the code above, if sso_new were to return a resource it is
automatically unset from $_SESSION. I need it to persist.Ultimately I want to create one 'struct sso_context *' stored as a global
(or one per MINIT is ok) from which I will derive 'struct sso *' objects
in sso_new() that must persist for the life of the user's session. Can
someone recommend a good technique for this?Thanks,
Mike
On Wed, 21 Dec 2005 01:58:41 -0500
Wez Furlong kingwez@gmail.com wrote:
Just curious, why aren't you writing this as an apache module?
Is this of any use; it seems a bit dated, but could save you some effort:
http://meta.cesnet.cz/cms/opencms/en/docs/software/devel/negotiate.html
Well for one, mod_auth_gss_krb5 only does authentication. My real
product is Windows integration libraries for non-Windows environments
(i.e. LAMP). So, for example, this SSO module is going to include Windows
authorization functionality for integration with AD. Meaning the developer
can restrict content based on group membership of groups defined in an
AD domain:
$auth = sso_authenticate();
if (!sso_is_member($auth, "Authenticated Users")) {
header("Location: /login.php");
die("You are not authorized to access this content.");
}
...
if (sso_is_member($auth, "FOONET\Engineers")) {
echo "Engineers rule!";
} else if (sso_is_member($auth, "FOONET\Consultants")) {
echo "Consultants rule!";
}
Also I think there's also alot of polish that can go into failing over to
other authentication methods and redirecting to login pages and so on. You
just can't do any of this well unless your at the language level.
Mike
So you're duplicating the ldap extension? :)
--Jani
On Wed, 21 Dec 2005 01:58:41 -0500
Wez Furlong kingwez@gmail.com wrote:Just curious, why aren't you writing this as an apache module?
Is this of any use; it seems a bit dated, but could save you some effort:
http://meta.cesnet.cz/cms/opencms/en/docs/software/devel/negotiate.htmlWell for one, mod_auth_gss_krb5 only does authentication. My real
product is Windows integration libraries for non-Windows environments
(i.e. LAMP). So, for example, this SSO module is going to include Windows
authorization functionality for integration with AD. Meaning the developer
can restrict content based on group membership of groups defined in an
AD domain:$auth = sso_authenticate();
if (!sso_is_member($auth, "Authenticated Users")) {
header("Location: /login.php");
die("You are not authorized to access this content.");
}...
if (sso_is_member($auth, "FOONET\Engineers")) {
echo "Engineers rule!";
} else if (sso_is_member($auth, "FOONET\Consultants")) {
echo "Consultants rule!";
}Also I think there's also alot of polish that can go into failing over to
other authentication methods and redirecting to login pages and so on. You
just can't do any of this well unless your at the language level.Mike
On Wed, 21 Dec 2005 12:27:39 +0200 (EET)
Jani Taskinen sniper@iki.fi wrote:
So you're duplicating the ldap extension? :)
Yeah, you might be able to do it that way. But considering the Kerberos
ticket has the SIDs and LDAP would have to perform group expansion each
time I think a DCE/RPC SID lookup would be a little faster. Actually it
could be a lot faster if you do things like cache the SIDs since many
people would have the same ones.
Mike
On Wed, 21 Dec 2005 03:56:06 -0500
mba2000@ioplex.com (Michael B Allen) wrote:
On Wed, 21 Dec 2005 01:58:41 -0500
Wez Furlong kingwez@gmail.com wrote:Just curious, why aren't you writing this as an apache module?
Is this of any use; it seems a bit dated, but could save you some
effort:
http://meta.cesnet.cz/cms/opencms/en/docs/software/devel/negotiate.htmlWell for one, mod_auth_gss_krb5 only does authentication. My real
product is Windows integration libraries for non-Windows environments
(i.e. LAMP). So, for example, this SSO module is going to include
Windows authorization functionality for integration with AD. Meaning
the developer can restrict content based on group membership of
groups defined in an AD domain:
There is already some NTLM modules for apache. A php version will may
be available in PEAR. NTLM is what you are trying to achieve, or a part
of it. Single Sign On is another problem, and can be done with various
auth mechanisms. Are you implementing SSO as well? :)
--Pierre
On Wed, 21 Dec 2005 14:06:13 +0100
Pierre pierre.dev@gmail.com wrote:
On Wed, 21 Dec 2005 03:56:06 -0500
mba2000@ioplex.com (Michael B Allen) wrote:On Wed, 21 Dec 2005 01:58:41 -0500
Wez Furlong kingwez@gmail.com wrote:Just curious, why aren't you writing this as an apache module?
Is this of any use; it seems a bit dated, but could save you some
effort:
http://meta.cesnet.cz/cms/opencms/en/docs/software/devel/negotiate.htmlWell for one, mod_auth_gss_krb5 only does authentication. My real
product is Windows integration libraries for non-Windows environments
(i.e. LAMP). So, for example, this SSO module is going to include
Windows authorization functionality for integration with AD. Meaning
the developer can restrict content based on group membership of
groups defined in an AD domain:There is already some NTLM modules for apache. A php version will may
be available in PEAR. NTLM is what you are trying to achieve, or a part
of it. Single Sign On is another problem, and can be done with various
auth mechanisms. Are you implementing SSO as well? :)
Actually I don't think you're going to be satisfied with NTLM. Here's a
few reasons:
- W2K3 requires SMB signing by default and with NTLM you don't have
the plain text equivalent password hash necessary to generate a valid
MAC key. You have to setup credentials to perform the initial connect
to the DC which is ugly because people don't want to put passwords into
config files. - You cannot perform delegation with NTLM. That's one of the principal
reasons why MS has moved to Kerberos. So if you want to use the negotiated
credentials to then connect to other resources like file servers it will
not work [1]. - Prevailing security policy these days is moving away from NTLM. At
some point you're going to run into an admin that refuses to support it
in which case you must also implement NTLMv2. - For NTLM or NTLMv2 you must implement NTLMSSP which is not supported
by Heimdal or MIT Kerberos GSSAPI implementations (although I might fix
this soon).
Basically NTLM is depricated. NTLMv2 is still used when communicating
with non-domain members but Kerberos is a much nicer system and honestly
it's probably easier considering there are GSSAPI implementations that
can do the heavy lifting for you now.
Mike
[1] Actually you can proxy NTLM but that means you must renegotiate with
each resource you try to access.