static int verify_single_result(LDAP *l, int always_log, char *reason, LDAPMessage *messages) { int rc, erc, num_entries; char *errmsg; rc = ldap_parse_result(l, messages, &erc, NULL, &errmsg, NULL, NULL, 0); if (rc != LDAP_SUCCESS) { prtmsg("Failed to %s (parse_result): %s", reason, ldap_err2string(rc)); return 0; } if (erc != LDAP_SUCCESS) { prtmsg("Failed to %s (server response): %s%s%s", reason, ldap_err2string(erc), (errmsg?", ":""), (errmsg?errmsg:"")); if (errmsg) ldap_memfree(errmsg); return 0; } if (errmsg) ldap_memfree(errmsg); num_entries=ldap_count_entries(l, messages); if (num_entries == 0) { if (always_log) prtmsg("Failed to %s (no entries returned)", reason); return 0; } if (num_entries > 1) { prtmsg("Failed to %s (too many entries: %d)", reason, num_entries); return 0; } return 1; }
ULONG CDECL ldap_parse_resultW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result, ULONG *retcode, PWCHAR *matched, PWCHAR *error, PWCHAR **referrals, PLDAPControlW **serverctrls, BOOLEAN free ) { ULONG ret = LDAP_NOT_SUPPORTED; #ifdef HAVE_LDAP char **matchedU = NULL, **errorU = NULL, **referralsU = NULL; LDAPControl **serverctrlsU = NULL; TRACE( "(%p, %p, %p, %p, %p, %p, %p, 0x%02x)\n", ld, result, retcode, matched, error, referrals, serverctrls, free ); if (!ld) return ~0UL; ret = ldap_parse_result( ld, result, (int *)retcode, matchedU, errorU, &referralsU, &serverctrlsU, free ); matched = strarrayUtoW( matchedU ); error = strarrayUtoW( errorU ); *referrals = strarrayUtoW( referralsU ); *serverctrls = controlarrayUtoW( serverctrlsU ); ldap_memfree( matchedU ); ldap_memfree( errorU ); ldap_memfree( referralsU ); ldap_controls_free( serverctrlsU ); #endif return ret; }
static void on_bind_readable(verto_ctx *vctx, verto_ev *ev) { const char *errstr = "error"; LDAPMessage *results; struct otpd_queue_item *item = NULL; int i, rslt; (void)vctx; rslt = ldap_result(verto_get_private(ev), LDAP_RES_ANY, 0, NULL, &results); if (rslt != LDAP_RES_BIND) { if (rslt <= 0) results = NULL; ldap_msgfree(results); otpd_log_err(EIO, "IO error received on bind socket"); verto_break(ctx.vctx); ctx.exitstatus = 1; return; } item = otpd_queue_pop_msgid(&ctx.bind.responses, ldap_msgid(results)); if (item == NULL) { ldap_msgfree(results); return; } item->msgid = -1; rslt = ldap_parse_result(verto_get_private(ev), results, &i, NULL, NULL, NULL, NULL, 0); if (rslt != LDAP_SUCCESS) { errstr = ldap_err2string(rslt); goto error; } rslt = i; if (rslt != LDAP_SUCCESS) { errstr = ldap_err2string(rslt); goto error; } item->sent = 0; i = krad_packet_new_response(ctx.kctx, SECRET, krad_code_name2num("Access-Accept"), NULL, item->req, &item->rsp); if (i != 0) { errstr = krb5_get_error_message(ctx.kctx, i); goto error; } error: if (item != NULL) otpd_log_req(item->req, "bind end: %s", item->rsp != NULL ? "success" : errstr); ldap_msgfree(results); otpd_queue_push(&ctx.stdio.responses, item); verto_set_flags(ctx.stdio.writer, VERTO_EV_FLAG_PERSIST | VERTO_EV_FLAG_IO_ERROR | VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_IO_WRITE); }
/* Called when results come in for a key send */ static gboolean on_import_add_completed (LDAPMessage *result, gpointer user_data) { GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); source_import_closure *closure = g_simple_async_result_get_op_res_gpointer (res); SeahorseLDAPSource *self = SEAHORSE_LDAP_SOURCE (g_async_result_get_source_object (user_data)); GError *error = NULL; char *message; int code; int rc; g_return_val_if_fail (ldap_msgtype (result) == LDAP_RES_ADD, FALSE); rc = ldap_parse_result (closure->ldap, result, &code, NULL, &message, NULL, NULL, 0); g_return_val_if_fail (rc == LDAP_SUCCESS, FALSE); /* TODO: Somehow communicate this to the user */ if (code == LDAP_ALREADY_EXISTS) code = LDAP_SUCCESS; ldap_memfree (message); if (seahorse_ldap_source_propagate_error (self, code, &error)) { g_simple_async_result_take_error (res, error); g_simple_async_result_complete (res); return FALSE; /* don't call for this source again */ } import_send_key (self, res); return FALSE; /* don't call for this source again */ }
static int result_message(lua_State *L) { struct timeval *timeout = NULL; /* ??? function parameter ??? */ LDAPMessage *res; int rc; lua_apr_ldap_object *object = check_ldap_connection(L, lua_upvalueindex(1)); int msgid = (int)lua_tonumber(L, lua_upvalueindex(2)); /*int res_code = (int)lua_tonumber(L, lua_upvalueindex(3));*/ luaL_argcheck(L, object->ldap, 1, "LDAP connection is closed"); rc = ldap_result(object->ldap, msgid, LDAP_MSG_ONE, timeout, &res); if (rc == 0) { return push_error_message(L, "result timeout expired"); } else if (rc < 0) { ldap_msgfree(res); return push_error_message(L, "result error"); } else { int err, ret = 1; char *mdn, *msg1, *msg2; rc = ldap_parse_result(object->ldap, res, &err, &mdn, &msg1, NULL, NULL, 1); if (rc != LDAP_SUCCESS) return push_error_message(L, ldap_err2string(rc)); switch (err) { case LDAP_SUCCESS: case LDAP_COMPARE_TRUE: lua_pushboolean(L, 1); break; case LDAP_COMPARE_FALSE: lua_pushboolean(L, 0); break; default: lua_pushnil(L); /* Either error message string may be NULL. */ msg2 = ldap_err2string(err); if (msg1 == NULL && msg2 == NULL) { ret = 1; } else if (msg1 != NULL && msg2 == NULL) { lua_pushstring(L, msg1); ret = 2; } else if (msg1 == NULL && msg2 != NULL) { lua_pushstring(L, msg2); ret = 2; } else { lua_pushstring(L, msg1); lua_pushliteral(L, " ("); lua_pushstring(L, msg2); lua_pushliteral(L, ")"); lua_concat(L, 4); ret = 2; } } ldap_memfree(mdn); ldap_memfree(msg1); return ret; } }
static gboolean on_connect_bind_completed (LDAPMessage *result, gpointer user_data) { GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); source_connect_closure *closure = g_simple_async_result_get_op_res_gpointer (res); SeahorseLDAPSource *self = SEAHORSE_LDAP_SOURCE (g_async_result_get_source_object (user_data)); LDAPServerInfo *sinfo; GError *error = NULL; char *message; int ldap_op; int code; int rc; g_return_val_if_fail (ldap_msgtype (result) == LDAP_RES_BIND, FALSE); /* The result of the bind operation */ rc = ldap_parse_result (closure->ldap, result, &code, NULL, &message, NULL, NULL, 0); g_return_val_if_fail (rc == LDAP_SUCCESS, FALSE); ldap_memfree (message); if (seahorse_ldap_source_propagate_error (self, rc, &error)) { g_simple_async_result_take_error (res, error); g_simple_async_result_complete_in_idle (res); return FALSE; /* don't call this callback again */ } /* Check if we need server info */ sinfo = get_ldap_server_info (self, FALSE); if (sinfo != NULL) { g_simple_async_result_complete_in_idle (res); seahorse_progress_end (closure->cancellable, res); return FALSE; /* don't call this callback again */ } /* Retrieve the server info */ rc = ldap_search_ext (closure->ldap, "cn=PGPServerInfo", LDAP_SCOPE_BASE, "(objectclass=*)", (char **)SERVER_ATTRIBUTES, 0, NULL, NULL, NULL, 0, &ldap_op); if (seahorse_ldap_source_propagate_error (self, rc, &error)) { g_simple_async_result_take_error (res, error); g_simple_async_result_complete_in_idle (res); return FALSE; /* don't call this callback again */ } else { GSource *gsource = seahorse_ldap_gsource_new (closure->ldap, ldap_op, closure->cancellable); g_source_set_callback (gsource, (GSourceFunc)on_connect_server_info_completed, g_object_ref (res), g_object_unref); g_source_attach (gsource, g_main_context_default ()); g_source_unref (gsource); } return FALSE; /* don't call this callback again */ }
/* deprecated */ int ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit ) { int rc, err; rc = ldap_parse_result( ld, r, &err, NULL, NULL, NULL, NULL, freeit ); return err != LDAP_SUCCESS ? err : rc; }
static gboolean on_search_search_completed (LDAPMessage *result, gpointer user_data) { GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); source_search_closure *closure = g_simple_async_result_get_op_res_gpointer (res); SeahorseLDAPSource *self = SEAHORSE_LDAP_SOURCE (g_async_result_get_source_object (user_data)); GError *error = NULL; char *message; int code; int type; int rc; type = ldap_msgtype (result); g_return_val_if_fail (type == LDAP_RES_SEARCH_ENTRY || type == LDAP_RES_SEARCH_RESULT, FALSE); /* An LDAP entry */ if (type == LDAP_RES_SEARCH_ENTRY) { g_debug ("Retrieved Key Entry"); #ifdef WITH_DEBUG dump_ldap_entry (closure->ldap, result); #endif search_parse_key_from_ldap_entry (self, closure->results, closure->ldap, result); return TRUE; /* keep calling this callback */ /* All entries done */ } else { rc = ldap_parse_result (closure->ldap, result, &code, NULL, &message, NULL, NULL, 0); g_return_val_if_fail (rc == LDAP_SUCCESS, FALSE); /* Error codes that we ignore */ switch (code) { case LDAP_SIZELIMIT_EXCEEDED: code = LDAP_SUCCESS; break; }; /* Failure */ if (code != LDAP_SUCCESS) g_simple_async_result_set_error (res, LDAP_ERROR_DOMAIN, code, "%s", message); else if (seahorse_ldap_source_propagate_error (self, code, &error)) g_simple_async_result_take_error (res, error); ldap_memfree (message); seahorse_progress_end (closure->cancellable, res); g_simple_async_result_complete (res); return FALSE; } }
static int ipa_ldap_extended_op(LDAP *ld, const char *reqoid, struct berval *control, LDAPControl ***srvctrl) { struct berval *retdata = NULL; LDAPMessage *res = NULL; char *retoid = NULL; struct timeval tv; char *err = NULL; int msgid; int ret, rc; ret = ldap_extended_operation(ld, reqoid, control, NULL, NULL, &msgid); if (ret != LDAP_SUCCESS) { fprintf(stderr, _("Operation failed: %s\n"), ldap_err2string(ret)); return ret; } /* wait max 100 secs for the answer */ tv.tv_sec = 100; tv.tv_usec = 0; ret = ldap_result(ld, msgid, 1, &tv, &res); if (ret == -1) { fprintf(stderr, _("Failed to get result: %s\n"), ldap_err2string(ret)); goto done; } else if (res == NULL) { fprintf(stderr, _("Timeout exceeded.")); goto done; } ret = ldap_parse_extended_result(ld, res, &retoid, &retdata, 0); if (ret != LDAP_SUCCESS) { fprintf(stderr, _("Failed to parse extended result: %s\n"), ldap_err2string(ret)); goto done; } ret = ldap_parse_result(ld, res, &rc, NULL, &err, NULL, srvctrl, 0); if (ret != LDAP_SUCCESS || rc != LDAP_SUCCESS) { fprintf(stderr, _("Failed to parse result: %s\n"), err ? err : ldap_err2string(ret)); if (ret == LDAP_SUCCESS) ret = rc; goto done; } done: if (err) ldap_memfree(err); if (res) ldap_msgfree(res); return ret; }
static gboolean on_connect_server_info_completed (LDAPMessage *result, gpointer user_data) { GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data); source_connect_closure *closure = g_simple_async_result_get_op_res_gpointer (res); SeahorseLDAPSource *self = SEAHORSE_LDAP_SOURCE (g_async_result_get_source_object (user_data)); LDAPServerInfo *sinfo; char *message; int code; int type; int rc; type = ldap_msgtype (result); g_return_val_if_fail (type == LDAP_RES_SEARCH_ENTRY || type == LDAP_RES_SEARCH_RESULT, FALSE); /* If we have results then fill in the server info */ if (type == LDAP_RES_SEARCH_ENTRY) { g_debug ("Server Info Result"); #ifdef WITH_DEBUG dump_ldap_entry (closure->ldap, result); #endif /* NOTE: When adding attributes here make sure to add them to kServerAttributes */ sinfo = g_new0 (LDAPServerInfo, 1); sinfo->version = get_int_attribute (closure->ldap, result, "version"); sinfo->base_dn = get_string_attribute (closure->ldap, result, "basekeyspacedn"); if (!sinfo->base_dn) sinfo->base_dn = get_string_attribute (closure->ldap, result, "pgpbasekeyspacedn"); sinfo->key_attr = g_strdup (sinfo->version > 1 ? "pgpkeyv2" : "pgpkey"); set_ldap_server_info (self, sinfo); return TRUE; /* callback again */ } else { rc = ldap_parse_result (closure->ldap, result, &code, NULL, &message, NULL, NULL, 0); g_return_val_if_fail (rc == LDAP_SUCCESS, FALSE); if (code != LDAP_SUCCESS) g_warning ("operation to get LDAP server info failed: %s", message); ldap_memfree (message); g_simple_async_result_complete_in_idle (res); seahorse_progress_end (closure->cancellable, res); return FALSE; /* don't callback again */ } }
static int nsldapi_sasl_bind_s( LDAP *ld, const char *dn, const char *mechanism, const struct berval *cred, LDAPControl **serverctrls, LDAPControl **clientctrls, struct berval **servercredp, LDAPControl ***responsectrls ) { int err, msgid; LDAPMessage *result; LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_sasl_bind_s\n", 0, 0, 0 ); if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { return( LDAP_PARAM_ERROR ); } if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); return( LDAP_NOT_SUPPORTED ); } if ( ( err = ldap_sasl_bind( ld, dn, mechanism, cred, serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS ) return( err ); if ( ldap_result( ld, msgid, 1, (struct timeval *) 0, &result ) == -1 ) return( LDAP_GET_LDERRNO( ld, NULL, NULL ) ); /* Get the controls sent by the server if requested */ if ( responsectrls ) { if ( ( err = ldap_parse_result( ld, result, &err, NULL, NULL, NULL, responsectrls, 0 )) != LDAP_SUCCESS ) return( err ); } err = ldap_parse_sasl_bind_result( ld, result, servercredp, 0 ); if (err != LDAP_SUCCESS && err != LDAP_SASL_BIND_IN_PROGRESS) { ldap_msgfree( result ); return( err ); } return( ldap_result2error( ld, result, 1 ) ); }
/* ** Get the result message of an operation. ** #1 upvalue == connection ** #2 upvalue == msgid ** #3 upvalue == result code of the message (ADD, DEL etc.) to be received. */ static int result_message (lua_State *L) { struct timeval *timeout = NULL; /* ??? function parameter ??? */ LDAPMessage *res; int rc; conn_data *conn = (conn_data *)lua_touserdata (L, lua_upvalueindex (1)); int msgid = (int)lua_tonumber (L, lua_upvalueindex (2)); /*int res_code = (int)lua_tonumber (L, lua_upvalueindex (3));*/ luaL_argcheck (L, conn->ld, 1, LUALDAP_PREFIX"LDAP connection is closed"); rc = ldap_result (conn->ld, msgid, LDAP_MSG_ONE, timeout, &res); if (rc == 0) return faildirect (L, LUALDAP_PREFIX"result timeout expired"); else if (rc < 0) { ldap_msgfree (res); return faildirect (L, LUALDAP_PREFIX"result error"); } else { int err, ret = 1; char *mdn, *msg; rc = ldap_parse_result (conn->ld, res, &err, &mdn, &msg, NULL, NULL, 1); if (rc != LDAP_SUCCESS) return faildirect (L, ldap_err2string (rc)); switch (err) { case LDAP_SUCCESS: case LDAP_COMPARE_TRUE: lua_pushboolean (L, 1); break; case LDAP_COMPARE_FALSE: lua_pushboolean (L, 0); break; default: lua_pushnil (L); lua_pushliteral (L, LUALDAP_PREFIX); lua_pushstring (L, msg); lua_pushliteral (L, " "); lua_pushstring (L, ldap_err2string(err)); lua_concat (L, 4); ret = 2; } ldap_memfree (mdn); ldap_memfree (msg); return ret; } }
/*********************************************************************** * ldap_result2error (WLDAP32.@) * * Parse an LDAP message and return the error obtained from it. * * PARAMS * ld [I] Pointer to an LDAP context. * res [I] Pointer to an LDAPMessage structure. * free [I] Ask for the LDAPMessage structure to be freed. * * RETURNS * Success: LDAP_SUCCESS * Failure: An LDAP error code. * * NOTES * If not asked for, use ldap_msgfree to free the LDAPMessage. */ ULONG CDECL WLDAP32_ldap_result2error( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *res, ULONG free ) { ULONG ret = LDAP_NOT_SUPPORTED; #ifdef HAVE_LDAP int error; TRACE( "(%p, %p, 0x%08lx)\n", ld, res, free ); if (!ld || !res) return ~0UL; ret = ldap_parse_result( ld, res, &error, NULL, NULL, NULL, NULL, free ); if (ret == LDAP_SUCCESS) ret = error; else ret = ~0UL; #endif return ret; }
static void signal_ldap_error(LDAP * ld, LDAPMessage * res, int ldap_err) { if (ldap_err <= 0) { #if defined HAVE_LDAP_PARSE_RESULT int err; ldap_err = ldap_parse_result(ld, res, &err, NULL, NULL, NULL, NULL, 0); if (ldap_err == LDAP_SUCCESS) ldap_err = err; #elif defined HAVE_LDAP_GET_LDERRNO ldap_err = ldap_get_lderrno(ld, NULL, NULL); #elif defined HAVE_LDAP_RESULT2ERROR ldap_err = ldap_result2error(ld, res, 0); #else ldap_err = ld->ld_errno; #endif } signal_simple_error("LDAP error", build_string(ldap_err2string(ldap_err))); }
/// connects and binds to LDAP server /// @param[in] ld refernce to LDAP socket data /// @param[in] cnf reference to common configuration struct int ldaputils_search(LDAP * ld, LdapUtilsConfig * cnf, LDAPMessage ** resp) { int rc; int err; int msgid; if ((err = ldap_search_ext(ld, cnf->basedn, cnf->scope, cnf->filter, cnf->attrs, 0, NULL, NULL, NULL, -1, &msgid))) { fprintf(stderr, "%s: ldap_search_ext_s(): %s\n", PROGRAM_NAME, ldap_err2string(err)); ldap_unbind_ext_s(ld, NULL, NULL); return(-1); }; switch((err = ldap_result(ld, msgid, LDAP_MSG_ALL, NULL, resp))) { case 0: break; case -1: fprintf(stderr, "%s: ldap_result(): %s\n", PROGRAM_NAME, ldap_err2string(err)); ldap_unbind_ext_s(ld, NULL, NULL); return(-1); default: break; }; rc = ldap_parse_result(ld, *resp, &err, NULL, NULL, NULL, NULL, 0); if (rc != LDAP_SUCCESS) { fprintf(stderr, "%s: ldap_parse_result(): %s\n", PROGRAM_NAME, ldap_err2string(rc)); ldap_unbind_ext_s(ld, NULL, NULL); return(-1); }; if (err != LDAP_SUCCESS) { fprintf(stderr, "%s: ldap_parse_result(): %s\n", PROGRAM_NAME, ldap_err2string(err)); ldap_unbind_ext_s(ld, NULL, NULL); return(-1); }; return(0); }
static int verify_op_success(LDAP *l, char *reason, LDAPMessage *messages) { int rc, erc; char *errmsg; rc = ldap_parse_result(l, messages, &erc, NULL, &errmsg, NULL, NULL, 0); if (rc != LDAP_SUCCESS) { prtmsg("Failed to %s (parse_result): %s", reason, ldap_err2string(rc)); return 0; } if (erc != LDAP_SUCCESS) { prtmsg("Failed to %s (server response): %s%s%s", reason, ldap_err2string(erc), (errmsg?", ":""), (errmsg?errmsg:"")); if (errmsg) ldap_memfree(errmsg); return 0; } if (errmsg) ldap_memfree(errmsg); return 1; }
/* wrappers to some depricated functions */ static void ldaplookup_parse_result ( LDAP *ld, LDAPMessage *res ) { static const int freeit = 0; int result; #ifdef HAVE_LDAP_PARSE_RESULT int ret; char *matcheddn; char *errmsg; ret = ldap_parse_result(ld, res, &result, &matcheddn, &errmsg, NULL, NULL, freeit); if (ret == LDAP_SUCCESS) { if (errmsg) ERR_add_error_data(1, errmsg); } if (matcheddn) ldap_memfree(matcheddn); if (errmsg) ldap_memfree(errmsg); #else result = ldap_result2error(ld, res, freeit); openssl_add_ldap_error(result); #endif }
int ldap_compare_ext_s(LDAP *ld, char *dn, char *attr, struct berval *bvalue, LDAPControl ** serverctrls, LDAPControl **clientctrls) { int msgid, retcode = LDAP_SUCCESS; LDAPMessage *res; if ( (retcode = ldap_compare_ext( ld, dn, attr, bvalue, serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS ) return( retcode ); if ( ldap_result( ld, msgid, 1, (struct timeval *) NULL, &res ) == -1 ) return( ld->ld_errno ); #ifdef _REENTRANT LOCK_LDAP(ld); #endif retcode = ldap_parse_result( ld, res, &ld->ld_errno, &ld->ld_matched, &ld->ld_error, &ld->ld_referrals, &ld->ld_ret_ctrls, 1); if (retcode == LDAP_SUCCESS) retcode = ld->ld_errno; #ifdef _REENTRANT UNLOCK_LDAP(ld); #endif return (retcode); }
extern "C" std::string getRecipient(void * vh, Source * source) { ldap_handle * h = (ldap_handle *) vh; int msgtype; int code; int rc; struct berval bv; std::string result; if (!h) return ""; for (;;) { if (h->value && h->value->bv_val) { result = std::string(h->value->bv_val, h->value->bv_len); h->value++; if (result.length() > 5 && !strncasecmp(result.c_str(), "smtp:", 5)) result = result.substr(5); if (result.find_first_not_of(mailchars) != std::string::npos) continue; return result; } if (h->ber) { rc = ldap_get_attribute_ber(h->ldap, h->msg, h->ber, &bv, &h->values); h->value = h->values; if (rc == LDAP_SUCCESS && bv.bv_val) continue; } h->release_message(); rc = ldap_result(h->ldap, LDAP_RES_ANY, LDAP_MSG_ONE, NULL, &h->msg); if (!h->msg) throw ldap_error(rc); msgtype = ldap_msgtype(h->msg); switch (msgtype) { case LDAP_RES_SEARCH_RESULT: rc = ldap_parse_result(h->ldap, h->msg, &code, NULL, NULL, NULL, NULL, 0); if (rc != LDAP_SUCCESS) throw ldap_error(rc); if (code != LDAP_SUCCESS) throw ldap_error(code); return ""; case LDAP_RES_SEARCH_ENTRY: break; default: continue; } rc = ldap_get_dn_ber(h->ldap, h->msg, &h->ber, &bv); if (rc != LDAP_SUCCESS) throw ldap_error(rc); } return ""; }
static int domodrdn( LDAP *ld, char *dn, char *rdn, char *newSuperior, int remove ) /* flag: remove old RDN */ { int rc, code, id; char *matcheddn=NULL, *text=NULL, **refs=NULL; LDAPMessage *res; if ( verbose ) { printf( "Renaming \"%s\"\n", dn ); printf( "\tnew rdn=\"%s\" (%s old rdn)\n", rdn, remove ? "delete" : "keep" ); if( newSuperior != NULL ) { printf("\tnew parent=\"%s\"\n", newSuperior); } } if( not ) return LDAP_SUCCESS; rc = ldap_rename( ld, dn, rdn, newSuperior, remove, NULL, NULL, &id ); if ( rc != LDAP_SUCCESS ) { fprintf( stderr, "%s: ldap_rename: %s (%d)\n", prog, ldap_err2string( rc ), rc ); return rc; } rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res ); if ( rc < 0 ) { ldap_perror( ld, "ldapmodrdn: ldap_result" ); return rc; } rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 1 ); if( rc != LDAP_SUCCESS ) { fprintf( stderr, "%s: ldap_parse_result: %s (%d)\n", prog, ldap_err2string( rc ), rc ); return rc; } if( verbose || code != LDAP_SUCCESS || (matcheddn && *matcheddn) || (text && *text) || (refs && *refs) ) { printf( "Rename Result: %s (%d)\n", ldap_err2string( code ), code ); if( text && *text ) { printf( "Additional info: %s\n", text ); } if( matcheddn && *matcheddn ) { printf( "Matched DN: %s\n", matcheddn ); } if( refs ) { int i; for( i=0; refs[i]; i++ ) { printf("Referral: %s\n", refs[i] ); } } } ber_memfree( text ); ber_memfree( matcheddn ); ber_memvfree( (void **) refs ); return code; }
/* * handle the LDAP_RES_SEARCH_RESULT response */ static int ldap_sync_search_result( ldap_sync_t *ls, LDAPMessage *res ) { int err; char *matched = NULL, *msg = NULL; LDAPControl **ctrls = NULL; int rc; int refreshDeletes = -1; #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\tgot LDAP_RES_SEARCH_RESULT\n" ); #endif /* LDAP_SYNC_TRACE */ assert( ls != NULL ); assert( res != NULL ); /* should not happen in refreshAndPersist... */ rc = ldap_parse_result( ls->ls_ld, res, &err, &matched, &msg, NULL, &ctrls, 0 ); #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\tldap_parse_result(%d, \"%s\", \"%s\") == %d\n", err, matched ? matched : "", msg ? msg : "", rc ); #endif /* LDAP_SYNC_TRACE */ if ( rc == LDAP_SUCCESS ) { rc = err; } ls->ls_refreshPhase = LDAP_SYNC_CAPI_DONE; switch ( rc ) { case LDAP_SUCCESS: { int i; BerElement *ber = NULL; ber_len_t len; struct berval cookie = { 0 }; rc = LDAP_OTHER; /* deal with control; then fallthru to handler */ if ( ctrls == NULL ) { goto done; } /* lookup the sync state control */ for ( i = 0; ctrls[ i ] != NULL; i++ ) { if ( strcmp( ctrls[ i ]->ldctl_oid, LDAP_CONTROL_SYNC_DONE ) == 0 ) { break; } } /* control must be present; there might be other... */ if ( ctrls[ i ] == NULL ) { goto done; } /* extract data */ ber = ber_init( &ctrls[ i ]->ldctl_value ); if ( ber == NULL ) { goto done; } if ( ber_scanf( ber, "{" /*"}"*/) == LBER_ERROR ) { goto ber_done; } if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) { if ( ber_scanf( ber, "m", &cookie ) == LBER_ERROR ) { goto ber_done; } if ( cookie.bv_val != NULL ) { ber_bvreplace( &ls->ls_cookie, &cookie ); } #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tgot cookie=%s\n", cookie.bv_val ? cookie.bv_val : "(null)" ); #endif /* LDAP_SYNC_TRACE */ } refreshDeletes = 0; if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES ) { if ( ber_scanf( ber, "b", &refreshDeletes ) == LBER_ERROR ) { goto ber_done; } if ( refreshDeletes ) { refreshDeletes = 1; } } if ( ber_scanf( ber, /*"{"*/ "}" ) != LBER_ERROR ) { rc = LDAP_SUCCESS; } ber_done:; ber_free( ber, 1 ); if ( rc != LDAP_SUCCESS ) { break; } #ifdef LDAP_SYNC_TRACE fprintf( stderr, "\t\tgot refreshDeletes=%s\n", refreshDeletes ? "TRUE" : "FALSE" ); #endif /* LDAP_SYNC_TRACE */ /* FIXME: what should we do with the refreshDelete? */ switch ( refreshDeletes ) { case 0: ls->ls_refreshPhase = LDAP_SYNC_CAPI_PRESENTS; break; default: ls->ls_refreshPhase = LDAP_SYNC_CAPI_DELETES; break; } } /* fallthru */ case LDAP_SYNC_REFRESH_REQUIRED: /* TODO: check for Sync Done Control */ /* FIXME: perhaps the handler should be called * also in case of failure; we'll deal with this * later when implementing refreshOnly */ if ( ls->ls_search_result ) { err = ls->ls_search_result( ls, res, refreshDeletes ); } break; } done:; if ( matched != NULL ) { ldap_memfree( matched ); } if ( msg != NULL ) { ldap_memfree( msg ); } if ( ctrls != NULL ) { ldap_controls_free( ctrls ); } ls->ls_refreshPhase = LDAP_SYNC_CAPI_DONE; return rc; }
/** * Initializes a message. * * @param aConnection The nsLDAPConnection this message is on * @param aMsgHandle The native LDAPMessage to be wrapped. * * @exception NS_ERROR_ILLEGAL_VALUE null pointer passed in * @exception NS_ERROR_UNEXPECTED internal err; shouldn't happen * @exception NS_ERROR_LDAP_DECODING_ERROR problem during BER decoding * @exception NS_ERROR_OUT_OF_MEMORY ran out of memory */ nsresult nsLDAPMessage::Init(nsILDAPConnection *aConnection, LDAPMessage *aMsgHandle) { int parseResult; if (!aConnection || !aMsgHandle) { NS_WARNING("Null pointer passed in to nsLDAPMessage::Init()"); return NS_ERROR_ILLEGAL_VALUE; } // initialize the appropriate member vars // mConnection = aConnection; mMsgHandle = aMsgHandle; // cache the connection handle. we're violating the XPCOM type-system // here since we're a friend of the connection class and in the // same module. // mConnectionHandle = static_cast<nsLDAPConnection *>(aConnection)->mConnectionHandle; // do any useful message parsing // const int msgType = ldap_msgtype(mMsgHandle); if ( msgType == -1) { NS_ERROR("nsLDAPMessage::Init(): ldap_msgtype() failed"); return NS_ERROR_UNEXPECTED; } switch (msgType) { case LDAP_RES_SEARCH_REFERENCE: // XXX should do something here? break; case LDAP_RES_SEARCH_ENTRY: // nothing to do here break; case LDAP_RES_EXTENDED: // XXX should do something here? break; case LDAP_RES_BIND: case LDAP_RES_SEARCH_RESULT: case LDAP_RES_MODIFY: case LDAP_RES_ADD: case LDAP_RES_DELETE: case LDAP_RES_MODRDN: case LDAP_RES_COMPARE: parseResult = ldap_parse_result(mConnectionHandle, mMsgHandle, &mErrorCode, &mMatchedDn, &mErrorMessage,&mReferrals, &mServerControls, 0); switch (parseResult) { case LDAP_SUCCESS: // we're good break; case LDAP_DECODING_ERROR: NS_WARNING("nsLDAPMessage::Init(): ldap_parse_result() hit a " "decoding error"); return NS_ERROR_LDAP_DECODING_ERROR; case LDAP_NO_MEMORY: NS_WARNING("nsLDAPMessage::Init(): ldap_parse_result() ran out " "of memory"); return NS_ERROR_OUT_OF_MEMORY; case LDAP_PARAM_ERROR: case LDAP_MORE_RESULTS_TO_RETURN: case LDAP_NO_RESULTS_RETURNED: default: NS_ERROR("nsLDAPMessage::Init(): ldap_parse_result returned " "unexpected return code"); return NS_ERROR_UNEXPECTED; } break; default: NS_ERROR("nsLDAPMessage::Init(): unexpected message type"); return NS_ERROR_UNEXPECTED; } return NS_OK; }
static int _mu_ldap_bind (LDAP *ld) { int msgid, err, rc; LDAPMessage *result; LDAPControl **ctrls; char msgbuf[256]; char *matched = NULL; char *info = NULL; char **refs = NULL; static struct berval passwd; passwd.bv_val = ldap_param.passwd; passwd.bv_len = passwd.bv_val ? strlen (passwd.bv_val) : 0; msgbuf[0] = 0; rc = ldap_sasl_bind (ld, ldap_param.binddn, LDAP_SASL_SIMPLE, &passwd, NULL, NULL, &msgid); if (msgid == -1) { mu_error ("ldap_sasl_bind(SIMPLE) failed: %s", ldap_err2string (rc)); return 1; } if (ldap_result (ld, msgid, LDAP_MSG_ALL, NULL, &result ) == -1) { mu_error ("ldap_result failed"); return 1; } rc = ldap_parse_result (ld, result, &err, &matched, &info, &refs, &ctrls, 1); if (rc != LDAP_SUCCESS) { mu_error ("ldap_parse_result failed: %s", ldap_err2string (rc)); return 1; } if (ctrls) ldap_controls_free (ctrls); if (err != LDAP_SUCCESS || msgbuf[0] || (matched && matched[0]) || (info && info[0]) || refs) { /* FIXME: Use debug output for that */ mu_error ("ldap_bind: %s (%d)%s", ldap_err2string (err), err, msgbuf); if (matched && *matched) mu_error ("matched DN: %s", matched); if (info && *info) mu_error ("additional info: %s", info); if (refs && *refs) { int i; mu_error ("referrals:"); for (i = 0; refs[i]; i++) mu_error ("%s", refs[i]); } } if (matched) ber_memfree (matched); if (info) ber_memfree (info); if (refs) ber_memvfree ((void **)refs); return err == LDAP_SUCCESS ? 0 : MU_ERR_FAILURE; }
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; }
meta_search_candidate_t asyncmeta_dobind_result( a_metaconn_t *mc, int candidate, SlapReply *bind_result, LDAPMessage *res ) { a_metainfo_t *mi = mc->mc_info; a_metatarget_t *mt = mi->mi_targets[ candidate ]; a_metasingleconn_t *msc = &mc->mc_conns[ candidate ]; meta_search_candidate_t retcode = META_SEARCH_NOT_CANDIDATE; int rc; assert( msc->msc_ldr != NULL ); if ( mi->mi_idle_timeout != 0 ) { asyncmeta_set_msc_time(msc); } if ( LogTest( asyncmeta_debug ) ) { char time_buf[ SLAP_TEXT_BUFLEN ]; asyncmeta_get_timestamp(time_buf); Debug( asyncmeta_debug, "[%x] [%s] asyncmeta_dobind_result msc: %p, " "msc->msc_binding_time: %x, msc->msc_flags:%x\n ", (unsigned int)slap_get_time(), time_buf, msc, (unsigned int)msc->msc_binding_time, msc->msc_mscflags ); } /* FIXME: matched? referrals? response controls? */ rc = ldap_parse_result( msc->msc_ldr, res, &(bind_result->sr_err), (char **)&(bind_result->sr_matched), (char **)&(bind_result->sr_text), NULL, NULL, 0 ); if ( LogTest( asyncmeta_debug ) ) { char time_buf[ SLAP_TEXT_BUFLEN ]; asyncmeta_get_timestamp(time_buf); Debug( asyncmeta_debug, "[%s] asyncmeta_dobind_result error=%d msc: %p\n", time_buf,bind_result->sr_err, msc ); } if ( rc != LDAP_SUCCESS ) { bind_result->sr_err = rc; } rc = slap_map_api2result( bind_result ); LDAP_BACK_CONN_BINDING_CLEAR( msc ); if ( rc != LDAP_SUCCESS ) { bind_result->sr_err = rc; } else { /* FIXME: check if bound as idassert authcDN! */ if ( BER_BVISNULL( &msc->msc_bound_ndn ) || BER_BVISEMPTY( &msc->msc_bound_ndn ) ) { LDAP_BACK_CONN_ISANON_SET( msc ); if ( LogTest( asyncmeta_debug ) ) { char time_buf[ SLAP_TEXT_BUFLEN ]; asyncmeta_get_timestamp(time_buf); Debug( asyncmeta_debug, "[%s] asyncmeta_dobind_result anonymous msc: %p\n", time_buf, msc ); } } else { if ( META_BACK_TGT_SAVECRED( mt ) && !BER_BVISNULL( &msc->msc_cred ) && !BER_BVISEMPTY( &msc->msc_cred ) ) { ldap_set_rebind_proc( msc->msc_ldr, mt->mt_rebind_f, msc ); } if ( LogTest( asyncmeta_debug ) ) { char time_buf[ SLAP_TEXT_BUFLEN ]; asyncmeta_get_timestamp(time_buf); Debug( asyncmeta_debug, "[%s] asyncmeta_dobind_result success msc: %p\n", time_buf, msc ); } LDAP_BACK_CONN_ISBOUND_SET( msc ); } retcode = META_SEARCH_CANDIDATE; } return retcode; }
/* * Get the number of times an object has been referred to in a realm. This is * needed to find out if deleting the attribute will cause dangling links. * * An LDAP handle may be optionally specified to prevent race condition - there * are a limited number of LDAP handles. */ krb5_error_code krb5_ldap_get_reference_count(krb5_context context, char *dn, char *refattr, int *count, LDAP *ld) { int n, st, tempst, gothandle = 0; unsigned int i, ntrees = 0; char *refcntattr[2]; char *filter = NULL, *corrected = NULL, **subtree = NULL; kdb5_dal_handle *dal_handle = NULL; krb5_ldap_context *ldap_context = NULL; krb5_ldap_server_handle *ldap_server_handle = NULL; LDAPMessage *result = NULL; if (dn == NULL || refattr == NULL) { st = EINVAL; goto cleanup; } SETUP_CONTEXT(); if (ld == NULL) { GET_HANDLE(); gothandle = 1; } refcntattr[0] = refattr; refcntattr[1] = NULL; corrected = ldap_filter_correct(dn); if (corrected == NULL) { st = ENOMEM; goto cleanup; } if (asprintf(&filter, "%s=%s", refattr, corrected) < 0) { filter = NULL; st = ENOMEM; goto cleanup; } st = krb5_get_subtree_info(ldap_context, &subtree, &ntrees); if (st) goto cleanup; for (i = 0, *count = 0; i < ntrees; i++) { LDAP_SEARCH(subtree[i], LDAP_SCOPE_SUBTREE, filter, refcntattr); n = ldap_count_entries(ld, result); if (n == -1) { int ret, errcode = 0; ret = ldap_parse_result(ld, result, &errcode, NULL, NULL, NULL, NULL, 0); if (ret != LDAP_SUCCESS) errcode = ret; st = translate_ldap_error(errcode, OP_SEARCH); goto cleanup; } ldap_msgfree(result); result = NULL; *count += n; } cleanup: free(filter); ldap_msgfree(result); for (i = 0; i < ntrees; i++) free(subtree[i]); free(subtree); free(corrected); if (gothandle) krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); return st; }
/* * always protected by conn_mutex * optionally protected by req_mutex and res_mutex */ LDAPConn * ldap_new_connection( LDAP *ld, LDAPURLDesc **srvlist, int use_ldsb, int connect, LDAPreqinfo *bind, int m_req, int m_res ) { LDAPConn *lc; int async = 0; LDAP_ASSERT_MUTEX_OWNER( &ld->ld_conn_mutex ); Debug( LDAP_DEBUG_TRACE, "ldap_new_connection %d %d %d\n", use_ldsb, connect, (bind != NULL) ); /* * make a new LDAP server connection * XXX open connection synchronously for now */ lc = (LDAPConn *)LDAP_CALLOC( 1, sizeof( LDAPConn ) ); if ( lc == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; return( NULL ); } if ( use_ldsb ) { assert( ld->ld_sb != NULL ); lc->lconn_sb = ld->ld_sb; } else { lc->lconn_sb = ber_sockbuf_alloc(); if ( lc->lconn_sb == NULL ) { LDAP_FREE( (char *)lc ); ld->ld_errno = LDAP_NO_MEMORY; return( NULL ); } } if ( connect ) { LDAPURLDesc **srvp, *srv = NULL; async = LDAP_BOOL_GET( &ld->ld_options, LDAP_BOOL_CONNECT_ASYNC ); for ( srvp = srvlist; *srvp != NULL; srvp = &(*srvp)->lud_next ) { int rc; rc = ldap_int_open_connection( ld, lc, *srvp, async ); if ( rc != -1 ) { srv = *srvp; if ( ld->ld_urllist_proc && ( !async || rc != -2 ) ) { ld->ld_urllist_proc( ld, srvlist, srvp, ld->ld_urllist_params ); } break; } } if ( srv == NULL ) { if ( !use_ldsb ) { ber_sockbuf_free( lc->lconn_sb ); } LDAP_FREE( (char *)lc ); ld->ld_errno = LDAP_SERVER_DOWN; return( NULL ); } lc->lconn_server = ldap_url_dup( srv ); } lc->lconn_status = async ? LDAP_CONNST_CONNECTING : LDAP_CONNST_CONNECTED; lc->lconn_next = ld->ld_conns; ld->ld_conns = lc; if ( connect ) { #ifdef HAVE_TLS if ( lc->lconn_server->lud_exts ) { int rc, ext = find_tls_ext( lc->lconn_server ); if ( ext ) { LDAPConn *savedefconn; savedefconn = ld->ld_defconn; ++lc->lconn_refcnt; /* avoid premature free */ ld->ld_defconn = lc; LDAP_REQ_UNLOCK_IF(m_req); LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); LDAP_RES_UNLOCK_IF(m_res); rc = ldap_start_tls_s( ld, NULL, NULL ); LDAP_RES_LOCK_IF(m_res); LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); LDAP_REQ_LOCK_IF(m_req); ld->ld_defconn = savedefconn; --lc->lconn_refcnt; if ( rc != LDAP_SUCCESS && ext == 2 ) { ldap_free_connection( ld, lc, 1, 0 ); return NULL; } } } #endif } if ( bind != NULL ) { int err = 0; LDAPConn *savedefconn; /* Set flag to prevent additional referrals * from being processed on this * connection until the bind has completed */ lc->lconn_rebind_inprogress = 1; /* V3 rebind function */ if ( ld->ld_rebind_proc != NULL) { LDAPURLDesc *srvfunc; srvfunc = ldap_url_dup( *srvlist ); if ( srvfunc == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; err = -1; } else { savedefconn = ld->ld_defconn; ++lc->lconn_refcnt; /* avoid premature free */ ld->ld_defconn = lc; Debug( LDAP_DEBUG_TRACE, "Call application rebind_proc\n", 0, 0, 0); LDAP_REQ_UNLOCK_IF(m_req); LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); LDAP_RES_UNLOCK_IF(m_res); err = (*ld->ld_rebind_proc)( ld, bind->ri_url, bind->ri_request, bind->ri_msgid, ld->ld_rebind_params ); LDAP_RES_LOCK_IF(m_res); LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); LDAP_REQ_LOCK_IF(m_req); ld->ld_defconn = savedefconn; --lc->lconn_refcnt; if ( err != 0 ) { err = -1; ldap_free_connection( ld, lc, 1, 0 ); lc = NULL; } ldap_free_urldesc( srvfunc ); } } else { int msgid, rc; struct berval passwd = BER_BVNULL; savedefconn = ld->ld_defconn; ++lc->lconn_refcnt; /* avoid premature free */ ld->ld_defconn = lc; Debug( LDAP_DEBUG_TRACE, "anonymous rebind via ldap_sasl_bind(\"\")\n", 0, 0, 0); LDAP_REQ_UNLOCK_IF(m_req); LDAP_MUTEX_UNLOCK( &ld->ld_conn_mutex ); LDAP_RES_UNLOCK_IF(m_res); rc = ldap_sasl_bind( ld, "", LDAP_SASL_SIMPLE, &passwd, NULL, NULL, &msgid ); if ( rc != LDAP_SUCCESS ) { err = -1; } else { for ( err = 1; err > 0; ) { struct timeval tv = { 0, 100000 }; LDAPMessage *res = NULL; switch ( ldap_result( ld, msgid, LDAP_MSG_ALL, &tv, &res ) ) { case -1: err = -1; break; case 0: #ifdef LDAP_R_COMPILE ldap_pvt_thread_yield(); #endif break; case LDAP_RES_BIND: rc = ldap_parse_result( ld, res, &err, NULL, NULL, NULL, NULL, 1 ); if ( rc != LDAP_SUCCESS ) { err = -1; } else if ( err != LDAP_SUCCESS ) { err = -1; } /* else err == LDAP_SUCCESS == 0 */ break; default: Debug( LDAP_DEBUG_TRACE, "ldap_new_connection %p: " "unexpected response %d " "from BIND request id=%d\n", (void *) ld, ldap_msgtype( res ), msgid ); err = -1; break; } } } LDAP_RES_LOCK_IF(m_res); LDAP_MUTEX_LOCK( &ld->ld_conn_mutex ); LDAP_REQ_LOCK_IF(m_req); ld->ld_defconn = savedefconn; --lc->lconn_refcnt; if ( err != 0 ) { ldap_free_connection( ld, lc, 1, 0 ); lc = NULL; } } if ( lc != NULL ) lc->lconn_rebind_inprogress = 0; } return( lc ); }
static int ldap_back_exop_passwd( Operation *op, SlapReply *rs, ldapconn_t **lcp ) { ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private; ldapconn_t *lc = *lcp; req_pwdexop_s *qpw = &op->oq_pwdexop; LDAPMessage *res; ber_int_t msgid; int rc, isproxy, freedn = 0; int do_retry = 1; char *text = NULL; struct berval dn = op->o_req_dn, ndn = op->o_req_ndn; assert( lc != NULL ); assert( rs->sr_ctrls == NULL ); if ( BER_BVISNULL( &ndn ) && op->ore_reqdata != NULL ) { /* NOTE: most of this code is mutated * from slap_passwd_parse(); * But here we only need * the first berval... */ ber_tag_t tag; ber_len_t len = -1; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; struct berval tmpid = BER_BVNULL; if ( op->ore_reqdata->bv_len == 0 ) { return LDAP_PROTOCOL_ERROR; } /* ber_init2 uses reqdata directly, doesn't allocate new buffers */ ber_init2( ber, op->ore_reqdata, 0 ); tag = ber_scanf( ber, "{" /*}*/ ); if ( tag == LBER_ERROR ) { return LDAP_PROTOCOL_ERROR; } tag = ber_peek_tag( ber, &len ); if ( tag == LDAP_TAG_EXOP_MODIFY_PASSWD_ID ) { tag = ber_get_stringbv( ber, &tmpid, LBER_BV_NOTERM ); if ( tag == LBER_ERROR ) { return LDAP_PROTOCOL_ERROR; } } if ( !BER_BVISEMPTY( &tmpid ) ) { char idNull = tmpid.bv_val[tmpid.bv_len]; tmpid.bv_val[tmpid.bv_len] = '\0'; rs->sr_err = dnPrettyNormal( NULL, &tmpid, &dn, &ndn, op->o_tmpmemctx ); tmpid.bv_val[tmpid.bv_len] = idNull; if ( rs->sr_err != LDAP_SUCCESS ) { /* should have been successfully parsed earlier! */ return rs->sr_err; } freedn = 1; } else { dn = op->o_dn; ndn = op->o_ndn; } } isproxy = ber_bvcmp( &ndn, &op->o_ndn ); Debug( LDAP_DEBUG_ARGS, "==> ldap_back_exop_passwd(\"%s\")%s\n", dn.bv_val, isproxy ? " (proxy)" : "", 0 ); retry: rc = ldap_passwd( lc->lc_ld, &dn, qpw->rs_old.bv_val ? &qpw->rs_old : NULL, qpw->rs_new.bv_val ? &qpw->rs_new : NULL, op->o_ctrls, NULL, &msgid ); if ( rc == LDAP_SUCCESS ) { /* TODO: set timeout? */ /* by now, make sure no timeout is used (ITS#6282) */ struct timeval tv = { -1, 0 }; if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, &tv, &res ) == -1 ) { ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, &rc ); rs->sr_err = rc; } else { /* only touch when activity actually took place... */ if ( li->li_idle_timeout ) { lc->lc_time = op->o_time; } /* sigh. parse twice, because parse_passwd * doesn't give us the err / match / msg info. */ rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err, (char **)&rs->sr_matched, &text, NULL, &rs->sr_ctrls, 0 ); if ( rc == LDAP_SUCCESS ) { if ( rs->sr_err == LDAP_SUCCESS ) { struct berval newpw; /* this never happens because * the frontend is generating * the new password, so when * the passwd exop is proxied, * it never delegates password * generation to the remote server */ rc = ldap_parse_passwd( lc->lc_ld, res, &newpw ); if ( rc == LDAP_SUCCESS && !BER_BVISNULL( &newpw ) ) { rs->sr_type = REP_EXTENDED; rs->sr_rspdata = slap_passwd_return( &newpw ); free( newpw.bv_val ); } } else { rc = rs->sr_err; } } ldap_msgfree( res ); } } if ( rc != LDAP_SUCCESS ) { rs->sr_err = slap_map_api2result( rs ); if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { do_retry = 0; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { goto retry; } } if ( LDAP_BACK_QUARANTINE( li ) ) { ldap_back_quarantine( op, rs ); } if ( text ) rs->sr_text = text; send_ldap_extended( op, rs ); /* otherwise frontend resends result */ rc = rs->sr_err = SLAPD_ABANDON; } else if ( LDAP_BACK_QUARANTINE( li ) ) { ldap_back_quarantine( op, rs ); } ldap_pvt_thread_mutex_lock( &li->li_counter_mutex ); ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_EXTENDED ], 1 ); ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex ); if ( freedn ) { op->o_tmpfree( dn.bv_val, op->o_tmpmemctx ); op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); } /* these have to be freed anyway... */ if ( rs->sr_matched ) { free( (char *)rs->sr_matched ); rs->sr_matched = NULL; } if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } if ( text ) { free( text ); rs->sr_text = NULL; } /* in case, cleanup handler */ if ( lc == NULL ) { *lcp = NULL; } return rc; }
static int process_response( LDAP *ld, int msgid, int op, const char *dn ) { LDAPMessage *res; int rc = LDAP_OTHER, msgtype; struct timeval tv = { 0, 0 }; int err; char *text = NULL, *matched = NULL, **refs = NULL; LDAPControl **ctrls = NULL; for ( ; ; ) { tv.tv_sec = 0; tv.tv_usec = 100000; rc = ldap_result( ld, msgid, LDAP_MSG_ALL, &tv, &res ); if ( tool_check_abandon( ld, msgid ) ) { return LDAP_CANCELLED; } if ( rc == -1 ) { ldap_get_option( ld, LDAP_OPT_RESULT_CODE, &rc ); tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL ); return rc; } if ( rc != 0 ) { break; } } msgtype = ldap_msgtype( res ); rc = ldap_parse_result( ld, res, &err, &matched, &text, &refs, &ctrls, 1 ); if ( rc == LDAP_SUCCESS ) rc = err; #ifdef LDAP_X_TXN if ( rc == LDAP_X_TXN_SPECIFY_OKAY ) { rc = LDAP_SUCCESS; } else #endif if ( rc != LDAP_SUCCESS ) { tool_perror( res2str( op ), rc, NULL, matched, text, refs ); } else if ( msgtype != op ) { fprintf( stderr, "%s: msgtype: expected %d got %d\n", res2str( op ), op, msgtype ); rc = LDAP_OTHER; } if ( text ) ldap_memfree( text ); if ( matched ) ldap_memfree( matched ); if ( text ) ber_memvfree( (void **)refs ); if ( ctrls ) { tool_print_ctrls( ld, ctrls ); ldap_controls_free( ctrls ); } return rc; }
static int ldap_back_exop_generic( Operation *op, SlapReply *rs, ldapconn_t **lcp ) { ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private; ldapconn_t *lc = *lcp; LDAPMessage *res; ber_int_t msgid; int rc; int do_retry = 1; char *text = NULL; Debug( LDAP_DEBUG_ARGS, "==> ldap_back_exop_generic(%s, \"%s\")\n", op->ore_reqoid.bv_val, op->o_req_dn.bv_val, 0 ); assert( lc != NULL ); assert( rs->sr_ctrls == NULL ); retry: rc = ldap_extended_operation( lc->lc_ld, op->ore_reqoid.bv_val, op->ore_reqdata, op->o_ctrls, NULL, &msgid ); if ( rc == LDAP_SUCCESS ) { /* TODO: set timeout? */ /* by now, make sure no timeout is used (ITS#6282) */ struct timeval tv = { -1, 0 }; if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, &tv, &res ) == -1 ) { ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, &rc ); rs->sr_err = rc; } else { /* only touch when activity actually took place... */ if ( li->li_idle_timeout ) { lc->lc_time = op->o_time; } /* sigh. parse twice, because parse_passwd * doesn't give us the err / match / msg info. */ rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err, (char **)&rs->sr_matched, &text, NULL, &rs->sr_ctrls, 0 ); if ( rc == LDAP_SUCCESS ) { if ( rs->sr_err == LDAP_SUCCESS ) { rc = ldap_parse_extended_result( lc->lc_ld, res, (char **)&rs->sr_rspoid, &rs->sr_rspdata, 0 ); if ( rc == LDAP_SUCCESS ) { rs->sr_type = REP_EXTENDED; } } else { rc = rs->sr_err; } } ldap_msgfree( res ); } } if ( rc != LDAP_SUCCESS ) { rs->sr_err = slap_map_api2result( rs ); if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) { do_retry = 0; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { goto retry; } } if ( LDAP_BACK_QUARANTINE( li ) ) { ldap_back_quarantine( op, rs ); } if ( text ) rs->sr_text = text; send_ldap_extended( op, rs ); /* otherwise frontend resends result */ rc = rs->sr_err = SLAPD_ABANDON; } else if ( LDAP_BACK_QUARANTINE( li ) ) { ldap_back_quarantine( op, rs ); } ldap_pvt_thread_mutex_lock( &li->li_counter_mutex ); ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_EXTENDED ], 1 ); ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex ); /* these have to be freed anyway... */ if ( rs->sr_matched ) { free( (char *)rs->sr_matched ); rs->sr_matched = NULL; } if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } if ( text ) { free( text ); rs->sr_text = NULL; } /* in case, cleanup handler */ if ( lc == NULL ) { *lcp = NULL; } return rc; }