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

Re: API use in Shared objects?



I see a number of errors in your code which are likely to cause problems
you may erroneusly refer to the object being shared.

> I am not sure if I am posting my questions to the correct list.
>
> I am attempting to create a shared objecs (.so) for use on a linux
> platform which utilizes OpenLDAP API calls, everything works fine until
> I attempt to make a second connection on an unsuccessful search...
>
> ex.
> I connect for the first time and search for a bit of information on the
> LDAP server, it results nothing for the user input, I connect again
> looking for a different piece of information and it crashes.  This
> result happens everytime for any ldap() API calls within' the shared
> object.
>
> If i use the same API calls within a binary or executable application it
> works fine, it tells me there is nothing for that input and allows me to
> try a second search.
>
> In the shared object which I am compiling with the following bit of code:
> CC=gcc
> CFLAGS=-fPIC
> LDFLAGS=-x --shared
> LIBS=-lnsl -lpam -lldap -lc
> SRCS=pam_ldap_lookup.c
> OBJS=pam_ldap_lookup.o
> LIBSHARED=pam_ldap_lookup.so
> LIBCONF=looser.conf
> SECUREDIRECTORY=/lib/security
> CONFDIR=/etc
> CONFMODE=700
> SECUREMODE=755
> INSTALL=install
>
> all: $(LIBSHARED)
>
> install: all
>         $(INSTALL) -m $(SECUREMODE) $(LIBSHARED) $(SECUREDIRECTORY);
>         $(INSTALL) -m $(CONFMODE) $(LIBCONF) $(CONFDIR);
>
> $(LIBSHARED): $(OBJS)
>         $(LD) $(LDFLAGS) -o $@ $? $(LIBS)
>
> $(OBJS): $(SRCS)
>         $(CC) $(CFLAGS) -o $@ -c $*.c
>
> and the function I have created to do the simple search is here...
> static int _ldap_search(udataptr myUser)
> {
>     LDAP            *ld;
>     LDAPMessage     *res, *e, **result;
>     LDAPMessage     *entry;
>     LDAPMessage     *msg;
>     int             i, y;
>     char            *x, *dn;
>     char            *attr;
>     char            **vals;
>     char            buffer[80];
>     char            errors[256];
>     BerElement      **berptr;
>     BerElement      * ber;
>
>     struct timeval myTime;
>     myTime.tv_sec=15;
>     myTime.tv_usec=30;
>     struct timeval *timeout = &myTime;
>
>     berptr = &ber;
>
>     sprintf(buffer, "\"(cn=%s,%s)\"", myUser->usrname, dflts[10]);

              ^^^ are you sure "buffer" is large enough?
              use snprintf AND TEST THE RETURN VALUE

>
>     /* initialize a connection */
>     if((ld = ldap_init(dflts[7], *dflts[8])) == NULL) {
>         _pam_log(LOG_ERR, "Connection failed for %s", dflts[7]);
>         return 0;
>     }
>     _pam_log(LOG_ERR, "Connection succeeded for %s", dflts[7]);
>
>     if(!ldap_simple_bind(ld, dflts[9], dflts[12])) {
>         _pam_log(LOG_ERR, "Couldn't bind to %s", dflts[9]);
>         return 0;
>     }

      ^^^ ldap_simple_bind(), although being deprecated,
      returns the message id to be used in a subsequent
      call to ldap_result.  If you proceed any further
      without calling ldap_result you'll have no chance
      of knowing if bind succeeded or not.  Your code seems
      to work the first time because you interpret message
      id 0 as success, while further message is show up
      as errors.  Use ldap_simple_bind_s() instead.

>     _pam_log(LOG_ERR, "Bind to %s successful", dflts[9]);
>     if(!ldap_search_s(ld, dflts[10], LDAP_SCOPE_SUBTREE,
>                       buffer, NULL, 0, &res)) {
>         _pam_log(LOG_ERR, "LDAP Search failed for: %s", buffer);
>         return 0;
>     }
>     _pam_log(LOG_ERR, "LDAP Search succeeded for: %s", buffer);
>
>     for(e = ldap_first_entry(ld, res); e == NULL; e =

                                         ^^^^ the logic of the test
      is reversed; the loop should continue while e != NULL, work
      with the entry and exit when it's NULL; here you're asking
      for ldap_next_entry() in case of failure!  Note that, according
      to the manual, ldap_next_entry() wants the "entry" field, not
      "res".

> ldap_next_entry(ld, res)) {
>         _pam_log(LOG_ERR, "No results for %s", buffer);
>         ldap_msgfree(res);
>         ldap_unbind_s(ld);
>         return 0;
>     }
>     _pam_log(LOG_ERR, "Results for %s were found", buffer);
>
>     vals = ldap_get_values(ld, e, x);
>     _pam_log(LOG_ERR, "Assigned ldap_get_values() to vals[]");
>     for(i = 0; vals[i] != NULL; i++) {
>         _pam_log(LOG_ERR, "Value: %s", vals[i]);
>         ldap_value_free(vals);
>         return 0;
>     }
>
>     ldap_msgfree(res);
>     ldap_unbind_s(ld);
>     return 0;
> }
>
> As you can see I am at this point only trying to log everything to
> syslog, and you can also see that the appropriate calls to
> ldap_msgfree() & ldap_unbind() are being made.
>
> I have been scouring the online documentation and so far it looks as if
> what I am doing is correct, but like I said, it works up until the point
> of making a second request of the ldap api then crashes.  Do I need to
> do some memory allocation for the ldap api calls when compiled as a
> shared object?

I suggest you fix the above problems and give a better look to the man
pages before getting to any unspecified "online documentation" (google?)

p.

-- 
Pierangelo Masarati
mailto:pierangelo.masarati@sys-net.it


    SysNet - via Dossi,8 27100 Pavia Tel: +390382573859 Fax: +390382476497