LCOV - code coverage report
Current view: top level - source4/lib/tls - tls_tstream.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 482 741 65.0 %
Date: 2024-02-28 12:06:22 Functions: 28 30 93.3 %

          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 "../util/tevent_unix.h"
      25             : #include "../lib/tsocket/tsocket.h"
      26             : #include "../lib/tsocket/tsocket_internal.h"
      27             : #include "../lib/util/util_net.h"
      28             : #include "lib/tls/tls.h"
      29             : 
      30             : #include <gnutls/gnutls.h>
      31             : #include <gnutls/x509.h>
      32             : 
      33             : #define DH_BITS 2048
      34             : 
      35          17 : const char *tls_verify_peer_string(enum tls_verify_peer_state verify_peer)
      36             : {
      37          17 :         switch (verify_peer) {
      38           0 :         case TLS_VERIFY_PEER_NO_CHECK:
      39           0 :                 return TLS_VERIFY_PEER_NO_CHECK_STRING;
      40             : 
      41           0 :         case TLS_VERIFY_PEER_CA_ONLY:
      42           0 :                 return TLS_VERIFY_PEER_CA_ONLY_STRING;
      43             : 
      44           3 :         case TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE:
      45           3 :                 return TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE_STRING;
      46             : 
      47           6 :         case TLS_VERIFY_PEER_CA_AND_NAME:
      48           6 :                 return TLS_VERIFY_PEER_CA_AND_NAME_STRING;
      49             : 
      50           8 :         case TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE:
      51           8 :                 return TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE_STRING;
      52             :         }
      53             : 
      54           0 :         return "unknown tls_verify_peer_state";
      55             : }
      56             : 
      57             : static const struct tstream_context_ops tstream_tls_ops;
      58             : 
      59             : struct tstream_tls {
      60             :         struct tstream_context *plain_stream;
      61             :         int error;
      62             : 
      63             :         gnutls_session_t tls_session;
      64             : 
      65             :         enum tls_verify_peer_state verify_peer;
      66             :         const char *peer_name;
      67             : 
      68             :         struct tevent_context *current_ev;
      69             : 
      70             :         struct tevent_immediate *retry_im;
      71             : 
      72             :         struct {
      73             :                 uint8_t *buf;
      74             :                 off_t ofs;
      75             :                 struct iovec iov;
      76             :                 struct tevent_req *subreq;
      77             :                 struct tevent_immediate *im;
      78             :         } push;
      79             : 
      80             :         struct {
      81             :                 uint8_t *buf;
      82             :                 struct iovec iov;
      83             :                 struct tevent_req *subreq;
      84             :         } pull;
      85             : 
      86             :         struct {
      87             :                 struct tevent_req *req;
      88             :         } handshake;
      89             : 
      90             :         struct {
      91             :                 off_t ofs;
      92             :                 size_t left;
      93             :                 uint8_t buffer[1024];
      94             :                 struct tevent_req *req;
      95             :         } write;
      96             : 
      97             :         struct {
      98             :                 off_t ofs;
      99             :                 size_t left;
     100             :                 uint8_t buffer[1024];
     101             :                 struct tevent_req *req;
     102             :         } read;
     103             : 
     104             :         struct {
     105             :                 struct tevent_req *req;
     106             :         } disconnect;
     107             : };
     108             : 
     109             : static void tstream_tls_retry_handshake(struct tstream_context *stream);
     110             : static void tstream_tls_retry_read(struct tstream_context *stream);
     111             : static void tstream_tls_retry_write(struct tstream_context *stream);
     112             : static void tstream_tls_retry_disconnect(struct tstream_context *stream);
     113             : static void tstream_tls_retry_trigger(struct tevent_context *ctx,
     114             :                                       struct tevent_immediate *im,
     115             :                                       void *private_data);
     116             : 
     117     2333205 : static void tstream_tls_retry(struct tstream_context *stream, bool deferred)
     118             : {
     119             : 
     120           0 :         struct tstream_tls *tlss =
     121     2333205 :                 tstream_context_data(stream,
     122             :                 struct tstream_tls);
     123             : 
     124     2333205 :         if (tlss->disconnect.req) {
     125           0 :                 tstream_tls_retry_disconnect(stream);
     126           0 :                 return;
     127             :         }
     128             : 
     129     2333205 :         if (tlss->handshake.req) {
     130       11926 :                 tstream_tls_retry_handshake(stream);
     131       11926 :                 return;
     132             :         }
     133             : 
     134     2321279 :         if (tlss->write.req && tlss->read.req && !deferred) {
     135           0 :                 tevent_schedule_immediate(tlss->retry_im, tlss->current_ev,
     136             :                                           tstream_tls_retry_trigger,
     137           0 :                                           stream);
     138             :         }
     139             : 
     140     2321279 :         if (tlss->write.req) {
     141       17976 :                 tstream_tls_retry_write(stream);
     142       17976 :                 return;
     143             :         }
     144             : 
     145     2303303 :         if (tlss->read.req) {
     146     2303303 :                 tstream_tls_retry_read(stream);
     147     2303303 :                 return;
     148             :         }
     149             : }
     150             : 
     151           0 : static void tstream_tls_retry_trigger(struct tevent_context *ctx,
     152             :                                       struct tevent_immediate *im,
     153             :                                       void *private_data)
     154             : {
     155           0 :         struct tstream_context *stream =
     156           0 :                 talloc_get_type_abort(private_data,
     157             :                 struct tstream_context);
     158             : 
     159           0 :         tstream_tls_retry(stream, true);
     160           0 : }
     161             : 
     162             : static void tstream_tls_push_trigger_write(struct tevent_context *ev,
     163             :                                            struct tevent_immediate *im,
     164             :                                            void *private_data);
     165             : 
     166     1184730 : static ssize_t tstream_tls_push_function(gnutls_transport_ptr_t ptr,
     167             :                                          const void *buf, size_t size)
     168             : {
     169           0 :         struct tstream_context *stream =
     170     1184730 :                 talloc_get_type_abort(ptr,
     171             :                 struct tstream_context);
     172           0 :         struct tstream_tls *tlss =
     173     1184730 :                 tstream_context_data(stream,
     174             :                 struct tstream_tls);
     175           0 :         uint8_t *nbuf;
     176           0 :         size_t len;
     177             : 
     178     1184730 :         if (tlss->error != 0) {
     179           0 :                 errno = tlss->error;
     180           0 :                 return -1;
     181             :         }
     182             : 
     183     1184730 :         if (tlss->push.subreq) {
     184           0 :                 errno = EAGAIN;
     185           0 :                 return -1;
     186             :         }
     187             : 
     188     1184730 :         len = MIN(size, UINT16_MAX - tlss->push.ofs);
     189             : 
     190     1184730 :         if (len == 0) {
     191       17976 :                 errno = EAGAIN;
     192       17976 :                 return -1;
     193             :         }
     194             : 
     195     1166754 :         nbuf = talloc_realloc(tlss, tlss->push.buf,
     196             :                               uint8_t, tlss->push.ofs + len);
     197     1166754 :         if (nbuf == NULL) {
     198           0 :                 if (tlss->push.buf) {
     199           0 :                         errno = EAGAIN;
     200           0 :                         return -1;
     201             :                 }
     202             : 
     203           0 :                 return -1;
     204             :         }
     205     1166754 :         tlss->push.buf = nbuf;
     206             : 
     207     1166754 :         memcpy(tlss->push.buf + tlss->push.ofs, buf, len);
     208             : 
     209     1166754 :         if (tlss->push.im == NULL) {
     210         965 :                 tlss->push.im = tevent_create_immediate(tlss);
     211         965 :                 if (tlss->push.im == NULL) {
     212           0 :                         errno = ENOMEM;
     213           0 :                         return -1;
     214             :                 }
     215             :         }
     216             : 
     217     1166754 :         if (tlss->push.ofs == 0) {
     218             :                 /*
     219             :                  * We'll do start the tstream_writev
     220             :                  * in the next event cycle.
     221             :                  *
     222             :                  * This way we can batch all push requests,
     223             :                  * if they fit into a UINT16_MAX buffer.
     224             :                  *
     225             :                  * This is important as gnutls_handshake()
     226             :                  * had a bug in some versions e.g. 2.4.1
     227             :                  * and others (See bug #7218) and it doesn't
     228             :                  * handle EAGAIN.
     229             :                  */
     230       26823 :                 tevent_schedule_immediate(tlss->push.im,
     231             :                                           tlss->current_ev,
     232             :                                           tstream_tls_push_trigger_write,
     233           0 :                                           stream);
     234             :         }
     235             : 
     236     1166754 :         tlss->push.ofs += len;
     237     1166754 :         return len;
     238             : }
     239             : 
     240             : static void tstream_tls_push_done(struct tevent_req *subreq);
     241             : 
     242       26812 : static void tstream_tls_push_trigger_write(struct tevent_context *ev,
     243             :                                            struct tevent_immediate *im,
     244             :                                            void *private_data)
     245             : {
     246           0 :         struct tstream_context *stream =
     247       26812 :                 talloc_get_type_abort(private_data,
     248             :                 struct tstream_context);
     249           0 :         struct tstream_tls *tlss =
     250       26812 :                 tstream_context_data(stream,
     251             :                 struct tstream_tls);
     252           0 :         struct tevent_req *subreq;
     253             : 
     254       26812 :         if (tlss->push.subreq) {
     255             :                 /* nothing todo */
     256           0 :                 return;
     257             :         }
     258             : 
     259       26812 :         tlss->push.iov.iov_base = (char *)tlss->push.buf;
     260       26812 :         tlss->push.iov.iov_len = tlss->push.ofs;
     261             : 
     262       26812 :         subreq = tstream_writev_send(tlss,
     263             :                                      tlss->current_ev,
     264             :                                      tlss->plain_stream,
     265       26812 :                                      &tlss->push.iov, 1);
     266       26812 :         if (subreq == NULL) {
     267           0 :                 tlss->error = ENOMEM;
     268           0 :                 tstream_tls_retry(stream, false);
     269           0 :                 return;
     270             :         }
     271       26812 :         tevent_req_set_callback(subreq, tstream_tls_push_done, stream);
     272             : 
     273       26812 :         tlss->push.subreq = subreq;
     274             : }
     275             : 
     276       26804 : static void tstream_tls_push_done(struct tevent_req *subreq)
     277             : {
     278           0 :         struct tstream_context *stream =
     279       26804 :                 tevent_req_callback_data(subreq,
     280             :                 struct tstream_context);
     281           0 :         struct tstream_tls *tlss =
     282       26804 :                 tstream_context_data(stream,
     283             :                 struct tstream_tls);
     284           0 :         int ret;
     285           0 :         int sys_errno;
     286             : 
     287       26804 :         tlss->push.subreq = NULL;
     288       26804 :         ZERO_STRUCT(tlss->push.iov);
     289       26804 :         TALLOC_FREE(tlss->push.buf);
     290       26804 :         tlss->push.ofs = 0;
     291             : 
     292       26804 :         ret = tstream_writev_recv(subreq, &sys_errno);
     293       26804 :         TALLOC_FREE(subreq);
     294       26804 :         if (ret == -1) {
     295           1 :                 tlss->error = sys_errno;
     296           1 :                 tstream_tls_retry(stream, false);
     297           1 :                 return;
     298             :         }
     299             : 
     300       26803 :         tstream_tls_retry(stream, false);
     301             : }
     302             : 
     303             : static void tstream_tls_pull_done(struct tevent_req *subreq);
     304             : 
     305     4621152 : static ssize_t tstream_tls_pull_function(gnutls_transport_ptr_t ptr,
     306             :                                          void *buf, size_t size)
     307             : {
     308           0 :         struct tstream_context *stream =
     309     4621152 :                 talloc_get_type_abort(ptr,
     310             :                 struct tstream_context);
     311           0 :         struct tstream_tls *tlss =
     312     4621152 :                 tstream_context_data(stream,
     313             :                 struct tstream_tls);
     314           0 :         struct tevent_req *subreq;
     315           0 :         size_t len;
     316             : 
     317     4621152 :         if (tlss->error != 0) {
     318           0 :                 errno = tlss->error;
     319           0 :                 return -1;
     320             :         }
     321             : 
     322     4621152 :         if (tlss->pull.subreq) {
     323        8827 :                 errno = EAGAIN;
     324        8827 :                 return -1;
     325             :         }
     326             : 
     327     4612325 :         if (tlss->pull.iov.iov_base) {
     328           0 :                 uint8_t *b;
     329           0 :                 size_t n;
     330             : 
     331     2305921 :                 b = (uint8_t *)tlss->pull.iov.iov_base;
     332             : 
     333     2305921 :                 n = MIN(tlss->pull.iov.iov_len, size);
     334     2305921 :                 memcpy(buf, b, n);
     335             : 
     336     2305921 :                 tlss->pull.iov.iov_len -= n;
     337     2305921 :                 b += n;
     338     2305921 :                 tlss->pull.iov.iov_base = (char *)b;
     339     2305921 :                 if (tlss->pull.iov.iov_len == 0) {
     340     2305921 :                         tlss->pull.iov.iov_base = NULL;
     341     2305921 :                         TALLOC_FREE(tlss->pull.buf);
     342             :                 }
     343             : 
     344     2305921 :                 return n;
     345             :         }
     346             : 
     347     2306404 :         if (size == 0) {
     348           0 :                 return 0;
     349             :         }
     350             : 
     351     2306404 :         len = MIN(size, UINT16_MAX);
     352             : 
     353     2306404 :         tlss->pull.buf = talloc_array(tlss, uint8_t, len);
     354     2306404 :         if (tlss->pull.buf == NULL) {
     355           0 :                 return -1;
     356             :         }
     357             : 
     358     2306404 :         tlss->pull.iov.iov_base = (char *)tlss->pull.buf;
     359     2306404 :         tlss->pull.iov.iov_len = len;
     360             : 
     361     2306404 :         subreq = tstream_readv_send(tlss,
     362             :                                     tlss->current_ev,
     363             :                                     tlss->plain_stream,
     364             :                                     &tlss->pull.iov, 1);
     365     2306404 :         if (subreq == NULL) {
     366           0 :                 errno = ENOMEM;
     367           0 :                 return -1;
     368             :         }
     369     2306404 :         tevent_req_set_callback(subreq, tstream_tls_pull_done, stream);
     370             : 
     371     2306404 :         tlss->pull.subreq = subreq;
     372     2306404 :         errno = EAGAIN;
     373     2306404 :         return -1;
     374             : }
     375             : 
     376     2306401 : static void tstream_tls_pull_done(struct tevent_req *subreq)
     377             : {
     378           0 :         struct tstream_context *stream =
     379     2306401 :                 tevent_req_callback_data(subreq,
     380             :                 struct tstream_context);
     381           0 :         struct tstream_tls *tlss =
     382     2306401 :                 tstream_context_data(stream,
     383             :                 struct tstream_tls);
     384           0 :         int ret;
     385           0 :         int sys_errno;
     386             : 
     387     2306401 :         tlss->pull.subreq = NULL;
     388             : 
     389     2306401 :         ret = tstream_readv_recv(subreq, &sys_errno);
     390     2306401 :         TALLOC_FREE(subreq);
     391     2306401 :         if (ret == -1) {
     392         480 :                 tlss->error = sys_errno;
     393         480 :                 tstream_tls_retry(stream, false);
     394         480 :                 return;
     395             :         }
     396             : 
     397     2305921 :         tstream_tls_retry(stream, false);
     398             : }
     399             : 
     400         967 : static int tstream_tls_destructor(struct tstream_tls *tlss)
     401             : {
     402         967 :         if (tlss->tls_session) {
     403         967 :                 gnutls_deinit(tlss->tls_session);
     404         967 :                 tlss->tls_session = NULL;
     405             :         }
     406             : 
     407         967 :         return 0;
     408             : }
     409             : 
     410           0 : static ssize_t tstream_tls_pending_bytes(struct tstream_context *stream)
     411             : {
     412           0 :         struct tstream_tls *tlss =
     413           0 :                 tstream_context_data(stream,
     414             :                 struct tstream_tls);
     415           0 :         size_t ret;
     416             : 
     417           0 :         if (tlss->error != 0) {
     418           0 :                 errno = tlss->error;
     419           0 :                 return -1;
     420             :         }
     421             : 
     422           0 :         ret = gnutls_record_check_pending(tlss->tls_session);
     423           0 :         ret += tlss->read.left;
     424             : 
     425           0 :         return ret;
     426             : }
     427             : 
     428             : struct tstream_tls_readv_state {
     429             :         struct tstream_context *stream;
     430             : 
     431             :         struct iovec *vector;
     432             :         int count;
     433             : 
     434             :         int ret;
     435             : };
     436             : 
     437             : static void tstream_tls_readv_crypt_next(struct tevent_req *req);
     438             : 
     439       23469 : static struct tevent_req *tstream_tls_readv_send(TALLOC_CTX *mem_ctx,
     440             :                                         struct tevent_context *ev,
     441             :                                         struct tstream_context *stream,
     442             :                                         struct iovec *vector,
     443             :                                         size_t count)
     444             : {
     445           0 :         struct tstream_tls *tlss =
     446       23469 :                 tstream_context_data(stream,
     447             :                 struct tstream_tls);
     448           0 :         struct tevent_req *req;
     449           0 :         struct tstream_tls_readv_state *state;
     450             : 
     451       23469 :         tlss->read.req = NULL;
     452       23469 :         tlss->current_ev = ev;
     453             : 
     454       23469 :         req = tevent_req_create(mem_ctx, &state,
     455             :                                 struct tstream_tls_readv_state);
     456       23469 :         if (req == NULL) {
     457           0 :                 return NULL;
     458             :         }
     459             : 
     460       23469 :         state->stream = stream;
     461       23469 :         state->ret = 0;
     462             : 
     463       23469 :         if (tlss->error != 0) {
     464           0 :                 tevent_req_error(req, tlss->error);
     465           0 :                 return tevent_req_post(req, ev);
     466             :         }
     467             : 
     468             :         /*
     469             :          * we make a copy of the vector so we can change the structure
     470             :          */
     471       23469 :         state->vector = talloc_array(state, struct iovec, count);
     472       23469 :         if (tevent_req_nomem(state->vector, req)) {
     473           0 :                 return tevent_req_post(req, ev);
     474             :         }
     475       23469 :         memcpy(state->vector, vector, sizeof(struct iovec) * count);
     476       23469 :         state->count = count;
     477             : 
     478       23469 :         tstream_tls_readv_crypt_next(req);
     479       23469 :         if (!tevent_req_is_in_progress(req)) {
     480       13937 :                 return tevent_req_post(req, ev);
     481             :         }
     482             : 
     483        9532 :         return req;
     484             : }
     485             : 
     486     1235438 : static void tstream_tls_readv_crypt_next(struct tevent_req *req)
     487             : {
     488           0 :         struct tstream_tls_readv_state *state =
     489     1235438 :                 tevent_req_data(req,
     490             :                 struct tstream_tls_readv_state);
     491           0 :         struct tstream_tls *tlss =
     492     1235438 :                 tstream_context_data(state->stream,
     493             :                 struct tstream_tls);
     494             : 
     495             :         /*
     496             :          * copy the pending buffer first
     497             :          */
     498     2462954 :         while (tlss->read.left > 0 && state->count > 0) {
     499     1227516 :                 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
     500     1227516 :                 size_t len = MIN(tlss->read.left, state->vector[0].iov_len);
     501             : 
     502     1227516 :                 memcpy(base, tlss->read.buffer + tlss->read.ofs, len);
     503             : 
     504     1227516 :                 base += len;
     505     1227516 :                 state->vector[0].iov_base = (char *) base;
     506     1227516 :                 state->vector[0].iov_len -= len;
     507             : 
     508     1227516 :                 tlss->read.ofs += len;
     509     1227516 :                 tlss->read.left -= len;
     510             : 
     511     1227516 :                 if (state->vector[0].iov_len == 0) {
     512       22994 :                         state->vector += 1;
     513       22994 :                         state->count -= 1;
     514             :                 }
     515             : 
     516     1227516 :                 state->ret += len;
     517             :         }
     518             : 
     519     1235438 :         if (state->count == 0) {
     520       22994 :                 tevent_req_done(req);
     521       22994 :                 return;
     522             :         }
     523             : 
     524     1212444 :         tlss->read.req = req;
     525     1212444 :         tstream_tls_retry_read(state->stream);
     526             : }
     527             : 
     528     3515747 : static void tstream_tls_retry_read(struct tstream_context *stream)
     529             : {
     530           0 :         struct tstream_tls *tlss =
     531     3515747 :                 tstream_context_data(stream,
     532             :                 struct tstream_tls);
     533     3515747 :         struct tevent_req *req = tlss->read.req;
     534           0 :         int ret;
     535             : 
     536     3515747 :         if (tlss->error != 0) {
     537         467 :                 tevent_req_error(req, tlss->error);
     538         467 :                 return;
     539             :         }
     540             : 
     541     3515280 :         tlss->read.left = 0;
     542     3515280 :         tlss->read.ofs = 0;
     543             : 
     544     7030560 :         ret = gnutls_record_recv(tlss->tls_session,
     545     3515280 :                                  tlss->read.buffer,
     546             :                                  sizeof(tlss->read.buffer));
     547     3515280 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
     548     2303305 :                 return;
     549             :         }
     550             : 
     551     1211975 :         tlss->read.req = NULL;
     552             : 
     553     1211975 :         if (gnutls_error_is_fatal(ret) != 0) {
     554           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
     555           0 :                 tlss->error = EIO;
     556           0 :                 tevent_req_error(req, tlss->error);
     557           0 :                 return;
     558             :         }
     559             : 
     560     1211975 :         if (ret == 0) {
     561           6 :                 tlss->error = EPIPE;
     562           6 :                 tevent_req_error(req, tlss->error);
     563           6 :                 return;
     564             :         }
     565             : 
     566     1211969 :         tlss->read.left = ret;
     567     1211969 :         tstream_tls_readv_crypt_next(req);
     568             : }
     569             : 
     570       23467 : static int tstream_tls_readv_recv(struct tevent_req *req,
     571             :                                   int *perrno)
     572             : {
     573           0 :         struct tstream_tls_readv_state *state =
     574       23467 :                 tevent_req_data(req,
     575             :                 struct tstream_tls_readv_state);
     576           0 :         struct tstream_tls *tlss =
     577       23467 :                 tstream_context_data(state->stream,
     578             :                 struct tstream_tls);
     579           0 :         int ret;
     580             : 
     581       23467 :         tlss->read.req = NULL;
     582             : 
     583       23467 :         ret = tsocket_simple_int_recv(req, perrno);
     584       23467 :         if (ret == 0) {
     585       22994 :                 ret = state->ret;
     586             :         }
     587             : 
     588       23467 :         tevent_req_received(req);
     589       23467 :         return ret;
     590             : }
     591             : 
     592             : struct tstream_tls_writev_state {
     593             :         struct tstream_context *stream;
     594             : 
     595             :         struct iovec *vector;
     596             :         int count;
     597             : 
     598             :         int ret;
     599             : };
     600             : 
     601             : static void tstream_tls_writev_crypt_next(struct tevent_req *req);
     602             : 
     603        7423 : static struct tevent_req *tstream_tls_writev_send(TALLOC_CTX *mem_ctx,
     604             :                                         struct tevent_context *ev,
     605             :                                         struct tstream_context *stream,
     606             :                                         const struct iovec *vector,
     607             :                                         size_t count)
     608             : {
     609           0 :         struct tstream_tls *tlss =
     610        7423 :                 tstream_context_data(stream,
     611             :                 struct tstream_tls);
     612           0 :         struct tevent_req *req;
     613           0 :         struct tstream_tls_writev_state *state;
     614             : 
     615        7423 :         tlss->write.req = NULL;
     616        7423 :         tlss->current_ev = ev;
     617             : 
     618        7423 :         req = tevent_req_create(mem_ctx, &state,
     619             :                                 struct tstream_tls_writev_state);
     620        7423 :         if (req == NULL) {
     621           0 :                 return NULL;
     622             :         }
     623             : 
     624        7423 :         state->stream = stream;
     625        7423 :         state->ret = 0;
     626             : 
     627        7423 :         if (tlss->error != 0) {
     628           0 :                 tevent_req_error(req, tlss->error);
     629           0 :                 return tevent_req_post(req, ev);
     630             :         }
     631             : 
     632             :         /*
     633             :          * we make a copy of the vector so we can change the structure
     634             :          */
     635        7423 :         state->vector = talloc_array(state, struct iovec, count);
     636        7423 :         if (tevent_req_nomem(state->vector, req)) {
     637           0 :                 return tevent_req_post(req, ev);
     638             :         }
     639        7423 :         memcpy(state->vector, vector, sizeof(struct iovec) * count);
     640        7423 :         state->count = count;
     641             : 
     642        7423 :         tstream_tls_writev_crypt_next(req);
     643        7423 :         if (!tevent_req_is_in_progress(req)) {
     644        7188 :                 return tevent_req_post(req, ev);
     645             :         }
     646             : 
     647         235 :         return req;
     648             : }
     649             : 
     650     1150860 : static void tstream_tls_writev_crypt_next(struct tevent_req *req)
     651             : {
     652           0 :         struct tstream_tls_writev_state *state =
     653     1150860 :                 tevent_req_data(req,
     654             :                 struct tstream_tls_writev_state);
     655           0 :         struct tstream_tls *tlss =
     656     1150860 :                 tstream_context_data(state->stream,
     657             :                 struct tstream_tls);
     658             : 
     659     1150860 :         tlss->write.left = sizeof(tlss->write.buffer);
     660     1150860 :         tlss->write.ofs = 0;
     661             : 
     662             :         /*
     663             :          * first fill our buffer
     664             :          */
     665     2298350 :         while (tlss->write.left > 0 && state->count > 0) {
     666     1147490 :                 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
     667     1147490 :                 size_t len = MIN(tlss->write.left, state->vector[0].iov_len);
     668             : 
     669     1147490 :                 memcpy(tlss->write.buffer + tlss->write.ofs, base, len);
     670             : 
     671     1147490 :                 base += len;
     672     1147490 :                 state->vector[0].iov_base = (char *) base;
     673     1147490 :                 state->vector[0].iov_len -= len;
     674             : 
     675     1147490 :                 tlss->write.ofs += len;
     676     1147490 :                 tlss->write.left -= len;
     677             : 
     678     1147490 :                 if (state->vector[0].iov_len == 0) {
     679       11491 :                         state->vector += 1;
     680       11491 :                         state->count -= 1;
     681             :                 }
     682             : 
     683     1147490 :                 state->ret += len;
     684             :         }
     685             : 
     686     1150860 :         if (tlss->write.ofs == 0) {
     687        7423 :                 tevent_req_done(req);
     688        7423 :                 return;
     689             :         }
     690             : 
     691     1143437 :         tlss->write.left = tlss->write.ofs;
     692     1143437 :         tlss->write.ofs = 0;
     693             : 
     694     1143437 :         tlss->write.req = req;
     695     1143437 :         tstream_tls_retry_write(state->stream);
     696             : }
     697             : 
     698     1161413 : static void tstream_tls_retry_write(struct tstream_context *stream)
     699             : {
     700           0 :         struct tstream_tls *tlss =
     701     1161413 :                 tstream_context_data(stream,
     702             :                 struct tstream_tls);
     703     1161413 :         struct tevent_req *req = tlss->write.req;
     704           0 :         int ret;
     705             : 
     706     1161413 :         if (tlss->error != 0) {
     707           0 :                 tevent_req_error(req, tlss->error);
     708           0 :                 return;
     709             :         }
     710             : 
     711     2322826 :         ret = gnutls_record_send(tlss->tls_session,
     712     1161413 :                                  tlss->write.buffer + tlss->write.ofs,
     713             :                                  tlss->write.left);
     714     1161413 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
     715       17976 :                 return;
     716             :         }
     717             : 
     718     1143437 :         tlss->write.req = NULL;
     719             : 
     720     1143437 :         if (gnutls_error_is_fatal(ret) != 0) {
     721           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
     722           0 :                 tlss->error = EIO;
     723           0 :                 tevent_req_error(req, tlss->error);
     724           0 :                 return;
     725             :         }
     726             : 
     727     1143437 :         if (ret == 0) {
     728           0 :                 tlss->error = EPIPE;
     729           0 :                 tevent_req_error(req, tlss->error);
     730           0 :                 return;
     731             :         }
     732             : 
     733     1143437 :         tlss->write.ofs += ret;
     734     1143437 :         tlss->write.left -= ret;
     735             : 
     736     1143437 :         if (tlss->write.left > 0) {
     737           0 :                 tlss->write.req = req;
     738           0 :                 tstream_tls_retry_write(stream);
     739           0 :                 return;
     740             :         }
     741             : 
     742     1143437 :         tstream_tls_writev_crypt_next(req);
     743             : }
     744             : 
     745        7423 : static int tstream_tls_writev_recv(struct tevent_req *req,
     746             :                                    int *perrno)
     747             : {
     748           0 :         struct tstream_tls_writev_state *state =
     749        7423 :                 tevent_req_data(req,
     750             :                 struct tstream_tls_writev_state);
     751           0 :         struct tstream_tls *tlss =
     752        7423 :                 tstream_context_data(state->stream,
     753             :                 struct tstream_tls);
     754           0 :         int ret;
     755             : 
     756        7423 :         tlss->write.req = NULL;
     757             : 
     758        7423 :         ret = tsocket_simple_int_recv(req, perrno);
     759        7423 :         if (ret == 0) {
     760        7423 :                 ret = state->ret;
     761             :         }
     762             : 
     763        7423 :         tevent_req_received(req);
     764        7423 :         return ret;
     765             : }
     766             : 
     767             : struct tstream_tls_disconnect_state {
     768             :         uint8_t _dummy;
     769             : };
     770             : 
     771         481 : static struct tevent_req *tstream_tls_disconnect_send(TALLOC_CTX *mem_ctx,
     772             :                                                 struct tevent_context *ev,
     773             :                                                 struct tstream_context *stream)
     774             : {
     775           0 :         struct tstream_tls *tlss =
     776         481 :                 tstream_context_data(stream,
     777             :                 struct tstream_tls);
     778           0 :         struct tevent_req *req;
     779           0 :         struct tstream_tls_disconnect_state *state;
     780             : 
     781         481 :         tlss->disconnect.req = NULL;
     782         481 :         tlss->current_ev = ev;
     783             : 
     784         481 :         req = tevent_req_create(mem_ctx, &state,
     785             :                                 struct tstream_tls_disconnect_state);
     786         481 :         if (req == NULL) {
     787           0 :                 return NULL;
     788             :         }
     789             : 
     790         481 :         if (tlss->error != 0) {
     791         473 :                 tevent_req_error(req, tlss->error);
     792         473 :                 return tevent_req_post(req, ev);
     793             :         }
     794             : 
     795           8 :         tlss->disconnect.req = req;
     796           8 :         tstream_tls_retry_disconnect(stream);
     797           8 :         if (!tevent_req_is_in_progress(req)) {
     798           8 :                 return tevent_req_post(req, ev);
     799             :         }
     800             : 
     801           0 :         return req;
     802             : }
     803             : 
     804           8 : static void tstream_tls_retry_disconnect(struct tstream_context *stream)
     805             : {
     806           0 :         struct tstream_tls *tlss =
     807           8 :                 tstream_context_data(stream,
     808             :                 struct tstream_tls);
     809           8 :         struct tevent_req *req = tlss->disconnect.req;
     810           0 :         int ret;
     811             : 
     812           8 :         if (tlss->error != 0) {
     813           0 :                 tevent_req_error(req, tlss->error);
     814           0 :                 return;
     815             :         }
     816             : 
     817           8 :         ret = gnutls_bye(tlss->tls_session, GNUTLS_SHUT_WR);
     818           8 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
     819           0 :                 return;
     820             :         }
     821             : 
     822           8 :         tlss->disconnect.req = NULL;
     823             : 
     824           8 :         if (gnutls_error_is_fatal(ret) != 0) {
     825           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
     826           0 :                 tlss->error = EIO;
     827           0 :                 tevent_req_error(req, tlss->error);
     828           0 :                 return;
     829             :         }
     830             : 
     831           8 :         if (ret != GNUTLS_E_SUCCESS) {
     832           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
     833           0 :                 tlss->error = EIO;
     834           0 :                 tevent_req_error(req, tlss->error);
     835           0 :                 return;
     836             :         }
     837             : 
     838           8 :         tevent_req_done(req);
     839             : }
     840             : 
     841         481 : static int tstream_tls_disconnect_recv(struct tevent_req *req,
     842             :                                        int *perrno)
     843             : {
     844           0 :         int ret;
     845             : 
     846         481 :         ret = tsocket_simple_int_recv(req, perrno);
     847             : 
     848         481 :         tevent_req_received(req);
     849         481 :         return ret;
     850             : }
     851             : 
     852             : static const struct tstream_context_ops tstream_tls_ops = {
     853             :         .name                   = "tls",
     854             : 
     855             :         .pending_bytes          = tstream_tls_pending_bytes,
     856             : 
     857             :         .readv_send             = tstream_tls_readv_send,
     858             :         .readv_recv             = tstream_tls_readv_recv,
     859             : 
     860             :         .writev_send            = tstream_tls_writev_send,
     861             :         .writev_recv            = tstream_tls_writev_recv,
     862             : 
     863             :         .disconnect_send        = tstream_tls_disconnect_send,
     864             :         .disconnect_recv        = tstream_tls_disconnect_recv,
     865             : };
     866             : 
     867             : struct tstream_tls_params_internal {
     868             :         gnutls_certificate_credentials_t x509_cred;
     869             :         gnutls_dh_params_t dh_params;
     870             :         const char *tls_priority;
     871             :         bool tls_enabled;
     872             :         enum tls_verify_peer_state verify_peer;
     873             :         const char *peer_name;
     874             : };
     875             : 
     876             : struct tstream_tls_params {
     877             :         struct tstream_tls_params_internal *internal;
     878             : };
     879             : 
     880       15572 : static int tstream_tls_params_internal_destructor(struct tstream_tls_params_internal *tlsp)
     881             : {
     882       15572 :         if (tlsp->x509_cred) {
     883       15572 :                 gnutls_certificate_free_credentials(tlsp->x509_cred);
     884       15572 :                 tlsp->x509_cred = NULL;
     885             :         }
     886       15572 :         if (tlsp->dh_params) {
     887       15095 :                 gnutls_dh_params_deinit(tlsp->dh_params);
     888       15095 :                 tlsp->dh_params = NULL;
     889             :         }
     890             : 
     891       15572 :         return 0;
     892             : }
     893             : 
     894         240 : bool tstream_tls_params_enabled(struct tstream_tls_params *tls_params)
     895             : {
     896         240 :         struct tstream_tls_params_internal *tlsp = tls_params->internal;
     897             : 
     898         240 :         return tlsp->tls_enabled;
     899             : }
     900             : 
     901         477 : NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
     902             :                                    const char *ca_file,
     903             :                                    const char *crl_file,
     904             :                                    const char *tls_priority,
     905             :                                    enum tls_verify_peer_state verify_peer,
     906             :                                    const char *peer_name,
     907             :                                    struct tstream_tls_params **_tlsp)
     908             : {
     909         477 :         struct tstream_tls_params *__tlsp = NULL;
     910         477 :         struct tstream_tls_params_internal *tlsp = NULL;
     911           0 :         int ret;
     912             : 
     913         477 :         __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
     914         477 :         if (__tlsp == NULL) {
     915           0 :                 return NT_STATUS_NO_MEMORY;
     916             :         }
     917             : 
     918         477 :         tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
     919         477 :         if (tlsp == NULL) {
     920           0 :                 TALLOC_FREE(__tlsp);
     921           0 :                 return NT_STATUS_NO_MEMORY;
     922             :         }
     923         477 :         talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
     924         477 :         __tlsp->internal = tlsp;
     925             : 
     926         477 :         tlsp->verify_peer = verify_peer;
     927         477 :         if (peer_name != NULL) {
     928         477 :                 tlsp->peer_name = talloc_strdup(tlsp, peer_name);
     929         477 :                 if (tlsp->peer_name == NULL) {
     930           0 :                         TALLOC_FREE(__tlsp);
     931           0 :                         return NT_STATUS_NO_MEMORY;
     932             :                 }
     933           0 :         } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
     934           0 :                 DEBUG(0,("TLS failed to missing peer_name - "
     935             :                          "with 'tls verify peer = %s'\n",
     936             :                          tls_verify_peer_string(tlsp->verify_peer)));
     937           0 :                 TALLOC_FREE(__tlsp);
     938           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
     939             :         }
     940             : 
     941         477 :         ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
     942         477 :         if (ret != GNUTLS_E_SUCCESS) {
     943           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
     944           0 :                 TALLOC_FREE(__tlsp);
     945           0 :                 return NT_STATUS_NO_MEMORY;
     946             :         }
     947             : 
     948         477 :         if (ca_file && *ca_file && file_exist(ca_file)) {
     949         477 :                 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
     950             :                                                              ca_file,
     951             :                                                              GNUTLS_X509_FMT_PEM);
     952         477 :                 if (ret < 0) {
     953           0 :                         DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
     954             :                                  ca_file, gnutls_strerror(ret)));
     955           0 :                         TALLOC_FREE(__tlsp);
     956           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
     957             :                 }
     958           0 :         } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
     959           0 :                 DEBUG(0,("TLS failed to missing cafile %s - "
     960             :                          "with 'tls verify peer = %s'\n",
     961             :                          ca_file,
     962             :                          tls_verify_peer_string(tlsp->verify_peer)));
     963           0 :                 TALLOC_FREE(__tlsp);
     964           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
     965             :         }
     966             : 
     967         477 :         if (crl_file && *crl_file && file_exist(crl_file)) {
     968         360 :                 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
     969             :                                                            crl_file, 
     970             :                                                            GNUTLS_X509_FMT_PEM);
     971         360 :                 if (ret < 0) {
     972           0 :                         DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
     973             :                                  crl_file, gnutls_strerror(ret)));
     974           0 :                         TALLOC_FREE(__tlsp);
     975           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
     976             :                 }
     977         117 :         } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE) {
     978           6 :                 DEBUG(0,("TLS failed to missing crlfile %s - "
     979             :                          "with 'tls verify peer = %s'\n",
     980             :                          crl_file,
     981             :                          tls_verify_peer_string(tlsp->verify_peer)));
     982           6 :                 TALLOC_FREE(__tlsp);
     983           6 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
     984             :         }
     985             : 
     986         471 :         tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
     987         471 :         if (tlsp->tls_priority == NULL) {
     988           0 :                 TALLOC_FREE(__tlsp);
     989           0 :                 return NT_STATUS_NO_MEMORY;
     990             :         }
     991             : 
     992         471 :         tlsp->tls_enabled = true;
     993             : 
     994         471 :         *_tlsp = __tlsp;
     995         471 :         return NT_STATUS_OK;
     996             : }
     997             : 
     998             : struct tstream_tls_connect_state {
     999             :         struct tstream_context *tls_stream;
    1000             : };
    1001             : 
    1002         471 : struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
    1003             :                                              struct tevent_context *ev,
    1004             :                                              struct tstream_context *plain_stream,
    1005             :                                              struct tstream_tls_params *_tls_params,
    1006             :                                              const char *location)
    1007             : {
    1008           0 :         struct tevent_req *req;
    1009           0 :         struct tstream_tls_connect_state *state;
    1010           0 :         const char *error_pos;
    1011           0 :         struct tstream_tls *tlss;
    1012         471 :         struct tstream_tls_params_internal *tls_params = NULL;
    1013           0 :         int ret;
    1014         471 :         unsigned int flags = GNUTLS_CLIENT;
    1015             : 
    1016         471 :         req = tevent_req_create(mem_ctx, &state,
    1017             :                                 struct tstream_tls_connect_state);
    1018         471 :         if (req == NULL) {
    1019           0 :                 return NULL;
    1020             :         }
    1021             : 
    1022         471 :         state->tls_stream = tstream_context_create(state,
    1023             :                                                    &tstream_tls_ops,
    1024             :                                                    &tlss,
    1025             :                                                    struct tstream_tls,
    1026             :                                                    location);
    1027         471 :         if (tevent_req_nomem(state->tls_stream, req)) {
    1028           0 :                 return tevent_req_post(req, ev);
    1029             :         }
    1030         471 :         ZERO_STRUCTP(tlss);
    1031         471 :         talloc_set_destructor(tlss, tstream_tls_destructor);
    1032             : 
    1033             :         /*
    1034             :          * Note we need to make sure x509_cred and dh_params
    1035             :          * from tstream_tls_params_internal stay alive for
    1036             :          * the whole lifetime of this session!
    1037             :          *
    1038             :          * See 'man gnutls_credentials_set' and
    1039             :          * 'man gnutls_certificate_set_dh_params'.
    1040             :          *
    1041             :          * Note: here we use talloc_reference() in a way
    1042             :          *       that does not expose it to the caller.
    1043             :          *
    1044             :          */
    1045         471 :         tls_params = talloc_reference(tlss, _tls_params->internal);
    1046         471 :         if (tevent_req_nomem(tls_params, req)) {
    1047           0 :                 return tevent_req_post(req, ev);
    1048             :         }
    1049             : 
    1050         471 :         tlss->plain_stream = plain_stream;
    1051         471 :         tlss->verify_peer = tls_params->verify_peer;
    1052         471 :         if (tls_params->peer_name != NULL) {
    1053         471 :                 tlss->peer_name = talloc_strdup(tlss, tls_params->peer_name);
    1054         471 :                 if (tevent_req_nomem(tlss->peer_name, req)) {
    1055           0 :                         return tevent_req_post(req, ev);
    1056             :                 }
    1057             :         }
    1058             : 
    1059         471 :         tlss->current_ev = ev;
    1060         471 :         tlss->retry_im = tevent_create_immediate(tlss);
    1061         471 :         if (tevent_req_nomem(tlss->retry_im, req)) {
    1062           0 :                 return tevent_req_post(req, ev);
    1063             :         }
    1064             : 
    1065             : #ifdef GNUTLS_NO_TICKETS
    1066             :         /*
    1067             :          * tls_tstream can't properly handle 'New Session Ticket' messages
    1068             :          * sent 'after' the client sends the 'Finished' message.
    1069             :          * GNUTLS_NO_TICKETS was introduced in GnuTLS 3.5.6.  This flag is to
    1070             :          * indicate the session Flag session should not use resumption with
    1071             :          * session tickets.
    1072             :          */
    1073         471 :         flags |= GNUTLS_NO_TICKETS;
    1074             : #endif
    1075             : 
    1076         471 :         ret = gnutls_init(&tlss->tls_session, flags);
    1077         471 :         if (ret != GNUTLS_E_SUCCESS) {
    1078           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1079           0 :                 tevent_req_error(req, EINVAL);
    1080           0 :                 return tevent_req_post(req, ev);
    1081             :         }
    1082             : 
    1083         471 :         ret = gnutls_set_default_priority(tlss->tls_session);
    1084         471 :         if (ret != GNUTLS_E_SUCCESS) {
    1085           0 :                 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
    1086             :                         __location__, gnutls_strerror(ret));
    1087           0 :                 tevent_req_error(req, EINVAL);
    1088           0 :                 return tevent_req_post(req, ev);
    1089             :         }
    1090             : 
    1091         471 :         if (strlen(tls_params->tls_priority) > 0) {
    1092         471 :                 ret = gnutls_priority_set_direct(tlss->tls_session,
    1093             :                                                  tls_params->tls_priority,
    1094             :                                                  &error_pos);
    1095         471 :                 if (ret != GNUTLS_E_SUCCESS) {
    1096           1 :                         DEBUG(0,("TLS %s - %s.  Check 'tls priority' option at '%s'\n",
    1097             :                                  __location__, gnutls_strerror(ret), error_pos));
    1098           1 :                         tevent_req_error(req, EINVAL);
    1099           1 :                         return tevent_req_post(req, ev);
    1100             :                 }
    1101             :         }
    1102             : 
    1103         470 :         ret = gnutls_credentials_set(tlss->tls_session,
    1104             :                                      GNUTLS_CRD_CERTIFICATE,
    1105         470 :                                      tls_params->x509_cred);
    1106         470 :         if (ret != GNUTLS_E_SUCCESS) {
    1107           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1108           0 :                 tevent_req_error(req, EINVAL);
    1109           0 :                 return tevent_req_post(req, ev);
    1110             :         }
    1111             : 
    1112         470 :         gnutls_transport_set_ptr(tlss->tls_session,
    1113         470 :                                  (gnutls_transport_ptr_t)state->tls_stream);
    1114         470 :         gnutls_transport_set_pull_function(tlss->tls_session,
    1115             :                                            (gnutls_pull_func)tstream_tls_pull_function);
    1116         470 :         gnutls_transport_set_push_function(tlss->tls_session,
    1117             :                                            (gnutls_push_func)tstream_tls_push_function);
    1118             : 
    1119         470 :         tlss->handshake.req = req;
    1120         470 :         tstream_tls_retry_handshake(state->tls_stream);
    1121         470 :         if (!tevent_req_is_in_progress(req)) {
    1122           0 :                 return tevent_req_post(req, ev);
    1123             :         }
    1124             : 
    1125         470 :         return req;
    1126             : }
    1127             : 
    1128         471 : int tstream_tls_connect_recv(struct tevent_req *req,
    1129             :                              int *perrno,
    1130             :                              TALLOC_CTX *mem_ctx,
    1131             :                              struct tstream_context **tls_stream)
    1132             : {
    1133           0 :         struct tstream_tls_connect_state *state =
    1134         471 :                 tevent_req_data(req,
    1135             :                 struct tstream_tls_connect_state);
    1136             : 
    1137         471 :         if (tevent_req_is_unix_error(req, perrno)) {
    1138          13 :                 tevent_req_received(req);
    1139          13 :                 return -1;
    1140             :         }
    1141             : 
    1142         458 :         *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
    1143         458 :         tevent_req_received(req);
    1144         458 :         return 0;
    1145             : }
    1146             : 
    1147             : /*
    1148             :   initialise global tls state
    1149             : */
    1150          62 : NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
    1151             :                                    const char *dns_host_name,
    1152             :                                    bool enabled,
    1153             :                                    const char *key_file,
    1154             :                                    const char *cert_file,
    1155             :                                    const char *ca_file,
    1156             :                                    const char *crl_file,
    1157             :                                    const char *dhp_file,
    1158             :                                    const char *tls_priority,
    1159             :                                    struct tstream_tls_params **_tlsp)
    1160             : {
    1161          62 :         struct tstream_tls_params *__tlsp = NULL;
    1162          62 :         struct tstream_tls_params_internal *tlsp = NULL;
    1163           2 :         int ret;
    1164           2 :         struct stat st;
    1165             : 
    1166          62 :         if (!enabled || key_file == NULL || *key_file == 0) {
    1167           0 :                 __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
    1168           0 :                 if (__tlsp == NULL) {
    1169           0 :                         return NT_STATUS_NO_MEMORY;
    1170             :                 }
    1171             : 
    1172           0 :                 tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
    1173           0 :                 if (tlsp == NULL) {
    1174           0 :                         TALLOC_FREE(__tlsp);
    1175           0 :                         return NT_STATUS_NO_MEMORY;
    1176             :                 }
    1177             : 
    1178           0 :                 talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
    1179           0 :                 __tlsp->internal = tlsp;
    1180           0 :                 tlsp->tls_enabled = false;
    1181             : 
    1182           0 :                 *_tlsp = __tlsp;
    1183           0 :                 return NT_STATUS_OK;
    1184             :         }
    1185             : 
    1186          62 :         __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
    1187          62 :         if (__tlsp == NULL) {
    1188           0 :                 return NT_STATUS_NO_MEMORY;
    1189             :         }
    1190             : 
    1191          62 :         tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
    1192          62 :         if (tlsp == NULL) {
    1193           0 :                 TALLOC_FREE(__tlsp);
    1194           0 :                 return NT_STATUS_NO_MEMORY;
    1195             :         }
    1196             : 
    1197          62 :         talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
    1198          62 :         __tlsp->internal = tlsp;
    1199             : 
    1200          62 :         if (!file_exist(ca_file)) {
    1201          33 :                 tls_cert_generate(tlsp, dns_host_name,
    1202             :                                   key_file, cert_file, ca_file);
    1203             :         }
    1204             : 
    1205          64 :         if (file_exist(key_file) &&
    1206          62 :             !file_check_permissions(key_file, geteuid(), 0600, &st))
    1207             :         {
    1208           0 :                 DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
    1209             :                           "owner uid %u should be %u, mode 0%o should be 0%o\n"
    1210             :                           "This is known as CVE-2013-4476.\n"
    1211             :                           "Removing all tls .pem files will cause an "
    1212             :                           "auto-regeneration with the correct permissions.\n",
    1213             :                           key_file,
    1214             :                           (unsigned int)st.st_uid, geteuid(),
    1215             :                           (unsigned int)(st.st_mode & 0777), 0600));
    1216           0 :                 TALLOC_FREE(__tlsp);
    1217           0 :                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1218             :         }
    1219             : 
    1220          62 :         ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
    1221          62 :         if (ret != GNUTLS_E_SUCCESS) {
    1222           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1223           0 :                 TALLOC_FREE(__tlsp);
    1224           0 :                 return NT_STATUS_NO_MEMORY;
    1225             :         }
    1226             : 
    1227          62 :         if (ca_file && *ca_file) {
    1228          62 :                 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
    1229             :                                                              ca_file,
    1230             :                                                              GNUTLS_X509_FMT_PEM);
    1231          62 :                 if (ret < 0) {
    1232           0 :                         DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
    1233             :                                  ca_file, gnutls_strerror(ret)));
    1234           0 :                         TALLOC_FREE(__tlsp);
    1235           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1236             :                 }
    1237             :         }
    1238             : 
    1239          62 :         if (crl_file && *crl_file) {
    1240          27 :                 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
    1241             :                                                            crl_file, 
    1242             :                                                            GNUTLS_X509_FMT_PEM);
    1243          27 :                 if (ret < 0) {
    1244           0 :                         DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
    1245             :                                  crl_file, gnutls_strerror(ret)));
    1246           0 :                         TALLOC_FREE(__tlsp);
    1247           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1248             :                 }
    1249             :         }
    1250             : 
    1251          62 :         ret = gnutls_certificate_set_x509_key_file(tlsp->x509_cred,
    1252             :                                                    cert_file, key_file,
    1253             :                                                    GNUTLS_X509_FMT_PEM);
    1254          62 :         if (ret != GNUTLS_E_SUCCESS) {
    1255           0 :                 DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
    1256             :                          cert_file, key_file, gnutls_strerror(ret)));
    1257           0 :                 TALLOC_FREE(__tlsp);
    1258           0 :                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1259             :         }
    1260             : 
    1261          62 :         ret = gnutls_dh_params_init(&tlsp->dh_params);
    1262          62 :         if (ret != GNUTLS_E_SUCCESS) {
    1263           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1264           0 :                 TALLOC_FREE(__tlsp);
    1265           0 :                 return NT_STATUS_NO_MEMORY;
    1266             :         }
    1267             : 
    1268         124 :         if (dhp_file && *dhp_file) {
    1269           2 :                 gnutls_datum_t dhparms;
    1270           2 :                 size_t size;
    1271             : 
    1272          62 :                 dhparms.data = (uint8_t *)file_load(dhp_file, &size, 0, tlsp);
    1273             : 
    1274          62 :                 if (!dhparms.data) {
    1275           0 :                         DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
    1276             :                                  dhp_file, errno, strerror(errno)));
    1277           0 :                         TALLOC_FREE(__tlsp);
    1278           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1279             :                 }
    1280          62 :                 dhparms.size = size;
    1281             : 
    1282          62 :                 ret = gnutls_dh_params_import_pkcs3(tlsp->dh_params,
    1283             :                                                     &dhparms,
    1284             :                                                     GNUTLS_X509_FMT_PEM);
    1285          62 :                 if (ret != GNUTLS_E_SUCCESS) {
    1286           0 :                         DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
    1287             :                                  dhp_file, gnutls_strerror(ret)));
    1288           0 :                         TALLOC_FREE(__tlsp);
    1289           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1290             :                 }
    1291             :         } else {
    1292           0 :                 ret = gnutls_dh_params_generate2(tlsp->dh_params, DH_BITS);
    1293           0 :                 if (ret != GNUTLS_E_SUCCESS) {
    1294           0 :                         DEBUG(0,("TLS failed to generate dh_params - %s\n",
    1295             :                                  gnutls_strerror(ret)));
    1296           0 :                         TALLOC_FREE(__tlsp);
    1297           0 :                         return NT_STATUS_INTERNAL_ERROR;
    1298             :                 }
    1299             :         }
    1300             : 
    1301          62 :         gnutls_certificate_set_dh_params(tlsp->x509_cred, tlsp->dh_params);
    1302             : 
    1303          62 :         tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
    1304          62 :         if (tlsp->tls_priority == NULL) {
    1305           0 :                 TALLOC_FREE(__tlsp);
    1306           0 :                 return NT_STATUS_NO_MEMORY;
    1307             :         }
    1308             : 
    1309          62 :         tlsp->tls_enabled = true;
    1310             : 
    1311          62 :         *_tlsp = __tlsp;
    1312          62 :         return NT_STATUS_OK;
    1313             : }
    1314             : 
    1315             : struct tstream_tls_accept_state {
    1316             :         struct tstream_context *tls_stream;
    1317             : };
    1318             : 
    1319         496 : struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
    1320             :                                             struct tevent_context *ev,
    1321             :                                             struct tstream_context *plain_stream,
    1322             :                                             struct tstream_tls_params *_tlsp,
    1323             :                                             const char *location)
    1324             : {
    1325           0 :         struct tevent_req *req;
    1326           0 :         struct tstream_tls_accept_state *state;
    1327           0 :         struct tstream_tls *tlss;
    1328           0 :         const char *error_pos;
    1329         496 :         struct tstream_tls_params_internal *tlsp = NULL;
    1330           0 :         int ret;
    1331             : 
    1332         496 :         req = tevent_req_create(mem_ctx, &state,
    1333             :                                 struct tstream_tls_accept_state);
    1334         496 :         if (req == NULL) {
    1335           0 :                 return NULL;
    1336             :         }
    1337             : 
    1338         496 :         state->tls_stream = tstream_context_create(state,
    1339             :                                                    &tstream_tls_ops,
    1340             :                                                    &tlss,
    1341             :                                                    struct tstream_tls,
    1342             :                                                    location);
    1343         496 :         if (tevent_req_nomem(state->tls_stream, req)) {
    1344           0 :                 return tevent_req_post(req, ev);
    1345             :         }
    1346         496 :         ZERO_STRUCTP(tlss);
    1347         496 :         talloc_set_destructor(tlss, tstream_tls_destructor);
    1348             : 
    1349             :         /*
    1350             :          * Note we need to make sure x509_cred and dh_params
    1351             :          * from tstream_tls_params_internal stay alive for
    1352             :          * the whole lifetime of this session!
    1353             :          *
    1354             :          * See 'man gnutls_credentials_set' and
    1355             :          * 'man gnutls_certificate_set_dh_params'.
    1356             :          *
    1357             :          * Note: here we use talloc_reference() in a way
    1358             :          *       that does not expose it to the caller.
    1359             :          */
    1360         496 :         tlsp = talloc_reference(tlss, _tlsp->internal);
    1361         496 :         if (tevent_req_nomem(tlsp, req)) {
    1362           0 :                 return tevent_req_post(req, ev);
    1363             :         }
    1364             : 
    1365         496 :         tlss->plain_stream = plain_stream;
    1366             : 
    1367         496 :         tlss->current_ev = ev;
    1368         496 :         tlss->retry_im = tevent_create_immediate(tlss);
    1369         496 :         if (tevent_req_nomem(tlss->retry_im, req)) {
    1370           0 :                 return tevent_req_post(req, ev);
    1371             :         }
    1372             : 
    1373         496 :         ret = gnutls_init(&tlss->tls_session, GNUTLS_SERVER);
    1374         496 :         if (ret != GNUTLS_E_SUCCESS) {
    1375           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1376           0 :                 tevent_req_error(req, EINVAL);
    1377           0 :                 return tevent_req_post(req, ev);
    1378             :         }
    1379             : 
    1380         496 :         ret = gnutls_set_default_priority(tlss->tls_session);
    1381         496 :         if (ret != GNUTLS_E_SUCCESS) {
    1382           0 :                 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
    1383             :                         __location__, gnutls_strerror(ret));
    1384           0 :                 tevent_req_error(req, EINVAL);
    1385           0 :                 return tevent_req_post(req, ev);
    1386             :         }
    1387             : 
    1388         496 :         if (strlen(tlsp->tls_priority) > 0) {
    1389         496 :                 ret = gnutls_priority_set_direct(tlss->tls_session,
    1390             :                                                  tlsp->tls_priority,
    1391             :                                                  &error_pos);
    1392         496 :                 if (ret != GNUTLS_E_SUCCESS) {
    1393           0 :                         DEBUG(0,("TLS %s - %s.  Check 'tls priority' option at '%s'\n",
    1394             :                                  __location__, gnutls_strerror(ret), error_pos));
    1395           0 :                         tevent_req_error(req, EINVAL);
    1396           0 :                         return tevent_req_post(req, ev);
    1397             :                 }
    1398             :         }
    1399             : 
    1400         496 :         ret = gnutls_credentials_set(tlss->tls_session, GNUTLS_CRD_CERTIFICATE,
    1401         496 :                                      tlsp->x509_cred);
    1402         496 :         if (ret != GNUTLS_E_SUCCESS) {
    1403           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1404           0 :                 tevent_req_error(req, EINVAL);
    1405           0 :                 return tevent_req_post(req, ev);
    1406             :         }
    1407             : 
    1408         496 :         gnutls_certificate_server_set_request(tlss->tls_session,
    1409             :                                               GNUTLS_CERT_REQUEST);
    1410         496 :         gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS);
    1411             : 
    1412         496 :         gnutls_transport_set_ptr(tlss->tls_session,
    1413         496 :                                  (gnutls_transport_ptr_t)state->tls_stream);
    1414         496 :         gnutls_transport_set_pull_function(tlss->tls_session,
    1415             :                                            (gnutls_pull_func)tstream_tls_pull_function);
    1416         496 :         gnutls_transport_set_push_function(tlss->tls_session,
    1417             :                                            (gnutls_push_func)tstream_tls_push_function);
    1418             : 
    1419         496 :         tlss->handshake.req = req;
    1420         496 :         tstream_tls_retry_handshake(state->tls_stream);
    1421         496 :         if (!tevent_req_is_in_progress(req)) {
    1422           0 :                 return tevent_req_post(req, ev);
    1423             :         }
    1424             : 
    1425         496 :         return req;
    1426             : }
    1427             : 
    1428       12892 : static void tstream_tls_retry_handshake(struct tstream_context *stream)
    1429             : {
    1430           0 :         struct tstream_tls *tlss =
    1431       12892 :                 tstream_context_data(stream,
    1432             :                 struct tstream_tls);
    1433       12892 :         struct tevent_req *req = tlss->handshake.req;
    1434           0 :         int ret;
    1435             : 
    1436       12892 :         if (tlss->error != 0) {
    1437          14 :                 tevent_req_error(req, tlss->error);
    1438          14 :                 return;
    1439             :         }
    1440             : 
    1441       12878 :         ret = gnutls_handshake(tlss->tls_session);
    1442       12878 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
    1443       11926 :                 return;
    1444             :         }
    1445             : 
    1446         952 :         tlss->handshake.req = NULL;
    1447             : 
    1448         952 :         if (gnutls_error_is_fatal(ret) != 0) {
    1449           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1450           0 :                 tlss->error = EIO;
    1451           0 :                 tevent_req_error(req, tlss->error);
    1452           0 :                 return;
    1453             :         }
    1454             : 
    1455         952 :         if (ret != GNUTLS_E_SUCCESS) {
    1456           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1457           0 :                 tlss->error = EIO;
    1458           0 :                 tevent_req_error(req, tlss->error);
    1459           0 :                 return;
    1460             :         }
    1461             : 
    1462         952 :         if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
    1463          30 :                 unsigned int status = UINT32_MAX;
    1464          30 :                 bool ip = true;
    1465          30 :                 const char *hostname = NULL;
    1466             : 
    1467          30 :                 if (tlss->peer_name != NULL) {
    1468          30 :                         ip = is_ipaddress(tlss->peer_name);
    1469             :                 }
    1470             : 
    1471          30 :                 if (!ip) {
    1472          20 :                         hostname = tlss->peer_name;
    1473             :                 }
    1474             : 
    1475          30 :                 if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
    1476           9 :                         hostname = NULL;
    1477             :                 }
    1478             : 
    1479          30 :                 if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
    1480          12 :                         if (hostname == NULL) {
    1481           4 :                                 DEBUG(1,("TLS %s - no hostname available for "
    1482             :                                          "verify_peer[%s] and peer_name[%s]\n",
    1483             :                                          __location__,
    1484             :                                          tls_verify_peer_string(tlss->verify_peer),
    1485             :                                          tlss->peer_name));
    1486           4 :                                 tlss->error = EINVAL;
    1487           4 :                                 tevent_req_error(req, tlss->error);
    1488          11 :                                 return;
    1489             :                         }
    1490             :                 }
    1491             : 
    1492          26 :                 ret = gnutls_certificate_verify_peers3(tlss->tls_session,
    1493             :                                                        hostname,
    1494             :                                                        &status);
    1495          26 :                 if (ret != GNUTLS_E_SUCCESS) {
    1496           0 :                         DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1497           0 :                         tlss->error = EIO;
    1498           0 :                         tevent_req_error(req, tlss->error);
    1499           0 :                         return;
    1500             :                 }
    1501             : 
    1502          26 :                 if (status != 0) {
    1503           7 :                         DEBUG(1,("TLS %s - check failed for "
    1504             :                                  "verify_peer[%s] and peer_name[%s] "
    1505             :                                  "status 0x%x (%s%s%s%s%s%s%s%s)\n",
    1506             :                                  __location__,
    1507             :                                  tls_verify_peer_string(tlss->verify_peer),
    1508             :                                  tlss->peer_name,
    1509             :                                  status,
    1510             :                                  status & GNUTLS_CERT_INVALID ? "invalid " : "",
    1511             :                                  status & GNUTLS_CERT_REVOKED ? "revoked " : "",
    1512             :                                  status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
    1513             :                                         "signer_not_found " : "",
    1514             :                                  status & GNUTLS_CERT_SIGNER_NOT_CA ?
    1515             :                                         "signer_not_ca " : "",
    1516             :                                  status & GNUTLS_CERT_INSECURE_ALGORITHM ?
    1517             :                                         "insecure_algorithm " : "",
    1518             :                                  status & GNUTLS_CERT_NOT_ACTIVATED ?
    1519             :                                         "not_activated " : "",
    1520             :                                  status & GNUTLS_CERT_EXPIRED ?
    1521             :                                         "expired " : "",
    1522             :                                  status & GNUTLS_CERT_UNEXPECTED_OWNER ?
    1523             :                                         "unexpected_owner " : ""));
    1524           7 :                         tlss->error = EINVAL;
    1525           7 :                         tevent_req_error(req, tlss->error);
    1526           7 :                         return;
    1527             :                 }
    1528             :         }
    1529             : 
    1530         941 :         tevent_req_done(req);
    1531             : }
    1532             : 
    1533         496 : int tstream_tls_accept_recv(struct tevent_req *req,
    1534             :                             int *perrno,
    1535             :                             TALLOC_CTX *mem_ctx,
    1536             :                             struct tstream_context **tls_stream)
    1537             : {
    1538           0 :         struct tstream_tls_accept_state *state =
    1539         496 :                 tevent_req_data(req,
    1540             :                 struct tstream_tls_accept_state);
    1541             : 
    1542         496 :         if (tevent_req_is_unix_error(req, perrno)) {
    1543          13 :                 tevent_req_received(req);
    1544          13 :                 return -1;
    1545             :         }
    1546             : 
    1547         483 :         *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
    1548         483 :         tevent_req_received(req);
    1549         483 :         return 0;
    1550             : }

Generated by: LCOV version 1.14