/* In GnuTLS 2.12 since we don't have a normal privkey and hence can't just use gnutls_privkey_sign_data() with it, we have to jump through hoops to prepare the hash in exactly the right way and call our internal TPM signing function. */ int gtls2_tpm_sign_dummy_data(struct openconnect_info *vpninfo, const gnutls_datum_t *data, gnutls_datum_t *sig) { static const unsigned char ber_encode[15] = { 0x30, 0x21, /* SEQUENCE, length 31 */ 0x30, 0x09, /* SEQUENCE, length 9 */ 0x06, 0x05, /* OBJECT_ID, length 5 */ 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* SHA1 OID: 1.3.14.3.2.26 */ 0x05, 0x00, /* NULL (parameters) */ 0x04, 0x14, /* OCTET_STRING, length 20 */ /* followed by the 20-byte sha1 */ }; gnutls_datum_t hash; unsigned char digest[sizeof(ber_encode) + SHA1_SIZE]; size_t shalen = SHA1_SIZE; int err; err = gnutls_fingerprint(GNUTLS_DIG_SHA1, data, &digest[sizeof(ber_encode)], &shalen); if (err) { vpn_progress(vpninfo, PRG_ERR, _("Failed to SHA1 input data for signing: %s\n"), gnutls_strerror(err)); return err; } memcpy(digest, ber_encode, sizeof(ber_encode)); hash.data = digest; hash.size = sizeof(digest); return tpm_sign_fn(NULL, vpninfo, &hash, sig); }
const unsigned char* gtlsGeneric::generateSha1(const unsigned char* _data, size_t _data_size) { static unsigned char hash[20]; size_t result_size = 20; unsigned char* buffer = new unsigned char[_data_size]; memcpy(buffer, _data, _data_size); gnutls_datum_t data; data.data = buffer; data.size = _data_size; if (gnutls_fingerprint(SHA_DIGEST, &data, hash, &result_size) < 0) { // BTG_NOTICE("gtlsGeneric::generateSha1() failed"); delete [] buffer; buffer = 0; return 0; } delete [] buffer; buffer = 0; return hash; }
unsigned int ma_ssl_get_finger_print(MARIADB_SSL *cssl, unsigned char *fp, unsigned int len) { MYSQL *mysql; size_t fp_len= len; const gnutls_datum_t *cert_list; unsigned int cert_list_size; if (!cssl || !cssl->ssl) return 0; mysql= (MYSQL *)gnutls_session_get_ptr(cssl->ssl); cert_list = gnutls_certificate_get_peers (cssl->ssl, &cert_list_size); if (cert_list == NULL) { my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ER(CR_SSL_CONNECTION_ERROR), "Unable to get server certificate"); return 0; } if (gnutls_fingerprint(GNUTLS_DIG_SHA1, &cert_list[0], fp, &fp_len) == 0) return fp_len; else { my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN, ER(CR_SSL_CONNECTION_ERROR), "Finger print buffer too small"); return 0; } }
static void vncws_send_handshake_response(VncState *vs, const char* key) { char combined_key[WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1]; unsigned char hash[SHA1_DIGEST_LEN]; size_t hash_size = sizeof(hash); char *accept = NULL, *response = NULL; gnutls_datum_t in; int ret; g_strlcpy(combined_key, key, WS_CLIENT_KEY_LEN + 1); g_strlcat(combined_key, WS_GUID, WS_CLIENT_KEY_LEN + WS_GUID_LEN + 1); /* hash and encode it */ in.data = (void *)combined_key; in.size = WS_CLIENT_KEY_LEN + WS_GUID_LEN; ret = gnutls_fingerprint(GNUTLS_DIG_SHA1, &in, hash, &hash_size); if (ret == GNUTLS_E_SUCCESS && hash_size <= SHA1_DIGEST_LEN) { accept = g_base64_encode(hash, hash_size); } if (accept == NULL) { VNC_DEBUG("Hashing Websocket combined key failed\n"); vnc_client_error(vs); return; } response = g_strdup_printf(WS_HANDSHAKE, accept); vnc_client_write_buf(vs, (const uint8_t *)response, strlen(response)); g_free(accept); g_free(response); vs->encode_ws = 1; vnc_init_state(vs); }
static void ssl_vfy_fp(struct sockifo* ifo) { unsigned int i; uint8_t result[41]; size_t resultsiz = 20; if (!ifo->fingerprint) { esock(ifo, "No fingerprint given"); return; } const gnutls_datum_t* cert = gnutls_certificate_get_peers(ifo->ssl, &i); if (i < 1) { esock(ifo, "No certificate given to fingerprint"); return; } int rv = gnutls_fingerprint(GNUTLS_DIG_SHA1, cert, result + 20, &resultsiz); if (rv) { esock(ifo, gnutls_strerror(rv)); return; } for(i=0; i < 20; i++) { uint8_t v = result[20+i]; result[2*i ] = hex[v / 16]; result[2*i+1] = hex[v % 16]; } result[40] = 0; char* fp = ifo->fingerprint - 1; while (fp) { if (!memcmp(result, fp + 1, 40)) return; fp = strchr(fp + 1, ','); } snprintf(errbuf, sizeof(errbuf), "SSL fingerprint error: got %s expected %s", result, ifo->fingerprint); esock(ifo, errbuf); }
bool_t SSLi_getSHA1Hash(SSL_handle_t *session, uint8_t *hash) { gnutls_datum_t const * certificateData = gnutls_certificate_get_peers(*session, NULL); size_t resultSize = 0; int error = gnutls_fingerprint( GNUTLS_DIG_SHA1, certificateData, hash, &resultSize); return error == GNUTLS_E_SUCCESS && resultSize == 20; }
InfoHash InfoHash::get(const uint8_t* data, size_t data_len) { InfoHash h; size_t s = h.size(); const gnutls_datum_t gnudata = {(uint8_t*)data, (unsigned)data_len}; const gnutls_digest_algorithm_t algo = (HASH_LEN == 64) ? GNUTLS_DIG_SHA512 : ( (HASH_LEN == 32) ? GNUTLS_DIG_SHA256 : ( (HASH_LEN == 20) ? GNUTLS_DIG_SHA1 : GNUTLS_DIG_NULL )); static_assert(algo != GNUTLS_DIG_NULL, "Can't find hash function to use."); int rc = gnutls_fingerprint(algo, &gnudata, h.data(), &s); if (rc == 0 && s == HASH_LEN) return h; throw std::string("Error while hashing"); }
/** * tls_fingerprint - Create a fingerprint of a TLS Certificate * @param algo Fingerprint algorithm, e.g. GNUTLS_MAC_SHA256 * @param buf Buffer for the fingerprint * @param buflen Length of the buffer * @param data Certificate */ static void tls_fingerprint(gnutls_digest_algorithm_t algo, char *buf, size_t buflen, const gnutls_datum_t *data) { unsigned char md[64]; size_t n; n = 64; if (gnutls_fingerprint(algo, data, (char *) md, &n) < 0) { snprintf(buf, buflen, _("[unable to calculate]")); } else { for (int i = 0; i < (int) n; i++) { char ch[8]; snprintf(ch, 8, "%02X%s", md[i], ((i % 2) ? " " : "")); mutt_str_strcat(buf, buflen, ch); } buf[2 * n + n / 2 - 1] = '\0'; /* don't want trailing space */ } }
static void tls_fingerprint (gnutls_digest_algorithm algo, char* s, int l, const gnutls_datum* data) { unsigned char md[36]; size_t n; int j; n = 36; if (gnutls_fingerprint (algo, data, (char *)md, &n) < 0) { snprintf (s, l, _("[unable to calculate]")); } else { for (j = 0; j < (int) n; j++) { char ch[8]; snprintf (ch, 8, "%02X%s", md[j], (j % 2 ? " " : "")); safe_strcat (s, l, ch); } s[2*n+n/2-1] = '\0'; /* don't want trailing space */ } }
std::string Authenticator::computeDigestResponse(std::string &method, std::string &uri) { #if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT // The "response" field is computed as: // md5(md5(<username>:<realm>:<password>):<nonce>:md5(<cmd>:<url>)) size_t md5len = 16; unsigned char md5buf[md5len]; char md5HexBuf[md5len*2+1]; // Step 1: md5(<username>:<realm>:<password>) std::string ha1Data = username() + ":" + realm() + ":" + password(); Debug( 2, "HA1 pre-md5: %s", ha1Data.c_str() ); #if HAVE_DECL_MD5 MD5((unsigned char*)ha1Data.c_str(), ha1Data.length(), md5buf); #elif HAVE_DECL_GNUTLS_FINGERPRINT gnutls_datum_t md5dataha1 = { (unsigned char*)ha1Data.c_str(), ha1Data.length() }; gnutls_fingerprint( GNUTLS_DIG_MD5, &md5dataha1, md5buf, &md5len ); #endif for ( unsigned int j = 0; j < md5len; j++ ) { sprintf(&md5HexBuf[2*j], "%02x", md5buf[j] ); } md5HexBuf[md5len*2]='\0'; std::string ha1Hash = md5HexBuf; // Step 2: md5(<cmd>:<url>) std::string ha2Data = method + ":" + uri; Debug( 2, "HA2 pre-md5: %s", ha2Data.c_str() ); #if HAVE_DECL_MD5 MD5((unsigned char*)ha2Data.c_str(), ha2Data.length(), md5buf ); #elif HAVE_DECL_GNUTLS_FINGERPRINT gnutls_datum_t md5dataha2 = { (unsigned char*)ha2Data.c_str(), ha2Data.length() }; gnutls_fingerprint( GNUTLS_DIG_MD5, &md5dataha2, md5buf, &md5len ); #endif for ( unsigned int j = 0; j < md5len; j++ ) { sprintf( &md5HexBuf[2*j], "%02x", md5buf[j] ); } md5HexBuf[md5len*2]='\0'; std::string ha2Hash = md5HexBuf; // Step 3: md5(ha1:<nonce>:ha2) std::string digestData = ha1Hash + ":" + nonce(); if ( ! fQop.empty() ) { digestData += ":" + stringtf("%08x", nc) + ":"+fCnonce + ":" + fQop; nc ++; // if qop was specified, then we have to include t and a cnonce and an nccount } digestData += ":" + ha2Hash; Debug( 2, "pre-md5: %s", digestData.c_str() ); #if HAVE_DECL_MD5 MD5((unsigned char*)digestData.c_str(), digestData.length(), md5buf); #elif HAVE_DECL_GNUTLS_FINGERPRINT gnutls_datum_t md5datadigest = { (unsigned char*)digestData.c_str(), digestData.length() }; gnutls_fingerprint( GNUTLS_DIG_MD5, &md5datadigest, md5buf, &md5len ); #endif for ( unsigned int j = 0; j < md5len; j++ ) { sprintf( &md5HexBuf[2*j], "%02x", md5buf[j] ); } md5HexBuf[md5len*2]='\0'; return md5HexBuf; #else // HAVE_DECL_MD5 Error( "You need to build with gnutls or openssl installed to use digest authentication" ); return( 0 ); #endif // HAVE_DECL_MD5 }
// Function to validate an authentication string User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) { #if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT #ifdef HAVE_GCRYPT_H // Special initialisation for libgcrypt if ( !gcry_check_version( GCRYPT_VERSION ) ) { Fatal( "Unable to initialise libgcrypt" ); } gcry_control( GCRYCTL_DISABLE_SECMEM, 0 ); gcry_control( GCRYCTL_INITIALIZATION_FINISHED, 0 ); #endif // HAVE_GCRYPT_H const char *remote_addr = ""; if ( use_remote_addr ) { remote_addr = getenv( "REMOTE_ADDR" ); if ( !remote_addr ) { Warning( "Can't determine remote address, using null" ); remote_addr = ""; } } Debug( 1, "Attempting to authenticate user from auth string '%s'", auth ); char sql[ZM_SQL_SML_BUFSIZ] = ""; snprintf( sql, sizeof(sql), "SELECT Id, Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds FROM Users WHERE Enabled = 1" ); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't run query: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } MYSQL_RES *result = mysql_store_result( &dbconn ); if ( !result ) { Error( "Can't use query result: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } int n_users = mysql_num_rows( result ); if ( n_users < 1 ) { mysql_free_result( result ); Warning( "Unable to authenticate user" ); return( 0 ); } while( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) { const char *user = dbrow[1]; const char *pass = dbrow[2]; char auth_key[512] = ""; char auth_md5[32+1] = ""; size_t md5len = 16; unsigned char md5sum[md5len]; time_t now = time( 0 ); unsigned int hours = config.auth_hash_ttl; if ( ! hours ) { Warning("No value set for ZM_AUTH_HASH_TTL. Defaulting to 2."); hours = 2; } else { Debug( 1, "AUTH_HASH_TTL is %d", hours ); } for ( unsigned int i = 0; i < hours; i++, now -= 3600 ) { struct tm *now_tm = localtime( &now ); snprintf( auth_key, sizeof(auth_key), "%s%s%s%s%d%d%d%d", config.auth_hash_secret, user, pass, remote_addr, now_tm->tm_hour, now_tm->tm_mday, now_tm->tm_mon, now_tm->tm_year ); #if HAVE_DECL_MD5 MD5( (unsigned char *)auth_key, strlen(auth_key), md5sum ); #elif HAVE_DECL_GNUTLS_FINGERPRINT gnutls_datum_t md5data = { (unsigned char *)auth_key, strlen(auth_key) }; gnutls_fingerprint( GNUTLS_DIG_MD5, &md5data, md5sum, &md5len ); #endif auth_md5[0] = '\0'; for ( unsigned int j = 0; j < md5len; j++ ) { sprintf( &auth_md5[2*j], "%02x", md5sum[j] ); } Debug( 1, "Checking auth_key '%s' -> auth_md5 '%s' == '%s'", auth_key, auth_md5, auth ); if ( !strcmp( auth, auth_md5 ) ) { // We have a match User *user = new User( dbrow ); Debug(1, "Authenticated user '%s'", user->getUsername() ); mysql_free_result( result ); return( user ); } else { Debug(1, "No match for %s", auth ); } } } mysql_free_result( result ); #else // HAVE_DECL_MD5 Error( "You need to build with gnutls or openssl installed to use hash based authentication" ); #endif // HAVE_DECL_MD5 Debug(1, "No user found for auth_key %s", auth ); return 0; }
static gboolean ssl_verify_certificate (LmSSL *ssl, const gchar *server) { LmSSLBase *base; unsigned int status; int rc; base = LM_SSL_BASE (ssl); /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ rc = gnutls_certificate_verify_peers2 (ssl->gnutls_session, &status); if (rc == GNUTLS_E_NO_CERTIFICATE_FOUND) { if (base->func (ssl, LM_SSL_STATUS_NO_CERT_FOUND, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (rc != 0) { if (base->func (ssl, LM_SSL_STATUS_GENERIC_ERROR, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (rc == GNUTLS_E_NO_CERTIFICATE_FOUND) { if (base->func (ssl, LM_SSL_STATUS_NO_CERT_FOUND, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (status & GNUTLS_CERT_INVALID || status & GNUTLS_CERT_REVOKED) { if (base->func (ssl, LM_SSL_STATUS_UNTRUSTED_CERT, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (gnutls_certificate_expiration_time_peers (ssl->gnutls_session) < time (0)) { if (base->func (ssl, LM_SSL_STATUS_CERT_EXPIRED, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (gnutls_certificate_activation_time_peers (ssl->gnutls_session) > time (0)) { if (base->func (ssl, LM_SSL_STATUS_CERT_NOT_ACTIVATED, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (gnutls_certificate_type_get (ssl->gnutls_session) == GNUTLS_CRT_X509) { const gnutls_datum_t* cert_list; guint cert_list_size; gnutls_digest_algorithm_t digest = GNUTLS_DIG_SHA256; guchar digest_bin[LM_FINGERPRINT_LENGTH]; size_t digest_size; gnutls_x509_crt_t cert; cert_list = gnutls_certificate_get_peers (ssl->gnutls_session, &cert_list_size); if (cert_list == NULL) { if (base->func (ssl, LM_SSL_STATUS_NO_CERT_FOUND, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } gnutls_x509_crt_init (&cert); if (gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER) != 0) { if (base->func (ssl, LM_SSL_STATUS_NO_CERT_FOUND, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (!gnutls_x509_crt_check_hostname (cert, server)) { if (base->func (ssl, LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } gnutls_x509_crt_deinit (cert); digest_size = gnutls_hash_get_len(digest); g_assert(digest_size < sizeof(digest_bin)); if (gnutls_fingerprint (digest, &cert_list[0], digest_bin, &digest_size) >= 0) { _lm_ssl_base_set_fingerprint(base, digest_bin, digest_size); if (_lm_ssl_base_check_fingerprint(base) != 0 && base->func (ssl, LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } else if (base->func (ssl, LM_SSL_STATUS_GENERIC_ERROR, base->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } return TRUE; }
/* This function will print information about this session's peer * certificate. */ static void logcertinfo (gnutls_session_t session) { time_t now = time (NULL); const gnutls_datum_t *cert_list; unsigned cert_list_size = 0; gnutls_x509_crt_t cert; size_t i; int rc; cert_list = gnutls_certificate_get_peers (session, &cert_list_size); if (!cert_list) return; rc = gnutls_x509_crt_init (&cert); if (rc < 0) { syslog (LOG_ERR | LOG_DAEMON, "TLS xci failed (%d): %s", rc, gnutls_strerror (rc)); return; } if (gnutls_certificate_type_get (session) == GNUTLS_CRT_X509) for (i = 0; i < cert_list_size; i++) { time_t expiration_time, activation_time; char *expiration_time_str = NULL, *activation_time_str = NULL; unsigned char *serial = NULL, *serialhex = NULL; char *issuer = NULL, *subject = NULL; size_t seriallen, issuerlen, subjectlen; unsigned char md5fingerprint[16], md5fingerprinthex[3 * 16 + 1]; size_t md5fingerprintlen; int algo; unsigned bits; const char *keytype, *validity; rc = gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER); if (rc < 0) { syslog (LOG_ERR | LOG_DAEMON, "TLS xci[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } md5fingerprintlen = sizeof (md5fingerprint); rc = gnutls_fingerprint (GNUTLS_DIG_MD5, &cert_list[i], md5fingerprint, &md5fingerprintlen); if (rc != GNUTLS_E_SUCCESS) { syslog (LOG_ERR | LOG_DAEMON, "TLS f[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } for (i = 0; i < md5fingerprintlen; i++) sprintf ((char *) &md5fingerprinthex[3 * i], "%.2x:", md5fingerprint[i]); expiration_time = gnutls_x509_crt_get_expiration_time (cert); if (expiration_time == (time_t) - 1) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcget[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } activation_time = gnutls_x509_crt_get_activation_time (cert); if (expiration_time == (time_t) - 1) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcgat[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } expiration_time_str = xstrdup (ctime (&expiration_time)); if (expiration_time_str[strlen (expiration_time_str) - 1] == '\n') expiration_time_str[strlen (expiration_time_str) - 1] = '\0'; activation_time_str = xstrdup (ctime (&activation_time)); if (activation_time_str[strlen (activation_time_str) - 1] == '\n') activation_time_str[strlen (activation_time_str) - 1] = '\0'; rc = gnutls_x509_crt_get_dn (cert, NULL, &subjectlen); if (rc != GNUTLS_E_SUCCESS && rc != GNUTLS_E_SHORT_MEMORY_BUFFER) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcgd[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } subject = xmalloc (++subjectlen); rc = gnutls_x509_crt_get_dn (cert, subject, &subjectlen); if (rc != GNUTLS_E_SUCCESS) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcgd2[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } rc = gnutls_x509_crt_get_issuer_dn (cert, NULL, &issuerlen); if (rc != GNUTLS_E_SUCCESS && rc != GNUTLS_E_SHORT_MEMORY_BUFFER) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcgid[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } issuer = xmalloc (++issuerlen); rc = gnutls_x509_crt_get_issuer_dn (cert, issuer, &issuerlen); if (rc != GNUTLS_E_SUCCESS) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcgid2[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } seriallen = 0; rc = gnutls_x509_crt_get_serial (cert, NULL, &seriallen); if (rc != GNUTLS_E_SUCCESS && rc != GNUTLS_E_SHORT_MEMORY_BUFFER) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcgs[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } serial = xmalloc (seriallen); rc = gnutls_x509_crt_get_serial (cert, serial, &seriallen); if (rc != GNUTLS_E_SUCCESS) { syslog (LOG_ERR | LOG_DAEMON, "TLS xcgs2[%zu] failed (%d): %s", i, rc, gnutls_strerror (rc)); goto cleanup; } serialhex = xmalloc (2 * seriallen + 1); for (i = 0; i < seriallen; i++) sprintf ((char *) &serialhex[2 * i], "%.2x", serial[i]); algo = gnutls_x509_crt_get_pk_algorithm (cert, &bits); if (algo == GNUTLS_PK_RSA) keytype = "RSA modulus"; else if (algo == GNUTLS_PK_DSA) keytype = "DSA exponent"; else keytype = "UNKNOWN"; if (expiration_time < now) validity = "EXPIRED"; else if (activation_time > now) validity = "NOT YET ACTIVATED"; else validity = "valid"; /* This message can arguably belong to LOG_AUTH. */ syslog (LOG_INFO, "TLS client certificate `%s', issued by `%s', " "serial number `%s', MD5 fingerprint `%s', activated `%s', " "expires `%s', version #%d, key %s %d bits, currently %s", subject, issuer, serialhex, md5fingerprinthex, activation_time_str, expiration_time_str, gnutls_x509_crt_get_version (cert), keytype, bits, validity); cleanup: free (serialhex); free (serial); free (expiration_time_str); free (activation_time_str); free (issuer); free (subject); } gnutls_x509_crt_deinit (cert); { unsigned int status; /* Accept default syslog facility for these errors. * They are clearly relevant as audit traces. */ rc = gnutls_certificate_verify_peers2 (session, &status); if (rc != GNUTLS_E_SUCCESS) syslog (LOG_ERR, "TLS client certificate failed (%d): %s", rc, gnutls_strerror (rc)); if (status != 0) syslog (LOG_ERR, "TLS client certificate verify failure (%d)", status); } }
static gboolean ssl_verify_certificate (LmSSL *ssl, const gchar *server) { int status; /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ status = gnutls_certificate_verify_peers (ssl->gnutls_session); if (status == GNUTLS_E_NO_CERTIFICATE_FOUND) { if (ssl->func (ssl, LM_SSL_STATUS_NO_CERT_FOUND, ssl->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (status & GNUTLS_CERT_INVALID || status & GNUTLS_CERT_REVOKED) { if (ssl->func (ssl, LM_SSL_STATUS_UNTRUSTED_CERT, ssl->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (gnutls_certificate_expiration_time_peers (ssl->gnutls_session) < time (0)) { if (ssl->func (ssl, LM_SSL_STATUS_CERT_EXPIRED, ssl->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (gnutls_certificate_activation_time_peers (ssl->gnutls_session) > time (0)) { if (ssl->func (ssl, LM_SSL_STATUS_CERT_NOT_ACTIVATED, ssl->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (gnutls_certificate_type_get (ssl->gnutls_session) == GNUTLS_CRT_X509) { const gnutls_datum* cert_list; guint cert_list_size; size_t digest_size; gnutls_x509_crt cert; cert_list = gnutls_certificate_get_peers (ssl->gnutls_session, &cert_list_size); if (cert_list == NULL) { if (ssl->func (ssl, LM_SSL_STATUS_NO_CERT_FOUND, ssl->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } gnutls_x509_crt_init (&cert); if (!gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER)) { if (ssl->func (ssl, LM_SSL_STATUS_NO_CERT_FOUND, ssl->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } if (!gnutls_x509_crt_check_hostname (cert, server)) { if (ssl->func (ssl, LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH, ssl->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } gnutls_x509_crt_deinit (cert); if (gnutls_fingerprint (GNUTLS_DIG_MD5, &cert_list[0], ssl->fingerprint, &digest_size) >= 0) { if (ssl->expected_fingerprint && memcmp (ssl->expected_fingerprint, ssl->fingerprint, digest_size) && ssl->func (ssl, LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH, ssl->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } else if (ssl->func (ssl, LM_SSL_STATUS_GENERIC_ERROR, ssl->func_data) != LM_SSL_RESPONSE_CONTINUE) { return FALSE; } } return TRUE; }