Google Groups Home
Help | Sign in
Message from discussion ESOE with SAMBA authentication
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
Martijn van der Plaat  
View profile
 More options Jun 3, 3:51 am
From: Martijn van der Plaat <martijnpl...@gmail.com>
Date: Mon, 2 Jun 2008 10:51:52 -0700 (PDT)
Local: Tues, Jun 3 2008 3:51 am
Subject: Re: ESOE with SAMBA authentication
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 -


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2008 Google