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