LCOV - code coverage report
Current view: top level - source4/lib/tls - tls_tstream.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 444 637 69.7 %
Date: 2024-02-14 10:14:15 Functions: 27 30 90.0 %

          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     2309150 : static void tstream_tls_retry(struct tstream_context *stream, bool deferred)
     118             : {
     119             : 
     120             :         struct tstream_tls *tlss =
     121     2309150 :                 tstream_context_data(stream,
     122             :                 struct tstream_tls);
     123             : 
     124     2309150 :         if (tlss->disconnect.req) {
     125           0 :                 tstream_tls_retry_disconnect(stream);
     126           0 :                 return;
     127             :         }
     128             : 
     129     2309150 :         if (tlss->handshake.req) {
     130        9895 :                 tstream_tls_retry_handshake(stream);
     131        9895 :                 return;
     132             :         }
     133             : 
     134     2299255 :         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             :                                           stream);
     138             :         }
     139             : 
     140     2299255 :         if (tlss->write.req) {
     141       17973 :                 tstream_tls_retry_write(stream);
     142       17973 :                 return;
     143             :         }
     144             : 
     145     2281282 :         if (tlss->read.req) {
     146     2281282 :                 tstream_tls_retry_read(stream);
     147     2281282 :                 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             :         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     1179214 : static ssize_t tstream_tls_push_function(gnutls_transport_ptr_t ptr,
     167             :                                          const void *buf, size_t size)
     168             : {
     169             :         struct tstream_context *stream =
     170     1179214 :                 talloc_get_type_abort(ptr,
     171             :                 struct tstream_context);
     172             :         struct tstream_tls *tlss =
     173     1179214 :                 tstream_context_data(stream,
     174             :                 struct tstream_tls);
     175             :         uint8_t *nbuf;
     176             :         size_t len;
     177             : 
     178     1179214 :         if (tlss->error != 0) {
     179           0 :                 errno = tlss->error;
     180           0 :                 return -1;
     181             :         }
     182             : 
     183     1179214 :         if (tlss->push.subreq) {
     184           0 :                 errno = EAGAIN;
     185           0 :                 return -1;
     186             :         }
     187             : 
     188     1179214 :         len = MIN(size, UINT16_MAX - tlss->push.ofs);
     189             : 
     190     1179214 :         if (len == 0) {
     191       17973 :                 errno = EAGAIN;
     192       17973 :                 return -1;
     193             :         }
     194             : 
     195     1161241 :         nbuf = talloc_realloc(tlss, tlss->push.buf,
     196             :                               uint8_t, tlss->push.ofs + len);
     197     1161241 :         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     1161241 :         tlss->push.buf = nbuf;
     206             : 
     207     1161241 :         memcpy(tlss->push.buf + tlss->push.ofs, buf, len);
     208             : 
     209     1161241 :         if (tlss->push.im == NULL) {
     210         795 :                 tlss->push.im = tevent_create_immediate(tlss);
     211         795 :                 if (tlss->push.im == NULL) {
     212           0 :                         errno = ENOMEM;
     213           0 :                         return -1;
     214             :                 }
     215             :         }
     216             : 
     217     1161241 :         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       22256 :                 tevent_schedule_immediate(tlss->push.im,
     231             :                                           tlss->current_ev,
     232             :                                           tstream_tls_push_trigger_write,
     233             :                                           stream);
     234             :         }
     235             : 
     236     1161241 :         tlss->push.ofs += len;
     237     1161241 :         return len;
     238             : }
     239             : 
     240             : static void tstream_tls_push_done(struct tevent_req *subreq);
     241             : 
     242       22245 : static void tstream_tls_push_trigger_write(struct tevent_context *ev,
     243             :                                            struct tevent_immediate *im,
     244             :                                            void *private_data)
     245             : {
     246             :         struct tstream_context *stream =
     247       22245 :                 talloc_get_type_abort(private_data,
     248             :                 struct tstream_context);
     249             :         struct tstream_tls *tlss =
     250       22245 :                 tstream_context_data(stream,
     251             :                 struct tstream_tls);
     252             :         struct tevent_req *subreq;
     253             : 
     254       22245 :         if (tlss->push.subreq) {
     255             :                 /* nothing todo */
     256           0 :                 return;
     257             :         }
     258             : 
     259       22245 :         tlss->push.iov.iov_base = (char *)tlss->push.buf;
     260       22245 :         tlss->push.iov.iov_len = tlss->push.ofs;
     261             : 
     262       22245 :         subreq = tstream_writev_send(tlss,
     263             :                                      tlss->current_ev,
     264             :                                      tlss->plain_stream,
     265       22245 :                                      &tlss->push.iov, 1);
     266       22245 :         if (subreq == NULL) {
     267           0 :                 tlss->error = ENOMEM;
     268           0 :                 tstream_tls_retry(stream, false);
     269           0 :                 return;
     270             :         }
     271       22245 :         tevent_req_set_callback(subreq, tstream_tls_push_done, stream);
     272             : 
     273       22245 :         tlss->push.subreq = subreq;
     274             : }
     275             : 
     276       22245 : static void tstream_tls_push_done(struct tevent_req *subreq)
     277             : {
     278             :         struct tstream_context *stream =
     279       22245 :                 tevent_req_callback_data(subreq,
     280             :                 struct tstream_context);
     281             :         struct tstream_tls *tlss =
     282       22245 :                 tstream_context_data(stream,
     283             :                 struct tstream_tls);
     284             :         int ret;
     285             :         int sys_errno;
     286             : 
     287       22245 :         tlss->push.subreq = NULL;
     288       22245 :         ZERO_STRUCT(tlss->push.iov);
     289       22245 :         TALLOC_FREE(tlss->push.buf);
     290       22245 :         tlss->push.ofs = 0;
     291             : 
     292       22245 :         ret = tstream_writev_recv(subreq, &sys_errno);
     293       22245 :         TALLOC_FREE(subreq);
     294       22245 :         if (ret == -1) {
     295           1 :                 tlss->error = sys_errno;
     296           1 :                 tstream_tls_retry(stream, false);
     297           1 :                 return;
     298             :         }
     299             : 
     300       22244 :         tstream_tls_retry(stream, false);
     301             : }
     302             : 
     303             : static void tstream_tls_pull_done(struct tevent_req *subreq);
     304             : 
     305     4577687 : static ssize_t tstream_tls_pull_function(gnutls_transport_ptr_t ptr,
     306             :                                          void *buf, size_t size)
     307             : {
     308             :         struct tstream_context *stream =
     309     4577687 :                 talloc_get_type_abort(ptr,
     310             :                 struct tstream_context);
     311             :         struct tstream_tls *tlss =
     312     4577687 :                 tstream_context_data(stream,
     313             :                 struct tstream_tls);
     314             :         struct tevent_req *subreq;
     315             :         size_t len;
     316             : 
     317     4577687 :         if (tlss->error != 0) {
     318           0 :                 errno = tlss->error;
     319           0 :                 return -1;
     320             :         }
     321             : 
     322     4577687 :         if (tlss->pull.subreq) {
     323        4271 :                 errno = EAGAIN;
     324        4271 :                 return -1;
     325             :         }
     326             : 
     327     4573416 :         if (tlss->pull.iov.iov_base) {
     328             :                 uint8_t *b;
     329             :                 size_t n;
     330             : 
     331     2286508 :                 b = (uint8_t *)tlss->pull.iov.iov_base;
     332             : 
     333     2286508 :                 n = MIN(tlss->pull.iov.iov_len, size);
     334     2286508 :                 memcpy(buf, b, n);
     335             : 
     336     2286508 :                 tlss->pull.iov.iov_len -= n;
     337     2286508 :                 b += n;
     338     2286508 :                 tlss->pull.iov.iov_base = (char *)b;
     339     2286508 :                 if (tlss->pull.iov.iov_len == 0) {
     340     2286508 :                         tlss->pull.iov.iov_base = NULL;
     341     2286508 :                         TALLOC_FREE(tlss->pull.buf);
     342             :                 }
     343             : 
     344     2286508 :                 return n;
     345             :         }
     346             : 
     347     2286908 :         if (size == 0) {
     348           0 :                 return 0;
     349             :         }
     350             : 
     351     2286908 :         len = MIN(size, UINT16_MAX);
     352             : 
     353     2286908 :         tlss->pull.buf = talloc_array(tlss, uint8_t, len);
     354     2286908 :         if (tlss->pull.buf == NULL) {
     355           0 :                 return -1;
     356             :         }
     357             : 
     358     2286908 :         tlss->pull.iov.iov_base = (char *)tlss->pull.buf;
     359     2286908 :         tlss->pull.iov.iov_len = len;
     360             : 
     361     2286908 :         subreq = tstream_readv_send(tlss,
     362             :                                     tlss->current_ev,
     363             :                                     tlss->plain_stream,
     364             :                                     &tlss->pull.iov, 1);
     365     2286908 :         if (subreq == NULL) {
     366           0 :                 errno = ENOMEM;
     367           0 :                 return -1;
     368             :         }
     369     2286908 :         tevent_req_set_callback(subreq, tstream_tls_pull_done, stream);
     370             : 
     371     2286908 :         tlss->pull.subreq = subreq;
     372     2286908 :         errno = EAGAIN;
     373     2286908 :         return -1;
     374             : }
     375             : 
     376     2286905 : static void tstream_tls_pull_done(struct tevent_req *subreq)
     377             : {
     378             :         struct tstream_context *stream =
     379     2286905 :                 tevent_req_callback_data(subreq,
     380             :                 struct tstream_context);
     381             :         struct tstream_tls *tlss =
     382     2286905 :                 tstream_context_data(stream,
     383             :                 struct tstream_tls);
     384             :         int ret;
     385             :         int sys_errno;
     386             : 
     387     2286905 :         tlss->pull.subreq = NULL;
     388             : 
     389     2286905 :         ret = tstream_readv_recv(subreq, &sys_errno);
     390     2286905 :         TALLOC_FREE(subreq);
     391     2286905 :         if (ret == -1) {
     392         397 :                 tlss->error = sys_errno;
     393         397 :                 tstream_tls_retry(stream, false);
     394         397 :                 return;
     395             :         }
     396             : 
     397     2286508 :         tstream_tls_retry(stream, false);
     398             : }
     399             : 
     400         798 : static int tstream_tls_destructor(struct tstream_tls *tlss)
     401             : {
     402         798 :         if (tlss->tls_session) {
     403         798 :                 gnutls_deinit(tlss->tls_session);
     404         798 :                 tlss->tls_session = NULL;
     405             :         }
     406             : 
     407         798 :         return 0;
     408             : }
     409             : 
     410           0 : static ssize_t tstream_tls_pending_bytes(struct tstream_context *stream)
     411             : {
     412             :         struct tstream_tls *tlss =
     413           0 :                 tstream_context_data(stream,
     414             :                 struct tstream_tls);
     415             :         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       10632 : 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             :         struct tstream_tls *tlss =
     446       10632 :                 tstream_context_data(stream,
     447             :                 struct tstream_tls);
     448             :         struct tevent_req *req;
     449             :         struct tstream_tls_readv_state *state;
     450             : 
     451       10632 :         tlss->read.req = NULL;
     452       10632 :         tlss->current_ev = ev;
     453             : 
     454       10632 :         req = tevent_req_create(mem_ctx, &state,
     455             :                                 struct tstream_tls_readv_state);
     456       10632 :         if (req == NULL) {
     457           0 :                 return NULL;
     458             :         }
     459             : 
     460       10632 :         state->stream = stream;
     461       10632 :         state->ret = 0;
     462             : 
     463       10632 :         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       10632 :         state->vector = talloc_array(state, struct iovec, count);
     472       10632 :         if (tevent_req_nomem(state->vector, req)) {
     473           0 :                 return tevent_req_post(req, ev);
     474             :         }
     475       10632 :         memcpy(state->vector, vector, sizeof(struct iovec) * count);
     476       10632 :         state->count = count;
     477             : 
     478       10632 :         tstream_tls_readv_crypt_next(req);
     479       10632 :         if (!tevent_req_is_in_progress(req)) {
     480        5742 :                 return tevent_req_post(req, ev);
     481             :         }
     482             : 
     483        4890 :         return req;
     484             : }
     485             : 
     486     1149541 : static void tstream_tls_readv_crypt_next(struct tevent_req *req)
     487             : {
     488             :         struct tstream_tls_readv_state *state =
     489     1149541 :                 tevent_req_data(req,
     490             :                 struct tstream_tls_readv_state);
     491             :         struct tstream_tls *tlss =
     492     1149541 :                 tstream_context_data(state->stream,
     493             :                 struct tstream_tls);
     494             : 
     495             :         /*
     496             :          * copy the pending buffer first
     497             :          */
     498     2295572 :         while (tlss->read.left > 0 && state->count > 0) {
     499     1146031 :                 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
     500     1146031 :                 size_t len = MIN(tlss->read.left, state->vector[0].iov_len);
     501             : 
     502     1146031 :                 memcpy(base, tlss->read.buffer + tlss->read.ofs, len);
     503             : 
     504     1146031 :                 base += len;
     505     1146031 :                 state->vector[0].iov_base = (char *) base;
     506     1146031 :                 state->vector[0].iov_len -= len;
     507             : 
     508     1146031 :                 tlss->read.ofs += len;
     509     1146031 :                 tlss->read.left -= len;
     510             : 
     511     1146031 :                 if (state->vector[0].iov_len == 0) {
     512       10246 :                         state->vector += 1;
     513       10246 :                         state->count -= 1;
     514             :                 }
     515             : 
     516     1146031 :                 state->ret += len;
     517             :         }
     518             : 
     519     1149541 :         if (state->count == 0) {
     520       10246 :                 tevent_req_done(req);
     521       10246 :                 return;
     522             :         }
     523             : 
     524     1139295 :         tlss->read.req = req;
     525     1139295 :         tstream_tls_retry_read(state->stream);
     526             : }
     527             : 
     528     3420577 : static void tstream_tls_retry_read(struct tstream_context *stream)
     529             : {
     530             :         struct tstream_tls *tlss =
     531     3420577 :                 tstream_context_data(stream,
     532             :                 struct tstream_tls);
     533     3420577 :         struct tevent_req *req = tlss->read.req;
     534             :         int ret;
     535             : 
     536     3420577 :         if (tlss->error != 0) {
     537         384 :                 tevent_req_error(req, tlss->error);
     538         384 :                 return;
     539             :         }
     540             : 
     541     3420193 :         tlss->read.left = 0;
     542     3420193 :         tlss->read.ofs = 0;
     543             : 
     544     6840386 :         ret = gnutls_record_recv(tlss->tls_session,
     545     3420193 :                                  tlss->read.buffer,
     546             :                                  sizeof(tlss->read.buffer));
     547     3420193 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
     548     2281284 :                 return;
     549             :         }
     550             : 
     551     1138909 :         tlss->read.req = NULL;
     552             : 
     553     1138909 :         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     1138909 :         if (ret == 0) {
     561           0 :                 tlss->error = EPIPE;
     562           0 :                 tevent_req_error(req, tlss->error);
     563           0 :                 return;
     564             :         }
     565             : 
     566     1138909 :         tlss->read.left = ret;
     567     1138909 :         tstream_tls_readv_crypt_next(req);
     568             : }
     569             : 
     570       10630 : static int tstream_tls_readv_recv(struct tevent_req *req,
     571             :                                   int *perrno)
     572             : {
     573             :         struct tstream_tls_readv_state *state =
     574       10630 :                 tevent_req_data(req,
     575             :                 struct tstream_tls_readv_state);
     576             :         struct tstream_tls *tlss =
     577       10630 :                 tstream_context_data(state->stream,
     578             :                 struct tstream_tls);
     579             :         int ret;
     580             : 
     581       10630 :         tlss->read.req = NULL;
     582             : 
     583       10630 :         ret = tsocket_simple_int_recv(req, perrno);
     584       10630 :         if (ret == 0) {
     585       10246 :                 ret = state->ret;
     586             :         }
     587             : 
     588       10630 :         tevent_req_received(req);
     589       10630 :         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        3108 : 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             :         struct tstream_tls *tlss =
     610        3108 :                 tstream_context_data(stream,
     611             :                 struct tstream_tls);
     612             :         struct tevent_req *req;
     613             :         struct tstream_tls_writev_state *state;
     614             : 
     615        3108 :         tlss->write.req = NULL;
     616        3108 :         tlss->current_ev = ev;
     617             : 
     618        3108 :         req = tevent_req_create(mem_ctx, &state,
     619             :                                 struct tstream_tls_writev_state);
     620        3108 :         if (req == NULL) {
     621           0 :                 return NULL;
     622             :         }
     623             : 
     624        3108 :         state->stream = stream;
     625        3108 :         state->ret = 0;
     626             : 
     627        3108 :         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        3108 :         state->vector = talloc_array(state, struct iovec, count);
     636        3108 :         if (tevent_req_nomem(state->vector, req)) {
     637           0 :                 return tevent_req_post(req, ev);
     638             :         }
     639        3108 :         memcpy(state->vector, vector, sizeof(struct iovec) * count);
     640        3108 :         state->count = count;
     641             : 
     642        3108 :         tstream_tls_writev_crypt_next(req);
     643        3108 :         if (!tevent_req_is_in_progress(req)) {
     644        2875 :                 return tevent_req_post(req, ev);
     645             :         }
     646             : 
     647         233 :         return req;
     648             : }
     649             : 
     650     1142017 : static void tstream_tls_writev_crypt_next(struct tevent_req *req)
     651             : {
     652             :         struct tstream_tls_writev_state *state =
     653     1142017 :                 tevent_req_data(req,
     654             :                 struct tstream_tls_writev_state);
     655             :         struct tstream_tls *tlss =
     656     1142017 :                 tstream_context_data(state->stream,
     657             :                 struct tstream_tls);
     658             : 
     659     1142017 :         tlss->write.left = sizeof(tlss->write.buffer);
     660     1142017 :         tlss->write.ofs = 0;
     661             : 
     662             :         /*
     663             :          * first fill our buffer
     664             :          */
     665     2282929 :         while (tlss->write.left > 0 && state->count > 0) {
     666     1140912 :                 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
     667     1140912 :                 size_t len = MIN(tlss->write.left, state->vector[0].iov_len);
     668             : 
     669     1140912 :                 memcpy(tlss->write.buffer + tlss->write.ofs, base, len);
     670             : 
     671     1140912 :                 base += len;
     672     1140912 :                 state->vector[0].iov_base = (char *) base;
     673     1140912 :                 state->vector[0].iov_len -= len;
     674             : 
     675     1140912 :                 tlss->write.ofs += len;
     676     1140912 :                 tlss->write.left -= len;
     677             : 
     678     1140912 :                 if (state->vector[0].iov_len == 0) {
     679        5123 :                         state->vector += 1;
     680        5123 :                         state->count -= 1;
     681             :                 }
     682             : 
     683     1140912 :                 state->ret += len;
     684             :         }
     685             : 
     686     1142017 :         if (tlss->write.ofs == 0) {
     687        3108 :                 tevent_req_done(req);
     688        3108 :                 return;
     689             :         }
     690             : 
     691     1138909 :         tlss->write.left = tlss->write.ofs;
     692     1138909 :         tlss->write.ofs = 0;
     693             : 
     694     1138909 :         tlss->write.req = req;
     695     1138909 :         tstream_tls_retry_write(state->stream);
     696             : }
     697             : 
     698     1156882 : static void tstream_tls_retry_write(struct tstream_context *stream)
     699             : {
     700             :         struct tstream_tls *tlss =
     701     1156882 :                 tstream_context_data(stream,
     702             :                 struct tstream_tls);
     703     1156882 :         struct tevent_req *req = tlss->write.req;
     704             :         int ret;
     705             : 
     706     1156882 :         if (tlss->error != 0) {
     707           0 :                 tevent_req_error(req, tlss->error);
     708           0 :                 return;
     709             :         }
     710             : 
     711     2313764 :         ret = gnutls_record_send(tlss->tls_session,
     712     1156882 :                                  tlss->write.buffer + tlss->write.ofs,
     713             :                                  tlss->write.left);
     714     1156882 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
     715       17973 :                 return;
     716             :         }
     717             : 
     718     1138909 :         tlss->write.req = NULL;
     719             : 
     720     1138909 :         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     1138909 :         if (ret == 0) {
     728           0 :                 tlss->error = EPIPE;
     729           0 :                 tevent_req_error(req, tlss->error);
     730           0 :                 return;
     731             :         }
     732             : 
     733     1138909 :         tlss->write.ofs += ret;
     734     1138909 :         tlss->write.left -= ret;
     735             : 
     736     1138909 :         if (tlss->write.left > 0) {
     737           0 :                 tlss->write.req = req;
     738           0 :                 tstream_tls_retry_write(stream);
     739           0 :                 return;
     740             :         }
     741             : 
     742     1138909 :         tstream_tls_writev_crypt_next(req);
     743             : }
     744             : 
     745        3108 : static int tstream_tls_writev_recv(struct tevent_req *req,
     746             :                                    int *perrno)
     747             : {
     748             :         struct tstream_tls_writev_state *state =
     749        3108 :                 tevent_req_data(req,
     750             :                 struct tstream_tls_writev_state);
     751             :         struct tstream_tls *tlss =
     752        3108 :                 tstream_context_data(state->stream,
     753             :                 struct tstream_tls);
     754             :         int ret;
     755             : 
     756        3108 :         tlss->write.req = NULL;
     757             : 
     758        3108 :         ret = tsocket_simple_int_recv(req, perrno);
     759        3108 :         if (ret == 0) {
     760        3108 :                 ret = state->ret;
     761             :         }
     762             : 
     763        3108 :         tevent_req_received(req);
     764        3108 :         return ret;
     765             : }
     766             : 
     767             : struct tstream_tls_disconnect_state {
     768             :         uint8_t _dummy;
     769             : };
     770             : 
     771         384 : static struct tevent_req *tstream_tls_disconnect_send(TALLOC_CTX *mem_ctx,
     772             :                                                 struct tevent_context *ev,
     773             :                                                 struct tstream_context *stream)
     774             : {
     775             :         struct tstream_tls *tlss =
     776         384 :                 tstream_context_data(stream,
     777             :                 struct tstream_tls);
     778             :         struct tevent_req *req;
     779             :         struct tstream_tls_disconnect_state *state;
     780             : 
     781         384 :         tlss->disconnect.req = NULL;
     782         384 :         tlss->current_ev = ev;
     783             : 
     784         384 :         req = tevent_req_create(mem_ctx, &state,
     785             :                                 struct tstream_tls_disconnect_state);
     786         384 :         if (req == NULL) {
     787           0 :                 return NULL;
     788             :         }
     789             : 
     790         384 :         if (tlss->error != 0) {
     791         384 :                 tevent_req_error(req, tlss->error);
     792         384 :                 return tevent_req_post(req, ev);
     793             :         }
     794             : 
     795           0 :         tlss->disconnect.req = req;
     796           0 :         tstream_tls_retry_disconnect(stream);
     797           0 :         if (!tevent_req_is_in_progress(req)) {
     798           0 :                 return tevent_req_post(req, ev);
     799             :         }
     800             : 
     801           0 :         return req;
     802             : }
     803             : 
     804           0 : static void tstream_tls_retry_disconnect(struct tstream_context *stream)
     805             : {
     806             :         struct tstream_tls *tlss =
     807           0 :                 tstream_context_data(stream,
     808             :                 struct tstream_tls);
     809           0 :         struct tevent_req *req = tlss->disconnect.req;
     810             :         int ret;
     811             : 
     812           0 :         if (tlss->error != 0) {
     813           0 :                 tevent_req_error(req, tlss->error);
     814           0 :                 return;
     815             :         }
     816             : 
     817           0 :         ret = gnutls_bye(tlss->tls_session, GNUTLS_SHUT_WR);
     818           0 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
     819           0 :                 return;
     820             :         }
     821             : 
     822           0 :         tlss->disconnect.req = NULL;
     823             : 
     824           0 :         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           0 :         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           0 :         tevent_req_done(req);
     839             : }
     840             : 
     841         384 : static int tstream_tls_disconnect_recv(struct tevent_req *req,
     842             :                                        int *perrno)
     843             : {
     844             :         int ret;
     845             : 
     846         384 :         ret = tsocket_simple_int_recv(req, perrno);
     847             : 
     848         384 :         tevent_req_received(req);
     849         384 :         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 {
     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       15257 : static int tstream_tls_params_destructor(struct tstream_tls_params *tlsp)
     877             : {
     878       15257 :         if (tlsp->x509_cred) {
     879       15257 :                 gnutls_certificate_free_credentials(tlsp->x509_cred);
     880       15257 :                 tlsp->x509_cred = NULL;
     881             :         }
     882       15257 :         if (tlsp->dh_params) {
     883       14852 :                 gnutls_dh_params_deinit(tlsp->dh_params);
     884       14852 :                 tlsp->dh_params = NULL;
     885             :         }
     886             : 
     887       15257 :         return 0;
     888             : }
     889             : 
     890         200 : bool tstream_tls_params_enabled(struct tstream_tls_params *tlsp)
     891             : {
     892         200 :         return tlsp->tls_enabled;
     893             : }
     894             : 
     895         405 : NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
     896             :                                    const char *ca_file,
     897             :                                    const char *crl_file,
     898             :                                    const char *tls_priority,
     899             :                                    enum tls_verify_peer_state verify_peer,
     900             :                                    const char *peer_name,
     901             :                                    struct tstream_tls_params **_tlsp)
     902             : {
     903             :         struct tstream_tls_params *tlsp;
     904             :         int ret;
     905             : 
     906         405 :         tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
     907         405 :         NT_STATUS_HAVE_NO_MEMORY(tlsp);
     908             : 
     909         405 :         talloc_set_destructor(tlsp, tstream_tls_params_destructor);
     910             : 
     911         405 :         tlsp->verify_peer = verify_peer;
     912         405 :         if (peer_name != NULL) {
     913         405 :                 tlsp->peer_name = talloc_strdup(tlsp, peer_name);
     914         405 :                 if (tlsp->peer_name == NULL) {
     915           0 :                         talloc_free(tlsp);
     916           0 :                         return NT_STATUS_NO_MEMORY;
     917             :                 }
     918           0 :         } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
     919           0 :                 DEBUG(0,("TLS failed to missing peer_name - "
     920             :                          "with 'tls verify peer = %s'\n",
     921             :                          tls_verify_peer_string(tlsp->verify_peer)));
     922           0 :                 talloc_free(tlsp);
     923           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
     924             :         }
     925             : 
     926         405 :         ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
     927         405 :         if (ret != GNUTLS_E_SUCCESS) {
     928           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
     929           0 :                 talloc_free(tlsp);
     930           0 :                 return NT_STATUS_NO_MEMORY;
     931             :         }
     932             : 
     933         405 :         if (ca_file && *ca_file && file_exist(ca_file)) {
     934         405 :                 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
     935             :                                                              ca_file,
     936             :                                                              GNUTLS_X509_FMT_PEM);
     937         405 :                 if (ret < 0) {
     938           0 :                         DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
     939             :                                  ca_file, gnutls_strerror(ret)));
     940           0 :                         talloc_free(tlsp);
     941           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
     942             :                 }
     943           0 :         } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
     944           0 :                 DEBUG(0,("TLS failed to missing cafile %s - "
     945             :                          "with 'tls verify peer = %s'\n",
     946             :                          ca_file,
     947             :                          tls_verify_peer_string(tlsp->verify_peer)));
     948           0 :                 talloc_free(tlsp);
     949           0 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
     950             :         }
     951             : 
     952         405 :         if (crl_file && *crl_file && file_exist(crl_file)) {
     953         292 :                 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
     954             :                                                            crl_file, 
     955             :                                                            GNUTLS_X509_FMT_PEM);
     956         292 :                 if (ret < 0) {
     957           0 :                         DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
     958             :                                  crl_file, gnutls_strerror(ret)));
     959           0 :                         talloc_free(tlsp);
     960           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
     961             :                 }
     962         113 :         } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE) {
     963           6 :                 DEBUG(0,("TLS failed to missing crlfile %s - "
     964             :                          "with 'tls verify peer = %s'\n",
     965             :                          crl_file,
     966             :                          tls_verify_peer_string(tlsp->verify_peer)));
     967           6 :                 talloc_free(tlsp);
     968           6 :                 return NT_STATUS_INVALID_PARAMETER_MIX;
     969             :         }
     970             : 
     971         399 :         tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
     972         399 :         if (tlsp->tls_priority == NULL) {
     973           0 :                 talloc_free(tlsp);
     974           0 :                 return NT_STATUS_NO_MEMORY;
     975             :         }
     976             : 
     977         399 :         tlsp->tls_enabled = true;
     978             : 
     979         399 :         *_tlsp = tlsp;
     980         399 :         return NT_STATUS_OK;
     981             : }
     982             : 
     983             : struct tstream_tls_connect_state {
     984             :         struct tstream_context *tls_stream;
     985             : };
     986             : 
     987         399 : struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
     988             :                                              struct tevent_context *ev,
     989             :                                              struct tstream_context *plain_stream,
     990             :                                              struct tstream_tls_params *tls_params,
     991             :                                              const char *location)
     992             : {
     993             :         struct tevent_req *req;
     994             :         struct tstream_tls_connect_state *state;
     995             :         const char *error_pos;
     996             :         struct tstream_tls *tlss;
     997             :         int ret;
     998         399 :         unsigned int flags = GNUTLS_CLIENT;
     999             : 
    1000         399 :         req = tevent_req_create(mem_ctx, &state,
    1001             :                                 struct tstream_tls_connect_state);
    1002         399 :         if (req == NULL) {
    1003           0 :                 return NULL;
    1004             :         }
    1005             : 
    1006         399 :         state->tls_stream = tstream_context_create(state,
    1007             :                                                    &tstream_tls_ops,
    1008             :                                                    &tlss,
    1009             :                                                    struct tstream_tls,
    1010             :                                                    location);
    1011         399 :         if (tevent_req_nomem(state->tls_stream, req)) {
    1012           0 :                 return tevent_req_post(req, ev);
    1013             :         }
    1014         399 :         ZERO_STRUCTP(tlss);
    1015         399 :         talloc_set_destructor(tlss, tstream_tls_destructor);
    1016             : 
    1017         399 :         tlss->plain_stream = plain_stream;
    1018         399 :         tlss->verify_peer = tls_params->verify_peer;
    1019         399 :         if (tls_params->peer_name != NULL) {
    1020         399 :                 tlss->peer_name = talloc_strdup(tlss, tls_params->peer_name);
    1021         399 :                 if (tevent_req_nomem(tlss->peer_name, req)) {
    1022           0 :                         return tevent_req_post(req, ev);
    1023             :                 }
    1024             :         }
    1025             : 
    1026         399 :         tlss->current_ev = ev;
    1027         399 :         tlss->retry_im = tevent_create_immediate(tlss);
    1028         399 :         if (tevent_req_nomem(tlss->retry_im, req)) {
    1029           0 :                 return tevent_req_post(req, ev);
    1030             :         }
    1031             : 
    1032             : #ifdef GNUTLS_NO_TICKETS
    1033             :         /*
    1034             :          * tls_tstream can't properly handle 'New Session Ticket' messages
    1035             :          * sent 'after' the client sends the 'Finished' message.
    1036             :          * GNUTLS_NO_TICKETS was introduced in GnuTLS 3.5.6.  This flag is to
    1037             :          * indicate the session Flag session should not use resumption with
    1038             :          * session tickets.
    1039             :          */
    1040         399 :         flags |= GNUTLS_NO_TICKETS;
    1041             : #endif
    1042             : 
    1043         399 :         ret = gnutls_init(&tlss->tls_session, flags);
    1044         399 :         if (ret != GNUTLS_E_SUCCESS) {
    1045           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1046           0 :                 tevent_req_error(req, EINVAL);
    1047           0 :                 return tevent_req_post(req, ev);
    1048             :         }
    1049             : 
    1050         399 :         ret = gnutls_set_default_priority(tlss->tls_session);
    1051         399 :         if (ret != GNUTLS_E_SUCCESS) {
    1052           0 :                 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
    1053             :                         __location__, gnutls_strerror(ret));
    1054           0 :                 tevent_req_error(req, EINVAL);
    1055           0 :                 return tevent_req_post(req, ev);
    1056             :         }
    1057             : 
    1058         399 :         if (strlen(tls_params->tls_priority) > 0) {
    1059         399 :                 ret = gnutls_priority_set_direct(tlss->tls_session,
    1060             :                                                  tls_params->tls_priority,
    1061             :                                                  &error_pos);
    1062         399 :                 if (ret != GNUTLS_E_SUCCESS) {
    1063           1 :                         DEBUG(0,("TLS %s - %s.  Check 'tls priority' option at '%s'\n",
    1064             :                                  __location__, gnutls_strerror(ret), error_pos));
    1065           1 :                         tevent_req_error(req, EINVAL);
    1066           1 :                         return tevent_req_post(req, ev);
    1067             :                 }
    1068             :         }
    1069             : 
    1070         398 :         ret = gnutls_credentials_set(tlss->tls_session,
    1071             :                                      GNUTLS_CRD_CERTIFICATE,
    1072         398 :                                      tls_params->x509_cred);
    1073         398 :         if (ret != GNUTLS_E_SUCCESS) {
    1074           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1075           0 :                 tevent_req_error(req, EINVAL);
    1076           0 :                 return tevent_req_post(req, ev);
    1077             :         }
    1078             : 
    1079         398 :         gnutls_transport_set_ptr(tlss->tls_session,
    1080         398 :                                  (gnutls_transport_ptr_t)state->tls_stream);
    1081         398 :         gnutls_transport_set_pull_function(tlss->tls_session,
    1082             :                                            (gnutls_pull_func)tstream_tls_pull_function);
    1083         398 :         gnutls_transport_set_push_function(tlss->tls_session,
    1084             :                                            (gnutls_push_func)tstream_tls_push_function);
    1085             : 
    1086         398 :         tlss->handshake.req = req;
    1087         398 :         tstream_tls_retry_handshake(state->tls_stream);
    1088         398 :         if (!tevent_req_is_in_progress(req)) {
    1089           0 :                 return tevent_req_post(req, ev);
    1090             :         }
    1091             : 
    1092         398 :         return req;
    1093             : }
    1094             : 
    1095         399 : int tstream_tls_connect_recv(struct tevent_req *req,
    1096             :                              int *perrno,
    1097             :                              TALLOC_CTX *mem_ctx,
    1098             :                              struct tstream_context **tls_stream)
    1099             : {
    1100             :         struct tstream_tls_connect_state *state =
    1101         399 :                 tevent_req_data(req,
    1102             :                 struct tstream_tls_connect_state);
    1103             : 
    1104         399 :         if (tevent_req_is_unix_error(req, perrno)) {
    1105          13 :                 tevent_req_received(req);
    1106          13 :                 return -1;
    1107             :         }
    1108             : 
    1109         386 :         *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
    1110         386 :         tevent_req_received(req);
    1111         386 :         return 0;
    1112             : }
    1113             : 
    1114             : /*
    1115             :   initialise global tls state
    1116             : */
    1117          50 : NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
    1118             :                                    const char *dns_host_name,
    1119             :                                    bool enabled,
    1120             :                                    const char *key_file,
    1121             :                                    const char *cert_file,
    1122             :                                    const char *ca_file,
    1123             :                                    const char *crl_file,
    1124             :                                    const char *dhp_file,
    1125             :                                    const char *tls_priority,
    1126             :                                    struct tstream_tls_params **_tlsp)
    1127             : {
    1128             :         struct tstream_tls_params *tlsp;
    1129             :         int ret;
    1130             :         struct stat st;
    1131             : 
    1132          50 :         if (!enabled || key_file == NULL || *key_file == 0) {
    1133           0 :                 tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
    1134           0 :                 NT_STATUS_HAVE_NO_MEMORY(tlsp);
    1135           0 :                 talloc_set_destructor(tlsp, tstream_tls_params_destructor);
    1136           0 :                 tlsp->tls_enabled = false;
    1137             : 
    1138           0 :                 *_tlsp = tlsp;
    1139           0 :                 return NT_STATUS_OK;
    1140             :         }
    1141             : 
    1142          50 :         tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
    1143          50 :         NT_STATUS_HAVE_NO_MEMORY(tlsp);
    1144             : 
    1145          50 :         talloc_set_destructor(tlsp, tstream_tls_params_destructor);
    1146             : 
    1147          50 :         if (!file_exist(ca_file)) {
    1148          27 :                 tls_cert_generate(tlsp, dns_host_name,
    1149             :                                   key_file, cert_file, ca_file);
    1150             :         }
    1151             : 
    1152          50 :         if (file_exist(key_file) &&
    1153          50 :             !file_check_permissions(key_file, geteuid(), 0600, &st))
    1154             :         {
    1155           0 :                 DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
    1156             :                           "owner uid %u should be %u, mode 0%o should be 0%o\n"
    1157             :                           "This is known as CVE-2013-4476.\n"
    1158             :                           "Removing all tls .pem files will cause an "
    1159             :                           "auto-regeneration with the correct permissions.\n",
    1160             :                           key_file,
    1161             :                           (unsigned int)st.st_uid, geteuid(),
    1162             :                           (unsigned int)(st.st_mode & 0777), 0600));
    1163           0 :                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1164             :         }
    1165             : 
    1166          50 :         ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
    1167          50 :         if (ret != GNUTLS_E_SUCCESS) {
    1168           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1169           0 :                 talloc_free(tlsp);
    1170           0 :                 return NT_STATUS_NO_MEMORY;
    1171             :         }
    1172             : 
    1173          50 :         if (ca_file && *ca_file) {
    1174          50 :                 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
    1175             :                                                              ca_file,
    1176             :                                                              GNUTLS_X509_FMT_PEM);
    1177          50 :                 if (ret < 0) {
    1178           0 :                         DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
    1179             :                                  ca_file, gnutls_strerror(ret)));
    1180           0 :                         talloc_free(tlsp);
    1181           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1182             :                 }
    1183             :         }
    1184             : 
    1185          50 :         if (crl_file && *crl_file) {
    1186          21 :                 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
    1187             :                                                            crl_file, 
    1188             :                                                            GNUTLS_X509_FMT_PEM);
    1189          21 :                 if (ret < 0) {
    1190           0 :                         DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
    1191             :                                  crl_file, gnutls_strerror(ret)));
    1192           0 :                         talloc_free(tlsp);
    1193           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1194             :                 }
    1195             :         }
    1196             : 
    1197          50 :         ret = gnutls_certificate_set_x509_key_file(tlsp->x509_cred,
    1198             :                                                    cert_file, key_file,
    1199             :                                                    GNUTLS_X509_FMT_PEM);
    1200          50 :         if (ret != GNUTLS_E_SUCCESS) {
    1201           0 :                 DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
    1202             :                          cert_file, key_file, gnutls_strerror(ret)));
    1203           0 :                 talloc_free(tlsp);
    1204           0 :                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1205             :         }
    1206             : 
    1207          50 :         ret = gnutls_dh_params_init(&tlsp->dh_params);
    1208          50 :         if (ret != GNUTLS_E_SUCCESS) {
    1209           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1210           0 :                 talloc_free(tlsp);
    1211           0 :                 return NT_STATUS_NO_MEMORY;
    1212             :         }
    1213             : 
    1214         100 :         if (dhp_file && *dhp_file) {
    1215             :                 gnutls_datum_t dhparms;
    1216             :                 size_t size;
    1217             : 
    1218          50 :                 dhparms.data = (uint8_t *)file_load(dhp_file, &size, 0, tlsp);
    1219             : 
    1220          50 :                 if (!dhparms.data) {
    1221           0 :                         DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
    1222             :                                  dhp_file, errno, strerror(errno)));
    1223           0 :                         talloc_free(tlsp);
    1224           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1225             :                 }
    1226          50 :                 dhparms.size = size;
    1227             : 
    1228          50 :                 ret = gnutls_dh_params_import_pkcs3(tlsp->dh_params,
    1229             :                                                     &dhparms,
    1230             :                                                     GNUTLS_X509_FMT_PEM);
    1231          50 :                 if (ret != GNUTLS_E_SUCCESS) {
    1232           0 :                         DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
    1233             :                                  dhp_file, gnutls_strerror(ret)));
    1234           0 :                         talloc_free(tlsp);
    1235           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1236             :                 }
    1237             :         } else {
    1238           0 :                 ret = gnutls_dh_params_generate2(tlsp->dh_params, DH_BITS);
    1239           0 :                 if (ret != GNUTLS_E_SUCCESS) {
    1240           0 :                         DEBUG(0,("TLS failed to generate dh_params - %s\n",
    1241             :                                  gnutls_strerror(ret)));
    1242           0 :                         talloc_free(tlsp);
    1243           0 :                         return NT_STATUS_INTERNAL_ERROR;
    1244             :                 }
    1245             :         }
    1246             : 
    1247          50 :         gnutls_certificate_set_dh_params(tlsp->x509_cred, tlsp->dh_params);
    1248             : 
    1249          50 :         tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
    1250          50 :         if (tlsp->tls_priority == NULL) {
    1251           0 :                 talloc_free(tlsp);
    1252           0 :                 return NT_STATUS_NO_MEMORY;
    1253             :         }
    1254             : 
    1255          50 :         tlsp->tls_enabled = true;
    1256             : 
    1257          50 :         *_tlsp = tlsp;
    1258          50 :         return NT_STATUS_OK;
    1259             : }
    1260             : 
    1261             : struct tstream_tls_accept_state {
    1262             :         struct tstream_context *tls_stream;
    1263             : };
    1264             : 
    1265         399 : struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
    1266             :                                             struct tevent_context *ev,
    1267             :                                             struct tstream_context *plain_stream,
    1268             :                                             struct tstream_tls_params *tlsp,
    1269             :                                             const char *location)
    1270             : {
    1271             :         struct tevent_req *req;
    1272             :         struct tstream_tls_accept_state *state;
    1273             :         struct tstream_tls *tlss;
    1274             :         const char *error_pos;
    1275             :         int ret;
    1276             : 
    1277         399 :         req = tevent_req_create(mem_ctx, &state,
    1278             :                                 struct tstream_tls_accept_state);
    1279         399 :         if (req == NULL) {
    1280           0 :                 return NULL;
    1281             :         }
    1282             : 
    1283         399 :         state->tls_stream = tstream_context_create(state,
    1284             :                                                    &tstream_tls_ops,
    1285             :                                                    &tlss,
    1286             :                                                    struct tstream_tls,
    1287             :                                                    location);
    1288         399 :         if (tevent_req_nomem(state->tls_stream, req)) {
    1289           0 :                 return tevent_req_post(req, ev);
    1290             :         }
    1291         399 :         ZERO_STRUCTP(tlss);
    1292         399 :         talloc_set_destructor(tlss, tstream_tls_destructor);
    1293             : 
    1294         399 :         tlss->plain_stream = plain_stream;
    1295             : 
    1296         399 :         tlss->current_ev = ev;
    1297         399 :         tlss->retry_im = tevent_create_immediate(tlss);
    1298         399 :         if (tevent_req_nomem(tlss->retry_im, req)) {
    1299           0 :                 return tevent_req_post(req, ev);
    1300             :         }
    1301             : 
    1302         399 :         ret = gnutls_init(&tlss->tls_session, GNUTLS_SERVER);
    1303         399 :         if (ret != GNUTLS_E_SUCCESS) {
    1304           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1305           0 :                 tevent_req_error(req, EINVAL);
    1306           0 :                 return tevent_req_post(req, ev);
    1307             :         }
    1308             : 
    1309         399 :         ret = gnutls_set_default_priority(tlss->tls_session);
    1310         399 :         if (ret != GNUTLS_E_SUCCESS) {
    1311           0 :                 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
    1312             :                         __location__, gnutls_strerror(ret));
    1313           0 :                 tevent_req_error(req, EINVAL);
    1314           0 :                 return tevent_req_post(req, ev);
    1315             :         }
    1316             : 
    1317         399 :         if (strlen(tlsp->tls_priority) > 0) {
    1318         399 :                 ret = gnutls_priority_set_direct(tlss->tls_session,
    1319             :                                                  tlsp->tls_priority,
    1320             :                                                  &error_pos);
    1321         399 :                 if (ret != GNUTLS_E_SUCCESS) {
    1322           0 :                         DEBUG(0,("TLS %s - %s.  Check 'tls priority' option at '%s'\n",
    1323             :                                  __location__, gnutls_strerror(ret), error_pos));
    1324           0 :                         tevent_req_error(req, EINVAL);
    1325           0 :                         return tevent_req_post(req, ev);
    1326             :                 }
    1327             :         }
    1328             : 
    1329         399 :         ret = gnutls_credentials_set(tlss->tls_session, GNUTLS_CRD_CERTIFICATE,
    1330         399 :                                      tlsp->x509_cred);
    1331         399 :         if (ret != GNUTLS_E_SUCCESS) {
    1332           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1333           0 :                 tevent_req_error(req, EINVAL);
    1334           0 :                 return tevent_req_post(req, ev);
    1335             :         }
    1336             : 
    1337         399 :         gnutls_certificate_server_set_request(tlss->tls_session,
    1338             :                                               GNUTLS_CERT_REQUEST);
    1339         399 :         gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS);
    1340             : 
    1341         399 :         gnutls_transport_set_ptr(tlss->tls_session,
    1342         399 :                                  (gnutls_transport_ptr_t)state->tls_stream);
    1343         399 :         gnutls_transport_set_pull_function(tlss->tls_session,
    1344             :                                            (gnutls_pull_func)tstream_tls_pull_function);
    1345         399 :         gnutls_transport_set_push_function(tlss->tls_session,
    1346             :                                            (gnutls_push_func)tstream_tls_push_function);
    1347             : 
    1348         399 :         tlss->handshake.req = req;
    1349         399 :         tstream_tls_retry_handshake(state->tls_stream);
    1350         399 :         if (!tevent_req_is_in_progress(req)) {
    1351           0 :                 return tevent_req_post(req, ev);
    1352             :         }
    1353             : 
    1354         399 :         return req;
    1355             : }
    1356             : 
    1357       10692 : static void tstream_tls_retry_handshake(struct tstream_context *stream)
    1358             : {
    1359             :         struct tstream_tls *tlss =
    1360       10692 :                 tstream_context_data(stream,
    1361             :                 struct tstream_tls);
    1362       10692 :         struct tevent_req *req = tlss->handshake.req;
    1363             :         int ret;
    1364             : 
    1365       10692 :         if (tlss->error != 0) {
    1366          14 :                 tevent_req_error(req, tlss->error);
    1367          14 :                 return;
    1368             :         }
    1369             : 
    1370       10678 :         ret = gnutls_handshake(tlss->tls_session);
    1371       10678 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
    1372        9895 :                 return;
    1373             :         }
    1374             : 
    1375         783 :         tlss->handshake.req = NULL;
    1376             : 
    1377         783 :         if (gnutls_error_is_fatal(ret) != 0) {
    1378           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1379           0 :                 tlss->error = EIO;
    1380           0 :                 tevent_req_error(req, tlss->error);
    1381           0 :                 return;
    1382             :         }
    1383             : 
    1384         783 :         if (ret != GNUTLS_E_SUCCESS) {
    1385           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1386           0 :                 tlss->error = EIO;
    1387           0 :                 tevent_req_error(req, tlss->error);
    1388           0 :                 return;
    1389             :         }
    1390             : 
    1391         783 :         if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
    1392          30 :                 unsigned int status = UINT32_MAX;
    1393          30 :                 bool ip = true;
    1394          30 :                 const char *hostname = NULL;
    1395             : 
    1396          30 :                 if (tlss->peer_name != NULL) {
    1397          30 :                         ip = is_ipaddress(tlss->peer_name);
    1398             :                 }
    1399             : 
    1400          30 :                 if (!ip) {
    1401          20 :                         hostname = tlss->peer_name;
    1402             :                 }
    1403             : 
    1404          30 :                 if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
    1405           9 :                         hostname = NULL;
    1406             :                 }
    1407             : 
    1408          30 :                 if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
    1409          12 :                         if (hostname == NULL) {
    1410           4 :                                 DEBUG(1,("TLS %s - no hostname available for "
    1411             :                                          "verify_peer[%s] and peer_name[%s]\n",
    1412             :                                          __location__,
    1413             :                                          tls_verify_peer_string(tlss->verify_peer),
    1414             :                                          tlss->peer_name));
    1415           4 :                                 tlss->error = EINVAL;
    1416           4 :                                 tevent_req_error(req, tlss->error);
    1417          11 :                                 return;
    1418             :                         }
    1419             :                 }
    1420             : 
    1421          26 :                 ret = gnutls_certificate_verify_peers3(tlss->tls_session,
    1422             :                                                        hostname,
    1423             :                                                        &status);
    1424          26 :                 if (ret != GNUTLS_E_SUCCESS) {
    1425           0 :                         DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1426           0 :                         tlss->error = EIO;
    1427           0 :                         tevent_req_error(req, tlss->error);
    1428           0 :                         return;
    1429             :                 }
    1430             : 
    1431          26 :                 if (status != 0) {
    1432           7 :                         DEBUG(1,("TLS %s - check failed for "
    1433             :                                  "verify_peer[%s] and peer_name[%s] "
    1434             :                                  "status 0x%x (%s%s%s%s%s%s%s%s)\n",
    1435             :                                  __location__,
    1436             :                                  tls_verify_peer_string(tlss->verify_peer),
    1437             :                                  tlss->peer_name,
    1438             :                                  status,
    1439             :                                  status & GNUTLS_CERT_INVALID ? "invalid " : "",
    1440             :                                  status & GNUTLS_CERT_REVOKED ? "revoked " : "",
    1441             :                                  status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
    1442             :                                         "signer_not_found " : "",
    1443             :                                  status & GNUTLS_CERT_SIGNER_NOT_CA ?
    1444             :                                         "signer_not_ca " : "",
    1445             :                                  status & GNUTLS_CERT_INSECURE_ALGORITHM ?
    1446             :                                         "insecure_algorithm " : "",
    1447             :                                  status & GNUTLS_CERT_NOT_ACTIVATED ?
    1448             :                                         "not_activated " : "",
    1449             :                                  status & GNUTLS_CERT_EXPIRED ?
    1450             :                                         "expired " : "",
    1451             :                                  status & GNUTLS_CERT_UNEXPECTED_OWNER ?
    1452             :                                         "unexptected_owner " : ""));
    1453           7 :                         tlss->error = EINVAL;
    1454           7 :                         tevent_req_error(req, tlss->error);
    1455           7 :                         return;
    1456             :                 }
    1457             :         }
    1458             : 
    1459         772 :         tevent_req_done(req);
    1460             : }
    1461             : 
    1462         399 : int tstream_tls_accept_recv(struct tevent_req *req,
    1463             :                             int *perrno,
    1464             :                             TALLOC_CTX *mem_ctx,
    1465             :                             struct tstream_context **tls_stream)
    1466             : {
    1467             :         struct tstream_tls_accept_state *state =
    1468         399 :                 tevent_req_data(req,
    1469             :                 struct tstream_tls_accept_state);
    1470             : 
    1471         399 :         if (tevent_req_is_unix_error(req, perrno)) {
    1472          13 :                 tevent_req_received(req);
    1473          13 :                 return -1;
    1474             :         }
    1475             : 
    1476         386 :         *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
    1477         386 :         tevent_req_received(req);
    1478         386 :         return 0;
    1479             : }

Generated by: LCOV version 1.14