2 Unix SMB/CIFS implementation.
3 Infrastructure for async ldap client requests
4 Copyright (C) Volker Lendecke 2009
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/network.h"
23 #include "system/locale.h"
24 #include "lib/util/talloc_stack.h"
25 #include "lib/util/samba_util.h"
26 #include "lib/util_tsock.h"
27 #include "../lib/util/asn1.h"
28 #include "../lib/tsocket/tsocket.h"
29 #include "../lib/util/tevent_unix.h"
31 static int tldap_simple_recv(struct tevent_req
*req
);
33 bool tevent_req_is_ldap_error(struct tevent_req
*req
, int *perr
)
35 enum tevent_req_state state
;
38 if (!tevent_req_is_error(req
, &state
, &err
)) {
42 case TEVENT_REQ_TIMED_OUT
:
43 *perr
= TLDAP_TIMEOUT
;
45 case TEVENT_REQ_NO_MEMORY
:
46 *perr
= TLDAP_NO_MEMORY
;
48 case TEVENT_REQ_USER_ERROR
:
52 *perr
= TLDAP_OPERATIONS_ERROR
;
58 struct tldap_ctx_attribute
{
63 struct tldap_context
{
65 struct tstream_context
*conn
;
68 struct tevent_queue
*outgoing
;
69 struct tevent_req
**pending
;
71 /* For the sync wrappers we need something like get_last_error... */
72 struct tldap_message
*last_msg
;
75 void (*log_fn
)(void *context
, enum tldap_debug_level level
,
76 const char *fmt
, va_list ap
);
79 struct tldap_ctx_attribute
*ctx_attrs
;
82 struct tldap_message
{
83 struct asn1_data
*data
;
90 struct tldap_attribute
*attribs
;
92 /* Error data sent by the server */
95 char *res_diagnosticmessage
;
97 struct tldap_control
*res_sctrls
;
99 /* Controls sent by the server */
100 struct tldap_control
*ctrls
;
103 void tldap_set_debug(struct tldap_context
*ld
,
104 void (*log_fn
)(void *log_private
,
105 enum tldap_debug_level level
,
107 va_list ap
) PRINTF_ATTRIBUTE(3,0),
111 ld
->log_private
= log_private
;
114 static void tldap_debug(struct tldap_context
*ld
,
115 enum tldap_debug_level level
,
116 const char *fmt
, ...)
122 if (ld
->log_fn
== NULL
) {
126 ld
->log_fn(ld
->log_private
, level
, fmt
, ap
);
130 static int tldap_next_msgid(struct tldap_context
*ld
)
134 result
= ld
->msgid
++;
135 if (ld
->msgid
== 2147483647) {
141 struct tldap_context
*tldap_context_create(TALLOC_CTX
*mem_ctx
, int fd
)
143 struct tldap_context
*ctx
;
146 ctx
= talloc_zero(mem_ctx
, struct tldap_context
);
150 ret
= tstream_bsd_existing_socket(ctx
, fd
, &ctx
->conn
);
157 ctx
->outgoing
= tevent_queue_create(ctx
, "tldap_outgoing");
158 if (ctx
->outgoing
== NULL
) {
165 bool tldap_connection_ok(struct tldap_context
*ld
)
170 return !ld
->server_down
;
173 static struct tldap_ctx_attribute
*tldap_context_findattr(
174 struct tldap_context
*ld
, const char *name
)
178 num_attrs
= talloc_array_length(ld
->ctx_attrs
);
180 for (i
=0; i
<num_attrs
; i
++) {
181 if (strcmp(ld
->ctx_attrs
[i
].name
, name
) == 0) {
182 return &ld
->ctx_attrs
[i
];
188 bool tldap_context_setattr(struct tldap_context
*ld
,
189 const char *name
, const void *_pptr
)
191 struct tldap_ctx_attribute
*tmp
, *attr
;
194 void **pptr
= (void **)discard_const_p(void,_pptr
);
196 attr
= tldap_context_findattr(ld
, name
);
199 * We don't actually delete attrs, we don't expect tons of
200 * attributes being shuffled around.
202 TALLOC_FREE(attr
->ptr
);
204 attr
->ptr
= talloc_move(ld
->ctx_attrs
, pptr
);
210 tmpname
= talloc_strdup(ld
, name
);
211 if (tmpname
== NULL
) {
215 num_attrs
= talloc_array_length(ld
->ctx_attrs
);
217 tmp
= talloc_realloc(ld
, ld
->ctx_attrs
, struct tldap_ctx_attribute
,
220 TALLOC_FREE(tmpname
);
223 tmp
[num_attrs
].name
= talloc_move(tmp
, &tmpname
);
225 tmp
[num_attrs
].ptr
= talloc_move(tmp
, pptr
);
227 tmp
[num_attrs
].ptr
= NULL
;
234 void *tldap_context_getattr(struct tldap_context
*ld
, const char *name
)
236 struct tldap_ctx_attribute
*attr
= tldap_context_findattr(ld
, name
);
244 struct read_ldap_state
{
249 static ssize_t
read_ldap_more(uint8_t *buf
, size_t buflen
, void *private_data
);
250 static void read_ldap_done(struct tevent_req
*subreq
);
252 static struct tevent_req
*read_ldap_send(TALLOC_CTX
*mem_ctx
,
253 struct tevent_context
*ev
,
254 struct tstream_context
*conn
)
256 struct tevent_req
*req
, *subreq
;
257 struct read_ldap_state
*state
;
259 req
= tevent_req_create(mem_ctx
, &state
, struct read_ldap_state
);
265 subreq
= tstream_read_packet_send(state
, ev
, conn
, 2, read_ldap_more
,
267 if (tevent_req_nomem(subreq
, req
)) {
268 return tevent_req_post(req
, ev
);
270 tevent_req_set_callback(subreq
, read_ldap_done
, req
);
274 static ssize_t
read_ldap_more(uint8_t *buf
, size_t buflen
, void *private_data
)
276 struct read_ldap_state
*state
= talloc_get_type_abort(
277 private_data
, struct read_ldap_state
);
282 /* We've been here, we're done */
287 * From ldap.h: LDAP_TAG_MESSAGE is 0x30
289 if (buf
[0] != 0x30) {
294 if ((len
& 0x80) == 0) {
299 lensize
= (len
& 0x7f);
303 /* Please get us the full length */
306 if (buflen
> 2 + lensize
) {
310 if (buflen
!= 2 + lensize
) {
314 for (i
=0; i
<lensize
; i
++) {
315 len
= (len
<< 8) | buf
[2+i
];
320 static void read_ldap_done(struct tevent_req
*subreq
)
322 struct tevent_req
*req
= tevent_req_callback_data(
323 subreq
, struct tevent_req
);
324 struct read_ldap_state
*state
= tevent_req_data(
325 req
, struct read_ldap_state
);
329 nread
= tstream_read_packet_recv(subreq
, state
, &state
->buf
, &err
);
332 tevent_req_error(req
, err
);
335 tevent_req_done(req
);
338 static ssize_t
read_ldap_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
339 uint8_t **pbuf
, int *perrno
)
341 struct read_ldap_state
*state
= tevent_req_data(
342 req
, struct read_ldap_state
);
344 if (tevent_req_is_unix_error(req
, perrno
)) {
347 *pbuf
= talloc_move(mem_ctx
, &state
->buf
);
348 return talloc_get_size(*pbuf
);
351 struct tldap_msg_state
{
352 struct tldap_context
*ld
;
353 struct tevent_context
*ev
;
357 struct asn1_data
*data
;
361 static bool tldap_push_controls(struct asn1_data
*data
,
362 struct tldap_control
*sctrls
,
367 if ((sctrls
== NULL
) || (num_sctrls
== 0)) {
371 if (!asn1_push_tag(data
, ASN1_CONTEXT(0))) return false;
373 for (i
=0; i
<num_sctrls
; i
++) {
374 struct tldap_control
*c
= &sctrls
[i
];
375 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) return false;
376 if (!asn1_write_OctetString(data
, c
->oid
, strlen(c
->oid
))) return false;
378 if (!asn1_write_BOOLEAN(data
, true)) return false;
380 if (c
->value
.data
!= NULL
) {
381 if (!asn1_write_OctetString(data
, c
->value
.data
,
382 c
->value
.length
)) return false;
384 if (!asn1_pop_tag(data
)) return false; /* ASN1_SEQUENCE(0) */
387 return asn1_pop_tag(data
); /* ASN1_CONTEXT(0) */
390 static void tldap_msg_sent(struct tevent_req
*subreq
);
391 static void tldap_msg_received(struct tevent_req
*subreq
);
393 static struct tevent_req
*tldap_msg_send(TALLOC_CTX
*mem_ctx
,
394 struct tevent_context
*ev
,
395 struct tldap_context
*ld
,
396 int id
, struct asn1_data
*data
,
397 struct tldap_control
*sctrls
,
400 struct tevent_req
*req
, *subreq
;
401 struct tldap_msg_state
*state
;
404 tldap_debug(ld
, TLDAP_DEBUG_TRACE
, "tldap_msg_send: sending msg %d\n",
407 req
= tevent_req_create(mem_ctx
, &state
, struct tldap_msg_state
);
415 if (state
->ld
->server_down
) {
416 tevent_req_error(req
, TLDAP_SERVER_DOWN
);
417 return tevent_req_post(req
, ev
);
420 if (!tldap_push_controls(data
, sctrls
, num_sctrls
)) {
421 tevent_req_error(req
, TLDAP_ENCODING_ERROR
);
422 return tevent_req_post(req
, ev
);
426 if (!asn1_pop_tag(data
)) {
427 tevent_req_error(req
, TLDAP_ENCODING_ERROR
);
428 return tevent_req_post(req
, ev
);
431 if (!asn1_blob(data
, &blob
)) {
432 tevent_req_error(req
, TLDAP_ENCODING_ERROR
);
433 return tevent_req_post(req
, ev
);
436 state
->iov
.iov_base
= (void *)blob
.data
;
437 state
->iov
.iov_len
= blob
.length
;
439 subreq
= tstream_writev_queue_send(state
, ev
, ld
->conn
, ld
->outgoing
,
441 if (tevent_req_nomem(subreq
, req
)) {
442 return tevent_req_post(req
, ev
);
444 tevent_req_set_callback(subreq
, tldap_msg_sent
, req
);
448 static void tldap_msg_unset_pending(struct tevent_req
*req
)
450 struct tldap_msg_state
*state
= tevent_req_data(
451 req
, struct tldap_msg_state
);
452 struct tldap_context
*ld
= state
->ld
;
453 int num_pending
= talloc_array_length(ld
->pending
);
456 tevent_req_set_cleanup_fn(req
, NULL
);
458 if (num_pending
== 1) {
459 TALLOC_FREE(ld
->pending
);
463 for (i
=0; i
<num_pending
; i
++) {
464 if (req
== ld
->pending
[i
]) {
468 if (i
== num_pending
) {
470 * Something's seriously broken. Just returning here is the
471 * right thing nevertheless, the point of this routine is to
472 * remove ourselves from cli->pending.
478 * Remove ourselves from the cli->pending array
480 if (num_pending
> 1) {
481 ld
->pending
[i
] = ld
->pending
[num_pending
-1];
485 * No NULL check here, we're shrinking by sizeof(void *), and
486 * talloc_realloc just adjusts the size for this.
488 ld
->pending
= talloc_realloc(NULL
, ld
->pending
, struct tevent_req
*,
492 static void tldap_msg_cleanup(struct tevent_req
*req
,
493 enum tevent_req_state req_state
)
496 case TEVENT_REQ_USER_ERROR
:
497 case TEVENT_REQ_RECEIVED
:
498 tldap_msg_unset_pending(req
);
505 static bool tldap_msg_set_pending(struct tevent_req
*req
)
507 struct tldap_msg_state
*state
= tevent_req_data(
508 req
, struct tldap_msg_state
);
509 struct tldap_context
*ld
;
510 struct tevent_req
**pending
;
512 struct tevent_req
*subreq
;
515 num_pending
= talloc_array_length(ld
->pending
);
517 pending
= talloc_realloc(ld
, ld
->pending
, struct tevent_req
*,
519 if (pending
== NULL
) {
522 pending
[num_pending
] = req
;
523 ld
->pending
= pending
;
524 tevent_req_set_cleanup_fn(req
, tldap_msg_cleanup
);
526 if (num_pending
> 0) {
531 * We're the first one, add the read_ldap request that waits for the
532 * answer from the server
534 subreq
= read_ldap_send(ld
->pending
, state
->ev
, ld
->conn
);
535 if (subreq
== NULL
) {
536 tldap_msg_unset_pending(req
);
539 tevent_req_set_callback(subreq
, tldap_msg_received
, ld
);
543 static void tldap_msg_sent(struct tevent_req
*subreq
)
545 struct tevent_req
*req
= tevent_req_callback_data(
546 subreq
, struct tevent_req
);
547 struct tldap_msg_state
*state
= tevent_req_data(
548 req
, struct tldap_msg_state
);
552 nwritten
= tstream_writev_queue_recv(subreq
, &err
);
554 if (nwritten
== -1) {
555 state
->ld
->server_down
= true;
556 tevent_req_error(req
, TLDAP_SERVER_DOWN
);
560 if (!tldap_msg_set_pending(req
)) {
566 static int tldap_msg_msgid(struct tevent_req
*req
)
568 struct tldap_msg_state
*state
= tevent_req_data(
569 req
, struct tldap_msg_state
);
574 static void tldap_msg_received(struct tevent_req
*subreq
)
576 struct tldap_context
*ld
= tevent_req_callback_data(
577 subreq
, struct tldap_context
);
578 struct tevent_req
*req
;
579 struct tldap_msg_state
*state
;
580 struct asn1_data
*data
;
589 received
= read_ldap_recv(subreq
, talloc_tos(), &inbuf
, &err
);
591 if (received
== -1) {
592 status
= TLDAP_SERVER_DOWN
;
596 data
= asn1_init(talloc_tos());
598 status
= TLDAP_NO_MEMORY
;
601 asn1_load_nocopy(data
, inbuf
, received
);
604 ok
&= asn1_start_tag(data
, ASN1_SEQUENCE(0));
605 ok
&= asn1_read_Integer(data
, &id
);
606 ok
&= asn1_peek_uint8(data
, &type
);
609 status
= TLDAP_PROTOCOL_ERROR
;
613 tldap_debug(ld
, TLDAP_DEBUG_TRACE
, "tldap_msg_received: got msg %d "
614 "type %d\n", id
, (int)type
);
616 num_pending
= talloc_array_length(ld
->pending
);
618 for (i
=0; i
<num_pending
; i
++) {
619 if (id
== tldap_msg_msgid(ld
->pending
[i
])) {
623 if (i
== num_pending
) {
624 /* Dump unexpected reply */
625 tldap_debug(ld
, TLDAP_DEBUG_WARNING
, "tldap_msg_received: "
626 "No request pending for msg %d\n", id
);
632 req
= ld
->pending
[i
];
633 state
= tevent_req_data(req
, struct tldap_msg_state
);
635 state
->inbuf
= talloc_move(state
, &inbuf
);
636 state
->data
= talloc_move(state
, &data
);
638 tldap_msg_unset_pending(req
);
639 num_pending
= talloc_array_length(ld
->pending
);
641 tevent_req_done(req
);
644 if (num_pending
== 0) {
647 if (talloc_array_length(ld
->pending
) > num_pending
) {
649 * The callback functions called from tevent_req_done() above
650 * have put something on the pending queue. We don't have to
651 * trigger the read_ldap_send(), tldap_msg_set_pending() has
652 * done it for us already.
657 state
= tevent_req_data(ld
->pending
[0], struct tldap_msg_state
);
658 subreq
= read_ldap_send(ld
->pending
, state
->ev
, ld
->conn
);
659 if (subreq
== NULL
) {
660 status
= TLDAP_NO_MEMORY
;
663 tevent_req_set_callback(subreq
, tldap_msg_received
, ld
);
667 while (talloc_array_length(ld
->pending
) > 0) {
668 req
= ld
->pending
[0];
669 state
= tevent_req_data(req
, struct tldap_msg_state
);
670 tevent_req_defer_callback(req
, state
->ev
);
671 tevent_req_error(req
, status
);
675 static int tldap_msg_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
676 struct tldap_message
**pmsg
)
678 struct tldap_msg_state
*state
= tevent_req_data(
679 req
, struct tldap_msg_state
);
680 struct tldap_message
*msg
;
684 if (tevent_req_is_ldap_error(req
, &err
)) {
688 if (!asn1_peek_uint8(state
->data
, &msgtype
)) {
689 return TLDAP_PROTOCOL_ERROR
;
693 return TLDAP_SUCCESS
;
696 msg
= talloc_zero(mem_ctx
, struct tldap_message
);
698 return TLDAP_NO_MEMORY
;
702 msg
->inbuf
= talloc_move(msg
, &state
->inbuf
);
703 msg
->data
= talloc_move(msg
, &state
->data
);
707 return TLDAP_SUCCESS
;
710 struct tldap_req_state
{
712 struct asn1_data
*out
;
713 struct tldap_message
*result
;
716 static struct tevent_req
*tldap_req_create(TALLOC_CTX
*mem_ctx
,
717 struct tldap_context
*ld
,
718 struct tldap_req_state
**pstate
)
720 struct tevent_req
*req
;
721 struct tldap_req_state
*state
;
723 req
= tevent_req_create(mem_ctx
, &state
, struct tldap_req_state
);
727 state
->out
= asn1_init(state
);
728 if (state
->out
== NULL
) {
731 state
->id
= tldap_next_msgid(ld
);
733 if (!asn1_push_tag(state
->out
, ASN1_SEQUENCE(0))) goto err
;
734 if (!asn1_write_Integer(state
->out
, state
->id
)) goto err
;
745 static void tldap_save_msg(struct tldap_context
*ld
, struct tevent_req
*req
)
747 struct tldap_req_state
*state
= tevent_req_data(
748 req
, struct tldap_req_state
);
750 TALLOC_FREE(ld
->last_msg
);
751 ld
->last_msg
= talloc_move(ld
, &state
->result
);
754 static char *blob2string_talloc(TALLOC_CTX
*mem_ctx
, DATA_BLOB blob
)
756 char *result
= talloc_array(mem_ctx
, char, blob
.length
+1);
758 if (result
== NULL
) {
762 memcpy(result
, blob
.data
, blob
.length
);
763 result
[blob
.length
] = '\0';
767 static bool asn1_read_OctetString_talloc(TALLOC_CTX
*mem_ctx
,
768 struct asn1_data
*data
,
773 if (!asn1_read_OctetString(data
, mem_ctx
, &string
))
776 result
= blob2string_talloc(mem_ctx
, string
);
778 data_blob_free(&string
);
780 if (result
== NULL
) {
787 static bool tldap_decode_controls(struct tldap_req_state
*state
);
789 static bool tldap_decode_response(struct tldap_req_state
*state
)
791 struct asn1_data
*data
= state
->result
->data
;
792 struct tldap_message
*msg
= state
->result
;
795 ok
&= asn1_read_enumerated(data
, &msg
->lderr
);
796 ok
&= asn1_read_OctetString_talloc(msg
, data
, &msg
->res_matcheddn
);
797 ok
&= asn1_read_OctetString_talloc(msg
, data
,
798 &msg
->res_diagnosticmessage
);
800 if (asn1_peek_tag(data
, ASN1_CONTEXT(3))) {
801 ok
&= asn1_start_tag(data
, ASN1_CONTEXT(3));
802 ok
&= asn1_read_OctetString_talloc(msg
, data
,
804 ok
&= asn1_end_tag(data
);
806 msg
->res_referral
= NULL
;
812 static void tldap_sasl_bind_done(struct tevent_req
*subreq
);
814 struct tevent_req
*tldap_sasl_bind_send(TALLOC_CTX
*mem_ctx
,
815 struct tevent_context
*ev
,
816 struct tldap_context
*ld
,
818 const char *mechanism
,
820 struct tldap_control
*sctrls
,
822 struct tldap_control
*cctrls
,
825 struct tevent_req
*req
, *subreq
;
826 struct tldap_req_state
*state
;
828 req
= tldap_req_create(mem_ctx
, ld
, &state
);
837 if (!asn1_push_tag(state
->out
, TLDAP_REQ_BIND
)) goto err
;
838 if (!asn1_write_Integer(state
->out
, ld
->ld_version
)) goto err
;
839 if (!asn1_write_OctetString(state
->out
, dn
, strlen(dn
))) goto err
;
841 if (mechanism
== NULL
) {
842 if (!asn1_push_tag(state
->out
, ASN1_CONTEXT_SIMPLE(0))) goto err
;
843 if (!asn1_write(state
->out
, creds
->data
, creds
->length
)) goto err
;
844 if (!asn1_pop_tag(state
->out
)) goto err
;
846 if (!asn1_push_tag(state
->out
, ASN1_CONTEXT(3))) goto err
;
847 if (!asn1_write_OctetString(state
->out
, mechanism
,
848 strlen(mechanism
))) goto err
;
849 if ((creds
!= NULL
) && (creds
->data
!= NULL
)) {
850 if (!asn1_write_OctetString(state
->out
, creds
->data
,
851 creds
->length
)) goto err
;
853 if (!asn1_pop_tag(state
->out
)) goto err
;
856 if (!asn1_pop_tag(state
->out
)) goto err
;
858 subreq
= tldap_msg_send(state
, ev
, ld
, state
->id
, state
->out
,
860 if (tevent_req_nomem(subreq
, req
)) {
861 return tevent_req_post(req
, ev
);
863 tevent_req_set_callback(subreq
, tldap_sasl_bind_done
, req
);
868 tevent_req_error(req
, TLDAP_ENCODING_ERROR
);
869 return tevent_req_post(req
, ev
);
872 static void tldap_sasl_bind_done(struct tevent_req
*subreq
)
874 struct tevent_req
*req
= tevent_req_callback_data(
875 subreq
, struct tevent_req
);
876 struct tldap_req_state
*state
= tevent_req_data(
877 req
, struct tldap_req_state
);
880 err
= tldap_msg_recv(subreq
, state
, &state
->result
);
882 if (err
!= TLDAP_SUCCESS
) {
883 tevent_req_error(req
, err
);
886 if (state
->result
->type
!= TLDAP_RES_BIND
) {
887 tevent_req_error(req
, TLDAP_PROTOCOL_ERROR
);
890 if (!asn1_start_tag(state
->result
->data
, state
->result
->type
) ||
891 !tldap_decode_response(state
) ||
892 !asn1_end_tag(state
->result
->data
)) {
893 tevent_req_error(req
, TLDAP_DECODING_ERROR
);
897 * TODO: pull the reply blob
899 if (state
->result
->lderr
!= TLDAP_SUCCESS
) {
900 tevent_req_error(req
, state
->result
->lderr
);
903 tevent_req_done(req
);
906 int tldap_sasl_bind_recv(struct tevent_req
*req
)
908 return tldap_simple_recv(req
);
911 int tldap_sasl_bind(struct tldap_context
*ld
,
913 const char *mechanism
,
915 struct tldap_control
*sctrls
,
917 struct tldap_control
*cctrls
,
920 TALLOC_CTX
*frame
= talloc_stackframe();
921 struct tevent_context
*ev
;
922 struct tevent_req
*req
;
925 ev
= samba_tevent_context_init(frame
);
927 result
= TLDAP_NO_MEMORY
;
931 req
= tldap_sasl_bind_send(frame
, ev
, ld
, dn
, mechanism
, creds
,
932 sctrls
, num_sctrls
, cctrls
, num_cctrls
);
934 result
= TLDAP_NO_MEMORY
;
938 if (!tevent_req_poll(req
, ev
)) {
939 result
= TLDAP_OPERATIONS_ERROR
;
943 result
= tldap_sasl_bind_recv(req
);
944 tldap_save_msg(ld
, req
);
950 struct tevent_req
*tldap_simple_bind_send(TALLOC_CTX
*mem_ctx
,
951 struct tevent_context
*ev
,
952 struct tldap_context
*ld
,
958 if (passwd
!= NULL
) {
959 cred
.data
= discard_const_p(uint8_t, passwd
);
960 cred
.length
= strlen(passwd
);
962 cred
.data
= discard_const_p(uint8_t, "");
965 return tldap_sasl_bind_send(mem_ctx
, ev
, ld
, dn
, NULL
, &cred
, NULL
, 0,
969 int tldap_simple_bind_recv(struct tevent_req
*req
)
971 return tldap_sasl_bind_recv(req
);
974 int tldap_simple_bind(struct tldap_context
*ld
, const char *dn
,
979 if (passwd
!= NULL
) {
980 cred
.data
= discard_const_p(uint8_t, passwd
);
981 cred
.length
= strlen(passwd
);
983 cred
.data
= discard_const_p(uint8_t, "");
986 return tldap_sasl_bind(ld
, dn
, NULL
, &cred
, NULL
, 0, NULL
, 0);
989 /*****************************************************************************/
991 /* can't use isalpha() as only a strict set is valid for LDAP */
993 static bool tldap_is_alpha(char c
)
995 return (((c
>= 'a') && (c
<= 'z')) || \
996 ((c
>= 'A') && (c
<= 'Z')));
999 static bool tldap_is_adh(char c
)
1001 return tldap_is_alpha(c
) || isdigit(c
) || (c
== '-');
1004 #define TLDAP_FILTER_AND ASN1_CONTEXT(0)
1005 #define TLDAP_FILTER_OR ASN1_CONTEXT(1)
1006 #define TLDAP_FILTER_NOT ASN1_CONTEXT(2)
1007 #define TLDAP_FILTER_EQ ASN1_CONTEXT(3)
1008 #define TLDAP_FILTER_SUB ASN1_CONTEXT(4)
1009 #define TLDAP_FILTER_LE ASN1_CONTEXT(5)
1010 #define TLDAP_FILTER_GE ASN1_CONTEXT(6)
1011 #define TLDAP_FILTER_PRES ASN1_CONTEXT_SIMPLE(7)
1012 #define TLDAP_FILTER_APX ASN1_CONTEXT(8)
1013 #define TLDAP_FILTER_EXT ASN1_CONTEXT(9)
1015 #define TLDAP_SUB_INI ASN1_CONTEXT_SIMPLE(0)
1016 #define TLDAP_SUB_ANY ASN1_CONTEXT_SIMPLE(1)
1017 #define TLDAP_SUB_FIN ASN1_CONTEXT_SIMPLE(2)
1020 /* oid's should be numerical only in theory,
1021 * but apparently some broken servers may have alphanum aliases instead.
1022 * Do like openldap libraries and allow alphanum aliases for oids, but
1023 * do not allow Tagging options in that case.
1025 static bool tldap_is_attrdesc(const char *s
, int len
, bool no_tagopts
)
1027 bool is_oid
= false;
1031 /* first char has stricter rules */
1034 } else if (!tldap_is_alpha(*s
)) {
1035 /* bad first char */
1039 for (i
= 1; i
< len
; i
++) {
1042 if (isdigit(s
[i
])) {
1055 if (tldap_is_adh(s
[i
])) {
1062 /* no tagging options */
1069 if ((i
+ 1) == len
) {
1087 /* this function copies the value until the closing parenthesis is found. */
1088 static char *tldap_get_val(TALLOC_CTX
*memctx
,
1089 const char *value
, const char **_s
)
1091 const char *s
= value
;
1093 /* find terminator */
1096 if (s
&& (*(s
- 1) == '\\')) {
1101 if (!s
|| !(*s
== ')')) {
1102 /* malformed filter */
1108 return talloc_strndup(memctx
, value
, s
- value
);
1111 static int tldap_hex2char(const char *x
)
1113 if (isxdigit(x
[0]) && isxdigit(x
[1])) {
1114 const char h1
= x
[0], h2
= x
[1];
1117 if (h1
>= 'a') c
= h1
- (int)'a' + 10;
1118 else if (h1
>= 'A') c
= h1
- (int)'A' + 10;
1119 else if (h1
>= '0') c
= h1
- (int)'0';
1121 if (h2
>= 'a') c
+= h2
- (int)'a' + 10;
1122 else if (h2
>= 'A') c
+= h2
- (int)'A' + 10;
1123 else if (h2
>= '0') c
+= h2
- (int)'0';
1131 static bool tldap_find_first_star(const char *val
, const char **star
)
1135 for (s
= val
; *s
; s
++) {
1138 if (isxdigit(s
[1]) && isxdigit(s
[2])) {
1142 /* not hex based escape, check older syntax */
1151 /* invalid escape sequence */
1156 /* end of val, nothing found */
1166 /* string ended without closing parenthesis, filter is malformed */
1170 static bool tldap_unescape_inplace(char *value
, size_t *val_len
)
1174 for (i
= 0,p
= 0; i
< *val_len
; i
++) {
1180 /* these must be escaped */
1184 if (!value
[i
+ 1]) {
1190 c
= tldap_hex2char(&value
[i
]);
1191 if (c
>= 0 && c
< 256) {
1203 value
[p
] = value
[i
];
1212 value
[p
] = value
[i
];
1221 static bool tldap_push_filter_basic(struct tldap_context
*ld
,
1222 struct asn1_data
*data
,
1224 static bool tldap_push_filter_substring(struct tldap_context
*ld
,
1225 struct asn1_data
*data
,
1228 static bool tldap_push_filter_int(struct tldap_context
*ld
,
1229 struct asn1_data
*data
,
1232 const char *s
= *_s
;
1236 tldap_debug(ld
, TLDAP_DEBUG_ERROR
,
1237 "Incomplete or malformed filter\n");
1242 /* we are right after a parenthesis,
1243 * find out what op we have at hand */
1246 tldap_debug(ld
, TLDAP_DEBUG_TRACE
, "Filter op: AND\n");
1247 if (!asn1_push_tag(data
, TLDAP_FILTER_AND
)) return false;
1252 tldap_debug(ld
, TLDAP_DEBUG_TRACE
, "Filter op: OR\n");
1253 if (!asn1_push_tag(data
, TLDAP_FILTER_OR
)) return false;
1258 tldap_debug(ld
, TLDAP_DEBUG_TRACE
, "Filter op: NOT\n");
1259 if (!asn1_push_tag(data
, TLDAP_FILTER_NOT
)) return false;
1261 ret
= tldap_push_filter_int(ld
, data
, &s
);
1265 if (!asn1_pop_tag(data
)) return false;
1270 tldap_debug(ld
, TLDAP_DEBUG_ERROR
,
1271 "Invalid parenthesis '%c'\n", *s
);
1275 tldap_debug(ld
, TLDAP_DEBUG_ERROR
,
1276 "Invalid filter termination\n");
1280 ret
= tldap_push_filter_basic(ld
, data
, &s
);
1287 /* only and/or filters get here.
1288 * go through the list of filters */
1291 /* RFC 4526: empty and/or */
1292 if (!asn1_pop_tag(data
)) return false;
1297 ret
= tldap_push_filter_int(ld
, data
, &s
);
1303 /* end of list, return */
1304 if (!asn1_pop_tag(data
)) return false;
1311 tldap_debug(ld
, TLDAP_DEBUG_ERROR
,
1312 "Incomplete or malformed filter\n");
1317 if (asn1_has_error(data
)) {
1326 static bool tldap_push_filter_basic(struct tldap_context
*ld
,
1327 struct asn1_data
*data
,
1330 TALLOC_CTX
*tmpctx
= talloc_tos();
1331 const char *s
= *_s
;
1339 size_t type_len
= 0;
1342 bool write_octect
= true;
1345 eq
= strchr(s
, '=');
1347 tldap_debug(ld
, TLDAP_DEBUG_ERROR
,
1348 "Invalid filter, missing equal sign\n");
1357 if (!asn1_push_tag(data
, TLDAP_FILTER_LE
)) return false;
1361 if (!asn1_push_tag(data
, TLDAP_FILTER_GE
)) return false;
1365 if (!asn1_push_tag(data
, TLDAP_FILTER_APX
)) return false;
1369 if (!asn1_push_tag(data
, TLDAP_FILTER_EXT
)) return false;
1370 write_octect
= false;
1376 if (*s
== ':') { /* [:dn]:rule:= value */
1378 /* malformed filter */
1382 } else { /* type[:dn][:rule]:= value */
1384 dn
= strchr(s
, ':');
1385 type_len
= dn
- type
;
1386 if (dn
== e
) { /* type:= value */
1393 rule
= strchr(dn
, ':');
1397 if ((rule
== dn
+ 1) || rule
+ 1 == e
) {
1398 /* malformed filter, contains "::" */
1402 if (strncasecmp_m(dn
, "dn:", 3) != 0) {
1407 /* malformed filter. With two
1408 * optionals, the first must be "dn"
1421 if (!type
&& !dn
&& !rule
) {
1422 /* malformed filter, there must be at least one */
1427 MatchingRuleAssertion ::= SEQUENCE {
1428 matchingRule [1] MatchingRuleID OPTIONAL,
1429 type [2] AttributeDescription OPTIONAL,
1430 matchValue [3] AssertionValue,
1431 dnAttributes [4] BOOLEAN DEFAULT FALSE
1435 /* check and add rule */
1437 ret
= tldap_is_attrdesc(rule
, e
- rule
, true);
1441 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(1))) return false;
1442 if (!asn1_write(data
, rule
, e
- rule
)) return false;
1443 if (!asn1_pop_tag(data
)) return false;
1446 /* check and add type */
1448 ret
= tldap_is_attrdesc(type
, type_len
, false);
1452 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(2))) return false;
1453 if (!asn1_write(data
, type
, type_len
)) return false;
1454 if (!asn1_pop_tag(data
)) return false;
1457 uval
= tldap_get_val(tmpctx
, val
, _s
);
1461 uval_len
= *_s
- val
;
1462 ret
= tldap_unescape_inplace(uval
, &uval_len
);
1467 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(3))) return false;
1468 if (!asn1_write(data
, uval
, uval_len
)) return false;
1469 if (!asn1_pop_tag(data
)) return false;
1471 if (!asn1_push_tag(data
, ASN1_CONTEXT_SIMPLE(4))) return false;
1472 if (!asn1_write_uint8(data
, dn
?1:0)) return false;
1473 if (!asn1_pop_tag(data
)) return false;
1479 ret
= tldap_is_attrdesc(s
, e
- s
, false);
1484 if (strncmp(val
, "*)", 2) == 0) {
1486 if (!asn1_push_tag(data
, TLDAP_FILTER_PRES
)) return false;
1487 if (!asn1_write(data
, s
, e
- s
)) return false;
1489 write_octect
= false;
1493 ret
= tldap_find_first_star(val
, &star
);
1499 if (!asn1_push_tag(data
, TLDAP_FILTER_SUB
)) return false;
1500 if (!asn1_write_OctetString(data
, s
, e
- s
)) return false;
1501 ret
= tldap_push_filter_substring(ld
, data
, val
, &s
);
1506 write_octect
= false;
1510 /* if nothing else, then it is just equality */
1511 if (!asn1_push_tag(data
, TLDAP_FILTER_EQ
)) return false;
1512 write_octect
= true;
1517 uval
= tldap_get_val(tmpctx
, val
, _s
);
1521 uval_len
= *_s
- val
;
1522 ret
= tldap_unescape_inplace(uval
, &uval_len
);
1527 if (!asn1_write_OctetString(data
, s
, e
- s
)) return false;
1528 if (!asn1_write_OctetString(data
, uval
, uval_len
)) return false;
1531 if (asn1_has_error(data
)) {
1534 return asn1_pop_tag(data
);
1537 static bool tldap_push_filter_substring(struct tldap_context
*ld
,
1538 struct asn1_data
*data
,
1542 TALLOC_CTX
*tmpctx
= talloc_tos();
1543 bool initial
= true;
1550 SubstringFilter ::= SEQUENCE {
1551 type AttributeDescription,
1552 -- at least one must be present
1553 substrings SEQUENCE OF CHOICE {
1554 initial [0] LDAPString,
1556 final [2] LDAPString } }
1558 if (!asn1_push_tag(data
, ASN1_SEQUENCE(0))) return false;
1561 ret
= tldap_find_first_star(val
, &star
);
1565 chunk_len
= star
- val
;
1569 if (!initial
&& chunk_len
== 0) {
1570 /* found '**', which is illegal */
1586 if (initial
&& chunk_len
== 0) {
1592 chunk
= talloc_strndup(tmpctx
, val
, chunk_len
);
1596 ret
= tldap_unescape_inplace(chunk
, &chunk_len
);
1603 if (!asn1_push_tag(data
, TLDAP_SUB_INI
)) return false;
1606 if (!asn1_push_tag(data
, TLDAP_SUB_ANY
)) return false;
1610 if (!asn1_push_tag(data
, TLDAP_SUB_FIN
)) return false;
1616 if (!asn1_write(data
, chunk
, chunk_len
)) return false;
1617 if (!asn1_pop_tag(data
)) return false;
1621 } while (*star
== '*');
1625 /* end of sequence */
1626 return asn1_pop_tag(data
);
1629 /* NOTE: although openldap libraries allow for spaces in some places, mosly
1630 * around parenthesis, we do not allow any spaces (except in values of
1631 * course) as I couldn't fine any place in RFC 4512 or RFC 4515 where
1632 * leading or trailing spaces where allowed.
1634 static bool tldap_push_filter(struct tldap_context
*ld
,
1635 struct asn1_data
*data
,
1638 const char *s
= filter
;
1641 ret
= tldap_push_filter_int(ld
, data
, &s
);
1643 tldap_debug(ld
, TLDAP_DEBUG_ERROR
,
1644 "Incomplete or malformed filter\n");
1650 /*****************************************************************************/
1652 static void tldap_search_done(struct tevent_req
*subreq
);
1654 struct tevent_req
*tldap_search_send(TALLOC_CTX
*mem_ctx
,
1655 struct tevent_context
*ev
,
1656 struct tldap_context
*ld
,
1657 const char *base
, int scope
,
1662 struct tldap_control
*sctrls
,
1664 struct tldap_control
*cctrls
,
1670 struct tevent_req
*req
, *subreq
;
1671 struct tldap_req_state
*state
;
1674 req
= tldap_req_create(mem_ctx
, ld
, &state
);
1679 if (!asn1_push_tag(state
->out
, TLDAP_REQ_SEARCH
)) goto encoding_error
;
1680 if (!asn1_write_OctetString(state
->out
, base
, strlen(base
))) goto encoding_error
;
1681 if (!asn1_write_enumerated(state
->out
, scope
)) goto encoding_error
;
1682 if (!asn1_write_enumerated(state
->out
, deref
)) goto encoding_error
;
1683 if (!asn1_write_Integer(state
->out
, sizelimit
)) goto encoding_error
;
1684 if (!asn1_write_Integer(state
->out
, timelimit
)) goto encoding_error
;
1685 if (!asn1_write_BOOLEAN(state
->out
, attrsonly
)) goto encoding_error
;
1687 if (!tldap_push_filter(ld
, state
->out
, filter
)) {
1688 goto encoding_error
;
1691 if (!asn1_push_tag(state
->out
, ASN1_SEQUENCE(0))) goto encoding_error
;
1692 for (i
=0; i
<num_attrs
; i
++) {
1693 if (!asn1_write_OctetString(state
->out
, attrs
[i
], strlen(attrs
[i
]))) goto encoding_error
;
1695 if (!asn1_pop_tag(state
->out
)) goto encoding_error
;
1696 if (!asn1_pop_tag(state
->out
)) goto encoding_error
;
1698 subreq
= tldap_msg_send(state
, ev
, ld
, state
->id
, state
->out
,
1699 sctrls
, num_sctrls
);
1700 if (tevent_req_nomem(subreq
, req
)) {
1701 return tevent_req_post(req
, ev
);
1703 tevent_req_set_callback(subreq
, tldap_search_done
, req
);
1707 tevent_req_error(req
, TLDAP_ENCODING_ERROR
);
1708 return tevent_req_post(req
, ev
);
1711 static void tldap_search_done(struct tevent_req
*subreq
)
1713 struct tevent_req
*req
= tevent_req_callback_data(
1714 subreq
, struct tevent_req
);
1715 struct tldap_req_state
*state
= tevent_req_data(
1716 req
, struct tldap_req_state
);
1719 err
= tldap_msg_recv(subreq
, state
, &state
->result
);
1720 if (err
!= TLDAP_SUCCESS
) {
1721 tevent_req_error(req
, err
);
1724 switch (state
->result
->type
) {
1725 case TLDAP_RES_SEARCH_ENTRY
:
1726 case TLDAP_RES_SEARCH_REFERENCE
:
1727 if (!tldap_msg_set_pending(subreq
)) {
1728 tevent_req_oom(req
);
1731 tevent_req_notify_callback(req
);
1733 case TLDAP_RES_SEARCH_RESULT
:
1734 TALLOC_FREE(subreq
);
1735 if (!asn1_start_tag(state
->result
->data
,
1736 state
->result
->type
) ||
1737 !tldap_decode_response(state
) ||
1738 !asn1_end_tag(state
->result
->data
) ||
1739 !tldap_decode_controls(state
)) {
1740 tevent_req_error(req
, TLDAP_DECODING_ERROR
);
1743 tevent_req_done(req
);
1746 tevent_req_error(req
, TLDAP_PROTOCOL_ERROR
);
1751 int tldap_search_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
1752 struct tldap_message
**pmsg
)
1754 struct tldap_req_state
*state
= tevent_req_data(
1755 req
, struct tldap_req_state
);
1758 if (!tevent_req_is_in_progress(req
)
1759 && tevent_req_is_ldap_error(req
, &err
)) {
1763 if (tevent_req_is_in_progress(req
)) {
1764 switch (state
->result
->type
) {
1765 case TLDAP_RES_SEARCH_ENTRY
:
1766 case TLDAP_RES_SEARCH_REFERENCE
:
1769 return TLDAP_OPERATIONS_ERROR
;
1773 *pmsg
= talloc_move(mem_ctx
, &state
->result
);
1774 return TLDAP_SUCCESS
;
1777 struct tldap_sync_search_state
{
1778 TALLOC_CTX
*mem_ctx
;
1779 struct tldap_message
**entries
;
1780 struct tldap_message
**refs
;
1784 static void tldap_search_cb(struct tevent_req
*req
)
1786 struct tldap_sync_search_state
*state
=
1787 (struct tldap_sync_search_state
*)
1788 tevent_req_callback_data_void(req
);
1789 struct tldap_message
*msg
, **tmp
;
1790 int rc
, num_entries
, num_refs
;
1792 rc
= tldap_search_recv(req
, talloc_tos(), &msg
);
1793 if (rc
!= TLDAP_SUCCESS
) {
1798 switch (tldap_msg_type(msg
)) {
1799 case TLDAP_RES_SEARCH_ENTRY
:
1800 num_entries
= talloc_array_length(state
->entries
);
1801 tmp
= talloc_realloc(state
->mem_ctx
, state
->entries
,
1802 struct tldap_message
*, num_entries
+ 1);
1804 state
->rc
= TLDAP_NO_MEMORY
;
1807 state
->entries
= tmp
;
1808 state
->entries
[num_entries
] = talloc_move(state
->entries
,
1811 case TLDAP_RES_SEARCH_REFERENCE
:
1812 num_refs
= talloc_array_length(state
->refs
);
1813 tmp
= talloc_realloc(state
->mem_ctx
, state
->refs
,
1814 struct tldap_message
*, num_refs
+ 1);
1816 state
->rc
= TLDAP_NO_MEMORY
;
1820 state
->refs
[num_refs
] = talloc_move(state
->refs
, &msg
);
1822 case TLDAP_RES_SEARCH_RESULT
:
1823 state
->rc
= TLDAP_SUCCESS
;
1826 state
->rc
= TLDAP_PROTOCOL_ERROR
;
1831 int tldap_search(struct tldap_context
*ld
,
1832 const char *base
, int scope
, const char *filter
,
1833 const char **attrs
, int num_attrs
, int attrsonly
,
1834 struct tldap_control
*sctrls
, int num_sctrls
,
1835 struct tldap_control
*cctrls
, int num_cctrls
,
1836 int timelimit
, int sizelimit
, int deref
,
1837 TALLOC_CTX
*mem_ctx
, struct tldap_message
***entries
,
1838 struct tldap_message
***refs
)
1840 TALLOC_CTX
*frame
= talloc_stackframe();
1841 struct tevent_context
*ev
;
1842 struct tevent_req
*req
;
1843 struct tldap_sync_search_state state
= {
1844 .mem_ctx
= mem_ctx
, .rc
= TLDAP_SUCCESS
1847 ev
= samba_tevent_context_init(frame
);
1849 state
.rc
= TLDAP_NO_MEMORY
;
1853 req
= tldap_search_send(frame
, ev
, ld
, base
, scope
, filter
,
1854 attrs
, num_attrs
, attrsonly
,
1855 sctrls
, num_sctrls
, cctrls
, num_cctrls
,
1856 timelimit
, sizelimit
, deref
);
1858 state
.rc
= TLDAP_NO_MEMORY
;
1862 tevent_req_set_callback(req
, tldap_search_cb
, &state
);
1864 if (!tevent_req_is_in_progress(req
)) {
1865 /* an error happend before sending */
1866 if (tevent_req_is_ldap_error(req
, &state
.rc
)) {
1871 while (tevent_req_is_in_progress(req
)
1872 && (state
.rc
== TLDAP_SUCCESS
)) {
1873 if (tevent_loop_once(ev
) == -1) {
1874 return TLDAP_OPERATIONS_ERROR
;
1878 if (state
.rc
!= TLDAP_SUCCESS
) {
1882 if (entries
!= NULL
) {
1883 *entries
= state
.entries
;
1885 TALLOC_FREE(state
.entries
);
1890 TALLOC_FREE(state
.refs
);
1892 tldap_save_msg(ld
, req
);
1898 static bool tldap_parse_search_entry(struct tldap_message
*msg
)
1900 int num_attribs
= 0;
1902 if (!asn1_start_tag(msg
->data
, msg
->type
)) return false;
1906 if (!asn1_read_OctetString_talloc(msg
, msg
->data
, &msg
->dn
)) return false;
1908 if (msg
->dn
== NULL
) {
1913 * Attributes: We overallocate msg->attribs by one, so that while
1914 * looping over the attributes we can directly parse into the last
1915 * array element. Same for the values in the inner loop.
1918 msg
->attribs
= talloc_array(msg
, struct tldap_attribute
, 1);
1919 if (msg
->attribs
== NULL
) {
1923 if (!asn1_start_tag(msg
->data
, ASN1_SEQUENCE(0))) return false;
1924 while (asn1_peek_tag(msg
->data
, ASN1_SEQUENCE(0))) {
1925 struct tldap_attribute
*attrib
;
1928 attrib
= &msg
->attribs
[num_attribs
];
1929 attrib
->values
= talloc_array(msg
->attribs
, DATA_BLOB
, 1);
1930 if (attrib
->values
== NULL
) {
1933 if (!asn1_start_tag(msg
->data
, ASN1_SEQUENCE(0))) return false;
1934 if (!asn1_read_OctetString_talloc(msg
->attribs
, msg
->data
,
1935 &attrib
->name
)) return false;
1936 if (!asn1_start_tag(msg
->data
, ASN1_SET
)) return false;
1938 while (asn1_peek_tag(msg
->data
, ASN1_OCTET_STRING
)) {
1939 if (!asn1_read_OctetString(msg
->data
, msg
,
1940 &attrib
->values
[num_values
])) return false;
1942 attrib
->values
= talloc_realloc(
1943 msg
->attribs
, attrib
->values
, DATA_BLOB
,
1945 if (attrib
->values
== NULL
) {
1950 attrib
->values
= talloc_realloc(msg
->attribs
, attrib
->values
,
1951 DATA_BLOB
, num_values
);
1952 attrib
->num_values
= num_values
;
1954 if (!asn1_end_tag(msg
->data
)) return false; /* ASN1_SET */
1955 if (!asn1_end_tag(msg
->data
)) return false; /* ASN1_SEQUENCE(0) */
1956 msg
->attribs
= talloc_realloc(
1957 msg
, msg
->attribs
, struct tldap_attribute
,
1959 if (msg
->attribs
== NULL
) {
1964 msg
->attribs
= talloc_realloc(
1965 msg
, msg
->attribs
, struct tldap_attribute
, num_attribs
);
1966 return asn1_end_tag(msg
->data
);
1969 bool tldap_entry_dn(struct tldap_message
*msg
, char **dn
)
1971 if ((msg
->dn
== NULL
) && (!tldap_parse_search_entry(msg
))) {
1978 bool tldap_entry_attributes(struct tldap_message
*msg
,
1979 struct tldap_attribute
**attributes
,
1980 int *num_attributes
)
1982 if ((msg
->dn
== NULL
) && (!tldap_parse_search_entry(msg
))) {
1985 *attributes
= msg
->attribs
;
1986 *num_attributes
= talloc_array_length(msg
->attribs
);
1990 static bool tldap_decode_controls(struct tldap_req_state
*state
)
1992 struct tldap_message
*msg
= state
->result
;
1993 struct asn1_data
*data
= msg
->data
;
1994 struct tldap_control
*sctrls
= NULL
;
1995 int num_controls
= 0;
1998 msg
->res_sctrls
= NULL
;
2000 if (!asn1_peek_tag(data
, ASN1_CONTEXT(0))) {
2004 if (!asn1_start_tag(data
, ASN1_CONTEXT(0))) goto out
;
2006 while (asn1_peek_tag(data
, ASN1_SEQUENCE(0))) {
2007 struct tldap_control
*c
;
2010 sctrls
= talloc_realloc(msg
, sctrls
, struct tldap_control
,
2012 if (sctrls
== NULL
) {
2015 c
= &sctrls
[num_controls
];
2017 if (!asn1_start_tag(data
, ASN1_SEQUENCE(0))) goto out
;
2018 if (!asn1_read_OctetString_talloc(msg
, data
, &oid
)) goto out
;
2019 if (asn1_has_error(data
) || (oid
== NULL
)) {
2023 if (asn1_peek_tag(data
, ASN1_BOOLEAN
)) {
2024 if (!asn1_read_BOOLEAN(data
, &c
->critical
)) goto out
;
2026 c
->critical
= false;
2028 c
->value
= data_blob_null
;
2029 if (asn1_peek_tag(data
, ASN1_OCTET_STRING
) &&
2030 !asn1_read_OctetString(data
, msg
, &c
->value
)) {
2033 if (!asn1_end_tag(data
)) goto out
; /* ASN1_SEQUENCE(0) */
2038 if (!asn1_end_tag(data
)) goto out
; /* ASN1_CONTEXT(0) */
2045 TALLOC_FREE(sctrls
);
2047 msg
->res_sctrls
= sctrls
;
2052 static void tldap_simple_done(struct tevent_req
*subreq
, int type
)
2054 struct tevent_req
*req
= tevent_req_callback_data(
2055 subreq
, struct tevent_req
);
2056 struct tldap_req_state
*state
= tevent_req_data(
2057 req
, struct tldap_req_state
);
2060 err
= tldap_msg_recv(subreq
, state
, &state
->result
);
2061 TALLOC_FREE(subreq
);
2062 if (err
!= TLDAP_SUCCESS
) {
2063 tevent_req_error(req
, err
);
2066 if (state
->result
->type
!= type
) {
2067 tevent_req_error(req
, TLDAP_PROTOCOL_ERROR
);
2070 if (!asn1_start_tag(state
->result
->data
, state
->result
->type
) ||
2071 !tldap_decode_response(state
) ||
2072 !asn1_end_tag(state
->result
->data
) ||
2073 !tldap_decode_controls(state
)) {
2074 tevent_req_error(req
, TLDAP_DECODING_ERROR
);
2077 if (state
->result
->lderr
!= TLDAP_SUCCESS
) {
2078 tevent_req_error(req
, state
->result
->lderr
);
2081 tevent_req_done(req
);
2084 static int tldap_simple_recv(struct tevent_req
*req
)
2087 if (tevent_req_is_ldap_error(req
, &err
)) {
2090 return TLDAP_SUCCESS
;
2093 static void tldap_add_done(struct tevent_req
*subreq
);
2095 struct tevent_req
*tldap_add_send(TALLOC_CTX
*mem_ctx
,
2096 struct tevent_context
*ev
,
2097 struct tldap_context
*ld
,
2099 struct tldap_mod
*attributes
,
2101 struct tldap_control
*sctrls
,
2103 struct tldap_control
*cctrls
,
2106 struct tevent_req
*req
, *subreq
;
2107 struct tldap_req_state
*state
;
2110 req
= tldap_req_create(mem_ctx
, ld
, &state
);
2115 if (!asn1_push_tag(state
->out
, TLDAP_REQ_ADD
)) goto err
;
2116 if (!asn1_write_OctetString(state
->out
, dn
, strlen(dn
))) goto err
;
2117 if (!asn1_push_tag(state
->out
, ASN1_SEQUENCE(0))) goto err
;
2119 for (i
=0; i
<num_attributes
; i
++) {
2120 struct tldap_mod
*attrib
= &attributes
[i
];
2121 if (!asn1_push_tag(state
->out
, ASN1_SEQUENCE(0))) goto err
;
2122 if (!asn1_write_OctetString(state
->out
, attrib
->attribute
,
2123 strlen(attrib
->attribute
))) goto err
;
2124 if (!asn1_push_tag(state
->out
, ASN1_SET
)) goto err
;
2125 for (j
=0; j
<attrib
->num_values
; j
++) {
2126 if (!asn1_write_OctetString(state
->out
,
2127 attrib
->values
[j
].data
,
2128 attrib
->values
[j
].length
)) goto err
;
2130 if (!asn1_pop_tag(state
->out
)) goto err
;
2131 if (!asn1_pop_tag(state
->out
)) goto err
;
2134 if (!asn1_pop_tag(state
->out
)) goto err
;
2135 if (!asn1_pop_tag(state
->out
)) goto err
;
2137 subreq
= tldap_msg_send(state
, ev
, ld
, state
->id
, state
->out
,
2138 sctrls
, num_sctrls
);
2139 if (tevent_req_nomem(subreq
, req
)) {
2140 return tevent_req_post(req
, ev
);
2142 tevent_req_set_callback(subreq
, tldap_add_done
, req
);
2147 tevent_req_error(req
, TLDAP_ENCODING_ERROR
);
2148 return tevent_req_post(req
, ev
);
2151 static void tldap_add_done(struct tevent_req
*subreq
)
2153 tldap_simple_done(subreq
, TLDAP_RES_ADD
);
2156 int tldap_add_recv(struct tevent_req
*req
)
2158 return tldap_simple_recv(req
);
2161 int tldap_add(struct tldap_context
*ld
, const char *dn
,
2162 struct tldap_mod
*attributes
, int num_attributes
,
2163 struct tldap_control
*sctrls
, int num_sctrls
,
2164 struct tldap_control
*cctrls
, int num_cctrls
)
2166 TALLOC_CTX
*frame
= talloc_stackframe();
2167 struct tevent_context
*ev
;
2168 struct tevent_req
*req
;
2171 ev
= samba_tevent_context_init(frame
);
2173 result
= TLDAP_NO_MEMORY
;
2177 req
= tldap_add_send(frame
, ev
, ld
, dn
, attributes
, num_attributes
,
2178 sctrls
, num_sctrls
, cctrls
, num_cctrls
);
2180 result
= TLDAP_NO_MEMORY
;
2184 if (!tevent_req_poll(req
, ev
)) {
2185 result
= TLDAP_OPERATIONS_ERROR
;
2189 result
= tldap_add_recv(req
);
2190 tldap_save_msg(ld
, req
);
2196 static void tldap_modify_done(struct tevent_req
*subreq
);
2198 struct tevent_req
*tldap_modify_send(TALLOC_CTX
*mem_ctx
,
2199 struct tevent_context
*ev
,
2200 struct tldap_context
*ld
,
2202 struct tldap_mod
*mods
, int num_mods
,
2203 struct tldap_control
*sctrls
,
2205 struct tldap_control
*cctrls
,
2208 struct tevent_req
*req
, *subreq
;
2209 struct tldap_req_state
*state
;
2212 req
= tldap_req_create(mem_ctx
, ld
, &state
);
2217 if (!asn1_push_tag(state
->out
, TLDAP_REQ_MODIFY
)) goto err
;
2218 if (!asn1_write_OctetString(state
->out
, dn
, strlen(dn
))) goto err
;
2219 if (!asn1_push_tag(state
->out
, ASN1_SEQUENCE(0))) goto err
;
2221 for (i
=0; i
<num_mods
; i
++) {
2222 struct tldap_mod
*mod
= &mods
[i
];
2223 if (!asn1_push_tag(state
->out
, ASN1_SEQUENCE(0))) goto err
;
2224 if (!asn1_write_enumerated(state
->out
, mod
->mod_op
)) goto err
;
2225 if (!asn1_push_tag(state
->out
, ASN1_SEQUENCE(0))) goto err
;
2226 if (!asn1_write_OctetString(state
->out
, mod
->attribute
,
2227 strlen(mod
->attribute
))) goto err
;
2228 if (!asn1_push_tag(state
->out
, ASN1_SET
)) goto err
;
2229 for (j
=0; j
<mod
->num_values
; j
++) {
2230 if (!asn1_write_OctetString(state
->out
,
2231 mod
->values
[j
].data
,
2232 mod
->values
[j
].length
)) goto err
;
2234 if (!asn1_pop_tag(state
->out
)) goto err
;
2235 if (!asn1_pop_tag(state
->out
)) goto err
;
2236 if (!asn1_pop_tag(state
->out
)) goto err
;
2239 if (!asn1_pop_tag(state
->out
)) goto err
;
2240 if (!asn1_pop_tag(state
->out
)) goto err
;
2242 subreq
= tldap_msg_send(state
, ev
, ld
, state
->id
, state
->out
,
2243 sctrls
, num_sctrls
);
2244 if (tevent_req_nomem(subreq
, req
)) {
2245 return tevent_req_post(req
, ev
);
2247 tevent_req_set_callback(subreq
, tldap_modify_done
, req
);
2252 tevent_req_error(req
, TLDAP_ENCODING_ERROR
);
2253 return tevent_req_post(req
, ev
);
2256 static void tldap_modify_done(struct tevent_req
*subreq
)
2258 tldap_simple_done(subreq
, TLDAP_RES_MODIFY
);
2261 int tldap_modify_recv(struct tevent_req
*req
)
2263 return tldap_simple_recv(req
);
2266 int tldap_modify(struct tldap_context
*ld
, const char *dn
,
2267 struct tldap_mod
*mods
, int num_mods
,
2268 struct tldap_control
*sctrls
, int num_sctrls
,
2269 struct tldap_control
*cctrls
, int num_cctrls
)
2271 TALLOC_CTX
*frame
= talloc_stackframe();
2272 struct tevent_context
*ev
;
2273 struct tevent_req
*req
;
2276 ev
= samba_tevent_context_init(frame
);
2278 result
= TLDAP_NO_MEMORY
;
2282 req
= tldap_modify_send(frame
, ev
, ld
, dn
, mods
, num_mods
,
2283 sctrls
, num_sctrls
, cctrls
, num_cctrls
);
2285 result
= TLDAP_NO_MEMORY
;
2289 if (!tevent_req_poll(req
, ev
)) {
2290 result
= TLDAP_OPERATIONS_ERROR
;
2294 result
= tldap_modify_recv(req
);
2295 tldap_save_msg(ld
, req
);
2301 static void tldap_delete_done(struct tevent_req
*subreq
);
2303 struct tevent_req
*tldap_delete_send(TALLOC_CTX
*mem_ctx
,
2304 struct tevent_context
*ev
,
2305 struct tldap_context
*ld
,
2307 struct tldap_control
*sctrls
,
2309 struct tldap_control
*cctrls
,
2312 struct tevent_req
*req
, *subreq
;
2313 struct tldap_req_state
*state
;
2315 req
= tldap_req_create(mem_ctx
, ld
, &state
);
2320 if (!asn1_push_tag(state
->out
, TLDAP_REQ_DELETE
)) goto err
;
2321 if (!asn1_write(state
->out
, dn
, strlen(dn
))) goto err
;
2322 if (!asn1_pop_tag(state
->out
)) goto err
;
2324 subreq
= tldap_msg_send(state
, ev
, ld
, state
->id
, state
->out
,
2325 sctrls
, num_sctrls
);
2326 if (tevent_req_nomem(subreq
, req
)) {
2327 return tevent_req_post(req
, ev
);
2329 tevent_req_set_callback(subreq
, tldap_delete_done
, req
);
2334 tevent_req_error(req
, TLDAP_ENCODING_ERROR
);
2335 return tevent_req_post(req
, ev
);
2338 static void tldap_delete_done(struct tevent_req
*subreq
)
2340 tldap_simple_done(subreq
, TLDAP_RES_DELETE
);
2343 int tldap_delete_recv(struct tevent_req
*req
)
2345 return tldap_simple_recv(req
);
2348 int tldap_delete(struct tldap_context
*ld
, const char *dn
,
2349 struct tldap_control
*sctrls
, int num_sctrls
,
2350 struct tldap_control
*cctrls
, int num_cctrls
)
2352 TALLOC_CTX
*frame
= talloc_stackframe();
2353 struct tevent_context
*ev
;
2354 struct tevent_req
*req
;
2357 ev
= samba_tevent_context_init(frame
);
2359 result
= TLDAP_NO_MEMORY
;
2363 req
= tldap_delete_send(frame
, ev
, ld
, dn
, sctrls
, num_sctrls
,
2364 cctrls
, num_cctrls
);
2366 result
= TLDAP_NO_MEMORY
;
2370 if (!tevent_req_poll(req
, ev
)) {
2371 result
= TLDAP_OPERATIONS_ERROR
;
2375 result
= tldap_delete_recv(req
);
2376 tldap_save_msg(ld
, req
);
2382 int tldap_msg_id(const struct tldap_message
*msg
)
2387 int tldap_msg_type(const struct tldap_message
*msg
)
2392 const char *tldap_msg_matcheddn(struct tldap_message
*msg
)
2397 return msg
->res_matcheddn
;
2400 const char *tldap_msg_diagnosticmessage(struct tldap_message
*msg
)
2405 return msg
->res_diagnosticmessage
;
2408 const char *tldap_msg_referral(struct tldap_message
*msg
)
2413 return msg
->res_referral
;
2416 void tldap_msg_sctrls(struct tldap_message
*msg
, int *num_sctrls
,
2417 struct tldap_control
**sctrls
)
2424 *sctrls
= msg
->res_sctrls
;
2425 *num_sctrls
= talloc_array_length(msg
->res_sctrls
);
2428 struct tldap_message
*tldap_ctx_lastmsg(struct tldap_context
*ld
)
2430 return ld
->last_msg
;
2433 const char *tldap_err2string(int rc
)
2435 const char *res
= NULL
;
2438 * This would normally be a table, but the error codes are not fully
2439 * sequential. Let the compiler figure out the optimum implementation
2445 res
= "TLDAP_SUCCESS";
2447 case TLDAP_OPERATIONS_ERROR
:
2448 res
= "TLDAP_OPERATIONS_ERROR";
2450 case TLDAP_PROTOCOL_ERROR
:
2451 res
= "TLDAP_PROTOCOL_ERROR";
2453 case TLDAP_TIMELIMIT_EXCEEDED
:
2454 res
= "TLDAP_TIMELIMIT_EXCEEDED";
2456 case TLDAP_SIZELIMIT_EXCEEDED
:
2457 res
= "TLDAP_SIZELIMIT_EXCEEDED";
2459 case TLDAP_COMPARE_FALSE
:
2460 res
= "TLDAP_COMPARE_FALSE";
2462 case TLDAP_COMPARE_TRUE
:
2463 res
= "TLDAP_COMPARE_TRUE";
2465 case TLDAP_STRONG_AUTH_NOT_SUPPORTED
:
2466 res
= "TLDAP_STRONG_AUTH_NOT_SUPPORTED";
2468 case TLDAP_STRONG_AUTH_REQUIRED
:
2469 res
= "TLDAP_STRONG_AUTH_REQUIRED";
2471 case TLDAP_REFERRAL
:
2472 res
= "TLDAP_REFERRAL";
2474 case TLDAP_ADMINLIMIT_EXCEEDED
:
2475 res
= "TLDAP_ADMINLIMIT_EXCEEDED";
2477 case TLDAP_UNAVAILABLE_CRITICAL_EXTENSION
:
2478 res
= "TLDAP_UNAVAILABLE_CRITICAL_EXTENSION";
2480 case TLDAP_CONFIDENTIALITY_REQUIRED
:
2481 res
= "TLDAP_CONFIDENTIALITY_REQUIRED";
2483 case TLDAP_SASL_BIND_IN_PROGRESS
:
2484 res
= "TLDAP_SASL_BIND_IN_PROGRESS";
2486 case TLDAP_NO_SUCH_ATTRIBUTE
:
2487 res
= "TLDAP_NO_SUCH_ATTRIBUTE";
2489 case TLDAP_UNDEFINED_TYPE
:
2490 res
= "TLDAP_UNDEFINED_TYPE";
2492 case TLDAP_INAPPROPRIATE_MATCHING
:
2493 res
= "TLDAP_INAPPROPRIATE_MATCHING";
2495 case TLDAP_CONSTRAINT_VIOLATION
:
2496 res
= "TLDAP_CONSTRAINT_VIOLATION";
2498 case TLDAP_TYPE_OR_VALUE_EXISTS
:
2499 res
= "TLDAP_TYPE_OR_VALUE_EXISTS";
2501 case TLDAP_INVALID_SYNTAX
:
2502 res
= "TLDAP_INVALID_SYNTAX";
2504 case TLDAP_NO_SUCH_OBJECT
:
2505 res
= "TLDAP_NO_SUCH_OBJECT";
2507 case TLDAP_ALIAS_PROBLEM
:
2508 res
= "TLDAP_ALIAS_PROBLEM";
2510 case TLDAP_INVALID_DN_SYNTAX
:
2511 res
= "TLDAP_INVALID_DN_SYNTAX";
2514 res
= "TLDAP_IS_LEAF";
2516 case TLDAP_ALIAS_DEREF_PROBLEM
:
2517 res
= "TLDAP_ALIAS_DEREF_PROBLEM";
2519 case TLDAP_INAPPROPRIATE_AUTH
:
2520 res
= "TLDAP_INAPPROPRIATE_AUTH";
2522 case TLDAP_INVALID_CREDENTIALS
:
2523 res
= "TLDAP_INVALID_CREDENTIALS";
2525 case TLDAP_INSUFFICIENT_ACCESS
:
2526 res
= "TLDAP_INSUFFICIENT_ACCESS";
2531 case TLDAP_UNAVAILABLE
:
2532 res
= "TLDAP_UNAVAILABLE";
2534 case TLDAP_UNWILLING_TO_PERFORM
:
2535 res
= "TLDAP_UNWILLING_TO_PERFORM";
2537 case TLDAP_LOOP_DETECT
:
2538 res
= "TLDAP_LOOP_DETECT";
2540 case TLDAP_NAMING_VIOLATION
:
2541 res
= "TLDAP_NAMING_VIOLATION";
2543 case TLDAP_OBJECT_CLASS_VIOLATION
:
2544 res
= "TLDAP_OBJECT_CLASS_VIOLATION";
2546 case TLDAP_NOT_ALLOWED_ON_NONLEAF
:
2547 res
= "TLDAP_NOT_ALLOWED_ON_NONLEAF";
2549 case TLDAP_NOT_ALLOWED_ON_RDN
:
2550 res
= "TLDAP_NOT_ALLOWED_ON_RDN";
2552 case TLDAP_ALREADY_EXISTS
:
2553 res
= "TLDAP_ALREADY_EXISTS";
2555 case TLDAP_NO_OBJECT_CLASS_MODS
:
2556 res
= "TLDAP_NO_OBJECT_CLASS_MODS";
2558 case TLDAP_RESULTS_TOO_LARGE
:
2559 res
= "TLDAP_RESULTS_TOO_LARGE";
2561 case TLDAP_AFFECTS_MULTIPLE_DSAS
:
2562 res
= "TLDAP_AFFECTS_MULTIPLE_DSAS";
2565 res
= "TLDAP_OTHER";
2567 case TLDAP_SERVER_DOWN
:
2568 res
= "TLDAP_SERVER_DOWN";
2570 case TLDAP_LOCAL_ERROR
:
2571 res
= "TLDAP_LOCAL_ERROR";
2573 case TLDAP_ENCODING_ERROR
:
2574 res
= "TLDAP_ENCODING_ERROR";
2576 case TLDAP_DECODING_ERROR
:
2577 res
= "TLDAP_DECODING_ERROR";
2580 res
= "TLDAP_TIMEOUT";
2582 case TLDAP_AUTH_UNKNOWN
:
2583 res
= "TLDAP_AUTH_UNKNOWN";
2585 case TLDAP_FILTER_ERROR
:
2586 res
= "TLDAP_FILTER_ERROR";
2588 case TLDAP_USER_CANCELLED
:
2589 res
= "TLDAP_USER_CANCELLED";
2591 case TLDAP_PARAM_ERROR
:
2592 res
= "TLDAP_PARAM_ERROR";
2594 case TLDAP_NO_MEMORY
:
2595 res
= "TLDAP_NO_MEMORY";
2597 case TLDAP_CONNECT_ERROR
:
2598 res
= "TLDAP_CONNECT_ERROR";
2600 case TLDAP_NOT_SUPPORTED
:
2601 res
= "TLDAP_NOT_SUPPORTED";
2603 case TLDAP_CONTROL_NOT_FOUND
:
2604 res
= "TLDAP_CONTROL_NOT_FOUND";
2606 case TLDAP_NO_RESULTS_RETURNED
:
2607 res
= "TLDAP_NO_RESULTS_RETURNED";
2609 case TLDAP_MORE_RESULTS_TO_RETURN
:
2610 res
= "TLDAP_MORE_RESULTS_TO_RETURN";
2612 case TLDAP_CLIENT_LOOP
:
2613 res
= "TLDAP_CLIENT_LOOP";
2615 case TLDAP_REFERRAL_LIMIT_EXCEEDED
:
2616 res
= "TLDAP_REFERRAL_LIMIT_EXCEEDED";
2619 res
= talloc_asprintf(talloc_tos(), "Unknown LDAP Error (%d)",
2624 res
= "Unknown LDAP Error";