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

Generated by: LCOV version 1.14