1/* 2 Unix SMB/CIFS implementation. 3 4 cldap client library 5 6 Copyright (C) Andrew Tridgell 2005 7 Copyright (C) Stefan Metzmacher 2009 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 21*/ 22 23/* 24 see RFC1798 for details of CLDAP 25 26 basic properties 27 - carried over UDP on port 389 28 - request and response matched by message ID 29 - request consists of only a single searchRequest element 30 - response can be in one of two forms 31 - a single searchResponse, followed by a searchResult 32 - a single searchResult 33*/ 34 35#include "includes.h" 36#include <tevent.h> 37#include "../lib/util/dlinklist.h" 38#include "../libcli/ldap/ldap_message.h" 39#include "../libcli/ldap/ldap_ndr.h" 40#include "../libcli/cldap/cldap.h" 41#include "../lib/tsocket/tsocket.h" 42#include "../libcli/security/dom_sid.h" 43#include "../librpc/gen_ndr/ndr_nbt.h" 44#include "../lib/util/asn1.h" 45#include "../lib/util/tevent_ntstatus.h" 46 47#undef strcasecmp 48 49/* 50 context structure for operations on cldap packets 51*/ 52struct cldap_socket { 53 /* the low level socket */ 54 struct tdgram_context *sock; 55 56 /* 57 * Are we in connected mode, which means 58 * we get ICMP errors back instead of timing 59 * out requests. And we can only send requests 60 * to the connected peer. 61 */ 62 bool connected; 63 64 /* 65 * we allow sync requests only, if the caller 66 * did not pass an event context to cldap_socket_init() 67 */ 68 struct { 69 bool allow_poll; 70 struct tevent_context *ctx; 71 } event; 72 73 /* the queue for outgoing dgrams */ 74 struct tevent_queue *send_queue; 75 76 /* do we have an async tsocket_recvfrom request pending */ 77 struct tevent_req *recv_subreq; 78 79 struct { 80 /* a queue of pending search requests */ 81 struct cldap_search_state *list; 82 83 /* mapping from message_id to pending request */ 84 struct idr_context *idr; 85 } searches; 86 87 /* what to do with incoming request packets */ 88 struct { 89 void (*handler)(struct cldap_socket *, 90 void *private_data, 91 struct cldap_incoming *); 92 void *private_data; 93 } incoming; 94}; 95 96struct cldap_search_state { 97 struct cldap_search_state *prev, *next; 98 99 struct { 100 struct cldap_socket *cldap; 101 } caller; 102 103 int message_id; 104 105 struct { 106 uint32_t idx; 107 uint32_t delay; 108 uint32_t count; 109 struct tsocket_address *dest; 110 DATA_BLOB blob; 111 } request; 112 113 struct { 114 struct cldap_incoming *in; 115 struct asn1_data *asn1; 116 } response; 117 118 struct tevent_req *req; 119}; 120 121static int cldap_socket_destructor(struct cldap_socket *c) 122{ 123 while (c->searches.list) { 124 struct cldap_search_state *s = c->searches.list; 125 DLIST_REMOVE(c->searches.list, s); 126 ZERO_STRUCT(s->caller); 127 } 128 129 talloc_free(c->recv_subreq); 130 talloc_free(c->send_queue); 131 talloc_free(c->sock); 132 return 0; 133} 134 135static void cldap_recvfrom_done(struct tevent_req *subreq); 136 137static bool cldap_recvfrom_setup(struct cldap_socket *c) 138{ 139 if (c->recv_subreq) { 140 return true; 141 } 142 143 if (!c->searches.list && !c->incoming.handler) { 144 return true; 145 } 146 147 c->recv_subreq = tdgram_recvfrom_send(c, c->event.ctx, c->sock); 148 if (!c->recv_subreq) { 149 return false; 150 } 151 tevent_req_set_callback(c->recv_subreq, cldap_recvfrom_done, c); 152 153 return true; 154} 155 156static void cldap_recvfrom_stop(struct cldap_socket *c) 157{ 158 if (!c->recv_subreq) { 159 return; 160 } 161 162 if (c->searches.list || c->incoming.handler) { 163 return; 164 } 165 166 talloc_free(c->recv_subreq); 167 c->recv_subreq = NULL; 168} 169 170static void cldap_socket_recv_dgram(struct cldap_socket *c, 171 struct cldap_incoming *in); 172 173static void cldap_recvfrom_done(struct tevent_req *subreq) 174{ 175 struct cldap_socket *c = tevent_req_callback_data(subreq, 176 struct cldap_socket); 177 struct cldap_incoming *in = NULL; 178 ssize_t ret; 179 180 c->recv_subreq = NULL; 181 182 in = talloc_zero(c, struct cldap_incoming); 183 if (!in) { 184 goto nomem; 185 } 186 187 ret = tdgram_recvfrom_recv(subreq, 188 &in->recv_errno, 189 in, 190 &in->buf, 191 &in->src); 192 talloc_free(subreq); 193 subreq = NULL; 194 if (ret >= 0) { 195 in->len = ret; 196 } 197 if (ret == -1 && in->recv_errno == 0) { 198 in->recv_errno = EIO; 199 } 200 201 /* this function should free or steal 'in' */ 202 cldap_socket_recv_dgram(c, in); 203 in = NULL; 204 205 if (!cldap_recvfrom_setup(c)) { 206 goto nomem; 207 } 208 209 return; 210 211nomem: 212 talloc_free(subreq); 213 talloc_free(in); 214 /*TODO: call a dead socket handler */ 215 return; 216} 217 218/* 219 handle recv events on a cldap socket 220*/ 221static void cldap_socket_recv_dgram(struct cldap_socket *c, 222 struct cldap_incoming *in) 223{ 224 DATA_BLOB blob; 225 struct asn1_data *asn1; 226 void *p; 227 struct cldap_search_state *search; 228 NTSTATUS status; 229 230 if (in->recv_errno != 0) { 231 goto error; 232 } 233 234 blob = data_blob_const(in->buf, in->len); 235 236 asn1 = asn1_init(in); 237 if (!asn1) { 238 goto nomem; 239 } 240 241 if (!asn1_load(asn1, blob)) { 242 goto nomem; 243 } 244 245 in->ldap_msg = talloc(in, struct ldap_message); 246 if (in->ldap_msg == NULL) { 247 goto nomem; 248 } 249 250 /* this initial decode is used to find the message id */ 251 status = ldap_decode(asn1, NULL, in->ldap_msg); 252 if (!NT_STATUS_IS_OK(status)) { 253 goto nterror; 254 } 255 256 /* find the pending request */ 257 p = idr_find(c->searches.idr, in->ldap_msg->messageid); 258 if (p == NULL) { 259 if (!c->incoming.handler) { 260 goto done; 261 } 262 263 /* this function should free or steal 'in' */ 264 c->incoming.handler(c, c->incoming.private_data, in); 265 return; 266 } 267 268 search = talloc_get_type(p, struct cldap_search_state); 269 search->response.in = talloc_move(search, &in); 270 search->response.asn1 = asn1; 271 search->response.asn1->ofs = 0; 272 273 tevent_req_done(search->req); 274 goto done; 275 276nomem: 277 in->recv_errno = ENOMEM; 278error: 279 status = map_nt_error_from_unix(in->recv_errno); 280nterror: 281 /* in connected mode the first pending search gets the error */ 282 if (!c->connected) { 283 /* otherwise we just ignore the error */ 284 goto done; 285 } 286 if (!c->searches.list) { 287 goto done; 288 } 289 tevent_req_nterror(c->searches.list->req, status); 290done: 291 talloc_free(in); 292} 293 294/* 295 initialise a cldap_sock 296*/ 297NTSTATUS cldap_socket_init(TALLOC_CTX *mem_ctx, 298 struct tevent_context *ev, 299 const struct tsocket_address *local_addr, 300 const struct tsocket_address *remote_addr, 301 struct cldap_socket **_cldap) 302{ 303 struct cldap_socket *c = NULL; 304 struct tsocket_address *any = NULL; 305 NTSTATUS status; 306 int ret; 307 308 c = talloc_zero(mem_ctx, struct cldap_socket); 309 if (!c) { 310 goto nomem; 311 } 312 313 if (!ev) { 314 ev = tevent_context_init(c); 315 if (!ev) { 316 goto nomem; 317 } 318 c->event.allow_poll = true; 319 } 320 c->event.ctx = ev; 321 322 if (!local_addr) { 323 ret = tsocket_address_inet_from_strings(c, "ip", 324 NULL, 0, 325 &any); 326 if (ret != 0) { 327 status = map_nt_error_from_unix(errno); 328 goto nterror; 329 } 330 local_addr = any; 331 } 332 333 c->searches.idr = idr_init(c); 334 if (!c->searches.idr) { 335 goto nomem; 336 } 337 338 ret = tdgram_inet_udp_socket(local_addr, remote_addr, 339 c, &c->sock); 340 if (ret != 0) { 341 status = map_nt_error_from_unix(errno); 342 goto nterror; 343 } 344 talloc_free(any); 345 346 if (remote_addr) { 347 c->connected = true; 348 } 349 350 c->send_queue = tevent_queue_create(c, "cldap_send_queue"); 351 if (!c->send_queue) { 352 goto nomem; 353 } 354 355 talloc_set_destructor(c, cldap_socket_destructor); 356 357 *_cldap = c; 358 return NT_STATUS_OK; 359 360nomem: 361 status = NT_STATUS_NO_MEMORY; 362nterror: 363 talloc_free(c); 364 return status; 365} 366 367/* 368 setup a handler for incoming requests 369*/ 370NTSTATUS cldap_set_incoming_handler(struct cldap_socket *c, 371 void (*handler)(struct cldap_socket *, 372 void *private_data, 373 struct cldap_incoming *), 374 void *private_data) 375{ 376 if (c->connected) { 377 return NT_STATUS_PIPE_CONNECTED; 378 } 379 380 /* if sync requests are allowed, we don't allow an incoming handler */ 381 if (c->event.allow_poll) { 382 return NT_STATUS_INVALID_PIPE_STATE; 383 } 384 385 c->incoming.handler = handler; 386 c->incoming.private_data = private_data; 387 388 if (!cldap_recvfrom_setup(c)) { 389 ZERO_STRUCT(c->incoming); 390 return NT_STATUS_NO_MEMORY; 391 } 392 393 return NT_STATUS_OK; 394} 395 396struct cldap_reply_state { 397 struct tsocket_address *dest; 398 DATA_BLOB blob; 399}; 400 401static void cldap_reply_state_destroy(struct tevent_req *subreq); 402 403/* 404 queue a cldap reply for send 405*/ 406NTSTATUS cldap_reply_send(struct cldap_socket *cldap, struct cldap_reply *io) 407{ 408 struct cldap_reply_state *state = NULL; 409 struct ldap_message *msg; 410 DATA_BLOB blob1, blob2; 411 NTSTATUS status; 412 struct tevent_req *subreq; 413 414 if (cldap->connected) { 415 return NT_STATUS_PIPE_CONNECTED; 416 } 417 418 if (!io->dest) { 419 return NT_STATUS_INVALID_ADDRESS; 420 } 421 422 state = talloc(cldap, struct cldap_reply_state); 423 NT_STATUS_HAVE_NO_MEMORY(state); 424 425 state->dest = tsocket_address_copy(io->dest, state); 426 if (!state->dest) { 427 goto nomem; 428 } 429 430 msg = talloc(state, struct ldap_message); 431 if (!msg) { 432 goto nomem; 433 } 434 435 msg->messageid = io->messageid; 436 msg->controls = NULL; 437 438 if (io->response) { 439 msg->type = LDAP_TAG_SearchResultEntry; 440 msg->r.SearchResultEntry = *io->response; 441 442 if (!ldap_encode(msg, NULL, &blob1, state)) { 443 status = NT_STATUS_INVALID_PARAMETER; 444 goto failed; 445 } 446 } else { 447 blob1 = data_blob(NULL, 0); 448 } 449 450 msg->type = LDAP_TAG_SearchResultDone; 451 msg->r.SearchResultDone = *io->result; 452 453 if (!ldap_encode(msg, NULL, &blob2, state)) { 454 status = NT_STATUS_INVALID_PARAMETER; 455 goto failed; 456 } 457 talloc_free(msg); 458 459 state->blob = data_blob_talloc(state, NULL, blob1.length + blob2.length); 460 if (!state->blob.data) { 461 goto nomem; 462 } 463 464 memcpy(state->blob.data, blob1.data, blob1.length); 465 memcpy(state->blob.data+blob1.length, blob2.data, blob2.length); 466 data_blob_free(&blob1); 467 data_blob_free(&blob2); 468 469 subreq = tdgram_sendto_queue_send(state, 470 cldap->event.ctx, 471 cldap->sock, 472 cldap->send_queue, 473 state->blob.data, 474 state->blob.length, 475 state->dest); 476 if (!subreq) { 477 goto nomem; 478 } 479 /* the callback will just free the state, as we don't need a result */ 480 tevent_req_set_callback(subreq, cldap_reply_state_destroy, state); 481 482 return NT_STATUS_OK; 483 484nomem: 485 status = NT_STATUS_NO_MEMORY; 486failed: 487 talloc_free(state); 488 return status; 489} 490 491static void cldap_reply_state_destroy(struct tevent_req *subreq) 492{ 493 struct cldap_reply_state *state = tevent_req_callback_data(subreq, 494 struct cldap_reply_state); 495 496 /* we don't want to know the result here, we just free the state */ 497 talloc_free(subreq); 498 talloc_free(state); 499} 500 501static int cldap_search_state_destructor(struct cldap_search_state *s) 502{ 503 if (s->caller.cldap) { 504 if (s->message_id != -1) { 505 idr_remove(s->caller.cldap->searches.idr, s->message_id); 506 s->message_id = -1; 507 } 508 DLIST_REMOVE(s->caller.cldap->searches.list, s); 509 cldap_recvfrom_stop(s->caller.cldap); 510 ZERO_STRUCT(s->caller); 511 } 512 513 return 0; 514} 515 516static void cldap_search_state_queue_done(struct tevent_req *subreq); 517static void cldap_search_state_wakeup_done(struct tevent_req *subreq); 518 519/* 520 queue a cldap reply for send 521*/ 522struct tevent_req *cldap_search_send(TALLOC_CTX *mem_ctx, 523 struct cldap_socket *cldap, 524 const struct cldap_search *io) 525{ 526 struct tevent_req *req, *subreq; 527 struct cldap_search_state *state = NULL; 528 struct ldap_message *msg; 529 struct ldap_SearchRequest *search; 530 struct timeval now; 531 struct timeval end; 532 uint32_t i; 533 int ret; 534 535 req = tevent_req_create(mem_ctx, &state, 536 struct cldap_search_state); 537 if (!req) { 538 return NULL; 539 } 540 ZERO_STRUCTP(state); 541 state->req = req; 542 state->caller.cldap = cldap; 543 state->message_id = -1; 544 545 talloc_set_destructor(state, cldap_search_state_destructor); 546 547 if (io->in.dest_address) { 548 if (cldap->connected) { 549 tevent_req_nterror(req, NT_STATUS_PIPE_CONNECTED); 550 goto post; 551 } 552 ret = tsocket_address_inet_from_strings(state, 553 "ip", 554 io->in.dest_address, 555 io->in.dest_port, 556 &state->request.dest); 557 if (ret != 0) { 558 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 559 goto post; 560 } 561 } else { 562 if (!cldap->connected) { 563 tevent_req_nterror(req, NT_STATUS_INVALID_ADDRESS); 564 goto post; 565 } 566 state->request.dest = NULL; 567 } 568 569 state->message_id = idr_get_new_random(cldap->searches.idr, 570 state, UINT16_MAX); 571 if (state->message_id == -1) { 572 tevent_req_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES); 573 goto post; 574 } 575 576 msg = talloc(state, struct ldap_message); 577 if (tevent_req_nomem(msg, req)) { 578 goto post; 579 } 580 581 msg->messageid = state->message_id; 582 msg->type = LDAP_TAG_SearchRequest; 583 msg->controls = NULL; 584 search = &msg->r.SearchRequest; 585 586 search->basedn = ""; 587 search->scope = LDAP_SEARCH_SCOPE_BASE; 588 search->deref = LDAP_DEREFERENCE_NEVER; 589 search->timelimit = 0; 590 search->sizelimit = 0; 591 search->attributesonly = false; 592 search->num_attributes = str_list_length(io->in.attributes); 593 search->attributes = io->in.attributes; 594 search->tree = ldb_parse_tree(msg, io->in.filter); 595 if (tevent_req_nomem(search->tree, req)) { 596 goto post; 597 } 598 599 if (!ldap_encode(msg, NULL, &state->request.blob, state)) { 600 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 601 goto post; 602 } 603 talloc_free(msg); 604 605 state->request.idx = 0; 606 state->request.delay = 10*1000*1000; 607 state->request.count = 3; 608 if (io->in.timeout > 0) { 609 state->request.delay = io->in.timeout * 1000 * 1000; 610 state->request.count = io->in.retries + 1; 611 } 612 613 now = tevent_timeval_current(); 614 end = now; 615 for (i = 0; i < state->request.count; i++) { 616 end = tevent_timeval_add(&end, 0, state->request.delay); 617 } 618 619 if (!tevent_req_set_endtime(req, state->caller.cldap->event.ctx, end)) { 620 tevent_req_nomem(NULL, req); 621 goto post; 622 } 623 624 subreq = tdgram_sendto_queue_send(state, 625 state->caller.cldap->event.ctx, 626 state->caller.cldap->sock, 627 state->caller.cldap->send_queue, 628 state->request.blob.data, 629 state->request.blob.length, 630 state->request.dest); 631 if (tevent_req_nomem(subreq, req)) { 632 goto post; 633 } 634 tevent_req_set_callback(subreq, cldap_search_state_queue_done, req); 635 636 DLIST_ADD_END(cldap->searches.list, state, struct cldap_search_state *); 637 638 return req; 639 640 post: 641 return tevent_req_post(req, cldap->event.ctx); 642} 643 644static void cldap_search_state_queue_done(struct tevent_req *subreq) 645{ 646 struct tevent_req *req = tevent_req_callback_data(subreq, 647 struct tevent_req); 648 struct cldap_search_state *state = tevent_req_data(req, 649 struct cldap_search_state); 650 ssize_t ret; 651 int sys_errno = 0; 652 struct timeval next; 653 654 ret = tdgram_sendto_queue_recv(subreq, &sys_errno); 655 talloc_free(subreq); 656 if (ret == -1) { 657 NTSTATUS status; 658 status = map_nt_error_from_unix(sys_errno); 659 DLIST_REMOVE(state->caller.cldap->searches.list, state); 660 ZERO_STRUCT(state->caller.cldap); 661 tevent_req_nterror(req, status); 662 return; 663 } 664 665 state->request.idx++; 666 667 /* wait for incoming traffic */ 668 if (!cldap_recvfrom_setup(state->caller.cldap)) { 669 tevent_req_nomem(NULL, req); 670 return; 671 } 672 673 if (state->request.idx > state->request.count) { 674 /* we just wait for the response or a timeout */ 675 return; 676 } 677 678 next = tevent_timeval_current_ofs(0, state->request.delay); 679 subreq = tevent_wakeup_send(state, 680 state->caller.cldap->event.ctx, 681 next); 682 if (tevent_req_nomem(subreq, req)) { 683 return; 684 } 685 tevent_req_set_callback(subreq, cldap_search_state_wakeup_done, req); 686} 687 688static void cldap_search_state_wakeup_done(struct tevent_req *subreq) 689{ 690 struct tevent_req *req = tevent_req_callback_data(subreq, 691 struct tevent_req); 692 struct cldap_search_state *state = tevent_req_data(req, 693 struct cldap_search_state); 694 bool ok; 695 696 ok = tevent_wakeup_recv(subreq); 697 talloc_free(subreq); 698 if (!ok) { 699 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); 700 return; 701 } 702 703 subreq = tdgram_sendto_queue_send(state, 704 state->caller.cldap->event.ctx, 705 state->caller.cldap->sock, 706 state->caller.cldap->send_queue, 707 state->request.blob.data, 708 state->request.blob.length, 709 state->request.dest); 710 if (tevent_req_nomem(subreq, req)) { 711 return; 712 } 713 tevent_req_set_callback(subreq, cldap_search_state_queue_done, req); 714} 715 716/* 717 receive a cldap reply 718*/ 719NTSTATUS cldap_search_recv(struct tevent_req *req, 720 TALLOC_CTX *mem_ctx, 721 struct cldap_search *io) 722{ 723 struct cldap_search_state *state = tevent_req_data(req, 724 struct cldap_search_state); 725 struct ldap_message *ldap_msg; 726 NTSTATUS status; 727 728 if (tevent_req_is_nterror(req, &status)) { 729 goto failed; 730 } 731 732 ldap_msg = talloc(mem_ctx, struct ldap_message); 733 if (!ldap_msg) { 734 goto nomem; 735 } 736 737 status = ldap_decode(state->response.asn1, NULL, ldap_msg); 738 if (!NT_STATUS_IS_OK(status)) { 739 goto failed; 740 } 741 742 ZERO_STRUCT(io->out); 743 744 /* the first possible form has a search result in first place */ 745 if (ldap_msg->type == LDAP_TAG_SearchResultEntry) { 746 io->out.response = talloc(mem_ctx, struct ldap_SearchResEntry); 747 if (!io->out.response) { 748 goto nomem; 749 } 750 *io->out.response = ldap_msg->r.SearchResultEntry; 751 752 /* decode the 2nd part */ 753 status = ldap_decode(state->response.asn1, NULL, ldap_msg); 754 if (!NT_STATUS_IS_OK(status)) { 755 goto failed; 756 } 757 } 758 759 if (ldap_msg->type != LDAP_TAG_SearchResultDone) { 760 status = NT_STATUS_LDAP(LDAP_PROTOCOL_ERROR); 761 goto failed; 762 } 763 764 io->out.result = talloc(mem_ctx, struct ldap_Result); 765 if (!io->out.result) { 766 goto nomem; 767 } 768 *io->out.result = ldap_msg->r.SearchResultDone; 769 770 if (io->out.result->resultcode != LDAP_SUCCESS) { 771 status = NT_STATUS_LDAP(io->out.result->resultcode); 772 goto failed; 773 } 774 775 tevent_req_received(req); 776 return NT_STATUS_OK; 777 778nomem: 779 status = NT_STATUS_NO_MEMORY; 780failed: 781 tevent_req_received(req); 782 return status; 783} 784 785 786/* 787 synchronous cldap search 788*/ 789NTSTATUS cldap_search(struct cldap_socket *cldap, 790 TALLOC_CTX *mem_ctx, 791 struct cldap_search *io) 792{ 793 struct tevent_req *req; 794 NTSTATUS status; 795 796 if (!cldap->event.allow_poll) { 797 return NT_STATUS_INVALID_PIPE_STATE; 798 } 799 800 if (cldap->searches.list) { 801 return NT_STATUS_PIPE_BUSY; 802 } 803 804 req = cldap_search_send(mem_ctx, cldap, io); 805 NT_STATUS_HAVE_NO_MEMORY(req); 806 807 if (!tevent_req_poll(req, cldap->event.ctx)) { 808 talloc_free(req); 809 return NT_STATUS_INTERNAL_ERROR; 810 } 811 812 status = cldap_search_recv(req, mem_ctx, io); 813 talloc_free(req); 814 815 return status; 816} 817 818struct cldap_netlogon_state { 819 struct cldap_search search; 820}; 821 822static void cldap_netlogon_state_done(struct tevent_req *subreq); 823/* 824 queue a cldap netlogon for send 825*/ 826struct tevent_req *cldap_netlogon_send(TALLOC_CTX *mem_ctx, 827 struct cldap_socket *cldap, 828 const struct cldap_netlogon *io) 829{ 830 struct tevent_req *req, *subreq; 831 struct cldap_netlogon_state *state; 832 char *filter; 833 static const char * const attr[] = { "NetLogon", NULL }; 834 835 req = tevent_req_create(mem_ctx, &state, 836 struct cldap_netlogon_state); 837 if (!req) { 838 return NULL; 839 } 840 841 filter = talloc_asprintf(state, "(&(NtVer=%s)", 842 ldap_encode_ndr_uint32(state, io->in.version)); 843 if (tevent_req_nomem(filter, req)) { 844 goto post; 845 } 846 if (io->in.user) { 847 filter = talloc_asprintf_append_buffer(filter, "(User=%s)", io->in.user); 848 if (tevent_req_nomem(filter, req)) { 849 goto post; 850 } 851 } 852 if (io->in.host) { 853 filter = talloc_asprintf_append_buffer(filter, "(Host=%s)", io->in.host); 854 if (tevent_req_nomem(filter, req)) { 855 goto post; 856 } 857 } 858 if (io->in.realm) { 859 filter = talloc_asprintf_append_buffer(filter, "(DnsDomain=%s)", io->in.realm); 860 if (tevent_req_nomem(filter, req)) { 861 goto post; 862 } 863 } 864 if (io->in.acct_control != -1) { 865 filter = talloc_asprintf_append_buffer(filter, "(AAC=%s)", 866 ldap_encode_ndr_uint32(state, io->in.acct_control)); 867 if (tevent_req_nomem(filter, req)) { 868 goto post; 869 } 870 } 871 if (io->in.domain_sid) { 872 struct dom_sid *sid = dom_sid_parse_talloc(state, io->in.domain_sid); 873 if (tevent_req_nomem(sid, req)) { 874 goto post; 875 } 876 filter = talloc_asprintf_append_buffer(filter, "(domainSid=%s)", 877 ldap_encode_ndr_dom_sid(state, sid)); 878 if (tevent_req_nomem(filter, req)) { 879 goto post; 880 } 881 } 882 if (io->in.domain_guid) { 883 struct GUID guid; 884 NTSTATUS status; 885 status = GUID_from_string(io->in.domain_guid, &guid); 886 if (tevent_req_nterror(req, status)) { 887 goto post; 888 } 889 filter = talloc_asprintf_append_buffer(filter, "(DomainGuid=%s)", 890 ldap_encode_ndr_GUID(state, &guid)); 891 if (tevent_req_nomem(filter, req)) { 892 goto post; 893 } 894 } 895 filter = talloc_asprintf_append_buffer(filter, ")"); 896 if (tevent_req_nomem(filter, req)) { 897 goto post; 898 } 899 900 if (io->in.dest_address) { 901 state->search.in.dest_address = talloc_strdup(state, 902 io->in.dest_address); 903 if (tevent_req_nomem(state->search.in.dest_address, req)) { 904 goto post; 905 } 906 state->search.in.dest_port = io->in.dest_port; 907 } else { 908 state->search.in.dest_address = NULL; 909 state->search.in.dest_port = 0; 910 } 911 state->search.in.filter = filter; 912 state->search.in.attributes = attr; 913 state->search.in.timeout = 2; 914 state->search.in.retries = 2; 915 916 subreq = cldap_search_send(state, cldap, &state->search); 917 if (tevent_req_nomem(subreq, req)) { 918 goto post; 919 } 920 tevent_req_set_callback(subreq, cldap_netlogon_state_done, req); 921 922 return req; 923post: 924 return tevent_req_post(req, cldap->event.ctx); 925} 926 927static void cldap_netlogon_state_done(struct tevent_req *subreq) 928{ 929 struct tevent_req *req = tevent_req_callback_data(subreq, 930 struct tevent_req); 931 struct cldap_netlogon_state *state = tevent_req_data(req, 932 struct cldap_netlogon_state); 933 NTSTATUS status; 934 935 status = cldap_search_recv(subreq, state, &state->search); 936 talloc_free(subreq); 937 938 if (tevent_req_nterror(req, status)) { 939 return; 940 } 941 942 tevent_req_done(req); 943} 944 945/* 946 receive a cldap netlogon reply 947*/ 948NTSTATUS cldap_netlogon_recv(struct tevent_req *req, 949 struct smb_iconv_convenience *iconv_convenience, 950 TALLOC_CTX *mem_ctx, 951 struct cldap_netlogon *io) 952{ 953 struct cldap_netlogon_state *state = tevent_req_data(req, 954 struct cldap_netlogon_state); 955 NTSTATUS status; 956 DATA_BLOB *data; 957 958 if (tevent_req_is_nterror(req, &status)) { 959 goto failed; 960 } 961 962 if (state->search.out.response == NULL) { 963 status = NT_STATUS_NOT_FOUND; 964 goto failed; 965 } 966 967 if (state->search.out.response->num_attributes != 1 || 968 strcasecmp(state->search.out.response->attributes[0].name, "netlogon") != 0 || 969 state->search.out.response->attributes[0].num_values != 1 || 970 state->search.out.response->attributes[0].values->length < 2) { 971 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR; 972 goto failed; 973 } 974 data = state->search.out.response->attributes[0].values; 975 976 status = pull_netlogon_samlogon_response(data, mem_ctx, 977 iconv_convenience, 978 &io->out.netlogon); 979 if (!NT_STATUS_IS_OK(status)) { 980 goto failed; 981 } 982 983 if (io->in.map_response) { 984 map_netlogon_samlogon_response(&io->out.netlogon); 985 } 986 987 status = NT_STATUS_OK; 988failed: 989 tevent_req_received(req); 990 return status; 991} 992 993/* 994 sync cldap netlogon search 995*/ 996NTSTATUS cldap_netlogon(struct cldap_socket *cldap, 997 struct smb_iconv_convenience *iconv_convenience, 998 TALLOC_CTX *mem_ctx, 999 struct cldap_netlogon *io) 1000{ 1001 struct tevent_req *req; 1002 NTSTATUS status; 1003 1004 if (!cldap->event.allow_poll) { 1005 return NT_STATUS_INVALID_PIPE_STATE; 1006 } 1007 1008 if (cldap->searches.list) { 1009 return NT_STATUS_PIPE_BUSY; 1010 } 1011 1012 req = cldap_netlogon_send(mem_ctx, cldap, io); 1013 NT_STATUS_HAVE_NO_MEMORY(req); 1014 1015 if (!tevent_req_poll(req, cldap->event.ctx)) { 1016 talloc_free(req); 1017 return NT_STATUS_INTERNAL_ERROR; 1018 } 1019 1020 status = cldap_netlogon_recv(req, iconv_convenience, mem_ctx, io); 1021 talloc_free(req); 1022 1023 return status; 1024} 1025 1026 1027/* 1028 send an empty reply (used on any error, so the client doesn't keep waiting 1029 or send the bad request again) 1030*/ 1031NTSTATUS cldap_empty_reply(struct cldap_socket *cldap, 1032 uint32_t message_id, 1033 struct tsocket_address *dest) 1034{ 1035 NTSTATUS status; 1036 struct cldap_reply reply; 1037 struct ldap_Result result; 1038 1039 reply.messageid = message_id; 1040 reply.dest = dest; 1041 reply.response = NULL; 1042 reply.result = &result; 1043 1044 ZERO_STRUCT(result); 1045 1046 status = cldap_reply_send(cldap, &reply); 1047 1048 return status; 1049} 1050 1051/* 1052 send an error reply (used on any error, so the client doesn't keep waiting 1053 or send the bad request again) 1054*/ 1055NTSTATUS cldap_error_reply(struct cldap_socket *cldap, 1056 uint32_t message_id, 1057 struct tsocket_address *dest, 1058 int resultcode, 1059 const char *errormessage) 1060{ 1061 NTSTATUS status; 1062 struct cldap_reply reply; 1063 struct ldap_Result result; 1064 1065 reply.messageid = message_id; 1066 reply.dest = dest; 1067 reply.response = NULL; 1068 reply.result = &result; 1069 1070 ZERO_STRUCT(result); 1071 result.resultcode = resultcode; 1072 result.errormessage = errormessage; 1073 1074 status = cldap_reply_send(cldap, &reply); 1075 1076 return status; 1077} 1078 1079 1080/* 1081 send a netlogon reply 1082*/ 1083NTSTATUS cldap_netlogon_reply(struct cldap_socket *cldap, 1084 struct smb_iconv_convenience *iconv_convenience, 1085 uint32_t message_id, 1086 struct tsocket_address *dest, 1087 uint32_t version, 1088 struct netlogon_samlogon_response *netlogon) 1089{ 1090 NTSTATUS status; 1091 struct cldap_reply reply; 1092 struct ldap_SearchResEntry response; 1093 struct ldap_Result result; 1094 TALLOC_CTX *tmp_ctx = talloc_new(cldap); 1095 DATA_BLOB blob; 1096 1097 status = push_netlogon_samlogon_response(&blob, tmp_ctx, 1098 iconv_convenience, 1099 netlogon); 1100 if (!NT_STATUS_IS_OK(status)) { 1101 talloc_free(tmp_ctx); 1102 return status; 1103 } 1104 reply.messageid = message_id; 1105 reply.dest = dest; 1106 reply.response = &response; 1107 reply.result = &result; 1108 1109 ZERO_STRUCT(result); 1110 1111 response.dn = ""; 1112 response.num_attributes = 1; 1113 response.attributes = talloc(tmp_ctx, struct ldb_message_element); 1114 NT_STATUS_HAVE_NO_MEMORY(response.attributes); 1115 response.attributes->name = "netlogon"; 1116 response.attributes->num_values = 1; 1117 response.attributes->values = &blob; 1118 1119 status = cldap_reply_send(cldap, &reply); 1120 1121 talloc_free(tmp_ctx); 1122 1123 return status; 1124} 1125 1126