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

Re: PHP+LDAP not really works [includes small debug patch to 2.1.12]



Frode,

As much as I don't like to say it, I've heard some bad things about
RedHat8 and PHP. As a benchmark, why don't you try another PHP/LDAP
application on  your system to verify that your code is indeed working.
I can recommend DaveDAP:

http://students.cs.byu.edu/~djsmith/davedap/

If that doesn't work, then I'd recommend changing versions of PHP and/or
Apache. Note that you'll have to enable register_globals for DaveDAP to
run under RH8.

--Dave


On Sat, 2003-01-11 at 05:57, Frode E. Moe wrote:
> On Sat, Jan 11, 2003 at 01:20:09PM +0100, Veres Imre wrote:
> > It's my first email to the list os firstly let me introduce myself: My
> > name is Imre Veres aged 27, I'm working in Hungary at the fourth biggest
> > hungarian software company. We are working for banks and other financial
> > institutes.
> > 
> > There is a working openldap 2.0.27 here which serve authenticating with
> > Samba, Apache and internal SSH, moreover ldap tree contains all data
> > from our colleagues and going to serve intranet applications. This is my
> > real problem now, I'm using PHP 4.2.2 (RedHat 8.0) and the modify
> > function to LDAP works in 40% of the cases without any error or
> > warning,  works another 20% with warnings and doesn't work in the rest
> > of the cases either. I can't understand this situation. They could not
> > help me in the PHP list because my PHP code is perfect. :-) I think
> > there is some weird thing in the LDAP side. 
> 
> 
> I don't know your specific code or your specific errors, but we've been
> experiencing random segfaults and crashes when using APACHE+PHP+LDAP to
> access a windows Active Directory LDAP server. I've spent almost a day in
> gdb trying to track down the error and it seems some "lr_parent" pointers in
> LDAP structures are corrupted, as PHP and APACHE segfaults when PHP tries to
> unbind from the LDAP server and free all objects; when the ldap code frees
> up its request objects, it seems to traverse through 'parent' and 'children'
> request pointers. As the parent pointer pointed into what seemed like the
> remainings of a string buffer (the base DN?), segfault was inevitable as the
> code tried interpreting the "parent" pointer part of the structure as a
> pointer when in fact it was ASCII characters.
> 
> I tried turning on LDAP_MEMORY_DEBUG and LDAP_MEMORY_TRACE defines,  which,
> by the way, in 2.1.12 doesn't even compile cleanly (there's a define in
> libraries/liblber/memory.c at around line 55 which is wrong), here's
> a short patch:
> 
> --- dist/openldap-2.1.12/libraries/liblber/memory.c	2002-10-17 17:08:01.000000000 +0200
> +++ openldap-2.1.12/libraries/liblber/memory.c	2003-01-09 22:05:29.000000000 +0100
> @@ -53,7 +53,7 @@
>  };
>  
>  /* Pattern at top of allocated space */
> -#define LLBER_MEM_JUNK 0xdeaddadaU
> +#define LBER_MEM_JUNK 0xdeaddadaU
>  
>  static const struct ber_mem_hdr ber_int_mem_hdr = { LBER_MEM_JUNK, 0, 0 };
>  
> 
> 
> 
> When running with this DEBUG compiled library, after a long reponse
> (we have many user objects in AD, so a request for all users returns
>  quite long a reponse), the ldap memory debug code stopped the application
>  with failed assertions at locations such as this:
>  
> libraries/libldap/result.c around line 778 (in version 2.1.12):
> 
> 				if ( !simple_request ) {
> 					ber_free( ber, 1 );
> 					ber = NULL;
> 					if ( build_result_ber( ld, &ber, lr )
> 					    == LBER_ERROR ) {
> 						rc = -1; /* fatal error */
> 					}
> 				}
> 
> The ber_free called failed an assertion that ber != NULL.  I'm not very
> familiar with the openldap code base, but I compared this bit of source with
> the old openldap 1.2.13, where it seems the corresponding code goes like
> this:
> 
> libraries/libldap/result.c around line 400 (in version 1.2.13)
> 
> 				if ( !simple_request ) {
> 					if ( ber.ber_buf != NULL ) {
> 						free( ber.ber_buf ); /* gack! */
> 						ber.ber_buf = NULL;
> 					}
> 					if ( build_result_ber( ld, &ber, lr )
> 					    == LBER_ERROR ) {
> 						ld->ld_errno = LDAP_NO_MEMORY;
> 						rc = -1; /* fatal error */
> 					}
> 				}
> 
> As you can see it probably makes more sense to set a member of the ber
> struct to NULL and then re-use the ber object just afterwards, instead of
> nulling the entire thing. 
> 
> 
> Well, to put a long story short:
> 
> I wrote a simple test case in C which for some time reproduced the error,
> but at the end I couldn't even get the assertion failures to trigger. By
> luck I happened to read upon the ldap_set_option PHP manual online,  where
> some people recommend explicitly setting the protocol version to v3.  We
> tried this and our problems went away, so I never bothered to track down the
> exact bug.   
> 
> It might also be that the assertions failed just because I was stupid
> enough to use LD_PRELOAD tricks instead of overwriting my system
> ldap libraries (i'm running debian linux by the way).
> 
> Here's an example of the assertion failures:
> (see attached example application)
> 
> gdb ./test
> GNU gdb 5.3-debian
> (gdb) run
> Starting program: /home/frode/temp/ldap-testcase/test 
> ldap test case
> 0x00000000 0x0804abd8 -a- 25 ber_memalloc 25
> 0x00000001 0x0804ac10 -a- 18 ber_memalloc 43
> 0x00000002 0x0804ac40 -a- 8 ber_memalloc 51
> 0x00000003 0x0804ac68 -a- 18 ber_memalloc 69
> 
>   ( lots of memory debugging output )
> 
> 0x00000042 0x0804af88 -f- 24 ber_memfree 22127
> 0x00000053 0x08050ca0 -a- 64 ber_memcalloc 22191
> search ok
> 0x00000054 0x08050e50 -a- 44 ber_memcalloc 22235
> 0x00000055 0x08050e98 -a- 221 ber_memalloc 22456
> 0x00000056 0x0804af88 -a- 24 ber_memcalloc 22480
> currently at numresults/numresponses 0/0 - type 100 
> 0x00000055 0x08050e98 -f- 221 ber_memfree 22259
> 0x00000054 0x08050e50 -f- 44 ber_memfree 22215
> 0x00000056 0x0804af88 -f- 24 ber_memfree 22191
> 0x00000057 0x08050e50 -a- 44 ber_memcalloc 22235
> 0x00000058 0x08050e98 -a- 107 ber_memalloc 22342
> 0x00000059 0x0804af88 -a- 24 ber_memcalloc 22366
> currently at numresults/numresponses 1/1 - type 100 
> 0x00000058 0x08050e98 -f- 107 ber_memfree 22259
> 0x00000057 0x08050e50 -f- 44 ber_memfree 22215
> 
>   ( lots of more uninteresting output )
> 
> 0x0000051c 0x08050e50 -a- 44 ber_memcalloc 22235
> 0x0000051d 0x08050d08 -a- 219 ber_memalloc 22454
> 0x0000051e 0x08050b88 -a- 24 ber_memcalloc 22478
> currently at numresults/numresponses 408/408 - type 100 
> 0x0000051d 0x08050d08 -f- 219 ber_memfree 22259
> 0x0000051c 0x08050e50 -f- 44 ber_memfree 22215
> 0x0000051e 0x08050b88 -f- 24 ber_memfree 22191
> 0x0000051f 0x08050e50 -a- 44 ber_memcalloc 22235
> 0x00000520 0x08050d08 -a- 112 ber_memalloc 22347
> 0x00000521 0x08050d98 -a- 1 ber_memalloc 22348
> 0x00000522 0x0804af40 -a- 96 ber_memalloc 22444
> 0x00000523 0x08050db8 -a- 79 ber_memalloc 22523
> 0x00000524 0x08050e98 -a- 40 ber_memcalloc 22563
> 0x00000525 0x08050bc0 -a- 5 ber_memalloc 22568
> 0x00000526 0x08050b88 -a- 25 ber_memalloc 22593
> 0x00000527 0x08050ee0 -a- 54 ber_memalloc 22647
> 0x00000523 0x08050db8 -f- 79 ber_memfree 22568
> 0x00000528 0x08050db8 -a- 37 ber_memalloc 22605
> 0x00000529 0x08050e00 -a- 44 ber_memcalloc 22649
> 0x0000052a 0x08050f38 -a- 24 ber_memcalloc 22673
> 0x0000052b 0x08050f70 -a- 4060 ber_memalloc 26733
> 0x0000052c 0x08051f68 -a- 24 ber_memcalloc 26757
> 0x00000528 0x08050db8 -f- 37 ber_memfree 26720
> 0x0000052c 0x08051f68 -f- 24 ber_memfree 26696
> 0x0000052a 0x08050f38 -f- 24 ber_memfree 26672
> 0x0000052d 0x08051f68 -a- 86 ber_memalloc 26758
> 0x0000052e 0x08050db8 -a- 44 ber_memcalloc 26802
> 0x0000052f 0x08050f38 -a- 28 ber_memcalloc 26830
> 0x00000530 0x08052028 -a- 20 ber_memalloc 26850
> 0x00000531 0x08052058 -a- 5 ber_memalloc 26855
> 0x00000532 0x08052080 -a- 20 ber_memalloc 26875
> 0x00000533 0x08051ff0 -a- 25 ber_memalloc 26900
> 0x00000534 0x080520b0 -a- 20 ber_memalloc 26920
> 0x00000535 0x080520e0 -a- 16 ber_memalloc 26936
> 0x00000536 0x08052110 -a- 16384 ber_memalloc 43320
> 0x00000537 0x08056130 -a- 20 ber_memalloc 43340
> 0x00000538 0x08056160 -a- 6 ber_memalloc 43346
> 0x00000539 0x08056188 -a- 176 ber_memalloc 43522
> 0x0000053a 0x08056258 -a- 5 ber_memalloc 43527
> 0x0000053b 0x08056280 -a- 25 ber_memalloc 43552
> 0x0000053c 0x080562b8 -a- 56 ber_memalloc 43608
> 0x0000053d 0x08056310 -a- 116 ber_memalloc 43724
> 0x0000053e 0x080563a0 -a- 12 ber_memalloc 43736
> 0x0000053f 0x080563c8 -a- 25 ber_memalloc 43761
> 0x00000533 0x08051ff0 -f- 25 ber_memfree 43736
> 0x00000540 0x08056400 -a- 40 ber_memalloc 43776
> 0x00000541 0x08056448 -a- 5 ber_memalloc 43781
> 0x00000542 0x08051ff0 -a- 25 ber_memalloc 43806
> 0x00000543 0x08056470 -a- 54 ber_memalloc 43860
> 0x00000544 0x080564c8 -a- 44 ber_memcalloc 43904
> 0x00000545 0x08056510 -a- 24 ber_memcalloc 43928
> 0x00000546 0x08056548 -a- 4060 ber_memalloc 47988
> 0x00000547 0x08057540 -a- 24 ber_memcalloc 48012
> 0x00000547 0x08057540 -f- 24 ber_memfree 47988
> 0x00000545 0x08056510 -f- 24 ber_memfree 47964
> 0x00000548 0x08057578 -a- 64 ber_memcalloc 48028
> 0x00000549 0x080575d8 -a- 44 ber_memcalloc 48072
> 0x0000054a 0x08057620 -a- 17 ber_memalloc 48089
> 0x0000054b 0x08057650 -a- 1 ber_memalloc 48090
> 0x0000054c 0x08057670 -a- 1 ber_memalloc 48091
> 0x00000546 0x08056548 -f- 4060 ber_memfree 44031
> 0x00000544 0x080564c8 -f- 44 ber_memfree 43987
> 0x0000054c 0x08057670 -f- 1 ber_memfree 43986
> 0x0000054b 0x08057650 -f- 1 ber_memfree 43985
> 0x00000548 0x08057578 -f- 64 ber_memfree 43921
> 0x0000054d 0x08056510 -a- 24 ber_memcalloc 43945
> 0x00000040 0x08050c80 -f- 1 ber_memfree 43944
> 0x0000003f 0x08050c60 -f- 1 ber_memfree 43943
> 0x0000054e 0x080564c8 -a- 44 ber_memcalloc 43987
> 0x0000054f 0x08050c60 -a- 1 ber_memalloc 43988
> 0x00000550 0x08050c80 -a- 1 ber_memalloc 43989
> 0x0000054e 0x080564c8 -f- 44 ber_memfree 43945
> 0x0000054a 0x08057620 -f- 17 ber_memfree 43928
> 0x00000549 0x080575d8 -f- 44 ber_memfree 43884
> 0x0000054d 0x08056510 -f- 24 ber_memfree 43860
> 0x00000551 0x08057578 -a- 64 ber_memcalloc 43924
> 0x0000052d 0x08051f68 -f- 86 ber_memfree 43838
> 0x00000525 0x08050bc0 -f- 5 ber_memfree 43833
> 0x00000526 0x08050b88 -f- 25 ber_memfree 43808
> 0x00000527 0x08050ee0 -f- 54 ber_memfree 43754
> 0x00000524 0x08050e98 -f- 40 ber_memfree 43714
> 0x00000522 0x0804af40 -f- 96 ber_memfree 43618
> 0x00000520 0x08050d08 -f- 112 ber_memfree 43506
> 0x0000051f 0x08050e50 -f- 44 ber_memfree 43462
> 0x00000552 0x08050e50 -a- 44 ber_memcalloc 43506
> 0x00000553 0x08050d08 -a- 107 ber_memalloc 43613
> 0x00000553 0x08050d08 -f- 107 ber_memfree 43506
> 0x00000552 0x08050e50 -f- 44 ber_memfree 43462
> test: io.c:179: ber_free: Assertion `ber != ((void *)0)' failed.
> 
> Program received signal SIGABRT, Aborted.
> 0x40171911 in kill () from /lib/libc.so.6
> (gdb) bt
> #0  0x40171911 in kill () from /lib/libc.so.6
> #1  0x40171732 in raise () from /lib/libc.so.6
> #2  0x40172846 in abort () from /lib/libc.so.6
> #3  0x4016b9a9 in __assert_fail () from /lib/libc.so.6
> #4  0x400440d5 in ber_free (ber=0x0, freebuf=1) at io.c:187
> #5  0x4001bc72 in try_read1msg (ld=0x804ae8c, msgid=-1, all=0, sb=0x8050f4c, 
>     lc=0x8050dcc, result=0xbffff670) at result.c:779
> #6  0x4001b341 in wait4msg (ld=0x804ae8c, msgid=-1, all=0, timeout=0x8050dcc, 
>     result=0xbffff670) at result.c:354
> #7  0x08048880 in main ()
> #8  0x401609f1 in __libc_start_main () from /lib/libc.so.6
> (gdb) 
> 
> 
> 
> I intended to file a bug report, but the documentation claimed
> the memory debugging could trigger false asserts and was for
> experts only; seeing as I am not really familiar enough with the
> openldap C interface and I had other urgent things to work on
> I never got to report this. 
> 
> Well, now I've reported my findings. Hope somebody here can pick
> up on it and perhaps investigate to see if these memory leaks/
> free troubles/null pointer troubles are a problem in the openldap
> source code, or due to my abuse of the C API :)
> 
> 
> With regards,
> Frode E. Moe
> Systems developer,
> Coretrek AS  -- http://www.coretrek.com
> ----
> 

> 
> /*
>  * Minimal LDAP testcase to provoke pointer failures
>  * a la PHP 4.3.0 (and earlier)
>  *
>  */
> 
> //#define USE_LDAPv3
> 
> #define CROAK { fprintf(stderr, "failure at %s %d\n", __FILE__, __LINE__); exit(1); }
> 
> #include <ldap.h>
> 
> 
> #include <stdio.h>
> #include <stdlib.h>
> 
> static char * LDAP_URI = "ldap://10.0.0.34";;
> static char * BINDDN   = "cn=Administrator,cn=Users,dc=testserver,dc=intra,dc=coretrek,dc=com";
> static char * BASE     = "dc=testserver,dc=intra,dc=coretrek,dc=com";
> static char * PASSWORD = "XXX"; 
> static char * attribs[] = { "displayName", "sAMAccountName", "mail" };
> static char * search  = "(&(objectCategory=person)(objectClass=user)(!(objectClass=computer)))";
> 
> 
> int main(int argc, char**argv) {
> 
> 	LDAP *ld = NULL;
> 	LDAPMessage *res, *msg;
> 	int rc, i;
> 
> 	ber_int_t msgid;
> 	int numresults, numresponses;
>     int msgtype;
> 
> 	fprintf(stderr, "ldap test case\n");
> 
> 	rc = ldap_initialize(&ld, LDAP_URI);
> 	if (rc != LDAP_SUCCESS) {
> 		CROAK
> 	}
>     
> #ifdef USE_LDAPv3
>     {
>         int version = 3;
>         ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
>     }
> #endif 
> 
> 
> 	rc = ldap_bind_s (ld, BINDDN, PASSWORD, LDAP_AUTH_SIMPLE);
> 	if (rc != LDAP_SUCCESS) {
> 		CROAK
> 	}
> 
> 
> 	rc = ldap_search_ext (ld, BASE, LDAP_SCOPE_SUBTREE, 
> 			search,
> 			attribs,
> 			0,		//	attrsonly?
> 			NULL,		//	sctrls
> 			NULL,		//	cctrls
> 			NULL,		//	timeout	
> 			-1,		//	sizelimit
> 			&msgid
> 			);
> 
> 	if (rc != LDAP_SUCCESS) {
> 		CROAK
> 	}
> 
> 	fprintf(stderr, "search ok\n");
> 	
> 	numresponses = 0;
>     numresults = 0;
> 	res = NULL;
> 	
> 	while ( (rc = ldap_result (ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res)) > 0 ) {
> 	
> 		for ( msg = ldap_first_message(ld, res);
> 				msg != NULL;
> 				msg = ldap_next_message(ld,res) ) {
> 		
>             msgtype = ldap_msgtype(msg);
> 	    	fprintf(stderr, "currently at numresults/numresponses %d/%d - type %d \n", numresults, numresponses, msgtype);
>             numresponses++;
> 
>             if (msgtype == LDAP_RES_SEARCH_RESULT) {
>                 goto done;
>             }
>                     
> 			//	don't do much about the response
> 		}
> 
> 		numresults++;
> 		ldap_msgfree(res);
> 	}
> 
>  done:	
>     fprintf(stderr, "done!\n");
>     ldap_msgfree(res);
> 
> 	fprintf(stderr, "numresults: %d\n", numresults);
> 	
>     ldap_unbind(ld);
>     
> 	fprintf(stderr, "Unbind OK\n");
>     
>     return 0;
> }