/* returns an LDAP error code */ int nsldapi_append_referral( LDAP *ld, char **referralsp, char *s ) { int first; if ( *referralsp == NULL ) { first = 1; *referralsp = (char *)NSLDAPI_MALLOC( strlen( s ) + LDAP_REF_STR_LEN + 1 ); } else { first = 0; *referralsp = (char *)NSLDAPI_REALLOC( *referralsp, strlen( *referralsp ) + strlen( s ) + 2 ); } if ( *referralsp == NULL ) { return( LDAP_NO_MEMORY ); } if ( first ) { strcpy( *referralsp, LDAP_REF_STR ); } else { strcat( *referralsp, "\n" ); } strcat( *referralsp, s ); return( LDAP_SUCCESS ); }
static int break_into_words(char *str, char *delims, char ***wordsp) { char *word, **words; int count; char *lasts; if ((words = (char **)NSLDAPI_CALLOC(1, sizeof(char *))) == NULL) { return (-1); } count = 0; words[count] = NULL; word = ldap_utf8strtok_r(str, delims, &lasts); while (word != NULL) { if ((words = (char **)NSLDAPI_REALLOC( words, (count + 2) * sizeof(char *))) == NULL) { return (-1); } words[count] = word; words[++count] = NULL; word = ldap_utf8strtok_r(NULL, delims, &lasts); } *wordsp = words; return (count); }
LDAP_CALL ldap_explode_dns( const char *dn ) { int ncomps, maxcomps; char *s, *cpydn; char **rdns; #ifdef HAVE_STRTOK_R /* defined in portable.h */ char *lasts; #endif if ( dn == NULL ) { dn = ""; } if ( (rdns = (char **)NSLDAPI_MALLOC( 8 * sizeof(char *) )) == NULL ) { return( NULL ); } maxcomps = 8; ncomps = 0; cpydn = nsldapi_strdup( (char *)dn ); for ( s = STRTOK( cpydn, "@.", &lasts ); s != NULL; s = STRTOK( NULL, "@.", &lasts ) ) { if ( ncomps == maxcomps ) { maxcomps *= 2; if ( (rdns = (char **)NSLDAPI_REALLOC( rdns, maxcomps * sizeof(char *) )) == NULL ) { NSLDAPI_FREE( cpydn ); return( NULL ); } } rdns[ncomps++] = nsldapi_strdup( s ); } rdns[ncomps] = NULL; NSLDAPI_FREE( cpydn ); return( rdns ); }
/* * Abandon all outstanding requests for msgid (included child requests * spawned when chasing referrals). This function calls itself recursively. * No locking is done is this function so it must be done by the caller. * Returns an LDAP error code and sets it in LDAP *ld as well */ static int do_abandon(LDAP *ld, int origid, int msgid, LDAPControl **serverctrls, LDAPControl **clientctrls) { BerElement *ber; int i, bererr, lderr, sendabandon; LDAPRequest *lr = NULL; /* * An abandon request looks like this: * AbandonRequest ::= MessageID */ LDAPDebug(LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n", origid, msgid, 0); /* optimistic */ lderr = LDAP_SUCCESS; /* * Find the request that we are abandoning. Don't send an * abandon message unless there is something to abandon. */ sendabandon = 0; for (lr = ld->ld_requests; lr != NULL; lr = lr->lr_next) { if (lr->lr_msgid == msgid) { /* this message */ if (origid == msgid && lr->lr_parent != NULL) { /* don't let caller abandon child requests! */ lderr = LDAP_PARAM_ERROR; goto set_errorcode_and_return; } if (lr->lr_status == LDAP_REQST_INPROGRESS) { /* * We only need to send an abandon message if * the request is in progress. */ sendabandon = 1; } break; } if (lr->lr_origid == msgid) { /* child: abandon it */ (void)do_abandon(ld, msgid, lr->lr_msgid, serverctrls, clientctrls); /* we ignore errors from child abandons... */ } } if (ldap_msgdelete(ld, msgid) == 0) { /* we had all the results and deleted them */ goto set_errorcode_and_return; } if (lr != NULL && sendabandon) { /* create a message to send */ if ((lderr = nsldapi_alloc_ber_with_options(ld, &ber)) == LDAP_SUCCESS) { int abandon_msgid; LDAP_MUTEX_LOCK(ld, LDAP_MSGID_LOCK); abandon_msgid = ++ld->ld_msgid; LDAP_MUTEX_UNLOCK(ld, LDAP_MSGID_LOCK); #ifdef CLDAP if (ld->ld_dbp->sb_naddr > 0) { bererr = ber_printf(ber, "{isti", abandon_msgid, ld->ld_cldapdn, LDAP_REQ_ABANDON, msgid); } else { #endif /* CLDAP */ bererr = ber_printf(ber, "{iti", abandon_msgid, LDAP_REQ_ABANDON, msgid); #ifdef CLDAP } #endif /* CLDAP */ if (bererr == -1 || (lderr = nsldapi_put_controls(ld, serverctrls, 1, ber)) != LDAP_SUCCESS) { lderr = LDAP_ENCODING_ERROR; ber_free(ber, 1); } else { /* try to send the message */ lderr = nsldapi_send_abandon_message(ld, lr->lr_conn, ber, abandon_msgid); } } } if (lr != NULL) { /* * Always call nsldapi_free_connection() so that the connection's * ref count is correctly decremented. It is OK to always pass * 1 for the "unbind" parameter because doing so will only affect * connections that resulted from a child request (because the * default connection's ref count never goes to zero). */ nsldapi_free_connection(ld, lr->lr_conn, NULL, NULL, 0 /* do not force */, 1 /* send unbind before closing */); /* * Free the entire request chain if we finished abandoning everything. */ if (origid == msgid) { nsldapi_free_request(ld, lr, 0); } } /* * Record the abandoned message ID (used to discard any server responses * that arrive later). */ LDAP_MUTEX_LOCK(ld, LDAP_ABANDON_LOCK); if (ld->ld_abandoned == NULL) { if ((ld->ld_abandoned = (int *)NSLDAPI_MALLOC(2 * sizeof(int))) == NULL) { lderr = LDAP_NO_MEMORY; LDAP_MUTEX_UNLOCK(ld, LDAP_ABANDON_LOCK); goto set_errorcode_and_return; } i = 0; } else { for (i = 0; ld->ld_abandoned[i] != -1; i++) ; /* NULL */ if ((ld->ld_abandoned = (int *)NSLDAPI_REALLOC( (char *)ld->ld_abandoned, (i + 2) * sizeof(int))) == NULL) { lderr = LDAP_NO_MEMORY; LDAP_MUTEX_UNLOCK(ld, LDAP_ABANDON_LOCK); goto set_errorcode_and_return; } } ld->ld_abandoned[i] = msgid; ld->ld_abandoned[i + 1] = -1; LDAP_MUTEX_UNLOCK(ld, LDAP_ABANDON_LOCK); set_errorcode_and_return: LDAP_SET_LDERRNO(ld, lderr, NULL, NULL); return (lderr); }
/* * Pull controls out of "ber" (if any present) and return them in "controlsp." * Returns an LDAP error code. */ int nsldapi_get_controls( BerElement *ber, LDAPControl ***controlsp ) { LDAPControl *newctrl; ber_tag_t tag; ber_len_t len; int rc, maxcontrols, curcontrols; char *last; /* * Each LDAPMessage can have a set of controls appended * to it. Controls are used to extend the functionality * of an LDAP operation (e.g., add an attribute size limit * to the search operation). These controls look like this: * * Controls ::= SEQUENCE OF Control * * Control ::= SEQUENCE { * controlType LDAPOID, * criticality BOOLEAN DEFAULT FALSE, * controlValue OCTET STRING * } */ LDAPDebug( LDAP_DEBUG_TRACE, "=> nsldapi_get_controls\n", 0, 0, 0 ); *controlsp = NULL; /* * check to see if controls were included */ if ( ber_get_option( ber, LBER_OPT_REMAINING_BYTES, &len ) != 0 ) { return( LDAP_DECODING_ERROR ); /* unexpected error */ } if ( len == 0 ) { LDAPDebug( LDAP_DEBUG_TRACE, "<= nsldapi_get_controls no controls\n", 0, 0, 0 ); return( LDAP_SUCCESS ); /* no controls */ } if (( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) { if ( tag == LBER_ERROR ) { LDAPDebug( LDAP_DEBUG_TRACE, "<= nsldapi_get_controls LDAP_PROTOCOL_ERROR\n", 0, 0, 0 ); return( LDAP_DECODING_ERROR ); /* decoding error */ } /* * We found something other than controls. This should never * happen in LDAPv3, but we don't treat this is a hard error -- * we just ignore the extra stuff. */ LDAPDebug( LDAP_DEBUG_TRACE, "<= nsldapi_get_controls ignoring unrecognized data in message (tag 0x%x)\n", tag, 0, 0 ); return( LDAP_SUCCESS ); } maxcontrols = curcontrols = 0; for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET; tag = ber_next_element( ber, &len, last ) ) { if ( curcontrols >= maxcontrols - 1 ) { #define CONTROL_GRABSIZE 5 maxcontrols += CONTROL_GRABSIZE; *controlsp = (struct ldapcontrol **)NSLDAPI_REALLOC( (char *)*controlsp, maxcontrols * sizeof(struct ldapcontrol *) ); if ( *controlsp == NULL ) { rc = LDAP_NO_MEMORY; goto free_and_return; } } if (( newctrl = (struct ldapcontrol *)NSLDAPI_CALLOC( 1, sizeof(LDAPControl))) == NULL ) { rc = LDAP_NO_MEMORY; goto free_and_return; } (*controlsp)[curcontrols++] = newctrl; (*controlsp)[curcontrols] = NULL; if ( ber_scanf( ber, "{a", &newctrl->ldctl_oid ) == LBER_ERROR ) { rc = LDAP_DECODING_ERROR; goto free_and_return; } /* the criticality is optional */ if ( ber_peek_tag( ber, &len ) == LBER_BOOLEAN ) { int aint; if ( ber_scanf( ber, "b", &aint ) == LBER_ERROR ) { rc = LDAP_DECODING_ERROR; goto free_and_return; } newctrl->ldctl_iscritical = (char)aint; /* XXX lossy cast */ } else { /* absent is synonomous with FALSE */ newctrl->ldctl_iscritical = 0; } /* the control value is optional */ if ( ber_peek_tag( ber, &len ) == LBER_OCTETSTRING ) { if ( ber_scanf( ber, "o", &newctrl->ldctl_value ) == LBER_ERROR ) { rc = LDAP_DECODING_ERROR; goto free_and_return; } } else { (newctrl->ldctl_value).bv_val = NULL; (newctrl->ldctl_value).bv_len = 0; } } if ( tag == LBER_ERROR ) { rc = LDAP_DECODING_ERROR; goto free_and_return; } LDAPDebug( LDAP_DEBUG_TRACE, "<= nsldapi_get_controls found %d controls\n", curcontrols, 0, 0 ); return( LDAP_SUCCESS ); free_and_return:; ldap_controls_free( *controlsp ); *controlsp = NULL; LDAPDebug( LDAP_DEBUG_TRACE, "<= nsldapi_get_controls error 0x%x\n", rc, 0, 0 ); return( rc ); }
LDAP_CALL ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs, int exclude, unsigned long syntaxmask ) { /* * this routine should filter out duplicate attributes... */ struct ldap_tmplitem *tirowp, *ticolp; int i, attrcnt, memerr; char **attrs; attrcnt = 0; memerr = 0; if (( attrs = (char **)NSLDAPI_MALLOC( sizeof( char * ))) == NULL ) { return( NULL ); } if ( includeattrs != NULL ) { for ( i = 0; !memerr && includeattrs[ i ] != NULL; ++i ) { if (( attrs = (char **)NSLDAPI_REALLOC( attrs, ( attrcnt + 2 ) * sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] = nsldapi_strdup( includeattrs[ i ] )) == NULL ) { memerr = 1; } else { attrs[ attrcnt ] = NULL; } } } for ( tirowp = ldap_first_tmplrow( tmpl ); !memerr && tirowp != NULLTMPLITEM; tirowp = ldap_next_tmplrow( tmpl, tirowp )) { for ( ticolp = ldap_first_tmplcol( tmpl, tirowp ); ticolp != NULLTMPLITEM; ticolp = ldap_next_tmplcol( tmpl, tirowp, ticolp )) { if ( syntaxmask != 0 ) { if (( exclude && ( syntaxmask & ticolp->ti_syntaxid ) != 0 ) || ( !exclude && ( syntaxmask & ticolp->ti_syntaxid ) == 0 )) { continue; } } if ( ticolp->ti_attrname != NULL ) { if (( attrs = (char **)NSLDAPI_REALLOC( attrs, ( attrcnt + 2 ) * sizeof( char * ))) == NULL || ( attrs[ attrcnt++ ] = nsldapi_strdup( ticolp->ti_attrname )) == NULL ) { memerr = 1; } else { attrs[ attrcnt ] = NULL; } } } } if ( memerr || attrcnt == 0 ) { for ( i = 0; i < attrcnt; ++i ) { if ( attrs[ i ] != NULL ) { NSLDAPI_FREE( attrs[ i ] ); } } NSLDAPI_FREE( (char *)attrs ); return( NULL ); } return( attrs ); }