LCOV - code coverage report
Current view: top level - source4/lib/tls - tls_tstream.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 610 914 66.7 %
Date: 2024-05-31 13:13:24 Functions: 40 41 97.6 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Stefan Metzmacher 2010
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "system/network.h"
      22             : #include "system/filesys.h"
      23             : #include "system/time.h"
      24             : #include "lib/util/util_file.h"
      25             : #include "../util/tevent_unix.h"
      26             : #include "../lib/tsocket/tsocket.h"
      27             : #include "../lib/tsocket/tsocket_internal.h"
      28             : #include "../lib/util/util_net.h"
      29             : #include "lib/tls/tls.h"
      30             : #include "lib/param/param.h"
      31             : 
      32             : #include <gnutls/gnutls.h>
      33             : #include <gnutls/x509.h>
      34             : #include "lib/crypto/gnutls_helpers.h"
      35             : 
      36             : #define DH_BITS 2048
      37             : 
      38          17 : const char *tls_verify_peer_string(enum tls_verify_peer_state verify_peer)
      39             : {
      40          17 :         switch (verify_peer) {
      41           0 :         case TLS_VERIFY_PEER_NO_CHECK:
      42           0 :                 return TLS_VERIFY_PEER_NO_CHECK_STRING;
      43             : 
      44           0 :         case TLS_VERIFY_PEER_CA_ONLY:
      45           0 :                 return TLS_VERIFY_PEER_CA_ONLY_STRING;
      46             : 
      47           3 :         case TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE:
      48           3 :                 return TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE_STRING;
      49             : 
      50           6 :         case TLS_VERIFY_PEER_CA_AND_NAME:
      51           6 :                 return TLS_VERIFY_PEER_CA_AND_NAME_STRING;
      52             : 
      53           8 :         case TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE:
      54           8 :                 return TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE_STRING;
      55             :         }
      56             : 
      57           0 :         return "unknown tls_verify_peer_state";
      58             : }
      59             : 
      60             : static const struct tstream_context_ops tstream_tls_ops;
      61             : 
      62             : struct tstream_tls {
      63             :         struct tstream_context *plain_stream;
      64             :         int error;
      65             : 
      66             :         gnutls_session_t tls_session;
      67             : 
      68             :         bool is_server;
      69             : 
      70             :         enum tls_verify_peer_state verify_peer;
      71             :         const char *peer_name;
      72             : 
      73             :         DATA_BLOB channel_bindings;
      74             : 
      75             :         struct tevent_context *current_ev;
      76             : 
      77             :         struct tevent_immediate *retry_im;
      78             : 
      79             :         struct {
      80             :                 struct tevent_req *mgmt_req;
      81             :         } waiting_flush;
      82             : 
      83             :         struct {
      84             :                 uint8_t *buf;
      85             :                 off_t ofs;
      86             :                 struct iovec iov;
      87             :                 struct tevent_req *subreq;
      88             :         } push;
      89             : 
      90             :         struct {
      91             :                 uint8_t *buf;
      92             :                 struct iovec iov;
      93             :                 struct tevent_req *subreq;
      94             :         } pull;
      95             : 
      96             :         struct {
      97             :                 struct tevent_req *req;
      98             :         } handshake;
      99             : 
     100             :         struct {
     101             :                 off_t ofs;
     102             :                 size_t left;
     103             :                 uint8_t buffer[1024];
     104             :                 struct tevent_req *req;
     105             :         } write;
     106             : 
     107             :         struct {
     108             :                 off_t ofs;
     109             :                 size_t left;
     110             :                 uint8_t buffer[1024];
     111             :                 struct tevent_req *req;
     112             :         } read;
     113             : 
     114             :         struct {
     115             :                 struct tevent_req *req;
     116             :         } disconnect;
     117             : };
     118             : 
     119             : static void tstream_tls_retry_handshake(struct tstream_context *stream);
     120             : static void tstream_tls_retry_read(struct tstream_context *stream);
     121             : static void tstream_tls_retry_write(struct tstream_context *stream);
     122             : static void tstream_tls_retry_disconnect(struct tstream_context *stream);
     123             : static void tstream_tls_retry_trigger(struct tevent_context *ctx,
     124             :                                       struct tevent_immediate *im,
     125             :                                       void *private_data);
     126             : 
     127     3466209 : static void tstream_tls_retry(struct tstream_context *stream, bool deferred)
     128             : {
     129             : 
     130           0 :         struct tstream_tls *tlss =
     131     3466209 :                 tstream_context_data(stream,
     132             :                 struct tstream_tls);
     133             : 
     134     3466209 :         if (tlss->push.subreq == NULL && tlss->pull.subreq == NULL) {
     135     3463222 :                 if (tlss->waiting_flush.mgmt_req != NULL) {
     136         588 :                         struct tevent_req *req = tlss->waiting_flush.mgmt_req;
     137             : 
     138         588 :                         tlss->waiting_flush.mgmt_req = NULL;
     139             : 
     140         588 :                         tevent_req_done(req);
     141         588 :                         return;
     142             :                 }
     143             :         }
     144             : 
     145     3465621 :         if (tlss->disconnect.req) {
     146           0 :                 tstream_tls_retry_disconnect(stream);
     147           0 :                 return;
     148             :         }
     149             : 
     150     3465621 :         if (tlss->handshake.req) {
     151       19632 :                 tstream_tls_retry_handshake(stream);
     152       19632 :                 return;
     153             :         }
     154             : 
     155     3445989 :         if (tlss->write.req && tlss->read.req && !deferred) {
     156           0 :                 tevent_schedule_immediate(tlss->retry_im, tlss->current_ev,
     157             :                                           tstream_tls_retry_trigger,
     158           0 :                                           stream);
     159             :         }
     160             : 
     161     3445989 :         if (tlss->write.req) {
     162     1137050 :                 tstream_tls_retry_write(stream);
     163     1137050 :                 return;
     164             :         }
     165             : 
     166     2308939 :         if (tlss->read.req) {
     167     2301559 :                 tstream_tls_retry_read(stream);
     168     2301559 :                 return;
     169             :         }
     170             : }
     171             : 
     172           0 : static void tstream_tls_retry_trigger(struct tevent_context *ctx,
     173             :                                       struct tevent_immediate *im,
     174             :                                       void *private_data)
     175             : {
     176           0 :         struct tstream_context *stream =
     177           0 :                 talloc_get_type_abort(private_data,
     178             :                 struct tstream_context);
     179             : 
     180           0 :         tstream_tls_retry(stream, true);
     181           0 : }
     182             : 
     183             : static void tstream_tls_push_done(struct tevent_req *subreq);
     184             : 
     185     2293926 : static ssize_t tstream_tls_push_function(gnutls_transport_ptr_t ptr,
     186             :                                          const void *buf, size_t size)
     187             : {
     188           0 :         struct tstream_context *stream =
     189     2293926 :                 talloc_get_type_abort(ptr,
     190             :                 struct tstream_context);
     191           0 :         struct tstream_tls *tlss =
     192     2293926 :                 tstream_context_data(stream,
     193             :                 struct tstream_tls);
     194     2293926 :         struct tevent_req *subreq = NULL;
     195           0 :         uint8_t *nbuf;
     196           0 :         size_t len;
     197             : 
     198     2293926 :         if (tlss->error != 0) {
     199           0 :                 errno = tlss->error;
     200           0 :                 return -1;
     201             :         }
     202             : 
     203     2293926 :         if (tlss->push.subreq) {
     204     1141480 :                 errno = EAGAIN;
     205     1141480 :                 return -1;
     206             :         }
     207             : 
     208     1152446 :         len = MIN(size, UINT16_MAX - tlss->push.ofs);
     209             : 
     210     1152446 :         if (len == 0) {
     211           0 :                 errno = EAGAIN;
     212           0 :                 return -1;
     213             :         }
     214             : 
     215     1152446 :         nbuf = talloc_realloc(tlss, tlss->push.buf,
     216             :                               uint8_t, tlss->push.ofs + len);
     217     1152446 :         if (nbuf == NULL) {
     218           0 :                 if (tlss->push.buf) {
     219           0 :                         errno = EAGAIN;
     220           0 :                         return -1;
     221             :                 }
     222             : 
     223           0 :                 return -1;
     224             :         }
     225     1152446 :         tlss->push.buf = nbuf;
     226             : 
     227     1152446 :         memcpy(tlss->push.buf + tlss->push.ofs, buf, len);
     228     1152446 :         tlss->push.ofs += len;
     229             : 
     230     1152446 :         tlss->push.iov.iov_base = (char *)tlss->push.buf;
     231     1152446 :         tlss->push.iov.iov_len = tlss->push.ofs;
     232             : 
     233     1152446 :         subreq = tstream_writev_send(tlss,
     234             :                                      tlss->current_ev,
     235             :                                      tlss->plain_stream,
     236     1152446 :                                      &tlss->push.iov, 1);
     237     1152446 :         if (subreq == NULL) {
     238           0 :                 errno = ENOMEM;
     239           0 :                 return -1;
     240             :         }
     241     1152446 :         tevent_req_set_callback(subreq, tstream_tls_push_done, stream);
     242             : 
     243     1152446 :         tlss->push.subreq = subreq;
     244     1152446 :         return len;
     245             : }
     246             : 
     247     1152435 : static void tstream_tls_push_done(struct tevent_req *subreq)
     248             : {
     249           0 :         struct tstream_context *stream =
     250     1152435 :                 tevent_req_callback_data(subreq,
     251             :                 struct tstream_context);
     252           0 :         struct tstream_tls *tlss =
     253     1152435 :                 tstream_context_data(stream,
     254             :                 struct tstream_tls);
     255           0 :         int ret;
     256           0 :         int sys_errno;
     257             : 
     258     1152435 :         tlss->push.subreq = NULL;
     259     1152435 :         ZERO_STRUCT(tlss->push.iov);
     260     1152435 :         TALLOC_FREE(tlss->push.buf);
     261     1152435 :         tlss->push.ofs = 0;
     262             : 
     263     1152435 :         ret = tstream_writev_recv(subreq, &sys_errno);
     264     1152435 :         TALLOC_FREE(subreq);
     265     1152435 :         if (ret == -1) {
     266           2 :                 tlss->error = sys_errno;
     267           2 :                 tstream_tls_retry(stream, false);
     268           2 :                 return;
     269             :         }
     270             : 
     271     1152433 :         tstream_tls_retry(stream, false);
     272             : }
     273             : 
     274             : static void tstream_tls_pull_done(struct tevent_req *subreq);
     275             : 
     276     4629913 : static ssize_t tstream_tls_pull_function(gnutls_transport_ptr_t ptr,
     277             :                                          void *buf, size_t size)
     278             : {
     279           0 :         struct tstream_context *stream =
     280     4629913 :                 talloc_get_type_abort(ptr,
     281             :                 struct tstream_context);
     282           0 :         struct tstream_tls *tlss =
     283     4629913 :                 tstream_context_data(stream,
     284             :                 struct tstream_tls);
     285           0 :         struct tevent_req *subreq;
     286           0 :         size_t len;
     287             : 
     288     4629913 :         if (tlss->error != 0) {
     289           0 :                 errno = tlss->error;
     290           0 :                 return -1;
     291             :         }
     292             : 
     293     4629913 :         if (tlss->pull.subreq) {
     294        2986 :                 errno = EAGAIN;
     295        2986 :                 return -1;
     296             :         }
     297             : 
     298     4626927 :         if (tlss->pull.iov.iov_base) {
     299           0 :                 uint8_t *b;
     300           0 :                 size_t n;
     301             : 
     302     2313150 :                 b = (uint8_t *)tlss->pull.iov.iov_base;
     303             : 
     304     2313150 :                 n = MIN(tlss->pull.iov.iov_len, size);
     305     2313150 :                 memcpy(buf, b, n);
     306             : 
     307     2313150 :                 tlss->pull.iov.iov_len -= n;
     308     2313150 :                 b += n;
     309     2313150 :                 tlss->pull.iov.iov_base = (char *)b;
     310     2313150 :                 if (tlss->pull.iov.iov_len == 0) {
     311     2313150 :                         tlss->pull.iov.iov_base = NULL;
     312     2313150 :                         TALLOC_FREE(tlss->pull.buf);
     313             :                 }
     314             : 
     315     2313150 :                 return n;
     316             :         }
     317             : 
     318     2313777 :         if (size == 0) {
     319           0 :                 return 0;
     320             :         }
     321             : 
     322     2313777 :         len = MIN(size, UINT16_MAX);
     323             : 
     324     2313777 :         tlss->pull.buf = talloc_array(tlss, uint8_t, len);
     325     2313777 :         if (tlss->pull.buf == NULL) {
     326           0 :                 return -1;
     327             :         }
     328             : 
     329     2313777 :         tlss->pull.iov.iov_base = (char *)tlss->pull.buf;
     330     2313777 :         tlss->pull.iov.iov_len = len;
     331             : 
     332     2313777 :         subreq = tstream_readv_send(tlss,
     333             :                                     tlss->current_ev,
     334             :                                     tlss->plain_stream,
     335             :                                     &tlss->pull.iov, 1);
     336     2313777 :         if (subreq == NULL) {
     337           0 :                 errno = ENOMEM;
     338           0 :                 return -1;
     339             :         }
     340     2313777 :         tevent_req_set_callback(subreq, tstream_tls_pull_done, stream);
     341             : 
     342     2313777 :         tlss->pull.subreq = subreq;
     343     2313777 :         errno = EAGAIN;
     344     2313777 :         return -1;
     345             : }
     346             : 
     347     2313774 : static void tstream_tls_pull_done(struct tevent_req *subreq)
     348             : {
     349           0 :         struct tstream_context *stream =
     350     2313774 :                 tevent_req_callback_data(subreq,
     351             :                 struct tstream_context);
     352           0 :         struct tstream_tls *tlss =
     353     2313774 :                 tstream_context_data(stream,
     354             :                 struct tstream_tls);
     355           0 :         int ret;
     356           0 :         int sys_errno;
     357             : 
     358     2313774 :         tlss->pull.subreq = NULL;
     359             : 
     360     2313774 :         ret = tstream_readv_recv(subreq, &sys_errno);
     361     2313774 :         TALLOC_FREE(subreq);
     362     2313774 :         if (ret == -1) {
     363         624 :                 tlss->error = sys_errno;
     364         624 :                 tstream_tls_retry(stream, false);
     365         624 :                 return;
     366             :         }
     367             : 
     368     2313150 :         tstream_tls_retry(stream, false);
     369             : }
     370             : 
     371        1257 : static int tstream_tls_destructor(struct tstream_tls *tlss)
     372             : {
     373        1257 :         if (tlss->tls_session) {
     374        1257 :                 gnutls_deinit(tlss->tls_session);
     375        1257 :                 tlss->tls_session = NULL;
     376             :         }
     377             : 
     378        1257 :         return 0;
     379             : }
     380             : 
     381         220 : static ssize_t tstream_tls_pending_bytes(struct tstream_context *stream)
     382             : {
     383           0 :         struct tstream_tls *tlss =
     384         220 :                 tstream_context_data(stream,
     385             :                 struct tstream_tls);
     386           0 :         size_t ret;
     387             : 
     388         220 :         if (tlss->error != 0) {
     389           0 :                 errno = tlss->error;
     390           0 :                 return -1;
     391             :         }
     392             : 
     393         220 :         ret = gnutls_record_check_pending(tlss->tls_session);
     394         220 :         ret += tlss->read.left;
     395             : 
     396         220 :         return ret;
     397             : }
     398             : 
     399             : struct tstream_tls_readv_state {
     400             :         struct tstream_context *stream;
     401             : 
     402             :         struct iovec *vector;
     403             :         int count;
     404             : 
     405             :         int ret;
     406             : };
     407             : 
     408             : static void tstream_tls_readv_crypt_next(struct tevent_req *req);
     409             : 
     410       28100 : static struct tevent_req *tstream_tls_readv_send(TALLOC_CTX *mem_ctx,
     411             :                                         struct tevent_context *ev,
     412             :                                         struct tstream_context *stream,
     413             :                                         struct iovec *vector,
     414             :                                         size_t count)
     415             : {
     416           0 :         struct tstream_tls *tlss =
     417       28100 :                 tstream_context_data(stream,
     418             :                 struct tstream_tls);
     419           0 :         struct tevent_req *req;
     420           0 :         struct tstream_tls_readv_state *state;
     421             : 
     422       28100 :         tlss->read.req = NULL;
     423             : 
     424       28100 :         if (tlss->current_ev != ev) {
     425          12 :                 SMB_ASSERT(tlss->push.subreq == NULL);
     426          12 :                 SMB_ASSERT(tlss->pull.subreq == NULL);
     427             :         }
     428             : 
     429       28100 :         tlss->current_ev = ev;
     430             : 
     431       28100 :         req = tevent_req_create(mem_ctx, &state,
     432             :                                 struct tstream_tls_readv_state);
     433       28100 :         if (req == NULL) {
     434           0 :                 return NULL;
     435             :         }
     436             : 
     437       28100 :         state->stream = stream;
     438       28100 :         state->ret = 0;
     439             : 
     440       28100 :         if (tlss->error != 0) {
     441           0 :                 tevent_req_error(req, tlss->error);
     442           0 :                 return tevent_req_post(req, ev);
     443             :         }
     444             : 
     445             :         /*
     446             :          * we make a copy of the vector so we can change the structure
     447             :          */
     448       28100 :         state->vector = talloc_array(state, struct iovec, count);
     449       28100 :         if (tevent_req_nomem(state->vector, req)) {
     450           0 :                 return tevent_req_post(req, ev);
     451             :         }
     452       28100 :         memcpy(state->vector, vector, sizeof(struct iovec) * count);
     453       28100 :         state->count = count;
     454             : 
     455       28100 :         tstream_tls_readv_crypt_next(req);
     456       28100 :         if (!tevent_req_is_in_progress(req)) {
     457       16531 :                 return tevent_req_post(req, ev);
     458             :         }
     459             : 
     460       11569 :         return req;
     461             : }
     462             : 
     463     1242269 : static void tstream_tls_readv_crypt_next(struct tevent_req *req)
     464             : {
     465           0 :         struct tstream_tls_readv_state *state =
     466     1242269 :                 tevent_req_data(req,
     467             :                 struct tstream_tls_readv_state);
     468           0 :         struct tstream_tls *tlss =
     469     1242269 :                 tstream_context_data(state->stream,
     470             :                 struct tstream_tls);
     471             : 
     472             :         /*
     473             :          * copy the pending buffer first
     474             :          */
     475     2475304 :         while (tlss->read.left > 0 && state->count > 0) {
     476     1233035 :                 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
     477     1233035 :                 size_t len = MIN(tlss->read.left, state->vector[0].iov_len);
     478             : 
     479     1233035 :                 memcpy(base, tlss->read.buffer + tlss->read.ofs, len);
     480             : 
     481     1233035 :                 base += len;
     482     1233035 :                 state->vector[0].iov_base = (char *) base;
     483     1233035 :                 state->vector[0].iov_len -= len;
     484             : 
     485     1233035 :                 tlss->read.ofs += len;
     486     1233035 :                 tlss->read.left -= len;
     487             : 
     488     1233035 :                 if (state->vector[0].iov_len == 0) {
     489       27469 :                         state->vector += 1;
     490       27469 :                         state->count -= 1;
     491             :                 }
     492             : 
     493     1233035 :                 state->ret += len;
     494             :         }
     495             : 
     496     1242269 :         if (state->count == 0) {
     497       27469 :                 tevent_req_done(req);
     498       27469 :                 return;
     499             :         }
     500             : 
     501     1214800 :         tlss->read.req = req;
     502     1214800 :         tstream_tls_retry_read(state->stream);
     503             : }
     504             : 
     505     3516359 : static void tstream_tls_retry_read(struct tstream_context *stream)
     506             : {
     507           0 :         struct tstream_tls *tlss =
     508     3516359 :                 tstream_context_data(stream,
     509             :                 struct tstream_tls);
     510     3516359 :         struct tevent_req *req = tlss->read.req;
     511           0 :         int ret;
     512             : 
     513     3516359 :         if (tlss->error != 0) {
     514         623 :                 tevent_req_error(req, tlss->error);
     515         623 :                 return;
     516             :         }
     517             : 
     518     3515736 :         tlss->read.left = 0;
     519     3515736 :         tlss->read.ofs = 0;
     520             : 
     521     7031472 :         ret = gnutls_record_recv(tlss->tls_session,
     522     3515736 :                                  tlss->read.buffer,
     523             :                                  sizeof(tlss->read.buffer));
     524     3515736 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
     525     2301561 :                 return;
     526             :         }
     527             : 
     528     1214175 :         tlss->read.req = NULL;
     529             : 
     530     1214175 :         if (gnutls_error_is_fatal(ret) != 0) {
     531           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
     532           0 :                 tlss->error = EIO;
     533           0 :                 tevent_req_error(req, tlss->error);
     534           0 :                 return;
     535             :         }
     536             : 
     537     1214175 :         if (ret == 0) {
     538           6 :                 tlss->error = EPIPE;
     539           6 :                 tevent_req_error(req, tlss->error);
     540           6 :                 return;
     541             :         }
     542             : 
     543     1214169 :         tlss->read.left = ret;
     544     1214169 :         tstream_tls_readv_crypt_next(req);
     545             : }
     546             : 
     547       28098 : static int tstream_tls_readv_recv(struct tevent_req *req,
     548             :                                   int *perrno)
     549             : {
     550           0 :         struct tstream_tls_readv_state *state =
     551       28098 :                 tevent_req_data(req,
     552             :                 struct tstream_tls_readv_state);
     553           0 :         struct tstream_tls *tlss =
     554       28098 :                 tstream_context_data(state->stream,
     555             :                 struct tstream_tls);
     556           0 :         int ret;
     557             : 
     558       28098 :         tlss->read.req = NULL;
     559             : 
     560       28098 :         ret = tsocket_simple_int_recv(req, perrno);
     561       28098 :         if (ret == 0) {
     562       27469 :                 ret = state->ret;
     563             :         }
     564             : 
     565       28098 :         tevent_req_received(req);
     566       28098 :         return ret;
     567             : }
     568             : 
     569             : struct tstream_tls_writev_state {
     570             :         struct tstream_context *stream;
     571             : 
     572             :         struct iovec *vector;
     573             :         int count;
     574             : 
     575             :         int ret;
     576             : };
     577             : 
     578             : static void tstream_tls_writev_crypt_next(struct tevent_req *req);
     579             : 
     580        8575 : static struct tevent_req *tstream_tls_writev_send(TALLOC_CTX *mem_ctx,
     581             :                                         struct tevent_context *ev,
     582             :                                         struct tstream_context *stream,
     583             :                                         const struct iovec *vector,
     584             :                                         size_t count)
     585             : {
     586           0 :         struct tstream_tls *tlss =
     587        8575 :                 tstream_context_data(stream,
     588             :                 struct tstream_tls);
     589           0 :         struct tevent_req *req;
     590           0 :         struct tstream_tls_writev_state *state;
     591             : 
     592        8575 :         tlss->write.req = NULL;
     593             : 
     594        8575 :         if (tlss->current_ev != ev) {
     595           0 :                 SMB_ASSERT(tlss->push.subreq == NULL);
     596           0 :                 SMB_ASSERT(tlss->pull.subreq == NULL);
     597             :         }
     598             : 
     599        8575 :         tlss->current_ev = ev;
     600             : 
     601        8575 :         req = tevent_req_create(mem_ctx, &state,
     602             :                                 struct tstream_tls_writev_state);
     603        8575 :         if (req == NULL) {
     604           0 :                 return NULL;
     605             :         }
     606             : 
     607        8575 :         state->stream = stream;
     608        8575 :         state->ret = 0;
     609             : 
     610        8575 :         if (tlss->error != 0) {
     611           0 :                 tevent_req_error(req, tlss->error);
     612           0 :                 return tevent_req_post(req, ev);
     613             :         }
     614             : 
     615             :         /*
     616             :          * we make a copy of the vector so we can change the structure
     617             :          */
     618        8575 :         state->vector = talloc_array(state, struct iovec, count);
     619        8575 :         if (tevent_req_nomem(state->vector, req)) {
     620           0 :                 return tevent_req_post(req, ev);
     621             :         }
     622        8575 :         memcpy(state->vector, vector, sizeof(struct iovec) * count);
     623        8575 :         state->count = count;
     624             : 
     625        8575 :         tstream_tls_writev_crypt_next(req);
     626        8575 :         if (!tevent_req_is_in_progress(req)) {
     627        7600 :                 return tevent_req_post(req, ev);
     628             :         }
     629             : 
     630         975 :         return req;
     631             : }
     632             : 
     633     1154171 : static void tstream_tls_writev_crypt_next(struct tevent_req *req)
     634             : {
     635           0 :         struct tstream_tls_writev_state *state =
     636     1154171 :                 tevent_req_data(req,
     637             :                 struct tstream_tls_writev_state);
     638           0 :         struct tstream_tls *tlss =
     639     1154171 :                 tstream_context_data(state->stream,
     640             :                 struct tstream_tls);
     641             : 
     642     1154171 :         tlss->write.left = sizeof(tlss->write.buffer);
     643     1154171 :         tlss->write.ofs = 0;
     644             : 
     645             :         /*
     646             :          * first fill our buffer
     647             :          */
     648     2304951 :         while (tlss->write.left > 0 && state->count > 0) {
     649     1150780 :                 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
     650     1150780 :                 size_t len = MIN(tlss->write.left, state->vector[0].iov_len);
     651             : 
     652     1150780 :                 memcpy(tlss->write.buffer + tlss->write.ofs, base, len);
     653             : 
     654     1150780 :                 base += len;
     655     1150780 :                 state->vector[0].iov_base = (char *) base;
     656     1150780 :                 state->vector[0].iov_len -= len;
     657             : 
     658     1150780 :                 tlss->write.ofs += len;
     659     1150780 :                 tlss->write.left -= len;
     660             : 
     661     1150780 :                 if (state->vector[0].iov_len == 0) {
     662       13776 :                         state->vector += 1;
     663       13776 :                         state->count -= 1;
     664             :                 }
     665             : 
     666     1150780 :                 state->ret += len;
     667             :         }
     668             : 
     669     1154171 :         if (tlss->write.ofs == 0) {
     670        8575 :                 tevent_req_done(req);
     671        8575 :                 return;
     672             :         }
     673             : 
     674     1145596 :         tlss->write.left = tlss->write.ofs;
     675     1145596 :         tlss->write.ofs = 0;
     676             : 
     677     1145596 :         tlss->write.req = req;
     678     1145596 :         tstream_tls_retry_write(state->stream);
     679             : }
     680             : 
     681     2282646 : static void tstream_tls_retry_write(struct tstream_context *stream)
     682             : {
     683           0 :         struct tstream_tls *tlss =
     684     2282646 :                 tstream_context_data(stream,
     685             :                 struct tstream_tls);
     686     2282646 :         struct tevent_req *req = tlss->write.req;
     687           0 :         int ret;
     688             : 
     689     2282646 :         if (tlss->error != 0) {
     690           0 :                 tevent_req_error(req, tlss->error);
     691           0 :                 return;
     692             :         }
     693             : 
     694     4565292 :         ret = gnutls_record_send(tlss->tls_session,
     695     2282646 :                                  tlss->write.buffer + tlss->write.ofs,
     696             :                                  tlss->write.left);
     697     2282646 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
     698     1137050 :                 return;
     699             :         }
     700             : 
     701     1145596 :         tlss->write.req = NULL;
     702             : 
     703     1145596 :         if (gnutls_error_is_fatal(ret) != 0) {
     704           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
     705           0 :                 tlss->error = EIO;
     706           0 :                 tevent_req_error(req, tlss->error);
     707           0 :                 return;
     708             :         }
     709             : 
     710     1145596 :         if (ret == 0) {
     711           0 :                 tlss->error = EPIPE;
     712           0 :                 tevent_req_error(req, tlss->error);
     713           0 :                 return;
     714             :         }
     715             : 
     716     1145596 :         tlss->write.ofs += ret;
     717     1145596 :         tlss->write.left -= ret;
     718             : 
     719     1145596 :         if (tlss->write.left > 0) {
     720           0 :                 tlss->write.req = req;
     721           0 :                 tstream_tls_retry_write(stream);
     722           0 :                 return;
     723             :         }
     724             : 
     725     1145596 :         tstream_tls_writev_crypt_next(req);
     726             : }
     727             : 
     728        8575 : static int tstream_tls_writev_recv(struct tevent_req *req,
     729             :                                    int *perrno)
     730             : {
     731           0 :         struct tstream_tls_writev_state *state =
     732        8575 :                 tevent_req_data(req,
     733             :                 struct tstream_tls_writev_state);
     734           0 :         struct tstream_tls *tlss =
     735        8575 :                 tstream_context_data(state->stream,
     736             :                 struct tstream_tls);
     737           0 :         int ret;
     738             : 
     739        8575 :         tlss->write.req = NULL;
     740             : 
     741        8575 :         ret = tsocket_simple_int_recv(req, perrno);
     742        8575 :         if (ret == 0) {
     743        8575 :                 ret = state->ret;
     744             :         }
     745             : 
     746        8575 :         tevent_req_received(req);
     747        8575 :         return ret;
     748             : }
     749             : 
     750             : struct tstream_tls_disconnect_state {
     751             :         uint8_t _dummy;
     752             : };
     753             : 
     754         638 : static struct tevent_req *tstream_tls_disconnect_send(TALLOC_CTX *mem_ctx,
     755             :                                                 struct tevent_context *ev,
     756             :                                                 struct tstream_context *stream)
     757             : {
     758           0 :         struct tstream_tls *tlss =
     759         638 :                 tstream_context_data(stream,
     760             :                 struct tstream_tls);
     761           0 :         struct tevent_req *req;
     762           0 :         struct tstream_tls_disconnect_state *state;
     763             : 
     764         638 :         tlss->disconnect.req = NULL;
     765             : 
     766         638 :         if (tlss->current_ev != ev) {
     767           0 :                 SMB_ASSERT(tlss->push.subreq == NULL);
     768           0 :                 SMB_ASSERT(tlss->pull.subreq == NULL);
     769             :         }
     770             : 
     771         638 :         tlss->current_ev = ev;
     772             : 
     773         638 :         req = tevent_req_create(mem_ctx, &state,
     774             :                                 struct tstream_tls_disconnect_state);
     775         638 :         if (req == NULL) {
     776           0 :                 return NULL;
     777             :         }
     778             : 
     779         638 :         if (tlss->error != 0) {
     780         629 :                 tevent_req_error(req, tlss->error);
     781         629 :                 return tevent_req_post(req, ev);
     782             :         }
     783             : 
     784           9 :         tlss->disconnect.req = req;
     785           9 :         tstream_tls_retry_disconnect(stream);
     786           9 :         if (!tevent_req_is_in_progress(req)) {
     787           0 :                 return tevent_req_post(req, ev);
     788             :         }
     789             : 
     790           9 :         return req;
     791             : }
     792             : 
     793           9 : static void tstream_tls_retry_disconnect(struct tstream_context *stream)
     794             : {
     795           0 :         struct tstream_tls *tlss =
     796           9 :                 tstream_context_data(stream,
     797             :                 struct tstream_tls);
     798           9 :         struct tevent_req *req = tlss->disconnect.req;
     799           0 :         int ret;
     800             : 
     801           9 :         if (tlss->error != 0) {
     802           0 :                 tevent_req_error(req, tlss->error);
     803           0 :                 return;
     804             :         }
     805             : 
     806           9 :         ret = gnutls_bye(tlss->tls_session, GNUTLS_SHUT_WR);
     807           9 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
     808           0 :                 return;
     809             :         }
     810             : 
     811           9 :         tlss->disconnect.req = NULL;
     812             : 
     813           9 :         if (gnutls_error_is_fatal(ret) != 0) {
     814           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
     815           0 :                 tlss->error = EIO;
     816           0 :                 tevent_req_error(req, tlss->error);
     817           0 :                 return;
     818             :         }
     819             : 
     820           9 :         if (ret != GNUTLS_E_SUCCESS) {
     821           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
     822           0 :                 tlss->error = EIO;
     823           0 :                 tevent_req_error(req, tlss->error);
     824           0 :                 return;
     825             :         }
     826             : 
     827           9 :         if (tlss->push.subreq != NULL || tlss->pull.subreq != NULL) {
     828           9 :                 tlss->waiting_flush.mgmt_req = req;
     829           9 :                 return;
     830             :         }
     831             : 
     832           0 :         tevent_req_done(req);
     833             : }
     834             : 
     835         638 : static int tstream_tls_disconnect_recv(struct tevent_req *req,
     836             :                                        int *perrno)
     837             : {
     838           0 :         int ret;
     839             : 
     840         638 :         ret = tsocket_simple_int_recv(req, perrno);
     841             : 
     842         638 :         tevent_req_received(req);
     843         638 :         return ret;
     844             : }
     845             : 
     846             : static const struct tstream_context_ops tstream_tls_ops = {
     847             :         .name                   = "tls",
     848             : 
     849             :         .pending_bytes          = tstream_tls_pending_bytes,
     850             : 
     851             :         .readv_send             = tstream_tls_readv_send,
     852             :         .readv_recv             = tstream_tls_readv_recv,
     853             : 
     854             :         .writev_send            = tstream_tls_writev_send,
     855             :         .writev_recv            = tstream_tls_writev_recv,
     856             : 
     857             :         .disconnect_send        = tstream_tls_disconnect_send,
     858             :         .disconnect_recv        = tstream_tls_disconnect_recv,
     859             : };
     860             : 
     861             : struct tstream_tls_params_internal {
     862             :         gnutls_certificate_credentials_t x509_cred;
     863             :         gnutls_dh_params_t dh_params;
     864             :         const char *tls_priority;
     865             :         bool tls_enabled;
     866             :         enum tls_verify_peer_state verify_peer;
     867             :         const char *peer_name;
     868             : };
     869             : 
     870             : struct tstream_tls_params {
     871             :         struct tstream_tls_params_internal *internal;
     872             : };
     873             : 
     874       15966 : static int tstream_tls_params_internal_destructor(struct tstream_tls_params_internal *tlsp)
     875             : {
     876       15966 :         if (tlsp->x509_cred) {
     877       15966 :                 gnutls_certificate_free_credentials(tlsp->x509_cred);
     878       15966 :                 tlsp->x509_cred = NULL;
     879             :         }
     880       15966 :         if (tlsp->dh_params) {
     881       15344 :                 gnutls_dh_params_deinit(tlsp->dh_params);
     882       15344 :                 tlsp->dh_params = NULL;
     883             :         }
     884             : 
     885       15966 :         return 0;
     886             : }
     887             : 
     888         240 : bool tstream_tls_params_enabled(struct tstream_tls_params *tls_params)
     889             : {
     890         240 :         struct tstream_tls_params_internal *tlsp = tls_params->internal;
     891             : 
     892         240 :         return tlsp->tls_enabled;
     893             : }
     894             : 
     895        1243 : static NTSTATUS tstream_tls_setup_channel_bindings(struct tstream_tls *tlss)
     896             : {
     897        1243 :         gnutls_datum_t cb = { .size = 0 };
     898           0 :         int ret;
     899             : 
     900             : #ifdef HAVE_GNUTLS_CB_TLS_SERVER_END_POINT
     901        1243 :         ret = gnutls_session_channel_binding(tlss->tls_session,
     902             :                                              GNUTLS_CB_TLS_SERVER_END_POINT,
     903             :                                              &cb);
     904             : #else /* not HAVE_GNUTLS_CB_TLS_SERVER_END_POINT */
     905             :         ret = legacy_gnutls_server_end_point_cb(tlss->tls_session,
     906             :                                                 tlss->is_server,
     907             :                                                 &cb);
     908             : #endif /* not HAVE_GNUTLS_CB_TLS_SERVER_END_POINT */
     909        1243 :         if (ret != GNUTLS_E_SUCCESS) {
     910           0 :                 return gnutls_error_to_ntstatus(ret,
     911             :                                 NT_STATUS_CRYPTO_SYSTEM_INVALID);
     912             :         }
     913             : 
     914        1243 :         if (cb.size != 0) {
     915             :                 /*
     916             :                  * Looking at the OpenLDAP implementation
     917             :                  * for LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT
     918             :                  * revealed that we need to prefix it with
     919             :                  * 'tls-server-end-point:'
     920             :                  */
     921        1243 :                 const char endpoint_prefix[] = "tls-server-end-point:";
     922        1243 :                 size_t prefix_size = strlen(endpoint_prefix);
     923        1243 :                 size_t size = prefix_size + cb.size;
     924             : 
     925        1243 :                 tlss->channel_bindings = data_blob_talloc_named(tlss, NULL, size,
     926             :                                                                 "tls_channel_bindings");
     927        1243 :                 if (tlss->channel_bindings.data == NULL) {
     928           0 :                         gnutls_free(cb.data);
     929           0 :                         return NT_STATUS_NO_MEMORY;
     930             :                 }
     931        1243 :                 memcpy(tlss->channel_bindings.data, endpoint_prefix, prefix_size);
     932        1243 :                 memcpy(tlss->channel_bindings.data + prefix_size, cb.data, cb.size);
     933        1243 :                 gnutls_free(cb.data);
     934             :         }
     935             : 
     936        1243 :         return NT_STATUS_OK;
     937             : }
     938             : 
     939         350 : const DATA_BLOB *tstream_tls_channel_bindings(struct tstream_context *tls_tstream)
     940             : {
     941           0 :         struct tstream_tls *tlss =
     942         350 :                 talloc_get_type(_tstream_context_data(tls_tstream),
     943             :                 struct tstream_tls);
     944             : 
     945         350 :         if (tlss == NULL) {
     946           0 :                 return NULL;
     947             :         }
     948             : 
     949         350 :         return &tlss->channel_bindings;
     950             : }
     951             : 
     952         622 : NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
     953             :                                    bool system_cas,
     954             :                                    const char * const *ca_dirs,
     955             :                                    const char *ca_file,
     956             :                                    const char *crl_file,
     957             :                                    const char *tls_priority,
     958             :                                    enum tls_verify_peer_state verify_peer,
     959             :                                    const char *peer_name,
     960             :                                    struct tstream_tls_params **_tlsp)
     961             : {
     962         622 :         struct tstream_tls_params *__tlsp = NULL;
     963         622 :         struct tstream_tls_params_internal *tlsp = NULL;
     964         622 :         bool got_ca = false;
     965           0 :         size_t i;
     966           0 :         int ret;
     967             : 
     968         622 :         __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
     969         622 :         if (__tlsp == NULL) {
     970           0 :                 return NT_STATUS_NO_MEMORY;
     971             :         }
     972             : 
     973         622 :         tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
     974         622 :         if (tlsp == NULL) {
     975           0 :                 TALLOC_FREE(__tlsp);
     976           0 :                 return NT_STATUS_NO_MEMORY;
     977             :         }
     978         622 :         talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
     979         622 :         __tlsp->internal = tlsp;
     980             : 
     981         622 :         tlsp->verify_peer = verify_peer;
     982         622 :         if (peer_name != NULL) {
     983         622 :                 tlsp->peer_name = talloc_strdup(tlsp, peer_name);
     984         622 :                 if (tlsp->peer_name == NULL) {
     985           0 :                         TALLOC_FREE(__tlsp);
     986           0 :                         return NT_STATUS_NO_MEMORY;
     987             :                 }
     988           0 :         } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
     989           0 :                 DEBUG(0,("TLS failed to missing peer_name - "
     990             :                          "with 'tls verify peer = %s'\n",
     991             :                          tls_verify_peer_string(tlsp->verify_peer)));
     992           0 :                 TALLOC_FREE(__tlsp);
     993           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
     994             :         }
     995             : 
     996         622 :         ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
     997         622 :         if (ret != GNUTLS_E_SUCCESS) {
     998           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
     999           0 :                 TALLOC_FREE(__tlsp);
    1000           0 :                 return NT_STATUS_NO_MEMORY;
    1001             :         }
    1002             : 
    1003         622 :         if (system_cas) {
    1004           0 :                 ret = gnutls_certificate_set_x509_system_trust(tlsp->x509_cred);
    1005           0 :                 if (ret < 0) {
    1006           0 :                         DBG_ERR("gnutls_certificate_set_x509_system_trust() - %s\n",
    1007             :                                 gnutls_strerror(ret));
    1008           0 :                         TALLOC_FREE(__tlsp);
    1009           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1010             :                 }
    1011           0 :                 if (ret > 0) {
    1012           0 :                         got_ca = true;
    1013             :                 }
    1014             :         }
    1015             : 
    1016         622 :         for (i = 0; ca_dirs != NULL && ca_dirs[i] != NULL; i++) {
    1017           0 :                 const char *ca_dir = ca_dirs[i];
    1018             : 
    1019           0 :                 if (!directory_exist(ca_dir)) {
    1020           0 :                         continue;
    1021             :                 }
    1022             : 
    1023           0 :                 ret = gnutls_certificate_set_x509_trust_dir(tlsp->x509_cred,
    1024             :                                                             ca_dir,
    1025             :                                                             GNUTLS_X509_FMT_PEM);
    1026           0 :                 if (ret < 0) {
    1027           0 :                         DBG_ERR("gnutls_certificate_set_x509_trust_dir(%s) - %s\n",
    1028             :                                 ca_dir, gnutls_strerror(ret));
    1029           0 :                         TALLOC_FREE(__tlsp);
    1030           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1031             :                 }
    1032           0 :                 if (ret > 0) {
    1033           0 :                         got_ca = true;
    1034             :                 }
    1035             :         }
    1036             : 
    1037         622 :         if (ca_file && *ca_file && file_exist(ca_file)) {
    1038         598 :                 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
    1039             :                                                              ca_file,
    1040             :                                                              GNUTLS_X509_FMT_PEM);
    1041         598 :                 if (ret < 0) {
    1042           0 :                         DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
    1043             :                                  ca_file, gnutls_strerror(ret)));
    1044           0 :                         TALLOC_FREE(__tlsp);
    1045           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1046             :                 }
    1047         598 :                 if (ret > 0) {
    1048         598 :                         got_ca = true;
    1049             :                 }
    1050             :         }
    1051             : 
    1052         622 :         if (!got_ca && tlsp->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
    1053           0 :                 D_ERR("TLS: 'tls verify peer = %s' requires "
    1054             :                       "'tls trust system cas', "
    1055             :                       "'tls ca directories' or "
    1056             :                       "'tls cafile'\n",
    1057             :                       tls_verify_peer_string(tlsp->verify_peer));
    1058           0 :                 TALLOC_FREE(__tlsp);
    1059           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
    1060             :         }
    1061             : 
    1062         622 :         if (crl_file && *crl_file && file_exist(crl_file)) {
    1063         481 :                 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
    1064             :                                                            crl_file, 
    1065             :                                                            GNUTLS_X509_FMT_PEM);
    1066         481 :                 if (ret < 0) {
    1067           0 :                         DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
    1068             :                                  crl_file, gnutls_strerror(ret)));
    1069           0 :                         TALLOC_FREE(__tlsp);
    1070           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1071             :                 }
    1072         141 :         } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE) {
    1073           6 :                 DEBUG(0,("TLS failed to missing crlfile %s - "
    1074             :                          "with 'tls verify peer = %s'\n",
    1075             :                          crl_file,
    1076             :                          tls_verify_peer_string(tlsp->verify_peer)));
    1077           6 :                 TALLOC_FREE(__tlsp);
    1078           6 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
    1079             :         }
    1080             : 
    1081         616 :         tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
    1082         616 :         if (tlsp->tls_priority == NULL) {
    1083           0 :                 TALLOC_FREE(__tlsp);
    1084           0 :                 return NT_STATUS_NO_MEMORY;
    1085             :         }
    1086             : 
    1087         616 :         tlsp->tls_enabled = true;
    1088             : 
    1089         616 :         *_tlsp = __tlsp;
    1090         616 :         return NT_STATUS_OK;
    1091             : }
    1092             : 
    1093         622 : NTSTATUS tstream_tls_params_client_lpcfg(TALLOC_CTX *mem_ctx,
    1094             :                                          struct loadparm_context *lp_ctx,
    1095             :                                          const char *peer_name,
    1096             :                                          struct tstream_tls_params **tlsp)
    1097             : {
    1098         622 :         TALLOC_CTX *frame = talloc_stackframe();
    1099         622 :         bool system_cas = false;
    1100         622 :         const char * const *ca_dirs = NULL;
    1101         622 :         const char *ptr = NULL;
    1102         622 :         char *ca_file = NULL;
    1103         622 :         char *crl_file = NULL;
    1104         622 :         const char *tls_priority = NULL;
    1105         622 :         enum tls_verify_peer_state verify_peer =
    1106             :                 TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE;
    1107           0 :         NTSTATUS status;
    1108             : 
    1109         622 :         system_cas = lpcfg_tls_trust_system_cas(lp_ctx);
    1110         622 :         ca_dirs = lpcfg_tls_ca_directories(lp_ctx);
    1111             : 
    1112         622 :         ptr = lpcfg__tls_cafile(lp_ctx);
    1113         622 :         if (ptr != NULL) {
    1114         622 :                 ca_file = lpcfg_tls_cafile(frame, lp_ctx);
    1115         622 :                 if (ca_file == NULL) {
    1116           0 :                         TALLOC_FREE(frame);
    1117           0 :                         return NT_STATUS_NO_MEMORY;
    1118             :                 }
    1119             :         }
    1120             : 
    1121         622 :         ptr = lpcfg__tls_crlfile(lp_ctx);
    1122         622 :         if (ptr != NULL) {
    1123         622 :                 crl_file = lpcfg_tls_crlfile(frame, lp_ctx);
    1124         622 :                 if (crl_file == NULL) {
    1125           0 :                         TALLOC_FREE(frame);
    1126           0 :                         return NT_STATUS_NO_MEMORY;
    1127             :                 }
    1128             :         }
    1129             : 
    1130         622 :         tls_priority = lpcfg_tls_priority(lp_ctx);
    1131         622 :         verify_peer = lpcfg_tls_verify_peer(lp_ctx);
    1132             : 
    1133         622 :         status = tstream_tls_params_client(mem_ctx,
    1134             :                                            system_cas,
    1135             :                                            ca_dirs,
    1136             :                                            ca_file,
    1137             :                                            crl_file,
    1138             :                                            tls_priority,
    1139             :                                            verify_peer,
    1140             :                                            peer_name,
    1141             :                                            tlsp);
    1142         622 :         TALLOC_FREE(frame);
    1143         622 :         return status;
    1144             : }
    1145             : 
    1146        1257 : static NTSTATUS tstream_tls_prepare_gnutls(struct tstream_tls_params *_tlsp,
    1147             :                                            struct tstream_tls *tlss)
    1148             : {
    1149        1257 :         struct tstream_tls_params_internal *tlsp = NULL;
    1150           0 :         int ret;
    1151           0 :         unsigned int flags;
    1152        1257 :         const char *hostname = NULL;
    1153             : 
    1154        1257 :         if (tlss->is_server) {
    1155         641 :                 flags = GNUTLS_SERVER;
    1156             :         } else {
    1157         616 :                 flags = GNUTLS_CLIENT;
    1158             :                 /*
    1159             :                  * tls_tstream can't properly handle 'New Session Ticket'
    1160             :                  * messages sent 'after' the client sends the 'Finished'
    1161             :                  * message.  GNUTLS_NO_TICKETS was introduced in GnuTLS 3.5.6.
    1162             :                  * This flag is to indicate the session Flag session should not
    1163             :                  * use resumption with session tickets.
    1164             :                  */
    1165         616 :                 flags |= GNUTLS_NO_TICKETS;
    1166             :         }
    1167             : 
    1168             :         /*
    1169             :          * Note we need to make sure x509_cred and dh_params
    1170             :          * from tstream_tls_params_internal stay alive for
    1171             :          * the whole lifetime of this session!
    1172             :          *
    1173             :          * See 'man gnutls_credentials_set' and
    1174             :          * 'man gnutls_certificate_set_dh_params'.
    1175             :          *
    1176             :          * Note: here we use talloc_reference() in a way
    1177             :          *       that does not expose it to the caller.
    1178             :          */
    1179        1257 :         tlsp = talloc_reference(tlss, _tlsp->internal);
    1180        1257 :         if (tlsp == NULL) {
    1181           0 :                 return NT_STATUS_NO_MEMORY;
    1182             :         }
    1183             : 
    1184        1257 :         tlss->verify_peer = tlsp->verify_peer;
    1185        1257 :         if (tlsp->peer_name != NULL) {
    1186         616 :                 bool ip = is_ipaddress(tlsp->peer_name);
    1187             : 
    1188         616 :                 tlss->peer_name = talloc_strdup(tlss, tlsp->peer_name);
    1189         616 :                 if (tlss->peer_name == NULL) {
    1190           0 :                         return NT_STATUS_NO_MEMORY;
    1191             :                 }
    1192             : 
    1193         616 :                 if (!ip) {
    1194         564 :                         hostname = tlss->peer_name;
    1195             :                 }
    1196             : 
    1197         616 :                 if (tlss->verify_peer < TLS_VERIFY_PEER_CA_AND_NAME) {
    1198         604 :                         hostname = NULL;
    1199             :                 }
    1200             :         }
    1201             : 
    1202        1257 :         if (tlss->current_ev != NULL) {
    1203        1233 :                 tlss->retry_im = tevent_create_immediate(tlss);
    1204        1233 :                 if (tlss->retry_im == NULL) {
    1205           0 :                         return NT_STATUS_NO_MEMORY;
    1206             :                 }
    1207             :         }
    1208             : 
    1209        1257 :         ret = gnutls_init(&tlss->tls_session, flags);
    1210        1257 :         if (ret != GNUTLS_E_SUCCESS) {
    1211           0 :                 return gnutls_error_to_ntstatus(ret,
    1212             :                         NT_STATUS_CRYPTO_SYSTEM_INVALID);
    1213             :         }
    1214             : 
    1215        1257 :         ret = gnutls_set_default_priority(tlss->tls_session);
    1216        1257 :         if (ret != GNUTLS_E_SUCCESS) {
    1217           0 :                 return gnutls_error_to_ntstatus(ret,
    1218             :                         NT_STATUS_CRYPTO_SYSTEM_INVALID);
    1219             :         }
    1220             : 
    1221        1257 :         if (strlen(tlsp->tls_priority) > 0) {
    1222        1257 :                 const char *error_pos = NULL;
    1223             : 
    1224        1257 :                 ret = gnutls_priority_set_direct(tlss->tls_session,
    1225             :                                                  tlsp->tls_priority,
    1226             :                                                  &error_pos);
    1227        1257 :                 if (ret != GNUTLS_E_SUCCESS) {
    1228           1 :                         return gnutls_error_to_ntstatus(ret,
    1229             :                                 NT_STATUS_CRYPTO_SYSTEM_INVALID);
    1230             :                 }
    1231             :         }
    1232             : 
    1233        1256 :         ret = gnutls_credentials_set(tlss->tls_session,
    1234             :                                      GNUTLS_CRD_CERTIFICATE,
    1235        1256 :                                      tlsp->x509_cred);
    1236        1256 :         if (ret != GNUTLS_E_SUCCESS) {
    1237           0 :                 return gnutls_error_to_ntstatus(ret,
    1238             :                                 NT_STATUS_CRYPTO_SYSTEM_INVALID);
    1239             :         }
    1240             : 
    1241        1256 :         if (hostname != NULL) {
    1242           8 :                 ret = gnutls_server_name_set(tlss->tls_session,
    1243             :                                              GNUTLS_NAME_DNS,
    1244             :                                              hostname,
    1245             :                                              strlen(hostname));
    1246           8 :                 if (ret != GNUTLS_E_SUCCESS) {
    1247           0 :                         return gnutls_error_to_ntstatus(ret,
    1248             :                                         NT_STATUS_CRYPTO_SYSTEM_INVALID);
    1249             :                 }
    1250             :         }
    1251             : 
    1252        1256 :         if (tlss->is_server) {
    1253         641 :                 gnutls_certificate_server_set_request(tlss->tls_session,
    1254             :                                                       GNUTLS_CERT_REQUEST);
    1255         641 :                 gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS);
    1256             :         }
    1257             : 
    1258        1256 :         return NT_STATUS_OK;
    1259             : }
    1260             : 
    1261        1254 : static NTSTATUS tstream_tls_verify_peer(struct tstream_tls *tlss)
    1262             : {
    1263        1254 :         unsigned int status = UINT32_MAX;
    1264        1254 :         bool ip = true;
    1265        1254 :         const char *hostname = NULL;
    1266           0 :         int ret;
    1267             : 
    1268        1254 :         if (tlss->verify_peer == TLS_VERIFY_PEER_NO_CHECK) {
    1269        1224 :                 return NT_STATUS_OK;
    1270             :         }
    1271             : 
    1272          30 :         if (tlss->peer_name != NULL) {
    1273          30 :                 ip = is_ipaddress(tlss->peer_name);
    1274             :         }
    1275             : 
    1276          30 :         if (!ip) {
    1277          20 :                 hostname = tlss->peer_name;
    1278             :         }
    1279             : 
    1280          30 :         if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
    1281           9 :                 hostname = NULL;
    1282             :         }
    1283             : 
    1284          30 :         if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
    1285          12 :                 if (hostname == NULL) {
    1286           4 :                         DEBUG(1,("TLS %s - no hostname available for "
    1287             :                                  "verify_peer[%s] and peer_name[%s]\n",
    1288             :                                  __location__,
    1289             :                                  tls_verify_peer_string(tlss->verify_peer),
    1290             :                                  tlss->peer_name));
    1291           4 :                         return NT_STATUS_IMAGE_CERT_REVOKED;
    1292             :                 }
    1293             :         }
    1294             : 
    1295          26 :         ret = gnutls_certificate_verify_peers3(tlss->tls_session,
    1296             :                                                hostname,
    1297             :                                                &status);
    1298          26 :         if (ret != GNUTLS_E_SUCCESS) {
    1299           0 :                 return gnutls_error_to_ntstatus(ret,
    1300             :                         NT_STATUS_CRYPTO_SYSTEM_INVALID);
    1301             :         }
    1302             : 
    1303          26 :         if (status != 0) {
    1304           7 :                 DEBUG(1,("TLS %s - check failed for "
    1305             :                          "verify_peer[%s] and peer_name[%s] "
    1306             :                          "status 0x%x (%s%s%s%s%s%s%s%s)\n",
    1307             :                          __location__,
    1308             :                          tls_verify_peer_string(tlss->verify_peer),
    1309             :                          tlss->peer_name,
    1310             :                          status,
    1311             :                          status & GNUTLS_CERT_INVALID ? "invalid " : "",
    1312             :                          status & GNUTLS_CERT_REVOKED ? "revoked " : "",
    1313             :                          status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
    1314             :                                 "signer_not_found " : "",
    1315             :                          status & GNUTLS_CERT_SIGNER_NOT_CA ?
    1316             :                                 "signer_not_ca " : "",
    1317             :                          status & GNUTLS_CERT_INSECURE_ALGORITHM ?
    1318             :                                 "insecure_algorithm " : "",
    1319             :                          status & GNUTLS_CERT_NOT_ACTIVATED ?
    1320             :                                 "not_activated " : "",
    1321             :                          status & GNUTLS_CERT_EXPIRED ?
    1322             :                                 "expired " : "",
    1323             :                          status & GNUTLS_CERT_UNEXPECTED_OWNER ?
    1324             :                                 "unexpected_owner " : ""));
    1325           7 :                 return NT_STATUS_IMAGE_CERT_REVOKED;
    1326             :         }
    1327             : 
    1328          19 :         return NT_STATUS_OK;
    1329             : }
    1330             : 
    1331             : struct tstream_tls_connect_state {
    1332             :         struct tstream_context *tls_stream;
    1333             : };
    1334             : 
    1335         592 : struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
    1336             :                                              struct tevent_context *ev,
    1337             :                                              struct tstream_context *plain_stream,
    1338             :                                              struct tstream_tls_params *_tls_params,
    1339             :                                              const char *location)
    1340             : {
    1341           0 :         struct tevent_req *req;
    1342           0 :         struct tstream_tls_connect_state *state;
    1343           0 :         struct tstream_tls *tlss;
    1344           0 :         NTSTATUS status;
    1345             : 
    1346         592 :         req = tevent_req_create(mem_ctx, &state,
    1347             :                                 struct tstream_tls_connect_state);
    1348         592 :         if (req == NULL) {
    1349           0 :                 return NULL;
    1350             :         }
    1351             : 
    1352         592 :         state->tls_stream = tstream_context_create(state,
    1353             :                                                    &tstream_tls_ops,
    1354             :                                                    &tlss,
    1355             :                                                    struct tstream_tls,
    1356             :                                                    location);
    1357         592 :         if (tevent_req_nomem(state->tls_stream, req)) {
    1358           0 :                 return tevent_req_post(req, ev);
    1359             :         }
    1360         592 :         ZERO_STRUCTP(tlss);
    1361         592 :         talloc_set_destructor(tlss, tstream_tls_destructor);
    1362         592 :         tlss->plain_stream = plain_stream;
    1363         592 :         tlss->is_server = false;
    1364         592 :         tlss->current_ev = ev;
    1365             : 
    1366         592 :         status = tstream_tls_prepare_gnutls(_tls_params, tlss);
    1367         592 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
    1368           0 :                 tevent_req_oom(req);
    1369           0 :                 return tevent_req_post(req, ev);
    1370             :         }
    1371         592 :         if (!NT_STATUS_IS_OK(status)) {
    1372           1 :                 tevent_req_error(req, EINVAL);
    1373           1 :                 return tevent_req_post(req, ev);
    1374             :         }
    1375             : 
    1376         591 :         gnutls_transport_set_ptr(tlss->tls_session,
    1377         591 :                                  (gnutls_transport_ptr_t)state->tls_stream);
    1378         591 :         gnutls_transport_set_pull_function(tlss->tls_session,
    1379             :                                            (gnutls_pull_func)tstream_tls_pull_function);
    1380         591 :         gnutls_transport_set_push_function(tlss->tls_session,
    1381             :                                            (gnutls_push_func)tstream_tls_push_function);
    1382             : 
    1383         591 :         tlss->handshake.req = req;
    1384         591 :         tstream_tls_retry_handshake(state->tls_stream);
    1385         591 :         if (!tevent_req_is_in_progress(req)) {
    1386           0 :                 return tevent_req_post(req, ev);
    1387             :         }
    1388             : 
    1389         591 :         return req;
    1390             : }
    1391             : 
    1392         592 : int tstream_tls_connect_recv(struct tevent_req *req,
    1393             :                              int *perrno,
    1394             :                              TALLOC_CTX *mem_ctx,
    1395             :                              struct tstream_context **tls_stream)
    1396             : {
    1397           0 :         struct tstream_tls_connect_state *state =
    1398         592 :                 tevent_req_data(req,
    1399             :                 struct tstream_tls_connect_state);
    1400             : 
    1401         592 :         if (tevent_req_is_unix_error(req, perrno)) {
    1402          13 :                 tevent_req_received(req);
    1403          13 :                 return -1;
    1404             :         }
    1405             : 
    1406         579 :         *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
    1407         579 :         tevent_req_received(req);
    1408         579 :         return 0;
    1409             : }
    1410             : 
    1411             : /*
    1412             :   initialise global tls state
    1413             : */
    1414          62 : NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
    1415             :                                    const char *dns_host_name,
    1416             :                                    bool enabled,
    1417             :                                    const char *key_file,
    1418             :                                    const char *cert_file,
    1419             :                                    const char *ca_file,
    1420             :                                    const char *crl_file,
    1421             :                                    const char *dhp_file,
    1422             :                                    const char *tls_priority,
    1423             :                                    struct tstream_tls_params **_tlsp)
    1424             : {
    1425          62 :         struct tstream_tls_params *__tlsp = NULL;
    1426          62 :         struct tstream_tls_params_internal *tlsp = NULL;
    1427           2 :         int ret;
    1428           2 :         struct stat st;
    1429             : 
    1430          62 :         if (!enabled || key_file == NULL || *key_file == 0) {
    1431           0 :                 __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
    1432           0 :                 if (__tlsp == NULL) {
    1433           0 :                         return NT_STATUS_NO_MEMORY;
    1434             :                 }
    1435             : 
    1436           0 :                 tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
    1437           0 :                 if (tlsp == NULL) {
    1438           0 :                         TALLOC_FREE(__tlsp);
    1439           0 :                         return NT_STATUS_NO_MEMORY;
    1440             :                 }
    1441             : 
    1442           0 :                 talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
    1443           0 :                 __tlsp->internal = tlsp;
    1444           0 :                 tlsp->tls_enabled = false;
    1445             : 
    1446           0 :                 *_tlsp = __tlsp;
    1447           0 :                 return NT_STATUS_OK;
    1448             :         }
    1449             : 
    1450          62 :         __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
    1451          62 :         if (__tlsp == NULL) {
    1452           0 :                 return NT_STATUS_NO_MEMORY;
    1453             :         }
    1454             : 
    1455          62 :         tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
    1456          62 :         if (tlsp == NULL) {
    1457           0 :                 TALLOC_FREE(__tlsp);
    1458           0 :                 return NT_STATUS_NO_MEMORY;
    1459             :         }
    1460             : 
    1461          62 :         talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
    1462          62 :         __tlsp->internal = tlsp;
    1463             : 
    1464          62 :         if (!file_exist(ca_file)) {
    1465          33 :                 tls_cert_generate(tlsp, dns_host_name,
    1466             :                                   key_file, cert_file, ca_file);
    1467             :         }
    1468             : 
    1469          64 :         if (file_exist(key_file) &&
    1470          62 :             !file_check_permissions(key_file, geteuid(), 0600, &st))
    1471             :         {
    1472           0 :                 DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
    1473             :                           "owner uid %u should be %u, mode 0%o should be 0%o\n"
    1474             :                           "This is known as CVE-2013-4476.\n"
    1475             :                           "Removing all tls .pem files will cause an "
    1476             :                           "auto-regeneration with the correct permissions.\n",
    1477             :                           key_file,
    1478             :                           (unsigned int)st.st_uid, geteuid(),
    1479             :                           (unsigned int)(st.st_mode & 0777), 0600));
    1480           0 :                 TALLOC_FREE(__tlsp);
    1481           0 :                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1482             :         }
    1483             : 
    1484          62 :         ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
    1485          62 :         if (ret != GNUTLS_E_SUCCESS) {
    1486           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1487           0 :                 TALLOC_FREE(__tlsp);
    1488           0 :                 return NT_STATUS_NO_MEMORY;
    1489             :         }
    1490             : 
    1491          62 :         if (ca_file && *ca_file) {
    1492          62 :                 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
    1493             :                                                              ca_file,
    1494             :                                                              GNUTLS_X509_FMT_PEM);
    1495          62 :                 if (ret < 0) {
    1496           0 :                         DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
    1497             :                                  ca_file, gnutls_strerror(ret)));
    1498           0 :                         TALLOC_FREE(__tlsp);
    1499           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1500             :                 }
    1501             :         }
    1502             : 
    1503          62 :         if (crl_file && *crl_file) {
    1504          27 :                 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
    1505             :                                                            crl_file, 
    1506             :                                                            GNUTLS_X509_FMT_PEM);
    1507          27 :                 if (ret < 0) {
    1508           0 :                         DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
    1509             :                                  crl_file, gnutls_strerror(ret)));
    1510           0 :                         TALLOC_FREE(__tlsp);
    1511           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1512             :                 }
    1513             :         }
    1514             : 
    1515          62 :         ret = gnutls_certificate_set_x509_key_file(tlsp->x509_cred,
    1516             :                                                    cert_file, key_file,
    1517             :                                                    GNUTLS_X509_FMT_PEM);
    1518          62 :         if (ret != GNUTLS_E_SUCCESS) {
    1519           0 :                 DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
    1520             :                          cert_file, key_file, gnutls_strerror(ret)));
    1521           0 :                 TALLOC_FREE(__tlsp);
    1522           0 :                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1523             :         }
    1524             : 
    1525          62 :         ret = gnutls_dh_params_init(&tlsp->dh_params);
    1526          62 :         if (ret != GNUTLS_E_SUCCESS) {
    1527           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1528           0 :                 TALLOC_FREE(__tlsp);
    1529           0 :                 return NT_STATUS_NO_MEMORY;
    1530             :         }
    1531             : 
    1532         124 :         if (dhp_file && *dhp_file) {
    1533           2 :                 gnutls_datum_t dhparms;
    1534           2 :                 size_t size;
    1535             : 
    1536          62 :                 dhparms.data = (uint8_t *)file_load(dhp_file, &size, 0, tlsp);
    1537             : 
    1538          62 :                 if (!dhparms.data) {
    1539           0 :                         DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
    1540             :                                  dhp_file, errno, strerror(errno)));
    1541           0 :                         TALLOC_FREE(__tlsp);
    1542           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1543             :                 }
    1544          62 :                 dhparms.size = size;
    1545             : 
    1546          62 :                 ret = gnutls_dh_params_import_pkcs3(tlsp->dh_params,
    1547             :                                                     &dhparms,
    1548             :                                                     GNUTLS_X509_FMT_PEM);
    1549          62 :                 if (ret != GNUTLS_E_SUCCESS) {
    1550           0 :                         DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
    1551             :                                  dhp_file, gnutls_strerror(ret)));
    1552           0 :                         TALLOC_FREE(__tlsp);
    1553           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1554             :                 }
    1555             :         } else {
    1556           0 :                 ret = gnutls_dh_params_generate2(tlsp->dh_params, DH_BITS);
    1557           0 :                 if (ret != GNUTLS_E_SUCCESS) {
    1558           0 :                         DEBUG(0,("TLS failed to generate dh_params - %s\n",
    1559             :                                  gnutls_strerror(ret)));
    1560           0 :                         TALLOC_FREE(__tlsp);
    1561           0 :                         return NT_STATUS_INTERNAL_ERROR;
    1562             :                 }
    1563             :         }
    1564             : 
    1565          62 :         gnutls_certificate_set_dh_params(tlsp->x509_cred, tlsp->dh_params);
    1566             : 
    1567          62 :         tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
    1568          62 :         if (tlsp->tls_priority == NULL) {
    1569           0 :                 TALLOC_FREE(__tlsp);
    1570           0 :                 return NT_STATUS_NO_MEMORY;
    1571             :         }
    1572             : 
    1573          62 :         tlsp->tls_enabled = true;
    1574             : 
    1575          62 :         *_tlsp = __tlsp;
    1576          62 :         return NT_STATUS_OK;
    1577             : }
    1578             : 
    1579             : struct tstream_tls_accept_state {
    1580             :         struct tstream_context *tls_stream;
    1581             : };
    1582             : 
    1583         641 : struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
    1584             :                                             struct tevent_context *ev,
    1585             :                                             struct tstream_context *plain_stream,
    1586             :                                             struct tstream_tls_params *_tlsp,
    1587             :                                             const char *location)
    1588             : {
    1589           0 :         struct tevent_req *req;
    1590           0 :         struct tstream_tls_accept_state *state;
    1591           0 :         struct tstream_tls *tlss;
    1592           0 :         NTSTATUS status;
    1593             : 
    1594         641 :         req = tevent_req_create(mem_ctx, &state,
    1595             :                                 struct tstream_tls_accept_state);
    1596         641 :         if (req == NULL) {
    1597           0 :                 return NULL;
    1598             :         }
    1599             : 
    1600         641 :         state->tls_stream = tstream_context_create(state,
    1601             :                                                    &tstream_tls_ops,
    1602             :                                                    &tlss,
    1603             :                                                    struct tstream_tls,
    1604             :                                                    location);
    1605         641 :         if (tevent_req_nomem(state->tls_stream, req)) {
    1606           0 :                 return tevent_req_post(req, ev);
    1607             :         }
    1608         641 :         ZERO_STRUCTP(tlss);
    1609         641 :         talloc_set_destructor(tlss, tstream_tls_destructor);
    1610         641 :         tlss->plain_stream = plain_stream;
    1611         641 :         tlss->is_server = true;
    1612         641 :         tlss->current_ev = ev;
    1613             : 
    1614         641 :         status = tstream_tls_prepare_gnutls(_tlsp, tlss);
    1615         641 :         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY)) {
    1616           0 :                 tevent_req_oom(req);
    1617           0 :                 return tevent_req_post(req, ev);
    1618             :         }
    1619         641 :         if (!NT_STATUS_IS_OK(status)) {
    1620           0 :                 tevent_req_error(req, EINVAL);
    1621           0 :                 return tevent_req_post(req, ev);
    1622             :         }
    1623             : 
    1624         641 :         gnutls_transport_set_ptr(tlss->tls_session,
    1625         641 :                                  (gnutls_transport_ptr_t)state->tls_stream);
    1626         641 :         gnutls_transport_set_pull_function(tlss->tls_session,
    1627             :                                            (gnutls_pull_func)tstream_tls_pull_function);
    1628         641 :         gnutls_transport_set_push_function(tlss->tls_session,
    1629             :                                            (gnutls_push_func)tstream_tls_push_function);
    1630             : 
    1631         641 :         tlss->handshake.req = req;
    1632         641 :         tstream_tls_retry_handshake(state->tls_stream);
    1633         641 :         if (!tevent_req_is_in_progress(req)) {
    1634           0 :                 return tevent_req_post(req, ev);
    1635             :         }
    1636             : 
    1637         641 :         return req;
    1638             : }
    1639             : 
    1640       20864 : static void tstream_tls_retry_handshake(struct tstream_context *stream)
    1641             : {
    1642           0 :         struct tstream_tls *tlss =
    1643       20864 :                 tstream_context_data(stream,
    1644             :                 struct tstream_tls);
    1645       20864 :         struct tevent_req *req = tlss->handshake.req;
    1646           0 :         NTSTATUS status;
    1647           0 :         int ret;
    1648             : 
    1649       20864 :         if (tlss->error != 0) {
    1650           2 :                 tevent_req_error(req, tlss->error);
    1651       20224 :                 return;
    1652             :         }
    1653             : 
    1654       20862 :         ret = gnutls_handshake(tlss->tls_session);
    1655       20862 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
    1656       19632 :                 return;
    1657             :         }
    1658             : 
    1659        1230 :         tlss->handshake.req = NULL;
    1660             : 
    1661        1230 :         if (gnutls_error_is_fatal(ret) != 0) {
    1662           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1663           0 :                 tlss->error = EIO;
    1664           0 :                 tevent_req_error(req, tlss->error);
    1665           0 :                 return;
    1666             :         }
    1667             : 
    1668        1230 :         if (ret != GNUTLS_E_SUCCESS) {
    1669           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1670           0 :                 tlss->error = EIO;
    1671           0 :                 tevent_req_error(req, tlss->error);
    1672           0 :                 return;
    1673             :         }
    1674             : 
    1675        1230 :         status = tstream_tls_verify_peer(tlss);
    1676        1230 :         if (NT_STATUS_EQUAL(status, NT_STATUS_IMAGE_CERT_REVOKED)) {
    1677          11 :                 tlss->error = EINVAL;
    1678          11 :                 tevent_req_error(req, tlss->error);
    1679          11 :                 return;
    1680             :         }
    1681        1219 :         if (!NT_STATUS_IS_OK(status)) {
    1682           0 :                 tlss->error = EIO;
    1683           0 :                 tevent_req_error(req, tlss->error);
    1684           0 :                 return;
    1685             :         }
    1686             : 
    1687        1219 :         status = tstream_tls_setup_channel_bindings(tlss);
    1688        1219 :         if (!NT_STATUS_IS_OK(status)) {
    1689           0 :                 tlss->error = EIO;
    1690           0 :                 tevent_req_error(req, tlss->error);
    1691           0 :                 return;
    1692             :         }
    1693             : 
    1694        1219 :         if (tlss->push.subreq != NULL || tlss->pull.subreq != NULL) {
    1695         579 :                 tlss->waiting_flush.mgmt_req = req;
    1696         579 :                 return;
    1697             :         }
    1698             : 
    1699         640 :         tevent_req_done(req);
    1700             : }
    1701             : 
    1702         641 : int tstream_tls_accept_recv(struct tevent_req *req,
    1703             :                             int *perrno,
    1704             :                             TALLOC_CTX *mem_ctx,
    1705             :                             struct tstream_context **tls_stream)
    1706             : {
    1707           0 :         struct tstream_tls_accept_state *state =
    1708         641 :                 tevent_req_data(req,
    1709             :                 struct tstream_tls_accept_state);
    1710             : 
    1711         641 :         if (tevent_req_is_unix_error(req, perrno)) {
    1712           1 :                 tevent_req_received(req);
    1713           1 :                 return -1;
    1714             :         }
    1715             : 
    1716         640 :         *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
    1717         640 :         tevent_req_received(req);
    1718         640 :         return 0;
    1719             : }
    1720             : 
    1721             : struct tstream_tls_sync {
    1722             :         struct tstream_tls *tlss;
    1723             :         void *io_private;
    1724             :         ssize_t (*io_send_fn)(void *io_private,
    1725             :                               const uint8_t *buf,
    1726             :                               size_t len);
    1727             :         ssize_t (*io_recv_fn)(void *io_private,
    1728             :                               uint8_t *buf,
    1729             :                               size_t len);
    1730             : };
    1731             : 
    1732          48 : const DATA_BLOB *tstream_tls_sync_channel_bindings(struct tstream_tls_sync *tlsss)
    1733             : {
    1734          48 :         return &tlsss->tlss->channel_bindings;
    1735             : }
    1736             : 
    1737         224 : static ssize_t tstream_tls_sync_push_function(gnutls_transport_ptr_t ptr,
    1738             :                                               const void *buf, size_t size)
    1739             : {
    1740           0 :         struct tstream_tls_sync *tlsss =
    1741         224 :                 talloc_get_type_abort(ptr,
    1742             :                 struct tstream_tls_sync);
    1743             : 
    1744         224 :         return tlsss->io_send_fn(tlsss->io_private, buf, size);
    1745             : }
    1746             : 
    1747         504 : static ssize_t tstream_tls_sync_pull_function(gnutls_transport_ptr_t ptr,
    1748             :                                               void *buf, size_t size)
    1749             : {
    1750           0 :         struct tstream_tls_sync *tlsss =
    1751         504 :                 talloc_get_type_abort(ptr,
    1752             :                 struct tstream_tls_sync);
    1753             : 
    1754         504 :         return tlsss->io_recv_fn(tlsss->io_private, buf, size);
    1755             : }
    1756             : 
    1757         240 : ssize_t tstream_tls_sync_read(struct tstream_tls_sync *tlsss,
    1758             :                               void *buf, size_t len)
    1759             : {
    1760           0 :         int ret;
    1761             : 
    1762         240 :         ret = gnutls_record_recv(tlsss->tlss->tls_session, buf, len);
    1763         240 :         if (ret == GNUTLS_E_INTERRUPTED) {
    1764           0 :                 errno = EINTR;
    1765           0 :                 return -1;
    1766             :         }
    1767         240 :         if (ret == GNUTLS_E_AGAIN) {
    1768           0 :                 errno = EAGAIN;
    1769           0 :                 return -1;
    1770             :         }
    1771             : 
    1772         240 :         if (ret < 0) {
    1773           0 :                 DBG_WARNING("TLS gnutls_record_recv(%zu) - %s\n",
    1774             :                             (size_t)len, gnutls_strerror(ret));
    1775           0 :                 errno = EIO;
    1776           0 :                 return -1;
    1777             :         }
    1778             : 
    1779         240 :         return ret;
    1780             : }
    1781             : 
    1782          96 : ssize_t tstream_tls_sync_write(struct tstream_tls_sync *tlsss,
    1783             :                                const void *buf, size_t len)
    1784             : {
    1785           0 :         int ret;
    1786             : 
    1787          96 :         ret = gnutls_record_send(tlsss->tlss->tls_session, buf, len);
    1788          96 :         if (ret == GNUTLS_E_INTERRUPTED) {
    1789           0 :                 errno = EINTR;
    1790           0 :                 return -1;
    1791             :         }
    1792          96 :         if (ret == GNUTLS_E_AGAIN) {
    1793           0 :                 errno = EAGAIN;
    1794           0 :                 return -1;
    1795             :         }
    1796             : 
    1797          96 :         if (ret < 0) {
    1798           0 :                 DBG_WARNING("TLS gnutls_record_send(%zu) - %s\n",
    1799             :                             (size_t)len, gnutls_strerror(ret));
    1800           0 :                 errno = EIO;
    1801           0 :                 return -1;
    1802             :         }
    1803             : 
    1804          96 :         return ret;
    1805             : }
    1806             : 
    1807         192 : size_t tstream_tls_sync_pending(struct tstream_tls_sync *tlsss)
    1808             : {
    1809         192 :         return gnutls_record_check_pending(tlsss->tlss->tls_session);
    1810             : }
    1811             : 
    1812          24 : NTSTATUS tstream_tls_sync_setup(struct tstream_tls_params *_tls_params,
    1813             :                                 void *io_private,
    1814             :                                 ssize_t (*io_send_fn)(void *io_private,
    1815             :                                                       const uint8_t *buf,
    1816             :                                                       size_t len),
    1817             :                                 ssize_t (*io_recv_fn)(void *io_private,
    1818             :                                                       uint8_t *buf,
    1819             :                                                       size_t len),
    1820             :                                 TALLOC_CTX *mem_ctx,
    1821             :                                 struct tstream_tls_sync **_tlsss)
    1822             : {
    1823          24 :         struct tstream_tls_sync *tlsss = NULL;
    1824          24 :         struct tstream_tls *tlss = NULL;
    1825           0 :         NTSTATUS status;
    1826           0 :         int ret;
    1827             : 
    1828          24 :         tlsss = talloc_zero(mem_ctx, struct tstream_tls_sync);
    1829          24 :         if (tlsss == NULL) {
    1830           0 :                 return NT_STATUS_NO_MEMORY;
    1831             :         }
    1832             : 
    1833          24 :         tlsss->io_private = io_private;
    1834          24 :         tlsss->io_send_fn = io_send_fn;
    1835          24 :         tlsss->io_recv_fn = io_recv_fn;
    1836             : 
    1837          24 :         tlss = talloc_zero(tlsss, struct tstream_tls);
    1838          24 :         if (tlss == NULL) {
    1839           0 :                 TALLOC_FREE(tlsss);
    1840           0 :                 return NT_STATUS_NO_MEMORY;
    1841             :         }
    1842          24 :         talloc_set_destructor(tlss, tstream_tls_destructor);
    1843          24 :         tlss->is_server = false;
    1844             : 
    1845          24 :         tlsss->tlss = tlss;
    1846             : 
    1847          24 :         status = tstream_tls_prepare_gnutls(_tls_params, tlss);
    1848          24 :         if (!NT_STATUS_IS_OK(status)) {
    1849           0 :                 TALLOC_FREE(tlsss);
    1850           0 :                 return status;
    1851             :         }
    1852             : 
    1853          24 :         gnutls_transport_set_ptr(tlss->tls_session,
    1854             :                                  (gnutls_transport_ptr_t)tlsss);
    1855          24 :         gnutls_transport_set_pull_function(tlss->tls_session,
    1856             :                                            (gnutls_pull_func)tstream_tls_sync_pull_function);
    1857          24 :         gnutls_transport_set_push_function(tlss->tls_session,
    1858             :                                            (gnutls_push_func)tstream_tls_sync_push_function);
    1859             : 
    1860           0 :         do {
    1861             :                 /*
    1862             :                  * The caller should have the socket blocking
    1863             :                  * and do the timeout handling in the
    1864             :                  * io_send/recv_fn
    1865             :                  */
    1866          24 :                 ret = gnutls_handshake(tlss->tls_session);
    1867          24 :         } while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
    1868             : 
    1869          24 :         if (gnutls_error_is_fatal(ret) != 0) {
    1870           0 :                 TALLOC_FREE(tlsss);
    1871           0 :                 return gnutls_error_to_ntstatus(ret,
    1872             :                                 NT_STATUS_CRYPTO_SYSTEM_INVALID);
    1873             :         }
    1874             : 
    1875          24 :         if (ret != GNUTLS_E_SUCCESS) {
    1876           0 :                 TALLOC_FREE(tlsss);
    1877           0 :                 return gnutls_error_to_ntstatus(ret,
    1878             :                                 NT_STATUS_CRYPTO_SYSTEM_INVALID);
    1879             :         }
    1880             : 
    1881          24 :         status = tstream_tls_verify_peer(tlss);
    1882          24 :         if (!NT_STATUS_IS_OK(status)) {
    1883           0 :                 TALLOC_FREE(tlsss);
    1884           0 :                 return status;
    1885             :         }
    1886             : 
    1887          24 :         status = tstream_tls_setup_channel_bindings(tlss);
    1888          24 :         if (!NT_STATUS_IS_OK(status)) {
    1889           0 :                 TALLOC_FREE(tlsss);
    1890           0 :                 return status;
    1891             :         }
    1892             : 
    1893          24 :         *_tlsss = tlsss;
    1894          24 :         return NT_STATUS_OK;
    1895             : }

Generated by: LCOV version 1.14