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