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