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