1 /* $NetBSD: tls_g.c,v 1.3 2021/08/14 16:14:56 christos Exp $ */
2
3 /* tls_g.c - Handle tls/ssl using GNUTLS. */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 2008-2021 The OpenLDAP Foundation.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
12 * Public License.
13 *
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
17 */
18 /* ACKNOWLEDGEMENTS: GNUTLS support written by Howard Chu and
19 * Emily Backes; sponsored by The Written Word (thewrittenword.com)
20 * and Stanford University (stanford.edu).
21 */
22
23 #include <sys/cdefs.h>
24 __RCSID("$NetBSD: tls_g.c,v 1.3 2021/08/14 16:14:56 christos Exp $");
25
26 #include "portable.h"
27
28 #ifdef HAVE_GNUTLS
29
30 #include "ldap_config.h"
31
32 #include <stdio.h>
33
34 #include <ac/stdlib.h>
35 #include <ac/errno.h>
36 #include <ac/socket.h>
37 #include <ac/string.h>
38 #include <ac/ctype.h>
39 #include <ac/time.h>
40 #include <ac/unistd.h>
41 #include <ac/param.h>
42 #include <ac/dirent.h>
43 #include <sys/stat.h>
44 #include <fcntl.h>
45
46 #include "ldap-int.h"
47 #include "ldap-tls.h"
48
49 #include <gnutls/gnutls.h>
50 #include <gnutls/x509.h>
51 #include <gnutls/abstract.h>
52 #include <gnutls/crypto.h>
53
54 typedef struct tlsg_ctx {
55 gnutls_certificate_credentials_t cred;
56 gnutls_dh_params_t dh_params;
57 unsigned long verify_depth;
58 int refcount;
59 int reqcert;
60 gnutls_priority_t prios;
61 #ifdef LDAP_R_COMPILE
62 ldap_pvt_thread_mutex_t ref_mutex;
63 #endif
64 } tlsg_ctx;
65
66 typedef struct tlsg_session {
67 gnutls_session_t session;
68 tlsg_ctx *ctx;
69 struct berval peer_der_dn;
70 } tlsg_session;
71
72 static int tlsg_parse_ciphers( tlsg_ctx *ctx, char *suites );
73 static int tlsg_cert_verify( tlsg_session *s );
74
75 #ifdef LDAP_R_COMPILE
76
77 static void
tlsg_thr_init(void)78 tlsg_thr_init( void )
79 {
80 /* do nothing */
81 }
82 #endif /* LDAP_R_COMPILE */
83
84 /*
85 * Initialize TLS subsystem. Should be called only once.
86 */
87 static int
tlsg_init(void)88 tlsg_init( void )
89 {
90 gnutls_global_init();
91 return 0;
92 }
93
94 /*
95 * Tear down the TLS subsystem. Should only be called once.
96 */
97 static void
tlsg_destroy(void)98 tlsg_destroy( void )
99 {
100 gnutls_global_deinit();
101 }
102
103 static tls_ctx *
tlsg_ctx_new(struct ldapoptions * lo)104 tlsg_ctx_new ( struct ldapoptions *lo )
105 {
106 tlsg_ctx *ctx;
107
108 ctx = ber_memcalloc ( 1, sizeof (*ctx) );
109 if ( ctx ) {
110 if ( gnutls_certificate_allocate_credentials( &ctx->cred )) {
111 ber_memfree( ctx );
112 return NULL;
113 }
114 ctx->refcount = 1;
115 gnutls_priority_init( &ctx->prios, "NORMAL", NULL );
116 #ifdef LDAP_R_COMPILE
117 ldap_pvt_thread_mutex_init( &ctx->ref_mutex );
118 #endif
119 }
120 return (tls_ctx *)ctx;
121 }
122
123 static void
tlsg_ctx_ref(tls_ctx * ctx)124 tlsg_ctx_ref( tls_ctx *ctx )
125 {
126 tlsg_ctx *c = (tlsg_ctx *)ctx;
127 LDAP_MUTEX_LOCK( &c->ref_mutex );
128 c->refcount++;
129 LDAP_MUTEX_UNLOCK( &c->ref_mutex );
130 }
131
132 static void
tlsg_ctx_free(tls_ctx * ctx)133 tlsg_ctx_free ( tls_ctx *ctx )
134 {
135 tlsg_ctx *c = (tlsg_ctx *)ctx;
136 int refcount;
137
138 if ( !c ) return;
139
140 LDAP_MUTEX_LOCK( &c->ref_mutex );
141 refcount = --c->refcount;
142 LDAP_MUTEX_UNLOCK( &c->ref_mutex );
143 if ( refcount )
144 return;
145 gnutls_priority_deinit( c->prios );
146 gnutls_certificate_free_credentials( c->cred );
147 if ( c->dh_params )
148 gnutls_dh_params_deinit( c->dh_params );
149 ber_memfree ( c );
150 }
151
152 static int
tlsg_getfile(const char * path,gnutls_datum_t * buf)153 tlsg_getfile( const char *path, gnutls_datum_t *buf )
154 {
155 int rc = -1, fd;
156 struct stat st;
157 char ebuf[128];
158
159 fd = open( path, O_RDONLY );
160 if ( fd < 0 ) {
161 Debug2( LDAP_DEBUG_ANY,
162 "TLS: opening `%s' failed: %s\n",
163 path,
164 AC_STRERROR_R( errno, ebuf, sizeof ebuf ));
165 return -1;
166 }
167 if ( fstat( fd, &st ) == 0 ) {
168 buf->size = st.st_size;
169 buf->data = LDAP_MALLOC( st.st_size + 1 );
170 if ( buf->data ) {
171 rc = read( fd, buf->data, st.st_size );
172 close( fd );
173 if ( rc < st.st_size )
174 rc = -1;
175 else
176 rc = 0;
177 }
178 }
179 return rc;
180 }
181
182 /* This is the GnuTLS default */
183 #define VERIFY_DEPTH 6
184
185 /*
186 * initialize a new TLS context
187 */
188 static int
tlsg_ctx_init(struct ldapoptions * lo,struct ldaptls * lt,int is_server)189 tlsg_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
190 {
191 tlsg_ctx *ctx = lo->ldo_tls_ctx;
192 int rc;
193
194 if ( lo->ldo_tls_ciphersuite &&
195 tlsg_parse_ciphers( ctx, lt->lt_ciphersuite )) {
196 Debug1( LDAP_DEBUG_ANY,
197 "TLS: could not set cipher list %s.\n",
198 lo->ldo_tls_ciphersuite );
199 return -1;
200 }
201
202 if (lo->ldo_tls_cacertdir != NULL) {
203 rc = gnutls_certificate_set_x509_trust_dir(
204 ctx->cred,
205 lt->lt_cacertdir,
206 GNUTLS_X509_FMT_PEM );
207 if ( rc > 0 ) {
208 Debug2( LDAP_DEBUG_TRACE,
209 "TLS: loaded %d CA certificates from directory `%s'.\n",
210 rc, lt->lt_cacertdir );
211 } else {
212 Debug1( LDAP_DEBUG_ANY,
213 "TLS: warning: no certificate found in CA certificate directory `%s'.\n",
214 lt->lt_cacertdir );
215 /* only warn, no return */
216 }
217 }
218
219 if (lo->ldo_tls_cacertfile != NULL) {
220 rc = gnutls_certificate_set_x509_trust_file(
221 ctx->cred,
222 lt->lt_cacertfile,
223 GNUTLS_X509_FMT_PEM );
224 if ( rc < 0 ) {
225 Debug3( LDAP_DEBUG_ANY,
226 "TLS: could not use CA certificate file `%s': %s (%d)\n",
227 lo->ldo_tls_cacertfile,
228 gnutls_strerror( rc ),
229 rc );
230 return -1;
231 } else if ( rc == 0 ) {
232 Debug1( LDAP_DEBUG_ANY,
233 "TLS: warning: no certificate loaded from CA certificate file `%s'.\n",
234 lo->ldo_tls_cacertfile );
235 /* only warn, no return */
236 }
237 }
238
239 if (lo->ldo_tls_cacert.bv_val != NULL ) {
240 gnutls_datum_t buf;
241 buf.data = (unsigned char *)lo->ldo_tls_cacert.bv_val;
242 buf.size = lo->ldo_tls_cacert.bv_len;
243 rc = gnutls_certificate_set_x509_trust_mem(
244 ctx->cred,
245 &buf,
246 GNUTLS_X509_FMT_DER );
247 if ( rc < 0 ) {
248 Debug2( LDAP_DEBUG_ANY,
249 "TLS: could not use CA certificate: %s (%d)\n",
250 gnutls_strerror( rc ),
251 rc );
252 return -1;
253 }
254 }
255
256 if (( lo->ldo_tls_certfile && lo->ldo_tls_keyfile ) ||
257 ( lo->ldo_tls_cert.bv_val && lo->ldo_tls_key.bv_val )) {
258 gnutls_x509_privkey_t key;
259 gnutls_datum_t buf;
260 gnutls_x509_crt_t certs[VERIFY_DEPTH];
261 unsigned int max = VERIFY_DEPTH;
262
263 rc = gnutls_x509_privkey_init( &key );
264 if ( rc ) return -1;
265
266 /* OpenSSL builds the cert chain for us, but GnuTLS
267 * expects it to be present in the certfile. If it's
268 * not, we have to build it ourselves. So we have to
269 * do some special checks here...
270 */
271 if ( lo->ldo_tls_key.bv_val ) {
272 buf.data = (unsigned char *)lo->ldo_tls_key.bv_val;
273 buf.size = lo->ldo_tls_key.bv_len;
274 rc = gnutls_x509_privkey_import( key, &buf,
275 GNUTLS_X509_FMT_DER );
276 } else {
277 rc = tlsg_getfile( lt->lt_keyfile, &buf );
278 if ( rc ) {
279 Debug1( LDAP_DEBUG_ANY,
280 "TLS: could not use private key file `%s`.\n",
281 lt->lt_keyfile);
282 return -1;
283 }
284 rc = gnutls_x509_privkey_import( key, &buf,
285 GNUTLS_X509_FMT_PEM );
286 LDAP_FREE( buf.data );
287 }
288 if ( rc < 0 ) {
289 Debug2( LDAP_DEBUG_ANY,
290 "TLS: could not use private key: %s (%d)\n",
291 gnutls_strerror( rc ),
292 rc );
293 return rc;
294 }
295
296 if ( lo->ldo_tls_cert.bv_val ) {
297 buf.data = (unsigned char *)lo->ldo_tls_cert.bv_val;
298 buf.size = lo->ldo_tls_cert.bv_len;
299 rc = gnutls_x509_crt_list_import( certs, &max, &buf,
300 GNUTLS_X509_FMT_DER, 0 );
301 } else {
302 rc = tlsg_getfile( lt->lt_certfile, &buf );
303 if ( rc ) {
304 Debug1( LDAP_DEBUG_ANY,
305 "TLS: could not use certificate file `%s`.\n",
306 lt->lt_certfile);
307 return -1;
308 }
309 rc = gnutls_x509_crt_list_import( certs, &max, &buf,
310 GNUTLS_X509_FMT_PEM, 0 );
311 LDAP_FREE( buf.data );
312 }
313 if ( rc < 0 ) {
314 Debug2( LDAP_DEBUG_ANY,
315 "TLS: could not use certificate: %s (%d)\n",
316 gnutls_strerror( rc ),
317 rc );
318 return rc;
319 }
320
321 /* If there's only one cert and it's not self-signed,
322 * then we have to build the cert chain.
323 */
324 if ( max == 1 && !gnutls_x509_crt_check_issuer( certs[0], certs[0] )) {
325 unsigned int i;
326 for ( i = 1; i<VERIFY_DEPTH; i++ ) {
327 if ( gnutls_certificate_get_issuer( ctx->cred, certs[i-1], &certs[i], 0 ))
328 break;
329 max++;
330 /* If this CA is self-signed, we're done */
331 if ( gnutls_x509_crt_check_issuer( certs[i], certs[i] ))
332 break;
333 }
334 }
335 rc = gnutls_certificate_set_x509_key( ctx->cred, certs, max, key );
336 if ( rc ) {
337 Debug2( LDAP_DEBUG_ANY,
338 "TLS: could not use certificate with key: %s (%d)\n",
339 gnutls_strerror( rc ),
340 rc );
341 return -1;
342 }
343 } else if (( lo->ldo_tls_certfile || lo->ldo_tls_keyfile )) {
344 Debug0( LDAP_DEBUG_ANY,
345 "TLS: only one of certfile and keyfile specified\n" );
346 return -1;
347 } else if (( lo->ldo_tls_cert.bv_val || lo->ldo_tls_key.bv_val )) {
348 Debug0( LDAP_DEBUG_ANY,
349 "TLS: only one of cert and key specified\n" );
350 return -1;
351 }
352
353 if ( lo->ldo_tls_crlfile ) {
354 rc = gnutls_certificate_set_x509_crl_file(
355 ctx->cred,
356 lt->lt_crlfile,
357 GNUTLS_X509_FMT_PEM );
358 if ( rc < 0 ) return -1;
359 rc = 0;
360 }
361
362 /* FIXME: ITS#5992 - this should be configurable,
363 * and V1 CA certs should be phased out ASAP.
364 */
365 gnutls_certificate_set_verify_flags( ctx->cred,
366 GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT );
367
368 if ( is_server && lo->ldo_tls_dhfile ) {
369 gnutls_datum_t buf;
370 rc = tlsg_getfile( lo->ldo_tls_dhfile, &buf );
371 if ( rc ) return -1;
372 rc = gnutls_dh_params_init( &ctx->dh_params );
373 if ( rc == 0 )
374 rc = gnutls_dh_params_import_pkcs3( ctx->dh_params, &buf,
375 GNUTLS_X509_FMT_PEM );
376 LDAP_FREE( buf.data );
377 if ( rc ) return -1;
378 gnutls_certificate_set_dh_params( ctx->cred, ctx->dh_params );
379 }
380
381 ctx->reqcert = lo->ldo_tls_require_cert;
382
383 return 0;
384 }
385
386 static tls_session *
tlsg_session_new(tls_ctx * ctx,int is_server)387 tlsg_session_new ( tls_ctx * ctx, int is_server )
388 {
389 tlsg_ctx *c = (tlsg_ctx *)ctx;
390 tlsg_session *session;
391
392 session = ber_memcalloc ( 1, sizeof (*session) );
393 if ( !session )
394 return NULL;
395
396 session->ctx = c;
397 gnutls_init( &session->session, is_server ? GNUTLS_SERVER : GNUTLS_CLIENT );
398 gnutls_priority_set( session->session, c->prios );
399 if ( c->cred )
400 gnutls_credentials_set( session->session, GNUTLS_CRD_CERTIFICATE, c->cred );
401
402 if ( is_server ) {
403 int flag = 0;
404 if ( c->reqcert ) {
405 flag = GNUTLS_CERT_REQUEST;
406 if ( c->reqcert == LDAP_OPT_X_TLS_DEMAND ||
407 c->reqcert == LDAP_OPT_X_TLS_HARD )
408 flag = GNUTLS_CERT_REQUIRE;
409 gnutls_certificate_server_set_request( session->session, flag );
410 }
411 }
412 return (tls_session *)session;
413 }
414
415 static int
tlsg_session_accept(tls_session * session)416 tlsg_session_accept( tls_session *session )
417 {
418 tlsg_session *s = (tlsg_session *)session;
419 int rc;
420
421 rc = gnutls_handshake( s->session );
422 if ( rc == 0 && s->ctx->reqcert != LDAP_OPT_X_TLS_NEVER ) {
423 const gnutls_datum_t *peer_cert_list;
424 unsigned int list_size;
425
426 peer_cert_list = gnutls_certificate_get_peers( s->session,
427 &list_size );
428 if ( !peer_cert_list && s->ctx->reqcert == LDAP_OPT_X_TLS_TRY )
429 rc = 0;
430 else {
431 rc = tlsg_cert_verify( s );
432 if ( rc && s->ctx->reqcert == LDAP_OPT_X_TLS_ALLOW )
433 rc = 0;
434 }
435 }
436 return rc;
437 }
438
439 static int
tlsg_session_connect(LDAP * ld,tls_session * session,const char * name_in)440 tlsg_session_connect( LDAP *ld, tls_session *session, const char *name_in )
441 {
442 tlsg_session *s = (tlsg_session *)session;
443 int rc;
444
445 if ( name_in ) {
446 rc = gnutls_server_name_set( s->session, GNUTLS_NAME_DNS, name_in, strlen(name_in) );
447 if ( rc != GNUTLS_E_SUCCESS ) {
448 return rc;
449 }
450 }
451
452 return tlsg_session_accept( session);
453 }
454
455 static int
tlsg_session_upflags(Sockbuf * sb,tls_session * session,int rc)456 tlsg_session_upflags( Sockbuf *sb, tls_session *session, int rc )
457 {
458 tlsg_session *s = (tlsg_session *)session;
459
460 if ( rc != GNUTLS_E_INTERRUPTED && rc != GNUTLS_E_AGAIN )
461 return 0;
462
463 switch (gnutls_record_get_direction (s->session)) {
464 case 0:
465 sb->sb_trans_needs_read = 1;
466 return 1;
467 case 1:
468 sb->sb_trans_needs_write = 1;
469 return 1;
470 }
471 return 0;
472 }
473
474 static char *
tlsg_session_errmsg(tls_session * sess,int rc,char * buf,size_t len)475 tlsg_session_errmsg( tls_session *sess, int rc, char *buf, size_t len )
476 {
477 return (char *)gnutls_strerror( rc );
478 }
479
480 static void
tlsg_x509_cert_dn(struct berval * cert,struct berval * dn,int get_subject)481 tlsg_x509_cert_dn( struct berval *cert, struct berval *dn, int get_subject )
482 {
483 BerElementBuffer berbuf;
484 BerElement *ber = (BerElement *)&berbuf;
485 ber_tag_t tag;
486 ber_len_t len;
487 ber_int_t i;
488
489 ber_init2( ber, cert, LBER_USE_DER );
490 tag = ber_skip_tag( ber, &len ); /* Sequence */
491 tag = ber_skip_tag( ber, &len ); /* Sequence */
492 tag = ber_peek_tag( ber, &len ); /* Context + Constructed (version) */
493 if ( tag == 0xa0 ) { /* Version is optional */
494 tag = ber_skip_tag( ber, &len );
495 tag = ber_get_int( ber, &i ); /* Int: Version */
496 }
497 tag = ber_skip_tag( ber, &len ); /* Int: Serial (can be longer than ber_int_t) */
498 ber_skip_data( ber, len );
499 tag = ber_skip_tag( ber, &len ); /* Sequence: Signature */
500 ber_skip_data( ber, len );
501 if ( !get_subject ) {
502 tag = ber_peek_tag( ber, &len ); /* Sequence: Issuer DN */
503 } else {
504 tag = ber_skip_tag( ber, &len );
505 ber_skip_data( ber, len );
506 tag = ber_skip_tag( ber, &len ); /* Sequence: Validity */
507 ber_skip_data( ber, len );
508 tag = ber_peek_tag( ber, &len ); /* Sequence: Subject DN */
509 }
510 len = ber_ptrlen( ber );
511 dn->bv_val = cert->bv_val + len;
512 dn->bv_len = cert->bv_len - len;
513 }
514
515 static int
tlsg_session_my_dn(tls_session * session,struct berval * der_dn)516 tlsg_session_my_dn( tls_session *session, struct berval *der_dn )
517 {
518 tlsg_session *s = (tlsg_session *)session;
519 const gnutls_datum_t *x;
520 struct berval bv;
521
522 x = gnutls_certificate_get_ours( s->session );
523
524 if (!x) return LDAP_INVALID_CREDENTIALS;
525
526 bv.bv_val = (char *) x->data;
527 bv.bv_len = x->size;
528
529 tlsg_x509_cert_dn( &bv, der_dn, 1 );
530 return 0;
531 }
532
533 static int
tlsg_session_peer_dn(tls_session * session,struct berval * der_dn)534 tlsg_session_peer_dn( tls_session *session, struct berval *der_dn )
535 {
536 tlsg_session *s = (tlsg_session *)session;
537 if ( !s->peer_der_dn.bv_val ) {
538 const gnutls_datum_t *peer_cert_list;
539 unsigned int list_size;
540 struct berval bv;
541
542 peer_cert_list = gnutls_certificate_get_peers( s->session,
543 &list_size );
544 if ( !peer_cert_list ) return LDAP_INVALID_CREDENTIALS;
545
546 bv.bv_len = peer_cert_list->size;
547 bv.bv_val = (char *) peer_cert_list->data;
548
549 tlsg_x509_cert_dn( &bv, &s->peer_der_dn, 1 );
550 }
551 *der_dn = s->peer_der_dn;
552 return 0;
553 }
554
555 /* what kind of hostname were we given? */
556 #define IS_DNS 0
557 #define IS_IP4 1
558 #define IS_IP6 2
559
560 #define CN_OID "2.5.4.3"
561
562 static int
tlsg_session_chkhost(LDAP * ld,tls_session * session,const char * name_in)563 tlsg_session_chkhost( LDAP *ld, tls_session *session, const char *name_in )
564 {
565 tlsg_session *s = (tlsg_session *)session;
566 int i, ret;
567 int chkSAN = ld->ld_options.ldo_tls_require_san, gotSAN = 0;
568 const gnutls_datum_t *peer_cert_list;
569 unsigned int list_size;
570 char altname[NI_MAXHOST];
571 size_t altnamesize;
572
573 gnutls_x509_crt_t cert;
574 const char *name;
575 char *ptr;
576 char *domain = NULL;
577 #ifdef LDAP_PF_INET6
578 struct in6_addr addr;
579 #else
580 struct in_addr addr;
581 #endif
582 int len1 = 0, len2 = 0;
583 int ntype = IS_DNS;
584
585 if( ldap_int_hostname &&
586 ( !name_in || !strcasecmp( name_in, "localhost" ) ) )
587 {
588 name = ldap_int_hostname;
589 } else {
590 name = name_in;
591 }
592
593 peer_cert_list = gnutls_certificate_get_peers( s->session,
594 &list_size );
595 if ( !peer_cert_list ) {
596 Debug0( LDAP_DEBUG_ANY,
597 "TLS: unable to get peer certificate.\n" );
598 /* If this was a fatal condition, things would have
599 * aborted long before now.
600 */
601 return LDAP_SUCCESS;
602 }
603 ret = gnutls_x509_crt_init( &cert );
604 if ( ret < 0 )
605 return LDAP_LOCAL_ERROR;
606 ret = gnutls_x509_crt_import( cert, peer_cert_list, GNUTLS_X509_FMT_DER );
607 if ( ret ) {
608 gnutls_x509_crt_deinit( cert );
609 return LDAP_LOCAL_ERROR;
610 }
611
612 #ifdef LDAP_PF_INET6
613 if (inet_pton(AF_INET6, name, &addr)) {
614 ntype = IS_IP6;
615 } else
616 #endif
617 if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) {
618 if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4;
619 }
620
621 if (ntype == IS_DNS) {
622 len1 = strlen(name);
623 domain = strchr(name, '.');
624 if (domain) {
625 len2 = len1 - (domain-name);
626 }
627 }
628
629 if (chkSAN) {
630 for ( i=0, ret=0; ret >= 0; i++ ) {
631 altnamesize = sizeof(altname);
632 ret = gnutls_x509_crt_get_subject_alt_name( cert, i,
633 altname, &altnamesize, NULL );
634 if ( ret < 0 ) break;
635
636 gotSAN = 1;
637 /* ignore empty */
638 if ( altnamesize == 0 ) continue;
639
640 if ( ret == GNUTLS_SAN_DNSNAME ) {
641 if (ntype != IS_DNS) continue;
642
643 /* Is this an exact match? */
644 if ((len1 == altnamesize) && !strncasecmp(name, altname, len1)) {
645 break;
646 }
647
648 /* Is this a wildcard match? */
649 if (domain && (altname[0] == '*') && (altname[1] == '.') &&
650 (len2 == altnamesize-1) && !strncasecmp(domain, &altname[1], len2))
651 {
652 break;
653 }
654 } else if ( ret == GNUTLS_SAN_IPADDRESS ) {
655 if (ntype == IS_DNS) continue;
656
657 #ifdef LDAP_PF_INET6
658 if (ntype == IS_IP6 && altnamesize != sizeof(struct in6_addr)) {
659 continue;
660 } else
661 #endif
662 if (ntype == IS_IP4 && altnamesize != sizeof(struct in_addr)) {
663 continue;
664 }
665 if (!memcmp(altname, &addr, altnamesize)) {
666 break;
667 }
668 }
669 }
670 if ( ret >= 0 ) {
671 ret = LDAP_SUCCESS;
672 }
673 }
674 if (ret != LDAP_SUCCESS && chkSAN) {
675 switch(chkSAN) {
676 case LDAP_OPT_X_TLS_DEMAND:
677 case LDAP_OPT_X_TLS_HARD:
678 if (!gotSAN) {
679 Debug0( LDAP_DEBUG_ANY,
680 "TLS: unable to get subjectAltName from peer certificate.\n" );
681 ret = LDAP_CONNECT_ERROR;
682 if ( ld->ld_error ) {
683 LDAP_FREE( ld->ld_error );
684 }
685 ld->ld_error = LDAP_STRDUP(
686 _("TLS: unable to get subjectAltName from peer certificate"));
687 goto done;
688 }
689 /* FALLTHRU */
690 case LDAP_OPT_X_TLS_TRY:
691 if (gotSAN) {
692 Debug1( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
693 "subjectAltName in certificate.\n",
694 name );
695 ret = LDAP_CONNECT_ERROR;
696 if ( ld->ld_error ) {
697 LDAP_FREE( ld->ld_error );
698 }
699 ld->ld_error = LDAP_STRDUP(
700 _("TLS: hostname does not match subjectAltName in peer certificate"));
701 goto done;
702 }
703 break;
704 case LDAP_OPT_X_TLS_ALLOW:
705 break;
706 }
707 }
708
709 if ( ret != LDAP_SUCCESS ){
710 /* find the last CN */
711 i=0;
712 do {
713 altnamesize = 0;
714 ret = gnutls_x509_crt_get_dn_by_oid( cert, CN_OID,
715 i, 1, altname, &altnamesize );
716 if ( ret == GNUTLS_E_SHORT_MEMORY_BUFFER )
717 i++;
718 else
719 break;
720 } while ( 1 );
721
722 if ( i ) {
723 altnamesize = sizeof(altname);
724 ret = gnutls_x509_crt_get_dn_by_oid( cert, CN_OID,
725 i-1, 0, altname, &altnamesize );
726 }
727
728 if ( ret < 0 ) {
729 Debug0( LDAP_DEBUG_ANY,
730 "TLS: unable to get common name from peer certificate.\n" );
731 ret = LDAP_CONNECT_ERROR;
732 if ( ld->ld_error ) {
733 LDAP_FREE( ld->ld_error );
734 }
735 ld->ld_error = LDAP_STRDUP(
736 _("TLS: unable to get CN from peer certificate"));
737
738 } else {
739 ret = LDAP_LOCAL_ERROR;
740 if ( !len1 ) len1 = strlen( name );
741 if ( len1 == altnamesize && strncasecmp(name, altname, altnamesize) == 0 ) {
742 ret = LDAP_SUCCESS;
743
744 } else if (( altname[0] == '*' ) && ( altname[1] == '.' )) {
745 /* Is this a wildcard match? */
746 if( domain &&
747 (len2 == altnamesize-1) && !strncasecmp(domain, &altname[1], len2)) {
748 ret = LDAP_SUCCESS;
749 }
750 }
751 }
752
753 if( ret == LDAP_LOCAL_ERROR ) {
754 altname[altnamesize] = '\0';
755 Debug2( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
756 "common name in certificate (%s).\n",
757 name, altname );
758 ret = LDAP_CONNECT_ERROR;
759 if ( ld->ld_error ) {
760 LDAP_FREE( ld->ld_error );
761 }
762 ld->ld_error = LDAP_STRDUP(
763 _("TLS: hostname does not match name in peer certificate"));
764 }
765 }
766 done:
767 gnutls_x509_crt_deinit( cert );
768 return ret;
769 }
770
771 static int
tlsg_session_strength(tls_session * session)772 tlsg_session_strength( tls_session *session )
773 {
774 tlsg_session *s = (tlsg_session *)session;
775 gnutls_cipher_algorithm_t c;
776
777 c = gnutls_cipher_get( s->session );
778 return gnutls_cipher_get_key_size( c ) * 8;
779 }
780
781 static int
tlsg_session_unique(tls_session * sess,struct berval * buf,int is_server)782 tlsg_session_unique( tls_session *sess, struct berval *buf, int is_server)
783 {
784 tlsg_session *s = (tlsg_session *)sess;
785 gnutls_datum_t cb;
786 int rc;
787
788 rc = gnutls_session_channel_binding( s->session, GNUTLS_CB_TLS_UNIQUE, &cb );
789 if ( rc == 0 ) {
790 int len = cb.size;
791 if ( len > buf->bv_len )
792 len = buf->bv_len;
793 buf->bv_len = len;
794 memcpy( buf->bv_val, cb.data, len );
795 return len;
796 }
797 return 0;
798 }
799
800 static int
tlsg_session_endpoint(tls_session * sess,struct berval * buf,int is_server)801 tlsg_session_endpoint( tls_session *sess, struct berval *buf, int is_server )
802 {
803 tlsg_session *s = (tlsg_session *)sess;
804 const gnutls_datum_t *cert_data;
805 gnutls_x509_crt_t server_cert;
806 gnutls_digest_algorithm_t md;
807 int sign_algo, md_len, rc;
808
809 if ( is_server )
810 cert_data = gnutls_certificate_get_ours( s->session );
811 else
812 cert_data = gnutls_certificate_get_peers( s->session, NULL );
813
814 if ( cert_data == NULL )
815 return 0;
816
817 rc = gnutls_x509_crt_init( &server_cert );
818 if ( rc != GNUTLS_E_SUCCESS )
819 return 0;
820
821 rc = gnutls_x509_crt_import( server_cert, cert_data, GNUTLS_X509_FMT_DER );
822 if ( rc != GNUTLS_E_SUCCESS ) {
823 gnutls_x509_crt_deinit( server_cert );
824 return 0;
825 }
826
827 sign_algo = gnutls_x509_crt_get_signature_algorithm( server_cert );
828 gnutls_x509_crt_deinit( server_cert );
829 if ( sign_algo <= GNUTLS_SIGN_UNKNOWN )
830 return 0;
831
832 md = gnutls_sign_get_hash_algorithm( sign_algo );
833 if ( md == GNUTLS_DIG_UNKNOWN )
834 return 0;
835
836 /* See RFC 5929 */
837 switch (md) {
838 case GNUTLS_DIG_NULL:
839 case GNUTLS_DIG_MD2:
840 case GNUTLS_DIG_MD5:
841 case GNUTLS_DIG_SHA1:
842 md = GNUTLS_DIG_SHA256;
843 }
844
845 md_len = gnutls_hash_get_len( md );
846 if ( md_len == 0 || md_len > buf->bv_len )
847 return 0;
848
849 rc = gnutls_hash_fast( md, cert_data->data, cert_data->size, buf->bv_val );
850 if ( rc != GNUTLS_E_SUCCESS )
851 return 0;
852
853 buf->bv_len = md_len;
854
855 return md_len;
856 }
857
858 static const char *
tlsg_session_version(tls_session * sess)859 tlsg_session_version( tls_session *sess )
860 {
861 tlsg_session *s = (tlsg_session *)sess;
862 return gnutls_protocol_get_name(gnutls_protocol_get_version( s->session ));
863 }
864
865 static const char *
tlsg_session_cipher(tls_session * sess)866 tlsg_session_cipher( tls_session *sess )
867 {
868 tlsg_session *s = (tlsg_session *)sess;
869 return gnutls_cipher_get_name(gnutls_cipher_get( s->session ));
870 }
871
872 static int
tlsg_session_peercert(tls_session * sess,struct berval * der)873 tlsg_session_peercert( tls_session *sess, struct berval *der )
874 {
875 tlsg_session *s = (tlsg_session *)sess;
876 const gnutls_datum_t *peer_cert_list;
877 unsigned int list_size;
878
879 peer_cert_list = gnutls_certificate_get_peers( s->session, &list_size );
880 if (!peer_cert_list)
881 return -1;
882 der->bv_len = peer_cert_list[0].size;
883 der->bv_val = LDAP_MALLOC( der->bv_len );
884 if (!der->bv_val)
885 return -1;
886 memcpy(der->bv_val, peer_cert_list[0].data, der->bv_len);
887 return 0;
888 }
889
890 static int
tlsg_session_pinning(LDAP * ld,tls_session * sess,char * hashalg,struct berval * hash)891 tlsg_session_pinning( LDAP *ld, tls_session *sess, char *hashalg, struct berval *hash )
892 {
893 tlsg_session *s = (tlsg_session *)sess;
894 const gnutls_datum_t *cert_list;
895 unsigned int cert_list_size = 0;
896 gnutls_x509_crt_t crt;
897 gnutls_pubkey_t pubkey;
898 gnutls_datum_t key = {};
899 gnutls_digest_algorithm_t alg;
900 struct berval keyhash;
901 size_t len;
902 int rc = -1;
903
904 if ( hashalg ) {
905 alg = gnutls_digest_get_id( hashalg );
906 if ( alg == GNUTLS_DIG_UNKNOWN ) {
907 Debug1( LDAP_DEBUG_ANY, "tlsg_session_pinning: "
908 "unknown hashing algorithm for GnuTLS: '%s'\n",
909 hashalg );
910 return rc;
911 }
912 }
913
914 cert_list = gnutls_certificate_get_peers( s->session, &cert_list_size );
915 if ( cert_list_size == 0 ) {
916 return rc;
917 }
918
919 if ( gnutls_x509_crt_init( &crt ) < 0 ) {
920 return rc;
921 }
922
923 if ( gnutls_x509_crt_import( crt, &cert_list[0], GNUTLS_X509_FMT_DER ) ) {
924 goto done;
925 }
926
927 if ( gnutls_pubkey_init( &pubkey ) ) {
928 goto done;
929 }
930
931 if ( gnutls_pubkey_import_x509( pubkey, crt, 0 ) < 0 ) {
932 goto done;
933 }
934
935 gnutls_pubkey_export( pubkey, GNUTLS_X509_FMT_DER, key.data, &len );
936 if ( len <= 0 ) {
937 goto done;
938 }
939
940 key.data = LDAP_MALLOC( len );
941 if ( !key.data ) {
942 goto done;
943 }
944
945 key.size = len;
946
947 if ( gnutls_pubkey_export( pubkey, GNUTLS_X509_FMT_DER,
948 key.data, &len ) < 0 ) {
949 goto done;
950 }
951
952 if ( hashalg ) {
953 keyhash.bv_len = gnutls_hash_get_len( alg );
954 keyhash.bv_val = LDAP_MALLOC( keyhash.bv_len );
955 if ( !keyhash.bv_val || gnutls_fingerprint( alg, &key,
956 keyhash.bv_val, &keyhash.bv_len ) < 0 ) {
957 goto done;
958 }
959 } else {
960 keyhash.bv_val = (char *)key.data;
961 keyhash.bv_len = key.size;
962 }
963
964 if ( ber_bvcmp( hash, &keyhash ) ) {
965 rc = LDAP_CONNECT_ERROR;
966 Debug0( LDAP_DEBUG_ANY, "tlsg_session_pinning: "
967 "public key hash does not match provided pin.\n" );
968 if ( ld->ld_error ) {
969 LDAP_FREE( ld->ld_error );
970 }
971 ld->ld_error = LDAP_STRDUP(
972 _("TLS: public key hash does not match provided pin"));
973 } else {
974 rc = LDAP_SUCCESS;
975 }
976
977 done:
978 if ( pubkey ) {
979 gnutls_pubkey_deinit( pubkey );
980 }
981 if ( crt ) {
982 gnutls_x509_crt_deinit( crt );
983 }
984 if ( keyhash.bv_val != (char *)key.data ) {
985 LDAP_FREE( keyhash.bv_val );
986 }
987 if ( key.data ) {
988 LDAP_FREE( key.data );
989 }
990 return rc;
991 }
992
993 /* suites is a string of colon-separated cipher suite names. */
994 static int
tlsg_parse_ciphers(tlsg_ctx * ctx,char * suites)995 tlsg_parse_ciphers( tlsg_ctx *ctx, char *suites )
996 {
997 const char *err;
998 int rc = gnutls_priority_init( &ctx->prios, suites, &err );
999 if ( rc )
1000 ctx->prios = NULL;
1001 return rc;
1002 }
1003
1004 /*
1005 * TLS support for LBER Sockbufs
1006 */
1007
1008 struct tls_data {
1009 tlsg_session *session;
1010 Sockbuf_IO_Desc *sbiod;
1011 };
1012
1013 static ssize_t
tlsg_recv(gnutls_transport_ptr_t ptr,void * buf,size_t len)1014 tlsg_recv( gnutls_transport_ptr_t ptr, void *buf, size_t len )
1015 {
1016 struct tls_data *p;
1017
1018 if ( buf == NULL || len <= 0 ) return 0;
1019
1020 p = (struct tls_data *)ptr;
1021
1022 if ( p == NULL || p->sbiod == NULL ) {
1023 return 0;
1024 }
1025
1026 return LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
1027 }
1028
1029 static ssize_t
tlsg_send(gnutls_transport_ptr_t ptr,const void * buf,size_t len)1030 tlsg_send( gnutls_transport_ptr_t ptr, const void *buf, size_t len )
1031 {
1032 struct tls_data *p;
1033
1034 if ( buf == NULL || len <= 0 ) return 0;
1035
1036 p = (struct tls_data *)ptr;
1037
1038 if ( p == NULL || p->sbiod == NULL ) {
1039 return 0;
1040 }
1041
1042 return LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
1043 }
1044
1045 static int
tlsg_sb_setup(Sockbuf_IO_Desc * sbiod,void * arg)1046 tlsg_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg )
1047 {
1048 struct tls_data *p;
1049 tlsg_session *session = arg;
1050
1051 assert( sbiod != NULL );
1052
1053 p = LBER_MALLOC( sizeof( *p ) );
1054 if ( p == NULL ) {
1055 return -1;
1056 }
1057
1058 gnutls_transport_set_ptr( session->session, (gnutls_transport_ptr_t)p );
1059 gnutls_transport_set_pull_function( session->session, tlsg_recv );
1060 gnutls_transport_set_push_function( session->session, tlsg_send );
1061 p->session = session;
1062 p->sbiod = sbiod;
1063 sbiod->sbiod_pvt = p;
1064 return 0;
1065 }
1066
1067 static int
tlsg_sb_remove(Sockbuf_IO_Desc * sbiod)1068 tlsg_sb_remove( Sockbuf_IO_Desc *sbiod )
1069 {
1070 struct tls_data *p;
1071
1072 assert( sbiod != NULL );
1073 assert( sbiod->sbiod_pvt != NULL );
1074
1075 p = (struct tls_data *)sbiod->sbiod_pvt;
1076 gnutls_deinit ( p->session->session );
1077 LBER_FREE( p->session );
1078 LBER_FREE( sbiod->sbiod_pvt );
1079 sbiod->sbiod_pvt = NULL;
1080 return 0;
1081 }
1082
1083 static int
tlsg_sb_close(Sockbuf_IO_Desc * sbiod)1084 tlsg_sb_close( Sockbuf_IO_Desc *sbiod )
1085 {
1086 struct tls_data *p;
1087
1088 assert( sbiod != NULL );
1089 assert( sbiod->sbiod_pvt != NULL );
1090
1091 p = (struct tls_data *)sbiod->sbiod_pvt;
1092 gnutls_bye ( p->session->session, GNUTLS_SHUT_WR );
1093 return 0;
1094 }
1095
1096 static int
tlsg_sb_ctrl(Sockbuf_IO_Desc * sbiod,int opt,void * arg)1097 tlsg_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
1098 {
1099 struct tls_data *p;
1100
1101 assert( sbiod != NULL );
1102 assert( sbiod->sbiod_pvt != NULL );
1103
1104 p = (struct tls_data *)sbiod->sbiod_pvt;
1105
1106 if ( opt == LBER_SB_OPT_GET_SSL ) {
1107 *((tlsg_session **)arg) = p->session;
1108 return 1;
1109
1110 } else if ( opt == LBER_SB_OPT_DATA_READY ) {
1111 if( gnutls_record_check_pending( p->session->session ) > 0 ) {
1112 return 1;
1113 }
1114 }
1115
1116 return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
1117 }
1118
1119 static ber_slen_t
tlsg_sb_read(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)1120 tlsg_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
1121 {
1122 struct tls_data *p;
1123 ber_slen_t ret;
1124
1125 assert( sbiod != NULL );
1126 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
1127
1128 p = (struct tls_data *)sbiod->sbiod_pvt;
1129
1130 ret = gnutls_record_recv ( p->session->session, buf, len );
1131 switch (ret) {
1132 case GNUTLS_E_INTERRUPTED:
1133 case GNUTLS_E_AGAIN:
1134 sbiod->sbiod_sb->sb_trans_needs_read = 1;
1135 sock_errset(EWOULDBLOCK);
1136 ret = 0;
1137 break;
1138 case GNUTLS_E_REHANDSHAKE:
1139 for ( ret = gnutls_handshake ( p->session->session );
1140 ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN;
1141 ret = gnutls_handshake ( p->session->session ) );
1142 sbiod->sbiod_sb->sb_trans_needs_read = 1;
1143 ret = 0;
1144 break;
1145 default:
1146 sbiod->sbiod_sb->sb_trans_needs_read = 0;
1147 }
1148 return ret;
1149 }
1150
1151 static ber_slen_t
tlsg_sb_write(Sockbuf_IO_Desc * sbiod,void * buf,ber_len_t len)1152 tlsg_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
1153 {
1154 struct tls_data *p;
1155 ber_slen_t ret;
1156
1157 assert( sbiod != NULL );
1158 assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
1159
1160 p = (struct tls_data *)sbiod->sbiod_pvt;
1161
1162 ret = gnutls_record_send ( p->session->session, (char *)buf, len );
1163
1164 if ( ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN ) {
1165 sbiod->sbiod_sb->sb_trans_needs_write = 1;
1166 sock_errset(EWOULDBLOCK);
1167 ret = 0;
1168 } else {
1169 sbiod->sbiod_sb->sb_trans_needs_write = 0;
1170 }
1171 return ret;
1172 }
1173
1174 static Sockbuf_IO tlsg_sbio =
1175 {
1176 tlsg_sb_setup, /* sbi_setup */
1177 tlsg_sb_remove, /* sbi_remove */
1178 tlsg_sb_ctrl, /* sbi_ctrl */
1179 tlsg_sb_read, /* sbi_read */
1180 tlsg_sb_write, /* sbi_write */
1181 tlsg_sb_close /* sbi_close */
1182 };
1183
1184 /* Certs are not automatically verified during the handshake */
1185 static int
tlsg_cert_verify(tlsg_session * ssl)1186 tlsg_cert_verify( tlsg_session *ssl )
1187 {
1188 unsigned int status = 0;
1189 int err;
1190 time_t now = time(0);
1191 time_t peertime;
1192
1193 err = gnutls_certificate_verify_peers2( ssl->session, &status );
1194 if ( err < 0 ) {
1195 Debug1( LDAP_DEBUG_ANY,"TLS: gnutls_certificate_verify_peers2 failed %d\n",
1196 err );
1197 return -1;
1198 }
1199 if ( status ) {
1200 Debug1( LDAP_DEBUG_TRACE,"TLS: peer cert untrusted or revoked (0x%x)\n",
1201 status );
1202 return -1;
1203 }
1204 peertime = gnutls_certificate_expiration_time_peers( ssl->session );
1205 if ( peertime == (time_t) -1 ) {
1206 Debug0( LDAP_DEBUG_ANY, "TLS: gnutls_certificate_expiration_time_peers failed\n" );
1207 return -1;
1208 }
1209 if ( peertime < now ) {
1210 Debug0( LDAP_DEBUG_ANY, "TLS: peer certificate is expired\n" );
1211 return -1;
1212 }
1213 peertime = gnutls_certificate_activation_time_peers( ssl->session );
1214 if ( peertime == (time_t) -1 ) {
1215 Debug0( LDAP_DEBUG_ANY, "TLS: gnutls_certificate_activation_time_peers failed\n" );
1216 return -1;
1217 }
1218 if ( peertime > now ) {
1219 Debug0( LDAP_DEBUG_ANY, "TLS: peer certificate not yet active\n" );
1220 return -1;
1221 }
1222 return 0;
1223 }
1224
1225 tls_impl ldap_int_tls_impl = {
1226 "GnuTLS",
1227
1228 tlsg_init,
1229 tlsg_destroy,
1230
1231 tlsg_ctx_new,
1232 tlsg_ctx_ref,
1233 tlsg_ctx_free,
1234 tlsg_ctx_init,
1235
1236 tlsg_session_new,
1237 tlsg_session_connect,
1238 tlsg_session_accept,
1239 tlsg_session_upflags,
1240 tlsg_session_errmsg,
1241 tlsg_session_my_dn,
1242 tlsg_session_peer_dn,
1243 tlsg_session_chkhost,
1244 tlsg_session_strength,
1245 tlsg_session_unique,
1246 tlsg_session_endpoint,
1247 tlsg_session_version,
1248 tlsg_session_cipher,
1249 tlsg_session_peercert,
1250 tlsg_session_pinning,
1251
1252 &tlsg_sbio,
1253
1254 #ifdef LDAP_R_COMPILE
1255 tlsg_thr_init,
1256 #else
1257 NULL,
1258 #endif
1259
1260 0
1261 };
1262
1263 #endif /* HAVE_GNUTLS */
1264