+static bool tnl_authenticate(tnl_t *tnl) {
+ gnutls_x509_crt cert;
+ const gnutls_datum *certs;
+ int ncerts = 0, result;
+ char buf[1024], *name, *p;
+ int len;
+
+ certs = gnutls_certificate_get_peers(tnl->session, &ncerts);
+
+ if (!certs || !ncerts) {
+ logger(LOG_ERR, _("tnl: no certificates from %s"), tnl->remote.hostname);
+ return false;
+ }
+
+ len = sizeof buf;
+ gnutls_x509_crt_init(&cert);
+ result = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_DER) ?: gnutls_x509_crt_get_dn(cert, buf, &len);
+
+ if(result) {
+ logger(LOG_ERR, _("tnl: error importing certificate from %s: %s"), tnl->remote.hostname, gnutls_strerror(errno));
+ gnutls_x509_crt_deinit(cert);
+ return false;
+ }
+
+ name = strstr(buf, "CN=");
+ if(!name) {
+ logger(LOG_ERR, _("tnl: no name in certificate from %s"), tnl->remote.hostname);
+ gnutls_x509_crt_deinit(cert);
+ return false;
+ }
+
+ name += 3;
+ for(p = name; *p && *p != ','; p++);
+ *p = '\0';
+
+ if(tnl->remote.id && strcmp(tnl->remote.id, name)) {
+ logger(LOG_ERR, _("tnl: peer %s is %s instead of %s"), tnl->remote.hostname, name, tnl->remote.id);
+ return false;
+ }
+
+ replace(tnl->remote.id, name);
+
+ result = gnutls_certificate_verify_peers(tnl->session);
+
+ if(result < 0) {
+ logger(LOG_ERR, "tnl: error verifying certificate from %s (%s): %s\n", tnl->remote.id, tnl->remote.hostname, gnutls_strerror(result));
+ return false;
+ }
+
+ if(result) {
+ logger(LOG_ERR, "tnl: certificate from %s (%s) not good, verification result %x", tnl->remote.id, tnl->remote.hostname, result);
+ return false;
+ }
+}
+
+
+