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