[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: (ITS#4750) libldap initialization of ~/.ldaprc and setuid



Sorry for the late reply, I never saw this followup until now.

The idea of using multiple contexts is good. I'm thinking though that we can do 
this simply by copying LDAP* session handles around, rather than introducing a 
new LDAPContext structure. That will minimize the impact on application 
writers, and allow us to continue using the current ldap_set_option() unchanged.

timo@physik.uni-potsdam.de wrote:

> Hi,
> 
> OpenLDAP issue ITS#4750 is still unresolved (it affects current
> versions of nss_ldap and pam_ldap), and I consider it to be pretty
> serious:
> - Even security-conscious applications like pam_ldap still parse
>   files from unsafe locations, including the current directory.
> - Attempting to read from a file in the current directory can
>   cause problems on its own, e.g. when the directory is an autofs
>   mountpoint (In fact, I became aware of this issue by investigating
>   deadlocks occurring in such a situation)
> - If an application uses LDAP in more than one context, like a
>   program using LDAP while also linking to nss_ldap and pam_ldap,
>   the settings can interfere (unless very much care is taken, see
>   below).  This is bad, as the very purpose of nss and pam is to
>   make the underlying mechanisms completely transparent to the
>   application.
> - The existing LDAPNOINIT mechanism is only effective for the first
>   call which initializes the global option structure. Thus, almost
>   no one can reliably use it: the options may already have been
>   initialized e.g. by nss_ldap which nearly every program might
>   link to.
> 
> The suggested workaround so far is to force nss_ldap, pam_ldap, and
> possibly others, to override all relevant options with safe values.
> To me, this seems to be quite error-prone and not a satisfactory
> solution:
> - it requires duplication of much of the configuration parsing code,
>   which needs to be kept in sync with OpenLDAP's syntax and semantics
>   (or worse, allow the syntax to diverge), and
> - it requires users to think of and nail down each and every potentially
>   relevant option separately (note that current versions of libldap and
>   pam_ldap silently ignore syntax errors in the config file, so one may
>   very easily be in a false sense of security).
> - It does not stop libldap from opening files it shouldn't open in the
>   first place.
> As Kurt Zeilenga already noted, a proper solution will require some
> redesign, so...
> 
> I include 3 patches: one for libldap (against HEAD as of 20070216), and
> corresponding patches for nss_ldap-254 and pam_ldap-183.
> 
> The first lines of the openldap patch (the changes to ldap.h) and
> the nss_ldap patch should tell you how it is supposed to work:
> libraries can obtain a private copy of the "globaloptions",
> in an opaque "LDAPContext" object, to be initialized in a safe way
> and independently from other copies of that structure.
> The existing struct globaloptions is used by default to stay compatible
> with existing programs.
> 
> I'm willing to write more documentation too but I would like to get
> some some feedback on it first,
> 
> Regards,
> 
> Timo Felbinger
> 
> 
> --pf9I7BMVVzbSWLtt
> Content-Type: text/plain; charset=us-ascii
> Content-Disposition: attachment; filename="openldap.patch"
> 
> This patch file is derived from OpenLDAP Software. All of the modifications to
> OpenLDAP Software represented in the following patch(es) were developed by
> Timo Felbinger <timo@physik.uni-potsdam.de>.
> These modifications are not subject to any license of University of Potsdam.
> 
> I, Timo Felbinger, hereby place the following modifications to OpenLDAP Software
> (and only these modifications) into the public domain.
> Hence, these modifications may be freely used and/or redistributed for any purpose
> with or without attribution and/or other notice. 
> 
> diff -Nru openldap-src/include/ldap.h openldap-src-context/include/ldap.h
> --- openldap-src/include/ldap.h	2007-02-12 10:53:59.000000000 +0000
> +++ openldap-src-context/include/ldap.h	2007-02-17 13:22:45.000000000 +0000
> @@ -696,6 +696,8 @@
>   */
>  typedef struct ldap LDAP;
>  
> +typedef struct ldapoptions LDAPContext;
> +
>  #define LDAP_DEREF_NEVER		0x00
>  #define LDAP_DEREF_SEARCHING	0x01
>  #define LDAP_DEREF_FINDING		0x02
> @@ -890,6 +892,12 @@
>  	int option,
>  	LDAP_CONST void *invalue));
>  
> +LDAP_F( int )
> +ldap_set_option_in_context LDAP_P((
> +	LDAPContext *context,
> +	int option,
> +	LDAP_CONST void *invalue));
> +
>  /* V3 REBIND Function Callback Prototype */
>  typedef int (LDAP_REBIND_PROC) LDAP_P((
>  	LDAP *ld, LDAP_CONST char *url,
> @@ -1382,10 +1390,30 @@
>  	LDAP **ldp ));
>  
>  LDAP_F( int )
> +ldap_create_in_context LDAP_P((
> +	LDAP **ldp,
> +	LDAPContext *context ));
> +
> +LDAP_F( int )
>  ldap_initialize LDAP_P((
>  	LDAP **ldp,
>  	LDAP_CONST char *url ));
>  
> +LDAP_F( int )
> +ldap_initialize_in_context LDAP_P((
> +	LDAP **ldp,
> +	LDAP_CONST char *url,
> +	LDAPContext *context ));
> +
> +LDAP_F( int )
> +ldap_create_context LDAP_P((
> +	LDAPContext **context,
> +	char **directives ));
> +
> +LDAP_F( int )
> +ldap_destroy_context LDAP_P((
> +	LDAPContext *context ));
> +
>  /*
>   * in tls.c
>   */
> diff -Nru openldap-src/include/ldap_pvt.h openldap-src-context/include/ldap_pvt.h
> --- openldap-src/include/ldap_pvt.h	2007-02-12 03:20:24.000000000 +0000
> +++ openldap-src-context/include/ldap_pvt.h	2007-02-17 13:22:45.000000000 +0000
> @@ -278,6 +278,8 @@
>  	int option, void *arg ));
>  LDAP_F (int) ldap_pvt_tls_set_option LDAP_P(( struct ldap *ld,
>  	int option, void *arg ));
> +LDAP_F (int) ldap_pvt_tls_set_option_2 LDAP_P(( struct ldapoptions *lo, struct ldap *ld,
> +	int option, void *arg ));
>  
>  LDAP_F (void) ldap_pvt_tls_destroy LDAP_P(( void ));
>  LDAP_F (int) ldap_pvt_tls_init LDAP_P(( void ));
> diff -Nru openldap-src/libraries/libldap/init.c openldap-src-context/libraries/libldap/init.c
> --- openldap-src/libraries/libldap/init.c	2007-02-05 19:32:44.000000000 +0000
> +++ openldap-src-context/libraries/libldap/init.c	2007-02-17 13:22:45.000000000 +0000
> @@ -124,6 +124,7 @@
>  #define MAX_LDAP_ENV_PREFIX_LEN 8
>  
>  static void openldap_ldap_init_w_conf(
> +	struct ldapoptions *gopts,
>  	const char *file, int userconf )
>  {
>  	char linebuf[ AC_LINE_MAX ];
> @@ -131,10 +132,11 @@
>  	int i;
>  	char *cmd, *opt;
>  	char *start, *end;
> -	struct ldapoptions *gopts;
>  
> -	if ((gopts = LDAP_INT_GLOBAL_OPT()) == NULL) {
> -		return;			/* Could not allocate mem for global options */
> +	if( ! gopts ) {
> +		if ((gopts = LDAP_INT_GLOBAL_OPT()) == NULL) {
> +			return;			/* Could not allocate mem for global options */
> +		}
>  	}
>  
>  	if (file == NULL) {
> @@ -244,7 +246,7 @@
>  				* (char**) p = LDAP_STRDUP(opt);
>  				break;
>  			case ATTR_OPTION:
> -				ldap_set_option( NULL, attrs[i].offset, opt );
> +				ldap_set_option_in_context( gopts, attrs[i].offset, opt );
>  				break;
>  			case ATTR_SASL:
>  #ifdef HAVE_CYRUS_SASL
> @@ -253,7 +255,7 @@
>  				break;
>  			case ATTR_TLS:
>  #ifdef HAVE_TLS
> -			   	ldap_int_tls_config( NULL, attrs[i].offset, opt );
> +			   	ldap_int_tls_config_in_context( gopts, attrs[i].offset, opt );
>  #endif
>  				break;
>  			case ATTR_OPT_TV: {
> @@ -285,7 +287,7 @@
>  
>  static void openldap_ldap_init_w_sysconf(const char *file)
>  {
> -	openldap_ldap_init_w_conf( file, 0 );
> +	openldap_ldap_init_w_conf( NULL, file, 0 );
>  }
>  
>  static void openldap_ldap_init_w_userconf(const char *file)
> @@ -314,11 +316,11 @@
>  
>  		/* try ~/file */
>  		sprintf(path, "%s" LDAP_DIRSEP "%s", home, file);
> -		openldap_ldap_init_w_conf(path, 1);
> +		openldap_ldap_init_w_conf(NULL, path, 1);
>  
>  		/* try ~/.file */
>  		sprintf(path, "%s" LDAP_DIRSEP ".%s", home, file);
> -		openldap_ldap_init_w_conf(path, 1);
> +		openldap_ldap_init_w_conf(NULL, path, 1);
>  	}
>  
>  	if(path != NULL) {
> @@ -326,7 +328,7 @@
>  	}
>  
>  	/* try file */
> -	openldap_ldap_init_w_conf(file, 1);
> +	openldap_ldap_init_w_conf(NULL, file, 1);
>  }
>  
>  static void openldap_ldap_init_w_env(
> @@ -466,9 +468,10 @@
>  void ldap_int_initialize_global_options( struct ldapoptions *gopts, int *dbglvl )
>  {
>  	if (dbglvl)
> -	    gopts->ldo_debug = *dbglvl;
> +      /* FIXME: currently ldo_debug is an always global option only, so we set both places: */
> +	    gopts->ldo_debug = LDAP_INT_GLOBAL_OPT()->ldo_debug = *dbglvl;
>  	else
> -		gopts->ldo_debug = 0;
> +		gopts->ldo_debug = LDAP_INT_GLOBAL_OPT()->ldo_debug = 0;
>  
>  	gopts->ldo_version   = LDAP_VERSION2;
>  	gopts->ldo_deref     = LDAP_DEREF_NEVER;
> @@ -531,7 +534,10 @@
>  char * ldap_int_hostname = NULL;
>  #endif
>  
> -void ldap_int_initialize( struct ldapoptions *gopts, int *dbglvl )
> +void ldap_int_initialize(
> +	struct ldapoptions *gopts,
> +	int *dbglvl,
> +	char **directives )
>  {
>  	if ( gopts->ldo_valid == LDAP_INITIALIZED ) {
>  		return;
> @@ -593,6 +599,19 @@
>  
>  	ldap_int_initialize_global_options(gopts, NULL);
>  
> +	if( directives ) {
> +		for( ; *directives; ++directives ) {
> +			if( ! strncmp( *directives, "file=", 5 ) ) {
> +				openldap_ldap_init_w_conf( gopts, *directives + 5, 1 );
> +				continue;
> +			}
> +			/* add more directives here... */
> +			gopts->ldo_valid = LDAP_TRASHED_SESSION;
> +			return;
> +		}
> +		return;
> +	}
> +
>  	if( getenv("LDAPNOINIT") != NULL ) {
>  		return;
>  	}
> diff -Nru openldap-src/libraries/libldap/ldap-int.h openldap-src-context/libraries/libldap/ldap-int.h
> --- openldap-src/libraries/libldap/ldap-int.h	2007-02-15 00:42:23.000000000 +0000
> +++ openldap-src-context/libraries/libldap/ldap-int.h	2007-02-17 13:22:45.000000000 +0000
> @@ -417,7 +417,7 @@
>  
>  LDAP_V ( struct ldapoptions ) ldap_int_global_options;
>  
> -LDAP_F ( void ) ldap_int_initialize LDAP_P((struct ldapoptions *, int *));
> +LDAP_F ( void ) ldap_int_initialize LDAP_P((struct ldapoptions *, int *, char **directives ));
>  LDAP_F ( void ) ldap_int_initialize_global_options LDAP_P((
>  	struct ldapoptions *, int *));
>  
> @@ -652,6 +652,9 @@
>  LDAP_F (int) ldap_int_tls_config LDAP_P(( LDAP *ld,
>  	int option, const char *arg ));
>  
> +LDAP_F (int) ldap_int_tls_config_in_context LDAP_P(( struct ldapoptions *lo,
> +	int option, const char *arg ));
> +
>  LDAP_F (int) ldap_int_tls_start LDAP_P(( LDAP *ld,
>  	LDAPConn *conn, LDAPURLDesc *srv ));
>  
> diff -Nru openldap-src/libraries/libldap/open.c openldap-src-context/libraries/libldap/open.c
> --- openldap-src/libraries/libldap/open.c	2007-02-12 03:20:24.000000000 +0000
> +++ openldap-src-context/libraries/libldap/open.c	2007-02-17 13:45:19.000000000 +0000
> @@ -87,27 +87,88 @@
>  	return ld;
>  }
>  
> +int
> +ldap_free_context_internals( LDAPContext *context )
> +{
> +	ldap_free_urllist( context->ldo_defludp );
> +#ifdef HAVE_CYRUS_SASL
> +	LDAP_FREE( context->ldo_def_sasl_authzid );
> +	LDAP_FREE( context->ldo_def_sasl_authcid );
> +	LDAP_FREE( context->ldo_def_sasl_realm );
> +	LDAP_FREE( context->ldo_def_sasl_mech );
> +#endif
> +	return LDAP_SUCCESS;
> +}
> +
> +/* public destructor of LDAPContext */
> +int
> +ldap_destroy_context( LDAPContext *context )
> +{
> +	if( context ) {
> +		ldap_free_context_internals( context );
> +		free( context );
> +	}
> +	return LDAP_SUCCESS;
> +}
> +
> +/* public constructor of LDAPContext */
> +int
> +ldap_create_context(
> +	LDAPContext **context,
> +	/* directives: NULL-terminated list of initialization directives:
> +	 *  - NULL: default initialization procedure (see ldap.conf(5))
> +	 *  - { NULL }: equivalent to LDAPNOINIT
> +	 *  - { ..., "file=path", ... }: parse path like user-config file
> +	 */
> +	char **directives )
> +{
> +	LDAPContext *lo;
> +	
> +	*context = NULL;
> +	lo = ( LDAPContext * ) LDAP_CALLOC( 1, sizeof( LDAPContext ) );
> +	if( ! lo )
> +		return LDAP_NO_MEMORY;
> +
> +	Debug( LDAP_DEBUG_TRACE, "ldap_create_context %p\n", lo, 0, 0 );
> +
> +	lo->ldo_valid = LDAP_UNINITIALIZED;
> +	ldap_int_initialize( lo, NULL, directives );
> +	if( lo->ldo_valid != LDAP_INITIALIZED )
> +		return LDAP_LOCAL_ERROR;
>  
> +	*context = lo;
> +
> +	return LDAP_SUCCESS;
> +}
>  
>  int
>  ldap_create( LDAP **ldp )
>  {
> +	return ldap_create_in_context( ldp, NULL );
> +}
> +
> +int
> +ldap_create_in_context( LDAP **ldp, LDAPContext *gopts )
> +{
>  	LDAP			*ld;
> -	struct ldapoptions	*gopts;
>  
>  	*ldp = NULL;
> -	/* Get pointer to global option structure */
> -	if ( (gopts = LDAP_INT_GLOBAL_OPT()) == NULL) {
> -		return LDAP_NO_MEMORY;
> -	}
>  
> -	/* Initialize the global options, if not already done. */
> -	if( gopts->ldo_valid != LDAP_INITIALIZED ) {
> -		ldap_int_initialize(gopts, NULL);
> -		if ( gopts->ldo_valid != LDAP_INITIALIZED )
> -			return LDAP_LOCAL_ERROR;
> +	if( ! gopts ) {
> +		/* default is the global context */
> +		if ( (gopts = LDAP_INT_GLOBAL_OPT()) == NULL) {
> +			return LDAP_NO_MEMORY;
> +		}
> +
> +		/* Initialize the global options, if not already done. */
> +		if( gopts->ldo_valid != LDAP_INITIALIZED ) {
> +			ldap_int_initialize(gopts, NULL, NULL);
> +		}
>  	}
>  
> +	if( gopts->ldo_valid != LDAP_INITIALIZED )
> +		return LDAP_LOCAL_ERROR;
> +
>  	Debug( LDAP_DEBUG_TRACE, "ldap_create\n", 0, 0, 0 );
>  
>  	if ( (ld = (LDAP *) LDAP_CALLOC( 1, sizeof(LDAP) )) == NULL ) {
> @@ -167,13 +228,7 @@
>  
>  nomem:
>  	ldap_free_select_info( ld->ld_selectinfo );
> -	ldap_free_urllist( ld->ld_options.ldo_defludp );
> -#ifdef HAVE_CYRUS_SASL
> -	LDAP_FREE( ld->ld_options.ldo_def_sasl_authzid );
> -	LDAP_FREE( ld->ld_options.ldo_def_sasl_authcid );
> -	LDAP_FREE( ld->ld_options.ldo_def_sasl_realm );
> -	LDAP_FREE( ld->ld_options.ldo_def_sasl_mech );
> -#endif
> +	ldap_free_context_internals( &ld->ld_options );
>  	LDAP_FREE( (char *)ld );
>  	return LDAP_NO_MEMORY;
>  }
> @@ -215,11 +270,17 @@
>  int
>  ldap_initialize( LDAP **ldp, LDAP_CONST char *url )
>  {
> +	return ldap_initialize_in_context( ldp, url, NULL );
> +}
> +
> +int
> +ldap_initialize_in_context( LDAP **ldp, LDAP_CONST char *url, LDAPContext *context ) 
> +{
>  	int rc;
>  	LDAP *ld;
>  
>  	*ldp = NULL;
> -	rc = ldap_create(&ld);
> +	rc = ldap_create_in_context(&ld, context);
>  	if ( rc != LDAP_SUCCESS )
>  		return rc;
>  
> diff -Nru openldap-src/libraries/libldap/options.c openldap-src-context/libraries/libldap/options.c
> --- openldap-src/libraries/libldap/options.c	2007-02-06 22:02:47.000000000 +0000
> +++ openldap-src-context/libraries/libldap/options.c	2007-02-17 13:22:45.000000000 +0000
> @@ -97,16 +97,6 @@
>  {
>  	struct ldapoptions *lo;
>  
> -	/* Get pointer to global option structure */
> -	lo = LDAP_INT_GLOBAL_OPT();   
> -	if (NULL == lo)	{
> -		return LDAP_NO_MEMORY;
> -	}
> -
> -	if( lo->ldo_valid != LDAP_INITIALIZED ) {
> -		ldap_int_initialize(lo, NULL);
> -	}
> -
>  	if(ld != NULL) {
>  		assert( LDAP_VALID( ld ) );
>  
> @@ -117,6 +107,18 @@
>  		lo = &ld->ld_options;
>  	}
>  
> +	if( lo == NULL ) {
> +		/* Get pointer to global option structure */
> +		lo = LDAP_INT_GLOBAL_OPT();   
> +		if (NULL == lo)	{
> +			return LDAP_NO_MEMORY;
> +		}
> +
> +		if( lo->ldo_valid != LDAP_INITIALIZED ) {
> +			ldap_int_initialize(lo, NULL, NULL);
> +		}
> +	}
> +
>  	if(outvalue == NULL) {
>  		/* no place to get to */
>  		return LDAP_OPT_ERROR;
> @@ -347,19 +349,35 @@
>  }
>  
>  int
> +ldap_set_option_in_context(
> +	LDAPContext *context,
> +	int		option,
> +	LDAP_CONST void	*invalue)
> +{
> +	return ldap_set_option_2( context, NULL, option, invalue );
> +}
> +
> +int
>  ldap_set_option(
>  	LDAP	*ld,
>  	int		option,
>  	LDAP_CONST void	*invalue)
>  {
> -	struct ldapoptions *lo;
> -	int *dbglvl = NULL;
> +	return ldap_set_option_2( NULL, ld, option, invalue );
> +}
>  
> -	/* Get pointer to global option structure */
> -	lo = LDAP_INT_GLOBAL_OPT();
> -	if (lo == NULL)	{
> -		return LDAP_NO_MEMORY;
> -	}
> +/*
> + *  ldap_set_option_2: can set options per LDAP handle or per context.
> + *  if handle is given, the context is ignored.
> + */
> +int
> +ldap_set_option_2(
> +	struct ldapoptions *lo,
> +	LDAP	*ld,
> +	int		option,
> +	LDAP_CONST void	*invalue)
> +{
> +	int *dbglvl = NULL;
>  
>  	/*
>  	 * The architecture to turn on debugging has a chicken and egg
> @@ -370,10 +388,6 @@
>  		dbglvl = (int *) invalue;
>  	}
>  
> -	if( lo->ldo_valid != LDAP_INITIALIZED ) {
> -		ldap_int_initialize(lo, dbglvl);
> -	}
> -
>  	if(ld != NULL) {
>  		assert( LDAP_VALID( ld ) );
>  
> @@ -384,6 +398,17 @@
>  		lo = &ld->ld_options;
>  	}
>  
> +	if( lo == NULL ) {
> +		/* Get pointer to global option structure */
> +		lo = LDAP_INT_GLOBAL_OPT();
> +		if (lo == NULL)	{
> +			return LDAP_NO_MEMORY;
> +		}
> +		if( lo->ldo_valid != LDAP_INITIALIZED ) {
> +			ldap_int_initialize(lo, dbglvl, NULL);
> +		}
> +	}
> +
>  	switch(option) {
>  	case LDAP_OPT_REFERRALS:
>  		if(invalue == LDAP_OPT_OFF) {
> @@ -668,7 +693,7 @@
>  
>  	default:
>  #ifdef HAVE_TLS
> -		if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
> +		if ( ldap_pvt_tls_set_option_2( lo, ld, option, (void *)invalue ) == 0 )
>  			return LDAP_OPT_SUCCESS;
>  #endif
>  #ifdef HAVE_CYRUS_SASL
> diff -Nru openldap-src/libraries/libldap/tls.c openldap-src-context/libraries/libldap/tls.c
> --- openldap-src/libraries/libldap/tls.c	2007-01-24 22:38:26.000000000 +0000
> +++ openldap-src-context/libraries/libldap/tls.c	2007-02-17 13:22:45.000000000 +0000
> @@ -1178,8 +1178,20 @@
>  }
>  
>  int
> +ldap_int_tls_config_in_context( struct ldapoptions *lo, int option, const char *arg )
> +{
> +	return ldap_int_tls_config_2( lo, NULL, option, arg );
> +}
> +
> +int
>  ldap_int_tls_config( LDAP *ld, int option, const char *arg )
>  {
> +	return ldap_int_tls_config_2( NULL, ld, option, arg );
> +}
> +
> +int
> +ldap_int_tls_config_2( struct ldapconfig *lo, LDAP *ld, int option, const char *arg )
> +{
>  	int i;
>  
>  	switch( option ) {
> @@ -1190,7 +1202,7 @@
>  	case LDAP_OPT_X_TLS_RANDOM_FILE:
>  	case LDAP_OPT_X_TLS_CIPHER_SUITE:
>  	case LDAP_OPT_X_TLS_DHFILE:
> -		return ldap_pvt_tls_set_option( ld, option, (void *) arg );
> +		return ldap_pvt_tls_set_option_2( lo, ld, option, (void *) arg );
>  
>  	case LDAP_OPT_X_TLS_REQUIRE_CERT:
>  	case LDAP_OPT_X_TLS:
> @@ -1216,7 +1228,7 @@
>  		}
>  
>  		if (i >= 0) {
> -			return ldap_pvt_tls_set_option( ld, option, &i );
> +			return ldap_pvt_tls_set_option_2( lo, ld, option, &i );
>  		}
>  		return -1;
>  #ifdef HAVE_OPENSSL_CRL
> @@ -1230,7 +1242,7 @@
>  			i = LDAP_OPT_X_TLS_CRL_ALL ;
>  		}
>  		if (i >= 0) {
> -			return ldap_pvt_tls_set_option( ld, option, &i );
> +			return ldap_pvt_tls_set_option_2( lo, ld, option, &i );
>  		}
>  		return -1;
>  #endif
> @@ -1334,7 +1346,12 @@
>  int
>  ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg )
>  {
> -	struct ldapoptions *lo;
> +	return ldap_pvt_tls_set_option_2( NULL, ld, option, arg );
> +}
> +
> +int
> +ldap_pvt_tls_set_option_2( struct ldapoptions *lo, LDAP *ld, int option, void *arg )
> +{
>  
>  	if( ld != NULL ) {
>  		assert( LDAP_VALID( ld ) );
> @@ -1345,7 +1362,8 @@
>  
>  		lo = &ld->ld_options;
>  
> -	} else {
> +	}
> +  if( lo == NULL ) {
>  		/* Get pointer to global option structure */
>  		lo = LDAP_INT_GLOBAL_OPT();   
>  		if ( lo == NULL ) {
> 
> --pf9I7BMVVzbSWLtt
> Content-Type: text/plain; charset=us-ascii
> Content-Disposition: attachment; filename="nss_ldap.patch"
> 
> This patch file is derived from PADL Software (nss_ldap).
> All of the modifications to PADL Software represented in the following
> patch(es) were developed by Timo Felbinger <timo@physik.uni-potsdam.de>.
> These modifications are not subject to any license of University of Potsdam.
> 
> I, Timo Felbinger, hereby place the following modifications to PADL Software
> (and only these modifications) into the public domain.
> Hence, these modifications may be freely used and/or redistributed for any purpose
> with or without attribution and/or other notice. 
> 
> diff -Nru nss_ldap-254/config.h.in nss_ldap-254-context/config.h.in
> --- nss_ldap-254/config.h.in	2006-12-18 08:12:56.000000000 +0000
> +++ nss_ldap-254-context/config.h.in	2007-02-17 14:46:02.000000000 +0000
> @@ -132,6 +132,9 @@
>  /* Define to 1 if you have the `ldap_initialize' function. */
>  #undef HAVE_LDAP_INITIALIZE
>  
> +/* Define to 1 if you have the `ldap_create_context' function. */
> +#undef HAVE_LDAP_CREATE_CONTEXT
> +
>  /* Define to 1 if you have the `ldap_ld_free' function. */
>  #undef HAVE_LDAP_LD_FREE
>  
> diff -Nru nss_ldap-254/configure nss_ldap-254-context/configure
> --- nss_ldap-254/configure	2006-12-18 08:12:56.000000000 +0000
> +++ nss_ldap-254-context/configure	2007-02-17 14:46:37.000000000 +0000
> @@ -1,4 +1,6 @@
>  #! /bin/sh
> +echo please run autoconf first!
> +exit 1
>  
>  # Guess values for system-dependent variables and create Makefiles.
>  # Generated automatically using autoconf version 2.13 
> diff -Nru nss_ldap-254/configure.in nss_ldap-254-context/configure.in
> --- nss_ldap-254/configure.in	2006-12-18 08:12:56.000000000 +0000
> +++ nss_ldap-254-context/configure.in	2007-02-17 14:46:02.000000000 +0000
> @@ -297,7 +297,7 @@
>  AC_CHECK_FUNCS(sasl_auxprop_request)
>  AC_CHECK_FUNCS(ldap_init ldap_get_lderrno ldap_parse_result ldap_memfree ldap_controls_free)
>  AC_CHECK_FUNCS(ldap_ld_free ldap_explode_rdn ldap_set_option ldap_get_option)
> -AC_CHECK_FUNCS(ldap_sasl_interactive_bind_s ldap_initialize ldap_search_ext)
> +AC_CHECK_FUNCS(ldap_sasl_interactive_bind_s ldap_initialize ldap_search_ext ldap_create_context)
>  AC_CHECK_FUNCS(ldap_create_control ldap_create_page_control ldap_parse_page_control)
>  if test "$enable_ssl" \!= "no"; then
>    AC_CHECK_FUNCS(ldapssl_client_init ldap_start_tls_s ldap_pvt_tls_set_option ldap_start_tls)
> diff -Nru nss_ldap-254/ldap-nss.c nss_ldap-254-context/ldap-nss.c
> --- nss_ldap-254/ldap-nss.c	2006-12-18 08:12:56.000000000 +0000
> +++ nss_ldap-254-context/ldap-nss.c	2007-02-17 14:46:02.000000000 +0000
> @@ -137,7 +137,7 @@
>  /*
>   * Global LDAP session.
>   */
> -static ldap_session_t __session = { NULL, NULL, 0, LS_UNINITIALIZED };
> +static ldap_session_t __session = { NULL, NULL, NULL, 0, LS_UNINITIALIZED };
>  
>  #if defined(HAVE_PTHREAD_ATFORK) || defined(HAVE_LIBC_LOCK_H) || defined(HAVE_BITS_LIBC_LOCK_H)
>  static pthread_once_t __once = PTHREAD_ONCE_INIT;
> @@ -1003,7 +1003,7 @@
>  }
>  
>  static NSS_STATUS
> -do_init_session (LDAP ** ld, const char *uri, int defport)
> +do_init_session ( LDAPContext **ldap_context, LDAP ** ld, const char *uri, int defport)
>  {
>    int rc;
>    int ldaps;
> @@ -1011,6 +1011,17 @@
>    char *p;
>    NSS_STATUS stat;
>  
> +#ifdef HAVE_LDAP_CREATE_CONTEXT
> +  if( ! *ldap_context )
> +    {
> +      /* make sure ldap config is read in a safe way */
> +      static const char *directives[2] = { "file=" NSS_LDAP_PATH_CONF, NULL };
> +      int rc = ldap_create_context( ldap_context, directives );
> +      if (rc != LDAP_SUCCESS)
> +        return NSS_UNAVAIL;
> +    }
> +#endif
> +
>    ldaps = (strncasecmp (uri, "ldaps://", sizeof ("ldaps://") - 1) == 0);
>    p = strchr (uri, ':');
>    /* we should be looking for the second instance to find the port number */
> @@ -1028,7 +1039,11 @@
>        uri = uribuf;
>      }
>  
> +# ifdef HAVE_LDAP_CREATE_CONTEXT
> +  rc = ldap_initialize_in_context (ld, uri, *ldap_context);
> +#	else
>    rc = ldap_initialize (ld, uri);
> +#	endif
>  #else
>    if (strncasecmp (uri, "ldap://";, sizeof ("ldap://";) - 1) != 0)
>      {
> @@ -1311,7 +1326,7 @@
>    assert (__session.ls_current_uri <= NSS_LDAP_CONFIG_URI_MAX);
>    assert (cfg->ldc_uris[__session.ls_current_uri] != NULL);
>  
> -  stat = do_init_session (&__session.ls_conn,
> +  stat = do_init_session ( &__session.ldap_context, &__session.ls_conn,
>  			  cfg->ldc_uris[__session.ls_current_uri],
>  			  cfg->ldc_port);
>    if (stat != NSS_SUCCESS)
> diff -Nru nss_ldap-254/ldap-nss.h nss_ldap-254-context/ldap-nss.h
> --- nss_ldap-254/ldap-nss.h	2006-12-18 08:12:56.000000000 +0000
> +++ nss_ldap-254-context/ldap-nss.h	2007-02-17 14:46:02.000000000 +0000
> @@ -416,12 +416,19 @@
>  
>  typedef enum ldap_session_state ldap_session_state_t;
>  
> +/* for readability, make sure LDAPContext is at least a dummy type: */
> +#ifndef HAVE_LDAP_CREATE_CONTEXT
> +#	define LDAPContext void
> +#endif
> +
>  /*
>   * convenient wrapper around pointer into global config list, and a
>   * connection to an LDAP server.
>   */
>  struct ldap_session
>  {
> +  /* the context, if supported */
> +  LDAPContext *ldap_context;
>    /* the connection */
>    LDAP *ls_conn;
>    /* pointer into config table */
> 
> --pf9I7BMVVzbSWLtt
> Content-Type: text/plain; charset=us-ascii
> Content-Disposition: attachment; filename="pam_ldap.patch"
> 
> This patch file is derived from PADL Software (pam_ldap).
> All of the modifications to PADL Software represented in the following
> patch(es) were developed by Timo Felbinger <timo@physik.uni-potsdam.de>.
> These modifications are not subject to any license of University of Potsdam.
> 
> I, Timo Felbinger, hereby place the following modifications to PADL Software
> (and only these modifications) into the public domain.
> Hence, these modifications may be freely used and/or redistributed for any purpose
> with or without attribution and/or other notice. 
> 
> diff -Nru pam_ldap-183/config.h.in pam_ldap-183-context/config.h.in
> --- pam_ldap-183/config.h.in	2006-10-19 13:22:27.000000000 +0000
> +++ pam_ldap-183-context/config.h.in	2007-02-17 14:55:38.000000000 +0000
> @@ -33,6 +33,9 @@
>  /* Define if you have the ldap_initialize function.  */
>  #undef HAVE_LDAP_INITIALIZE
>  
> +/* Define if you have the ldap_create_context function.  */
> +#undef HAVE_LDAP_CREATE_CONTEXT
> +
>  /* Define if you have the ldap_memfree function.  */
>  #undef HAVE_LDAP_MEMFREE
>  
> diff -Nru pam_ldap-183/configure pam_ldap-183-context/configure
> --- pam_ldap-183/configure	2006-10-19 13:22:27.000000000 +0000
> +++ pam_ldap-183-context/configure	2007-02-17 14:55:38.000000000 +0000
> @@ -1,4 +1,6 @@
>  #! /bin/sh
> +echo Please run autoconf first!
> +exit 1
>  
>  # Guess values for system-dependent variables and create Makefiles.
>  # Generated automatically using autoconf version 2.13 
> diff -Nru pam_ldap-183/configure.in pam_ldap-183-context/configure.in
> --- pam_ldap-183/configure.in	2006-10-19 13:22:27.000000000 +0000
> +++ pam_ldap-183-context/configure.in	2007-02-17 14:55:38.000000000 +0000
> @@ -131,6 +131,7 @@
>    AC_CHECK_FUNCS(ldapssl_init ldap_start_tls_s ldap_pvt_tls_set_option)
>  fi
>  AC_CHECK_FUNCS(ldap_initialize)
> +AC_CHECK_FUNCS(ldap_create_context)
>  AC_CHECK_FUNCS(ldap_sasl_bind ldap_sasl_interactive_bind_s)
>  AC_CHECK_FUNCS(gethostbyname_r)
>  
> diff -Nru pam_ldap-183/pam_ldap.c pam_ldap-183-context/pam_ldap.c
> --- pam_ldap-183/pam_ldap.c	2006-10-19 13:22:27.000000000 +0000
> +++ pam_ldap-183-context/pam_ldap.c	2007-02-17 15:08:39.000000000 +0000
> @@ -155,6 +155,11 @@
>  #endif
>  static int pam_debug_level __UNUSED__ = 0;
>  
> +#ifndef HAVE_LDAP_CREATE_CONTEXT
> +#	typedef LDAPContext void;
> +#endif
> +static LDAPContext *ldap_context = 0;
> +
>  #ifdef HAVE_LDAPSSL_INIT
>  static int ssl_initialized = 0;
>  #endif
> @@ -1190,6 +1195,36 @@
>    struct timeval tv;
>  #endif
>  
> +#ifdef HAVE_LDAP_CREATE_CONTEXT
> +  /* make sure ldap config is read in a safe and transparent way */
> +  if( ! ldap_context )
> +    {
> +      char *directives[2];
> +      int rc;
> +
> +      if( session->conf->configFile == NULL )
> +        {
> +          directives[0] = NULL;
> +        }
> +      else
> +        {
> +          directives[0] = malloc (strlen (session->conf->configFile) + 6);
> +          if( directives[0] == NULL )
> +            return PAM_BUF_ERR;
> +          strcpy( directives[0], "file=" );
> +          strcpy( directives[0]+5, session->conf->configFile );
> +        }
> +      directives[1] = NULL;
> +      rc = ldap_create_context( &ldap_context, directives );
> +      _pam_drop( directives[0] );
> +      if (rc != LDAP_SUCCESS || ! ldap_context )
> +        {
> +          syslog (LOG_ERR, "pam_ldap: ldap_create_context: %s", ldap_err2string (rc));
> +          return PAM_SERVICE_ERR;
> +        }
> +    }
> +#endif
> +
>  #ifdef HAVE_LDAP_SET_OPTION
>    if (session->conf->debug)
>      {
> @@ -1253,7 +1288,11 @@
>  #ifdef HAVE_LDAP_INITIALIZE
>        if (session->conf->uri != NULL)
>  	{
> +#	ifdef HAVE_LDAP_CREATE_CONTEXT
> +	  int rc = ldap_initialize_in_context (&session->ld, session->conf->uri, ldap_context);
> +#	else
>  	  int rc = ldap_initialize (&session->ld, session->conf->uri);
> +#	endif
>  	  if (rc != LDAP_SUCCESS)
>  	    {
>  	      syslog (LOG_ERR, "pam_ldap: ldap_initialize %s",
> @@ -1400,8 +1439,12 @@
>    /* rand file */
>    if (session->conf->tls_randfile != NULL)
>      {
> -      rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_RANDOM_FILE,
> -			    session->conf->tls_randfile);
> +#	ifdef HAVE_LDAP_CREATE_CONTEXT
> +      rc = ldap_set_option_in_context ( ldap_context, 
> +#	else
> +      rc = ldap_set_option (NULL,
> +#	endif
> +			    LDAP_OPT_X_TLS_RANDOM_FILE, session->conf->tls_randfile);
>        if (rc != LDAP_SUCCESS)
>  	{
>  	  syslog (LOG_ERR,
> @@ -1415,7 +1458,12 @@
>    /* ca cert file */
>    if (session->conf->tls_cacertfile != NULL)
>      {
> -      rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE,
> +#	ifdef HAVE_LDAP_CREATE_CONTEXT
> +      rc = ldap_set_option_in_context ( ldap_context,
> +#	else
> +      rc = ldap_set_option (NULL,
> +#	endif
> +			    LDAP_OPT_X_TLS_CACERTFILE,
>  			    session->conf->tls_cacertfile);
>        if (rc != LDAP_SUCCESS)
>  	{
> @@ -1429,7 +1477,12 @@
>    if (session->conf->tls_cacertdir != NULL)
>      {
>        /* ca cert directory */
> -      rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTDIR,
> +#	ifdef HAVE_LDAP_CREATE_CONTEXT
> +      rc = ldap_set_option_in_context ( ldap_context,
> +#	else
> +      rc = ldap_set_option (NULL,
> +#	endif
> +			    LDAP_OPT_X_TLS_CACERTDIR,
>  			    session->conf->tls_cacertdir);
>        if (rc != LDAP_SUCCESS)
>  	{
> @@ -1443,7 +1496,12 @@
>    if (session->conf->tls_checkpeer > -1)
>      {
>        /* require cert? */
> -      rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
> +#	ifdef HAVE_LDAP_CREATE_CONTEXT
> +      rc = ldap_set_option_in_context ( ldap_context,
> +#	else
> +      rc = ldap_set_option (NULL,
> +#	endif
> +		    LDAP_OPT_X_TLS_REQUIRE_CERT,
>  			    &session->conf->tls_checkpeer);
>        if (rc != LDAP_SUCCESS)
>  	{
> @@ -1457,7 +1515,12 @@
>    if (session->conf->tls_ciphers != NULL)
>      {
>        /* set cipher suite, certificate and private key: */
> -      rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CIPHER_SUITE,
> +#	ifdef HAVE_LDAP_CREATE_CONTEXT
> +      rc = ldap_set_option_in_context ( ldap_context,
> +#	else
> +      rc = ldap_set_option (NULL,
> +#	endif
> +			    LDAP_OPT_X_TLS_CIPHER_SUITE,
>  			    session->conf->tls_ciphers);
>        if (rc != LDAP_SUCCESS)
>  	{
> @@ -1470,7 +1533,12 @@
>  
>    if (session->conf->tls_cert != NULL)
>      {
> -      rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_CERTFILE,
> +#	ifdef HAVE_LDAP_CREATE_CONTEXT
> +      rc = ldap_set_option_in_context ( ldap_context,
> +#	else
> +      rc = ldap_set_option (NULL,
> +#	endif
> +			    LDAP_OPT_X_TLS_CERTFILE,
>  			    session->conf->tls_cert);
>        if (rc != LDAP_SUCCESS)
>  	{
> @@ -1483,7 +1551,12 @@
>  
>    if (session->conf->tls_key != NULL)
>      {
> -      rc = ldap_set_option (NULL, LDAP_OPT_X_TLS_KEYFILE,
> +#	ifdef HAVE_LDAP_CREATE_CONTEXT
> +      rc = ldap_set_option_in_context ( ldap_context,
> +#	else
> +      rc = ldap_set_option (NULL,
> +#	endif
> +			    LDAP_OPT_X_TLS_KEYFILE,
>  			    session->conf->tls_key);
>        if (rc != LDAP_SUCCESS)
>  	{
> 
> --pf9I7BMVVzbSWLtt--
> 
> 
> 


-- 
   -- Howard Chu
   Chief Architect, Symas Corp.  http://www.symas.com
   Director, Highland Sun        http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP     http://www.openldap.org/project/