This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
#include "includes.h"
#include "lib/events/events.h"
-#include "dlinklist.h"
+#include "lib/util/dlinklist.h"
#include "libcli/ldap/ldap.h"
#include "libcli/cldap/cldap.h"
#include "lib/socket/socket.h"
#include "libcli/security/security.h"
#include "librpc/gen_ndr/ndr_nbt.h"
+#include "param/param.h"
/*
destroy a pending request
struct socket_address *src;
DATA_BLOB blob;
size_t nread, dsize;
- struct asn1_data asn1;
+ struct asn1_data *asn1 = asn1_init(tmp_ctx);
struct ldap_message *ldap_msg;
struct cldap_request *req;
+ if (!asn1) return;
+
status = socket_pending(cldap->sock, &dsize);
if (!NT_STATUS_IS_OK(status)) {
talloc_free(tmp_ctx);
DEBUG(2,("Received cldap packet of length %d from %s:%d\n",
(int)blob.length, src->addr, src->port));
- if (!asn1_load(&asn1, blob)) {
+ if (!asn1_load(asn1, blob)) {
DEBUG(2,("Failed to setup for asn.1 decode\n"));
talloc_free(tmp_ctx);
return;
}
- talloc_steal(tmp_ctx, asn1.data);
ldap_msg = talloc(tmp_ctx, struct ldap_message);
if (ldap_msg == NULL) {
}
/* this initial decode is used to find the message id */
- if (!ldap_decode(&asn1, ldap_msg)) {
- DEBUG(2,("Failed to decode ldap message\n"));
+ status = ldap_decode(asn1, ldap_msg);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(2,("Failed to decode ldap message: %s\n", nt_errstr(status)));
talloc_free(tmp_ctx);
return;
}
return;
}
- req->asn1 = asn1;
- talloc_steal(req, asn1.data);
- req->asn1.ofs = 0;
+ req->asn1 = talloc_steal(req, asn1);
+ req->asn1->ofs = 0;
req->state = CLDAP_REQUEST_DONE;
talloc_free(req->te);
return;
}
- req->state = CLDAP_REQUEST_TIMEOUT;
+ req->state = CLDAP_REQUEST_ERROR;
+ req->status = NT_STATUS_IO_TIMEOUT;
if (req->async.fn) {
req->async.fn(req);
}
status = socket_sendto(cldap->sock, &req->encoded, &len,
req->dest);
if (NT_STATUS_IS_ERR(status)) {
- DEBUG(3,("Failed to send cldap request of length %u to %s:%d\n",
+ DEBUG(0,("Failed to send cldap request of length %u to %s:%d\n",
(unsigned)req->encoded.length, req->dest->addr, req->dest->port));
DLIST_REMOVE(cldap->send_queue, req);
- talloc_free(req);
+ req->state = CLDAP_REQUEST_ERROR;
+ req->status = status;
+ if (req->async.fn) {
+ req->async.fn(req);
+ }
continue;
}
req->timeout = io->in.timeout;
req->num_retries = io->in.retries;
req->is_reply = False;
+ req->asn1 = asn1_init(req);
+ if (!req->asn1) {
+ goto failed;
+ }
req->dest = socket_address_from_strings(req, cldap->sock->backend_name,
- io->in.dest_address, lp_cldap_port());
+ io->in.dest_address,
+ lp_cldap_port());
if (!req->dest) goto failed;
req->message_id = idr_get_new_random(cldap->idr, req, UINT16_MAX);
req->cldap = cldap;
req->state = CLDAP_REQUEST_SEND;
req->is_reply = True;
+ req->asn1 = asn1_init(req);
+ if (!req->asn1) {
+ goto failed;
+ }
req->dest = io->dest;
if (talloc_reference(req, io->dest) == NULL) goto failed;
struct cldap_search *io)
{
struct ldap_message *ldap_msg;
+ NTSTATUS status;
if (req == NULL) {
return NT_STATUS_NO_MEMORY;
}
}
- if (req->state == CLDAP_REQUEST_TIMEOUT) {
+ if (req->state == CLDAP_REQUEST_ERROR) {
+ status = req->status;
talloc_free(req);
- return NT_STATUS_IO_TIMEOUT;
+ return status;
}
ldap_msg = talloc(mem_ctx, struct ldap_message);
NT_STATUS_HAVE_NO_MEMORY(ldap_msg);
- if (!ldap_decode(&req->asn1, ldap_msg)) {
+ status = ldap_decode(req->asn1, ldap_msg);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(2,("Failed to decode cldap search reply: %s\n", nt_errstr(status)));
talloc_free(req);
- return NT_STATUS_INVALID_PARAMETER;
+ return status;
}
ZERO_STRUCT(io->out);
*io->out.response = ldap_msg->r.SearchResultEntry;
/* decode the 2nd part */
- if (!ldap_decode(&req->asn1, ldap_msg)) {
+ status = ldap_decode(req->asn1, ldap_msg);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(2,("Failed to decode cldap search result entry: %s\n", nt_errstr(status)));
talloc_free(req);
- return NT_STATUS_INVALID_PARAMETER;
+ return status;
}
}
if (ldap_msg->type != LDAP_TAG_SearchResultDone) {
talloc_free(req);
- return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
+ return NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR);
}
io->out.result = talloc(mem_ctx, struct ldap_Result);
*io->out.result = ldap_msg->r.SearchResultDone;
talloc_free(req);
+
+ if (io->out.result->resultcode != LDAP_SUCCESS) {
+ return NT_STATUS_LDAP(io->out.result->resultcode);
+ }
return NT_STATUS_OK;
}
return status;
}
+/*
+ send an error reply (used on any error, so the client doesn't keep waiting
+ or send the bad request again)
+*/
+NTSTATUS cldap_error_reply(struct cldap_socket *cldap,
+ uint32_t message_id,
+ struct socket_address *src,
+ int resultcode,
+ const char *errormessage)
+{
+ NTSTATUS status;
+ struct cldap_reply reply;
+ struct ldap_Result result;
+
+ reply.messageid = message_id;
+ reply.dest = src;
+ reply.response = NULL;
+ reply.result = &result;
+
+ ZERO_STRUCT(result);
+ result.resultcode = resultcode;
+ result.errormessage = errormessage;
+
+ status = cldap_reply_send(cldap, &reply);
+
+ return status;
+}
+
/*
send a netlogon reply