LCOV - code coverage report
Current view: top level - source4/lib/tls - tls_tstream.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 482 665 72.5 %
Date: 2021-09-23 10:06:22 Functions: 28 30 93.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Copyright (C) Stefan Metzmacher 2010
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "system/network.h"
      22             : #include "system/filesys.h"
      23             : #include "system/time.h"
      24             : #include "../util/tevent_unix.h"
      25             : #include "../lib/tsocket/tsocket.h"
      26             : #include "../lib/tsocket/tsocket_internal.h"
      27             : #include "../lib/util/util_net.h"
      28             : #include "lib/tls/tls.h"
      29             : 
      30             : #include <gnutls/gnutls.h>
      31             : #include <gnutls/x509.h>
      32             : 
      33             : #define DH_BITS 2048
      34             : 
      35          17 : const char *tls_verify_peer_string(enum tls_verify_peer_state verify_peer)
      36             : {
      37          17 :         switch (verify_peer) {
      38           0 :         case TLS_VERIFY_PEER_NO_CHECK:
      39           0 :                 return TLS_VERIFY_PEER_NO_CHECK_STRING;
      40             : 
      41           0 :         case TLS_VERIFY_PEER_CA_ONLY:
      42           0 :                 return TLS_VERIFY_PEER_CA_ONLY_STRING;
      43             : 
      44           3 :         case TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE:
      45           3 :                 return TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE_STRING;
      46             : 
      47           6 :         case TLS_VERIFY_PEER_CA_AND_NAME:
      48           6 :                 return TLS_VERIFY_PEER_CA_AND_NAME_STRING;
      49             : 
      50           8 :         case TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE:
      51           8 :                 return TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE_STRING;
      52             :         }
      53             : 
      54           0 :         return "unknown tls_verify_peer_state";
      55             : }
      56             : 
      57             : static const struct tstream_context_ops tstream_tls_ops;
      58             : 
      59             : struct tstream_tls {
      60             :         struct tstream_context *plain_stream;
      61             :         int error;
      62             : 
      63             :         gnutls_session_t tls_session;
      64             : 
      65             :         enum tls_verify_peer_state verify_peer;
      66             :         const char *peer_name;
      67             : 
      68             :         struct tevent_context *current_ev;
      69             : 
      70             :         struct tevent_immediate *retry_im;
      71             : 
      72             :         struct {
      73             :                 uint8_t *buf;
      74             :                 off_t ofs;
      75             :                 struct iovec iov;
      76             :                 struct tevent_req *subreq;
      77             :                 struct tevent_immediate *im;
      78             :         } push;
      79             : 
      80             :         struct {
      81             :                 uint8_t *buf;
      82             :                 struct iovec iov;
      83             :                 struct tevent_req *subreq;
      84             :         } pull;
      85             : 
      86             :         struct {
      87             :                 struct tevent_req *req;
      88             :         } handshake;
      89             : 
      90             :         struct {
      91             :                 off_t ofs;
      92             :                 size_t left;
      93             :                 uint8_t buffer[1024];
      94             :                 struct tevent_req *req;
      95             :         } write;
      96             : 
      97             :         struct {
      98             :                 off_t ofs;
      99             :                 size_t left;
     100             :                 uint8_t buffer[1024];
     101             :                 struct tevent_req *req;
     102             :         } read;
     103             : 
     104             :         struct {
     105             :                 struct tevent_req *req;
     106             :         } disconnect;
     107             : };
     108             : 
     109             : static void tstream_tls_retry_handshake(struct tstream_context *stream);
     110             : static void tstream_tls_retry_read(struct tstream_context *stream);
     111             : static void tstream_tls_retry_write(struct tstream_context *stream);
     112             : static void tstream_tls_retry_disconnect(struct tstream_context *stream);
     113             : static void tstream_tls_retry_trigger(struct tevent_context *ctx,
     114             :                                       struct tevent_immediate *im,
     115             :                                       void *private_data);
     116             : 
     117     3173313 : static void tstream_tls_retry(struct tstream_context *stream, bool deferred)
     118             : {
     119             : 
     120     3168174 :         struct tstream_tls *tlss =
     121     3173313 :                 tstream_context_data(stream,
     122             :                 struct tstream_tls);
     123             : 
     124     3173313 :         if (tlss->disconnect.req) {
     125           0 :                 tstream_tls_retry_disconnect(stream);
     126           0 :                 return;
     127             :         }
     128             : 
     129     3173313 :         if (tlss->handshake.req) {
     130        4458 :                 tstream_tls_retry_handshake(stream);
     131        4458 :                 return;
     132             :         }
     133             : 
     134     3168855 :         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     3168855 :         if (tlss->write.req) {
     141       24620 :                 tstream_tls_retry_write(stream);
     142       24620 :                 return;
     143             :         }
     144             : 
     145     3144235 :         if (tlss->read.req) {
     146     3144235 :                 tstream_tls_retry_read(stream);
     147     3144235 :                 return;
     148             :         }
     149             : }
     150             : 
     151           0 : static void tstream_tls_retry_trigger(struct tevent_context *ctx,
     152             :                                       struct tevent_immediate *im,
     153             :                                       void *private_data)
     154             : {
     155           0 :         struct tstream_context *stream =
     156           0 :                 talloc_get_type_abort(private_data,
     157             :                 struct tstream_context);
     158             : 
     159           0 :         tstream_tls_retry(stream, true);
     160           0 : }
     161             : 
     162             : static void tstream_tls_push_trigger_write(struct tevent_context *ev,
     163             :                                            struct tevent_immediate *im,
     164             :                                            void *private_data);
     165             : 
     166     1615067 : static ssize_t tstream_tls_push_function(gnutls_transport_ptr_t ptr,
     167             :                                          const void *buf, size_t size)
     168             : {
     169     1614693 :         struct tstream_context *stream =
     170         374 :                 talloc_get_type_abort(ptr,
     171             :                 struct tstream_context);
     172     1614693 :         struct tstream_tls *tlss =
     173     1615067 :                 tstream_context_data(stream,
     174             :                 struct tstream_tls);
     175             :         uint8_t *nbuf;
     176             :         size_t len;
     177             : 
     178     1615067 :         if (tlss->error != 0) {
     179           0 :                 errno = tlss->error;
     180           0 :                 return -1;
     181             :         }
     182             : 
     183     1615067 :         if (tlss->push.subreq) {
     184           0 :                 errno = EAGAIN;
     185           0 :                 return -1;
     186             :         }
     187             : 
     188     1615067 :         len = MIN(size, UINT16_MAX - tlss->push.ofs);
     189             : 
     190     1615067 :         if (len == 0) {
     191       24620 :                 errno = EAGAIN;
     192       24620 :                 return -1;
     193             :         }
     194             : 
     195     1590447 :         nbuf = talloc_realloc(tlss, tlss->push.buf,
     196             :                               uint8_t, tlss->push.ofs + len);
     197     1590447 :         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     1590447 :         tlss->push.buf = nbuf;
     206             : 
     207     1590447 :         memcpy(tlss->push.buf + tlss->push.ofs, buf, len);
     208             : 
     209     1590447 :         if (tlss->push.im == NULL) {
     210         340 :                 tlss->push.im = tevent_create_immediate(tlss);
     211         340 :                 if (tlss->push.im == NULL) {
     212           0 :                         errno = ENOMEM;
     213           0 :                         return -1;
     214             :                 }
     215             :         }
     216             : 
     217     1590447 :         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       33007 :                 tevent_schedule_immediate(tlss->push.im,
     231             :                                           tlss->current_ev,
     232             :                                           tstream_tls_push_trigger_write,
     233             :                                           stream);
     234             :         }
     235             : 
     236     1590447 :         tlss->push.ofs += len;
     237     1590447 :         return len;
     238             : }
     239             : 
     240             : static void tstream_tls_push_done(struct tevent_req *subreq);
     241             : 
     242       33004 : static void tstream_tls_push_trigger_write(struct tevent_context *ev,
     243             :                                            struct tevent_immediate *im,
     244             :                                            void *private_data)
     245             : {
     246       32829 :         struct tstream_context *stream =
     247         175 :                 talloc_get_type_abort(private_data,
     248             :                 struct tstream_context);
     249       32829 :         struct tstream_tls *tlss =
     250       33004 :                 tstream_context_data(stream,
     251             :                 struct tstream_tls);
     252             :         struct tevent_req *subreq;
     253             : 
     254       33004 :         if (tlss->push.subreq) {
     255             :                 /* nothing todo */
     256           0 :                 return;
     257             :         }
     258             : 
     259       33004 :         tlss->push.iov.iov_base = (char *)tlss->push.buf;
     260       33004 :         tlss->push.iov.iov_len = tlss->push.ofs;
     261             : 
     262       33004 :         subreq = tstream_writev_send(tlss,
     263             :                                      tlss->current_ev,
     264             :                                      tlss->plain_stream,
     265       33004 :                                      &tlss->push.iov, 1);
     266       33004 :         if (subreq == NULL) {
     267           0 :                 tlss->error = ENOMEM;
     268           0 :                 tstream_tls_retry(stream, false);
     269           0 :                 return;
     270             :         }
     271       33004 :         tevent_req_set_callback(subreq, tstream_tls_push_done, stream);
     272             : 
     273       33004 :         tlss->push.subreq = subreq;
     274             : }
     275             : 
     276       32996 : static void tstream_tls_push_done(struct tevent_req *subreq)
     277             : {
     278       32825 :         struct tstream_context *stream =
     279       32996 :                 tevent_req_callback_data(subreq,
     280             :                 struct tstream_context);
     281       32825 :         struct tstream_tls *tlss =
     282       32996 :                 tstream_context_data(stream,
     283             :                 struct tstream_tls);
     284             :         int ret;
     285             :         int sys_errno;
     286             : 
     287       32996 :         tlss->push.subreq = NULL;
     288       32996 :         ZERO_STRUCT(tlss->push.iov);
     289       32996 :         TALLOC_FREE(tlss->push.buf);
     290       32996 :         tlss->push.ofs = 0;
     291             : 
     292       32996 :         ret = tstream_writev_recv(subreq, &sys_errno);
     293       32996 :         TALLOC_FREE(subreq);
     294       32996 :         if (ret == -1) {
     295           0 :                 tlss->error = sys_errno;
     296           0 :                 tstream_tls_retry(stream, false);
     297           0 :                 return;
     298             :         }
     299             : 
     300       32996 :         tstream_tls_retry(stream, false);
     301             : }
     302             : 
     303             : static void tstream_tls_pull_done(struct tevent_req *subreq);
     304             : 
     305     6288841 : static ssize_t tstream_tls_pull_function(gnutls_transport_ptr_t ptr,
     306             :                                          void *buf, size_t size)
     307             : {
     308     6278756 :         struct tstream_context *stream =
     309       10085 :                 talloc_get_type_abort(ptr,
     310             :                 struct tstream_context);
     311     6278756 :         struct tstream_tls *tlss =
     312     6288841 :                 tstream_context_data(stream,
     313             :                 struct tstream_tls);
     314             :         struct tevent_req *subreq;
     315             :         size_t len;
     316             : 
     317     6288841 :         if (tlss->error != 0) {
     318           0 :                 errno = tlss->error;
     319           0 :                 return -1;
     320             :         }
     321             : 
     322     6288841 :         if (tlss->pull.subreq) {
     323        8376 :                 errno = EAGAIN;
     324        8376 :                 return -1;
     325             :         }
     326             : 
     327     6280465 :         if (tlss->pull.iov.iov_base) {
     328             :                 uint8_t *b;
     329             :                 size_t n;
     330             : 
     331     3140146 :                 b = (uint8_t *)tlss->pull.iov.iov_base;
     332             : 
     333     3140146 :                 n = MIN(tlss->pull.iov.iov_len, size);
     334     3140146 :                 memcpy(buf, b, n);
     335             : 
     336     3140146 :                 tlss->pull.iov.iov_len -= n;
     337     3140146 :                 b += n;
     338     3140146 :                 tlss->pull.iov.iov_base = (char *)b;
     339     3140146 :                 if (tlss->pull.iov.iov_len == 0) {
     340     3140146 :                         tlss->pull.iov.iov_base = NULL;
     341     3140146 :                         TALLOC_FREE(tlss->pull.buf);
     342             :                 }
     343             : 
     344     3140146 :                 return n;
     345             :         }
     346             : 
     347     3140319 :         if (size == 0) {
     348           0 :                 return 0;
     349             :         }
     350             : 
     351     3140319 :         len = MIN(size, UINT16_MAX);
     352             : 
     353     3140319 :         tlss->pull.buf = talloc_array(tlss, uint8_t, len);
     354     3140319 :         if (tlss->pull.buf == NULL) {
     355           0 :                 return -1;
     356             :         }
     357             : 
     358     3140319 :         tlss->pull.iov.iov_base = (char *)tlss->pull.buf;
     359     3140319 :         tlss->pull.iov.iov_len = len;
     360             : 
     361     3140319 :         subreq = tstream_readv_send(tlss,
     362             :                                     tlss->current_ev,
     363             :                                     tlss->plain_stream,
     364             :                                     &tlss->pull.iov, 1);
     365     3140319 :         if (subreq == NULL) {
     366           0 :                 errno = ENOMEM;
     367           0 :                 return -1;
     368             :         }
     369     3140319 :         tevent_req_set_callback(subreq, tstream_tls_pull_done, stream);
     370             : 
     371     3140319 :         tlss->pull.subreq = subreq;
     372     3140319 :         errno = EAGAIN;
     373     3140319 :         return -1;
     374             : }
     375             : 
     376     3140317 : static void tstream_tls_pull_done(struct tevent_req *subreq)
     377             : {
     378     3135349 :         struct tstream_context *stream =
     379     3140317 :                 tevent_req_callback_data(subreq,
     380             :                 struct tstream_context);
     381     3135349 :         struct tstream_tls *tlss =
     382     3140317 :                 tstream_context_data(stream,
     383             :                 struct tstream_tls);
     384             :         int ret;
     385             :         int sys_errno;
     386             : 
     387     3140317 :         tlss->pull.subreq = NULL;
     388             : 
     389     3140317 :         ret = tstream_readv_recv(subreq, &sys_errno);
     390     3140317 :         TALLOC_FREE(subreq);
     391     3140317 :         if (ret == -1) {
     392         171 :                 tlss->error = sys_errno;
     393         171 :                 tstream_tls_retry(stream, false);
     394         171 :                 return;
     395             :         }
     396             : 
     397     3140146 :         tstream_tls_retry(stream, false);
     398             : }
     399             : 
     400         341 : static int tstream_tls_destructor(struct tstream_tls *tlss)
     401             : {
     402         341 :         if (tlss->tls_session) {
     403         341 :                 gnutls_deinit(tlss->tls_session);
     404         341 :                 tlss->tls_session = NULL;
     405             :         }
     406             : 
     407         341 :         return 0;
     408             : }
     409             : 
     410           0 : static ssize_t tstream_tls_pending_bytes(struct tstream_context *stream)
     411             : {
     412           0 :         struct tstream_tls *tlss =
     413           0 :                 tstream_context_data(stream,
     414             :                 struct tstream_tls);
     415             :         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       33006 : 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       32677 :         struct tstream_tls *tlss =
     446       33006 :                 tstream_context_data(stream,
     447             :                 struct tstream_tls);
     448             :         struct tevent_req *req;
     449             :         struct tstream_tls_readv_state *state;
     450             : 
     451       33006 :         tlss->read.req = NULL;
     452       33006 :         tlss->current_ev = ev;
     453             : 
     454       33006 :         req = tevent_req_create(mem_ctx, &state,
     455             :                                 struct tstream_tls_readv_state);
     456       33006 :         if (req == NULL) {
     457           0 :                 return NULL;
     458             :         }
     459             : 
     460       33006 :         state->stream = stream;
     461       33006 :         state->ret = 0;
     462             : 
     463       33006 :         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       33006 :         state->vector = talloc_array(state, struct iovec, count);
     472       33006 :         if (tevent_req_nomem(state->vector, req)) {
     473           0 :                 return tevent_req_post(req, ev);
     474             :         }
     475       33006 :         memcpy(state->vector, vector, sizeof(struct iovec) * count);
     476       33006 :         state->count = count;
     477             : 
     478       33006 :         tstream_tls_readv_crypt_next(req);
     479       33006 :         if (!tevent_req_is_in_progress(req)) {
     480       19560 :                 return tevent_req_post(req, ev);
     481             :         }
     482             : 
     483       13446 :         return req;
     484             : }
     485             : 
     486     1665356 : static void tstream_tls_readv_crypt_next(struct tevent_req *req)
     487             : {
     488     1630637 :         struct tstream_tls_readv_state *state =
     489     1665356 :                 tevent_req_data(req,
     490             :                 struct tstream_tls_readv_state);
     491     1630637 :         struct tstream_tls *tlss =
     492     1665356 :                 tstream_context_data(state->stream,
     493             :                 struct tstream_tls);
     494             : 
     495             :         /*
     496             :          * copy the pending buffer first
     497             :          */
     498     4953378 :         while (tlss->read.left > 0 && state->count > 0) {
     499     1657385 :                 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
     500     1657385 :                 size_t len = MIN(tlss->read.left, state->vector[0].iov_len);
     501             : 
     502     1657385 :                 memcpy(base, tlss->read.buffer + tlss->read.ofs, len);
     503             : 
     504     1657385 :                 base += len;
     505     1657385 :                 state->vector[0].iov_base = (char *) base;
     506     1657385 :                 state->vector[0].iov_len -= len;
     507             : 
     508     1657385 :                 tlss->read.ofs += len;
     509     1657385 :                 tlss->read.left -= len;
     510             : 
     511     1657385 :                 if (state->vector[0].iov_len == 0) {
     512       32838 :                         state->vector += 1;
     513       32838 :                         state->count -= 1;
     514             :                 }
     515             : 
     516     1657385 :                 state->ret += len;
     517             :         }
     518             : 
     519     1665356 :         if (state->count == 0) {
     520       32838 :                 tevent_req_done(req);
     521       32838 :                 return;
     522             :         }
     523             : 
     524     1632518 :         tlss->read.req = req;
     525     1632518 :         tstream_tls_retry_read(state->stream);
     526             : }
     527             : 
     528     4776753 : static void tstream_tls_retry_read(struct tstream_context *stream)
     529             : {
     530     4737686 :         struct tstream_tls *tlss =
     531     4776753 :                 tstream_context_data(stream,
     532             :                 struct tstream_tls);
     533     4776753 :         struct tevent_req *req = tlss->read.req;
     534             :         int ret;
     535             : 
     536     4776753 :         if (tlss->error != 0) {
     537         166 :                 tevent_req_error(req, tlss->error);
     538         166 :                 return;
     539             :         }
     540             : 
     541     4776587 :         tlss->read.left = 0;
     542     4776587 :         tlss->read.ofs = 0;
     543             : 
     544     4815635 :         ret = gnutls_record_recv(tlss->tls_session,
     545     4776587 :                                  tlss->read.buffer,
     546             :                                  sizeof(tlss->read.buffer));
     547     4776587 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
     548     3144237 :                 return;
     549             :         }
     550             : 
     551     1632350 :         tlss->read.req = NULL;
     552             : 
     553     1632350 :         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     1632350 :         if (ret == 0) {
     561           0 :                 tlss->error = EPIPE;
     562           0 :                 tevent_req_error(req, tlss->error);
     563           0 :                 return;
     564             :         }
     565             : 
     566     1632350 :         tlss->read.left = ret;
     567     1632350 :         tstream_tls_readv_crypt_next(req);
     568             : }
     569             : 
     570       33004 : static int tstream_tls_readv_recv(struct tevent_req *req,
     571             :                                   int *perrno)
     572             : {
     573       32675 :         struct tstream_tls_readv_state *state =
     574       33004 :                 tevent_req_data(req,
     575             :                 struct tstream_tls_readv_state);
     576       32675 :         struct tstream_tls *tlss =
     577       33004 :                 tstream_context_data(state->stream,
     578             :                 struct tstream_tls);
     579             :         int ret;
     580             : 
     581       33004 :         tlss->read.req = NULL;
     582             : 
     583       33004 :         ret = tsocket_simple_int_recv(req, perrno);
     584       33004 :         if (ret == 0) {
     585       32838 :                 ret = state->ret;
     586             :         }
     587             : 
     588       33004 :         tevent_req_received(req);
     589       33004 :         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        7753 : 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        7640 :         struct tstream_tls *tlss =
     610        7753 :                 tstream_context_data(stream,
     611             :                 struct tstream_tls);
     612             :         struct tevent_req *req;
     613             :         struct tstream_tls_writev_state *state;
     614             : 
     615        7753 :         tlss->write.req = NULL;
     616        7753 :         tlss->current_ev = ev;
     617             : 
     618        7753 :         req = tevent_req_create(mem_ctx, &state,
     619             :                                 struct tstream_tls_writev_state);
     620        7753 :         if (req == NULL) {
     621           0 :                 return NULL;
     622             :         }
     623             : 
     624        7753 :         state->stream = stream;
     625        7753 :         state->ret = 0;
     626             : 
     627        7753 :         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        7753 :         state->vector = talloc_array(state, struct iovec, count);
     636        7753 :         if (tevent_req_nomem(state->vector, req)) {
     637           0 :                 return tevent_req_post(req, ev);
     638             :         }
     639        7753 :         memcpy(state->vector, vector, sizeof(struct iovec) * count);
     640        7753 :         state->count = count;
     641             : 
     642        7753 :         tstream_tls_writev_crypt_next(req);
     643        7753 :         if (!tevent_req_is_in_progress(req)) {
     644        7314 :                 return tevent_req_post(req, ev);
     645             :         }
     646             : 
     647         439 :         return req;
     648             : }
     649             : 
     650     1571571 : static void tstream_tls_writev_crypt_next(struct tevent_req *req)
     651             : {
     652     1571334 :         struct tstream_tls_writev_state *state =
     653     1571571 :                 tevent_req_data(req,
     654             :                 struct tstream_tls_writev_state);
     655     1571334 :         struct tstream_tls *tlss =
     656     1571571 :                 tstream_context_data(state->stream,
     657             :                 struct tstream_tls);
     658             : 
     659     1571571 :         tlss->write.left = sizeof(tlss->write.buffer);
     660     1571571 :         tlss->write.ofs = 0;
     661             : 
     662             :         /*
     663             :          * first fill our buffer
     664             :          */
     665     4715351 :         while (tlss->write.left > 0 && state->count > 0) {
     666     1572446 :                 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
     667     1572446 :                 size_t len = MIN(tlss->write.left, state->vector[0].iov_len);
     668             : 
     669     1572446 :                 memcpy(tlss->write.buffer + tlss->write.ofs, base, len);
     670             : 
     671     1572446 :                 base += len;
     672     1572446 :                 state->vector[0].iov_base = (char *) base;
     673     1572446 :                 state->vector[0].iov_len -= len;
     674             : 
     675     1572446 :                 tlss->write.ofs += len;
     676     1572446 :                 tlss->write.left -= len;
     677             : 
     678     1572446 :                 if (state->vector[0].iov_len == 0) {
     679       16413 :                         state->vector += 1;
     680       16413 :                         state->count -= 1;
     681             :                 }
     682             : 
     683     1572446 :                 state->ret += len;
     684             :         }
     685             : 
     686     1571571 :         if (tlss->write.ofs == 0) {
     687        7753 :                 tevent_req_done(req);
     688        7753 :                 return;
     689             :         }
     690             : 
     691     1563818 :         tlss->write.left = tlss->write.ofs;
     692     1563818 :         tlss->write.ofs = 0;
     693             : 
     694     1563818 :         tlss->write.req = req;
     695     1563818 :         tstream_tls_retry_write(state->stream);
     696             : }
     697             : 
     698     1588438 : static void tstream_tls_retry_write(struct tstream_context *stream)
     699             : {
     700     1588314 :         struct tstream_tls *tlss =
     701     1588438 :                 tstream_context_data(stream,
     702             :                 struct tstream_tls);
     703     1588438 :         struct tevent_req *req = tlss->write.req;
     704             :         int ret;
     705             : 
     706     1588438 :         if (tlss->error != 0) {
     707           0 :                 tevent_req_error(req, tlss->error);
     708           0 :                 return;
     709             :         }
     710             : 
     711     3176876 :         ret = gnutls_record_send(tlss->tls_session,
     712     1588438 :                                  tlss->write.buffer + tlss->write.ofs,
     713             :                                  tlss->write.left);
     714     1588438 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
     715       24620 :                 return;
     716             :         }
     717             : 
     718     1563818 :         tlss->write.req = NULL;
     719             : 
     720     1563818 :         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     1563818 :         if (ret == 0) {
     728           0 :                 tlss->error = EPIPE;
     729           0 :                 tevent_req_error(req, tlss->error);
     730           0 :                 return;
     731             :         }
     732             : 
     733     1563818 :         tlss->write.ofs += ret;
     734     1563818 :         tlss->write.left -= ret;
     735             : 
     736     1563818 :         if (tlss->write.left > 0) {
     737           0 :                 tlss->write.req = req;
     738           0 :                 tstream_tls_retry_write(stream);
     739           0 :                 return;
     740             :         }
     741             : 
     742     1563818 :         tstream_tls_writev_crypt_next(req);
     743             : }
     744             : 
     745        7753 : static int tstream_tls_writev_recv(struct tevent_req *req,
     746             :                                    int *perrno)
     747             : {
     748        7640 :         struct tstream_tls_writev_state *state =
     749        7753 :                 tevent_req_data(req,
     750             :                 struct tstream_tls_writev_state);
     751        7640 :         struct tstream_tls *tlss =
     752        7753 :                 tstream_context_data(state->stream,
     753             :                 struct tstream_tls);
     754             :         int ret;
     755             : 
     756        7753 :         tlss->write.req = NULL;
     757             : 
     758        7753 :         ret = tsocket_simple_int_recv(req, perrno);
     759        7753 :         if (ret == 0) {
     760        7753 :                 ret = state->ret;
     761             :         }
     762             : 
     763        7753 :         tevent_req_received(req);
     764        7753 :         return ret;
     765             : }
     766             : 
     767             : struct tstream_tls_disconnect_state {
     768             :         uint8_t _dummy;
     769             : };
     770             : 
     771         174 : static struct tevent_req *tstream_tls_disconnect_send(TALLOC_CTX *mem_ctx,
     772             :                                                 struct tevent_context *ev,
     773             :                                                 struct tstream_context *stream)
     774             : {
     775         151 :         struct tstream_tls *tlss =
     776         174 :                 tstream_context_data(stream,
     777             :                 struct tstream_tls);
     778             :         struct tevent_req *req;
     779             :         struct tstream_tls_disconnect_state *state;
     780             : 
     781         174 :         tlss->disconnect.req = NULL;
     782         174 :         tlss->current_ev = ev;
     783             : 
     784         174 :         req = tevent_req_create(mem_ctx, &state,
     785             :                                 struct tstream_tls_disconnect_state);
     786         174 :         if (req == NULL) {
     787           0 :                 return NULL;
     788             :         }
     789             : 
     790         174 :         if (tlss->error != 0) {
     791         166 :                 tevent_req_error(req, tlss->error);
     792         166 :                 return tevent_req_post(req, ev);
     793             :         }
     794             : 
     795           8 :         tlss->disconnect.req = req;
     796           8 :         tstream_tls_retry_disconnect(stream);
     797           8 :         if (!tevent_req_is_in_progress(req)) {
     798           8 :                 return tevent_req_post(req, ev);
     799             :         }
     800             : 
     801           0 :         return req;
     802             : }
     803             : 
     804           8 : static void tstream_tls_retry_disconnect(struct tstream_context *stream)
     805             : {
     806           4 :         struct tstream_tls *tlss =
     807           8 :                 tstream_context_data(stream,
     808             :                 struct tstream_tls);
     809           8 :         struct tevent_req *req = tlss->disconnect.req;
     810             :         int ret;
     811             : 
     812           8 :         if (tlss->error != 0) {
     813           0 :                 tevent_req_error(req, tlss->error);
     814           0 :                 return;
     815             :         }
     816             : 
     817           8 :         ret = gnutls_bye(tlss->tls_session, GNUTLS_SHUT_WR);
     818           8 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
     819           0 :                 return;
     820             :         }
     821             : 
     822           8 :         tlss->disconnect.req = NULL;
     823             : 
     824           8 :         if (gnutls_error_is_fatal(ret) != 0) {
     825           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
     826           0 :                 tlss->error = EIO;
     827           0 :                 tevent_req_error(req, tlss->error);
     828           0 :                 return;
     829             :         }
     830             : 
     831           8 :         if (ret != GNUTLS_E_SUCCESS) {
     832           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
     833           0 :                 tlss->error = EIO;
     834           0 :                 tevent_req_error(req, tlss->error);
     835           0 :                 return;
     836             :         }
     837             : 
     838           8 :         tevent_req_done(req);
     839             : }
     840             : 
     841         174 : static int tstream_tls_disconnect_recv(struct tevent_req *req,
     842             :                                        int *perrno)
     843             : {
     844             :         int ret;
     845             : 
     846         174 :         ret = tsocket_simple_int_recv(req, perrno);
     847             : 
     848         174 :         tevent_req_received(req);
     849         174 :         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       11651 : static int tstream_tls_params_destructor(struct tstream_tls_params *tlsp)
     877             : {
     878       11651 :         if (tlsp->x509_cred) {
     879       11651 :                 gnutls_certificate_free_credentials(tlsp->x509_cred);
     880       11651 :                 tlsp->x509_cred = NULL;
     881             :         }
     882       11651 :         if (tlsp->dh_params) {
     883       11484 :                 gnutls_dh_params_deinit(tlsp->dh_params);
     884       11484 :                 tlsp->dh_params = NULL;
     885             :         }
     886             : 
     887       11651 :         return 0;
     888             : }
     889             : 
     890         232 : bool tstream_tls_params_enabled(struct tstream_tls_params *tlsp)
     891             : {
     892         232 :         return tlsp->tls_enabled;
     893             : }
     894             : 
     895         167 : 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         167 :         tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
     907         167 :         NT_STATUS_HAVE_NO_MEMORY(tlsp);
     908             : 
     909         167 :         talloc_set_destructor(tlsp, tstream_tls_params_destructor);
     910             : 
     911         167 :         tlsp->verify_peer = verify_peer;
     912         167 :         if (peer_name != NULL) {
     913         167 :                 tlsp->peer_name = talloc_strdup(tlsp, peer_name);
     914         167 :                 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         167 :         ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
     927         167 :         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         167 :         if (ca_file && *ca_file && file_exist(ca_file)) {
     934         167 :                 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
     935             :                                                              ca_file,
     936             :                                                              GNUTLS_X509_FMT_PEM);
     937         315 :                 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         167 :         if (crl_file && *crl_file && file_exist(crl_file)) {
     953         131 :                 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
     954             :                                                            crl_file, 
     955             :                                                            GNUTLS_X509_FMT_PEM);
     956         258 :                 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          36 :         } 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         161 :         tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
     972         161 :         if (tlsp->tls_priority == NULL) {
     973           0 :                 talloc_free(tlsp);
     974           0 :                 return NT_STATUS_NO_MEMORY;
     975             :         }
     976             : 
     977         161 :         tlsp->tls_enabled = true;
     978             : 
     979         161 :         *_tlsp = tlsp;
     980         161 :         return NT_STATUS_OK;
     981             : }
     982             : 
     983             : struct tstream_tls_connect_state {
     984             :         struct tstream_context *tls_stream;
     985             : };
     986             : 
     987         161 : 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             : 
     999         161 :         req = tevent_req_create(mem_ctx, &state,
    1000             :                                 struct tstream_tls_connect_state);
    1001         161 :         if (req == NULL) {
    1002           0 :                 return NULL;
    1003             :         }
    1004             : 
    1005         161 :         state->tls_stream = tstream_context_create(state,
    1006             :                                                    &tstream_tls_ops,
    1007             :                                                    &tlss,
    1008             :                                                    struct tstream_tls,
    1009             :                                                    location);
    1010         161 :         if (tevent_req_nomem(state->tls_stream, req)) {
    1011           0 :                 return tevent_req_post(req, ev);
    1012             :         }
    1013         161 :         ZERO_STRUCTP(tlss);
    1014         161 :         talloc_set_destructor(tlss, tstream_tls_destructor);
    1015             : 
    1016         161 :         tlss->plain_stream = plain_stream;
    1017         161 :         tlss->verify_peer = tls_params->verify_peer;
    1018         161 :         if (tls_params->peer_name != NULL) {
    1019         161 :                 tlss->peer_name = talloc_strdup(tlss, tls_params->peer_name);
    1020         161 :                 if (tevent_req_nomem(tlss->peer_name, req)) {
    1021           0 :                         return tevent_req_post(req, ev);
    1022             :                 }
    1023             :         }
    1024             : 
    1025         161 :         tlss->current_ev = ev;
    1026         161 :         tlss->retry_im = tevent_create_immediate(tlss);
    1027         161 :         if (tevent_req_nomem(tlss->retry_im, req)) {
    1028           0 :                 return tevent_req_post(req, ev);
    1029             :         }
    1030             : 
    1031         161 :         ret = gnutls_init(&tlss->tls_session, GNUTLS_CLIENT);
    1032         161 :         if (ret != GNUTLS_E_SUCCESS) {
    1033           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1034           0 :                 tevent_req_error(req, EINVAL);
    1035           0 :                 return tevent_req_post(req, ev);
    1036             :         }
    1037             : 
    1038         161 :         ret = gnutls_set_default_priority(tlss->tls_session);
    1039         161 :         if (ret != GNUTLS_E_SUCCESS) {
    1040           0 :                 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
    1041             :                         __location__, gnutls_strerror(ret));
    1042           0 :                 tevent_req_error(req, EINVAL);
    1043           0 :                 return tevent_req_post(req, ev);
    1044             :         }
    1045             : 
    1046         161 :         if (strlen(tls_params->tls_priority) > 0) {
    1047         161 :                 ret = gnutls_priority_set_direct(tlss->tls_session,
    1048             :                                                  tls_params->tls_priority,
    1049             :                                                  &error_pos);
    1050         161 :                 if (ret != GNUTLS_E_SUCCESS) {
    1051           0 :                         DEBUG(0,("TLS %s - %s.  Check 'tls priority' option at '%s'\n",
    1052             :                                  __location__, gnutls_strerror(ret), error_pos));
    1053           0 :                         tevent_req_error(req, EINVAL);
    1054           0 :                         return tevent_req_post(req, ev);
    1055             :                 }
    1056             :         }
    1057             : 
    1058         161 :         ret = gnutls_credentials_set(tlss->tls_session,
    1059             :                                      GNUTLS_CRD_CERTIFICATE,
    1060         161 :                                      tls_params->x509_cred);
    1061         161 :         if (ret != GNUTLS_E_SUCCESS) {
    1062           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1063           0 :                 tevent_req_error(req, EINVAL);
    1064           0 :                 return tevent_req_post(req, ev);
    1065             :         }
    1066             : 
    1067         161 :         gnutls_transport_set_ptr(tlss->tls_session,
    1068         161 :                                  (gnutls_transport_ptr_t)state->tls_stream);
    1069         161 :         gnutls_transport_set_pull_function(tlss->tls_session,
    1070             :                                            (gnutls_pull_func)tstream_tls_pull_function);
    1071         161 :         gnutls_transport_set_push_function(tlss->tls_session,
    1072             :                                            (gnutls_push_func)tstream_tls_push_function);
    1073             : 
    1074         161 :         tlss->handshake.req = req;
    1075         161 :         tstream_tls_retry_handshake(state->tls_stream);
    1076         161 :         if (!tevent_req_is_in_progress(req)) {
    1077           0 :                 return tevent_req_post(req, ev);
    1078             :         }
    1079             : 
    1080         161 :         return req;
    1081             : }
    1082             : 
    1083         161 : int tstream_tls_connect_recv(struct tevent_req *req,
    1084             :                              int *perrno,
    1085             :                              TALLOC_CTX *mem_ctx,
    1086             :                              struct tstream_context **tls_stream)
    1087             : {
    1088         145 :         struct tstream_tls_connect_state *state =
    1089         161 :                 tevent_req_data(req,
    1090             :                 struct tstream_tls_connect_state);
    1091             : 
    1092         161 :         if (tevent_req_is_unix_error(req, perrno)) {
    1093          13 :                 tevent_req_received(req);
    1094          13 :                 return -1;
    1095             :         }
    1096             : 
    1097         148 :         *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
    1098         148 :         tevent_req_received(req);
    1099         148 :         return 0;
    1100             : }
    1101             : 
    1102             : /*
    1103             :   initialise global tls state
    1104             : */
    1105          58 : NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
    1106             :                                    const char *dns_host_name,
    1107             :                                    bool enabled,
    1108             :                                    const char *key_file,
    1109             :                                    const char *cert_file,
    1110             :                                    const char *ca_file,
    1111             :                                    const char *crl_file,
    1112             :                                    const char *dhp_file,
    1113             :                                    const char *tls_priority,
    1114             :                                    struct tstream_tls_params **_tlsp)
    1115             : {
    1116             :         struct tstream_tls_params *tlsp;
    1117             :         int ret;
    1118             :         struct stat st;
    1119             : 
    1120          58 :         if (!enabled || key_file == NULL || *key_file == 0) {
    1121           0 :                 tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
    1122           0 :                 NT_STATUS_HAVE_NO_MEMORY(tlsp);
    1123           0 :                 talloc_set_destructor(tlsp, tstream_tls_params_destructor);
    1124           0 :                 tlsp->tls_enabled = false;
    1125             : 
    1126           0 :                 *_tlsp = tlsp;
    1127           0 :                 return NT_STATUS_OK;
    1128             :         }
    1129             : 
    1130          58 :         tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
    1131          58 :         NT_STATUS_HAVE_NO_MEMORY(tlsp);
    1132             : 
    1133          58 :         talloc_set_destructor(tlsp, tstream_tls_params_destructor);
    1134             : 
    1135          58 :         if (!file_exist(ca_file)) {
    1136          29 :                 tls_cert_generate(tlsp, dns_host_name,
    1137             :                                   key_file, cert_file, ca_file);
    1138             :         }
    1139             : 
    1140         100 :         if (file_exist(key_file) &&
    1141          58 :             !file_check_permissions(key_file, geteuid(), 0600, &st))
    1142             :         {
    1143           0 :                 DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
    1144             :                           "owner uid %u should be %u, mode 0%o should be 0%o\n"
    1145             :                           "This is known as CVE-2013-4476.\n"
    1146             :                           "Removing all tls .pem files will cause an "
    1147             :                           "auto-regeneration with the correct permissions.\n",
    1148             :                           key_file,
    1149             :                           (unsigned int)st.st_uid, geteuid(),
    1150             :                           (unsigned int)(st.st_mode & 0777), 0600));
    1151           0 :                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1152             :         }
    1153             : 
    1154          58 :         ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
    1155          58 :         if (ret != GNUTLS_E_SUCCESS) {
    1156           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1157           0 :                 talloc_free(tlsp);
    1158           0 :                 return NT_STATUS_NO_MEMORY;
    1159             :         }
    1160             : 
    1161          58 :         if (ca_file && *ca_file) {
    1162          58 :                 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
    1163             :                                                              ca_file,
    1164             :                                                              GNUTLS_X509_FMT_PEM);
    1165          58 :                 if (ret < 0) {
    1166           0 :                         DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
    1167             :                                  ca_file, gnutls_strerror(ret)));
    1168           0 :                         talloc_free(tlsp);
    1169           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1170             :                 }
    1171             :         }
    1172             : 
    1173          58 :         if (crl_file && *crl_file) {
    1174          27 :                 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
    1175             :                                                            crl_file, 
    1176             :                                                            GNUTLS_X509_FMT_PEM);
    1177          27 :                 if (ret < 0) {
    1178           0 :                         DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
    1179             :                                  crl_file, gnutls_strerror(ret)));
    1180           0 :                         talloc_free(tlsp);
    1181           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1182             :                 }
    1183             :         }
    1184             : 
    1185          58 :         ret = gnutls_certificate_set_x509_key_file(tlsp->x509_cred,
    1186             :                                                    cert_file, key_file,
    1187             :                                                    GNUTLS_X509_FMT_PEM);
    1188          58 :         if (ret != GNUTLS_E_SUCCESS) {
    1189           0 :                 DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
    1190             :                          cert_file, key_file, gnutls_strerror(ret)));
    1191           0 :                 talloc_free(tlsp);
    1192           0 :                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1193             :         }
    1194             : 
    1195          58 :         ret = gnutls_dh_params_init(&tlsp->dh_params);
    1196          58 :         if (ret != GNUTLS_E_SUCCESS) {
    1197           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1198           0 :                 talloc_free(tlsp);
    1199           0 :                 return NT_STATUS_NO_MEMORY;
    1200             :         }
    1201             : 
    1202         116 :         if (dhp_file && *dhp_file) {
    1203             :                 gnutls_datum_t dhparms;
    1204             :                 size_t size;
    1205             : 
    1206          58 :                 dhparms.data = (uint8_t *)file_load(dhp_file, &size, 0, tlsp);
    1207             : 
    1208          58 :                 if (!dhparms.data) {
    1209           0 :                         DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
    1210             :                                  dhp_file, errno, strerror(errno)));
    1211           0 :                         talloc_free(tlsp);
    1212           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1213             :                 }
    1214          58 :                 dhparms.size = size;
    1215             : 
    1216          58 :                 ret = gnutls_dh_params_import_pkcs3(tlsp->dh_params,
    1217             :                                                     &dhparms,
    1218             :                                                     GNUTLS_X509_FMT_PEM);
    1219          58 :                 if (ret != GNUTLS_E_SUCCESS) {
    1220           0 :                         DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
    1221             :                                  dhp_file, gnutls_strerror(ret)));
    1222           0 :                         talloc_free(tlsp);
    1223           0 :                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
    1224             :                 }
    1225             :         } else {
    1226           0 :                 ret = gnutls_dh_params_generate2(tlsp->dh_params, DH_BITS);
    1227           0 :                 if (ret != GNUTLS_E_SUCCESS) {
    1228           0 :                         DEBUG(0,("TLS failed to generate dh_params - %s\n",
    1229             :                                  gnutls_strerror(ret)));
    1230           0 :                         talloc_free(tlsp);
    1231           0 :                         return NT_STATUS_INTERNAL_ERROR;
    1232             :                 }
    1233             :         }
    1234             : 
    1235          58 :         gnutls_certificate_set_dh_params(tlsp->x509_cred, tlsp->dh_params);
    1236             : 
    1237          58 :         tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
    1238          58 :         if (tlsp->tls_priority == NULL) {
    1239           0 :                 talloc_free(tlsp);
    1240           0 :                 return NT_STATUS_NO_MEMORY;
    1241             :         }
    1242             : 
    1243          58 :         tlsp->tls_enabled = true;
    1244             : 
    1245          58 :         *_tlsp = tlsp;
    1246          58 :         return NT_STATUS_OK;
    1247             : }
    1248             : 
    1249             : struct tstream_tls_accept_state {
    1250             :         struct tstream_context *tls_stream;
    1251             : };
    1252             : 
    1253         180 : struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
    1254             :                                             struct tevent_context *ev,
    1255             :                                             struct tstream_context *plain_stream,
    1256             :                                             struct tstream_tls_params *tlsp,
    1257             :                                             const char *location)
    1258             : {
    1259             :         struct tevent_req *req;
    1260             :         struct tstream_tls_accept_state *state;
    1261             :         struct tstream_tls *tlss;
    1262             :         const char *error_pos;
    1263             :         int ret;
    1264             : 
    1265         180 :         req = tevent_req_create(mem_ctx, &state,
    1266             :                                 struct tstream_tls_accept_state);
    1267         180 :         if (req == NULL) {
    1268           0 :                 return NULL;
    1269             :         }
    1270             : 
    1271         180 :         state->tls_stream = tstream_context_create(state,
    1272             :                                                    &tstream_tls_ops,
    1273             :                                                    &tlss,
    1274             :                                                    struct tstream_tls,
    1275             :                                                    location);
    1276         180 :         if (tevent_req_nomem(state->tls_stream, req)) {
    1277           0 :                 return tevent_req_post(req, ev);
    1278             :         }
    1279         180 :         ZERO_STRUCTP(tlss);
    1280         180 :         talloc_set_destructor(tlss, tstream_tls_destructor);
    1281             : 
    1282         180 :         tlss->plain_stream = plain_stream;
    1283             : 
    1284         180 :         tlss->current_ev = ev;
    1285         180 :         tlss->retry_im = tevent_create_immediate(tlss);
    1286         180 :         if (tevent_req_nomem(tlss->retry_im, req)) {
    1287           0 :                 return tevent_req_post(req, ev);
    1288             :         }
    1289             : 
    1290         180 :         ret = gnutls_init(&tlss->tls_session, GNUTLS_SERVER);
    1291         180 :         if (ret != GNUTLS_E_SUCCESS) {
    1292           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1293           0 :                 tevent_req_error(req, EINVAL);
    1294           0 :                 return tevent_req_post(req, ev);
    1295             :         }
    1296             : 
    1297         180 :         ret = gnutls_set_default_priority(tlss->tls_session);
    1298         180 :         if (ret != GNUTLS_E_SUCCESS) {
    1299           0 :                 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
    1300             :                         __location__, gnutls_strerror(ret));
    1301           0 :                 tevent_req_error(req, EINVAL);
    1302           0 :                 return tevent_req_post(req, ev);
    1303             :         }
    1304             : 
    1305         180 :         if (strlen(tlsp->tls_priority) > 0) {
    1306         180 :                 ret = gnutls_priority_set_direct(tlss->tls_session,
    1307             :                                                  tlsp->tls_priority,
    1308             :                                                  &error_pos);
    1309         180 :                 if (ret != GNUTLS_E_SUCCESS) {
    1310           0 :                         DEBUG(0,("TLS %s - %s.  Check 'tls priority' option at '%s'\n",
    1311             :                                  __location__, gnutls_strerror(ret), error_pos));
    1312           0 :                         tevent_req_error(req, EINVAL);
    1313           0 :                         return tevent_req_post(req, ev);
    1314             :                 }
    1315             :         }
    1316             : 
    1317         180 :         ret = gnutls_credentials_set(tlss->tls_session, GNUTLS_CRD_CERTIFICATE,
    1318         180 :                                      tlsp->x509_cred);
    1319         180 :         if (ret != GNUTLS_E_SUCCESS) {
    1320           0 :                 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1321           0 :                 tevent_req_error(req, EINVAL);
    1322           0 :                 return tevent_req_post(req, ev);
    1323             :         }
    1324             : 
    1325         180 :         gnutls_certificate_server_set_request(tlss->tls_session,
    1326             :                                               GNUTLS_CERT_REQUEST);
    1327         180 :         gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS);
    1328             : 
    1329         180 :         gnutls_transport_set_ptr(tlss->tls_session,
    1330         180 :                                  (gnutls_transport_ptr_t)state->tls_stream);
    1331         180 :         gnutls_transport_set_pull_function(tlss->tls_session,
    1332             :                                            (gnutls_pull_func)tstream_tls_pull_function);
    1333         180 :         gnutls_transport_set_push_function(tlss->tls_session,
    1334             :                                            (gnutls_push_func)tstream_tls_push_function);
    1335             : 
    1336         180 :         tlss->handshake.req = req;
    1337         180 :         tstream_tls_retry_handshake(state->tls_stream);
    1338         180 :         if (!tevent_req_is_in_progress(req)) {
    1339           0 :                 return tevent_req_post(req, ev);
    1340             :         }
    1341             : 
    1342         180 :         return req;
    1343             : }
    1344             : 
    1345        4799 : static void tstream_tls_retry_handshake(struct tstream_context *stream)
    1346             : {
    1347        4276 :         struct tstream_tls *tlss =
    1348        4799 :                 tstream_context_data(stream,
    1349             :                 struct tstream_tls);
    1350        4799 :         struct tevent_req *req = tlss->handshake.req;
    1351             :         int ret;
    1352             : 
    1353        4799 :         if (tlss->error != 0) {
    1354           5 :                 tevent_req_error(req, tlss->error);
    1355           5 :                 return;
    1356             :         }
    1357             : 
    1358        4794 :         ret = gnutls_handshake(tlss->tls_session);
    1359        4794 :         if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
    1360        4458 :                 return;
    1361             :         }
    1362             : 
    1363         336 :         tlss->handshake.req = NULL;
    1364             : 
    1365         336 :         if (gnutls_error_is_fatal(ret) != 0) {
    1366           1 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1367           1 :                 tlss->error = EIO;
    1368           1 :                 tevent_req_error(req, tlss->error);
    1369           1 :                 return;
    1370             :         }
    1371             : 
    1372         335 :         if (ret != GNUTLS_E_SUCCESS) {
    1373           0 :                 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1374           0 :                 tlss->error = EIO;
    1375           0 :                 tevent_req_error(req, tlss->error);
    1376           0 :                 return;
    1377             :         }
    1378             : 
    1379         335 :         if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
    1380          30 :                 unsigned int status = UINT32_MAX;
    1381          30 :                 bool ip = true;
    1382          30 :                 const char *hostname = NULL;
    1383             : 
    1384          30 :                 if (tlss->peer_name != NULL) {
    1385          30 :                         ip = is_ipaddress(tlss->peer_name);
    1386             :                 }
    1387             : 
    1388          30 :                 if (!ip) {
    1389          20 :                         hostname = tlss->peer_name;
    1390             :                 }
    1391             : 
    1392          30 :                 if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
    1393           9 :                         hostname = NULL;
    1394             :                 }
    1395             : 
    1396          30 :                 if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
    1397          12 :                         if (hostname == NULL) {
    1398           4 :                                 DEBUG(1,("TLS %s - no hostname available for "
    1399             :                                          "verify_peer[%s] and peer_name[%s]\n",
    1400             :                                          __location__,
    1401             :                                          tls_verify_peer_string(tlss->verify_peer),
    1402             :                                          tlss->peer_name));
    1403           4 :                                 tlss->error = EINVAL;
    1404           4 :                                 tevent_req_error(req, tlss->error);
    1405           6 :                                 return;
    1406             :                         }
    1407             :                 }
    1408             : 
    1409          26 :                 ret = gnutls_certificate_verify_peers3(tlss->tls_session,
    1410             :                                                        hostname,
    1411             :                                                        &status);
    1412          26 :                 if (ret != GNUTLS_E_SUCCESS) {
    1413           0 :                         DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
    1414           0 :                         tlss->error = EIO;
    1415           0 :                         tevent_req_error(req, tlss->error);
    1416           0 :                         return;
    1417             :                 }
    1418             : 
    1419          26 :                 if (status != 0) {
    1420           7 :                         DEBUG(1,("TLS %s - check failed for "
    1421             :                                  "verify_peer[%s] and peer_name[%s] "
    1422             :                                  "status 0x%x (%s%s%s%s%s%s%s%s)\n",
    1423             :                                  __location__,
    1424             :                                  tls_verify_peer_string(tlss->verify_peer),
    1425             :                                  tlss->peer_name,
    1426             :                                  status,
    1427             :                                  status & GNUTLS_CERT_INVALID ? "invalid " : "",
    1428             :                                  status & GNUTLS_CERT_REVOKED ? "revoked " : "",
    1429             :                                  status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
    1430             :                                         "signer_not_found " : "",
    1431             :                                  status & GNUTLS_CERT_SIGNER_NOT_CA ?
    1432             :                                         "signer_not_ca " : "",
    1433             :                                  status & GNUTLS_CERT_INSECURE_ALGORITHM ?
    1434             :                                         "insecure_algorithm " : "",
    1435             :                                  status & GNUTLS_CERT_NOT_ACTIVATED ?
    1436             :                                         "not_activated " : "",
    1437             :                                  status & GNUTLS_CERT_EXPIRED ?
    1438             :                                         "expired " : "",
    1439             :                                  status & GNUTLS_CERT_UNEXPECTED_OWNER ?
    1440             :                                         "unexptected_owner " : ""));
    1441           7 :                         tlss->error = EINVAL;
    1442           7 :                         tevent_req_error(req, tlss->error);
    1443           7 :                         return;
    1444             :                 }
    1445             :         }
    1446             : 
    1447         324 :         tevent_req_done(req);
    1448             : }
    1449             : 
    1450         180 : int tstream_tls_accept_recv(struct tevent_req *req,
    1451             :                             int *perrno,
    1452             :                             TALLOC_CTX *mem_ctx,
    1453             :                             struct tstream_context **tls_stream)
    1454             : {
    1455         154 :         struct tstream_tls_accept_state *state =
    1456         180 :                 tevent_req_data(req,
    1457             :                 struct tstream_tls_accept_state);
    1458             : 
    1459         180 :         if (tevent_req_is_unix_error(req, perrno)) {
    1460           4 :                 tevent_req_received(req);
    1461           4 :                 return -1;
    1462             :         }
    1463             : 
    1464         176 :         *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
    1465         176 :         tevent_req_received(req);
    1466         176 :         return 0;
    1467             : }

Generated by: LCOV version 1.13