LCOV - code coverage report
Current view: top level - source4/kdc - kdc-proxy.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 183 243 75.3 %
Date: 2024-06-13 04:01:37 Functions: 14 14 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    KDC Server request proxying
       5             : 
       6             :    Copyright (C) Andrew Tridgell        2010
       7             :    Copyright (C) Andrew Bartlett        2010
       8             :    Copyright (C) Stefan Metzmacher      2011
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             : 
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "samba/process_model.h"
      26             : #include "lib/tsocket/tsocket.h"
      27             : #include "libcli/util/tstream.h"
      28             : #include "lib/util/tevent_ntstatus.h"
      29             : #include "lib/stream/packet.h"
      30             : #include "kdc/kdc-server.h"
      31             : #include "kdc/kdc-proxy.h"
      32             : #include "dsdb/samdb/samdb.h"
      33             : #include "libcli/composite/composite.h"
      34             : #include "libcli/resolve/resolve.h"
      35             : 
      36             : 
      37             : /*
      38             :   get a list of our replication partners from repsFrom, returning it in *proxy_list
      39             :  */
      40        3053 : static WERROR kdc_proxy_get_writeable_dcs(struct kdc_server *kdc, TALLOC_CTX *mem_ctx, char ***proxy_list)
      41             : {
      42             :         WERROR werr;
      43             :         uint32_t count, i;
      44             :         struct repsFromToBlob *reps;
      45             : 
      46        3053 :         werr = dsdb_loadreps(kdc->samdb, mem_ctx, ldb_get_default_basedn(kdc->samdb), "repsFrom", &reps, &count);
      47        3053 :         W_ERROR_NOT_OK_RETURN(werr);
      48             : 
      49        3053 :         if (count == 0) {
      50             :                 /* we don't have any DCs to replicate with. Very
      51             :                    strange for a RODC */
      52           0 :                 DEBUG(1,(__location__ ": No replication sources for RODC in KDC proxy\n"));
      53           0 :                 talloc_free(reps);
      54           0 :                 return WERR_DS_DRA_NO_REPLICA;
      55             :         }
      56             : 
      57        3053 :         (*proxy_list) = talloc_array(mem_ctx, char *, count+1);
      58        3053 :         W_ERROR_HAVE_NO_MEMORY_AND_FREE(*proxy_list, reps);
      59             : 
      60        3053 :         talloc_steal(*proxy_list, reps);
      61             : 
      62        6106 :         for (i=0; i<count; i++) {
      63        3053 :                 const char *dns_name = NULL;
      64        3053 :                 if (reps->version == 1) {
      65        3053 :                         dns_name = reps->ctr.ctr1.other_info->dns_name;
      66           0 :                 } else if (reps->version == 2) {
      67           0 :                         dns_name = reps->ctr.ctr2.other_info->dns_name1;
      68             :                 }
      69        3053 :                 (*proxy_list)[i] = talloc_strdup(*proxy_list, dns_name);
      70        3053 :                 W_ERROR_HAVE_NO_MEMORY_AND_FREE((*proxy_list)[i], *proxy_list);
      71             :         }
      72        3053 :         (*proxy_list)[i] = NULL;
      73             : 
      74        3053 :         talloc_free(reps);
      75             : 
      76        3053 :         return WERR_OK;
      77             : }
      78             : 
      79             : 
      80             : struct kdc_udp_proxy_state {
      81             :         struct tevent_context *ev;
      82             :         struct kdc_server *kdc;
      83             :         uint16_t port;
      84             :         DATA_BLOB in;
      85             :         DATA_BLOB out;
      86             :         char **proxy_list;
      87             :         uint32_t next_proxy;
      88             :         struct {
      89             :                 struct nbt_name name;
      90             :                 const char *ip;
      91             :                 struct tdgram_context *dgram;
      92             :         } proxy;
      93             : };
      94             : 
      95             : 
      96             : static void kdc_udp_next_proxy(struct tevent_req *req);
      97             : 
      98         939 : struct tevent_req *kdc_udp_proxy_send(TALLOC_CTX *mem_ctx,
      99             :                                       struct tevent_context *ev,
     100             :                                       struct kdc_server *kdc,
     101             :                                       uint16_t port,
     102             :                                       DATA_BLOB in)
     103             : {
     104             :         struct tevent_req *req;
     105             :         struct kdc_udp_proxy_state *state;
     106             :         WERROR werr;
     107             : 
     108         939 :         req = tevent_req_create(mem_ctx, &state,
     109             :                                 struct kdc_udp_proxy_state);
     110         939 :         if (req == NULL) {
     111           0 :                 return NULL;
     112             :         }
     113         939 :         state->ev = ev;
     114         939 :         state->kdc  = kdc;
     115         939 :         state->port = port;
     116         939 :         state->in = in;
     117             : 
     118         939 :         werr = kdc_proxy_get_writeable_dcs(kdc, state, &state->proxy_list);
     119         939 :         if (!W_ERROR_IS_OK(werr)) {
     120           0 :                 NTSTATUS status = werror_to_ntstatus(werr);
     121           0 :                 tevent_req_nterror(req, status);
     122           0 :                 return tevent_req_post(req, ev);
     123             :         }
     124             : 
     125         939 :         kdc_udp_next_proxy(req);
     126         939 :         if (!tevent_req_is_in_progress(req)) {
     127           0 :                 return tevent_req_post(req, ev);
     128             :         }
     129             : 
     130         939 :         return req;
     131             : }
     132             : 
     133             : static void kdc_udp_proxy_resolve_done(struct composite_context *csubreq);
     134             : 
     135             : /*
     136             :   try the next proxy in the list
     137             :  */
     138         939 : static void kdc_udp_next_proxy(struct tevent_req *req)
     139             : {
     140         939 :         struct kdc_udp_proxy_state *state =
     141         939 :                 tevent_req_data(req,
     142             :                 struct kdc_udp_proxy_state);
     143         939 :         const char *proxy_dnsname = state->proxy_list[state->next_proxy];
     144             :         struct composite_context *csubreq;
     145             : 
     146         939 :         if (proxy_dnsname == NULL) {
     147           0 :                 tevent_req_nterror(req, NT_STATUS_NO_LOGON_SERVERS);
     148           0 :                 return;
     149             :         }
     150             : 
     151         939 :         state->next_proxy++;
     152             : 
     153             :         /* make sure we close the socket of the last try */
     154         939 :         TALLOC_FREE(state->proxy.dgram);
     155         939 :         ZERO_STRUCT(state->proxy);
     156             : 
     157         939 :         make_nbt_name(&state->proxy.name, proxy_dnsname, 0);
     158             : 
     159         939 :         csubreq = resolve_name_ex_send(lpcfg_resolve_context(state->kdc->task->lp_ctx),
     160             :                                        state,
     161             :                                        RESOLVE_NAME_FLAG_FORCE_DNS,
     162             :                                        0,
     163             :                                        &state->proxy.name,
     164             :                                        state->ev);
     165         939 :         if (tevent_req_nomem(csubreq, req)) {
     166           0 :                 return;
     167             :         }
     168         939 :         csubreq->async.fn = kdc_udp_proxy_resolve_done;
     169         939 :         csubreq->async.private_data = req;
     170             : }
     171             : 
     172             : static void kdc_udp_proxy_sendto_done(struct tevent_req *subreq);
     173             : static void kdc_udp_proxy_recvfrom_done(struct tevent_req *subreq);
     174             : 
     175         939 : static void kdc_udp_proxy_resolve_done(struct composite_context *csubreq)
     176             : {
     177         939 :         struct tevent_req *req =
     178         939 :                 talloc_get_type_abort(csubreq->async.private_data,
     179             :                 struct tevent_req);
     180         939 :         struct kdc_udp_proxy_state *state =
     181         939 :                 tevent_req_data(req,
     182             :                 struct kdc_udp_proxy_state);
     183             :         NTSTATUS status;
     184             :         struct tevent_req *subreq;
     185             :         struct tsocket_address *local_addr, *proxy_addr;
     186             :         int ret;
     187             :         bool ok;
     188             : 
     189         939 :         status = resolve_name_recv(csubreq, state, &state->proxy.ip);
     190         939 :         if (!NT_STATUS_IS_OK(status)) {
     191           0 :                 DEBUG(0,("Unable to resolve proxy[%s] - %s\n",
     192             :                         state->proxy.name.name, nt_errstr(status)));
     193           0 :                 kdc_udp_next_proxy(req);
     194           0 :                 return;
     195             :         }
     196             : 
     197             :         /* get an address for us to use locally */
     198         939 :         ret = tsocket_address_inet_from_strings(state, "ip", NULL, 0, &local_addr);
     199         939 :         if (ret != 0) {
     200           0 :                 kdc_udp_next_proxy(req);
     201           0 :                 return;
     202             :         }
     203             : 
     204         939 :         ret = tsocket_address_inet_from_strings(state, "ip",
     205             :                                                 state->proxy.ip,
     206             :                                                 state->port,
     207             :                                                 &proxy_addr);
     208         939 :         if (ret != 0) {
     209           0 :                 kdc_udp_next_proxy(req);
     210           0 :                 return;
     211             :         }
     212             : 
     213             :         /* create a socket for us to work on */
     214         939 :         ret = tdgram_inet_udp_socket(local_addr, proxy_addr,
     215             :                                      state, &state->proxy.dgram);
     216         939 :         if (ret != 0) {
     217           0 :                 kdc_udp_next_proxy(req);
     218           0 :                 return;
     219             :         }
     220             : 
     221        1878 :         subreq = tdgram_sendto_send(state,
     222             :                                     state->ev,
     223             :                                     state->proxy.dgram,
     224         939 :                                     state->in.data,
     225             :                                     state->in.length,
     226             :                                     NULL);
     227         939 :         if (tevent_req_nomem(subreq, req)) {
     228           0 :                 return;
     229             :         }
     230         939 :         tevent_req_set_callback(subreq, kdc_udp_proxy_sendto_done, req);
     231             : 
     232             :         /* setup to receive the reply from the proxy */
     233         939 :         subreq = tdgram_recvfrom_send(state, state->ev, state->proxy.dgram);
     234         939 :         if (tevent_req_nomem(subreq, req)) {
     235           0 :                 return;
     236             :         }
     237         939 :         tevent_req_set_callback(subreq, kdc_udp_proxy_recvfrom_done, req);
     238             : 
     239         939 :         ok = tevent_req_set_endtime(
     240             :                 subreq,
     241             :                 state->ev,
     242         939 :                 timeval_current_ofs(state->kdc->proxy_timeout, 0));
     243         939 :         if (!ok) {
     244           0 :                 DBG_DEBUG("tevent_req_set_endtime failed\n");
     245           0 :                 return;
     246             :         }
     247             : 
     248         939 :         DEBUG(4,("kdc_udp_proxy: proxying request to %s[%s]\n",
     249             :                  state->proxy.name.name, state->proxy.ip));
     250             : }
     251             : 
     252             : /*
     253             :   called when the send of the call to the proxy is complete
     254             :   this is used to get an errors from the sendto()
     255             :  */
     256         939 : static void kdc_udp_proxy_sendto_done(struct tevent_req *subreq)
     257             : {
     258         939 :         struct tevent_req *req =
     259         939 :                 tevent_req_callback_data(subreq,
     260             :                 struct tevent_req);
     261         939 :         struct kdc_udp_proxy_state *state =
     262         939 :                 tevent_req_data(req,
     263             :                 struct kdc_udp_proxy_state);
     264             :         ssize_t ret;
     265             :         int sys_errno;
     266             : 
     267         939 :         ret = tdgram_sendto_recv(subreq, &sys_errno);
     268         939 :         TALLOC_FREE(subreq);
     269         939 :         if (ret == -1) {
     270           0 :                 DEBUG(4,("kdc_udp_proxy: sendto for %s[%s] gave %d : %s\n",
     271             :                          state->proxy.name.name, state->proxy.ip,
     272             :                          sys_errno, strerror(sys_errno)));
     273           0 :                 kdc_udp_next_proxy(req);
     274             :         }
     275         939 : }
     276             : 
     277             : /*
     278             :   called when the proxy replies
     279             :  */
     280         939 : static void kdc_udp_proxy_recvfrom_done(struct tevent_req *subreq)
     281             : {
     282         939 :         struct tevent_req *req =
     283         939 :                 tevent_req_callback_data(subreq,
     284             :                 struct tevent_req);
     285         939 :         struct kdc_udp_proxy_state *state =
     286         939 :                 tevent_req_data(req,
     287             :                 struct kdc_udp_proxy_state);
     288             :         int sys_errno;
     289             :         uint8_t *buf;
     290             :         ssize_t len;
     291             : 
     292         939 :         len = tdgram_recvfrom_recv(subreq, &sys_errno,
     293             :                                    state, &buf, NULL);
     294         939 :         TALLOC_FREE(subreq);
     295         939 :         if (len == -1) {
     296           0 :                 DEBUG(4,("kdc_udp_proxy: reply from %s[%s] gave %d : %s\n",
     297             :                          state->proxy.name.name, state->proxy.ip,
     298             :                          sys_errno, strerror(sys_errno)));
     299           0 :                 kdc_udp_next_proxy(req);
     300           0 :                 return;
     301             :         }
     302             : 
     303             :         /*
     304             :          * Check the reply came from the right IP?
     305             :          * As we use connected udp sockets, that should not be needed...
     306             :          */
     307             : 
     308         939 :         state->out.length = len;
     309         939 :         state->out.data = buf;
     310             : 
     311         939 :         tevent_req_done(req);
     312             : }
     313             : 
     314         939 : NTSTATUS kdc_udp_proxy_recv(struct tevent_req *req,
     315             :                             TALLOC_CTX *mem_ctx,
     316             :                             DATA_BLOB *out)
     317             : {
     318         939 :         struct kdc_udp_proxy_state *state =
     319         939 :                 tevent_req_data(req,
     320             :                 struct kdc_udp_proxy_state);
     321             :         NTSTATUS status;
     322             : 
     323         939 :         if (tevent_req_is_nterror(req, &status)) {
     324           0 :                 tevent_req_received(req);
     325           0 :                 return status;
     326             :         }
     327             : 
     328         939 :         out->data = talloc_move(mem_ctx, &state->out.data);
     329         939 :         out->length = state->out.length;
     330             : 
     331         939 :         tevent_req_received(req);
     332         939 :         return NT_STATUS_OK;
     333             : }
     334             : 
     335             : struct kdc_tcp_proxy_state {
     336             :         struct tevent_context *ev;
     337             :         struct kdc_server *kdc;
     338             :         uint16_t port;
     339             :         DATA_BLOB in;
     340             :         uint8_t in_hdr[4];
     341             :         struct iovec in_iov[2];
     342             :         DATA_BLOB out;
     343             :         char **proxy_list;
     344             :         uint32_t next_proxy;
     345             :         struct {
     346             :                 struct nbt_name name;
     347             :                 const char *ip;
     348             :                 struct tstream_context *stream;
     349             :         } proxy;
     350             : };
     351             : 
     352             : static void kdc_tcp_next_proxy(struct tevent_req *req);
     353             : 
     354        2114 : struct tevent_req *kdc_tcp_proxy_send(TALLOC_CTX *mem_ctx,
     355             :                                       struct tevent_context *ev,
     356             :                                       struct kdc_server *kdc,
     357             :                                       uint16_t port,
     358             :                                       DATA_BLOB in)
     359             : {
     360             :         struct tevent_req *req;
     361             :         struct kdc_tcp_proxy_state *state;
     362             :         WERROR werr;
     363             : 
     364        2114 :         req = tevent_req_create(mem_ctx, &state,
     365             :                                 struct kdc_tcp_proxy_state);
     366        2114 :         if (req == NULL) {
     367           0 :                 return NULL;
     368             :         }
     369        2114 :         state->ev = ev;
     370        2114 :         state->kdc  = kdc;
     371        2114 :         state->port = port;
     372        2114 :         state->in = in;
     373             : 
     374        2114 :         werr = kdc_proxy_get_writeable_dcs(kdc, state, &state->proxy_list);
     375        2114 :         if (!W_ERROR_IS_OK(werr)) {
     376           0 :                 NTSTATUS status = werror_to_ntstatus(werr);
     377           0 :                 tevent_req_nterror(req, status);
     378           0 :                 return tevent_req_post(req, ev);
     379             :         }
     380             : 
     381        2114 :         RSIVAL(state->in_hdr, 0, state->in.length);
     382        2114 :         state->in_iov[0].iov_base = (char *)state->in_hdr;
     383        2114 :         state->in_iov[0].iov_len = 4;
     384        2114 :         state->in_iov[1].iov_base = (char *)state->in.data;
     385        2114 :         state->in_iov[1].iov_len = state->in.length;
     386             : 
     387        2114 :         kdc_tcp_next_proxy(req);
     388        2114 :         if (!tevent_req_is_in_progress(req)) {
     389           0 :                 return tevent_req_post(req, ev);
     390             :         }
     391             : 
     392        2114 :         return req;
     393             : }
     394             : 
     395             : static void kdc_tcp_proxy_resolve_done(struct composite_context *csubreq);
     396             : 
     397             : /*
     398             :   try the next proxy in the list
     399             :  */
     400        2114 : static void kdc_tcp_next_proxy(struct tevent_req *req)
     401             : {
     402        2114 :         struct kdc_tcp_proxy_state *state =
     403        2114 :                 tevent_req_data(req,
     404             :                 struct kdc_tcp_proxy_state);
     405        2114 :         const char *proxy_dnsname = state->proxy_list[state->next_proxy];
     406             :         struct composite_context *csubreq;
     407             : 
     408        2114 :         if (proxy_dnsname == NULL) {
     409           0 :                 tevent_req_nterror(req, NT_STATUS_NO_LOGON_SERVERS);
     410           0 :                 return;
     411             :         }
     412             : 
     413        2114 :         state->next_proxy++;
     414             : 
     415             :         /* make sure we close the socket of the last try */
     416        2114 :         TALLOC_FREE(state->proxy.stream);
     417        2114 :         ZERO_STRUCT(state->proxy);
     418             : 
     419        2114 :         make_nbt_name(&state->proxy.name, proxy_dnsname, 0);
     420             : 
     421        2114 :         csubreq = resolve_name_ex_send(lpcfg_resolve_context(state->kdc->task->lp_ctx),
     422             :                                        state,
     423             :                                        RESOLVE_NAME_FLAG_FORCE_DNS,
     424             :                                        0,
     425             :                                        &state->proxy.name,
     426             :                                        state->ev);
     427        2114 :         if (tevent_req_nomem(csubreq, req)) {
     428           0 :                 return;
     429             :         }
     430        2114 :         csubreq->async.fn = kdc_tcp_proxy_resolve_done;
     431        2114 :         csubreq->async.private_data = req;
     432             : }
     433             : 
     434             : static void kdc_tcp_proxy_connect_done(struct tevent_req *subreq);
     435             : 
     436        2114 : static void kdc_tcp_proxy_resolve_done(struct composite_context *csubreq)
     437             : {
     438        2114 :         struct tevent_req *req =
     439        2114 :                 talloc_get_type_abort(csubreq->async.private_data,
     440             :                 struct tevent_req);
     441        2114 :         struct kdc_tcp_proxy_state *state =
     442        2114 :                 tevent_req_data(req,
     443             :                 struct kdc_tcp_proxy_state);
     444             :         NTSTATUS status;
     445             :         struct tevent_req *subreq;
     446             :         struct tsocket_address *local_addr, *proxy_addr;
     447             :         int ret;
     448             : 
     449        2114 :         status = resolve_name_recv(csubreq, state, &state->proxy.ip);
     450        2114 :         if (!NT_STATUS_IS_OK(status)) {
     451           0 :                 DEBUG(0,("Unable to resolve proxy[%s] - %s\n",
     452             :                         state->proxy.name.name, nt_errstr(status)));
     453           0 :                 kdc_tcp_next_proxy(req);
     454           0 :                 return;
     455             :         }
     456             : 
     457             :         /* get an address for us to use locally */
     458        2114 :         ret = tsocket_address_inet_from_strings(state, "ip", NULL, 0, &local_addr);
     459        2114 :         if (ret != 0) {
     460           0 :                 kdc_tcp_next_proxy(req);
     461           0 :                 return;
     462             :         }
     463             : 
     464        2114 :         ret = tsocket_address_inet_from_strings(state, "ip",
     465             :                                                 state->proxy.ip,
     466             :                                                 state->port,
     467             :                                                 &proxy_addr);
     468        2114 :         if (ret != 0) {
     469           0 :                 kdc_tcp_next_proxy(req);
     470           0 :                 return;
     471             :         }
     472             : 
     473        2114 :         subreq = tstream_inet_tcp_connect_send(state, state->ev,
     474             :                                                local_addr, proxy_addr);
     475        2114 :         if (tevent_req_nomem(subreq, req)) {
     476           0 :                 return;
     477             :         }
     478        2114 :         tevent_req_set_callback(subreq, kdc_tcp_proxy_connect_done, req);
     479        2114 :         tevent_req_set_endtime(subreq, state->ev,
     480        2114 :                                timeval_current_ofs(state->kdc->proxy_timeout, 0));
     481             : }
     482             : 
     483             : static void kdc_tcp_proxy_writev_done(struct tevent_req *subreq);
     484             : static void kdc_tcp_proxy_read_pdu_done(struct tevent_req *subreq);
     485             : 
     486        2114 : static void kdc_tcp_proxy_connect_done(struct tevent_req *subreq)
     487             : {
     488        2114 :         struct tevent_req *req =
     489        2114 :                 tevent_req_callback_data(subreq,
     490             :                 struct tevent_req);
     491        2114 :         struct kdc_tcp_proxy_state *state =
     492        2114 :                 tevent_req_data(req,
     493             :                 struct kdc_tcp_proxy_state);
     494             :         int ret, sys_errno;
     495             : 
     496        2114 :         ret = tstream_inet_tcp_connect_recv(subreq, &sys_errno,
     497             :                                             state, &state->proxy.stream, NULL);
     498        2114 :         TALLOC_FREE(subreq);
     499        2114 :         if (ret != 0) {
     500           0 :                 kdc_tcp_next_proxy(req);
     501           0 :                 return;
     502             :         }
     503             : 
     504        2114 :         subreq = tstream_writev_send(state,
     505             :                                      state->ev,
     506             :                                      state->proxy.stream,
     507        2114 :                                      state->in_iov, 2);
     508        2114 :         if (tevent_req_nomem(subreq, req)) {
     509           0 :                 return;
     510             :         }
     511        2114 :         tevent_req_set_callback(subreq, kdc_tcp_proxy_writev_done, req);
     512             : 
     513        2114 :         subreq = tstream_read_pdu_blob_send(state,
     514             :                                             state->ev,
     515             :                                             state->proxy.stream,
     516             :                                             4, /* initial_read_size */
     517             :                                             packet_full_request_u32,
     518             :                                             req);
     519        2114 :         if (tevent_req_nomem(subreq, req)) {
     520           0 :                 return;
     521             :         }
     522        2114 :         tevent_req_set_callback(subreq, kdc_tcp_proxy_read_pdu_done, req);
     523        2114 :         tevent_req_set_endtime(subreq, state->kdc->task->event_ctx,
     524        2114 :                                timeval_current_ofs(state->kdc->proxy_timeout, 0));
     525             : 
     526        2114 :         DEBUG(4,("kdc_tcp_proxy: proxying request to %s[%s]\n",
     527             :                  state->proxy.name.name, state->proxy.ip));
     528             : }
     529             : 
     530        2114 : static void kdc_tcp_proxy_writev_done(struct tevent_req *subreq)
     531             : {
     532        2114 :         struct tevent_req *req =
     533        2114 :                 tevent_req_callback_data(subreq,
     534             :                 struct tevent_req);
     535             :         int ret, sys_errno;
     536             : 
     537        2114 :         ret = tstream_writev_recv(subreq, &sys_errno);
     538        2114 :         TALLOC_FREE(subreq);
     539        2114 :         if (ret == -1) {
     540           0 :                 kdc_tcp_next_proxy(req);
     541             :         }
     542        2114 : }
     543             : 
     544        2114 : static void kdc_tcp_proxy_read_pdu_done(struct tevent_req *subreq)
     545             : {
     546        2114 :         struct tevent_req *req =
     547        2114 :                 tevent_req_callback_data(subreq,
     548             :                 struct tevent_req);
     549        2114 :         struct kdc_tcp_proxy_state *state =
     550        2114 :                 tevent_req_data(req,
     551             :                 struct kdc_tcp_proxy_state);
     552             :         NTSTATUS status;
     553             :         DATA_BLOB raw;
     554             : 
     555        2114 :         status = tstream_read_pdu_blob_recv(subreq, state, &raw);
     556        2114 :         TALLOC_FREE(subreq);
     557        2114 :         if (!NT_STATUS_IS_OK(status)) {
     558           0 :                 kdc_tcp_next_proxy(req);
     559           0 :                 return;
     560             :         }
     561             : 
     562             :         /*
     563             :          * raw blob has the length in the first 4 bytes,
     564             :          * which we do not need here.
     565             :          */
     566        2114 :         state->out = data_blob_talloc(state, raw.data + 4, raw.length - 4);
     567        2114 :         if (state->out.length != raw.length - 4) {
     568           0 :                 tevent_req_oom(req);
     569           0 :                 return;
     570             :         }
     571             : 
     572        2114 :         tevent_req_done(req);
     573             : }
     574             : 
     575        2114 : NTSTATUS kdc_tcp_proxy_recv(struct tevent_req *req,
     576             :                             TALLOC_CTX *mem_ctx,
     577             :                             DATA_BLOB *out)
     578             : {
     579        2114 :         struct kdc_tcp_proxy_state *state =
     580        2114 :                 tevent_req_data(req,
     581             :                 struct kdc_tcp_proxy_state);
     582             :         NTSTATUS status;
     583             : 
     584        2114 :         if (tevent_req_is_nterror(req, &status)) {
     585           0 :                 tevent_req_received(req);
     586           0 :                 return status;
     587             :         }
     588             : 
     589        2114 :         out->data = talloc_move(mem_ctx, &state->out.data);
     590        2114 :         out->length = state->out.length;
     591             : 
     592        2114 :         tevent_req_received(req);
     593        2114 :         return NT_STATUS_OK;
     594             : }

Generated by: LCOV version 1.13