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

Generated by: LCOV version 1.14