lib: Give lib/util/util_file.c its own header file
[Samba.git] / source4 / lib / tls / tls_tstream.c
blob41fd6cce5e3587e3c9570c801e3be301a21cb17c
1 /*
2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan Metzmacher 2010
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.
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.
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/>.
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"
31 #include <gnutls/gnutls.h>
32 #include <gnutls/x509.h>
34 #define DH_BITS 2048
36 const char *tls_verify_peer_string(enum tls_verify_peer_state verify_peer)
38 switch (verify_peer) {
39 case TLS_VERIFY_PEER_NO_CHECK:
40 return TLS_VERIFY_PEER_NO_CHECK_STRING;
42 case TLS_VERIFY_PEER_CA_ONLY:
43 return TLS_VERIFY_PEER_CA_ONLY_STRING;
45 case TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE:
46 return TLS_VERIFY_PEER_CA_AND_NAME_IF_AVAILABLE_STRING;
48 case TLS_VERIFY_PEER_CA_AND_NAME:
49 return TLS_VERIFY_PEER_CA_AND_NAME_STRING;
51 case TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE:
52 return TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE_STRING;
55 return "unknown tls_verify_peer_state";
58 static const struct tstream_context_ops tstream_tls_ops;
60 struct tstream_tls {
61 struct tstream_context *plain_stream;
62 int error;
64 gnutls_session_t tls_session;
66 enum tls_verify_peer_state verify_peer;
67 const char *peer_name;
69 struct tevent_context *current_ev;
71 struct tevent_immediate *retry_im;
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;
81 struct {
82 uint8_t *buf;
83 struct iovec iov;
84 struct tevent_req *subreq;
85 } pull;
87 struct {
88 struct tevent_req *req;
89 } handshake;
91 struct {
92 off_t ofs;
93 size_t left;
94 uint8_t buffer[1024];
95 struct tevent_req *req;
96 } write;
98 struct {
99 off_t ofs;
100 size_t left;
101 uint8_t buffer[1024];
102 struct tevent_req *req;
103 } read;
105 struct {
106 struct tevent_req *req;
107 } disconnect;
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);
118 static void tstream_tls_retry(struct tstream_context *stream, bool deferred)
121 struct tstream_tls *tlss =
122 tstream_context_data(stream,
123 struct tstream_tls);
125 if (tlss->disconnect.req) {
126 tstream_tls_retry_disconnect(stream);
127 return;
130 if (tlss->handshake.req) {
131 tstream_tls_retry_handshake(stream);
132 return;
135 if (tlss->write.req && tlss->read.req && !deferred) {
136 tevent_schedule_immediate(tlss->retry_im, tlss->current_ev,
137 tstream_tls_retry_trigger,
138 stream);
141 if (tlss->write.req) {
142 tstream_tls_retry_write(stream);
143 return;
146 if (tlss->read.req) {
147 tstream_tls_retry_read(stream);
148 return;
152 static void tstream_tls_retry_trigger(struct tevent_context *ctx,
153 struct tevent_immediate *im,
154 void *private_data)
156 struct tstream_context *stream =
157 talloc_get_type_abort(private_data,
158 struct tstream_context);
160 tstream_tls_retry(stream, true);
163 static void tstream_tls_push_trigger_write(struct tevent_context *ev,
164 struct tevent_immediate *im,
165 void *private_data);
167 static ssize_t tstream_tls_push_function(gnutls_transport_ptr_t ptr,
168 const void *buf, size_t size)
170 struct tstream_context *stream =
171 talloc_get_type_abort(ptr,
172 struct tstream_context);
173 struct tstream_tls *tlss =
174 tstream_context_data(stream,
175 struct tstream_tls);
176 uint8_t *nbuf;
177 size_t len;
179 if (tlss->error != 0) {
180 errno = tlss->error;
181 return -1;
184 if (tlss->push.subreq) {
185 errno = EAGAIN;
186 return -1;
189 len = MIN(size, UINT16_MAX - tlss->push.ofs);
191 if (len == 0) {
192 errno = EAGAIN;
193 return -1;
196 nbuf = talloc_realloc(tlss, tlss->push.buf,
197 uint8_t, tlss->push.ofs + len);
198 if (nbuf == NULL) {
199 if (tlss->push.buf) {
200 errno = EAGAIN;
201 return -1;
204 return -1;
206 tlss->push.buf = nbuf;
208 memcpy(tlss->push.buf + tlss->push.ofs, buf, len);
210 if (tlss->push.im == NULL) {
211 tlss->push.im = tevent_create_immediate(tlss);
212 if (tlss->push.im == NULL) {
213 errno = ENOMEM;
214 return -1;
218 if (tlss->push.ofs == 0) {
220 * We'll do start the tstream_writev
221 * in the next event cycle.
223 * This way we can batch all push requests,
224 * if they fit into a UINT16_MAX buffer.
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.
231 tevent_schedule_immediate(tlss->push.im,
232 tlss->current_ev,
233 tstream_tls_push_trigger_write,
234 stream);
237 tlss->push.ofs += len;
238 return len;
241 static void tstream_tls_push_done(struct tevent_req *subreq);
243 static void tstream_tls_push_trigger_write(struct tevent_context *ev,
244 struct tevent_immediate *im,
245 void *private_data)
247 struct tstream_context *stream =
248 talloc_get_type_abort(private_data,
249 struct tstream_context);
250 struct tstream_tls *tlss =
251 tstream_context_data(stream,
252 struct tstream_tls);
253 struct tevent_req *subreq;
255 if (tlss->push.subreq) {
256 /* nothing todo */
257 return;
260 tlss->push.iov.iov_base = (char *)tlss->push.buf;
261 tlss->push.iov.iov_len = tlss->push.ofs;
263 subreq = tstream_writev_send(tlss,
264 tlss->current_ev,
265 tlss->plain_stream,
266 &tlss->push.iov, 1);
267 if (subreq == NULL) {
268 tlss->error = ENOMEM;
269 tstream_tls_retry(stream, false);
270 return;
272 tevent_req_set_callback(subreq, tstream_tls_push_done, stream);
274 tlss->push.subreq = subreq;
277 static void tstream_tls_push_done(struct tevent_req *subreq)
279 struct tstream_context *stream =
280 tevent_req_callback_data(subreq,
281 struct tstream_context);
282 struct tstream_tls *tlss =
283 tstream_context_data(stream,
284 struct tstream_tls);
285 int ret;
286 int sys_errno;
288 tlss->push.subreq = NULL;
289 ZERO_STRUCT(tlss->push.iov);
290 TALLOC_FREE(tlss->push.buf);
291 tlss->push.ofs = 0;
293 ret = tstream_writev_recv(subreq, &sys_errno);
294 TALLOC_FREE(subreq);
295 if (ret == -1) {
296 tlss->error = sys_errno;
297 tstream_tls_retry(stream, false);
298 return;
301 tstream_tls_retry(stream, false);
304 static void tstream_tls_pull_done(struct tevent_req *subreq);
306 static ssize_t tstream_tls_pull_function(gnutls_transport_ptr_t ptr,
307 void *buf, size_t size)
309 struct tstream_context *stream =
310 talloc_get_type_abort(ptr,
311 struct tstream_context);
312 struct tstream_tls *tlss =
313 tstream_context_data(stream,
314 struct tstream_tls);
315 struct tevent_req *subreq;
316 size_t len;
318 if (tlss->error != 0) {
319 errno = tlss->error;
320 return -1;
323 if (tlss->pull.subreq) {
324 errno = EAGAIN;
325 return -1;
328 if (tlss->pull.iov.iov_base) {
329 uint8_t *b;
330 size_t n;
332 b = (uint8_t *)tlss->pull.iov.iov_base;
334 n = MIN(tlss->pull.iov.iov_len, size);
335 memcpy(buf, b, n);
337 tlss->pull.iov.iov_len -= n;
338 b += n;
339 tlss->pull.iov.iov_base = (char *)b;
340 if (tlss->pull.iov.iov_len == 0) {
341 tlss->pull.iov.iov_base = NULL;
342 TALLOC_FREE(tlss->pull.buf);
345 return n;
348 if (size == 0) {
349 return 0;
352 len = MIN(size, UINT16_MAX);
354 tlss->pull.buf = talloc_array(tlss, uint8_t, len);
355 if (tlss->pull.buf == NULL) {
356 return -1;
359 tlss->pull.iov.iov_base = (char *)tlss->pull.buf;
360 tlss->pull.iov.iov_len = len;
362 subreq = tstream_readv_send(tlss,
363 tlss->current_ev,
364 tlss->plain_stream,
365 &tlss->pull.iov, 1);
366 if (subreq == NULL) {
367 errno = ENOMEM;
368 return -1;
370 tevent_req_set_callback(subreq, tstream_tls_pull_done, stream);
372 tlss->pull.subreq = subreq;
373 errno = EAGAIN;
374 return -1;
377 static void tstream_tls_pull_done(struct tevent_req *subreq)
379 struct tstream_context *stream =
380 tevent_req_callback_data(subreq,
381 struct tstream_context);
382 struct tstream_tls *tlss =
383 tstream_context_data(stream,
384 struct tstream_tls);
385 int ret;
386 int sys_errno;
388 tlss->pull.subreq = NULL;
390 ret = tstream_readv_recv(subreq, &sys_errno);
391 TALLOC_FREE(subreq);
392 if (ret == -1) {
393 tlss->error = sys_errno;
394 tstream_tls_retry(stream, false);
395 return;
398 tstream_tls_retry(stream, false);
401 static int tstream_tls_destructor(struct tstream_tls *tlss)
403 if (tlss->tls_session) {
404 gnutls_deinit(tlss->tls_session);
405 tlss->tls_session = NULL;
408 return 0;
411 static ssize_t tstream_tls_pending_bytes(struct tstream_context *stream)
413 struct tstream_tls *tlss =
414 tstream_context_data(stream,
415 struct tstream_tls);
416 size_t ret;
418 if (tlss->error != 0) {
419 errno = tlss->error;
420 return -1;
423 ret = gnutls_record_check_pending(tlss->tls_session);
424 ret += tlss->read.left;
426 return ret;
429 struct tstream_tls_readv_state {
430 struct tstream_context *stream;
432 struct iovec *vector;
433 int count;
435 int ret;
438 static void tstream_tls_readv_crypt_next(struct tevent_req *req);
440 static struct tevent_req *tstream_tls_readv_send(TALLOC_CTX *mem_ctx,
441 struct tevent_context *ev,
442 struct tstream_context *stream,
443 struct iovec *vector,
444 size_t count)
446 struct tstream_tls *tlss =
447 tstream_context_data(stream,
448 struct tstream_tls);
449 struct tevent_req *req;
450 struct tstream_tls_readv_state *state;
452 tlss->read.req = NULL;
453 tlss->current_ev = ev;
455 req = tevent_req_create(mem_ctx, &state,
456 struct tstream_tls_readv_state);
457 if (req == NULL) {
458 return NULL;
461 state->stream = stream;
462 state->ret = 0;
464 if (tlss->error != 0) {
465 tevent_req_error(req, tlss->error);
466 return tevent_req_post(req, ev);
470 * we make a copy of the vector so we can change the structure
472 state->vector = talloc_array(state, struct iovec, count);
473 if (tevent_req_nomem(state->vector, req)) {
474 return tevent_req_post(req, ev);
476 memcpy(state->vector, vector, sizeof(struct iovec) * count);
477 state->count = count;
479 tstream_tls_readv_crypt_next(req);
480 if (!tevent_req_is_in_progress(req)) {
481 return tevent_req_post(req, ev);
484 return req;
487 static void tstream_tls_readv_crypt_next(struct tevent_req *req)
489 struct tstream_tls_readv_state *state =
490 tevent_req_data(req,
491 struct tstream_tls_readv_state);
492 struct tstream_tls *tlss =
493 tstream_context_data(state->stream,
494 struct tstream_tls);
497 * copy the pending buffer first
499 while (tlss->read.left > 0 && state->count > 0) {
500 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
501 size_t len = MIN(tlss->read.left, state->vector[0].iov_len);
503 memcpy(base, tlss->read.buffer + tlss->read.ofs, len);
505 base += len;
506 state->vector[0].iov_base = (char *) base;
507 state->vector[0].iov_len -= len;
509 tlss->read.ofs += len;
510 tlss->read.left -= len;
512 if (state->vector[0].iov_len == 0) {
513 state->vector += 1;
514 state->count -= 1;
517 state->ret += len;
520 if (state->count == 0) {
521 tevent_req_done(req);
522 return;
525 tlss->read.req = req;
526 tstream_tls_retry_read(state->stream);
529 static void tstream_tls_retry_read(struct tstream_context *stream)
531 struct tstream_tls *tlss =
532 tstream_context_data(stream,
533 struct tstream_tls);
534 struct tevent_req *req = tlss->read.req;
535 int ret;
537 if (tlss->error != 0) {
538 tevent_req_error(req, tlss->error);
539 return;
542 tlss->read.left = 0;
543 tlss->read.ofs = 0;
545 ret = gnutls_record_recv(tlss->tls_session,
546 tlss->read.buffer,
547 sizeof(tlss->read.buffer));
548 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
549 return;
552 tlss->read.req = NULL;
554 if (gnutls_error_is_fatal(ret) != 0) {
555 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
556 tlss->error = EIO;
557 tevent_req_error(req, tlss->error);
558 return;
561 if (ret == 0) {
562 tlss->error = EPIPE;
563 tevent_req_error(req, tlss->error);
564 return;
567 tlss->read.left = ret;
568 tstream_tls_readv_crypt_next(req);
571 static int tstream_tls_readv_recv(struct tevent_req *req,
572 int *perrno)
574 struct tstream_tls_readv_state *state =
575 tevent_req_data(req,
576 struct tstream_tls_readv_state);
577 struct tstream_tls *tlss =
578 tstream_context_data(state->stream,
579 struct tstream_tls);
580 int ret;
582 tlss->read.req = NULL;
584 ret = tsocket_simple_int_recv(req, perrno);
585 if (ret == 0) {
586 ret = state->ret;
589 tevent_req_received(req);
590 return ret;
593 struct tstream_tls_writev_state {
594 struct tstream_context *stream;
596 struct iovec *vector;
597 int count;
599 int ret;
602 static void tstream_tls_writev_crypt_next(struct tevent_req *req);
604 static struct tevent_req *tstream_tls_writev_send(TALLOC_CTX *mem_ctx,
605 struct tevent_context *ev,
606 struct tstream_context *stream,
607 const struct iovec *vector,
608 size_t count)
610 struct tstream_tls *tlss =
611 tstream_context_data(stream,
612 struct tstream_tls);
613 struct tevent_req *req;
614 struct tstream_tls_writev_state *state;
616 tlss->write.req = NULL;
617 tlss->current_ev = ev;
619 req = tevent_req_create(mem_ctx, &state,
620 struct tstream_tls_writev_state);
621 if (req == NULL) {
622 return NULL;
625 state->stream = stream;
626 state->ret = 0;
628 if (tlss->error != 0) {
629 tevent_req_error(req, tlss->error);
630 return tevent_req_post(req, ev);
634 * we make a copy of the vector so we can change the structure
636 state->vector = talloc_array(state, struct iovec, count);
637 if (tevent_req_nomem(state->vector, req)) {
638 return tevent_req_post(req, ev);
640 memcpy(state->vector, vector, sizeof(struct iovec) * count);
641 state->count = count;
643 tstream_tls_writev_crypt_next(req);
644 if (!tevent_req_is_in_progress(req)) {
645 return tevent_req_post(req, ev);
648 return req;
651 static void tstream_tls_writev_crypt_next(struct tevent_req *req)
653 struct tstream_tls_writev_state *state =
654 tevent_req_data(req,
655 struct tstream_tls_writev_state);
656 struct tstream_tls *tlss =
657 tstream_context_data(state->stream,
658 struct tstream_tls);
660 tlss->write.left = sizeof(tlss->write.buffer);
661 tlss->write.ofs = 0;
664 * first fill our buffer
666 while (tlss->write.left > 0 && state->count > 0) {
667 uint8_t *base = (uint8_t *)state->vector[0].iov_base;
668 size_t len = MIN(tlss->write.left, state->vector[0].iov_len);
670 memcpy(tlss->write.buffer + tlss->write.ofs, base, len);
672 base += len;
673 state->vector[0].iov_base = (char *) base;
674 state->vector[0].iov_len -= len;
676 tlss->write.ofs += len;
677 tlss->write.left -= len;
679 if (state->vector[0].iov_len == 0) {
680 state->vector += 1;
681 state->count -= 1;
684 state->ret += len;
687 if (tlss->write.ofs == 0) {
688 tevent_req_done(req);
689 return;
692 tlss->write.left = tlss->write.ofs;
693 tlss->write.ofs = 0;
695 tlss->write.req = req;
696 tstream_tls_retry_write(state->stream);
699 static void tstream_tls_retry_write(struct tstream_context *stream)
701 struct tstream_tls *tlss =
702 tstream_context_data(stream,
703 struct tstream_tls);
704 struct tevent_req *req = tlss->write.req;
705 int ret;
707 if (tlss->error != 0) {
708 tevent_req_error(req, tlss->error);
709 return;
712 ret = gnutls_record_send(tlss->tls_session,
713 tlss->write.buffer + tlss->write.ofs,
714 tlss->write.left);
715 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
716 return;
719 tlss->write.req = NULL;
721 if (gnutls_error_is_fatal(ret) != 0) {
722 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
723 tlss->error = EIO;
724 tevent_req_error(req, tlss->error);
725 return;
728 if (ret == 0) {
729 tlss->error = EPIPE;
730 tevent_req_error(req, tlss->error);
731 return;
734 tlss->write.ofs += ret;
735 tlss->write.left -= ret;
737 if (tlss->write.left > 0) {
738 tlss->write.req = req;
739 tstream_tls_retry_write(stream);
740 return;
743 tstream_tls_writev_crypt_next(req);
746 static int tstream_tls_writev_recv(struct tevent_req *req,
747 int *perrno)
749 struct tstream_tls_writev_state *state =
750 tevent_req_data(req,
751 struct tstream_tls_writev_state);
752 struct tstream_tls *tlss =
753 tstream_context_data(state->stream,
754 struct tstream_tls);
755 int ret;
757 tlss->write.req = NULL;
759 ret = tsocket_simple_int_recv(req, perrno);
760 if (ret == 0) {
761 ret = state->ret;
764 tevent_req_received(req);
765 return ret;
768 struct tstream_tls_disconnect_state {
769 uint8_t _dummy;
772 static struct tevent_req *tstream_tls_disconnect_send(TALLOC_CTX *mem_ctx,
773 struct tevent_context *ev,
774 struct tstream_context *stream)
776 struct tstream_tls *tlss =
777 tstream_context_data(stream,
778 struct tstream_tls);
779 struct tevent_req *req;
780 struct tstream_tls_disconnect_state *state;
782 tlss->disconnect.req = NULL;
783 tlss->current_ev = ev;
785 req = tevent_req_create(mem_ctx, &state,
786 struct tstream_tls_disconnect_state);
787 if (req == NULL) {
788 return NULL;
791 if (tlss->error != 0) {
792 tevent_req_error(req, tlss->error);
793 return tevent_req_post(req, ev);
796 tlss->disconnect.req = req;
797 tstream_tls_retry_disconnect(stream);
798 if (!tevent_req_is_in_progress(req)) {
799 return tevent_req_post(req, ev);
802 return req;
805 static void tstream_tls_retry_disconnect(struct tstream_context *stream)
807 struct tstream_tls *tlss =
808 tstream_context_data(stream,
809 struct tstream_tls);
810 struct tevent_req *req = tlss->disconnect.req;
811 int ret;
813 if (tlss->error != 0) {
814 tevent_req_error(req, tlss->error);
815 return;
818 ret = gnutls_bye(tlss->tls_session, GNUTLS_SHUT_WR);
819 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
820 return;
823 tlss->disconnect.req = NULL;
825 if (gnutls_error_is_fatal(ret) != 0) {
826 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
827 tlss->error = EIO;
828 tevent_req_error(req, tlss->error);
829 return;
832 if (ret != GNUTLS_E_SUCCESS) {
833 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
834 tlss->error = EIO;
835 tevent_req_error(req, tlss->error);
836 return;
839 tevent_req_done(req);
842 static int tstream_tls_disconnect_recv(struct tevent_req *req,
843 int *perrno)
845 int ret;
847 ret = tsocket_simple_int_recv(req, perrno);
849 tevent_req_received(req);
850 return ret;
853 static const struct tstream_context_ops tstream_tls_ops = {
854 .name = "tls",
856 .pending_bytes = tstream_tls_pending_bytes,
858 .readv_send = tstream_tls_readv_send,
859 .readv_recv = tstream_tls_readv_recv,
861 .writev_send = tstream_tls_writev_send,
862 .writev_recv = tstream_tls_writev_recv,
864 .disconnect_send = tstream_tls_disconnect_send,
865 .disconnect_recv = tstream_tls_disconnect_recv,
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;
877 struct tstream_tls_params {
878 struct tstream_tls_params_internal *internal;
881 static int tstream_tls_params_internal_destructor(struct tstream_tls_params_internal *tlsp)
883 if (tlsp->x509_cred) {
884 gnutls_certificate_free_credentials(tlsp->x509_cred);
885 tlsp->x509_cred = NULL;
887 if (tlsp->dh_params) {
888 gnutls_dh_params_deinit(tlsp->dh_params);
889 tlsp->dh_params = NULL;
892 return 0;
895 bool tstream_tls_params_enabled(struct tstream_tls_params *tls_params)
897 struct tstream_tls_params_internal *tlsp = tls_params->internal;
899 return tlsp->tls_enabled;
902 NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
903 const char *ca_file,
904 const char *crl_file,
905 const char *tls_priority,
906 enum tls_verify_peer_state verify_peer,
907 const char *peer_name,
908 struct tstream_tls_params **_tlsp)
910 struct tstream_tls_params *__tlsp = NULL;
911 struct tstream_tls_params_internal *tlsp = NULL;
912 int ret;
914 __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
915 if (__tlsp == NULL) {
916 return NT_STATUS_NO_MEMORY;
919 tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
920 if (tlsp == NULL) {
921 TALLOC_FREE(__tlsp);
922 return NT_STATUS_NO_MEMORY;
924 talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
925 __tlsp->internal = tlsp;
927 tlsp->verify_peer = verify_peer;
928 if (peer_name != NULL) {
929 tlsp->peer_name = talloc_strdup(tlsp, peer_name);
930 if (tlsp->peer_name == NULL) {
931 TALLOC_FREE(__tlsp);
932 return NT_STATUS_NO_MEMORY;
934 } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
935 DEBUG(0,("TLS failed to missing peer_name - "
936 "with 'tls verify peer = %s'\n",
937 tls_verify_peer_string(tlsp->verify_peer)));
938 TALLOC_FREE(__tlsp);
939 return NT_STATUS_INVALID_PARAMETER_MIX;
942 ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
943 if (ret != GNUTLS_E_SUCCESS) {
944 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
945 TALLOC_FREE(__tlsp);
946 return NT_STATUS_NO_MEMORY;
949 if (ca_file && *ca_file && file_exist(ca_file)) {
950 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
951 ca_file,
952 GNUTLS_X509_FMT_PEM);
953 if (ret < 0) {
954 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
955 ca_file, gnutls_strerror(ret)));
956 TALLOC_FREE(__tlsp);
957 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
959 } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
960 DEBUG(0,("TLS failed to missing cafile %s - "
961 "with 'tls verify peer = %s'\n",
962 ca_file,
963 tls_verify_peer_string(tlsp->verify_peer)));
964 TALLOC_FREE(__tlsp);
965 return NT_STATUS_INVALID_PARAMETER_MIX;
968 if (crl_file && *crl_file && file_exist(crl_file)) {
969 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
970 crl_file,
971 GNUTLS_X509_FMT_PEM);
972 if (ret < 0) {
973 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
974 crl_file, gnutls_strerror(ret)));
975 TALLOC_FREE(__tlsp);
976 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
978 } else if (tlsp->verify_peer >= TLS_VERIFY_PEER_AS_STRICT_AS_POSSIBLE) {
979 DEBUG(0,("TLS failed to missing crlfile %s - "
980 "with 'tls verify peer = %s'\n",
981 crl_file,
982 tls_verify_peer_string(tlsp->verify_peer)));
983 TALLOC_FREE(__tlsp);
984 return NT_STATUS_INVALID_PARAMETER_MIX;
987 tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
988 if (tlsp->tls_priority == NULL) {
989 TALLOC_FREE(__tlsp);
990 return NT_STATUS_NO_MEMORY;
993 tlsp->tls_enabled = true;
995 *_tlsp = __tlsp;
996 return NT_STATUS_OK;
999 struct tstream_tls_connect_state {
1000 struct tstream_context *tls_stream;
1003 struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
1004 struct tevent_context *ev,
1005 struct tstream_context *plain_stream,
1006 struct tstream_tls_params *_tls_params,
1007 const char *location)
1009 struct tevent_req *req;
1010 struct tstream_tls_connect_state *state;
1011 const char *error_pos;
1012 struct tstream_tls *tlss;
1013 struct tstream_tls_params_internal *tls_params = NULL;
1014 int ret;
1015 unsigned int flags = GNUTLS_CLIENT;
1017 req = tevent_req_create(mem_ctx, &state,
1018 struct tstream_tls_connect_state);
1019 if (req == NULL) {
1020 return NULL;
1023 state->tls_stream = tstream_context_create(state,
1024 &tstream_tls_ops,
1025 &tlss,
1026 struct tstream_tls,
1027 location);
1028 if (tevent_req_nomem(state->tls_stream, req)) {
1029 return tevent_req_post(req, ev);
1031 ZERO_STRUCTP(tlss);
1032 talloc_set_destructor(tlss, tstream_tls_destructor);
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!
1039 * See 'man gnutls_credentials_set' and
1040 * 'man gnutls_certificate_set_dh_params'.
1042 * Note: here we use talloc_reference() in a way
1043 * that does not expose it to the caller.
1046 tls_params = talloc_reference(tlss, _tls_params->internal);
1047 if (tevent_req_nomem(tls_params, req)) {
1048 return tevent_req_post(req, ev);
1051 tlss->plain_stream = plain_stream;
1052 tlss->verify_peer = tls_params->verify_peer;
1053 if (tls_params->peer_name != NULL) {
1054 tlss->peer_name = talloc_strdup(tlss, tls_params->peer_name);
1055 if (tevent_req_nomem(tlss->peer_name, req)) {
1056 return tevent_req_post(req, ev);
1060 tlss->current_ev = ev;
1061 tlss->retry_im = tevent_create_immediate(tlss);
1062 if (tevent_req_nomem(tlss->retry_im, req)) {
1063 return tevent_req_post(req, ev);
1066 #ifdef GNUTLS_NO_TICKETS
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.
1074 flags |= GNUTLS_NO_TICKETS;
1075 #endif
1077 ret = gnutls_init(&tlss->tls_session, flags);
1078 if (ret != GNUTLS_E_SUCCESS) {
1079 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1080 tevent_req_error(req, EINVAL);
1081 return tevent_req_post(req, ev);
1084 ret = gnutls_set_default_priority(tlss->tls_session);
1085 if (ret != GNUTLS_E_SUCCESS) {
1086 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
1087 __location__, gnutls_strerror(ret));
1088 tevent_req_error(req, EINVAL);
1089 return tevent_req_post(req, ev);
1092 if (strlen(tls_params->tls_priority) > 0) {
1093 ret = gnutls_priority_set_direct(tlss->tls_session,
1094 tls_params->tls_priority,
1095 &error_pos);
1096 if (ret != GNUTLS_E_SUCCESS) {
1097 DEBUG(0,("TLS %s - %s. Check 'tls priority' option at '%s'\n",
1098 __location__, gnutls_strerror(ret), error_pos));
1099 tevent_req_error(req, EINVAL);
1100 return tevent_req_post(req, ev);
1104 ret = gnutls_credentials_set(tlss->tls_session,
1105 GNUTLS_CRD_CERTIFICATE,
1106 tls_params->x509_cred);
1107 if (ret != GNUTLS_E_SUCCESS) {
1108 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1109 tevent_req_error(req, EINVAL);
1110 return tevent_req_post(req, ev);
1113 gnutls_transport_set_ptr(tlss->tls_session,
1114 (gnutls_transport_ptr_t)state->tls_stream);
1115 gnutls_transport_set_pull_function(tlss->tls_session,
1116 (gnutls_pull_func)tstream_tls_pull_function);
1117 gnutls_transport_set_push_function(tlss->tls_session,
1118 (gnutls_push_func)tstream_tls_push_function);
1120 tlss->handshake.req = req;
1121 tstream_tls_retry_handshake(state->tls_stream);
1122 if (!tevent_req_is_in_progress(req)) {
1123 return tevent_req_post(req, ev);
1126 return req;
1129 int tstream_tls_connect_recv(struct tevent_req *req,
1130 int *perrno,
1131 TALLOC_CTX *mem_ctx,
1132 struct tstream_context **tls_stream)
1134 struct tstream_tls_connect_state *state =
1135 tevent_req_data(req,
1136 struct tstream_tls_connect_state);
1138 if (tevent_req_is_unix_error(req, perrno)) {
1139 tevent_req_received(req);
1140 return -1;
1143 *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1144 tevent_req_received(req);
1145 return 0;
1149 initialise global tls state
1151 NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
1152 const char *dns_host_name,
1153 bool enabled,
1154 const char *key_file,
1155 const char *cert_file,
1156 const char *ca_file,
1157 const char *crl_file,
1158 const char *dhp_file,
1159 const char *tls_priority,
1160 struct tstream_tls_params **_tlsp)
1162 struct tstream_tls_params *__tlsp = NULL;
1163 struct tstream_tls_params_internal *tlsp = NULL;
1164 int ret;
1165 struct stat st;
1167 if (!enabled || key_file == NULL || *key_file == 0) {
1168 __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1169 if (__tlsp == NULL) {
1170 return NT_STATUS_NO_MEMORY;
1173 tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
1174 if (tlsp == NULL) {
1175 TALLOC_FREE(__tlsp);
1176 return NT_STATUS_NO_MEMORY;
1179 talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
1180 __tlsp->internal = tlsp;
1181 tlsp->tls_enabled = false;
1183 *_tlsp = __tlsp;
1184 return NT_STATUS_OK;
1187 __tlsp = talloc_zero(mem_ctx, struct tstream_tls_params);
1188 if (__tlsp == NULL) {
1189 return NT_STATUS_NO_MEMORY;
1192 tlsp = talloc_zero(__tlsp, struct tstream_tls_params_internal);
1193 if (tlsp == NULL) {
1194 TALLOC_FREE(__tlsp);
1195 return NT_STATUS_NO_MEMORY;
1198 talloc_set_destructor(tlsp, tstream_tls_params_internal_destructor);
1199 __tlsp->internal = tlsp;
1201 if (!file_exist(ca_file)) {
1202 tls_cert_generate(tlsp, dns_host_name,
1203 key_file, cert_file, ca_file);
1206 if (file_exist(key_file) &&
1207 !file_check_permissions(key_file, geteuid(), 0600, &st))
1209 DEBUG(0, ("Invalid permissions on TLS private key file '%s':\n"
1210 "owner uid %u should be %u, mode 0%o should be 0%o\n"
1211 "This is known as CVE-2013-4476.\n"
1212 "Removing all tls .pem files will cause an "
1213 "auto-regeneration with the correct permissions.\n",
1214 key_file,
1215 (unsigned int)st.st_uid, geteuid(),
1216 (unsigned int)(st.st_mode & 0777), 0600));
1217 TALLOC_FREE(__tlsp);
1218 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1221 ret = gnutls_certificate_allocate_credentials(&tlsp->x509_cred);
1222 if (ret != GNUTLS_E_SUCCESS) {
1223 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1224 TALLOC_FREE(__tlsp);
1225 return NT_STATUS_NO_MEMORY;
1228 if (ca_file && *ca_file) {
1229 ret = gnutls_certificate_set_x509_trust_file(tlsp->x509_cred,
1230 ca_file,
1231 GNUTLS_X509_FMT_PEM);
1232 if (ret < 0) {
1233 DEBUG(0,("TLS failed to initialise cafile %s - %s\n",
1234 ca_file, gnutls_strerror(ret)));
1235 TALLOC_FREE(__tlsp);
1236 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1240 if (crl_file && *crl_file) {
1241 ret = gnutls_certificate_set_x509_crl_file(tlsp->x509_cred,
1242 crl_file,
1243 GNUTLS_X509_FMT_PEM);
1244 if (ret < 0) {
1245 DEBUG(0,("TLS failed to initialise crlfile %s - %s\n",
1246 crl_file, gnutls_strerror(ret)));
1247 TALLOC_FREE(__tlsp);
1248 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1252 ret = gnutls_certificate_set_x509_key_file(tlsp->x509_cred,
1253 cert_file, key_file,
1254 GNUTLS_X509_FMT_PEM);
1255 if (ret != GNUTLS_E_SUCCESS) {
1256 DEBUG(0,("TLS failed to initialise certfile %s and keyfile %s - %s\n",
1257 cert_file, key_file, gnutls_strerror(ret)));
1258 TALLOC_FREE(__tlsp);
1259 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1262 ret = gnutls_dh_params_init(&tlsp->dh_params);
1263 if (ret != GNUTLS_E_SUCCESS) {
1264 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1265 TALLOC_FREE(__tlsp);
1266 return NT_STATUS_NO_MEMORY;
1269 if (dhp_file && *dhp_file) {
1270 gnutls_datum_t dhparms;
1271 size_t size;
1273 dhparms.data = (uint8_t *)file_load(dhp_file, &size, 0, tlsp);
1275 if (!dhparms.data) {
1276 DEBUG(0,("TLS failed to read DH Parms from %s - %d:%s\n",
1277 dhp_file, errno, strerror(errno)));
1278 TALLOC_FREE(__tlsp);
1279 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1281 dhparms.size = size;
1283 ret = gnutls_dh_params_import_pkcs3(tlsp->dh_params,
1284 &dhparms,
1285 GNUTLS_X509_FMT_PEM);
1286 if (ret != GNUTLS_E_SUCCESS) {
1287 DEBUG(0,("TLS failed to import pkcs3 %s - %s\n",
1288 dhp_file, gnutls_strerror(ret)));
1289 TALLOC_FREE(__tlsp);
1290 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1292 } else {
1293 ret = gnutls_dh_params_generate2(tlsp->dh_params, DH_BITS);
1294 if (ret != GNUTLS_E_SUCCESS) {
1295 DEBUG(0,("TLS failed to generate dh_params - %s\n",
1296 gnutls_strerror(ret)));
1297 TALLOC_FREE(__tlsp);
1298 return NT_STATUS_INTERNAL_ERROR;
1302 gnutls_certificate_set_dh_params(tlsp->x509_cred, tlsp->dh_params);
1304 tlsp->tls_priority = talloc_strdup(tlsp, tls_priority);
1305 if (tlsp->tls_priority == NULL) {
1306 TALLOC_FREE(__tlsp);
1307 return NT_STATUS_NO_MEMORY;
1310 tlsp->tls_enabled = true;
1312 *_tlsp = __tlsp;
1313 return NT_STATUS_OK;
1316 struct tstream_tls_accept_state {
1317 struct tstream_context *tls_stream;
1320 struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
1321 struct tevent_context *ev,
1322 struct tstream_context *plain_stream,
1323 struct tstream_tls_params *_tlsp,
1324 const char *location)
1326 struct tevent_req *req;
1327 struct tstream_tls_accept_state *state;
1328 struct tstream_tls *tlss;
1329 const char *error_pos;
1330 struct tstream_tls_params_internal *tlsp = NULL;
1331 int ret;
1333 req = tevent_req_create(mem_ctx, &state,
1334 struct tstream_tls_accept_state);
1335 if (req == NULL) {
1336 return NULL;
1339 state->tls_stream = tstream_context_create(state,
1340 &tstream_tls_ops,
1341 &tlss,
1342 struct tstream_tls,
1343 location);
1344 if (tevent_req_nomem(state->tls_stream, req)) {
1345 return tevent_req_post(req, ev);
1347 ZERO_STRUCTP(tlss);
1348 talloc_set_destructor(tlss, tstream_tls_destructor);
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!
1355 * See 'man gnutls_credentials_set' and
1356 * 'man gnutls_certificate_set_dh_params'.
1358 * Note: here we use talloc_reference() in a way
1359 * that does not expose it to the caller.
1361 tlsp = talloc_reference(tlss, _tlsp->internal);
1362 if (tevent_req_nomem(tlsp, req)) {
1363 return tevent_req_post(req, ev);
1366 tlss->plain_stream = plain_stream;
1368 tlss->current_ev = ev;
1369 tlss->retry_im = tevent_create_immediate(tlss);
1370 if (tevent_req_nomem(tlss->retry_im, req)) {
1371 return tevent_req_post(req, ev);
1374 ret = gnutls_init(&tlss->tls_session, GNUTLS_SERVER);
1375 if (ret != GNUTLS_E_SUCCESS) {
1376 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1377 tevent_req_error(req, EINVAL);
1378 return tevent_req_post(req, ev);
1381 ret = gnutls_set_default_priority(tlss->tls_session);
1382 if (ret != GNUTLS_E_SUCCESS) {
1383 DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
1384 __location__, gnutls_strerror(ret));
1385 tevent_req_error(req, EINVAL);
1386 return tevent_req_post(req, ev);
1389 if (strlen(tlsp->tls_priority) > 0) {
1390 ret = gnutls_priority_set_direct(tlss->tls_session,
1391 tlsp->tls_priority,
1392 &error_pos);
1393 if (ret != GNUTLS_E_SUCCESS) {
1394 DEBUG(0,("TLS %s - %s. Check 'tls priority' option at '%s'\n",
1395 __location__, gnutls_strerror(ret), error_pos));
1396 tevent_req_error(req, EINVAL);
1397 return tevent_req_post(req, ev);
1401 ret = gnutls_credentials_set(tlss->tls_session, GNUTLS_CRD_CERTIFICATE,
1402 tlsp->x509_cred);
1403 if (ret != GNUTLS_E_SUCCESS) {
1404 DEBUG(0,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1405 tevent_req_error(req, EINVAL);
1406 return tevent_req_post(req, ev);
1409 gnutls_certificate_server_set_request(tlss->tls_session,
1410 GNUTLS_CERT_REQUEST);
1411 gnutls_dh_set_prime_bits(tlss->tls_session, DH_BITS);
1413 gnutls_transport_set_ptr(tlss->tls_session,
1414 (gnutls_transport_ptr_t)state->tls_stream);
1415 gnutls_transport_set_pull_function(tlss->tls_session,
1416 (gnutls_pull_func)tstream_tls_pull_function);
1417 gnutls_transport_set_push_function(tlss->tls_session,
1418 (gnutls_push_func)tstream_tls_push_function);
1420 tlss->handshake.req = req;
1421 tstream_tls_retry_handshake(state->tls_stream);
1422 if (!tevent_req_is_in_progress(req)) {
1423 return tevent_req_post(req, ev);
1426 return req;
1429 static void tstream_tls_retry_handshake(struct tstream_context *stream)
1431 struct tstream_tls *tlss =
1432 tstream_context_data(stream,
1433 struct tstream_tls);
1434 struct tevent_req *req = tlss->handshake.req;
1435 int ret;
1437 if (tlss->error != 0) {
1438 tevent_req_error(req, tlss->error);
1439 return;
1442 ret = gnutls_handshake(tlss->tls_session);
1443 if (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) {
1444 return;
1447 tlss->handshake.req = NULL;
1449 if (gnutls_error_is_fatal(ret) != 0) {
1450 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1451 tlss->error = EIO;
1452 tevent_req_error(req, tlss->error);
1453 return;
1456 if (ret != GNUTLS_E_SUCCESS) {
1457 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1458 tlss->error = EIO;
1459 tevent_req_error(req, tlss->error);
1460 return;
1463 if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_ONLY) {
1464 unsigned int status = UINT32_MAX;
1465 bool ip = true;
1466 const char *hostname = NULL;
1468 if (tlss->peer_name != NULL) {
1469 ip = is_ipaddress(tlss->peer_name);
1472 if (!ip) {
1473 hostname = tlss->peer_name;
1476 if (tlss->verify_peer == TLS_VERIFY_PEER_CA_ONLY) {
1477 hostname = NULL;
1480 if (tlss->verify_peer >= TLS_VERIFY_PEER_CA_AND_NAME) {
1481 if (hostname == NULL) {
1482 DEBUG(1,("TLS %s - no hostname available for "
1483 "verify_peer[%s] and peer_name[%s]\n",
1484 __location__,
1485 tls_verify_peer_string(tlss->verify_peer),
1486 tlss->peer_name));
1487 tlss->error = EINVAL;
1488 tevent_req_error(req, tlss->error);
1489 return;
1493 ret = gnutls_certificate_verify_peers3(tlss->tls_session,
1494 hostname,
1495 &status);
1496 if (ret != GNUTLS_E_SUCCESS) {
1497 DEBUG(1,("TLS %s - %s\n", __location__, gnutls_strerror(ret)));
1498 tlss->error = EIO;
1499 tevent_req_error(req, tlss->error);
1500 return;
1503 if (status != 0) {
1504 DEBUG(1,("TLS %s - check failed for "
1505 "verify_peer[%s] and peer_name[%s] "
1506 "status 0x%x (%s%s%s%s%s%s%s%s)\n",
1507 __location__,
1508 tls_verify_peer_string(tlss->verify_peer),
1509 tlss->peer_name,
1510 status,
1511 status & GNUTLS_CERT_INVALID ? "invalid " : "",
1512 status & GNUTLS_CERT_REVOKED ? "revoked " : "",
1513 status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
1514 "signer_not_found " : "",
1515 status & GNUTLS_CERT_SIGNER_NOT_CA ?
1516 "signer_not_ca " : "",
1517 status & GNUTLS_CERT_INSECURE_ALGORITHM ?
1518 "insecure_algorithm " : "",
1519 status & GNUTLS_CERT_NOT_ACTIVATED ?
1520 "not_activated " : "",
1521 status & GNUTLS_CERT_EXPIRED ?
1522 "expired " : "",
1523 status & GNUTLS_CERT_UNEXPECTED_OWNER ?
1524 "unexpected_owner " : ""));
1525 tlss->error = EINVAL;
1526 tevent_req_error(req, tlss->error);
1527 return;
1531 tevent_req_done(req);
1534 int tstream_tls_accept_recv(struct tevent_req *req,
1535 int *perrno,
1536 TALLOC_CTX *mem_ctx,
1537 struct tstream_context **tls_stream)
1539 struct tstream_tls_accept_state *state =
1540 tevent_req_data(req,
1541 struct tstream_tls_accept_state);
1543 if (tevent_req_is_unix_error(req, perrno)) {
1544 tevent_req_received(req);
1545 return -1;
1548 *tls_stream = talloc_move(mem_ctx, &state->tls_stream);
1549 tevent_req_received(req);
1550 return 0;