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 3173313 : static void tstream_tls_retry(struct tstream_context *stream, bool deferred)
118 : {
119 :
120 3168174 : struct tstream_tls *tlss =
121 3173313 : tstream_context_data(stream,
122 : struct tstream_tls);
123 :
124 3173313 : if (tlss->disconnect.req) {
125 0 : tstream_tls_retry_disconnect(stream);
126 0 : return;
127 : }
128 :
129 3173313 : if (tlss->handshake.req) {
130 4458 : tstream_tls_retry_handshake(stream);
131 4458 : return;
132 : }
133 :
134 3168855 : 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 3168855 : if (tlss->write.req) {
141 24620 : tstream_tls_retry_write(stream);
142 24620 : return;
143 : }
144 :
145 3144235 : if (tlss->read.req) {
146 3144235 : tstream_tls_retry_read(stream);
147 3144235 : 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 0 : 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 1615067 : static ssize_t tstream_tls_push_function(gnutls_transport_ptr_t ptr,
167 : const void *buf, size_t size)
168 : {
169 1614693 : struct tstream_context *stream =
170 374 : talloc_get_type_abort(ptr,
171 : struct tstream_context);
172 1614693 : struct tstream_tls *tlss =
173 1615067 : tstream_context_data(stream,
174 : struct tstream_tls);
175 : uint8_t *nbuf;
176 : size_t len;
177 :
178 1615067 : if (tlss->error != 0) {
179 0 : errno = tlss->error;
180 0 : return -1;
181 : }
182 :
183 1615067 : if (tlss->push.subreq) {
184 0 : errno = EAGAIN;
185 0 : return -1;
186 : }
187 :
188 1615067 : len = MIN(size, UINT16_MAX - tlss->push.ofs);
189 :
190 1615067 : if (len == 0) {
191 24620 : errno = EAGAIN;
192 24620 : return -1;
193 : }
194 :
195 1590447 : nbuf = talloc_realloc(tlss, tlss->push.buf,
196 : uint8_t, tlss->push.ofs + len);
197 1590447 : 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 1590447 : tlss->push.buf = nbuf;
206 :
207 1590447 : memcpy(tlss->push.buf + tlss->push.ofs, buf, len);
208 :
209 1590447 : if (tlss->push.im == NULL) {
210 340 : tlss->push.im = tevent_create_immediate(tlss);
211 340 : if (tlss->push.im == NULL) {
212 0 : errno = ENOMEM;
213 0 : return -1;
214 : }
215 : }
216 :
217 1590447 : 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 33007 : tevent_schedule_immediate(tlss->push.im,
231 : tlss->current_ev,
232 : tstream_tls_push_trigger_write,
233 : stream);
234 : }
235 :
236 1590447 : tlss->push.ofs += len;
237 1590447 : return len;
238 : }
239 :
240 : static void tstream_tls_push_done(struct tevent_req *subreq);
241 :
242 33004 : static void tstream_tls_push_trigger_write(struct tevent_context *ev,
243 : struct tevent_immediate *im,
244 : void *private_data)
245 : {
246 32829 : struct tstream_context *stream =
247 175 : talloc_get_type_abort(private_data,
248 : struct tstream_context);
249 32829 : struct tstream_tls *tlss =
250 33004 : tstream_context_data(stream,
251 : struct tstream_tls);
252 : struct tevent_req *subreq;
253 :
254 33004 : if (tlss->push.subreq) {
255 : /* nothing todo */
256 0 : return;
257 : }
258 :
259 33004 : tlss->push.iov.iov_base = (char *)tlss->push.buf;
260 33004 : tlss->push.iov.iov_len = tlss->push.ofs;
261 :
262 33004 : subreq = tstream_writev_send(tlss,
263 : tlss->current_ev,
264 : tlss->plain_stream,
265 33004 : &tlss->push.iov, 1);
266 33004 : if (subreq == NULL) {
267 0 : tlss->error = ENOMEM;
268 0 : tstream_tls_retry(stream, false);
269 0 : return;
270 : }
271 33004 : tevent_req_set_callback(subreq, tstream_tls_push_done, stream);
272 :
273 33004 : tlss->push.subreq = subreq;
274 : }
275 :
276 32996 : static void tstream_tls_push_done(struct tevent_req *subreq)
277 : {
278 32825 : struct tstream_context *stream =
279 32996 : tevent_req_callback_data(subreq,
280 : struct tstream_context);
281 32825 : struct tstream_tls *tlss =
282 32996 : tstream_context_data(stream,
283 : struct tstream_tls);
284 : int ret;
285 : int sys_errno;
286 :
287 32996 : tlss->push.subreq = NULL;
288 32996 : ZERO_STRUCT(tlss->push.iov);
289 32996 : TALLOC_FREE(tlss->push.buf);
290 32996 : tlss->push.ofs = 0;
291 :
292 32996 : ret = tstream_writev_recv(subreq, &sys_errno);
293 32996 : TALLOC_FREE(subreq);
294 32996 : if (ret == -1) {
295 0 : tlss->error = sys_errno;
296 0 : tstream_tls_retry(stream, false);
297 0 : return;
298 : }
299 :
300 32996 : tstream_tls_retry(stream, false);
301 : }
302 :
303 : static void tstream_tls_pull_done(struct tevent_req *subreq);
304 :
305 6288841 : static ssize_t tstream_tls_pull_function(gnutls_transport_ptr_t ptr,
306 : void *buf, size_t size)
307 : {
308 6278756 : struct tstream_context *stream =
309 10085 : talloc_get_type_abort(ptr,
310 : struct tstream_context);
311 6278756 : struct tstream_tls *tlss =
312 6288841 : tstream_context_data(stream,
313 : struct tstream_tls);
314 : struct tevent_req *subreq;
315 : size_t len;
316 :
317 6288841 : if (tlss->error != 0) {
318 0 : errno = tlss->error;
319 0 : return -1;
320 : }
321 :
322 6288841 : if (tlss->pull.subreq) {
323 8376 : errno = EAGAIN;
324 8376 : return -1;
325 : }
326 :
327 6280465 : if (tlss->pull.iov.iov_base) {
328 : uint8_t *b;
329 : size_t n;
330 :
331 3140146 : b = (uint8_t *)tlss->pull.iov.iov_base;
332 :
333 3140146 : n = MIN(tlss->pull.iov.iov_len, size);
334 3140146 : memcpy(buf, b, n);
335 :
336 3140146 : tlss->pull.iov.iov_len -= n;
337 3140146 : b += n;
338 3140146 : tlss->pull.iov.iov_base = (char *)b;
339 3140146 : if (tlss->pull.iov.iov_len == 0) {
340 3140146 : tlss->pull.iov.iov_base = NULL;
341 3140146 : TALLOC_FREE(tlss->pull.buf);
342 : }
343 :
344 3140146 : return n;
345 : }
346 :
347 3140319 : if (size == 0) {
348 0 : return 0;
349 : }
350 :
351 3140319 : len = MIN(size, UINT16_MAX);
352 :
353 3140319 : tlss->pull.buf = talloc_array(tlss, uint8_t, len);
354 3140319 : if (tlss->pull.buf == NULL) {
355 0 : return -1;
356 : }
357 :
358 3140319 : tlss->pull.iov.iov_base = (char *)tlss->pull.buf;
359 3140319 : tlss->pull.iov.iov_len = len;
360 :
361 3140319 : subreq = tstream_readv_send(tlss,
362 : tlss->current_ev,
363 : tlss->plain_stream,
364 : &tlss->pull.iov, 1);
365 3140319 : if (subreq == NULL) {
366 0 : errno = ENOMEM;
367 0 : return -1;
368 : }
369 3140319 : tevent_req_set_callback(subreq, tstream_tls_pull_done, stream);
370 :
371 3140319 : tlss->pull.subreq = subreq;
372 3140319 : errno = EAGAIN;
373 3140319 : return -1;
374 : }
375 :
376 3140317 : static void tstream_tls_pull_done(struct tevent_req *subreq)
377 : {
378 3135349 : struct tstream_context *stream =
379 3140317 : tevent_req_callback_data(subreq,
380 : struct tstream_context);
381 3135349 : struct tstream_tls *tlss =
382 3140317 : tstream_context_data(stream,
383 : struct tstream_tls);
384 : int ret;
385 : int sys_errno;
386 :
387 3140317 : tlss->pull.subreq = NULL;
388 :
389 3140317 : ret = tstream_readv_recv(subreq, &sys_errno);
390 3140317 : TALLOC_FREE(subreq);
391 3140317 : if (ret == -1) {
392 171 : tlss->error = sys_errno;
393 171 : tstream_tls_retry(stream, false);
394 171 : return;
395 : }
396 :
397 3140146 : tstream_tls_retry(stream, false);
398 : }
399 :
400 341 : static int tstream_tls_destructor(struct tstream_tls *tlss)
401 : {
402 341 : if (tlss->tls_session) {
403 341 : gnutls_deinit(tlss->tls_session);
404 341 : tlss->tls_session = NULL;
405 : }
406 :
407 341 : return 0;
408 : }
409 :
410 0 : static ssize_t tstream_tls_pending_bytes(struct tstream_context *stream)
411 : {
412 0 : 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 33006 : 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 32677 : struct tstream_tls *tlss =
446 33006 : tstream_context_data(stream,
447 : struct tstream_tls);
448 : struct tevent_req *req;
449 : struct tstream_tls_readv_state *state;
450 :
451 33006 : tlss->read.req = NULL;
452 33006 : tlss->current_ev = ev;
453 :
454 33006 : req = tevent_req_create(mem_ctx, &state,
455 : struct tstream_tls_readv_state);
456 33006 : if (req == NULL) {
457 0 : return NULL;
458 : }
459 :
460 33006 : state->stream = stream;
461 33006 : state->ret = 0;
462 :
463 33006 : 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 33006 : state->vector = talloc_array(state, struct iovec, count);
472 33006 : if (tevent_req_nomem(state->vector, req)) {
473 0 : return tevent_req_post(req, ev);
474 : }
475 33006 : memcpy(state->vector, vector, sizeof(struct iovec) * count);
476 33006 : state->count = count;
477 :
478 33006 : tstream_tls_readv_crypt_next(req);
479 33006 : if (!tevent_req_is_in_progress(req)) {
480 19560 : return tevent_req_post(req, ev);
481 : }
482 :
483 13446 : return req;
484 : }
485 :
486 1665356 : static void tstream_tls_readv_crypt_next(struct tevent_req *req)
487 : {
488 1630637 : struct tstream_tls_readv_state *state =
489 1665356 : tevent_req_data(req,
490 : struct tstream_tls_readv_state);
491 1630637 : struct tstream_tls *tlss =
492 1665356 : tstream_context_data(state->stream,
493 : struct tstream_tls);
494 :
495 : /*
496 : * copy the pending buffer first
497 : */
498 4953378 : while (tlss->read.left > 0 && state->count > 0) {
499 1657385 : uint8_t *base = (uint8_t *)state->vector[0].iov_base;
500 1657385 : size_t len = MIN(tlss->read.left, state->vector[0].iov_len);
501 :
502 1657385 : memcpy(base, tlss->read.buffer + tlss->read.ofs, len);
503 :
504 1657385 : base += len;
505 1657385 : state->vector[0].iov_base = (char *) base;
506 1657385 : state->vector[0].iov_len -= len;
507 :
508 1657385 : tlss->read.ofs += len;
509 1657385 : tlss->read.left -= len;
510 :
511 1657385 : if (state->vector[0].iov_len == 0) {
512 32838 : state->vector += 1;
513 32838 : state->count -= 1;
514 : }
515 :
516 1657385 : state->ret += len;
517 : }
518 :
519 1665356 : if (state->count == 0) {
520 32838 : tevent_req_done(req);
521 32838 : return;
522 : }
523 :
524 1632518 : tlss->read.req = req;
525 1632518 : tstream_tls_retry_read(state->stream);
526 : }
527 :
528 4776753 : static void tstream_tls_retry_read(struct tstream_context *stream)
529 : {
530 4737686 : struct tstream_tls *tlss =
531 4776753 : tstream_context_data(stream,
532 : struct tstream_tls);
533 4776753 : struct tevent_req *req = tlss->read.req;
534 : int ret;
535 :
536 4776753 : if (tlss->error != 0) {
537 166 : tevent_req_error(req, tlss->error);
538 166 : return;
539 : }
540 :
541 4776587 : tlss->read.left = 0;
542 4776587 : tlss->read.ofs = 0;
543 :
544 4815635 : ret = gnutls_record_recv(tlss->tls_session,
545 4776587 : tlss->read.buffer,
546 : sizeof(tlss->read.buffer));
547 4776587 : if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
548 3144237 : return;
549 : }
550 :
551 1632350 : tlss->read.req = NULL;
552 :
553 1632350 : 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 1632350 : if (ret == 0) {
561 0 : tlss->error = EPIPE;
562 0 : tevent_req_error(req, tlss->error);
563 0 : return;
564 : }
565 :
566 1632350 : tlss->read.left = ret;
567 1632350 : tstream_tls_readv_crypt_next(req);
568 : }
569 :
570 33004 : static int tstream_tls_readv_recv(struct tevent_req *req,
571 : int *perrno)
572 : {
573 32675 : struct tstream_tls_readv_state *state =
574 33004 : tevent_req_data(req,
575 : struct tstream_tls_readv_state);
576 32675 : struct tstream_tls *tlss =
577 33004 : tstream_context_data(state->stream,
578 : struct tstream_tls);
579 : int ret;
580 :
581 33004 : tlss->read.req = NULL;
582 :
583 33004 : ret = tsocket_simple_int_recv(req, perrno);
584 33004 : if (ret == 0) {
585 32838 : ret = state->ret;
586 : }
587 :
588 33004 : tevent_req_received(req);
589 33004 : 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 7753 : 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 7640 : struct tstream_tls *tlss =
610 7753 : tstream_context_data(stream,
611 : struct tstream_tls);
612 : struct tevent_req *req;
613 : struct tstream_tls_writev_state *state;
614 :
615 7753 : tlss->write.req = NULL;
616 7753 : tlss->current_ev = ev;
617 :
618 7753 : req = tevent_req_create(mem_ctx, &state,
619 : struct tstream_tls_writev_state);
620 7753 : if (req == NULL) {
621 0 : return NULL;
622 : }
623 :
624 7753 : state->stream = stream;
625 7753 : state->ret = 0;
626 :
627 7753 : 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 7753 : state->vector = talloc_array(state, struct iovec, count);
636 7753 : if (tevent_req_nomem(state->vector, req)) {
637 0 : return tevent_req_post(req, ev);
638 : }
639 7753 : memcpy(state->vector, vector, sizeof(struct iovec) * count);
640 7753 : state->count = count;
641 :
642 7753 : tstream_tls_writev_crypt_next(req);
643 7753 : if (!tevent_req_is_in_progress(req)) {
644 7314 : return tevent_req_post(req, ev);
645 : }
646 :
647 439 : return req;
648 : }
649 :
650 1571571 : static void tstream_tls_writev_crypt_next(struct tevent_req *req)
651 : {
652 1571334 : struct tstream_tls_writev_state *state =
653 1571571 : tevent_req_data(req,
654 : struct tstream_tls_writev_state);
655 1571334 : struct tstream_tls *tlss =
656 1571571 : tstream_context_data(state->stream,
657 : struct tstream_tls);
658 :
659 1571571 : tlss->write.left = sizeof(tlss->write.buffer);
660 1571571 : tlss->write.ofs = 0;
661 :
662 : /*
663 : * first fill our buffer
664 : */
665 4715351 : while (tlss->write.left > 0 && state->count > 0) {
666 1572446 : uint8_t *base = (uint8_t *)state->vector[0].iov_base;
667 1572446 : size_t len = MIN(tlss->write.left, state->vector[0].iov_len);
668 :
669 1572446 : memcpy(tlss->write.buffer + tlss->write.ofs, base, len);
670 :
671 1572446 : base += len;
672 1572446 : state->vector[0].iov_base = (char *) base;
673 1572446 : state->vector[0].iov_len -= len;
674 :
675 1572446 : tlss->write.ofs += len;
676 1572446 : tlss->write.left -= len;
677 :
678 1572446 : if (state->vector[0].iov_len == 0) {
679 16413 : state->vector += 1;
680 16413 : state->count -= 1;
681 : }
682 :
683 1572446 : state->ret += len;
684 : }
685 :
686 1571571 : if (tlss->write.ofs == 0) {
687 7753 : tevent_req_done(req);
688 7753 : return;
689 : }
690 :
691 1563818 : tlss->write.left = tlss->write.ofs;
692 1563818 : tlss->write.ofs = 0;
693 :
694 1563818 : tlss->write.req = req;
695 1563818 : tstream_tls_retry_write(state->stream);
696 : }
697 :
698 1588438 : static void tstream_tls_retry_write(struct tstream_context *stream)
699 : {
700 1588314 : struct tstream_tls *tlss =
701 1588438 : tstream_context_data(stream,
702 : struct tstream_tls);
703 1588438 : struct tevent_req *req = tlss->write.req;
704 : int ret;
705 :
706 1588438 : if (tlss->error != 0) {
707 0 : tevent_req_error(req, tlss->error);
708 0 : return;
709 : }
710 :
711 3176876 : ret = gnutls_record_send(tlss->tls_session,
712 1588438 : tlss->write.buffer + tlss->write.ofs,
713 : tlss->write.left);
714 1588438 : if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
715 24620 : return;
716 : }
717 :
718 1563818 : tlss->write.req = NULL;
719 :
720 1563818 : 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 1563818 : if (ret == 0) {
728 0 : tlss->error = EPIPE;
729 0 : tevent_req_error(req, tlss->error);
730 0 : return;
731 : }
732 :
733 1563818 : tlss->write.ofs += ret;
734 1563818 : tlss->write.left -= ret;
735 :
736 1563818 : if (tlss->write.left > 0) {
737 0 : tlss->write.req = req;
738 0 : tstream_tls_retry_write(stream);
739 0 : return;
740 : }
741 :
742 1563818 : tstream_tls_writev_crypt_next(req);
743 : }
744 :
745 7753 : static int tstream_tls_writev_recv(struct tevent_req *req,
746 : int *perrno)
747 : {
748 7640 : struct tstream_tls_writev_state *state =
749 7753 : tevent_req_data(req,
750 : struct tstream_tls_writev_state);
751 7640 : struct tstream_tls *tlss =
752 7753 : tstream_context_data(state->stream,
753 : struct tstream_tls);
754 : int ret;
755 :
756 7753 : tlss->write.req = NULL;
757 :
758 7753 : ret = tsocket_simple_int_recv(req, perrno);
759 7753 : if (ret == 0) {
760 7753 : ret = state->ret;
761 : }
762 :
763 7753 : tevent_req_received(req);
764 7753 : return ret;
765 : }
766 :
767 : struct tstream_tls_disconnect_state {
768 : uint8_t _dummy;
769 : };
770 :
771 174 : static struct tevent_req *tstream_tls_disconnect_send(TALLOC_CTX *mem_ctx,
772 : struct tevent_context *ev,
773 : struct tstream_context *stream)
774 : {
775 151 : struct tstream_tls *tlss =
776 174 : tstream_context_data(stream,
777 : struct tstream_tls);
778 : struct tevent_req *req;
779 : struct tstream_tls_disconnect_state *state;
780 :
781 174 : tlss->disconnect.req = NULL;
782 174 : tlss->current_ev = ev;
783 :
784 174 : req = tevent_req_create(mem_ctx, &state,
785 : struct tstream_tls_disconnect_state);
786 174 : if (req == NULL) {
787 0 : return NULL;
788 : }
789 :
790 174 : if (tlss->error != 0) {
791 166 : tevent_req_error(req, tlss->error);
792 166 : return tevent_req_post(req, ev);
793 : }
794 :
795 8 : tlss->disconnect.req = req;
796 8 : tstream_tls_retry_disconnect(stream);
797 8 : if (!tevent_req_is_in_progress(req)) {
798 8 : return tevent_req_post(req, ev);
799 : }
800 :
801 0 : return req;
802 : }
803 :
804 8 : static void tstream_tls_retry_disconnect(struct tstream_context *stream)
805 : {
806 4 : struct tstream_tls *tlss =
807 8 : tstream_context_data(stream,
808 : struct tstream_tls);
809 8 : struct tevent_req *req = tlss->disconnect.req;
810 : int ret;
811 :
812 8 : if (tlss->error != 0) {
813 0 : tevent_req_error(req, tlss->error);
814 0 : return;
815 : }
816 :
817 8 : ret = gnutls_bye(tlss->tls_session, GNUTLS_SHUT_WR);
818 8 : if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
819 0 : return;
820 : }
821 :
822 8 : tlss->disconnect.req = NULL;
823 :
824 8 : 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 8 : 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 8 : tevent_req_done(req);
839 : }
840 :
841 174 : static int tstream_tls_disconnect_recv(struct tevent_req *req,
842 : int *perrno)
843 : {
844 : int ret;
845 :
846 174 : ret = tsocket_simple_int_recv(req, perrno);
847 :
848 174 : tevent_req_received(req);
849 174 : 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 11651 : static int tstream_tls_params_destructor(struct tstream_tls_params *tlsp)
877 : {
878 11651 : if (tlsp->x509_cred) {
879 11651 : gnutls_certificate_free_credentials(tlsp->x509_cred);
880 11651 : tlsp->x509_cred = NULL;
881 : }
882 11651 : if (tlsp->dh_params) {
883 11484 : gnutls_dh_params_deinit(tlsp->dh_params);
884 11484 : tlsp->dh_params = NULL;
885 : }
886 :
887 11651 : return 0;
888 : }
889 :
890 232 : bool tstream_tls_params_enabled(struct tstream_tls_params *tlsp)
891 : {
892 232 : return tlsp->tls_enabled;
893 : }
894 :
895 167 : 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 167 : tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
907 167 : NT_STATUS_HAVE_NO_MEMORY(tlsp);
908 :
909 167 : talloc_set_destructor(tlsp, tstream_tls_params_destructor);
910 :
911 167 : tlsp->verify_peer = verify_peer;
912 167 : if (peer_name != NULL) {
913 167 : tlsp->peer_name = talloc_strdup(tlsp, peer_name);
914 167 : 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 167 : ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
927 167 : 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 167 : if (ca_file && *ca_file && file_exist(ca_file)) {
934 167 : ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
935 : ca_file,
936 : GNUTLS_X509_FMT_PEM);
937 315 : 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 167 : if (crl_file && *crl_file && file_exist(crl_file)) {
953 131 : ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
954 : crl_file,
955 : GNUTLS_X509_FMT_PEM);
956 258 : 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 36 : } 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 161 : tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
972 161 : if (tlsp->tls_priority == NULL) {
973 0 : talloc_free(tlsp);
974 0 : return NT_STATUS_NO_MEMORY;
975 : }
976 :
977 161 : tlsp->tls_enabled = true;
978 :
979 161 : *_tlsp = tlsp;
980 161 : return NT_STATUS_OK;
981 : }
982 :
983 : struct tstream_tls_connect_state {
984 : struct tstream_context *tls_stream;
985 : };
986 :
987 161 : 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 :
999 161 : req = tevent_req_create(mem_ctx, &state,
1000 : struct tstream_tls_connect_state);
1001 161 : if (req == NULL) {
1002 0 : return NULL;
1003 : }
1004 :
1005 161 : state->tls_stream = tstream_context_create(state,
1006 : &tstream_tls_ops,
1007 : &tlss,
1008 : struct tstream_tls,
1009 : location);
1010 161 : if (tevent_req_nomem(state->tls_stream, req)) {
1011 0 : return tevent_req_post(req, ev);
1012 : }
1013 161 : ZERO_STRUCTP(tlss);
1014 161 : talloc_set_destructor(tlss, tstream_tls_destructor);
1015 :
1016 161 : tlss->plain_stream = plain_stream;
1017 161 : tlss->verify_peer = tls_params->verify_peer;
1018 161 : if (tls_params->peer_name != NULL) {
1019 161 : tlss->peer_name = talloc_strdup(tlss, tls_params->peer_name);
1020 161 : if (tevent_req_nomem(tlss->peer_name, req)) {
1021 0 : return tevent_req_post(req, ev);
1022 : }
1023 : }
1024 :
1025 161 : tlss->current_ev = ev;
1026 161 : tlss->retry_im = tevent_create_immediate(tlss);
1027 161 : if (tevent_req_nomem(tlss->retry_im, req)) {
1028 0 : return tevent_req_post(req, ev);
1029 : }
1030 :
1031 161 : ret = gnutls_init(&tlss->tls_session, GNUTLS_CLIENT);
1032 161 : if (ret != GNUTLS_E_SUCCESS) {
1033 0 : DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1034 0 : tevent_req_error(req, EINVAL);
1035 0 : return tevent_req_post(req, ev);
1036 : }
1037 :
1038 161 : ret = gnutls_set_default_priority(tlss->tls_session);
1039 161 : if (ret != GNUTLS_E_SUCCESS) {
1040 0 : DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
1041 : __location__, gnutls_strerror(ret));
1042 0 : tevent_req_error(req, EINVAL);
1043 0 : return tevent_req_post(req, ev);
1044 : }
1045 :
1046 161 : if (strlen(tls_params->tls_priority) > 0) {
1047 161 : ret = gnutls_priority_set_direct(tlss->tls_session,
1048 : tls_params->tls_priority,
1049 : &error_pos);
1050 161 : if (ret != GNUTLS_E_SUCCESS) {
1051 0 : DEBUG(0,("TLS %s - %s. Check 'tls priority' option at '%s'\n",
1052 : __location__, gnutls_strerror(ret), error_pos));
1053 0 : tevent_req_error(req, EINVAL);
1054 0 : return tevent_req_post(req, ev);
1055 : }
1056 : }
1057 :
1058 161 : ret = gnutls_credentials_set(tlss->tls_session,
1059 : GNUTLS_CRD_CERTIFICATE,
1060 161 : tls_params->x509_cred);
1061 161 : if (ret != GNUTLS_E_SUCCESS) {
1062 0 : DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1063 0 : tevent_req_error(req, EINVAL);
1064 0 : return tevent_req_post(req, ev);
1065 : }
1066 :
1067 161 : gnutls_transport_set_ptr(tlss->tls_session,
1068 161 : (gnutls_transport_ptr_t)state->tls_stream);
1069 161 : gnutls_transport_set_pull_function(tlss->tls_session,
1070 : (gnutls_pull_func)tstream_tls_pull_function);
1071 161 : gnutls_transport_set_push_function(tlss->tls_session,
1072 : (gnutls_push_func)tstream_tls_push_function);
1073 :
1074 161 : tlss->handshake.req = req;
1075 161 : tstream_tls_retry_handshake(state->tls_stream);
1076 161 : if (!tevent_req_is_in_progress(req)) {
1077 0 : return tevent_req_post(req, ev);
1078 : }
1079 :
1080 161 : return req;
1081 : }
1082 :
1083 161 : int tstream_tls_connect_recv(struct tevent_req *req,
1084 : int *perrno,
1085 : TALLOC_CTX *mem_ctx,
1086 : struct tstream_context **tls_stream)
1087 : {
1088 145 : struct tstream_tls_connect_state *state =
1089 161 : tevent_req_data(req,
1090 : struct tstream_tls_connect_state);
1091 :
1092 161 : if (tevent_req_is_unix_error(req, perrno)) {
1093 13 : tevent_req_received(req);
1094 13 : return -1;
1095 : }
1096 :
1097 148 : *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1098 148 : tevent_req_received(req);
1099 148 : return 0;
1100 : }
1101 :
1102 : /*
1103 : initialise global tls state
1104 : */
1105 58 : NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
1106 : const char *dns_host_name,
1107 : bool enabled,
1108 : const char *key_file,
1109 : const char *cert_file,
1110 : const char *ca_file,
1111 : const char *crl_file,
1112 : const char *dhp_file,
1113 : const char *tls_priority,
1114 : struct tstream_tls_params **_tlsp)
1115 : {
1116 : struct tstream_tls_params *tlsp;
1117 : int ret;
1118 : struct stat st;
1119 :
1120 58 : if (!enabled || key_file == NULL || *key_file == 0) {
1121 0 : tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1122 0 : NT_STATUS_HAVE_NO_MEMORY(tlsp);
1123 0 : talloc_set_destructor(tlsp, tstream_tls_params_destructor);
1124 0 : tlsp->tls_enabled = false;
1125 :
1126 0 : *_tlsp = tlsp;
1127 0 : return NT_STATUS_OK;
1128 : }
1129 :
1130 58 : tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1131 58 : NT_STATUS_HAVE_NO_MEMORY(tlsp);
1132 :
1133 58 : talloc_set_destructor(tlsp, tstream_tls_params_destructor);
1134 :
1135 58 : if (!file_exist(ca_file)) {
1136 29 : tls_cert_generate(tlsp, dns_host_name,
1137 : key_file, cert_file, ca_file);
1138 : }
1139 :
1140 100 : if (file_exist(key_file) &&
1141 58 : !file_check_permissions(key_file, geteuid(), 0600, &st))
1142 : {
1143 0 : DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
1144 : "owner uid %u should be %u, mode 0%o should be 0%o\n"
1145 : "This is known as CVE-2013-4476.\n"
1146 : "Removing all tls .pem files will cause an "
1147 : "auto-regeneration with the correct permissions.\n",
1148 : key_file,
1149 : (unsigned int)st.st_uid, geteuid(),
1150 : (unsigned int)(st.st_mode & 0777), 0600));
1151 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1152 : }
1153 :
1154 58 : ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
1155 58 : if (ret != GNUTLS_E_SUCCESS) {
1156 0 : DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1157 0 : talloc_free(tlsp);
1158 0 : return NT_STATUS_NO_MEMORY;
1159 : }
1160 :
1161 58 : if (ca_file && *ca_file) {
1162 58 : ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
1163 : ca_file,
1164 : GNUTLS_X509_FMT_PEM);
1165 58 : if (ret < 0) {
1166 0 : DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1167 : ca_file, gnutls_strerror(ret)));
1168 0 : talloc_free(tlsp);
1169 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1170 : }
1171 : }
1172 :
1173 58 : if (crl_file && *crl_file) {
1174 27 : ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
1175 : crl_file,
1176 : GNUTLS_X509_FMT_PEM);
1177 27 : if (ret < 0) {
1178 0 : DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1179 : crl_file, gnutls_strerror(ret)));
1180 0 : talloc_free(tlsp);
1181 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1182 : }
1183 : }
1184 :
1185 58 : ret = gnutls_certificate_set_x509_key_file(tlsp->x509_cred,
1186 : cert_file, key_file,
1187 : GNUTLS_X509_FMT_PEM);
1188 58 : if (ret != GNUTLS_E_SUCCESS) {
1189 0 : DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
1190 : cert_file, key_file, gnutls_strerror(ret)));
1191 0 : talloc_free(tlsp);
1192 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1193 : }
1194 :
1195 58 : ret = gnutls_dh_params_init(&tlsp->dh_params);
1196 58 : if (ret != GNUTLS_E_SUCCESS) {
1197 0 : DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1198 0 : talloc_free(tlsp);
1199 0 : return NT_STATUS_NO_MEMORY;
1200 : }
1201 :
1202 116 : if (dhp_file && *dhp_file) {
1203 : gnutls_datum_t dhparms;
1204 : size_t size;
1205 :
1206 58 : dhparms.data = (uint8_t *)file_load(dhp_file, &size, 0, tlsp);
1207 :
1208 58 : if (!dhparms.data) {
1209 0 : DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
1210 : dhp_file, errno, strerror(errno)));
1211 0 : talloc_free(tlsp);
1212 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1213 : }
1214 58 : dhparms.size = size;
1215 :
1216 58 : ret = gnutls_dh_params_import_pkcs3(tlsp->dh_params,
1217 : &dhparms,
1218 : GNUTLS_X509_FMT_PEM);
1219 58 : if (ret != GNUTLS_E_SUCCESS) {
1220 0 : DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
1221 : dhp_file, gnutls_strerror(ret)));
1222 0 : talloc_free(tlsp);
1223 0 : return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1224 : }
1225 : } else {
1226 0 : ret = gnutls_dh_params_generate2(tlsp->dh_params, DH_BITS);
1227 0 : if (ret != GNUTLS_E_SUCCESS) {
1228 0 : DEBUG(0,("TLS failed to generate dh_params - %s\n",
1229 : gnutls_strerror(ret)));
1230 0 : talloc_free(tlsp);
1231 0 : return NT_STATUS_INTERNAL_ERROR;
1232 : }
1233 : }
1234 :
1235 58 : gnutls_certificate_set_dh_params(tlsp->x509_cred, tlsp->dh_params);
1236 :
1237 58 : tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
1238 58 : if (tlsp->tls_priority == NULL) {
1239 0 : talloc_free(tlsp);
1240 0 : return NT_STATUS_NO_MEMORY;
1241 : }
1242 :
1243 58 : tlsp->tls_enabled = true;
1244 :
1245 58 : *_tlsp = tlsp;
1246 58 : return NT_STATUS_OK;
1247 : }
1248 :
1249 : struct tstream_tls_accept_state {
1250 : struct tstream_context *tls_stream;
1251 : };
1252 :
1253 180 : struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
1254 : struct tevent_context *ev,
1255 : struct tstream_context *plain_stream,
1256 : struct tstream_tls_params *tlsp,
1257 : const char *location)
1258 : {
1259 : struct tevent_req *req;
1260 : struct tstream_tls_accept_state *state;
1261 : struct tstream_tls *tlss;
1262 : const char *error_pos;
1263 : int ret;
1264 :
1265 180 : req = tevent_req_create(mem_ctx, &state,
1266 : struct tstream_tls_accept_state);
1267 180 : if (req == NULL) {
1268 0 : return NULL;
1269 : }
1270 :
1271 180 : state->tls_stream = tstream_context_create(state,
1272 : &tstream_tls_ops,
1273 : &tlss,
1274 : struct tstream_tls,
1275 : location);
1276 180 : if (tevent_req_nomem(state->tls_stream, req)) {
1277 0 : return tevent_req_post(req, ev);
1278 : }
1279 180 : ZERO_STRUCTP(tlss);
1280 180 : talloc_set_destructor(tlss, tstream_tls_destructor);
1281 :
1282 180 : tlss->plain_stream = plain_stream;
1283 :
1284 180 : tlss->current_ev = ev;
1285 180 : tlss->retry_im = tevent_create_immediate(tlss);
1286 180 : if (tevent_req_nomem(tlss->retry_im, req)) {
1287 0 : return tevent_req_post(req, ev);
1288 : }
1289 :
1290 180 : ret = gnutls_init(&tlss->tls_session, GNUTLS_SERVER);
1291 180 : if (ret != GNUTLS_E_SUCCESS) {
1292 0 : DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1293 0 : tevent_req_error(req, EINVAL);
1294 0 : return tevent_req_post(req, ev);
1295 : }
1296 :
1297 180 : ret = gnutls_set_default_priority(tlss->tls_session);
1298 180 : if (ret != GNUTLS_E_SUCCESS) {
1299 0 : DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
1300 : __location__, gnutls_strerror(ret));
1301 0 : tevent_req_error(req, EINVAL);
1302 0 : return tevent_req_post(req, ev);
1303 : }
1304 :
1305 180 : if (strlen(tlsp->tls_priority) > 0) {
1306 180 : ret = gnutls_priority_set_direct(tlss->tls_session,
1307 : tlsp->tls_priority,
1308 : &error_pos);
1309 180 : if (ret != GNUTLS_E_SUCCESS) {
1310 0 : DEBUG(0,("TLS %s - %s. Check 'tls priority' option at '%s'\n",
1311 : __location__, gnutls_strerror(ret), error_pos));
1312 0 : tevent_req_error(req, EINVAL);
1313 0 : return tevent_req_post(req, ev);
1314 : }
1315 : }
1316 :
1317 180 : ret = gnutls_credentials_set(tlss->tls_session, GNUTLS_CRD_CERTIFICATE,
1318 180 : tlsp->x509_cred);
1319 180 : if (ret != GNUTLS_E_SUCCESS) {
1320 0 : DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1321 0 : tevent_req_error(req, EINVAL);
1322 0 : return tevent_req_post(req, ev);
1323 : }
1324 :
1325 180 : gnutls_certificate_server_set_request(tlss->tls_session,
1326 : GNUTLS_CERT_REQUEST);
1327 180 : gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS);
1328 :
1329 180 : gnutls_transport_set_ptr(tlss->tls_session,
1330 180 : (gnutls_transport_ptr_t)state->tls_stream);
1331 180 : gnutls_transport_set_pull_function(tlss->tls_session,
1332 : (gnutls_pull_func)tstream_tls_pull_function);
1333 180 : gnutls_transport_set_push_function(tlss->tls_session,
1334 : (gnutls_push_func)tstream_tls_push_function);
1335 :
1336 180 : tlss->handshake.req = req;
1337 180 : tstream_tls_retry_handshake(state->tls_stream);
1338 180 : if (!tevent_req_is_in_progress(req)) {
1339 0 : return tevent_req_post(req, ev);
1340 : }
1341 :
1342 180 : return req;
1343 : }
1344 :
1345 4799 : static void tstream_tls_retry_handshake(struct tstream_context *stream)
1346 : {
1347 4276 : struct tstream_tls *tlss =
1348 4799 : tstream_context_data(stream,
1349 : struct tstream_tls);
1350 4799 : struct tevent_req *req = tlss->handshake.req;
1351 : int ret;
1352 :
1353 4799 : if (tlss->error != 0) {
1354 5 : tevent_req_error(req, tlss->error);
1355 5 : return;
1356 : }
1357 :
1358 4794 : ret = gnutls_handshake(tlss->tls_session);
1359 4794 : if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
1360 4458 : return;
1361 : }
1362 :
1363 336 : tlss->handshake.req = NULL;
1364 :
1365 336 : if (gnutls_error_is_fatal(ret) != 0) {
1366 1 : DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1367 1 : tlss->error = EIO;
1368 1 : tevent_req_error(req, tlss->error);
1369 1 : return;
1370 : }
1371 :
1372 335 : if (ret != GNUTLS_E_SUCCESS) {
1373 0 : DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1374 0 : tlss->error = EIO;
1375 0 : tevent_req_error(req, tlss->error);
1376 0 : return;
1377 : }
1378 :
1379 335 : if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
1380 30 : unsigned int status = UINT32_MAX;
1381 30 : bool ip = true;
1382 30 : const char *hostname = NULL;
1383 :
1384 30 : if (tlss->peer_name != NULL) {
1385 30 : ip = is_ipaddress(tlss->peer_name);
1386 : }
1387 :
1388 30 : if (!ip) {
1389 20 : hostname = tlss->peer_name;
1390 : }
1391 :
1392 30 : if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
1393 9 : hostname = NULL;
1394 : }
1395 :
1396 30 : if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
1397 12 : if (hostname == NULL) {
1398 4 : DEBUG(1,("TLS %s - no hostname available for "
1399 : "verify_peer[%s] and peer_name[%s]\n",
1400 : __location__,
1401 : tls_verify_peer_string(tlss->verify_peer),
1402 : tlss->peer_name));
1403 4 : tlss->error = EINVAL;
1404 4 : tevent_req_error(req, tlss->error);
1405 6 : return;
1406 : }
1407 : }
1408 :
1409 26 : ret = gnutls_certificate_verify_peers3(tlss->tls_session,
1410 : hostname,
1411 : &status);
1412 26 : if (ret != GNUTLS_E_SUCCESS) {
1413 0 : DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1414 0 : tlss->error = EIO;
1415 0 : tevent_req_error(req, tlss->error);
1416 0 : return;
1417 : }
1418 :
1419 26 : if (status != 0) {
1420 7 : DEBUG(1,("TLS %s - check failed for "
1421 : "verify_peer[%s] and peer_name[%s] "
1422 : "status 0x%x (%s%s%s%s%s%s%s%s)\n",
1423 : __location__,
1424 : tls_verify_peer_string(tlss->verify_peer),
1425 : tlss->peer_name,
1426 : status,
1427 : status & GNUTLS_CERT_INVALID ? "invalid " : "",
1428 : status & GNUTLS_CERT_REVOKED ? "revoked " : "",
1429 : status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
1430 : "signer_not_found " : "",
1431 : status & GNUTLS_CERT_SIGNER_NOT_CA ?
1432 : "signer_not_ca " : "",
1433 : status & GNUTLS_CERT_INSECURE_ALGORITHM ?
1434 : "insecure_algorithm " : "",
1435 : status & GNUTLS_CERT_NOT_ACTIVATED ?
1436 : "not_activated " : "",
1437 : status & GNUTLS_CERT_EXPIRED ?
1438 : "expired " : "",
1439 : status & GNUTLS_CERT_UNEXPECTED_OWNER ?
1440 : "unexptected_owner " : ""));
1441 7 : tlss->error = EINVAL;
1442 7 : tevent_req_error(req, tlss->error);
1443 7 : return;
1444 : }
1445 : }
1446 :
1447 324 : tevent_req_done(req);
1448 : }
1449 :
1450 180 : int tstream_tls_accept_recv(struct tevent_req *req,
1451 : int *perrno,
1452 : TALLOC_CTX *mem_ctx,
1453 : struct tstream_context **tls_stream)
1454 : {
1455 154 : struct tstream_tls_accept_state *state =
1456 180 : tevent_req_data(req,
1457 : struct tstream_tls_accept_state);
1458 :
1459 180 : if (tevent_req_is_unix_error(req, perrno)) {
1460 4 : tevent_req_received(req);
1461 4 : return -1;
1462 : }
1463 :
1464 176 : *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1465 176 : tevent_req_received(req);
1466 176 : return 0;
1467 : }
|