/* * Pull the oid returned by the server and the data out of an extended * operation result. Return an LDAP error code. */ int LDAP_CALL ldap_parse_extended_result( LDAP *ld, LDAPMessage *res, char **retoidp, /* may be NULL */ struct berval **retdatap, /* may be NULL */ int freeit) { struct berelement ber; ber_len_t len; ber_int_t err; char *m, *e, *roid; struct berval *rdata; LDAPDebug(LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n", 0, 0, 0); if (!NSLDAPI_VALID_LDAP_POINTER(ld)) { return (LDAP_PARAM_ERROR); } if (!NSLDAPI_VALID_LDAPMESSAGE_EXRESULT_POINTER(res)) { return (LDAP_PARAM_ERROR); } m = e = NULL; ber = *(res->lm_ber); if (NSLDAPI_LDAP_VERSION(ld) < LDAP_VERSION3) { LDAP_SET_LDERRNO(ld, LDAP_NOT_SUPPORTED, NULL, NULL); return (LDAP_NOT_SUPPORTED); } if (ber_scanf(&ber, "{iaa", &err, &m, &e) == LBER_ERROR) { goto decoding_error; } roid = NULL; if (ber_peek_tag(&ber, &len) == LDAP_TAG_EXOP_RES_OID) { if (ber_scanf(&ber, "a", &roid) == LBER_ERROR) { goto decoding_error; } } if (retoidp != NULL) { *retoidp = roid; } else if (roid != NULL) { NSLDAPI_FREE(roid); } rdata = NULL; if (ber_peek_tag(&ber, &len) == LDAP_TAG_EXOP_RES_VALUE) { if (ber_scanf(&ber, "O", &rdata) == LBER_ERROR) { goto decoding_error; } } if (retdatap != NULL) { *retdatap = rdata; } else if (rdata != NULL) { ber_bvfree(rdata); } LDAP_SET_LDERRNO(ld, err, m, e); if (freeit) { ldap_msgfree(res); } return (LDAP_SUCCESS); decoding_error:; LDAP_SET_LDERRNO(ld, LDAP_DECODING_ERROR, NULL, NULL); return (LDAP_DECODING_ERROR); }
int LDAP_CALL ldap_parse_sort_control ( LDAP *ld, LDAPControl **ctrlp, unsigned long *result, char **attribute ) { BerElement *ber; int i, foundSortControl; LDAPControl *sortCtrlp; unsigned long len, tag; char *attr; if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || result == NULL || attribute == NULL ) { return( LDAP_PARAM_ERROR ); } /* find the sortControl in the list of controls if it exists */ if ( ctrlp == NULL ) { LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); return ( LDAP_CONTROL_NOT_FOUND ); } foundSortControl = 0; for ( i = 0; (( ctrlp[i] != NULL ) && ( !foundSortControl )); i++ ) { foundSortControl = !strcmp( ctrlp[i]->ldctl_oid, LDAP_CONTROL_SORTRESPONSE ); } if ( !foundSortControl ) { LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); return ( LDAP_CONTROL_NOT_FOUND ); } else { /* let local var point to the sortControl */ sortCtrlp = ctrlp[i-1]; } /* allocate a Ber element with the contents of the sort_control's struct berval */ if ( ( ber = ber_init( &sortCtrlp->ldctl_value ) ) == NULL ) { LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); return( LDAP_NO_MEMORY ); } /* decode the result from the Berelement */ if ( ber_scanf( ber, "{i", result ) == LBER_ERROR ) { LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); ber_free( ber, 1 ); return( LDAP_DECODING_ERROR ); } /* if the server returned one, decode the attribute from the Ber element */ if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SR_ATTRTYPE ) { if ( ber_scanf( ber, "ta", &tag, &attr ) == LBER_ERROR ) { LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); ber_free( ber, 1 ); return( LDAP_DECODING_ERROR ); } *attribute = attr; } else { *attribute = NULL; } if ( ber_scanf( ber, "}" ) == LBER_ERROR ) { LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); ber_free( ber, 1 ); return( LDAP_DECODING_ERROR ); } /* the ber encoding is no longer needed */ ber_free(ber,1); return( LDAP_SUCCESS ); }
int LDAP_CALL ldap_create_sort_control ( LDAP *ld, LDAPsortkey **sortKeyList, const char ctl_iscritical, LDAPControl **ctrlp ) { BerElement *ber; int i, rc; if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { return( LDAP_PARAM_ERROR ); } if ( sortKeyList == NULL || ctrlp == NULL ) { LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); return ( LDAP_PARAM_ERROR ); } /* create a ber package to hold the controlValue */ if ( ( nsldapi_alloc_ber_with_options( ld, &ber ) ) != LDAP_SUCCESS ) { LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); return( LDAP_NO_MEMORY ); } /* encode the start of the sequence of sequences into the ber */ if ( ber_printf( ber, "{" ) == -1 ) { goto encoding_error_exit; } /* the sort control value will be encoded as a sequence of sequences which are each encoded as one of the following: {s} or {sts} or {stb} or {ststb} since the orderingRule and reverseOrder flag are both optional */ for ( i = 0; sortKeyList[i] != NULL; i++ ) { /* encode the attributeType into the ber */ if ( ber_printf( ber, "{s", (sortKeyList[i])->sk_attrtype ) == -1 ) { goto encoding_error_exit; } /* encode the optional orderingRule into the ber */ if ( (sortKeyList[i])->sk_matchruleoid != NULL ) { if ( ber_printf( ber, "ts", LDAP_TAG_SK_MATCHRULE, (sortKeyList[i])->sk_matchruleoid ) == -1 ) { goto encoding_error_exit; } } /* Encode the optional reverseOrder flag into the ber. */ /* If the flag is false, it should be absent. */ if ( (sortKeyList[i])->sk_reverseorder ) { if ( ber_printf( ber, "tb}", LDAP_TAG_SK_REVERSE, (sortKeyList[i])->sk_reverseorder ) == -1 ) { goto encoding_error_exit; } } else { if ( ber_printf( ber, "}" ) == -1 ) { goto encoding_error_exit; } } } /* encode the end of the sequence of sequences into the ber */ if ( ber_printf( ber, "}" ) == -1 ) { goto encoding_error_exit; } rc = nsldapi_build_control( LDAP_CONTROL_SORTREQUEST, ber, 1, ctl_iscritical, ctrlp ); LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); return( rc ); encoding_error_exit: LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); ber_free( ber, 1 ); return( LDAP_ENCODING_ERROR ); }
/* returns an LDAP error code that indicates if parse succeeded or not */ int LDAP_CALL ldap_parse_sasl_bind_result( LDAP *ld, LDAPMessage *res, struct berval **servercredp, int freeit ) { BerElement ber; int rc, err; ber_int_t along; ber_len_t len; char *m, *e; LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_sasl_bind_result\n", 0, 0, 0 ); /* * the ldapv3 SASL bind response looks like this: * * BindResponse ::= [APPLICATION 1] SEQUENCE { * COMPONENTS OF LDAPResult, * serverSaslCreds [7] OCTET STRING OPTIONAL * } * * all wrapped up in an LDAPMessage sequence. */ if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || !NSLDAPI_VALID_LDAPMESSAGE_BINDRESULT_POINTER( res )) { return( LDAP_PARAM_ERROR ); } /* only ldapv3 or higher can do sasl binds */ if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); return( LDAP_NOT_SUPPORTED ); } if ( servercredp != NULL ) { *servercredp = NULL; } ber = *(res->lm_ber); /* struct copy */ /* skip past message id, matched dn, error message ... */ rc = ber_scanf( &ber, "{iaa}", &along, &m, &e ); if ( rc != LBER_ERROR && ber_peek_tag( &ber, &len ) == LDAP_TAG_SASL_RES_CREDS ) { rc = ber_get_stringal( &ber, servercredp ); } if ( freeit ) { ldap_msgfree( res ); } if ( rc == LBER_ERROR ) { err = LDAP_DECODING_ERROR; } else { err = (int) along; } LDAP_SET_LDERRNO( ld, err, m, e ); /* this is a little kludge for the 3.0 Barracuda/hammerhead relese */ /* the docs state that the return is either LDAP_DECODING_ERROR */ /* or LDAP_SUCCESS. Here we match the docs... it's cleaner in 3.1 */ if ( LDAP_DECODING_ERROR == err ) { return (LDAP_DECODING_ERROR); } else { return( LDAP_SUCCESS ); } }
int LDAP_CALL ldap_parse_userstatus_control ( LDAP *ld, LDAPControl **ctrlp, LDAPuserstatus *us ) { BerElement *ber = NULL; int i, foundUSControl; LDAPControl *USCtrlp = NULL; ber_tag_t tag; if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || us == NULL ) { return( LDAP_PARAM_ERROR ); } /* find the control in the list of controls if it exists */ if ( ctrlp == NULL ) { LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); return ( LDAP_CONTROL_NOT_FOUND ); } foundUSControl = 0; for ( i = 0; (( ctrlp[i] != NULL ) && ( !foundUSControl )); i++ ) { foundUSControl = !strcmp( ctrlp[i]->ldctl_oid, LDAP_CONTROL_ACCOUNT_USABLE ); } if ( !foundUSControl ) { LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL ); return ( LDAP_CONTROL_NOT_FOUND ); } else { /* let local var point to the control */ USCtrlp = ctrlp[i-1]; } /* allocate a Ber element with the contents of the control's struct berval */ if ( ( ber = ber_init( &USCtrlp->ldctl_value ) ) == NULL ) { LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); return( LDAP_NO_MEMORY ); } memset( us, 0, sizeof(struct LDAPuserstatus) ); /* * The control value should look like this: * * ACCOUNT_USABLE_RESPONSE::= CHOICE { * is_available [0] INTEGER, ** seconds before expiration ** * is_not_available [1] More_info * } * More_info::= SEQUENCE { * inactive [0] BOOLEAN DEFAULT FALSE, * reset [1] BOOLEAN DEFAULT FALSE, * expired [2] BOOLEAN DEFAULT FALSE, * remaining_grace [3] INTEGER OPTIONAL, * seconds_before_unlock [4] INTEGER OPTIONAL * } */ if ( ( ber_scanf( ber, "t", &tag ) ) == LBER_ERROR ) { LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); ber_free( ber, 1 ); return( LDAP_DECODING_ERROR ); } tag = (( tag & LBER_CONSTRUCTED ) == LBER_CONSTRUCTED ) ? 1 : 0; if ( !tag ) { us->us_available = 1; if ( ber_scanf( ber, "i", &us->us_expire ) == LBER_ERROR ) { LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); ber_free( ber, 1 ); return( LDAP_DECODING_ERROR ); } } else { us->us_available = 0; tag = 0; if ( ( ber_scanf( ber, "{t", &tag ) ) == LBER_ERROR ) { LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); ber_free( ber, 1 ); return( LDAP_DECODING_ERROR ); } while ( tag != LBER_ERROR && tag != LBER_END_OF_SEQORSET ) { tag = tag & (~LBER_CLASS_CONTEXT); switch (tag) { case 0: if ( ber_scanf( ber, "b", &us->us_inactive ) == LBER_ERROR ) { LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); ber_free( ber, 1 ); return( LDAP_DECODING_ERROR ); } us->us_inactive = ( us->us_inactive != 0 ) ? 1 : 0; break; case 1: if ( ber_scanf( ber, "b", &us->us_reset ) == LBER_ERROR ) { LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); ber_free( ber, 1 ); return( LDAP_DECODING_ERROR ); } us->us_reset = ( us->us_reset != 0 ) ? 1 : 0; break; case 2: if ( ber_scanf( ber, "b", &us->us_expired ) == LBER_ERROR ) { LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); ber_free( ber, 1 ); return( LDAP_DECODING_ERROR ); } us->us_expired = ( us->us_expired != 0 ) ? 1 : 0; break; case 3: if ( ber_scanf( ber, "i", &us->us_remaining ) == LBER_ERROR ) { LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); ber_free( ber, 1 ); return( LDAP_DECODING_ERROR ); } break; case 4: if ( ber_scanf( ber, "i", &us->us_seconds ) == LBER_ERROR ) { LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); ber_free( ber, 1 ); return( LDAP_DECODING_ERROR ); } break; default: LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); ber_free( ber, 1 ); return( LDAP_DECODING_ERROR ); } ber_scanf( ber, "t", &tag ); } } /* the ber encoding is no longer needed */ ber_free( ber, 1 ); return( LDAP_SUCCESS ); }
static int nsldapi_get_sasl_mechs ( LDAP *ld, char **pmech ) { char *attr[] = { "supportedSASLMechanisms", NULL }; char **values, **v, *mech, *m; LDAPMessage *res, *e; struct timeval timeout; int slen, rc; if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { return( LDAP_PARAM_ERROR ); } timeout.tv_sec = SEARCH_TIMEOUT_SECS; timeout.tv_usec = 0; rc = ldap_search_st( ld, "", LDAP_SCOPE_BASE, "objectclass=*", attr, 0, &timeout, &res ); if ( rc != LDAP_SUCCESS ) { return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); } e = ldap_first_entry( ld, res ); if ( e == NULL ) { ldap_msgfree( res ); if ( ld->ld_errno == LDAP_SUCCESS ) { LDAP_SET_LDERRNO( ld, LDAP_NO_SUCH_OBJECT, NULL, NULL ); } return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); } values = ldap_get_values( ld, e, "supportedSASLMechanisms" ); if ( values == NULL ) { ldap_msgfree( res ); LDAP_SET_LDERRNO( ld, LDAP_NO_SUCH_ATTRIBUTE, NULL, NULL ); return( LDAP_NO_SUCH_ATTRIBUTE ); } slen = 0; for(v = values; *v != NULL; v++ ) { slen += strlen(*v) + 1; } if ( (mech = NSLDAPI_CALLOC(1, slen)) == NULL) { ldap_value_free( values ); ldap_msgfree( res ); LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); return( LDAP_NO_MEMORY ); } m = mech; for(v = values; *v; v++) { if (v != values) { *m++ = ' '; } slen = strlen(*v); strncpy(m, *v, slen); m += slen; } *m = '\0'; ldap_value_free( values ); ldap_msgfree( res ); *pmech = mech; return( LDAP_SUCCESS ); }
/* * ldap_sasl_bind - authenticate to the ldap server. The dn, mechanism, * and credentials of the entry to which to bind are supplied. An LDAP * error code is returned and if LDAP_SUCCESS is returned *msgidp is set * to the id of the request initiated. * * Example: * struct berval creds; * LDAPControl **ctrls; * int err, msgid; * ... fill in creds with credentials ... * ... fill in ctrls with server controls ... * err = ldap_sasl_bind( ld, "cn=manager, o=university of michigan, c=us", * "mechanismname", &creds, ctrls, NULL, &msgid ); */ int LDAP_CALL ldap_sasl_bind( LDAP *ld, const char *dn, const char *mechanism, const struct berval *cred, LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp ) { BerElement *ber; int rc, simple, msgid, ldapversion; /* * The ldapv3 bind request looks like this: * BindRequest ::= SEQUENCE { * version INTEGER, * name DistinguishedName, -- who * authentication CHOICE { * simple [0] OCTET STRING, -- passwd * sasl [3] SaslCredentials -- v3 only * } * } * SaslCredentials ::= SEQUENCE { * mechanism LDAPString, * credentials OCTET STRING * } * all wrapped up in an LDAPMessage sequence. */ LDAPDebug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 ); if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { return( LDAP_PARAM_ERROR ); } if ( msgidp == NULL ) { LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); return( LDAP_PARAM_ERROR ); } if ( ( ld->ld_options & LDAP_BITOPT_RECONNECT ) != 0 ) { nsldapi_handle_reconnect( ld ); } simple = ( mechanism == LDAP_SASL_SIMPLE ); ldapversion = NSLDAPI_LDAP_VERSION( ld ); /* only ldapv3 or higher can do sasl binds */ if ( !simple && ldapversion < LDAP_VERSION3 ) { LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); return( LDAP_NOT_SUPPORTED ); } LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); msgid = ++ld->ld_msgid; LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); if ( dn == NULL ) dn = ""; if ( ld->ld_cache_on && ld->ld_cache_bind != NULL ) { LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); if ( (rc = (ld->ld_cache_bind)( ld, msgid, LDAP_REQ_BIND, dn, cred, LDAP_AUTH_SASL )) != 0 ) { *msgidp = rc; LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); return( LDAP_SUCCESS ); } LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); } /* create a message to send */ if (( rc = nsldapi_alloc_ber_with_options( ld, &ber )) != LDAP_SUCCESS ) { return( rc ); } /* fill it in */ if ( simple ) { /* simple bind; works in LDAPv2 or v3 */ struct berval tmpcred; if ( cred == NULL ) { tmpcred.bv_val = ""; tmpcred.bv_len = 0; cred = &tmpcred; } rc = ber_printf( ber, "{it{isto}", msgid, LDAP_REQ_BIND, ldapversion, dn, LDAP_AUTH_SIMPLE, cred->bv_val, cred->bv_len ); } else { /* SASL bind; requires LDAPv3 or better */ if ( cred == NULL ) { rc = ber_printf( ber, "{it{ist{s}}", msgid, LDAP_REQ_BIND, ldapversion, dn, LDAP_AUTH_SASL, mechanism ); } else { rc = ber_printf( ber, "{it{ist{so}}", msgid, LDAP_REQ_BIND, ldapversion, dn, LDAP_AUTH_SASL, mechanism, cred->bv_val, cred->bv_len ); } } if ( rc == -1 ) { LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL ); ber_free( ber, 1 ); return( LDAP_ENCODING_ERROR ); } if ( (rc = nsldapi_put_controls( ld, serverctrls, 1, ber )) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return( rc ); } /* send the message */ rc = nsldapi_send_initial_request( ld, msgid, LDAP_REQ_BIND, (char *)dn, ber ); *msgidp = rc; return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); }
int LDAP_CALL ldap_url_search( LDAP *ld, const char *url, int attrsonly ) { int err, msgid; LDAPURLDesc *ludp; BerElement *ber; LDAPServer *srv; char *host; if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { return( -1 ); /* punt */ } if ( ldap_url_parse( url, &ludp ) != 0 ) { LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); return( -1 ); } LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); msgid = ++ld->ld_msgid; LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); if ( nsldapi_build_search_req( ld, ludp->lud_dn, ludp->lud_scope, ludp->lud_filter, ludp->lud_attrs, attrsonly, NULL, NULL, -1, -1, msgid, &ber ) != LDAP_SUCCESS ) { return( -1 ); } err = 0; if ( ludp->lud_host == NULL ) { host = ld->ld_defhost; } else { host = ludp->lud_host; } if (( srv = (LDAPServer *)NSLDAPI_CALLOC( 1, sizeof( LDAPServer ))) == NULL || ( host != NULL && ( srv->lsrv_host = nsldapi_strdup( host )) == NULL )) { if ( srv != NULL ) { NSLDAPI_FREE( srv ); } LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); err = -1; } else { if ( ludp->lud_port == 0 ) { if (( ludp->lud_options & LDAP_URL_OPT_SECURE ) == 0 ) { srv->lsrv_port = LDAP_PORT; } else { srv->lsrv_port = LDAPS_PORT; } } else { srv->lsrv_port = ludp->lud_port; } } if (( ludp->lud_options & LDAP_URL_OPT_SECURE ) != 0 ) { srv->lsrv_options |= LDAP_SRV_OPT_SECURE; } if ( err != 0 ) { ber_free( ber, 1 ); } else { err = nsldapi_send_server_request( ld, ber, msgid, NULL, srv, NULL, NULL, 1 ); } ldap_free_urldesc( ludp ); return( err ); }
int LDAP_CALL ldap_modify_ext( LDAP *ld, const char *dn, LDAPMod **mods, LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp ) { BerElement *ber; int i, rc, lderr; /* * A modify request looks like this: * ModifyRequet ::= SEQUENCE { * object DistinguishedName, * modifications SEQUENCE OF SEQUENCE { * operation ENUMERATED { * add (0), * delete (1), * replace (2) * }, * modification SEQUENCE { * type AttributeType, * values SET OF AttributeValue * } * } * } */ LDAPDebug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 ); if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { return( LDAP_PARAM_ERROR ); } if ( !NSLDAPI_VALID_LDAPMESSAGE_POINTER( msgidp )) { LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); return( LDAP_PARAM_ERROR ); } if ( !NSLDAPI_VALID_NONEMPTY_LDAPMOD_ARRAY( mods )) { lderr = LDAP_PARAM_ERROR; LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); return( lderr ); } if ( dn == NULL ) { dn = ""; } LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); *msgidp = ++ld->ld_msgid; LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); /* see if we should add to the cache */ if ( ld->ld_cache_on && ld->ld_cache_modify != NULL ) { LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); if ( (rc = (ld->ld_cache_modify)( ld, *msgidp, LDAP_REQ_MODIFY, dn, mods )) != 0 ) { *msgidp = rc; LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); return( LDAP_SUCCESS ); } LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); } /* create a message to send */ if (( lderr = nsldapi_alloc_ber_with_options( ld, &ber )) != LDAP_SUCCESS ) { return( lderr ); } if ( ber_printf( ber, "{it{s{", *msgidp, LDAP_REQ_MODIFY, dn ) == -1 ) { lderr = LDAP_ENCODING_ERROR; LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); ber_free( ber, 1 ); return( lderr ); } /* for each modification to be performed... */ for ( i = 0; mods[i] != NULL; i++ ) { if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) { rc = ber_printf( ber, "{e{s[V]}}", mods[i]->mod_op & ~LDAP_MOD_BVALUES, mods[i]->mod_type, mods[i]->mod_bvalues ); } else { rc = ber_printf( ber, "{e{s[v]}}", mods[i]->mod_op, mods[i]->mod_type, mods[i]->mod_values ); } if ( rc == -1 ) { lderr = LDAP_ENCODING_ERROR; LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); ber_free( ber, 1 ); return( lderr ); } } if ( ber_printf( ber, "}}" ) == -1 ) { lderr = LDAP_ENCODING_ERROR; LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); ber_free( ber, 1 ); return( lderr ); } if (( lderr = nsldapi_put_controls( ld, serverctrls, 1, ber )) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return( lderr ); } /* send the message */ rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_MODIFY, (char *)dn, ber ); *msgidp = rc; return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); }
/* * Like ldap_search_ext() except an integer timelimit is passed instead of * using the overloaded struct timeval *timeoutp. */ static int nsldapi_search( LDAP *ld, const char *base, int scope, const char *filter, char **attrs, int attrsonly, LDAPControl **serverctrls, LDAPControl **clientctrls, int timelimit, /* -1 means use ld->ld_timelimit */ int sizelimit, /* -1 means use ld->ld_sizelimit */ int *msgidp ) { BerElement *ber; int rc, rc_key; unsigned long key; /* XXXmcs: memcache */ LDAPDebug( LDAP_DEBUG_TRACE, "ldap_search_ext\n", 0, 0, 0 ); if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { return( LDAP_PARAM_ERROR ); } if ( base == NULL ) { base = ""; } if ( filter == NULL ) { filter = "(objectclass=*)"; } if ( msgidp == NULL || ( scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL && scope != LDAP_SCOPE_SUBTREE ) || ( sizelimit < -1 )) { LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL ); return( LDAP_PARAM_ERROR ); } LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); *msgidp = ++ld->ld_msgid; LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); /* * XXXmcs: should use cache function pointers to hook in memcache */ if ( ld->ld_memcache == NULL ) { rc_key = LDAP_NOT_SUPPORTED; } else if (( rc_key = ldap_memcache_createkey( ld, base, scope, filter, attrs, attrsonly, serverctrls, clientctrls, &key)) == LDAP_SUCCESS && ldap_memcache_result( ld, *msgidp, key ) == LDAP_SUCCESS ) { return LDAP_SUCCESS; } /* check the cache */ if ( ld->ld_cache_on && ld->ld_cache_search != NULL ) { LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK ); if ( (rc = (ld->ld_cache_search)( ld, *msgidp, LDAP_REQ_SEARCH, base, scope, filter, attrs, attrsonly )) != 0 ) { *msgidp = rc; LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); return( LDAP_SUCCESS ); } LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK ); } /* caching off or did not find it in the cache - check the net */ if (( rc = nsldapi_build_search_req( ld, base, scope, filter, attrs, attrsonly, serverctrls, clientctrls, timelimit, sizelimit, *msgidp, &ber )) != LDAP_SUCCESS ) { return( rc ); } /* send the message */ rc = nsldapi_send_initial_request( ld, *msgidp, LDAP_REQ_SEARCH, (char *) base, ber ); /* * XXXmcs: should use cache function pointers to hook in memcache */ if ( (rc_key == LDAP_SUCCESS) && (rc >= 0) ) { ldap_memcache_new( ld, rc, key, base ); } *msgidp = rc; return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS ); }
static int do_vals2text( LDAP *ld, char *buf, /* NULL for "use internal" */ char **vals, char *label, int labelwidth, /* 0 means use default */ unsigned long syntaxid, writeptype writeproc, void *writeparm, char *eol, int rdncount, char *urlprefix ) { int err, i, html, writeoutval, freebuf, notascii; char *p, *s, *outval; if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || writeproc == NULL ) { return( LDAP_PARAM_ERROR ); } if ( vals == NULL ) { return( LDAP_SUCCESS ); } html = ( urlprefix != NULL ); switch( LDAP_GET_SYN_TYPE( syntaxid )) { case LDAP_SYN_TYPE_TEXT: case LDAP_SYN_TYPE_BOOLEAN: break; /* we only bother with these two types... */ default: return( LDAP_SUCCESS ); } if ( labelwidth == 0 || labelwidth < 0 ) { labelwidth = DEF_LABEL_WIDTH; } if ( buf == NULL ) { if (( buf = NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ )) == NULL ) { err = LDAP_NO_MEMORY; LDAP_SET_LDERRNO( ld, err, NULL, NULL ); return( err ); } freebuf = 1; } else { freebuf = 0; } output_label( buf, label, labelwidth, writeproc, writeparm, eol, html ); for ( i = 0; vals[ i ] != NULL; ++i ) { for ( p = vals[ i ]; *p != '\0'; ++p ) { if ( !isascii( *p )) { break; } } notascii = ( *p != '\0' ); outval = notascii ? dgettext(TEXT_DOMAIN, "(unable to display non-ASCII text value)") : vals[ i ]; writeoutval = 0; /* if non-zero, write outval after switch */ switch( syntaxid ) { case LDAP_SYN_CASEIGNORESTR: ++writeoutval; break; case LDAP_SYN_RFC822ADDR: if ( html ) { strcpy( buf, "<DD><A HREF=\"mailto:" ); strcat_escaped( buf, outval ); sprintf( buf + strlen( buf ), "\">%s</A><BR>%s", outval, eol ); (*writeproc)( writeparm, buf, strlen( buf )); } else { ++writeoutval; } break; case LDAP_SYN_DN: /* for now */ output_dn( buf, outval, labelwidth, rdncount, writeproc, writeparm, eol, urlprefix ); break; case LDAP_SYN_MULTILINESTR: if ( i > 0 && !html ) { output_label( buf, label, labelwidth, writeproc, writeparm, eol, html ); } p = s = outval; while (( s = strchr( s, '$' )) != NULL ) { *s++ = '\0'; while ( ldap_utf8isspace( s )) { ++s; } if ( html ) { sprintf( buf, "<DD>%s<BR>%s", p, eol ); } else { sprintf( buf, "%-*s%s%s", labelwidth, " ", p, eol ); } (*writeproc)( writeparm, buf, strlen( buf )); p = s; } outval = p; ++writeoutval; break; case LDAP_SYN_BOOLEAN: outval = toupper( outval[ 0 ] ) == 'T' ? dgettext(TEXT_DOMAIN, "TRUE") : dgettext(TEXT_DOMAIN, "FALSE"); ++writeoutval; break; case LDAP_SYN_TIME: case LDAP_SYN_DATE: outval = time2text( outval, syntaxid == LDAP_SYN_DATE ); ++writeoutval; break; case LDAP_SYN_LABELEDURL: if ( !notascii && ( p = strchr( outval, '$' )) != NULL ) { *p++ = '\0'; while ( ldap_utf8isspace( p )) { ++p; } s = outval; } else if ( !notascii && ( s = strchr( outval, ' ' )) != NULL ) { *s++ = '\0'; while ( ldap_utf8isspace( s )) { ++s; } p = outval; } else { s = "URL"; p = outval; } /* * at this point `s' points to the label & `p' to the URL */ if ( html ) { sprintf( buf, "<DD><A HREF=\"%s\">%s</A><BR>%s", p, s, eol ); } else { sprintf( buf, "%-*s%s%s%-*s%s%s", labelwidth, " ", s, eol, labelwidth + 2, " ",p , eol ); } (*writeproc)( writeparm, buf, strlen( buf )); break; default: sprintf( buf, dgettext(TEXT_DOMAIN, " Can't display item type %ld%s"), syntaxid, eol ); (*writeproc)( writeparm, buf, strlen( buf )); } if ( writeoutval ) { if ( html ) { sprintf( buf, "<DD>%s<BR>%s", outval, eol ); } else { sprintf( buf, "%-*s%s%s", labelwidth, " ", outval, eol ); } (*writeproc)( writeparm, buf, strlen( buf )); } } if ( freebuf ) { NSLDAPI_FREE( buf ); } return( LDAP_SUCCESS ); }
static int do_entry2text_search( LDAP *ld, char *dn, /* if NULL, use entry */ char *base, /* if NULL, no search actions */ LDAPMessage *entry, /* if NULL, use dn */ struct ldap_disptmpl* tmpllist, /* if NULL, no template used */ char **defattrs, char ***defvals, writeptype writeproc, void *writeparm, char *eol, int rdncount, /* if 0, display full DN */ unsigned long opts, char *urlprefix ) { int err, freedn, html; char *buf, **fetchattrs, **vals; LDAPMessage *ldmp; struct ldap_disptmpl *tmpl; struct timeval timeout; if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { return( LDAP_PARAM_ERROR ); } if ( dn == NULL && entry == NULLMSG ) { err = LDAP_PARAM_ERROR; LDAP_SET_LDERRNO( ld, err, NULL, NULL ); return( err ); } html = ( urlprefix != NULL ); timeout.tv_sec = SEARCH_TIMEOUT_SECS; timeout.tv_usec = 0; if (( buf = NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ )) == NULL ) { err = LDAP_NO_MEMORY; LDAP_SET_LDERRNO( ld, err, NULL, NULL ); return( err ); } freedn = 0; tmpl = NULL; if ( dn == NULL ) { if (( dn = ldap_get_dn( ld, entry )) == NULL ) { NSLDAPI_FREE( buf ); return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); } freedn = 1; } if ( tmpllist != NULL ) { ldmp = NULLMSG; if ( entry == NULL ) { char *ocattrs[2]; ocattrs[0] = OCATTRNAME; ocattrs[1] = NULL; #ifdef CLDAP if ( LDAP_IS_CLDAP( ld )) err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", ocattrs, 0, &ldmp, NULL ); else #endif /* CLDAP */ err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", ocattrs, 0, &timeout, &ldmp ); if ( err == LDAP_SUCCESS ) { entry = ldap_first_entry( ld, ldmp ); } } if ( entry != NULL ) { vals = ldap_get_values( ld, entry, OCATTRNAME ); tmpl = ldap_oc2template( vals, tmpllist ); if ( vals != NULL ) { ldap_value_free( vals ); } } if ( ldmp != NULL ) { ldap_msgfree( ldmp ); } } entry = NULL; if ( tmpl == NULL ) { fetchattrs = NULL; } else { fetchattrs = ldap_tmplattrs( tmpl, NULL, 1, LDAP_SYN_OPT_DEFER ); } #ifdef CLDAP if ( LDAP_IS_CLDAP( ld )) err = cldap_search_s( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", fetchattrs, 0, &ldmp, NULL ); else #endif /* CLDAP */ err = ldap_search_st( ld, dn, LDAP_SCOPE_BASE, "objectClass=*", fetchattrs, 0, &timeout, &ldmp ); if ( freedn ) { NSLDAPI_FREE( dn ); } if ( fetchattrs != NULL ) { ldap_value_free( fetchattrs ); } if ( err != LDAP_SUCCESS || ( entry = ldap_first_entry( ld, ldmp )) == NULL ) { NSLDAPI_FREE( buf ); return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); } err = do_entry2text( ld, buf, base, entry, tmpl, defattrs, defvals, writeproc, writeparm, eol, rdncount, opts, urlprefix ); NSLDAPI_FREE( buf ); ldap_msgfree( ldmp ); return( err ); }
static int do_entry2text( LDAP *ld, char *buf, /* NULL for use-internal */ char *base, /* used for search actions */ LDAPMessage *entry, struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals, writeptype writeproc, void *writeparm, char *eol, int rdncount, unsigned long opts, char *urlprefix /* if non-NULL, do HTML */ ) { int i, err, html, show, labelwidth; int freebuf, freevals; char *dn, **vals; struct ldap_tmplitem *rowp, *colp; if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { return( LDAP_PARAM_ERROR ); } if ( writeproc == NULL || !NSLDAPI_VALID_LDAPMESSAGE_ENTRY_POINTER( entry )) { err = LDAP_PARAM_ERROR; LDAP_SET_LDERRNO( ld, err, NULL, NULL ); return( err ); } if (( dn = ldap_get_dn( ld, entry )) == NULL ) { return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); } if ( buf == NULL ) { if (( buf = NSLDAPI_MALLOC( LDAP_DTMPL_BUFSIZ )) == NULL ) { err = LDAP_NO_MEMORY; LDAP_SET_LDERRNO( ld, err, NULL, NULL ); NSLDAPI_FREE( dn ); return( err ); } freebuf = 1; } else { freebuf = 0; } html = ( urlprefix != NULL ); if ( html ) { /* * add HTML intro. and title */ if (!(( opts & LDAP_DISP_OPT_HTMLBODYONLY ) != 0 )) { sprintf( buf, "<HTML>%s<HEAD>%s<TITLE>%s%s - ", eol, eol, eol, ( tmpl == NULL ) ? "Entry" : tmpl->dt_name ); (*writeproc)( writeparm, buf, strlen( buf )); output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL ); sprintf( buf, "%s</TITLE>%s</HEAD>%s<BODY>%s<H3>%s - ", eol, eol, eol, eol, ( tmpl == NULL ) ? "Entry" : tmpl->dt_name ); (*writeproc)( writeparm, buf, strlen( buf )); output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL ); sprintf( buf, "</H3>%s", eol ); (*writeproc)( writeparm, buf, strlen( buf )); } if (( opts & LDAP_DISP_OPT_NONLEAF ) != 0 && ( vals = ldap_explode_dn( dn, 0 )) != NULL ) { char *untagged; /* * add "Move Up" link */ sprintf( buf, "<A HREF=\"%s", urlprefix ); for ( i = 1; vals[ i ] != NULL; ++i ) { if ( i > 1 ) { strcat_escaped( buf, ", " ); } strcat_escaped( buf, vals[ i ] ); } if ( vals[ 1 ] != NULL ) { untagged = strchr( vals[ 1 ], '=' ); } else { untagged = "=The World"; } sprintf( buf + strlen( buf ), "%s\">Move Up To <EM>%s</EM></A>%s<BR>", ( vals[ 1 ] == NULL ) ? "??one" : "", ( untagged != NULL ) ? untagged + 1 : vals[ 1 ], eol ); (*writeproc)( writeparm, buf, strlen( buf )); /* * add "Browse" link */ untagged = strchr( vals[ 0 ], '=' ); sprintf( buf, "<A HREF=\"%s", urlprefix ); strcat_escaped( buf, dn ); sprintf( buf + strlen( buf ), "??one?(!(objectClass=dsa))\">Browse Below <EM>%s</EM></A>%s%s", ( untagged != NULL ) ? untagged + 1 : vals[ 0 ], eol, eol ); (*writeproc)( writeparm, buf, strlen( buf )); ldap_value_free( vals ); } (*writeproc)( writeparm, "<HR>", 4 ); /* horizontal rule */ } else { (*writeproc)( writeparm, "\"", 1 ); output_dn( buf, dn, 0, rdncount, writeproc, writeparm, "", NULL ); sprintf( buf, "\"%s", eol ); (*writeproc)( writeparm, buf, strlen( buf )); } if ( tmpl != NULL && ( opts & LDAP_DISP_OPT_AUTOLABELWIDTH ) != 0 ) { labelwidth = max_label_len( tmpl ) + 3; } else { labelwidth = DEF_LABEL_WIDTH;; } err = LDAP_SUCCESS; if ( tmpl == NULL ) { BerElement *ber; char *attr; ber = NULL; for ( attr = ldap_first_attribute( ld, entry, &ber ); NONFATAL_LDAP_ERR( err ) && attr != NULL; attr = ldap_next_attribute( ld, entry, ber )) { if (( vals = ldap_get_values( ld, entry, attr )) == NULL ) { freevals = 0; if ( defattrs != NULL ) { for ( i = 0; defattrs[ i ] != NULL; ++i ) { if ( strcasecmp( attr, defattrs[ i ] ) == 0 ) { break; } } if ( defattrs[ i ] != NULL ) { vals = defvals[ i ]; } } } else { freevals = 1; } if ( islower( *attr )) { /* cosmetic -- upcase attr. name */ *attr = toupper( *attr ); } err = do_vals2text( ld, buf, vals, attr, labelwidth, LDAP_SYN_CASEIGNORESTR, writeproc, writeparm, eol, rdncount, urlprefix ); if ( freevals ) { ldap_value_free( vals ); } } if ( ber == NULL ) { ber_free( ber, 0 ); } /* * XXX check for errors in ldap_first_attribute/ldap_next_attribute * here (but what should we do if there was one?) */ } else { for ( rowp = ldap_first_tmplrow( tmpl ); NONFATAL_LDAP_ERR( err ) && rowp != NULLTMPLITEM; rowp = ldap_next_tmplrow( tmpl, rowp )) { for ( colp = ldap_first_tmplcol( tmpl, rowp ); colp != NULLTMPLITEM; colp = ldap_next_tmplcol( tmpl, rowp, colp )) { vals = NULL; if ( colp->ti_attrname == NULL || ( vals = ldap_get_values( ld, entry, colp->ti_attrname )) == NULL ) { freevals = 0; if ( !LDAP_IS_TMPLITEM_OPTION_SET( colp, LDAP_DITEM_OPT_HIDEIFEMPTY ) && defattrs != NULL && colp->ti_attrname != NULL ) { for ( i = 0; defattrs[ i ] != NULL; ++i ) { if ( strcasecmp( colp->ti_attrname, defattrs[ i ] ) == 0 ) { break; } } if ( defattrs[ i ] != NULL ) { vals = defvals[ i ]; } } } else { freevals = 1; if ( LDAP_IS_TMPLITEM_OPTION_SET( colp, LDAP_DITEM_OPT_SORTVALUES ) && vals[ 0 ] != NULL && vals[ 1 ] != NULL ) { ldap_sort_values(ld, vals, ldap_sort_strcasecmp); } } /* * don't bother even calling do_vals2text() if no values * or boolean with value false and "hide if false" option set */ show = ( vals != NULL && vals[ 0 ] != NULL ); if ( show && LDAP_GET_SYN_TYPE( colp->ti_syntaxid ) == LDAP_SYN_TYPE_BOOLEAN && LDAP_IS_TMPLITEM_OPTION_SET( colp, LDAP_DITEM_OPT_HIDEIFFALSE ) && toupper( vals[ 0 ][ 0 ] ) != 'T' ) { show = 0; } if ( colp->ti_syntaxid == LDAP_SYN_SEARCHACTION ) { if (( opts & LDAP_DISP_OPT_DOSEARCHACTIONS ) != 0 ) { if ( colp->ti_attrname == NULL || ( show && toupper( vals[ 0 ][ 0 ] ) == 'T' )) { err = searchaction( ld, buf, base, entry, dn, colp, labelwidth, rdncount, writeproc, writeparm, eol, urlprefix ); } } show = 0; } if ( show ) { err = do_vals2text( ld, buf, vals, colp->ti_label, labelwidth, colp->ti_syntaxid, writeproc, writeparm, eol, rdncount, urlprefix ); } if ( freevals ) { ldap_value_free( vals ); } } } } if ( html && !(( opts & LDAP_DISP_OPT_HTMLBODYONLY ) != 0 )) { sprintf( buf, "</BODY>%s</HTML>%s", eol, eol ); (*writeproc)( writeparm, buf, strlen( buf )); } NSLDAPI_FREE( dn ); if ( freebuf ) { NSLDAPI_FREE( buf ); } return( err ); }
/* * simple_bindifnot_s() is like ldap_simple_bind_s() except that it only does * a bind if the default connection is not currently bound. * If a successful bind using the same DN has already taken place we just * return LDAP_SUCCESS without conversing with the server at all. */ static int simple_bindifnot_s( LDAP *ld, const char *dn, const char *passwd ) { int msgid, rc; LDAPMessage *result; char *binddn; LDAPDebug( LDAP_DEBUG_TRACE, "simple_bindifnot_s\n", 0, 0, 0 ); if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { return( LDAP_PARAM_ERROR ); } if ( dn == NULL ) { dn = ""; /* to make comparisons simpler */ } /* * if we are already bound using the same DN, just return LDAP_SUCCESS. */ if ( NULL != ( binddn = nsldapi_get_binddn( ld )) && 0 == strcmp( dn, binddn )) { rc = LDAP_SUCCESS; LDAP_SET_LDERRNO( ld, rc, NULL, NULL ); return rc; } /* * if the default connection has been lost and is now marked dead, * dispose of the default connection so it will get re-established. * * if not, clear the bind DN and status to ensure that we don't * report the wrong bind DN to a different thread while waiting * for our bind result to return from the server. */ LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); if ( NULL != ld->ld_defconn ) { if ( LDAP_CONNST_DEAD == ld->ld_defconn->lconn_status ) { nsldapi_free_connection( ld, ld->ld_defconn, NULL, NULL, 1, 0 ); ld->ld_defconn = NULL; } else if ( ld->ld_defconn->lconn_binddn != NULL ) { NSLDAPI_FREE( ld->ld_defconn->lconn_binddn ); ld->ld_defconn->lconn_binddn = NULL; ld->ld_defconn->lconn_bound = 0; } } LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); /* * finally, bind (this will open a new connection if necessary) * * do everything under the protection of the result lock to * ensure that only one thread will be in this code at a time. * XXXmcs: we should use a condition variable instead? */ LDAP_MUTEX_LOCK( ld, LDAP_RESULT_LOCK ); if ( (msgid = simple_bind_nolock( ld, dn, passwd, 0 )) == -1 ) { rc = LDAP_GET_LDERRNO( ld, NULL, NULL ); goto unlock_and_return; } /* * Note that at this point the bind request is on its way to the * server and at any time now we will either be bound as the new * DN (if the bind succeeded) or we will be bound as anonymous (if * the bind failed). */ /* * Wait for the bind result. Code inside result.c:read1msg() * takes care of setting the connection's bind DN and status. */ if ( nsldapi_result_nolock( ld, msgid, 1, 0, (struct timeval *) 0, &result ) == -1 ) { rc = LDAP_GET_LDERRNO( ld, NULL, NULL ); goto unlock_and_return; } rc = ldap_result2error( ld, result, 1 ); unlock_and_return: LDAP_MUTEX_UNLOCK( ld, LDAP_RESULT_LOCK ); return( rc ); }