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