LCOV - code coverage report
Current view: top level - source4/auth/gensec - gensec_tstream.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 208 242 86.0 %
Date: 2021-09-23 10:06:22 Functions: 13 13 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    tstream based generic authentication interface
       5             : 
       6             :    Copyright (c) 2010 Stefan Metzmacher
       7             :    Copyright (c) 2010 Andreas Schneider <asn@redhat.com>
       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             : #include "includes.h"
      24             : #include "system/network.h"
      25             : #include "auth/gensec/gensec.h"
      26             : #include "auth/gensec/gensec_proto.h"
      27             : #include "auth/gensec/gensec_tstream.h"
      28             : #include "lib/tsocket/tsocket.h"
      29             : #include "lib/tsocket/tsocket_internal.h"
      30             : #include "auth/gensec/gensec_toplevel_proto.h"
      31             : 
      32             : static const struct tstream_context_ops tstream_gensec_ops;
      33             : 
      34             : struct tstream_gensec {
      35             :         struct tstream_context *plain_stream;
      36             : 
      37             :         struct gensec_security *gensec_security;
      38             : 
      39             :         int error;
      40             : 
      41             :         struct {
      42             :                 size_t max_unwrapped_size;
      43             :                 size_t max_wrapped_size;
      44             :         } write;
      45             : 
      46             :         struct {
      47             :                 off_t ofs;
      48             :                 size_t left;
      49             :                 DATA_BLOB unwrapped;
      50             :         } read;
      51             : };
      52             : 
      53       34939 : _PUBLIC_ NTSTATUS _gensec_create_tstream(TALLOC_CTX *mem_ctx,
      54             :                                          struct gensec_security *gensec_security,
      55             :                                          struct tstream_context *plain_stream,
      56             :                                          struct tstream_context **_gensec_stream,
      57             :                                          const char *location)
      58             : {
      59             :         struct tstream_context *gensec_stream;
      60             :         struct tstream_gensec *tgss;
      61             : 
      62       34939 :         gensec_stream = tstream_context_create(mem_ctx,
      63             :                                                &tstream_gensec_ops,
      64             :                                                &tgss,
      65             :                                                struct tstream_gensec,
      66             :                                                location);
      67       34939 :         if (gensec_stream == NULL) {
      68           0 :                 return NT_STATUS_NO_MEMORY;
      69             :         }
      70             : 
      71       34939 :         tgss->plain_stream = plain_stream;
      72       34939 :         tgss->gensec_security = gensec_security;
      73       34939 :         tgss->error = 0;
      74             : 
      75       34939 :         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN) &&
      76           0 :             !gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
      77           0 :                 talloc_free(gensec_stream);
      78           0 :                 return NT_STATUS_INVALID_PARAMETER;
      79             :         }
      80             : 
      81       34939 :         tgss->write.max_unwrapped_size = gensec_max_input_size(gensec_security);
      82       34939 :         tgss->write.max_wrapped_size = gensec_max_wrapped_size(gensec_security);
      83             : 
      84       34939 :         ZERO_STRUCT(tgss->read);
      85             : 
      86       34939 :         *_gensec_stream = gensec_stream;
      87       34939 :         return NT_STATUS_OK;
      88             : }
      89             : 
      90          98 : static ssize_t tstream_gensec_pending_bytes(struct tstream_context *stream)
      91             : {
      92          49 :         struct tstream_gensec *tgss =
      93          98 :                 tstream_context_data(stream,
      94             :                 struct tstream_gensec);
      95             : 
      96          98 :         if (tgss->error != 0) {
      97           0 :                 errno = tgss->error;
      98           0 :                 return -1;
      99             :         }
     100             : 
     101          98 :         return tgss->read.left;
     102             : }
     103             : 
     104             : struct tstream_gensec_readv_state {
     105             :         struct tevent_context *ev;
     106             :         struct tstream_context *stream;
     107             : 
     108             :         struct iovec *vector;
     109             :         int count;
     110             : 
     111             :         struct {
     112             :                 bool asked_for_hdr;
     113             :                 uint8_t hdr[4];
     114             :                 bool asked_for_blob;
     115             :                 DATA_BLOB blob;
     116             :         } wrapped;
     117             : 
     118             :         int ret;
     119             : };
     120             : 
     121             : static void tstream_gensec_readv_wrapped_next(struct tevent_req *req);
     122             : 
     123     2808759 : static struct tevent_req *tstream_gensec_readv_send(TALLOC_CTX *mem_ctx,
     124             :                                                     struct tevent_context *ev,
     125             :                                                     struct tstream_context *stream,
     126             :                                                     struct iovec *vector,
     127             :                                                     size_t count)
     128             : {
     129     2220119 :         struct tstream_gensec *tgss =
     130     2808759 :                 tstream_context_data(stream,
     131             :                 struct tstream_gensec);
     132             :         struct tevent_req *req;
     133             :         struct tstream_gensec_readv_state *state;
     134             : 
     135     2808759 :         req = tevent_req_create(mem_ctx, &state,
     136             :                                 struct tstream_gensec_readv_state);
     137     2808759 :         if (!req) {
     138           0 :                 return NULL;
     139             :         }
     140             : 
     141     2808759 :         if (tgss->error != 0) {
     142           0 :                 tevent_req_error(req, tgss->error);
     143           0 :                 return tevent_req_post(req, ev);
     144             :         }
     145             : 
     146     2808759 :         state->ev = ev;
     147     2808759 :         state->stream = stream;
     148     2808759 :         state->ret = 0;
     149             : 
     150             :         /*
     151             :          * we make a copy of the vector so we can change the structure
     152             :          */
     153     2808759 :         state->vector = talloc_array(state, struct iovec, count);
     154     2808759 :         if (tevent_req_nomem(state->vector, req)) {
     155           0 :                 return tevent_req_post(req, ev);
     156             :         }
     157     2811311 :         memcpy(state->vector, vector, sizeof(struct iovec) * count);
     158     2808759 :         state->count = count;
     159             : 
     160     2808759 :         tstream_gensec_readv_wrapped_next(req);
     161     2808759 :         if (!tevent_req_is_in_progress(req)) {
     162     1994271 :                 return tevent_req_post(req, ev);
     163             :         }
     164             : 
     165      813436 :         return req;
     166             : }
     167             : 
     168             : static int tstream_gensec_readv_next_vector(struct tstream_context *unix_stream,
     169             :                                             void *private_data,
     170             :                                             TALLOC_CTX *mem_ctx,
     171             :                                             struct iovec **_vector,
     172             :                                             size_t *_count);
     173             : static void tstream_gensec_readv_wrapped_done(struct tevent_req *subreq);
     174             : 
     175     3640574 : static void tstream_gensec_readv_wrapped_next(struct tevent_req *req)
     176             : {
     177     2854661 :         struct tstream_gensec_readv_state *state =
     178     3640574 :                 tevent_req_data(req,
     179             :                 struct tstream_gensec_readv_state);
     180     2854661 :         struct tstream_gensec *tgss =
     181     3640574 :                 tstream_context_data(state->stream,
     182             :                 struct tstream_gensec);
     183             :         struct tevent_req *subreq;
     184             : 
     185             :         /*
     186             :          * copy the pending buffer first
     187             :          */
     188     9323135 :         while (tgss->read.left > 0 && state->count > 0) {
     189     2827900 :                 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
     190     2827900 :                 size_t len = MIN(tgss->read.left, state->vector[0].iov_len);
     191             : 
     192     2830330 :                 memcpy(base, tgss->read.unwrapped.data + tgss->read.ofs, len);
     193             : 
     194     2827900 :                 base += len;
     195     2827900 :                 state->vector[0].iov_base = (char *) base;
     196     2827900 :                 state->vector[0].iov_len -= len;
     197             : 
     198     2827900 :                 tgss->read.ofs += len;
     199     2827900 :                 tgss->read.left -= len;
     200             : 
     201     2827900 :                 if (state->vector[0].iov_len == 0) {
     202     2791384 :                         state->vector += 1;
     203     2791384 :                         state->count -= 1;
     204             :                 }
     205             : 
     206     2827900 :                 state->ret += len;
     207             :         }
     208             : 
     209     3640574 :         if (state->count == 0) {
     210     2791384 :                 tevent_req_done(req);
     211     2791384 :                 return;
     212             :         }
     213             : 
     214      849190 :         data_blob_free(&tgss->read.unwrapped);
     215      849190 :         ZERO_STRUCT(state->wrapped);
     216             : 
     217      849190 :         subreq = tstream_readv_pdu_send(state, state->ev,
     218             :                                         tgss->plain_stream,
     219             :                                         tstream_gensec_readv_next_vector,
     220             :                                         state);
     221      849190 :         if (tevent_req_nomem(subreq, req)) {
     222           0 :                 return;
     223             :         }
     224      849190 :         tevent_req_set_callback(subreq, tstream_gensec_readv_wrapped_done, req);
     225             : }
     226             : 
     227     2512820 : static int tstream_gensec_readv_next_vector(struct tstream_context *unix_stream,
     228             :                                             void *private_data,
     229             :                                             TALLOC_CTX *mem_ctx,
     230             :                                             struct iovec **_vector,
     231             :                                             size_t *_count)
     232             : {
     233     1916190 :         struct tstream_gensec_readv_state *state =
     234      596630 :                 talloc_get_type_abort(private_data,
     235             :                 struct tstream_gensec_readv_state);
     236             :         struct iovec *vector;
     237     2512820 :         size_t count = 1;
     238             : 
     239             :         /* we need to get a message header */
     240     2512820 :         vector = talloc_array(mem_ctx, struct iovec, count);
     241     2512820 :         if (!vector) {
     242           0 :                 return -1;
     243             :         }
     244             : 
     245     2512820 :         if (!state->wrapped.asked_for_hdr) {
     246      849190 :                 state->wrapped.asked_for_hdr = true;
     247      849190 :                 vector[0].iov_base = (char *)state->wrapped.hdr;
     248      849190 :                 vector[0].iov_len = sizeof(state->wrapped.hdr);
     249     1663630 :         } else if (!state->wrapped.asked_for_blob) {
     250             :                 uint32_t msg_len;
     251             : 
     252      831815 :                 state->wrapped.asked_for_blob = true;
     253             : 
     254      831815 :                 msg_len = RIVAL(state->wrapped.hdr, 0);
     255             : 
     256             :                 /*
     257             :                  * I got a Windows 2012R2 server responding with
     258             :                  * a message of 0x1b28a33.
     259             :                  */
     260      831815 :                 if (msg_len > 0x0FFFFFFF) {
     261           0 :                         errno = EMSGSIZE;
     262           0 :                         return -1;
     263             :                 }
     264             : 
     265      831815 :                 if (msg_len == 0) {
     266           0 :                         errno = EMSGSIZE;
     267           0 :                         return -1;
     268             :                 }
     269             : 
     270      831815 :                 state->wrapped.blob = data_blob_talloc(state, NULL, msg_len);
     271      831815 :                 if (state->wrapped.blob.data == NULL) {
     272           0 :                         return -1;
     273             :                 }
     274             : 
     275      831815 :                 vector[0].iov_base = (char *)state->wrapped.blob.data;
     276      831815 :                 vector[0].iov_len = state->wrapped.blob.length;
     277             :         } else {
     278      831815 :                 *_vector = NULL;
     279      831815 :                 *_count = 0;
     280      831815 :                 return 0;
     281             :         }
     282             : 
     283     1681005 :         *_vector = vector;
     284     1681005 :         *_count = count;
     285     1681005 :         return 0;
     286             : }
     287             : 
     288      849186 : static void tstream_gensec_readv_wrapped_done(struct tevent_req *subreq)
     289             : {
     290      647103 :         struct tevent_req *req =
     291      849186 :                 tevent_req_callback_data(subreq,
     292             :                 struct tevent_req);
     293      647103 :         struct tstream_gensec_readv_state *state =
     294      849186 :                 tevent_req_data(req,
     295             :                 struct tstream_gensec_readv_state);
     296      647103 :         struct tstream_gensec *tgss =
     297      849186 :                 tstream_context_data(state->stream,
     298             :                 struct tstream_gensec);
     299             :         int ret;
     300             :         int sys_errno;
     301             :         NTSTATUS status;
     302             : 
     303      849186 :         ret = tstream_readv_pdu_recv(subreq, &sys_errno);
     304      849186 :         TALLOC_FREE(subreq);
     305      849186 :         if (ret == -1) {
     306       17371 :                 tgss->error = sys_errno;
     307       17371 :                 tevent_req_error(req, sys_errno);
     308       17371 :                 return;
     309             :         }
     310             : 
     311     1466357 :         status = gensec_unwrap(tgss->gensec_security,
     312             :                                state,
     313      831815 :                                &state->wrapped.blob,
     314             :                                &tgss->read.unwrapped);
     315      831815 :         if (!NT_STATUS_IS_OK(status)) {
     316           0 :                 tgss->error = EIO;
     317           0 :                 tevent_req_error(req, tgss->error);
     318           0 :                 return;
     319             :         }
     320             : 
     321      831815 :         data_blob_free(&state->wrapped.blob);
     322             : 
     323      831815 :         talloc_steal(tgss, tgss->read.unwrapped.data);
     324      831815 :         tgss->read.left = tgss->read.unwrapped.length;
     325      831815 :         tgss->read.ofs = 0;
     326             : 
     327      831815 :         tstream_gensec_readv_wrapped_next(req);
     328             : }
     329             : 
     330     2808755 : static int tstream_gensec_readv_recv(struct tevent_req *req, int *perrno)
     331             : {
     332     2220116 :         struct tstream_gensec_readv_state *state =
     333     2808755 :                 tevent_req_data(req,
     334             :                 struct tstream_gensec_readv_state);
     335             :         int ret;
     336             : 
     337     2808755 :         ret = tsocket_simple_int_recv(req, perrno);
     338     2808755 :         if (ret == 0) {
     339     2791384 :                 ret = state->ret;
     340             :         }
     341             : 
     342     2808755 :         tevent_req_received(req);
     343     2808755 :         return ret;
     344             : }
     345             : 
     346             : struct tstream_gensec_writev_state {
     347             :         struct tevent_context *ev;
     348             :         struct tstream_context *stream;
     349             : 
     350             :         struct iovec *vector;
     351             :         int count;
     352             : 
     353             :         struct {
     354             :                 off_t ofs;
     355             :                 size_t left;
     356             :                 DATA_BLOB blob;
     357             :         } unwrapped;
     358             : 
     359             :         struct {
     360             :                 uint8_t hdr[4];
     361             :                 DATA_BLOB blob;
     362             :                 struct iovec iov[2];
     363             :         } wrapped;
     364             : 
     365             :         int ret;
     366             : };
     367             : 
     368             : static void tstream_gensec_writev_wrapped_next(struct tevent_req *req);
     369             : 
     370      795025 : static struct tevent_req *tstream_gensec_writev_send(TALLOC_CTX *mem_ctx,
     371             :                                         struct tevent_context *ev,
     372             :                                         struct tstream_context *stream,
     373             :                                         const struct iovec *vector,
     374             :                                         size_t count)
     375             : {
     376      597905 :         struct tstream_gensec *tgss =
     377      795025 :                 tstream_context_data(stream,
     378             :                 struct tstream_gensec);
     379             :         struct tevent_req *req;
     380             :         struct tstream_gensec_writev_state *state;
     381             :         int i;
     382             :         int total;
     383             :         int chunk;
     384             : 
     385      795025 :         req = tevent_req_create(mem_ctx, &state,
     386             :                                 struct tstream_gensec_writev_state);
     387      795025 :         if (req == NULL) {
     388           0 :                 return NULL;
     389             :         }
     390             : 
     391      795025 :         if (tgss->error != 0) {
     392           0 :                 tevent_req_error(req, tgss->error);
     393           0 :                 return tevent_req_post(req, ev);
     394             :         }
     395             : 
     396      795025 :         state->ev = ev;
     397      795025 :         state->stream = stream;
     398      795025 :         state->ret = 0;
     399             : 
     400             :         /*
     401             :          * we make a copy of the vector so we can change the structure
     402             :          */
     403      795025 :         state->vector = talloc_array(state, struct iovec, count);
     404      795025 :         if (tevent_req_nomem(state->vector, req)) {
     405           0 :                 return tevent_req_post(req, ev);
     406             :         }
     407      795955 :         memcpy(state->vector, vector, sizeof(struct iovec) * count);
     408      795025 :         state->count = count;
     409             : 
     410      795025 :         total = 0;
     411     2191592 :         for (i = 0; i < count; i++) {
     412             :                 /*
     413             :                  * the generic tstream code makes sure that
     414             :                  * this never wraps.
     415             :                  */
     416     1396567 :                 total += vector[i].iov_len;
     417             :         }
     418             : 
     419             :         /*
     420             :          * We may need to send data in chunks.
     421             :          */
     422      795025 :         chunk = MIN(total, tgss->write.max_unwrapped_size);
     423             : 
     424      795025 :         state->unwrapped.blob = data_blob_talloc(state, NULL, chunk);
     425      795025 :         if (tevent_req_nomem(state->unwrapped.blob.data, req)) {
     426           0 :                 return tevent_req_post(req, ev);
     427             :         }
     428             : 
     429      795025 :         tstream_gensec_writev_wrapped_next(req);
     430      795025 :         if (!tevent_req_is_in_progress(req)) {
     431           0 :                 return tevent_req_post(req, ev);
     432             :         }
     433             : 
     434      794095 :         return req;
     435             : }
     436             : 
     437             : static void tstream_gensec_writev_wrapped_done(struct tevent_req *subreq);
     438             : 
     439     1626565 : static void tstream_gensec_writev_wrapped_next(struct tevent_req *req)
     440             : {
     441     1232305 :         struct tstream_gensec_writev_state *state =
     442     1626565 :                 tevent_req_data(req,
     443             :                 struct tstream_gensec_writev_state);
     444     1232305 :         struct tstream_gensec *tgss =
     445     1626565 :                 tstream_context_data(state->stream,
     446             :                 struct tstream_gensec);
     447             :         struct tevent_req *subreq;
     448             :         NTSTATUS status;
     449             : 
     450     1626565 :         data_blob_free(&state->wrapped.blob);
     451             : 
     452     1626565 :         state->unwrapped.left = state->unwrapped.blob.length;
     453     1626565 :         state->unwrapped.ofs = 0;
     454             : 
     455             :         /*
     456             :          * first fill our buffer
     457             :          */
     458     4291953 :         while (state->unwrapped.left > 0 && state->count > 0) {
     459     1433083 :                 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
     460     1433083 :                 size_t len = MIN(state->unwrapped.left, state->vector[0].iov_len);
     461             : 
     462     1434298 :                 memcpy(state->unwrapped.blob.data + state->unwrapped.ofs, base, len);
     463             : 
     464     1433083 :                 base += len;
     465     1433083 :                 state->vector[0].iov_base = (char *) base;
     466     1433083 :                 state->vector[0].iov_len -= len;
     467             : 
     468     1433083 :                 state->unwrapped.ofs += len;
     469     1433083 :                 state->unwrapped.left -= len;
     470             : 
     471     1433083 :                 if (state->vector[0].iov_len == 0) {
     472     1396567 :                         state->vector += 1;
     473     1396567 :                         state->count -= 1;
     474             :                 }
     475             : 
     476     1433083 :                 state->ret += len;
     477             :         }
     478             : 
     479     1626565 :         if (state->unwrapped.ofs == 0) {
     480      795024 :                 tevent_req_done(req);
     481      795024 :                 return;
     482             :         }
     483             : 
     484      831541 :         state->unwrapped.blob.length = state->unwrapped.ofs;
     485             : 
     486     1465012 :         status = gensec_wrap(tgss->gensec_security,
     487             :                              state,
     488      831541 :                              &state->unwrapped.blob,
     489             :                              &state->wrapped.blob);
     490      831541 :         if (!NT_STATUS_IS_OK(status)) {
     491           0 :                 tgss->error = EIO;
     492           0 :                 tevent_req_error(req, tgss->error);
     493           0 :                 return;
     494             :         }
     495             : 
     496      831541 :         RSIVAL(state->wrapped.hdr, 0, state->wrapped.blob.length);
     497             : 
     498      831541 :         state->wrapped.iov[0].iov_base = (void *)state->wrapped.hdr;
     499      831541 :         state->wrapped.iov[0].iov_len = sizeof(state->wrapped.hdr);
     500      831541 :         state->wrapped.iov[1].iov_base = (void *)state->wrapped.blob.data;
     501      831541 :         state->wrapped.iov[1].iov_len = state->wrapped.blob.length;
     502             : 
     503      831541 :         subreq = tstream_writev_send(state, state->ev,
     504             :                                       tgss->plain_stream,
     505      831541 :                                       state->wrapped.iov, 2);
     506      831541 :         if (tevent_req_nomem(subreq, req)) {
     507           0 :                 return;
     508             :         }
     509      831541 :         tevent_req_set_callback(subreq,
     510             :                                 tstream_gensec_writev_wrapped_done,
     511             :                                 req);
     512             : }
     513             : 
     514      831540 : static void tstream_gensec_writev_wrapped_done(struct tevent_req *subreq)
     515             : {
     516      634400 :         struct tevent_req *req =
     517      831540 :                 tevent_req_callback_data(subreq,
     518             :                 struct tevent_req);
     519      634400 :         struct tstream_gensec_writev_state *state =
     520      831540 :                 tevent_req_data(req,
     521             :                 struct tstream_gensec_writev_state);
     522      634400 :         struct tstream_gensec *tgss =
     523      831540 :                 tstream_context_data(state->stream,
     524             :                 struct tstream_gensec);
     525             :         int sys_errno;
     526             :         int ret;
     527             : 
     528      831540 :         ret = tstream_writev_recv(subreq, &sys_errno);
     529      831540 :         TALLOC_FREE(subreq);
     530      831540 :         if (ret == -1) {
     531           0 :                 tgss->error = sys_errno;
     532           0 :                 tevent_req_error(req, sys_errno);
     533           0 :                 return;
     534             :         }
     535             : 
     536      831540 :         tstream_gensec_writev_wrapped_next(req);
     537             : }
     538             : 
     539      795024 : static int tstream_gensec_writev_recv(struct tevent_req *req,
     540             :                                    int *perrno)
     541             : {
     542      597904 :         struct tstream_gensec_writev_state *state =
     543      795024 :                 tevent_req_data(req,
     544             :                 struct tstream_gensec_writev_state);
     545             :         int ret;
     546             : 
     547      795024 :         ret = tsocket_simple_int_recv(req, perrno);
     548      795024 :         if (ret == 0) {
     549      795024 :                 ret = state->ret;
     550             :         }
     551             : 
     552      795024 :         tevent_req_received(req);
     553      795024 :         return ret;
     554             : }
     555             : 
     556             : struct tstream_gensec_disconnect_state {
     557             :         uint8_t _dummy;
     558             : };
     559             : 
     560       17647 : static struct tevent_req *tstream_gensec_disconnect_send(TALLOC_CTX *mem_ctx,
     561             :                                                          struct tevent_context *ev,
     562             :                                                          struct tstream_context *stream)
     563             : {
     564       12704 :         struct tstream_gensec *tgss =
     565       17647 :                 tstream_context_data(stream,
     566             :                 struct tstream_gensec);
     567             :         struct tevent_req *req;
     568             :         struct tstream_gensec_disconnect_state *state;
     569             : 
     570       17647 :         req = tevent_req_create(mem_ctx, &state,
     571             :                                 struct tstream_gensec_disconnect_state);
     572       17647 :         if (req == NULL) {
     573           0 :                 return NULL;
     574             :         }
     575             : 
     576       17647 :         if (tgss->error != 0) {
     577       17371 :                 tevent_req_error(req, tgss->error);
     578       17371 :                 return tevent_req_post(req, ev);
     579             :         }
     580             : 
     581             :         /*
     582             :          * The caller is responsible to do the real disconnect
     583             :          * on the plain stream!
     584             :          */
     585         276 :         tgss->plain_stream = NULL;
     586         276 :         tgss->error = ENOTCONN;
     587             : 
     588         276 :         tevent_req_done(req);
     589         276 :         return tevent_req_post(req, ev);
     590             : }
     591             : 
     592       17647 : static int tstream_gensec_disconnect_recv(struct tevent_req *req,
     593             :                                        int *perrno)
     594             : {
     595             :         int ret;
     596             : 
     597       17647 :         ret = tsocket_simple_int_recv(req, perrno);
     598             : 
     599       17647 :         tevent_req_received(req);
     600       17647 :         return ret;
     601             : }
     602             : 
     603             : static const struct tstream_context_ops tstream_gensec_ops = {
     604             :         .name                   = "gensec",
     605             : 
     606             :         .pending_bytes          = tstream_gensec_pending_bytes,
     607             : 
     608             :         .readv_send             = tstream_gensec_readv_send,
     609             :         .readv_recv             = tstream_gensec_readv_recv,
     610             : 
     611             :         .writev_send            = tstream_gensec_writev_send,
     612             :         .writev_recv            = tstream_gensec_writev_recv,
     613             : 
     614             :         .disconnect_send        = tstream_gensec_disconnect_send,
     615             :         .disconnect_recv        = tstream_gensec_disconnect_recv,
     616             : };

Generated by: LCOV version 1.13