testing. On the ESOE side configuration should be similar to that posted
online for full blown Active Directory it would appear.
> Hi,
> I did some little research and now i understand that SPNEGO helps the
> client and server to negotiate which mechanism to choose like
> Kerberos. I found in the source code of Samba the spnego.c file and it
> tells me that they use a RFC2478 Compliant SPNEGO implementation. With
> functions like:
> read_negTokenInit, write_negTokenInit to initiate
> and read_negTokenTarg, write_negTokenTarg to talk after the init.
> But i don't know if it is a problem for ESOE that the SPNEGO function
> in samba is used to communicate with an Windows AD.
> Greets Martijn.
> The C file :
> /*
> Unix SMB/CIFS implementation.
> RFC2478 Compliant SPNEGO implementation
> Copyright (C) Jim McDonough <j...@us.ibm.com> 2003
> This program is free software; you can redistribute it and/or
> modify
> it under the terms of the GNU General Public License as published
> by
> the Free Software Foundation; either version 2 of the License, or
> (at your option) any later version.
> This program is distributed in the hope that it will be useful,
> but WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> GNU General Public License for more details.
> You should have received a copy of the GNU General Public License
> along with this program; if not, write to the Free Software
> Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> */
> #include "includes.h"
> #undef DBGC_CLASS
> #define DBGC_CLASS DBGC_AUTH
> static BOOL read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
> {
> ZERO_STRUCTP(token);
> asn1_start_tag(asn1, ASN1_CONTEXT(0));
> asn1_start_tag(asn1, ASN1_SEQUENCE(0));
> while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) {
> int i;
> switch (asn1->data[asn1->ofs]) {
> /* Read mechTypes */
> case ASN1_CONTEXT(0):
> asn1_start_tag(asn1, ASN1_CONTEXT(0));
> asn1_start_tag(asn1, ASN1_SEQUENCE(0));
> token->mechTypes = SMB_MALLOC_P(char *);
> for (i = 0; !asn1->has_error &&
> 0 < asn1_tag_remaining(asn1); i++) {
> token->mechTypes =
> SMB_REALLOC_ARRAY(token->mechTypes, char *, i + 2);
> asn1_read_OID(asn1, token->mechTypes + i);
> }
> token->mechTypes[i] = NULL;
> asn1_end_tag(asn1);
> asn1_end_tag(asn1);
> break;
> /* Read reqFlags */
> case ASN1_CONTEXT(1):
> asn1_start_tag(asn1, ASN1_CONTEXT(1));
> asn1_read_Integer(asn1, &token->reqFlags);
> token->reqFlags |= SPNEGO_REQ_FLAG;
> asn1_end_tag(asn1);
> break;
> /* Read mechToken */
> case ASN1_CONTEXT(2):
> asn1_start_tag(asn1, ASN1_CONTEXT(2));
> asn1_read_OctetString(asn1, &token->mechToken);
> asn1_end_tag(asn1);
> break;
> /* Read mecListMIC */
> case ASN1_CONTEXT(3):
> asn1_start_tag(asn1, ASN1_CONTEXT(3));
> if (asn1->data[asn1->ofs] == ASN1_OCTET_STRING) {
> asn1_read_OctetString(asn1,
> &token->mechListMIC);
> } else {
> /* RFC 2478 says we have an Octet String here,
> but W2k sends something different... */
> char *mechListMIC;
> asn1_push_tag(asn1, ASN1_SEQUENCE(0));
> asn1_push_tag(asn1, ASN1_CONTEXT(0));
> asn1_read_GeneralString(asn1, &mechListMIC);
> asn1_pop_tag(asn1);
> asn1_pop_tag(asn1);
> token->mechListMIC =
> data_blob(mechListMIC, strlen(mechListMIC));
> SAFE_FREE(mechListMIC);
> }
> asn1_end_tag(asn1);
> break;
> default:
> asn1->has_error = True;
> break;
> }
> }
> asn1_end_tag(asn1);
> asn1_end_tag(asn1);
> return !asn1->has_error;
> }
> static BOOL write_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
> {
> asn1_push_tag(asn1, ASN1_CONTEXT(0));
> asn1_push_tag(asn1, ASN1_SEQUENCE(0));
> /* Write mechTypes */
> if (token->mechTypes && *token->mechTypes) {
> int i;
> asn1_push_tag(asn1, ASN1_CONTEXT(0));
> asn1_push_tag(asn1, ASN1_SEQUENCE(0));
> for (i = 0; token->mechTypes[i]; i++) {
> asn1_write_OID(asn1, token->mechTypes[i]);
> }
> asn1_pop_tag(asn1);
> asn1_pop_tag(asn1);
> }
> /* write reqFlags */
> if (token->reqFlags & SPNEGO_REQ_FLAG) {
> int flags = token->reqFlags & ~SPNEGO_REQ_FLAG;
> asn1_push_tag(asn1, ASN1_CONTEXT(1));
> asn1_write_Integer(asn1, flags);
> asn1_pop_tag(asn1);
> }
> /* write mechToken */
> if (token->mechToken.data) {
> asn1_push_tag(asn1, ASN1_CONTEXT(2));
> asn1_write_OctetString(asn1, token->mechToken.data,
> token->mechToken.length);
> asn1_pop_tag(asn1);
> }
> /* write mechListMIC */
> if (token->mechListMIC.data) {
> asn1_push_tag(asn1, ASN1_CONTEXT(3));
> #if 0
> /* This is what RFC 2478 says ... */
> asn1_write_OctetString(asn1, token->mechListMIC.data,
> token->mechListMIC.length);
> #else
> /* ... but unfortunately this is what Windows
> sends/expects */
> asn1_push_tag(asn1, ASN1_SEQUENCE(0));
> asn1_push_tag(asn1, ASN1_CONTEXT(0));
> asn1_push_tag(asn1, ASN1_GENERAL_STRING);
> asn1_write(asn1, token->mechListMIC.data,
> token->mechListMIC.length);
> asn1_pop_tag(asn1);
> asn1_pop_tag(asn1);
> asn1_pop_tag(asn1);
> #endif
> asn1_pop_tag(asn1);
> }
> asn1_pop_tag(asn1);
> asn1_pop_tag(asn1);
> return !asn1->has_error;
> }
> static BOOL read_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token)
> {
> ZERO_STRUCTP(token);
> asn1_start_tag(asn1, ASN1_CONTEXT(1));
> asn1_start_tag(asn1, ASN1_SEQUENCE(0));
> while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) {
> switch (asn1->data[asn1->ofs]) {
> case ASN1_CONTEXT(0):
> asn1_start_tag(asn1, ASN1_CONTEXT(0));
> asn1_start_tag(asn1, ASN1_ENUMERATED);
> asn1_read_uint8(asn1, &token->negResult);
> asn1_end_tag(asn1);
> asn1_end_tag(asn1);
> break;
> case ASN1_CONTEXT(1):
> asn1_start_tag(asn1, ASN1_CONTEXT(1));
> asn1_read_OID(asn1, &token->supportedMech);
> asn1_end_tag(asn1);
> break;
> case ASN1_CONTEXT(2):
> asn1_start_tag(asn1, ASN1_CONTEXT(2));
> asn1_read_OctetString(asn1, &token->responseToken);
> asn1_end_tag(asn1);
> break;
> case ASN1_CONTEXT(3):
> asn1_start_tag(asn1, ASN1_CONTEXT(3));
> asn1_read_OctetString(asn1, &token->mechListMIC);
> asn1_end_tag(asn1);
> break;
> default:
> asn1->has_error = True;
> break;
> }
> }
> asn1_end_tag(asn1);
> asn1_end_tag(asn1);
> return !asn1->has_error;
> }
> static BOOL write_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token)
> {
> asn1_push_tag(asn1, ASN1_CONTEXT(1));
> asn1_push_tag(asn1, ASN1_SEQUENCE(0));
> asn1_push_tag(asn1, ASN1_CONTEXT(0));
> asn1_write_enumerated(asn1, token->negResult);
> asn1_pop_tag(asn1);
> if (token->supportedMech) {
> asn1_push_tag(asn1, ASN1_CONTEXT(1));
> asn1_write_OID(asn1, token->supportedMech);
> asn1_pop_tag(asn1);
> }
> if (token->responseToken.data) {
> asn1_push_tag(asn1, ASN1_CONTEXT(2));
> asn1_write_OctetString(asn1, token->responseToken.data,
> token->responseToken.length);
> asn1_pop_tag(asn1);
> }
> if (token->mechListMIC.data) {
> asn1_push_tag(asn1, ASN1_CONTEXT(3));
> asn1_write_OctetString(asn1, token->mechListMIC.data,
> token->mechListMIC.length);
> asn1_pop_tag(asn1);
> }
> asn1_pop_tag(asn1);
> asn1_pop_tag(asn1);
> return !asn1->has_error;
> }
> ssize_t read_spnego_data(DATA_BLOB data, SPNEGO_DATA *token)
> {
> ASN1_DATA asn1;
> ssize_t ret = -1;
> ZERO_STRUCTP(token);
> ZERO_STRUCT(asn1);
> asn1_load(&asn1, data);
> switch (asn1.data[asn1.ofs]) {
> case ASN1_APPLICATION(0):
> asn1_start_tag(&asn1, ASN1_APPLICATION(0));
> asn1_check_OID(&asn1, OID_SPNEGO);
> if (read_negTokenInit(&asn1, &token->negTokenInit)) {
> token->type = SPNEGO_NEG_TOKEN_INIT;
> }
> asn1_end_tag(&asn1);
> break;
> case ASN1_CONTEXT(1):
> if (read_negTokenTarg(&asn1, &token->negTokenTarg)) {
> token->type = SPNEGO_NEG_TOKEN_TARG;
> }
> break;
> default:
> break;
> }
> if (!asn1.has_error) ret = asn1.ofs;
> asn1_free(&asn1);
> return ret;
> }
> ssize_t write_spnego_data(DATA_BLOB *blob, SPNEGO_DATA *spnego)
> {
> ASN1_DATA asn1;
> ssize_t ret = -1;
> ZERO_STRUCT(asn1);
> switch (spnego->type) {
> case SPNEGO_NEG_TOKEN_INIT:
> asn1_push_tag(&asn1, ASN1_APPLICATION(0));
> asn1_write_OID(&asn1, OID_SPNEGO);
> write_negTokenInit(&asn1, &spnego->negTokenInit);
> asn1_pop_tag(&asn1);
> break;
> case SPNEGO_NEG_TOKEN_TARG:
> write_negTokenTarg(&asn1, &spnego->negTokenTarg);
> break;
> default:
> asn1.has_error = True;
> break;
> }
> if (!asn1.has_error) {
> *blob = data_blob(asn1.data, asn1.length);
> ret = asn1.ofs;
> }
> asn1_free(&asn1);
> return ret;
> }
> BOOL free_spnego_data(SPNEGO_DATA *spnego)
> {
> BOOL ret = True;
> if (!spnego) goto out;
> switch(spnego->type) {
> case SPNEGO_NEG_TOKEN_INIT:
> if (spnego->negTokenInit.mechTypes) {
> int i;
> for (i = 0; spnego->negTokenInit.mechTypes[i]; i++) {
> free(spnego->negTokenInit.mechTypes[i]);
> }
> free(spnego->negTokenInit.mechTypes);
> }
> data_blob_free(&spnego->negTokenInit.mechToken);
> data_blob_free(&spnego->negTokenInit.mechListMIC);
> break;
> case SPNEGO_NEG_TOKEN_TARG:
> if (spnego->negTokenTarg.supportedMech) {
> free(spnego->negTokenTarg.supportedMech);
> }
> data_blob_free(&spnego->negTokenTarg.responseToken);
> data_blob_free(&spnego->negTokenTarg.mechListMIC);
> break;
> default:
> ret = False;
> break;
> }
> ZERO_STRUCTP(spnego);
> out:
> return ret;
> On Jun 2, 12:37 am, Bradley Beddoes <bedd...@intient.com> wrote:
>> Hello,
>> Martijn van der Plaat wrote:
>>> Hi Bradley,
>>> At the moment i don't have much pratical experience with Samba. I dont
>>> really understand the function of SPNEGO.
>> This wikipedia article and associated (linked) RFC's etc may be of
>> assistance to youhttp://en.wikipedia.org/wiki/SPNEGO
>>> I know that SAMBA can be configured with LDAP as backend. On the ESOE
>>> website i saw the graphical picture with LDAP as a possible solution
>>> beside the Windows Login service (that is i think the Active Directory
>>> integration you mean).
>>> So the trick lays in the LDAP session? If that LDAP connection to ESOE
>>> in the picture means that the LDAP session can be integrated in ESOE
>>> it would be great. But again i don't fully understand how things
>>> work.
>> Essentially your looking at either using native LDAP integration or
>> SPNEGO support (you can use both in sequence, if ESOE detects no SPNEGO
>> support it will fall through to native LDAP support with an associated
>> web form).
>>> Maybe you can tell how to do this? I want to take effort in realising
>>> this SAMBA-ESOE connection.
>> Basically you'd want to configure your PDC and the ESOE to utilize the
>> same LDAP server for authentication. When a user logs into their
>> workstation their credentials will ultimately be validated against this
>> LDAP server. Once this is completed (assuming Samba support for SPNEGO
>> is a go) their Windows machines will have access to tokens which ESOE
>> (also configured to talk to your PDC) can accept and validate.
>> For users not logged into the domain (off site for example) they will be
>> presented with a web form to enter their credentials for initial
>> authentication, this will be validated directly against your LDAP server
>> (no PDC involvement at all here).
>> By going with this approach you only have a single store of
>> users/credentials and for end users this means the same
>> username/password to access their workstations and web tier content.
>> The next step is probably to figure out just what level of SPNEGO
>> support a SAMBA PDC exports, if it can give everything we require on the
>> previous configuration URL i sent you then its probably good to go.
>> regards,
>> Bradley
>>> Greets.
>>> Martijn van der Plaat
>>> On 1 jun, 08:13, Bradley Beddoes <bedd...@intient.com> wrote:
>>>> Hi,
>>>> We already have an authentication mechanism in place which allows ESOE
>>>> to integrate with a domain controller setup provided by Windows servers
>>>> which we've documented here:http://esoeproject.org/confluence/display/eu/ESOE+to+Active+Directory...
>>>> Essentially this allows a user to login to their workstation of a
>>>> morning and automatically be provided access to ESOE services we call
>>>> this "true single sign on" and the clients we have who've deployed it
>>>> really love it. In the back end there is a bunch of SPNEGO ticket
>>>> validation going on.
>>>> Does the Samba PDC provide the SPNEGO type functionality? If so it may
>>>> not be much effort to test an ESOE setup against a Samba PDC and
>>>> validate this works.
>>>> I hope I've interpreted your query below correctly, please correct me if
>>>> I've totally misread your requirements :).
>>>> regards,
>>>> Bradley
>>>> --
>>>> Bradley Beddoes
>>>> Lead Software Architect
>>>> Intient Pty Ltd
>>>> Join me on LinkedIn:http://www.linkedin.com/in/beddoes
>>>> Martijn van der Plaat wrote:
>>>>> Hi all,
>>>>> I was wondering if it is possible when SAMBA is configured with LDAP
>>>>> as authentication backend and ESOE is configured with LDAP as
>>>>> authentication source the SAMBA session is available in ESOE.
>>>>> This connection is great because when as user logs in to the PDC the
>>>>> user is also connected to the applications that are connected to ESOE
>>>>> like blackboard, Google Apps, or OpenID or some other application.
>>>>> Greets Martijn.
>> --
>> Bradley Beddoes
>> Lead Software Architect
>> Intient Pty Ltd
>> Join me on LinkedIn:http://www.linkedin.com/in/beddoes- Hide quoted text -
>> - Show quoted text -