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