Logo Search packages:      
Sourcecode: ike version File versions  Download package

ike.xauth.cpp

/*
 * Copyright (c) 2007
 *      Shrew Soft Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Redistributions in any form must be accompanied by information on
 *    how to obtain complete source code for the software and any
 *    accompanying software that uses the software.  The source code
 *    must either be included in the distribution or be available for no
 *    more than the cost of distribution plus a nominal fee, and must be
 *    freely redistributable under reasonable conditions.  For an
 *    executable file, complete source code means the source code for all
 *    modules it contains.  It does not include source code for modules or
 *    files that typically accompany the major components of the operating
 *    system on which the executable file runs.
 *
 * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT, ARE DISCLAIMED.  IN NO EVENT SHALL SHREW SOFT INC
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 *
 * AUTHOR : Matthew Grooms
 *          mgrooms@shrew.net
 *
 */

#include "iked.h"

//
// XAUTH - BASE CLASS
//

_IKED_XAUTH::~_IKED_XAUTH()
{
}

//
// XAUTH - LOCAL ACCOUNT DB
//

static const char * iked_xauth_local_name = "local";

_IKED_XAUTH_LOCAL::_IKED_XAUTH_LOCAL()
{
}

_IKED_XAUTH_LOCAL::~_IKED_XAUTH_LOCAL()
{
}

const char * _IKED_XAUTH_LOCAL::name()
{
      return iked_xauth_local_name;
}

bool _IKED_XAUTH_LOCAL::auth_pwd( IKE_XAUTH & xauth )
{
      //
      // null terminate username and password
      //

      xauth.user.add( 0, 1 );
      xauth.pass.add( 0, 1 );

      const char * usr = ( const char * ) xauth.user.buff();
      const char * pwd = ( const char * ) xauth.pass.buff();

#ifdef UNIX

      struct passwd * pw = getpwnam( usr );

      if( pw == NULL )
            return false;

      if( pw->pw_uid == 0 )
            return false;

#ifdef OPT_SHADOW

      struct spwd * spw = getspnam( usr );

      if( spw == NULL )
            return false;

      char * syscryptpwd = spw->sp_pwdp;

#else

      char * syscryptpwd = pw->pw_passwd;

#endif

      char * cryptpwd = crypt( pwd, syscryptpwd ); 
      if( cryptpwd == NULL )
            return false;

      if( !strcmp( cryptpwd, syscryptpwd ) )
            return true;

#endif

      return false;
}

bool _IKED_XAUTH_LOCAL::auth_grp( IKE_XAUTH & xauth, BDATA & group )
{

#ifdef UNIX

      const char * usr = ( const char * ) xauth.user.buff();
      const char * grp = ( const char * ) group.buff();

      struct group * gr = getgrnam( grp );
      if( gr == NULL )
            return false;

      char * member;
      int index = 0;
      while( ( member = gr->gr_mem[ index++ ] ) != NULL )
            if( !strcmp( member, usr ) )
                  return true;

#endif

      return false;
}

//
// XAUTH - LDAP ACCOUNT DB
//

#ifdef OPT_LDAP

static const char * iked_xauth_ldap_name = "ldap";

_IKED_XAUTH_LDAP::_IKED_XAUTH_LDAP()
{
      //
      // set ldap defaults
      //

      version = 3;
      subtree = false;
      attr_user.set( "cn", strlen( "cn" ) + 1 );
      attr_group.set( "cn", strlen( "cn" ) + 1 );
      attr_member.set( "member", strlen( "member" ) + 1 );
}

_IKED_XAUTH_LDAP::~_IKED_XAUTH_LDAP()
{
}

const char * _IKED_XAUTH_LDAP::name()
{
      return iked_xauth_ldap_name;
}

bool _IKED_XAUTH_LDAP::open_conn( LDAP ** ld )
{
      // initialize the ldap handle

      int res = ldap_initialize( ld, url.text() );
      if( res != LDAP_SUCCESS )
      {
            iked.log.txt( LOG_ERROR,
                  "!! : xauth ldap initialize failed ( %s )\n",
                  ldap_err2string( res ) );

            return false;
      }

      // initialize the protocol version

      ldap_set_option( *ld,
            LDAP_OPT_PROTOCOL_VERSION,
            &version );

      //
      // attempt to bind to the ldap server.
    // default to anonymous bind unless a
      // user dn and password has been
      // specified in our configuration
    //

      if( bind_dn.size() && bind_pw.size() )
      {
            struct berval cred;
            cred.bv_val = bind_pw.text();
            cred.bv_len = bind_pw.size() - 1;

            res = ldap_sasl_bind_s( *ld,
                        bind_dn.text(), NULL, &cred,
                        NULL, NULL, NULL );
      }
      else
      {
            res = ldap_sasl_bind_s( *ld,
                        NULL, NULL, NULL,
                        NULL, NULL, NULL );
      }
      
      if( res != LDAP_SUCCESS )
      {
            iked.log.txt( LOG_ERROR,
                  "!! : xauth ldap search bind failed ( %s )\n",
                  ldap_err2string( res ) );

            ldap_unbind_ext_s( *ld, NULL, NULL );

            return false;
      }

      return true;
}

bool _IKED_XAUTH_LDAP::auth_pwd( IKE_XAUTH & xauth )
{
      bool result = false;

      LDAP *      ld = NULL;
      BDATA filter;
      char *      atlist[ 1 ] = { NULL };
      char *      userdn = NULL;
      int         scope = LDAP_SCOPE_ONELEVEL;
      int   ecount = 0;

      LDAPMessage * lr = NULL;
      LDAPMessage * le = NULL;

      // open an ldap connection

      if( !open_conn( &ld ) )
            return false;

      // build an ldap user search filter

      filter.add( attr_user.buff(), attr_user.size() - 1 );
      filter.add( "=", 1 );
      filter.add( xauth.user.buff(), xauth.user.size() - 1 );
      filter.add( 0, 1 );
      
      // attempt to locate the user dn

      if( subtree )
            scope = LDAP_SCOPE_SUBTREE;

      struct timeval timeout;
      timeout.tv_sec = 15;
      timeout.tv_usec = 0;

      int res = ldap_search_ext_s( ld,
                        base.text(),
                        scope,
                        filter.text(),
                        atlist,
                        0,
                        NULL,
                        NULL,
                        &timeout,
                        2,
                        &lr );

      if( res != LDAP_SUCCESS )
      {
            iked.log.txt( LOG_ERROR,
                  "!! : xauth ldap user search failed ( %s )\n",
                  ldap_err2string( res ) );

            goto ldap_pwd_end;
      }

      // check the number of ldap entries returned

      ecount = ldap_count_entries(ld, lr);
      if( ecount < 1 )
            goto ldap_pwd_end;

      if( ecount > 1 )
      {
            iked.log.txt( LOG_ERROR,
                  "!! : warning, ldap return multiple results for user %s\n",
                  xauth.user.buff() );
      }

      // obtain the first result entry

      le = ldap_first_entry( ld, lr );

      if( le == NULL )
      {
            iked.log.txt( LOG_ERROR,
                  "!! : xauth ldap unable to read result entry" );

            goto ldap_pwd_end;
      }

      // obtain the result entry dn

      userdn = ldap_get_dn( ld, le );

      if( userdn == NULL )
      {
            iked.log.txt( LOG_ERROR,
                  "!! : xauth ldap unable to read result dn" );

            goto ldap_pwd_end;
      }

      // cache the user dn in the xauth state

      xauth.context.set( userdn, strlen( userdn ) + 1 );

      //
      // finally, use the dn and the xauth
      // password to check the users given
      // credentials by attempting to bind
      // to the ldap server
      //

      struct berval cred;
      cred.bv_val = ( char * ) xauth.pass.buff();
      cred.bv_len = xauth.pass.size() - 1;

      res = ldap_sasl_bind_s(
                  ld,
                  userdn,
                  NULL,
                  &cred,
                  NULL,
                  NULL,
                  NULL);

      if( res == LDAP_SUCCESS )
            result = true;

ldap_pwd_end:

      // free ldap resources

      if( userdn != NULL )
            ldap_memfree( userdn );

      if( lr != NULL )
            ldap_msgfree( lr );

      ldap_unbind_ext_s( ld, NULL, NULL );

      return result;
}

bool _IKED_XAUTH_LDAP::auth_grp( IKE_XAUTH & xauth, BDATA & group )
{
      bool result = false;

      LDAP *      ld = NULL;
      BDATA filter;
      char *      atlist[ 1 ] = { NULL };
      int         scope = LDAP_SCOPE_ONELEVEL;
      int   ecount = 0;

      LDAPMessage * lr = NULL;

      // open an ldap connection

      if( !open_conn( &ld ) )
            return false;

      // build an ldap group search filter

      filter.add( "(&(", 3 );
      filter.add( attr_group.buff(), attr_group.size() - 1 );
      filter.add( "=", 1 );
      filter.add( group.buff(), group.size() - 1 );
      filter.add( ")(", 2 );
      filter.add( attr_member.buff(), attr_member.size() - 1 );
      filter.add( "=", 1 );
      filter.add( xauth.context.buff(), xauth.context.size() - 1 );
      filter.add( "))", 2 );
      filter.add( 0, 1 );

      // attempt to locate the group dn

      if( subtree )
            scope = LDAP_SCOPE_SUBTREE;

      struct timeval timeout;
      timeout.tv_sec = 15;
      timeout.tv_usec = 0;

      int res = ldap_search_ext_s( ld,
                        base.text(),
                        scope,
                        filter.text(),
                        atlist,
                        0,
                        NULL,
                        NULL,
                        &timeout,
                        2,
                        &lr );

      if( res != LDAP_SUCCESS )
      {
            iked.log.txt( LOG_ERROR,
                  "!! : xauth ldap group search failed ( %s )\n",
                  ldap_err2string( res ) );

            goto ldap_grp_end;
      }

      // check the number of ldap entries returned

      ecount = ldap_count_entries( ld, lr );
      if( ecount < 1 )
            goto ldap_grp_end;

      if( ecount > 1 )
      {
            iked.log.txt( LOG_ERROR,
                  "!! : warning, ldap return multiple results for group %s\n",
                  group.buff() );
      }

      // found a valid group membership

      result = true;

ldap_grp_end:

      // free ldap resources

      if( lr != NULL )
            ldap_msgfree( lr );

      ldap_unbind_ext_s( ld, NULL, NULL );

      return result;
}

#endif

Generated by  Doxygen 1.6.0   Back to index