Back to index

lightning-sunbird  0.9+nobinonly
Typedefs | Functions
ufn.c File Reference
#include "ldap-int.h"

Go to the source code of this file.

Typedefs

typedef int(LDAP_CALLcancelptype )(void *cancelparm)

Functions

static int ldap_ufn_search_ctx (LDAP *ld, char **ufncomp, int ncomp, char *prefix, char **attrs, int attrsonly, LDAPMessage **res, LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm, char *tag1, char *tag2, char *tag3)
static LDAPMessage * ldap_msg_merge (LDAP *ld, LDAPMessage *a, LDAPMessage *b)
static LDAPMessage * ldap_ufn_expand (LDAP *ld, LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm, char **dns, char *filter, int scope, char **attrs, int aonly, int *err)
int LDAP_CALL ldap_ufn_search_ct (LDAP *ld, char *ufn, char **attrs, int attrsonly, LDAPMessage **res, LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm, char *tag1, char *tag2, char *tag3)
int LDAP_CALL ldap_ufn_search_c (LDAP *ld, char *ufn, char **attrs, int attrsonly, LDAPMessage **res, LDAP_CANCELPROC_CALLBACK *cancelproc, void *cancelparm)
int LDAP_CALL ldap_ufn_search_s (LDAP *ld, char *ufn, char **attrs, int attrsonly, LDAPMessage **res)
LDAPFiltDesc *LDAP_CALL ldap_ufn_setfilter (LDAP *ld, char *fname)
void LDAP_CALL ldap_ufn_setprefix (LDAP *ld, char *prefix)
int LDAP_C ldap_ufn_timeout (void *tvparam)

Typedef Documentation

Definition at line 53 of file ufn.c.


Function Documentation

static LDAPMessage * ldap_msg_merge ( LDAP *  ld,
LDAPMessage *  a,
LDAPMessage *  b 
) [static]

Definition at line 389 of file ufn.c.

{
       LDAPMessage   *end, *aprev, *aend, *bprev, *bend;

       if ( a == NULL )
              return( b );

       if ( b == NULL )
              return( a );

       /* find the ends of the a and b chains */
       aprev = NULL;
       for ( aend = a; aend->lm_chain != NULL; aend = aend->lm_chain )
              aprev = aend;
       bprev = NULL;
       for ( bend = b; bend->lm_chain != NULL; bend = bend->lm_chain )
              bprev = bend;

       /* keep result a */
       if ( ldap_result2error( ld, aend, 0 ) != LDAP_SUCCESS ) {
              /* remove result b */
              ldap_msgfree( bend );
              if ( bprev != NULL )
                     bprev->lm_chain = NULL;
              else
                     b = NULL;
              end = aend;
              if ( aprev != NULL )
                     aprev->lm_chain = NULL;
              else
                     a = NULL;
       /* keep result b */
       } else {
              /* remove result a */
              ldap_msgfree( aend );
              if ( aprev != NULL )
                     aprev->lm_chain = NULL;
              else
                     a = NULL;
              end = bend;
              if ( bprev != NULL )
                     bprev->lm_chain = NULL;
              else
                     b = NULL;
       }

       if ( (a == NULL && b == NULL) || (a == NULL && bprev == NULL) ||
           (b == NULL && aprev == NULL) )
              return( end );

       if ( a == NULL ) {
              bprev->lm_chain = end;
              return( b );
       } else if ( b == NULL ) {
              aprev->lm_chain = end;
              return( a );
       } else {
              bprev->lm_chain = end;
              aprev->lm_chain = b;
              return( a );
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static LDAPMessage * ldap_ufn_expand ( LDAP *  ld,
LDAP_CANCELPROC_CALLBACK *  cancelproc,
void cancelparm,
char **  dns,
char *  filter,
int  scope,
char **  attrs,
int  aonly,
int err 
) [static]

Definition at line 453 of file ufn.c.

{
       LDAPMessage   *tmpcand, *tmpres;
       char          *dn;
       int           i, msgid;
       struct timeval       tv;

       /* search for this component below the current candidates */
       tmpcand = NULL;
       i = 0;
       do {
              if ( dns != NULL )
                     dn = dns[i];
              else
                     dn = "";

              if (( msgid = ldap_search( ld, dn, scope, filter, attrs,
                  aonly )) == -1 ) {
                     ldap_msgfree( tmpcand );
                     *err = LDAP_GET_LDERRNO( ld, NULL, NULL );
                     return( NULL );
              }

              tv.tv_sec = 0;
              tv.tv_usec = 100000; /* 1/10 of a second */

              do {
                     *err = ldap_result( ld, msgid, 1, &tv, &tmpres );
                     if ( *err == 0 && cancelproc != NULL &&
                         (*cancelproc)( cancelparm ) != 0 ) {
                            ldap_abandon( ld, msgid );
                            *err = LDAP_USER_CANCELLED;
                            LDAP_SET_LDERRNO( ld, *err, NULL, NULL );
                     }
              } while ( *err == 0 );

              if ( *err == LDAP_USER_CANCELLED || *err < 0 ||
                  ( *err = ldap_result2error( ld, tmpres, 0 )) == -1 ) {
                     ldap_msgfree( tmpcand );
                     return( NULL );
              }
              
              tmpcand = ldap_msg_merge( ld, tmpcand, tmpres );

              i++;
       } while ( dns != NULL && dns[i] != NULL );

       if ( ldap_count_entries( ld, tmpcand ) > 0 ) {
              return( tmpcand );
       } else {
              ldap_msgfree( tmpcand );
              return( NULL );
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int LDAP_CALL ldap_ufn_search_c ( LDAP *  ld,
char *  ufn,
char **  attrs,
int  attrsonly,
LDAPMessage **  res,
LDAP_CANCELPROC_CALLBACK *  cancelproc,
void cancelparm 
)

Definition at line 357 of file ufn.c.

{
       return( ldap_ufn_search_ct( ld, ufn, attrs, attrsonly, res, cancelproc,
           cancelparm, "ufn first", "ufn intermediate", "ufn last" ) );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int LDAP_CALL ldap_ufn_search_ct ( LDAP *  ld,
char *  ufn,
char **  attrs,
int  attrsonly,
LDAPMessage **  res,
LDAP_CANCELPROC_CALLBACK *  cancelproc,
void cancelparm,
char *  tag1,
char *  tag2,
char *  tag3 
)

Definition at line 263 of file ufn.c.

{
       char   **ufncomp, **prefixcomp;
       char   *pbuf;
       int    ncomp, pcomp, i, err = 0;

       /* getfilter stuff must be inited before we are called */
       if ( ld->ld_filtd == NULL ) {
              err = LDAP_PARAM_ERROR;
              LDAP_SET_LDERRNO( ld, err, NULL, NULL );
              return( err );
       }

       /* call ldap_explode_dn() to break the ufn into its components */
       if ( (ufncomp = ldap_explode_dn( ufn, 0 )) == NULL ) {
              err = LDAP_LOCAL_ERROR;
              LDAP_SET_LDERRNO( ld, err, NULL, NULL );
              return( err );
       }
       for ( ncomp = 0; ufncomp[ncomp] != NULL; ncomp++ )
              ;      /* NULL */

       /* more than two components => try it fully qualified first */
       if ( ncomp > 2 || ld->ld_ufnprefix == NULL ) {
              err = ldap_ufn_search_ctx( ld, ufncomp, ncomp, NULL, attrs,
                  attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 );

              if ( ldap_count_entries( ld, *res ) > 0 ) {
                     ldap_value_free( ufncomp );
                     return( err );
              } else {
                     ldap_msgfree( *res );
                     *res = NULL;
              }
       }

       if ( ld->ld_ufnprefix == NULL ) {
              ldap_value_free( ufncomp );
              return( err );
       }

       /* if that failed, or < 2 components, use the prefix */
       if ( (prefixcomp = ldap_explode_dn( ld->ld_ufnprefix, 0 )) == NULL ) {
              ldap_value_free( ufncomp );
              err = LDAP_LOCAL_ERROR;
              LDAP_SET_LDERRNO( ld, err, NULL, NULL );
              return( err );
       }
       for ( pcomp = 0; prefixcomp[pcomp] != NULL; pcomp++ )
              ;      /* NULL */
       if ( (pbuf = (char *)NSLDAPI_MALLOC( strlen( ld->ld_ufnprefix ) + 1 ))
           == NULL ) {      
              ldap_value_free( ufncomp );
              ldap_value_free( prefixcomp );
              err = LDAP_NO_MEMORY;
              LDAP_SET_LDERRNO( ld, err, NULL, NULL );
              return( err );
       }

       for ( i = 0; i < pcomp; i++ ) {
              int    j;

              *pbuf = '\0';
              for ( j = i; j < pcomp; j++ ) {
                     strcat( pbuf, prefixcomp[j] );
                     if ( j + 1 < pcomp )
                            strcat( pbuf, "," );
              }
              err = ldap_ufn_search_ctx( ld, ufncomp, ncomp, pbuf, attrs,
                  attrsonly, res, cancelproc, cancelparm, tag1, tag2, tag3 );

              if ( ldap_count_entries( ld, *res ) > 0 ) {
                     break;
              } else {
                     ldap_msgfree( *res );
                     *res = NULL;
              }
       }

       ldap_value_free( ufncomp );
       ldap_value_free( prefixcomp );
       NSLDAPI_FREE( pbuf );

       return( err );
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ldap_ufn_search_ctx ( LDAP *  ld,
char **  ufncomp,
int  ncomp,
char *  prefix,
char **  attrs,
int  attrsonly,
LDAPMessage **  res,
LDAP_CANCELPROC_CALLBACK *  cancelproc,
void cancelparm,
char *  tag1,
char *  tag2,
char *  tag3 
) [static]

Definition at line 92 of file ufn.c.

{
       char          *dn, *ftag = NULL;
       char          **dns = NULL;
       int           max, i, err, scope = 0, phase, tries;
       LDAPFiltInfo  *fi;
       LDAPMessage   *tmpcand;
       LDAPMessage   *candidates;
       static char   *objattrs[] = { "objectClass", NULL };

       /* 
        * look up ufn components from most to least significant.
        * there are 3 phases.  
        *     phase 1       search the root for orgs or countries
        *     phase 2       search for orgs
        *     phase 3       search for a person
        * in phases 1 and 2, we are building a list of candidate DNs,
        * below which we will search for the final component of the ufn.
        * for each component we try the filters listed in the
        * filterconfig file, first one-level (except the last compoment),
        * then subtree.  if any of them produce any results, we go on to
        * the next component.
        */

       *res = NULL;
       candidates = NULL;
       phase = 1;
       for ( ncomp--; ncomp != -1; ncomp-- ) {
              if ( *ufncomp[ncomp] == '"' ) {
                     char   *quote;

                     if ( (quote = strrchr( ufncomp[ncomp], '"' )) != NULL )
                            *quote = '\0';
                     strcpy( ufncomp[ncomp], ufncomp[ncomp] + 1 );
              }
              if ( ncomp == 0 )
                     phase = 3;

              switch ( phase ) {
              case 1:
                     ftag = tag1;
                     scope = LDAP_SCOPE_ONELEVEL;
                     break;
              case 2:
                     ftag = tag2;
                     scope = LDAP_SCOPE_ONELEVEL;
                     break;
              case 3:
                     ftag = tag3;
                     scope = LDAP_SCOPE_SUBTREE;
                     break;
              }

              /*
               * construct an array of DN's to search below from the
               * list of candidates.
               */

              if ( candidates == NULL ) {
                     if ( prefix != NULL ) {
                            if ( (dns = (char **)NSLDAPI_MALLOC(
                                sizeof(char *) * 2 )) == NULL ) {
                                   err = LDAP_NO_MEMORY;
                                   LDAP_SET_LDERRNO( ld, err, NULL, NULL );
                                   return( err );
                            }
                            dns[0] = nsldapi_strdup( prefix );
                            dns[1] = NULL;
                     } else {
                            dns = NULL;
                     }
              } else {
                     i = 0, max = 0;
                     for ( tmpcand = candidates; tmpcand != NULL &&
                         tmpcand->lm_msgtype != LDAP_RES_SEARCH_RESULT;
                         tmpcand = tmpcand->lm_chain )
                     {
                            if ( (dn = ldap_get_dn( ld, tmpcand )) == NULL )
                                   continue;

                            if ( dns == NULL ) {
                                   if ( (dns = (char **)NSLDAPI_MALLOC(
                                       sizeof(char *) * 8 )) == NULL ) {
                                          err = LDAP_NO_MEMORY;
                                          LDAP_SET_LDERRNO( ld, err,
                                              NULL, NULL );
                                          return( err );
                                   }
                                   max = 8;
                            } else if ( i >= max ) {
                                   if ( (dns = (char **)NSLDAPI_REALLOC(
                                       dns, sizeof(char *) * 2 * max ))
                                       == NULL ) {
                                          err = LDAP_NO_MEMORY;
                                          LDAP_SET_LDERRNO( ld, err,
                                              NULL, NULL );
                                          return( err );
                                   }
                                   max *= 2;
                            }
                            dns[i++] = dn;
                            dns[i] = NULL;
                     }
                     ldap_msgfree( candidates );
                     candidates = NULL;
              }
              tries = 0;
       tryagain:
              tries++;
              for ( fi = ldap_getfirstfilter( ld->ld_filtd, ftag,
                  ufncomp[ncomp] ); fi != NULL;
                  fi = ldap_getnextfilter( ld->ld_filtd ) )
              {
                     if ( (candidates = ldap_ufn_expand( ld, cancelproc,
                         cancelparm, dns, fi->lfi_filter, scope,
                         phase == 3 ? attrs : objattrs,
                         phase == 3 ? attrsonly : 1, &err )) != NULL )
                     {
                            break;
                     }

                     if ( err == -1 || err == LDAP_USER_CANCELLED ) {
                            if ( dns != NULL ) {
                                   ldap_value_free( dns );
                                   dns = NULL;
                            }
                            return( err );
                     }
              }

              if ( candidates == NULL ) {
                     if ( tries < 2 && phase != 3 ) {
                            scope = LDAP_SCOPE_SUBTREE;
                            goto tryagain;
                     } else {
                            if ( dns != NULL ) {
                                   ldap_value_free( dns );
                                   dns = NULL;
                            }
                            return( err );
                     }
              }

              /* go on to the next component */
              if ( phase == 1 )
                     phase++;
              if ( dns != NULL ) {
                     ldap_value_free( dns );
                     dns = NULL;
              }
       }
       *res = candidates;

       return( err );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int LDAP_CALL ldap_ufn_search_s ( LDAP *  ld,
char *  ufn,
char **  attrs,
int  attrsonly,
LDAPMessage **  res 
)

Definition at line 369 of file ufn.c.

{
       struct timeval       tv;

       tv.tv_sec = ld->ld_timelimit;

       return( ldap_ufn_search_ct( ld, ufn, attrs, attrsonly, res,
              ld->ld_timelimit ? ldap_ufn_timeout : NULL,
              ld->ld_timelimit ? (void *) &tv : NULL,
              "ufn first", "ufn intermediate", "ufn last" ) );
}

Here is the call graph for this function:

Here is the caller graph for this function:

LDAPFiltDesc* LDAP_CALL ldap_ufn_setfilter ( LDAP *  ld,
char *  fname 
)

Definition at line 516 of file ufn.c.

{
       if ( ld->ld_filtd != NULL )
              ldap_getfilter_free( ld->ld_filtd );

       return( ld->ld_filtd = ldap_init_getfilter( fname ) );
}

Here is the call graph for this function:

void LDAP_CALL ldap_ufn_setprefix ( LDAP *  ld,
char *  prefix 
)

Definition at line 526 of file ufn.c.

{
       if ( ld->ld_ufnprefix != NULL )
              NSLDAPI_FREE( ld->ld_ufnprefix );

       ld->ld_ufnprefix = nsldapi_strdup( prefix );
}

Here is the call graph for this function:

Here is the caller graph for this function:

int LDAP_C ldap_ufn_timeout ( void tvparam)

Definition at line 536 of file ufn.c.

{
       struct timeval       *tv;

       tv = (struct timeval *)tvparam;

       if ( tv->tv_sec != 0 ) {
              tv->tv_usec = tv->tv_sec * 1000000;       /* sec => micro sec */
              tv->tv_sec = 0;
       }
       tv->tv_usec -= 100000;      /* 1/10 of a second */

       return( tv->tv_usec <= 0 ? 1 : 0 );
}

Here is the caller graph for this function: