int tsps_ldap_get_userid(const char *user) { char user_filt[128]; int res; char *attrs[] = { "uidNumber", NULL }; LDAPMessage *vals = NULL; LDAPMessage *val; int uidnum = -1; snprintf(user_filt, sizeof(user_filt), "(uid=%s)", user); res = ldap_search_ext_s(ldp, server.ldap_user_base, LDAP_SCOPE_ONELEVEL, user_filt, attrs, 0, NULL, NULL, NULL, 0, &vals); if (res != LDAP_SUCCESS) { fprintf(stderr, "LDAP search error: %s\n", ldap_err2string(res)); return -1; } for (val = ldap_first_message(ldp, vals); val; val = ldap_next_message(ldp, val)) { struct berval **uid_val = ldap_get_values_len(ldp, val, "uidNumber"); if (uid_val) { uidnum = (int)strtol(uid_val[0]->bv_val, NULL, 0); ldap_value_free_len(uid_val); break; } } ldap_msgfree(vals); return uidnum; }
/* ** Retrieve next message... ** @return #1 entry's distinguished name. ** @return #2 table with entry's attributes and values. */ static int next_message (lua_State *L) { search_data *search = getsearch (L); conn_data *conn; struct timeval *timeout = NULL; /* ??? function parameter ??? */ LDAPMessage *res; int rc; int ret; lua_rawgeti (L, LUA_REGISTRYINDEX, search->conn); conn = (conn_data *)lua_touserdata (L, -1); /* get connection */ rc = ldap_result (conn->ld, search->msgid, LDAP_MSG_ONE, timeout, &res); if (rc == 0) return faildirect (L, LUALDAP_PREFIX"result timeout expired"); else if (rc == -1) return faildirect (L, LUALDAP_PREFIX"result error"); else if (rc == LDAP_RES_SEARCH_RESULT) { /* last message => nil */ /* close search object to avoid reuse */ search_close (L, search); ret = 0; } else { LDAPMessage *msg = ldap_first_message (conn->ld, res); switch (ldap_msgtype (msg)) { case LDAP_RES_SEARCH_ENTRY: { LDAPMessage *entry = ldap_first_entry (conn->ld, msg); push_dn (L, conn->ld, entry); lua_newtable (L); set_attribs (L, conn->ld, entry, lua_gettop (L)); ret = 2; /* two return values */ break; } /*No reference to LDAP_RES_SEARCH_REFERENCE on MSDN. Maybe there is a replacement to it?*/ #ifdef LDAP_RES_SEARCH_REFERENCE case LDAP_RES_SEARCH_REFERENCE: { LDAPMessage *ref = ldap_first_reference (conn->ld, msg); push_dn (L, conn->ld, ref); /* is this supposed to work? */ lua_pushnil (L); ret = 2; /* two return values */ break; } #endif case LDAP_RES_SEARCH_RESULT: /* close search object to avoid reuse */ search_close (L, search); ret = 0; break; default: ldap_msgfree (res); return luaL_error (L, LUALDAP_PREFIX"error on search result chain"); } } ldap_msgfree (res); return ret; }
static int search_iterator(lua_State *L) { LDAPMessage *result, *message, *entry; lua_apr_ldap_object *object; struct timeval *timeout; int status, msgid; object = lua_touserdata(L, lua_upvalueindex(1)); msgid = lua_tointeger(L, lua_upvalueindex(2)); timeout = lua_touserdata(L, lua_upvalueindex(3)); status = ldap_result(object->ldap, msgid, LDAP_MSG_ONE, timeout, &result); if (status == 0) raise_error_status(L, APR_TIMEUP); else if (status == -1) /* TODO Can we get a more specific error (message) here? ld_errno? */ raise_error_message(L, "Unspecified error"); else if (status == LDAP_RES_SEARCH_RESULT) { /* end of search results */ return 0; } else { message = ldap_first_message(object->ldap, result); switch (ldap_msgtype(message)) { case LDAP_RES_SEARCH_ENTRY: entry = ldap_first_entry(object->ldap, message); push_distinguished_name(L, object->ldap, entry); lua_newtable(L); set_attributes(L, object->ldap, entry, lua_gettop(L)); ldap_msgfree(result); return 2; /* No reference to LDAP_RES_SEARCH_REFERENCE on MSDN. Maybe is has a replacement? */ # ifdef LDAP_RES_SEARCH_REFERENCE case LDAP_RES_SEARCH_REFERENCE: { LDAPMessage *reference = ldap_first_reference(object->ldap, message); push_distinguished_name(L, object->ldap, reference); /* is this supposed to work? */ ldap_msgfree(result); return 1; } # endif case LDAP_RES_SEARCH_RESULT: /* end of search results */ ldap_msgfree(result); return 0; default: ldap_msgfree(result); raise_error_message(L, "unhandled message type in search results"); } } /* shouldn't be reached. */ ldap_msgfree(result); return 0; }
void BuildReply(int res, LDAPRequest *req) { LDAPResult *ldap_result = req->result = new LDAPResult(); req->result->type = req->type; if (res != LDAP_SUCCESS) { ldap_result->error = ldap_err2string(res); return; } if (req->message == NULL) { return; } /* a search result */ for (LDAPMessage *cur = ldap_first_message(this->con, req->message); cur; cur = ldap_next_message(this->con, cur)) { LDAPAttributes attributes; char *dn = ldap_get_dn(this->con, cur); if (dn != NULL) { attributes["dn"].push_back(dn); ldap_memfree(dn); dn = NULL; } BerElement *ber = NULL; for (char *attr = ldap_first_attribute(this->con, cur, &ber); attr; attr = ldap_next_attribute(this->con, cur, ber)) { berval **vals = ldap_get_values_len(this->con, cur, attr); int count = ldap_count_values_len(vals); std::vector<Anope::string> attrs; for (int j = 0; j < count; ++j) attrs.push_back(vals[j]->bv_val); attributes[attr] = attrs; ldap_value_free_len(vals); ldap_memfree(attr); } if (ber != NULL) ber_free(ber, 0); ldap_result->messages.push_back(attributes); } }
/* Iterate to the next search result in the linked list * of messages returned by the LDAP server and convert * the field values. */ static int search_entry(db_res_t* res, int init) { db_con_t* con; struct ld_res* lres; struct ld_con* lcon; int r; lres = DB_GET_PAYLOAD(res); /* FIXME */ con = res->cmd->ctx->con[db_payload_idx]; lcon = DB_GET_PAYLOAD(con); if (init || !lres->current || ldap_msgtype(lres->current) != LDAP_RES_SEARCH_ENTRY /* there is no more value combination result left */ || ld_incindex(res->cmd->result)) { do { if (init) { lres->current = ldap_first_message(lcon->con, lres->msg); init = 0; } else lres->current = ldap_next_message(lcon->con, lres->current); while(lres->current) { if (ldap_msgtype(lres->current) == LDAP_RES_SEARCH_ENTRY) { break; } lres->current = ldap_next_message(lcon->con, lres->current); } if (lres->current == NULL) return 1; r = ld_ldap2fldinit(res->cmd->result, lcon->con, lres->current); } while (r > 0); if (r < 0) return -1; } else { if (ld_ldap2fld(res->cmd->result, lcon->con, lres->current) < 0) return -1; } res->cur_rec->fld = res->cmd->result; return 0; }
static int do_base( char *uri, char *dn, struct berval *pass, char *base, char *filter, char *pwattr, int maxloop, int force, int chaserefs, int noinit, int delay, int action_type, void *action ) { LDAP *ld = NULL; int i = 0; int rc = LDAP_SUCCESS; ber_int_t msgid; LDAPMessage *res, *msg; char **dns = NULL; struct berval *creds = NULL; char *attrs[] = { LDAP_NO_ATTRS, NULL }; int ndns = 0; #ifdef _WIN32 DWORD beg, end; #else struct timeval beg, end; #endif int version = LDAP_VERSION3; char *nullstr = ""; ldap_initialize( &ld, uri ); if ( ld == NULL ) { tester_perror( "ldap_initialize", NULL ); exit( EXIT_FAILURE ); } (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); (void) ldap_set_option( ld, LDAP_OPT_REFERRALS, chaserefs ? LDAP_OPT_ON: LDAP_OPT_OFF ); rc = ldap_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, pass, NULL, NULL, NULL ); if ( rc != LDAP_SUCCESS ) { tester_ldap_error( ld, "ldap_sasl_bind_s", NULL ); exit( EXIT_FAILURE ); } fprintf( stderr, "PID=%ld - Bind(%d): base=\"%s\", filter=\"%s\" attr=\"%s\".\n", (long) pid, maxloop, base, filter, pwattr ); if ( pwattr != NULL ) { attrs[ 0 ] = pwattr; } rc = ldap_search_ext( ld, base, LDAP_SCOPE_SUBTREE, filter, attrs, 0, NULL, NULL, 0, 0, &msgid ); if ( rc != LDAP_SUCCESS ) { tester_ldap_error( ld, "ldap_search_ext", NULL ); exit( EXIT_FAILURE ); } while ( ( rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res ) ) > 0 ) { BerElement *ber; struct berval bv; int done = 0; for ( msg = ldap_first_message( ld, res ); msg; msg = ldap_next_message( ld, msg ) ) { switch ( ldap_msgtype( msg ) ) { case LDAP_RES_SEARCH_ENTRY: rc = ldap_get_dn_ber( ld, msg, &ber, &bv ); dns = realloc( dns, (ndns + 1)*sizeof(char *) ); dns[ndns] = ber_strdup( bv.bv_val ); if ( pwattr != NULL ) { struct berval **values = ldap_get_values_len( ld, msg, pwattr ); creds = realloc( creds, (ndns + 1)*sizeof(struct berval) ); if ( values == NULL ) { novals:; creds[ndns].bv_len = 0; creds[ndns].bv_val = nullstr; } else { static struct berval cleartext = BER_BVC( "{CLEARTEXT} " ); struct berval value = *values[ 0 ]; if ( value.bv_val[ 0 ] == '{' ) { char *end = ber_bvchr( &value, '}' ); if ( end ) { if ( ber_bvcmp( &value, &cleartext ) == 0 ) { value.bv_val += cleartext.bv_len; value.bv_len -= cleartext.bv_len; } else { ldap_value_free_len( values ); goto novals; } } } ber_dupbv( &creds[ndns], &value ); ldap_value_free_len( values ); } } ndns++; ber_free( ber, 0 ); break; case LDAP_RES_SEARCH_RESULT: done = 1; break; } if ( done ) break; } ldap_msgfree( res ); if ( done ) break; } #ifdef _WIN32 beg = GetTickCount(); #else gettimeofday( &beg, NULL ); #endif if ( ndns == 0 ) { tester_error( "No DNs" ); return 1; } fprintf( stderr, " PID=%ld - Bind base=\"%s\" filter=\"%s\" got %d values.\n", (long) pid, base, filter, ndns ); /* Ok, got list of DNs, now start binding to each */ for ( i = 0; i < maxloop; i++ ) { int j; struct berval cred = { 0, NULL }; #if 0 /* use high-order bits for better randomness (Numerical Recipes in "C") */ j = rand() % ndns; #endif j = ((double)ndns)*rand()/(RAND_MAX + 1.0); if ( creds && !BER_BVISEMPTY( &creds[j] ) ) { cred = creds[j]; } if ( do_bind( uri, dns[j], &cred, 1, force, chaserefs, noinit, &ld, action_type, action ) && !force ) { break; } if ( delay ) { sleep( delay ); } } if ( ld != NULL ) { ldap_unbind_ext( ld, NULL, NULL ); ld = NULL; } #ifdef _WIN32 end = GetTickCount(); end -= beg; fprintf( stderr, " PID=%ld - Bind done %d in %d.%03d seconds.\n", (long) pid, i, end / 1000, end % 1000 ); #else gettimeofday( &end, NULL ); end.tv_usec -= beg.tv_usec; if (end.tv_usec < 0 ) { end.tv_usec += 1000000; end.tv_sec -= 1; } end.tv_sec -= beg.tv_sec; fprintf( stderr, " PID=%ld - Bind done %d in %ld.%06ld seconds.\n", (long) pid, i, (long) end.tv_sec, (long) end.tv_usec ); #endif if ( dns ) { for ( i = 0; i < ndns; i++ ) { ber_memfree( dns[i] ); } free( dns ); } if ( creds ) { for ( i = 0; i < ndns; i++ ) { if ( creds[i].bv_val != nullstr ) { ber_memfree( creds[i].bv_val ); } } free( creds ); } return 0; }
/* * poll for new responses */ int ldap_sync_poll( ldap_sync_t *ls ) { struct timeval tv, *tvp = NULL; LDAPMessage *res = NULL, *msg; int rc = 0; #ifdef LDAP_SYNC_TRACE fprintf( stderr, "ldap_sync_poll...\n" ); #endif /* LDAP_SYNC_TRACE */ assert( ls != NULL ); assert( ls->ls_ld != NULL ); if ( ls->ls_timeout != -1 ) { tv.tv_sec = ls->ls_timeout; tv.tv_usec = 0; tvp = &tv; } rc = ldap_result( ls->ls_ld, ls->ls_msgid, LDAP_MSG_RECEIVED, tvp, &res ); if ( rc <= 0 ) { return rc; } for ( msg = ldap_first_message( ls->ls_ld, res ); msg; msg = ldap_next_message( ls->ls_ld, msg ) ) { int refreshDone; switch ( ldap_msgtype( msg ) ) { case LDAP_RES_SEARCH_ENTRY: rc = ldap_sync_search_entry( ls, res ); break; case LDAP_RES_SEARCH_REFERENCE: rc = ldap_sync_search_reference( ls, res ); break; case LDAP_RES_SEARCH_RESULT: rc = ldap_sync_search_result( ls, res ); goto done_search; case LDAP_RES_INTERMEDIATE: rc = ldap_sync_search_intermediate( ls, res, &refreshDone ); if ( rc != LDAP_SUCCESS || refreshDone ) { goto done_search; } break; default: #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\tgot something unexpected...\n" ); #endif /* LDAP_SYNC_TRACE */ ldap_msgfree( res ); rc = LDAP_OTHER; goto done; } } done_search:; ldap_msgfree( res ); done:; return rc; }
/* * initialize the sync */ int ldap_sync_init( ldap_sync_t *ls, int mode ) { LDAPControl ctrl = { 0 }, *ctrls[ 2 ]; BerElement *ber = NULL; int rc; struct timeval tv = { 0 }, *tvp = NULL; LDAPMessage *res = NULL; #ifdef LDAP_SYNC_TRACE fprintf( stderr, "ldap_sync_init(%s)...\n", mode == LDAP_SYNC_REFRESH_AND_PERSIST ? "LDAP_SYNC_REFRESH_AND_PERSIST" : ( mode == LDAP_SYNC_REFRESH_ONLY ? "LDAP_SYNC_REFRESH_ONLY" : "unknown" ) ); #endif /* LDAP_SYNC_TRACE */ assert( ls != NULL ); assert( ls->ls_ld != NULL ); /* support both refreshOnly and refreshAndPersist */ switch ( mode ) { case LDAP_SYNC_REFRESH_AND_PERSIST: case LDAP_SYNC_REFRESH_ONLY: break; default: fprintf( stderr, "ldap_sync_init: unknown mode=%d\n", mode ); return LDAP_PARAM_ERROR; } /* check consistency of cookie and reloadHint at initial refresh */ if ( ls->ls_cookie.bv_val == NULL && ls->ls_reloadHint != 0 ) { fprintf( stderr, "ldap_sync_init: inconsistent cookie/rhint\n" ); return LDAP_PARAM_ERROR; } ctrls[ 0 ] = &ctrl; ctrls[ 1 ] = NULL; /* prepare the Sync Request control */ ber = ber_alloc_t( LBER_USE_DER ); #ifdef LDAP_SYNC_TRACE fprintf( stderr, "%sber_alloc_t() %s= NULL\n", ber == NULL ? "!!! " : "", ber == NULL ? "=" : "!" ); #endif /* LDAP_SYNC_TRACE */ if ( ber == NULL ) { rc = LDAP_NO_MEMORY; goto done; } ls->ls_refreshPhase = LDAP_SYNC_CAPI_NONE; if ( ls->ls_cookie.bv_val != NULL ) { ber_printf( ber, "{eOb}", mode, &ls->ls_cookie, ls->ls_reloadHint ); } else { ber_printf( ber, "{eb}", mode, ls->ls_reloadHint ); } rc = ber_flatten2( ber, &ctrl.ldctl_value, 0 ); #ifdef LDAP_SYNC_TRACE fprintf( stderr, "%sber_flatten2() == %d\n", rc ? "!!! " : "", rc ); #endif /* LDAP_SYNC_TRACE */ if ( rc < 0 ) { rc = LDAP_OTHER; goto done; } /* make the control critical, as we cannot proceed without */ ctrl.ldctl_oid = LDAP_CONTROL_SYNC; ctrl.ldctl_iscritical = 1; /* timelimit? */ if ( ls->ls_timelimit ) { tv.tv_sec = ls->ls_timelimit; tvp = &tv; } /* actually run the search */ rc = ldap_search_ext( ls->ls_ld, ls->ls_base, ls->ls_scope, ls->ls_filter, ls->ls_attrs, 0, ctrls, NULL, tvp, ls->ls_sizelimit, &ls->ls_msgid ); #ifdef LDAP_SYNC_TRACE fprintf( stderr, "%sldap_search_ext(\"%s\", %d, \"%s\") == %d\n", rc ? "!!! " : "", ls->ls_base, ls->ls_scope, ls->ls_filter, rc ); #endif /* LDAP_SYNC_TRACE */ if ( rc != LDAP_SUCCESS ) { goto done; } /* initial content/content update phase */ for ( ; ; ) { LDAPMessage *msg = NULL; /* NOTE: this very short timeout is just to let * ldap_result() yield long enough to get something */ tv.tv_sec = 0; tv.tv_usec = 100000; rc = ldap_result( ls->ls_ld, ls->ls_msgid, LDAP_MSG_RECEIVED, &tv, &res ); #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t%sldap_result(%d) == %d\n", rc == -1 ? "!!! " : "", ls->ls_msgid, rc ); #endif /* LDAP_SYNC_TRACE */ switch ( rc ) { case 0: /* * timeout * * TODO: can do something else in the meanwhile) */ break; case -1: /* smtg bad! */ goto done; default: for ( msg = ldap_first_message( ls->ls_ld, res ); msg != NULL; msg = ldap_next_message( ls->ls_ld, msg ) ) { int refreshDone; switch ( ldap_msgtype( msg ) ) { case LDAP_RES_SEARCH_ENTRY: rc = ldap_sync_search_entry( ls, res ); break; case LDAP_RES_SEARCH_REFERENCE: rc = ldap_sync_search_reference( ls, res ); break; case LDAP_RES_SEARCH_RESULT: rc = ldap_sync_search_result( ls, res ); goto done_search; case LDAP_RES_INTERMEDIATE: rc = ldap_sync_search_intermediate( ls, res, &refreshDone ); if ( rc != LDAP_SUCCESS || refreshDone ) { goto done_search; } break; default: #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\tgot something unexpected...\n" ); #endif /* LDAP_SYNC_TRACE */ ldap_msgfree( res ); rc = LDAP_OTHER; goto done; } } ldap_msgfree( res ); res = NULL; break; } } done_search:; ldap_msgfree( res ); done:; if ( ber != NULL ) { ber_free( ber, 1 ); } return rc; }
int asyncmeta_handle_search_msg(LDAPMessage *res, a_metaconn_t *mc, bm_context_t *bc, int candidate) { a_metainfo_t *mi; a_metatarget_t *mt; a_metasingleconn_t *msc; Operation *op = bc->op; SlapReply *rs; int i, rc = LDAP_SUCCESS, sres; SlapReply *candidates; char **references = NULL; LDAPControl **ctrls = NULL; a_dncookie dc; LDAPMessage *msg; ber_int_t id; rs = &bc->rs; mi = mc->mc_info; mt = mi->mi_targets[ candidate ]; msc = &mc->mc_conns[ candidate ]; dc.op = op; dc.target = mt; dc.to_from = MASSAGE_REP; id = ldap_msgid(res); candidates = bc->candidates; i = candidate; while (res && !META_BACK_CONN_INVALID(msc)) { for (msg = ldap_first_message(msc->msc_ldr, res); msg; msg = ldap_next_message(msc->msc_ldr, msg)) { switch(ldap_msgtype(msg)) { case LDAP_RES_SEARCH_ENTRY: Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_handle_search_msg: msc %p entry\n", op->o_log_prefix, msc ); if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { /* don't retry any more... */ candidates[ i ].sr_type = REP_RESULT; } /* count entries returned by target */ candidates[ i ].sr_nentries++; if (bc->c_peer_name.bv_val == op->o_conn->c_peer_name.bv_val && !op->o_abandon) { rs->sr_err = asyncmeta_send_entry( &bc->copy_op, rs, mc, i, msg ); } else { goto err_cleanup; } switch ( rs->sr_err ) { case LDAP_SIZELIMIT_EXCEEDED: asyncmeta_send_ldap_result(bc, op, rs); rs->sr_err = LDAP_SUCCESS; goto err_cleanup; case LDAP_UNAVAILABLE: rs->sr_err = LDAP_OTHER; break; default: break; } bc->is_ok++; break; case LDAP_RES_SEARCH_REFERENCE: if ( META_BACK_TGT_NOREFS( mt ) ) { rs->sr_err = LDAP_OTHER; asyncmeta_send_ldap_result(bc, op, rs); goto err_cleanup; } if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { /* don't retry any more... */ candidates[ i ].sr_type = REP_RESULT; } bc->is_ok++; rc = ldap_parse_reference( msc->msc_ldr, msg, &references, &rs->sr_ctrls, 0 ); if ( rc != LDAP_SUCCESS || references == NULL ) { rs->sr_err = LDAP_OTHER; asyncmeta_send_ldap_result(bc, op, rs); goto err_cleanup; } /* FIXME: merge all and return at the end */ { int cnt; for ( cnt = 0; references[ cnt ]; cnt++ ) ; rs->sr_ref = ber_memalloc_x( sizeof( struct berval ) * ( cnt + 1 ), op->o_tmpmemctx ); for ( cnt = 0; references[ cnt ]; cnt++ ) { ber_str2bv_x( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ], op->o_tmpmemctx ); } BER_BVZERO( &rs->sr_ref[ cnt ] ); } { dc.memctx = op->o_tmpmemctx; ( void )asyncmeta_referral_result_rewrite( &dc, rs->sr_ref ); } if ( rs->sr_ref != NULL ) { if (!BER_BVISNULL( &rs->sr_ref[ 0 ] ) ) { /* ignore return value by now */ ( void )send_search_reference( op, rs ); } ber_bvarray_free_x( rs->sr_ref, op->o_tmpmemctx ); rs->sr_ref = NULL; } /* cleanup */ if ( references ) { ber_memvfree( (void **)references ); } if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } break; case LDAP_RES_INTERMEDIATE: if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) { /* don't retry any more... */ candidates[ i ].sr_type = REP_RESULT; } bc->is_ok++; /* FIXME: response controls * are passed without checks */ rs->sr_err = ldap_parse_intermediate( msc->msc_ldr, msg, (char **)&rs->sr_rspoid, &rs->sr_rspdata, &rs->sr_ctrls, 0 ); if ( rs->sr_err != LDAP_SUCCESS ) { candidates[ i ].sr_type = REP_RESULT; rs->sr_err = LDAP_OTHER; asyncmeta_send_ldap_result(bc, op, rs); goto err_cleanup; } slap_send_ldap_intermediate( op, rs ); if ( rs->sr_rspoid != NULL ) { ber_memfree( (char *)rs->sr_rspoid ); rs->sr_rspoid = NULL; } if ( rs->sr_rspdata != NULL ) { ber_bvfree( rs->sr_rspdata ); rs->sr_rspdata = NULL; } if ( rs->sr_ctrls != NULL ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } break; case LDAP_RES_SEARCH_RESULT: if ( mi->mi_idle_timeout != 0 ) { asyncmeta_set_msc_time(msc); } Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_handle_search_msg: msc %p result\n", op->o_log_prefix, msc ); candidates[ i ].sr_type = REP_RESULT; candidates[ i ].sr_msgid = META_MSGID_IGNORE; /* NOTE: ignores response controls * (and intermediate response controls * as well, except for those with search * references); this may not be correct, * but if they're not ignored then * back-meta would need to merge them * consistently (think of pagedResults...) */ /* FIXME: response controls? */ rs->sr_err = ldap_parse_result( msc->msc_ldr, msg, &candidates[ i ].sr_err, (char **)&candidates[ i ].sr_matched, (char **)&candidates[ i ].sr_text, &references, &ctrls /* &candidates[ i ].sr_ctrls (unused) */ , 0 ); if ( rs->sr_err != LDAP_SUCCESS ) { candidates[ i ].sr_err = rs->sr_err; sres = slap_map_api2result( &candidates[ i ] ); candidates[ i ].sr_type = REP_RESULT; goto finish; } rs->sr_err = candidates[ i ].sr_err; /* massage matchedDN if need be */ if ( candidates[ i ].sr_matched != NULL ) { struct berval match, mmatch; ber_str2bv( candidates[ i ].sr_matched, 0, 0, &match ); candidates[ i ].sr_matched = NULL; dc.memctx = NULL; asyncmeta_dn_massage( &dc, &match, &mmatch ); if ( mmatch.bv_val == match.bv_val ) { candidates[ i ].sr_matched = ch_strdup( mmatch.bv_val ); } else { candidates[ i ].sr_matched = mmatch.bv_val; } bc->candidate_match++; ldap_memfree( match.bv_val ); } /* add references to array */ /* RFC 4511: referrals can only appear * if result code is LDAP_REFERRAL */ if ( references != NULL && references[ 0 ] != NULL && references[ 0 ][ 0 ] != '\0' ) { if ( rs->sr_err != LDAP_REFERRAL ) { Debug( LDAP_DEBUG_ANY, "%s asncmeta_search_result[%d]: " "got referrals with err=%d\n", op->o_log_prefix, i, rs->sr_err ); } else { BerVarray sr_ref; int cnt; for ( cnt = 0; references[ cnt ]; cnt++ ) ; sr_ref = ber_memalloc_x( sizeof( struct berval ) * ( cnt + 1 ), op->o_tmpmemctx ); for ( cnt = 0; references[ cnt ]; cnt++ ) { ber_str2bv_x( references[ cnt ], 0, 1, &sr_ref[ cnt ], op->o_tmpmemctx ); } BER_BVZERO( &sr_ref[ cnt ] ); dc.memctx = op->o_tmpmemctx; ( void )asyncmeta_referral_result_rewrite( &dc, sr_ref ); if ( rs->sr_v2ref == NULL ) { rs->sr_v2ref = sr_ref; } else { for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) { ber_bvarray_add_x( &rs->sr_v2ref, &sr_ref[ cnt ], op->o_tmpmemctx ); } ber_memfree_x( sr_ref, op->o_tmpmemctx ); } } } else if ( rs->sr_err == LDAP_REFERRAL ) { Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_search_result[%d]: " "got err=%d with null " "or empty referrals\n", op->o_log_prefix, i, rs->sr_err ); rs->sr_err = LDAP_NO_SUCH_OBJECT; } /* cleanup */ ber_memvfree( (void **)references ); sres = slap_map_api2result( rs ); if ( candidates[ i ].sr_err == LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_search_result[%d] " "match=\"%s\" err=%ld", op->o_log_prefix, i, candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "", (long) candidates[ i ].sr_err ); } else { Debug( LDAP_DEBUG_ANY, "%s asyncmeta_search_result[%d] " "match=\"%s\" err=%ld (%s)", op->o_log_prefix, i, candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "", (long) candidates[ i ].sr_err, ldap_err2string( candidates[ i ].sr_err ) ); } switch ( sres ) { case LDAP_NO_SUCH_OBJECT: /* is_ok is touched any time a valid * (even intermediate) result is * returned; as a consequence, if * a candidate returns noSuchObject * it is ignored and the candidate * is simply demoted. */ if ( bc->is_ok ) { sres = LDAP_SUCCESS; } break; case LDAP_SUCCESS: if ( ctrls != NULL && ctrls[0] != NULL ) { #ifdef SLAPD_META_CLIENT_PR LDAPControl *pr_c; pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL ); if ( pr_c != NULL ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; ber_tag_t tag; ber_int_t prsize; struct berval prcookie; /* unsolicited, do not accept */ if ( mt->mt_ps == 0 ) { rs->sr_err = LDAP_OTHER; goto err_pr; } ber_init2( ber, &pr_c->ldctl_value, LBER_USE_DER ); tag = ber_scanf( ber, "{im}", &prsize, &prcookie ); if ( tag == LBER_ERROR ) { rs->sr_err = LDAP_OTHER; goto err_pr; } /* more pages? new search request */ if ( !BER_BVISNULL( &prcookie ) && !BER_BVISEMPTY( &prcookie ) ) { if ( mt->mt_ps > 0 ) { /* ignore size if specified */ prsize = 0; } else if ( prsize == 0 ) { /* guess the page size from the entries returned so far */ prsize = candidates[ i ].sr_nentries; } candidates[ i ].sr_nentries = 0; candidates[ i ].sr_msgid = META_MSGID_IGNORE; candidates[ i ].sr_type = REP_INTERMEDIATE; assert( candidates[ i ].sr_matched == NULL ); assert( candidates[ i ].sr_text == NULL ); assert( candidates[ i ].sr_ref == NULL ); switch ( asyncmeta_back_search_start( &bc->copy_op, rs, mc, bc, i, &prcookie, prsize, 1 ) ) { case META_SEARCH_CANDIDATE: assert( candidates[ i ].sr_msgid >= 0 ); ldap_controls_free( ctrls ); // goto free_message; case META_SEARCH_ERR: case META_SEARCH_NEED_BIND: err_pr:; candidates[ i ].sr_err = rs->sr_err; candidates[ i ].sr_type = REP_RESULT; if ( META_BACK_ONERR_STOP( mi ) ) { asyncmeta_send_ldap_result(bc, op, rs); ldap_controls_free( ctrls ); goto err_cleanup; } /* fallthru */ case META_SEARCH_NOT_CANDIDATE: /* means that asyncmeta_back_search_start() * failed but onerr == continue */ candidates[ i ].sr_msgid = META_MSGID_IGNORE; candidates[ i ].sr_type = REP_RESULT; break; default: /* impossible */ assert( 0 ); break; } break; } } #endif /* SLAPD_META_CLIENT_PR */ ldap_controls_free( ctrls ); } /* fallthru */ case LDAP_REFERRAL: bc->is_ok++; break; case LDAP_SIZELIMIT_EXCEEDED: /* if a target returned sizelimitExceeded * and the entry count is equal to the * proxy's limit, the target would have * returned more, and the error must be * propagated to the client; otherwise, * the target enforced a limit lower * than what requested by the proxy; * ignore it */ candidates[ i ].sr_err = rs->sr_err; if ( rs->sr_nentries == op->ors_slimit || META_BACK_ONERR_STOP( mi ) ) { const char *save_text; got_err: save_text = rs->sr_text; rs->sr_text = candidates[ i ].sr_text; asyncmeta_send_ldap_result(bc, op, rs); if (candidates[ i ].sr_text != NULL) { ch_free( (char *)candidates[ i ].sr_text ); candidates[ i ].sr_text = NULL; } rs->sr_text = save_text; ldap_controls_free( ctrls ); goto err_cleanup; } break; default: candidates[ i ].sr_err = rs->sr_err; if ( META_BACK_ONERR_STOP( mi ) ) { goto got_err; } break; } /* if this is the last result we will ever receive, send it back */ rc = rs->sr_err; if (asyncmeta_is_last_result(mc, bc, i) == 0) { Debug( LDAP_DEBUG_TRACE, "%s asyncmeta_handle_search_msg: msc %p last result\n", op->o_log_prefix, msc ); asyncmeta_search_last_result(mc, bc, i, sres); err_cleanup: rc = rs->sr_err; ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex ); asyncmeta_drop_bc( mc, bc); asyncmeta_clear_bm_context(bc); ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex ); ldap_msgfree(res); return rc; } finish: break; default: continue; } } ldap_msgfree(res); res = NULL; if (candidates[ i ].sr_type != REP_RESULT) { struct timeval tv = {0}; rc = ldap_result( msc->msc_ldr, id, LDAP_MSG_RECEIVED, &tv, &res ); if (res != NULL) { msc->msc_result_time = slap_get_time(); } } } ldap_pvt_thread_mutex_lock( &mc->mc_om_mutex ); bc->bc_active--; ldap_pvt_thread_mutex_unlock( &mc->mc_om_mutex ); return rc; }
static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, size_t len, CURLcode *err) { ldapconninfo *li = conn->proto.generic; struct SessionHandle *data = conn->data; ldapreqinfo *lr = data->req.protop; int rc, ret; LDAPMessage *msg = NULL; LDAPMessage *ent; BerElement *ber = NULL; struct timeval tv = {0, 1}; (void)len; (void)buf; (void)sockindex; rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &msg); if(rc < 0) { failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc)); *err = CURLE_RECV_ERROR; return -1; } *err = CURLE_AGAIN; ret = -1; /* timed out */ if(!msg) return ret; for(ent = ldap_first_message(li->ld, msg); ent; ent = ldap_next_message(li->ld, ent)) { struct berval bv, *bvals, **bvp = &bvals; int binary = 0, msgtype; msgtype = ldap_msgtype(ent); if(msgtype == LDAP_RES_SEARCH_RESULT) { int code; char *info = NULL; rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0); if(rc) { failf(data, "LDAP local: search ldap_parse_result %s", ldap_err2string(rc)); *err = CURLE_LDAP_SEARCH_FAILED; } else if(code && code != LDAP_SIZELIMIT_EXCEEDED) { failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc), info ? info : ""); *err = CURLE_LDAP_SEARCH_FAILED; } else { /* successful */ if(code == LDAP_SIZELIMIT_EXCEEDED) infof(data, "There are more than %d entries\n", lr->nument); data->req.size = data->req.bytecount; *err = CURLE_OK; ret = 0; } lr->msgid = 0; ldap_memfree(info); break; } else if(msgtype != LDAP_RES_SEARCH_ENTRY) continue; lr->nument++; rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv); if(rc < 0) { /* TODO: verify that this is really how this return code should be handled */ *err = CURLE_RECV_ERROR; return -1; } *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); if(*err) return -1; *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len); if(*err) return -1; *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); if(*err) return -1; data->req.bytecount += bv.bv_len + 5; for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp); rc == LDAP_SUCCESS; rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) { int i; if(bv.bv_val == NULL) break; if(bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7)) binary = 1; else binary = 0; for(i=0; bvals[i].bv_val != NULL; i++) { int binval = 0; *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1); if(*err) return -1; *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len); if(*err) return -1; *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1); if(*err) return -1; data->req.bytecount += bv.bv_len + 2; if(!binary) { /* check for leading or trailing whitespace */ if(ISSPACE(bvals[i].bv_val[0]) || ISSPACE(bvals[i].bv_val[bvals[i].bv_len-1])) binval = 1; else { /* check for unprintable characters */ unsigned int j; for(j=0; j<bvals[i].bv_len; j++) if(!ISPRINT(bvals[i].bv_val[j])) { binval = 1; break; } } } if(binary || binval) { char *val_b64 = NULL; size_t val_b64_sz = 0; /* Binary value, encode to base64. */ CURLcode error = Curl_base64_encode(data, bvals[i].bv_val, bvals[i].bv_len, &val_b64, &val_b64_sz); if(error) { ber_memfree(bvals); ber_free(ber, 0); ldap_msgfree(msg); *err = error; return -1; } *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2); if(*err) return -1; data->req.bytecount += 2; if(val_b64_sz > 0) { *err = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz); if(*err) return -1; free(val_b64); data->req.bytecount += val_b64_sz; } } else { *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1); if(*err) return -1; *err = Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val, bvals[i].bv_len); if(*err) return -1; data->req.bytecount += bvals[i].bv_len + 1; } *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); if(*err) return -1; data->req.bytecount++; } ber_memfree(bvals); *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); if(*err) return -1; data->req.bytecount++; } *err = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0); if(*err) return -1; data->req.bytecount++; ber_free(ber, 0); } ldap_msgfree(msg); return ret; }
/** Parse response from LDAP server dealing with any errors * * Should be called after an LDAP operation. Will check result of operation and if * it was successful, then attempt to retrieve and parse the result. Will also produce * extended error output including any messages the server sent, and information about * partial DN matches. * * @note Error messages should be retrieved with fr_strerror() and fr_strerror_pop() * * @param[out] result Where to write result, if NULL result will be freed. If not NULL caller * must free with ldap_msgfree(). * @param[out] ctrls Server ctrls returned to the client. May be NULL if not required. * Must be freed with ldap_free_ctrls. * @param[in] conn Current connection. * @param[in] msgid returned from last operation. * Special values are: * - LDAP_RES_ANY - Retrieve any received messages useful for multiplexing. * - LDAP_RES_UNSOLICITED - Any unsolicited message. * @param[in] all How many messages to retrieve: * - LDAP_MSG_ONE - Retrieve the first message matching msgid (waiting if one is not available). * - LDAP_MSG_ALL - Retrieve all received messages matching msgid (waiting if none are available). * - LDAP_MSG_RECEIVED - Retrieve all received messages. * @param[in] dn Last search or bind DN. May be NULL. * @param[in] timeout Override the default result timeout. * * @return One of the LDAP_PROC_* (#fr_ldap_rcode_t) values. */ fr_ldap_rcode_t fr_ldap_result(LDAPMessage **result, LDAPControl ***ctrls, fr_ldap_connection_t const *conn, int msgid, int all, char const *dn, struct timeval const *timeout) { fr_ldap_rcode_t status = LDAP_PROC_SUCCESS; int lib_errno; struct timeval tv; /* Holds timeout values */ LDAPMessage *tmp_msg = NULL, *msg; /* Temporary message pointer storage if we weren't provided with one */ LDAPMessage **result_p = result; if (result) *result = NULL; if (ctrls) *ctrls = NULL; /* * We always need the result, but our caller may not */ if (!result) result_p = &tmp_msg; /* * Check if there was an error sending the request */ ldap_get_option(conn->handle, LDAP_OPT_ERROR_NUMBER, &lib_errno); if (lib_errno != LDAP_SUCCESS) return fr_ldap_error_check(NULL, conn, NULL, dn); if (!timeout) { tv = conn->config->res_timeout; } else { tv = *timeout; } /* * Now retrieve the result and check for errors * ldap_result returns -1 on failure, and 0 on timeout */ lib_errno = ldap_result(conn->handle, msgid, all, &tv, result_p); switch (lib_errno) { case 0: lib_errno = LDAP_TIMEOUT; fr_strerror_printf("timeout waiting for result"); return LDAP_PROC_TIMEOUT; case -1: return fr_ldap_error_check(NULL, conn, NULL, dn); default: break; } for (msg = ldap_first_message(conn->handle, *result_p); msg; msg = ldap_next_message(conn->handle, msg)) { status = fr_ldap_error_check(ctrls, conn, msg, dn); if (status != LDAP_PROC_SUCCESS) break; } if (*result_p && ((status < 0) || !result)) { ldap_msgfree(*result_p); *result_p = NULL; } return status; }
void OPENLDAP::Book::refresh_result () { int result = LDAP_SUCCESS; int nbr = 0; struct timeval timeout = { 1, 0}; /* block 1s */ LDAPMessage *msg_entry = NULL; LDAPMessage *msg_result = NULL; gchar* c_status = NULL; result = ldap_result (ldap_context, LDAP_RES_ANY, LDAP_MSG_ALL, &timeout, &msg_entry); if (result <= 0) { if (patience == 3) { patience--; Ekiga::Runtime::run_in_main (boost::bind (&OPENLDAP::Book::refresh_result, this), 12); } else if (patience == 2) { patience--; Ekiga::Runtime::run_in_main (boost::bind (&OPENLDAP::Book::refresh_result, this), 21); } else if (patience == 1) { patience--; Ekiga::Runtime::run_in_main (boost::bind (&OPENLDAP::Book::refresh_result, this), 30); } else { // patience == 0 status = std::string (_("Could not search")); updated (this->shared_from_this ()); ldap_unbind_ext (ldap_context, NULL, NULL); ldap_context = NULL; } if (msg_entry != NULL) ldap_msgfree (msg_entry); return; } msg_result = ldap_first_message (ldap_context, msg_entry); do { if (ldap_msgtype (msg_result) == LDAP_RES_SEARCH_ENTRY) { ContactPtr contact = parse_result (msg_result); if (contact) { add_contact (contact); nbr++; } } msg_result = ldap_next_message (ldap_context, msg_result); } while (msg_result != NULL); // Do not count ekiga.net's first entry "Search Results ... 100 entries" if (bookinfo.uri_host == EKIGA_NET_URI) nbr--; c_status = g_strdup_printf (ngettext ("%d user found", "%d users found", nbr), nbr); status = c_status; g_free (c_status); updated (this->shared_from_this ()); (void)ldap_msgfree (msg_entry); ldap_unbind_ext (ldap_context, NULL, NULL); ldap_context = NULL; }
static bool_t linphone_ldap_contact_provider_iterate(void *data) { LinphoneLDAPContactProvider* obj = LINPHONE_LDAP_CONTACT_PROVIDER(data); if( obj->ld && obj->connected && (obj->req_count > 0) ){ // never block struct timeval timeout = {0,0}; LDAPMessage* results = NULL; int ret = ldap_result(obj->ld, LDAP_RES_ANY, LDAP_MSG_ONE, &timeout, &results); switch( ret ){ case -1: { ms_warning("Error in ldap_result : returned -1 (req_count %d): %s", obj->req_count, ldap_err2string(errno)); break; } case 0: break; // nothing to do case LDAP_RES_BIND: { ms_error("iterate: unexpected LDAP_RES_BIND"); break; } case LDAP_RES_EXTENDED: case LDAP_RES_SEARCH_ENTRY: case LDAP_RES_SEARCH_REFERENCE: case LDAP_RES_INTERMEDIATE: case LDAP_RES_SEARCH_RESULT: { LDAPMessage* message = ldap_first_message(obj->ld, results); LinphoneLDAPContactSearch* req = linphone_ldap_contact_provider_request_search(obj, ldap_msgid(message)); while( message != NULL ){ linphone_ldap_contact_provider_handle_search_result(obj, req, message ); message = ldap_next_message(obj->ld, message); } if( req && ret == LDAP_RES_SEARCH_RESULT) linphone_ldap_contact_provider_cancel_search( LINPHONE_CONTACT_PROVIDER(obj), LINPHONE_CONTACT_SEARCH(req)); break; } case LDAP_RES_MODIFY: case LDAP_RES_ADD: case LDAP_RES_DELETE: case LDAP_RES_MODDN: case LDAP_RES_COMPARE: default: ms_message("Unhandled LDAP result %x", ret); break; } if( results ) ldap_msgfree(results); } if( obj->ld && obj->connected ){ // check for pending searches unsigned int i; for( i=0; i<obj->req_count; i++){ LinphoneLDAPContactSearch* search = (LinphoneLDAPContactSearch*)ms_list_nth_data( obj->requests, i ); if( search && search->msgid == 0){ int ret; ms_message("Found pending search %p (for %s), launching...", search, search->filter); ret = linphone_ldap_contact_provider_perform_search(obj, search); if( ret != LDAP_SUCCESS ){ linphone_ldap_contact_provider_cancel_search( LINPHONE_CONTACT_PROVIDER(obj), LINPHONE_CONTACT_SEARCH(search)); } } } } return TRUE; }
int ld_cmd_exec(db_res_t* res, db_cmd_t* cmd) { db_con_t* con; struct ld_res* lres; struct ld_cmd* lcmd; struct ld_con* lcon; char* filter, *err_desc; int ret, err; LDAPMessage *msg, *resmsg; int reconn_cnt; int msgid; char *oid; struct berval *data; struct timeval restimeout; filter = NULL; err_desc = NULL; resmsg = NULL; /* First things first: retrieve connection info from the currently active * connection and also mysql payload from the database command */ con = cmd->ctx->con[db_payload_idx]; lcmd = DB_GET_PAYLOAD(cmd); lcon = DB_GET_PAYLOAD(con); reconn_cnt = ld_reconnect_attempt; if (ld_prepare_ldap_filter(&filter, cmd, &lcmd->filter) < 0) { ERR("ldap: Error while building LDAP search filter\n"); goto error; } DBG("ldap: ldap_search(base:'%s', filter:'%s')\n", lcmd->base, filter); do { if (lcon->flags & LD_CONNECTED) { ldap_set_option(lcon->con, LDAP_OPT_DEREF, ((void *)&lcmd->chase_references)); /* there is alternative method using LDAP_CONTROL_REFERRALS per request but is not well documented */ ldap_set_option(lcon->con, LDAP_OPT_REFERRALS, lcmd->chase_referrals?LDAP_OPT_ON:LDAP_OPT_OFF); ret = ldap_search_ext(lcon->con, lcmd->base, lcmd->scope, filter, lcmd->result, 0, NULL, NULL, lcmd->timelimit.tv_sec ? &lcmd->timelimit : NULL, lcmd->sizelimit, &msgid); if (ret != LDAP_SUCCESS) { ERR("ldap: Error while searching: %s\n", ldap_err2string(ret)); goto error; } /* openldap v2.3 library workaround for unsolicited messages: if only unsolicited messages are available then ldap_result of v2.3 library waits forever */ memset(&restimeout, 0, sizeof(restimeout)); restimeout.tv_sec = 5; ret = ldap_result(lcon->con, LDAP_RES_ANY, LDAP_MSG_ALL, &restimeout, &resmsg); } else { /* force it to reconnect */ ret = -1; } if (ret <= 0) { ERR("ldap: Error in ldap_search: %s\n", ret < 0 ? ldap_err2string(ret) : "timeout"); if (ret == LDAP_SERVER_DOWN) { lcon->flags &= ~LD_CONNECTED; do { if (!reconn_cnt) { ERR("ldap: maximum reconnection attempt reached! giving up\n"); goto error; } reconn_cnt--; err = ld_con_connect(con); } while (err != 0); } else { goto error; } } } while (ret <= 0); /* looking for unsolicited messages */ for (msg = ldap_first_message(lcon->con, resmsg); msg != NULL; msg = ldap_next_message(lcon->con, msg)) { if (ldap_msgtype(msg) == LDAP_RES_EXTENDED) { if (ldap_parse_extended_result(lcon->con, msg, &oid, &data, 0) != LDAP_SUCCESS) { ERR("ldap: Error while parsing extended result\n"); goto error; } if (oid != NULL) { if (strcmp(oid, LDAP_NOTICE_OF_DISCONNECTION) == 0) { WARN("ldap: Notice of Disconnection (OID: %s)\n", oid); } else { WARN("ldap: Unsolicited message received. OID: %s\n", oid); } ldap_memfree(oid); } if (data != NULL) { WARN("ldap: Unsolicited message data: %.*s\n", (int)data->bv_len, data->bv_val); ber_bvfree(data); } } } ret = ldap_parse_result(lcon->con, resmsg, &err, NULL, &err_desc, NULL, NULL, 0); if (ret != LDAP_SUCCESS) { ERR("ldap: Error while reading result status: %s\n", ldap_err2string(ret)); goto error; } if (err != LDAP_SUCCESS) { ERR("ldap: LDAP server reports error: %s\n", ldap_err2string(err)); goto error; } if (res) { lres = DB_GET_PAYLOAD(res); lres->msg = resmsg; } else if (resmsg) { ldap_msgfree(resmsg); } if (filter) pkg_free(filter); if (err_desc) ldap_memfree(err_desc); return 0; error: if (filter) pkg_free(filter); if (resmsg) ldap_msgfree(resmsg); if (err_desc) ldap_memfree(err_desc); return -1; }
static int l_search_do_filter(struct ldapsearch *s, int (*callback_func)(const char *utf8_name, const char *address, void *callback_arg), void *callback_arg, const char *filter, const char *lookup_key, int *found) { char *kk; struct timeval tv; LDAPMessage *result; char *attrs[3]; int rc_code=0; int msgidp; *found=0; kk=make_search_key(filter, lookup_key); if (!kk) return -1; if (s->handle == NULL) { errno=ETIMEDOUT; /* Timeout previously */ return -1; } attrs[0]="cn"; attrs[1]="mail"; attrs[2]=NULL; tv.tv_sec=60*60; tv.tv_usec=0; if (ldap_search_ext(s->handle, s->base, LDAP_SCOPE_SUBTREE, kk, attrs, 0, NULL, NULL, &tv, 1000000, &msgidp) != LDAP_SUCCESS) return -1; do { int rc; LDAPMessage *msg; const char *timeout=getenv("LDAP_SEARCH_TIMEOUT"); tv.tv_sec=atoi(timeout ? timeout:"30"); tv.tv_usec=0; rc=ldap_result(s->handle, msgidp, 0, &tv, &result); if (rc <= 0) { if (rc == 0) errno=ETIMEDOUT; ldap_unbind_ext(s->handle, NULL, NULL); s->handle=NULL; rc_code= -1; break; } if (rc == LDAP_RES_SEARCH_RESULT) { ldap_msgfree(result); break; /* End of search */ } if (rc != LDAP_RES_SEARCH_ENTRY) { ldap_msgfree(result); continue; } for (msg=ldap_first_message(s->handle, result); msg; msg=ldap_next_message(s->handle, msg)) { struct berval **n_val= ldap_get_values_len(s->handle, msg, "cn"); struct berval **a_val= ldap_get_values_len(s->handle, msg, "mail"); if (n_val && a_val) { size_t i, j; for (i=0; n_val[i]; i++) for (j=0; a_val[j]; j++) { char *p=malloc(n_val[i]->bv_len +1); char *q=malloc(a_val[j]->bv_len +1); if (!p || !q) { if (p) free(p); if (q) free(q); rc_code= -1; break; } memcpy(p, n_val[i]->bv_val, n_val[i]->bv_len); p[n_val[i]->bv_len]=0; memcpy(q, a_val[j]->bv_val, a_val[j]->bv_len); q[a_val[j]->bv_len]=0; rc_code=(*callback_func) (p, q, callback_arg); free(p); free(q); if (rc_code) break; *found=1; } } if (n_val) ldap_value_free_len(n_val); if (a_val) ldap_value_free_len(a_val); } ldap_msgfree(result); } while (rc_code == 0); return rc_code; }
static void * my_task( void *my_num ) { LDAP *ld = NULL, *sld = NULL; ber_int_t msgid; LDAPMessage *res, *msg; char *attrs[] = { "1.1", NULL }; int rc = LDAP_SUCCESS; int tid = *(int *)my_num; ldap_initialize( &ld, uri ); if ( ld == NULL ) { perror( "ldap_initialize" ); return NULL; } { int version = LDAP_VERSION3; (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); } (void) ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ); ldap_initialize( &sld, uri ); if ( sld == NULL ) { perror( "ldap_initialize" ); return NULL; } { int version = LDAP_VERSION3; (void) ldap_set_option( sld, LDAP_OPT_PROTOCOL_VERSION, &version ); } (void) ldap_set_option( sld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ); if ( binder ) { rc = ldap_bind_s( sld, binder, pass, LDAP_AUTH_SIMPLE ); if ( rc != LDAP_SUCCESS ) { ldap_perror( sld, "ldap_bind" ); } } r1binds[tid] = 0; for (;;) { char dn[BUFSIZ], *ptr, fstr[256]; int j, isr1; if ( finish ) break; j = rand() % 100; if ( j < r1per ) { j = rand() % r1hi; isr1 = 1; } else { j = rand() % (r2hi - r2lo + 1 ); j += r2lo; isr1 = 0; } sprintf(fstr, filter, j); rc = ldap_search_ext( sld, base, LDAP_SCOPE_SUB, fstr, attrs, 0, NULL, NULL, 0, 0, &msgid ); if ( rc != LDAP_SUCCESS ) { ldap_perror( sld, "ldap_search_ex" ); return NULL; } while (( rc=ldap_result( sld, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &res )) >0){ BerElement *ber; struct berval bv; char *ptr; int done = 0; for (msg = ldap_first_message( sld, res ); msg; msg = ldap_next_message( sld, msg )) { switch ( ldap_msgtype( msg )) { case LDAP_RES_SEARCH_ENTRY: rc = ldap_get_dn_ber( sld, msg, &ber, &bv ); strcpy(dn, bv.bv_val ); ber_free( ber, 0 ); break; case LDAP_RES_SEARCH_RESULT: done = 1; break; } if ( done ) break; } ldap_msgfree( res ); if ( done ) break; } rc = ldap_bind_s( ld, dn, pass, LDAP_AUTH_SIMPLE ); if ( rc != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_bind" ); } if ( isr1 ) r1binds[tid]++; else r2binds[tid]++; } ldap_unbind( sld ); ldap_unbind( ld ); return NULL; }