/* FIXME: this function is called only by ldap_free_connection(), * which, most of the times, is called with ld_req_mutex locked */ int ldap_send_unbind( LDAP *ld, Sockbuf *sb, LDAPControl **sctrls, LDAPControl **cctrls ) { BerElement *ber; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_send_unbind\n", 0, 0, 0 ); #ifdef LDAP_CONNECTIONLESS if (LDAP_IS_UDP(ld)) return LDAP_SUCCESS; #endif /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( ld->ld_errno ); } LDAP_NEXT_MSGID(ld, id); /* fill it in */ if ( ber_printf( ber, "{itn" /*}*/, id, LDAP_REQ_UNBIND ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}", LDAP_REQ_UNBIND ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } ld->ld_errno = LDAP_SUCCESS; /* send the message */ if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) == -1 ) { ld->ld_errno = LDAP_SERVER_DOWN; } return( ld->ld_errno ); }
/* * ldap_kerberos_bind1 - initiate a bind to the ldap server using * kerberos authentication. The dn is supplied. It is assumed the user * already has a valid ticket granting ticket. The msgid of the * request is returned on success (suitable for passing to ldap_result()), * -1 is returned if there's trouble. * * Example: * ldap_kerberos_bind1( ld, "cn=manager, o=university of michigan, c=us" ) */ int ldap_kerberos_bind1( LDAP *ld, LDAP_CONST char *dn ) { BerElement *ber; char *cred; int rc; ber_len_t credlen; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_kerberos_bind1\n", 0, 0, 0 ); if( ld->ld_version > LDAP_VERSION2 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return -1; } if ( dn == NULL ) dn = ""; if ( (cred = ldap_get_kerberosv4_credentials( ld, dn, "ldapserver", &credlen )) == NULL ) { return( -1 ); /* ld_errno should already be set */ } /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { LDAP_FREE( cred ); return( -1 ); } LDAP_NEXT_MSGID( ld, id ); /* fill it in */ rc = ber_printf( ber, "{it{istoN}N}", id, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_KRBV41, cred, credlen ); if ( rc == -1 ) { LDAP_FREE( cred ); ber_free( ber, 1 ); ld->ld_errno = LDAP_ENCODING_ERROR; return( -1 ); } LDAP_FREE( cred ); /* send the message */ return ( ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber, id )); }
BerElement * ldap_build_compare_req( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *attr, struct berval *bvalue, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( NULL ); } LDAP_NEXT_MSGID(ld, *msgidp); rc = ber_printf( ber, "{it{s{sON}N}", /* '}' */ *msgidp, LDAP_REQ_COMPARE, dn, attr, bvalue ); if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return( NULL ); } if( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } return( ber ); }
/* * XXX merging of errors in this routine needs to be improved * Protected by res_mutex, conn_mutex and req_mutex (try_read1msg) */ int ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int sref, int *hadrefp ) { int rc, count, id; unsigned len; char *p, *ref, *unfollowed; LDAPRequest *origreq; LDAPURLDesc *srv; BerElement *ber; LDAPreqinfo rinfo; LDAPConn *lc; LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); Debug( LDAP_DEBUG_TRACE, "ldap_chase_referrals\n", 0, 0, 0 ); ld->ld_errno = LDAP_SUCCESS; /* optimistic */ *hadrefp = 0; if ( *errstrp == NULL ) { return( 0 ); } len = strlen( *errstrp ); for ( p = *errstrp; len >= LDAP_REF_STR_LEN; ++p, --len ) { if ( strncasecmp( p, LDAP_REF_STR, LDAP_REF_STR_LEN ) == 0 ) { *p = '\0'; p += LDAP_REF_STR_LEN; break; } } if ( len < LDAP_REF_STR_LEN ) { return( 0 ); } if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) { Debug( LDAP_DEBUG_ANY, "more than %d referral hops (dropping)\n", ld->ld_refhoplimit, 0, 0 ); /* XXX report as error in ld->ld_errno? */ return( 0 ); } /* find original request */ for ( origreq = lr; origreq->lr_parent != NULL; origreq = origreq->lr_parent ) { /* empty */; } unfollowed = NULL; rc = count = 0; /* parse out & follow referrals */ for ( ref = p; rc == 0 && ref != NULL; ref = p ) { p = strchr( ref, '\n' ); if ( p != NULL ) { *p++ = '\0'; } rc = ldap_url_parse_ext( ref, &srv, LDAP_PVT_URL_PARSE_NOEMPTY_DN ); if ( rc != LDAP_URL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "ignoring %s referral <%s>\n", ref, rc == LDAP_URL_ERR_BADSCHEME ? "unknown" : "incorrect", 0 ); rc = ldap_append_referral( ld, &unfollowed, ref ); *hadrefp = 1; continue; } Debug( LDAP_DEBUG_TRACE, "chasing LDAP referral: <%s>\n", ref, 0, 0 ); *hadrefp = 1; /* See if we've already been here */ if (( lc = find_connection( ld, srv, 1 )) != NULL ) { LDAPRequest *lp; int looped = 0; ber_len_t len = srv->lud_dn ? strlen( srv->lud_dn ) : 0; for ( lp = lr; lp; lp = lp->lr_parent ) { if ( lp->lr_conn == lc && len == lp->lr_dn.bv_len ) { if ( len && strncmp( srv->lud_dn, lp->lr_dn.bv_val, len ) ) continue; looped = 1; break; } } if ( looped ) { ldap_free_urllist( srv ); ld->ld_errno = LDAP_CLIENT_LOOP; rc = -1; continue; } } LDAP_NEXT_MSGID( ld, id ); ber = re_encode_request( ld, origreq->lr_ber, id, sref, srv, &rinfo.ri_request ); if ( ber == NULL ) { return -1 ; } /* copy the complete referral for rebind process */ rinfo.ri_url = LDAP_STRDUP( ref ); rinfo.ri_msgid = origreq->lr_origid; rc = ldap_send_server_request( ld, ber, id, lr, &srv, NULL, &rinfo, 0, 1 ); LDAP_FREE( rinfo.ri_url ); if( rc >= 0 ) { ++count; } else { Debug( LDAP_DEBUG_ANY, "Unable to chase referral \"%s\" (%d: %s)\n", ref, ld->ld_errno, ldap_err2string( ld->ld_errno ) ); rc = ldap_append_referral( ld, &unfollowed, ref ); } ldap_free_urllist(srv); } LDAP_FREE( *errstrp ); *errstrp = unfollowed; return(( rc == 0 ) ? count : rc ); }
/* * Chase v3 referrals * * Parameters: * (IN) ld = LDAP connection handle * (IN) lr = LDAP Request structure * (IN) refs = array of pointers to referral strings that we will chase * The array will be free'd by this function when no longer needed * (IN) sref != 0 if following search reference * (OUT) errstrp = Place to return a string of referrals which could not be followed * (OUT) hadrefp = 1 if sucessfully followed referral * * Return value - number of referrals followed * * Protected by res_mutex, conn_mutex and req_mutex (try_read1msg) */ int ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr, char **refs, int sref, char **errstrp, int *hadrefp ) { char *unfollowed; int unfollowedcnt = 0; LDAPRequest *origreq; LDAPURLDesc *srv = NULL; BerElement *ber; char **refarray = NULL; LDAPConn *lc; int rc, count, i, j, id; LDAPreqinfo rinfo; LDAP_NEXTREF_PROC *nextref_proc = ld->ld_nextref_proc ? ld->ld_nextref_proc : ldap_int_nextref; LDAP_ASSERT_MUTEX_OWNER( &ld->ld_res_mutex ); LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals\n", 0, 0, 0 ); ld->ld_errno = LDAP_SUCCESS; /* optimistic */ *hadrefp = 0; unfollowed = NULL; rc = count = 0; /* If no referrals in array, return */ if ( (refs == NULL) || ( (refs)[0] == NULL) ) { rc = 0; goto done; } /* Check for hop limit exceeded */ if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) { Debug( LDAP_DEBUG_ANY, "more than %d referral hops (dropping)\n", ld->ld_refhoplimit, 0, 0 ); ld->ld_errno = LDAP_REFERRAL_LIMIT_EXCEEDED; rc = -1; goto done; } /* find original request */ for ( origreq = lr; origreq->lr_parent != NULL; origreq = origreq->lr_parent ) { /* empty */ ; } refarray = refs; refs = NULL; /* parse out & follow referrals */ /* NOTE: if nextref_proc == ldap_int_nextref, params is ignored */ i = -1; for ( nextref_proc( ld, &refarray, &i, ld->ld_nextref_params ); i != -1; nextref_proc( ld, &refarray, &i, ld->ld_nextref_params ) ) { /* Parse the referral URL */ rc = ldap_url_parse_ext( refarray[i], &srv, LDAP_PVT_URL_PARSE_NOEMPTY_DN ); if ( rc != LDAP_URL_SUCCESS ) { /* ldap_url_parse_ext() returns LDAP_URL_* errors * which do not map on API errors */ ld->ld_errno = LDAP_PARAM_ERROR; rc = -1; goto done; } if( srv->lud_crit_exts ) { int ok = 0; #ifdef HAVE_TLS /* If StartTLS is the only critical ext, OK. */ if ( find_tls_ext( srv ) == 2 && srv->lud_crit_exts == 1 ) ok = 1; #endif if ( !ok ) { /* we do not support any other extensions */ ld->ld_errno = LDAP_NOT_SUPPORTED; rc = -1; goto done; } } /* check connection for re-bind in progress */ if (( lc = find_connection( ld, srv, 1 )) != NULL ) { /* See if we've already requested this DN with this conn */ LDAPRequest *lp; int looped = 0; ber_len_t len = srv->lud_dn ? strlen( srv->lud_dn ) : 0; for ( lp = origreq; lp; ) { if ( lp->lr_conn == lc && len == lp->lr_dn.bv_len && len && strncmp( srv->lud_dn, lp->lr_dn.bv_val, len ) == 0 ) { looped = 1; break; } if ( lp == origreq ) { lp = lp->lr_child; } else { lp = lp->lr_refnext; } } if ( looped ) { ldap_free_urllist( srv ); srv = NULL; ld->ld_errno = LDAP_CLIENT_LOOP; rc = -1; continue; } if ( lc->lconn_rebind_inprogress ) { /* We are already chasing a referral or search reference and a * bind on that connection is in progress. We must queue * referrals on that connection, so we don't get a request * going out before the bind operation completes. This happens * if two search references come in one behind the other * for the same server with different contexts. */ Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referrals: queue referral \"%s\"\n", refarray[i], 0, 0); if( lc->lconn_rebind_queue == NULL ) { /* Create a referral list */ lc->lconn_rebind_queue = (char ***) LDAP_MALLOC( sizeof(void *) * 2); if( lc->lconn_rebind_queue == NULL) { ld->ld_errno = LDAP_NO_MEMORY; rc = -1; goto done; } lc->lconn_rebind_queue[0] = refarray; lc->lconn_rebind_queue[1] = NULL; refarray = NULL; } else { /* Count how many referral arrays we already have */ for( j = 0; lc->lconn_rebind_queue[j] != NULL; j++) { /* empty */; } /* Add the new referral to the list */ lc->lconn_rebind_queue = (char ***) LDAP_REALLOC( lc->lconn_rebind_queue, sizeof(void *) * (j + 2)); if( lc->lconn_rebind_queue == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; rc = -1; goto done; } lc->lconn_rebind_queue[j] = refarray; lc->lconn_rebind_queue[j+1] = NULL; refarray = NULL; } /* We have queued the referral/reference, now just return */ rc = 0; *hadrefp = 1; count = 1; /* Pretend we already followed referral */ goto done; } } /* Re-encode the request with the new starting point of the search. * Note: In the future we also need to replace the filter if one * was provided with the search reference */ /* For references we don't want old dn if new dn empty */ if ( sref && srv->lud_dn == NULL ) { srv->lud_dn = LDAP_STRDUP( "" ); } LDAP_NEXT_MSGID( ld, id ); ber = re_encode_request( ld, origreq->lr_ber, id, sref, srv, &rinfo.ri_request ); if( ber == NULL ) { ld->ld_errno = LDAP_ENCODING_ERROR; rc = -1; goto done; } Debug( LDAP_DEBUG_TRACE, "ldap_chase_v3referral: msgid %d, url \"%s\"\n", lr->lr_msgid, refarray[i], 0); /* Send the new request to the server - may require a bind */ rinfo.ri_msgid = origreq->lr_origid; rinfo.ri_url = refarray[i]; rc = ldap_send_server_request( ld, ber, id, origreq, &srv, NULL, &rinfo, 0, 1 ); if ( rc < 0 ) { /* Failure, try next referral in the list */ Debug( LDAP_DEBUG_ANY, "Unable to chase referral \"%s\" (%d: %s)\n", refarray[i], ld->ld_errno, ldap_err2string( ld->ld_errno ) ); unfollowedcnt += ldap_append_referral( ld, &unfollowed, refarray[i] ); ldap_free_urllist( srv ); srv = NULL; ld->ld_errno = LDAP_REFERRAL; } else { /* Success, no need to try this referral list further */ rc = 0; ++count; *hadrefp = 1; /* check if there is a queue of referrals that came in during bind */ if ( lc == NULL) { lc = find_connection( ld, srv, 1 ); if ( lc == NULL ) { ld->ld_errno = LDAP_OPERATIONS_ERROR; rc = -1; LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); goto done; } } if ( lc->lconn_rebind_queue != NULL ) { /* Release resources of previous list */ LDAP_VFREE( refarray ); refarray = NULL; ldap_free_urllist( srv ); srv = NULL; /* Pull entries off end of queue so list always null terminated */ for( j = 0; lc->lconn_rebind_queue[j] != NULL; j++ ) ; refarray = lc->lconn_rebind_queue[j - 1]; lc->lconn_rebind_queue[j-1] = NULL; /* we pulled off last entry from queue, free queue */ if ( j == 1 ) { LDAP_FREE( lc->lconn_rebind_queue ); lc->lconn_rebind_queue = NULL; } /* restart the loop the with new referral list */ i = -1; continue; } break; /* referral followed, break out of for loop */ } } /* end for loop */ done: LDAP_VFREE( refarray ); ldap_free_urllist( srv ); LDAP_FREE( *errstrp ); if( rc == 0 ) { *errstrp = NULL; LDAP_FREE( unfollowed ); return count; } else { *errstrp = unfollowed; return rc; } }
int ldap_rename( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, LDAP_CONST char *newSuperior, int deleteoldrdn, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_rename\n", 0, 0, 0 ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( LDAP_NO_MEMORY ); } LDAP_NEXT_MSGID( ld, id ); if( newSuperior != NULL ) { /* must be version 3 (or greater) */ if ( ld->ld_version < LDAP_VERSION3 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; ber_free( ber, 1 ); return( ld->ld_errno ); } rc = ber_printf( ber, "{it{ssbtsN}", /* '}' */ id, LDAP_REQ_MODDN, dn, newrdn, (ber_int_t) deleteoldrdn, LDAP_TAG_NEWSUPERIOR, newSuperior ); } else { rc = ber_printf( ber, "{it{ssbN}", /* '}' */ id, LDAP_REQ_MODDN, dn, newrdn, (ber_int_t) deleteoldrdn ); } if ( rc < 0 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } rc = ber_printf( ber, /*{*/ "N}" ); if ( rc < 0 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODRDN, dn, ber, id ); if( *msgidp < 0 ) { return( ld->ld_errno ); } return LDAP_SUCCESS; }
/* * ldap_modify_ext - initiate an ldap extended modify operation. * * Parameters: * * ld LDAP descriptor * dn DN of the object to modify * mods List of modifications to make. This is null-terminated * array of struct ldapmod's, specifying the modifications * to perform. * sctrls Server Controls * cctrls Client Controls * msgidp Message ID pointer * * Example: * LDAPMod *mods[] = { * { LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } }, * { LDAP_MOD_REPLACE, "sn", { "babs jensen", "babs", 0 } }, * { LDAP_MOD_DELETE, "ou", 0 }, * { LDAP_MOD_INCREMENT, "uidNumber, { "1", 0 } } * 0 * } * rc= ldap_modify_ext( ld, dn, mods, sctrls, cctrls, &msgid ); */ int ldap_modify_ext( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int i, rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( LDAP_NO_MEMORY ); } LDAP_NEXT_MSGID( ld, id ); rc = ber_printf( ber, "{it{s{" /*}}}*/, id, LDAP_REQ_MODIFY, dn ); if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* allow mods to be NULL ("touch") */ if ( mods ) { /* 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]N}N}", (ber_int_t) ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ), mods[i]->mod_type, mods[i]->mod_bvalues ); } else { rc = ber_printf( ber, "{e{s[v]N}N}", (ber_int_t) mods[i]->mod_op, mods[i]->mod_type, mods[i]->mod_values ); } if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } } } if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber, id ); return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS ); }
int ldap_extended_operation( LDAP *ld, LDAP_CONST char *reqoid, struct berval *reqdata, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_extended_operation\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( reqoid != NULL && *reqoid != '\0' ); assert( msgidp != NULL ); /* must be version 3 (or greater) */ if ( ld->ld_version < LDAP_VERSION3 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return( ld->ld_errno ); } /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return( ld->ld_errno ); } LDAP_NEXT_MSGID( ld, id ); if ( reqdata != NULL ) { rc = ber_printf( ber, "{it{tstON}", /* '}' */ id, LDAP_REQ_EXTENDED, LDAP_TAG_EXOP_REQ_OID, reqoid, LDAP_TAG_EXOP_REQ_VALUE, reqdata ); } else { rc = ber_printf( ber, "{it{tsN}", /* '}' */ id, LDAP_REQ_EXTENDED, LDAP_TAG_EXOP_REQ_OID, reqoid ); } if( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( ld->ld_errno ); } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_EXTENDED, NULL, ber, id ); return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS ); }
BerElement * ldap_build_search_req( LDAP *ld, LDAP_CONST char *base, ber_int_t scope, LDAP_CONST char *filter, char **attrs, ber_int_t attrsonly, LDAPControl **sctrls, LDAPControl **cctrls, ber_int_t timelimit, ber_int_t sizelimit, ber_int_t deref, ber_int_t *idp) { BerElement *ber; int err; /* * Create the search request. It looks like this: * SearchRequest := [APPLICATION 3] SEQUENCE { * baseObject DistinguishedName, * scope ENUMERATED { * baseObject (0), * singleLevel (1), * wholeSubtree (2) * }, * derefAliases ENUMERATED { * neverDerefaliases (0), * derefInSearching (1), * derefFindingBaseObj (2), * alwaysDerefAliases (3) * }, * sizelimit INTEGER (0 .. 65535), * timelimit INTEGER (0 .. 65535), * attrsOnly BOOLEAN, * filter Filter, * attributes SEQUENCE OF AttributeType * } * wrapped in an ldap message. */ /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( NULL ); } if ( base == NULL ) { /* no base provided, use session default base */ base = ld->ld_options.ldo_defbase; if ( base == NULL ) { /* no session default base, use top */ base = ""; } } LDAP_NEXT_MSGID( ld, *idp ); #ifdef LDAP_CONNECTIONLESS if ( LDAP_IS_UDP(ld) ) { struct sockaddr sa = {0}; /* dummy, filled with ldo_peer in request.c */ err = ber_write( ber, &sa, sizeof( sa ), 0 ); } if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) { char *dn = ld->ld_options.ldo_cldapdn; if (!dn) dn = ""; err = ber_printf( ber, "{ist{seeiib", *idp, dn, LDAP_REQ_SEARCH, base, (ber_int_t) scope, (deref < 0) ? ld->ld_deref : deref, (sizelimit < 0) ? ld->ld_sizelimit : sizelimit, (timelimit < 0) ? ld->ld_timelimit : timelimit, attrsonly ); } else #endif { err = ber_printf( ber, "{it{seeiib", *idp, LDAP_REQ_SEARCH, base, (ber_int_t) scope, (deref < 0) ? ld->ld_deref : deref, (sizelimit < 0) ? ld->ld_sizelimit : sizelimit, (timelimit < 0) ? ld->ld_timelimit : timelimit, attrsonly ); } if ( err == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } if( filter == NULL ) { filter = "(objectclass=*)"; } err = ldap_pvt_put_filter( ber, filter ); if ( err == -1 ) { ld->ld_errno = LDAP_FILTER_ERROR; ber_free( ber, 1 ); return( NULL ); } #ifdef LDAP_DEBUG if ( ldap_debug & LDAP_DEBUG_ARGS ) { char buf[ BUFSIZ ], *ptr = " *"; if ( attrs != NULL ) { int i, len, rest = sizeof( buf ); for ( i = 0; attrs[ i ] != NULL && rest > 0; i++ ) { ptr = &buf[ sizeof( buf ) - rest ]; len = snprintf( ptr, rest, " %s", attrs[ i ] ); rest -= (len >= 0 ? len : (int) sizeof( buf )); } if ( rest <= 0 ) { AC_MEMCPY( &buf[ sizeof( buf ) - STRLENOF( "...(truncated)" ) - 1 ], "...(truncated)", STRLENOF( "...(truncated)" ) + 1 ); } ptr = buf; } Debug( LDAP_DEBUG_ARGS, "ldap_build_search_req ATTRS:%s\n", ptr, 0,0 ); } #endif /* LDAP_DEBUG */ if ( ber_printf( ber, /*{*/ "{v}N}", attrs ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return( NULL ); } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } return( ber ); }
/* * ldap_add_ext - initiate an ldap extended add operation. Parameters: * * ld LDAP descriptor * dn DN of the entry to add * mods List of attributes for the entry. This is a null- * terminated array of pointers to LDAPMod structures. * only the type and values in the structures need be * filled in. * sctrl Server Controls * cctrl Client Controls * msgidp Message ID pointer * * Example: * LDAPMod *attrs[] = { * { 0, "cn", { "babs jensen", "babs", 0 } }, * { 0, "sn", { "jensen", 0 } }, * { 0, "objectClass", { "person", 0 } }, * 0 * } * rc = ldap_add_ext( ld, dn, attrs, NULL, NULL, &msgid ); */ int ldap_add_ext( LDAP *ld, LDAP_CONST char *dn, LDAPMod **attrs, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int i, rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_add_ext\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( dn != NULL ); assert( msgidp != NULL ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } LDAP_NEXT_MSGID(ld, id); rc = ber_printf( ber, "{it{s{", /* '}}}' */ id, LDAP_REQ_ADD, dn ); if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } /* allow attrs to be NULL ("touch"; should fail...) */ if ( attrs ) { /* for each attribute in the entry... */ for ( i = 0; attrs[i] != NULL; i++ ) { if ( ( attrs[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) { int j; if ( attrs[i]->mod_bvalues == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } for ( j = 0; attrs[i]->mod_bvalues[ j ] != NULL; j++ ) { if ( attrs[i]->mod_bvalues[ j ]->bv_val == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } } rc = ber_printf( ber, "{s[V]N}", attrs[i]->mod_type, attrs[i]->mod_bvalues ); } else { if ( attrs[i]->mod_values == NULL ) { ld->ld_errno = LDAP_PARAM_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } rc = ber_printf( ber, "{s[v]N}", attrs[i]->mod_type, attrs[i]->mod_values ); } if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } } } if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_ADD, dn, ber, id ); if(*msgidp < 0) return ld->ld_errno; return LDAP_SUCCESS; }
static int do_abandon( LDAP *ld, ber_int_t origid, ber_int_t msgid, LDAPControl **sctrls, int sendabandon ) { BerElement *ber; int i, err; Sockbuf *sb; LDAPRequest *lr; Debug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n", origid, msgid, 0 ); /* find the request that we are abandoning */ start_again: ; lr = ld->ld_requests; while ( lr != NULL ) { /* this message */ if ( lr->lr_msgid == msgid ) { break; } /* child: abandon it */ if ( lr->lr_origid == msgid && !lr->lr_abandoned ) { (void)do_abandon( ld, lr->lr_origid, lr->lr_msgid, sctrls, sendabandon ); /* restart, as lr may now be dangling... */ goto start_again; } lr = lr->lr_next; } if ( lr != NULL ) { if ( origid == msgid && lr->lr_parent != NULL ) { /* don't let caller abandon child requests! */ ld->ld_errno = LDAP_PARAM_ERROR; return( LDAP_PARAM_ERROR ); } if ( lr->lr_status != LDAP_REQST_INPROGRESS ) { /* no need to send abandon message */ sendabandon = 0; } } /* ldap_msgdelete locks the res_mutex. Give up the req_mutex * while we're in there. */ LDAP_MUTEX_UNLOCK( &ld->ld_req_mutex ); err = ldap_msgdelete( ld, msgid ); LDAP_MUTEX_LOCK( &ld->ld_req_mutex ); if ( err == 0 ) { ld->ld_errno = LDAP_SUCCESS; return LDAP_SUCCESS; } /* fetch again the request that we are abandoning */ if ( lr != NULL ) { for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) { /* this message */ if ( lr->lr_msgid == msgid ) { break; } } } err = 0; if ( sendabandon ) { if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) { /* not connected */ err = -1; ld->ld_errno = LDAP_SERVER_DOWN; } else if ( ( ber = ldap_alloc_ber_with_options( ld ) ) == NULL ) { /* BER element allocation failed */ err = -1; ld->ld_errno = LDAP_NO_MEMORY; } else { /* * We already have the mutex in LDAP_R_COMPILE, so * don't try to get it again. * LDAP_NEXT_MSGID(ld, i); */ LDAP_NEXT_MSGID(ld, i); #ifdef LDAP_CONNECTIONLESS if ( LDAP_IS_UDP(ld) ) { struct sockaddr sa = {0}; /* dummy, filled with ldo_peer in request.c */ err = ber_write( ber, (char *) &sa, sizeof(sa), 0 ); } if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2 ) { char *dn; LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex ); dn = ld->ld_options.ldo_cldapdn; if (!dn) dn = ""; err = ber_printf( ber, "{isti", /* '}' */ i, dn, LDAP_REQ_ABANDON, msgid ); LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex ); } else #endif { /* create a message to send */ err = ber_printf( ber, "{iti", /* '}' */ i, LDAP_REQ_ABANDON, msgid ); } if ( err == -1 ) { /* encoding error */ ld->ld_errno = LDAP_ENCODING_ERROR; } else { /* Put Server Controls */ if ( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { err = -1; } else { /* close '{' */ err = ber_printf( ber, /*{*/ "N}" ); if ( err == -1 ) { /* encoding error */ ld->ld_errno = LDAP_ENCODING_ERROR; } } } if ( err == -1 ) { ber_free( ber, 1 ); } else { /* send the message */ if ( lr != NULL ) { assert( lr->lr_conn != NULL ); sb = lr->lr_conn->lconn_sb; } else { sb = ld->ld_sb; } if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) != 0 ) { ld->ld_errno = LDAP_SERVER_DOWN; err = -1; } else { err = 0; } } } } if ( lr != NULL ) { if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) { LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); ldap_free_connection( ld, lr->lr_conn, 0, 1 ); LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); } if ( origid == msgid ) { ldap_free_request( ld, lr ); } else { lr->lr_abandoned = 1; } } LDAP_MUTEX_LOCK( &ld->ld_abandon_mutex ); /* use bisection */ i = 0; if ( ld->ld_nabandoned == 0 || ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &i ) == 0 ) { ldap_int_bisect_insert( &ld->ld_abandoned, &ld->ld_nabandoned, msgid, i ); } if ( err != -1 ) { ld->ld_errno = LDAP_SUCCESS; } LDAP_MUTEX_UNLOCK( &ld->ld_abandon_mutex ); return( ld->ld_errno ); }
int ldap_sasl_bind( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *mechanism, struct berval *cred, LDAPControl **sctrls, LDAPControl **cctrls, int *msgidp ) { BerElement *ber; int rc; ber_int_t id; Debug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 ); assert( ld != NULL ); assert( LDAP_VALID( ld ) ); assert( msgidp != NULL ); /* check client controls */ rc = ldap_int_client_controls( ld, cctrls ); if( rc != LDAP_SUCCESS ) return rc; if( mechanism == LDAP_SASL_SIMPLE ) { if( dn == NULL && cred != NULL && cred->bv_len ) { /* use default binddn */ dn = ld->ld_defbinddn; } } else if( ld->ld_version < LDAP_VERSION3 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return ld->ld_errno; } if ( dn == NULL ) { dn = ""; } /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return ld->ld_errno; } assert( LBER_VALID( ber ) ); LDAP_NEXT_MSGID( ld, id ); if( mechanism == LDAP_SASL_SIMPLE ) { /* simple bind */ rc = ber_printf( ber, "{it{istON}" /*}*/, id, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SIMPLE, cred ); } else if ( cred == NULL || cred->bv_val == NULL ) { /* SASL bind w/o credentials */ rc = ber_printf( ber, "{it{ist{sN}N}" /*}*/, id, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SASL, mechanism ); } else { /* SASL bind w/ credentials */ rc = ber_printf( ber, "{it{ist{sON}N}" /*}*/, id, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SASL, mechanism, cred ); } if( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( -1 ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return ld->ld_errno; } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return ld->ld_errno; } /* send the message */ *msgidp = ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber, id ); if(*msgidp < 0) return ld->ld_errno; return LDAP_SUCCESS; }
BerElement * ldap_build_modify_req( LDAP *ld, LDAP_CONST char *dn, LDAPMod **mods, LDAPControl **sctrls, LDAPControl **cctrls, ber_int_t *msgidp ) { BerElement *ber; int i, rc; /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( NULL ); } LDAP_NEXT_MSGID( ld, *msgidp ); rc = ber_printf( ber, "{it{s{" /*}}}*/, *msgidp, LDAP_REQ_MODIFY, dn ); if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } /* allow mods to be NULL ("touch") */ if ( mods ) { /* 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]N}N}", (ber_int_t) ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ), mods[i]->mod_type, mods[i]->mod_bvalues ); } else { rc = ber_printf( ber, "{e{s[v]N}N}", (ber_int_t) mods[i]->mod_op, mods[i]->mod_type, mods[i]->mod_values ); } if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } } } if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return( NULL ); } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } return( ber ); }
BerElement * ldap_build_bind_req( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *mechanism, struct berval *cred, LDAPControl **sctrls, LDAPControl **cctrls, ber_int_t *msgidp ) { BerElement *ber; int rc; if( mechanism == LDAP_SASL_SIMPLE ) { if( dn == NULL && cred != NULL && cred->bv_len ) { /* use default binddn */ dn = ld->ld_defbinddn; } } else if( ld->ld_version < LDAP_VERSION3 ) { ld->ld_errno = LDAP_NOT_SUPPORTED; return( NULL ); } if ( dn == NULL ) { dn = ""; } /* create a message to send */ if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) { return( NULL ); } LDAP_NEXT_MSGID( ld, *msgidp ); if( mechanism == LDAP_SASL_SIMPLE ) { /* simple bind */ rc = ber_printf( ber, "{it{istON}" /*}*/, *msgidp, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SIMPLE, cred ); } else if ( cred == NULL || cred->bv_val == NULL ) { /* SASL bind w/o credentials */ rc = ber_printf( ber, "{it{ist{sN}N}" /*}*/, *msgidp, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SASL, mechanism ); } else { /* SASL bind w/ credentials */ rc = ber_printf( ber, "{it{ist{sON}N}" /*}*/, *msgidp, LDAP_REQ_BIND, ld->ld_version, dn, LDAP_AUTH_SASL, mechanism, cred ); } if( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } /* Put Server Controls */ if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) { ber_free( ber, 1 ); return( NULL ); } if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; ber_free( ber, 1 ); return( NULL ); } return( ber ); }