int mailaddr_match(const struct mailaddr *maddr1, const struct mailaddr *maddr2) { struct mailaddr m1 = *maddr1; struct mailaddr m2 = *maddr2; char *p; /* catchall */ if (m2.user[0] == '\0' && m2.domain[0] == '\0') return 1; if (!hostname_match(m1.domain, m2.domain)) return 0; if (m2.user[0]) { /* if address from table has a tag, we must respect it */ if (strchr(m2.user, *env->sc_subaddressing_delim) == NULL) { /* otherwise, strip tag from session address if any */ p = strchr(m1.user, *env->sc_subaddressing_delim); if (p) *p = '\0'; } if (strcasecmp(m1.user, m2.user)) return 0; } return 1; }
/* Server Name Indication callback function */ static int sni_callback(void *sad, ssl_context *context, const unsigned char *sni_hostname, size_t len) { char hostname[SNI_MAX_HOSTNAME_LEN + 1]; t_sni_list *sni; int i; if (len > SNI_MAX_HOSTNAME_LEN) { return -1; } memcpy(hostname, sni_hostname, len); hostname[len] = '\0'; sni = sni_list; while (sni != NULL) { for (i = 0; i < sni->hostname->size; i++) { if (hostname_match(hostname, *(sni->hostname->item + i))) { ((t_ssl_accept_data*)sad)->timeout = HS_TIMEOUT_CERT_SELECT; /* Set private key and certificate */ if ((sni->private_key != NULL) && (sni->certificate != NULL)) { ssl_set_own_cert(context, sni->certificate, sni->private_key); } /* Set CA certificate for SSL client authentication */ if (sni->ca_certificate != NULL) { ssl_set_authmode(context, SSL_VERIFY_REQUIRED); ssl_set_ca_chain(context, sni->ca_certificate, sni->ca_crl, NULL); } return 0; } } sni = sni->next; } return 0; }
/* Server Name Indication callback function */ static int sni_callback(void UNUSED(*param), mbedtls_ssl_context *context, const unsigned char *sni_hostname, size_t len) { char hostname[SNI_MAX_HOSTNAME_LEN + 1]; t_sni_list *sni; int i; if (len > SNI_MAX_HOSTNAME_LEN) { return -1; } memcpy(hostname, sni_hostname, len); hostname[len] = '\0'; sni = sni_list; while (sni != NULL) { for (i = 0; i < sni->hostname->size; i++) { if (hostname_match(hostname, *(sni->hostname->item + i))) { /* Set private key and certificate */ if ((sni->private_key != NULL) && (sni->certificate != NULL)) { mbedtls_ssl_set_hs_own_cert(context, sni->certificate, sni->private_key); } /* Set CA certificate for TLS client authentication */ if (sni->ca_certificate != NULL) { mbedtls_ssl_set_hs_authmode(context, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_set_hs_ca_chain(context, sni->ca_certificate, sni->ca_crl); } return 0; } } sni = sni->next; } return 0; }
/* * Check whether a rule matches the provided info. */ static bool rule_matches(rule_t rule, const char * dbname, const char * user, SockAddr ip, char * hostname) { /* only one of the CHECK_IP / CHECK_HOST flags can be set */ Assert(!((rule.fields & CHECK_IP) && (rule.fields & CHECK_HOST))); /* dbname does not match */ if ((rule.fields & CHECK_DBNAME) && (strcmp(rule.database, dbname) != 0)) return false; /* username does not match */ if ((rule.fields & CHECK_USER) && (strcmp(rule.user, user) != 0)) return false; /* check the IP address (mask etc.) */ if (rule.fields & CHECK_IP) if (! check_ip(&ip, (struct sockaddr *)&rule.ip, (struct sockaddr *)&rule.mask)) return false; if ((rule.fields & CHECK_HOST) && (strcmp(rule.hostname, hostname) != 0)) { int ret; bool found = false; struct addrinfo *gai_result, *gai; /* was the reverse lookup successfull? */ if (hostname && (! hostname_match(rule.hostname, hostname))) return false; ret = getaddrinfo(rule.hostname, NULL, NULL, &gai_result); if (ret != 0) ereport(WARNING, (errmsg("could not translate host name \"%s\" to address: %s", rule.hostname, gai_strerror(ret)))); for (gai = gai_result; gai; gai = gai->ai_next) { if (gai->ai_addr->sa_family == ip.addr.ss_family) { if (gai->ai_addr->sa_family == AF_INET) { if (ipv4eq((struct sockaddr_in *) gai->ai_addr, (struct sockaddr_in *) & ip.addr)) { found = true; break; } } #ifdef HAVE_IPV6 else if (gai->ai_addr->sa_family == AF_INET6) { if (ipv6eq((struct sockaddr_in6 *) gai->ai_addr, (struct sockaddr_in6 *) & ip.addr)) { found = true; break; } } #endif } } if (gai_result) freeaddrinfo(gai_result); if (! found) { elog(WARNING, "pg_hba.conf host name \"%s\" rejected because address " "resolution did not return a match with IP address of client", rule.hostname); return false; } } return true; }
void multicast_recv(void) { socklen_t addrlen; int msg_id, n, nbytes = 0; char *line, *eol, *s, recv_buf[1025]; char from[128], to[256], message[256]; char msg_type[32], action[256]; boolean repeat, match; if (fd_recv < 0 || !pikrellcam.multicast_enable) return; ioctl(fd_recv, FIONREAD, &nbytes); if (nbytes <= 0) return; addrlen = sizeof(addr_recv); if ((nbytes = recvfrom(fd_recv, recv_buf, sizeof(recv_buf) - 1, 0, (struct sockaddr *) &addr_recv, &addrlen)) <= 0) return; if (recv_buf[nbytes - 1] != '\n') recv_buf[nbytes++] = '\n'; recv_buf[nbytes] = '\0'; line = recv_buf; while (*line) { eol = strchr(line, '\n'); if (!eol) break; *eol++ = '\0'; msg_id = 0; repeat = FALSE; from[0] = to[0] = message[0] = '\0'; n = sscanf(line, "%127s %255s %255[^\n]", from, to, message); if (pikrellcam.verbose_multicast) printf("multicast recv: <%s> <%s> <%s>\n", from, to, message); if ((s = strchr(from, ':')) != NULL) { *s++ = '\0'; msg_id = atoi(s); repeat = multicast_message_id_repeat(from, msg_id); } if (n == 3) { if ((match = hostname_match(from, to)) && !repeat) { if (pikrellcam.verbose_multicast) printf(" message accepted for %s\n", pikrellcam.hostname); if (sscanf(message, "%31s %255[^\n]", msg_type, action) == 2) { dup_string(&pikrellcam.multicast_from_hostname, from); if (!strcmp(msg_type, "command")) exec_no_wait(action, NULL); else if (!strcmp(msg_type, "pkc-message")) /* user defined */ exec_no_wait(pikrellcam.on_multicast_message_cmd, action); /* ack and other message types are ignored */ } else if (pikrellcam.verbose_multicast) printf(" msg_type action parse fail.\n"); } else if (pikrellcam.verbose_multicast) printf(" message rejected: %s\n", !match ? "hostname match failed" : "repeated message"); if (match && msg_id > 0) multicast_ack(from, msg_id); } line = eol; } }
/* port to mutt from msmtp's tls.c */ static int check_host (X509 *x509cert, const char *hostname, char *err, size_t errlen) { int i, rc = 0; /* hostname in ASCII format: */ char *hostname_ascii = NULL; /* needed to get the common name: */ X509_NAME *x509_subject; char *buf = NULL; int bufsize; /* needed to get the DNS subjectAltNames: */ STACK_OF(GENERAL_NAME) *subj_alt_names; int subj_alt_names_count; GENERAL_NAME *subj_alt_name; /* did we find a name matching hostname? */ int match_found; /* Check if 'hostname' matches the one of the subjectAltName extensions of * type DNS or the Common Name (CN). */ #ifdef HAVE_LIBIDN if (idna_to_ascii_lz(hostname, &hostname_ascii, 0) != IDNA_SUCCESS) { hostname_ascii = safe_strdup(hostname); } #else hostname_ascii = safe_strdup(hostname); #endif /* Try the DNS subjectAltNames. */ match_found = 0; if ((subj_alt_names = X509_get_ext_d2i(x509cert, NID_subject_alt_name, NULL, NULL))) { subj_alt_names_count = sk_GENERAL_NAME_num(subj_alt_names); for (i = 0; i < subj_alt_names_count; i++) { subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i); if (subj_alt_name->type == GEN_DNS) { if (subj_alt_name->d.ia5->length >= 0 && mutt_strlen((char *)subj_alt_name->d.ia5->data) == (size_t)subj_alt_name->d.ia5->length && (match_found = hostname_match(hostname_ascii, (char *)(subj_alt_name->d.ia5->data)))) { break; } } } } if (!match_found) { /* Try the common name */ if (!(x509_subject = X509_get_subject_name(x509cert))) { if (err && errlen) strfcpy (err, _("cannot get certificate subject"), errlen); goto out; } /* first get the space requirements */ bufsize = X509_NAME_get_text_by_NID(x509_subject, NID_commonName, NULL, 0); if (bufsize == -1) { if (err && errlen) strfcpy (err, _("cannot get certificate common name"), errlen); goto out; } bufsize++; /* space for the terminal nul char */ buf = safe_malloc((size_t)bufsize); if (X509_NAME_get_text_by_NID(x509_subject, NID_commonName, buf, bufsize) == -1) { if (err && errlen) strfcpy (err, _("cannot get certificate common name"), errlen); goto out; } /* cast is safe since bufsize is incremented above, so bufsize-1 is always * zero or greater. */ if (mutt_strlen(buf) == (size_t)bufsize - 1) { match_found = hostname_match(hostname_ascii, buf); } } if (!match_found) { if (err && errlen) snprintf (err, errlen, _("certificate owner does not match hostname %s"), hostname); goto out; } rc = 1; out: FREE(&buf); FREE(&hostname_ascii); return rc; }
int tls_check_cert(tls_t *tls, const char *hostname, char **errstr) { #ifdef HAVE_LIBGNUTLS int error_code; const char *error_msg; unsigned int status; const gnutls_datum_t *cert_list; unsigned int cert_list_size; unsigned int i; gnutls_x509_crt_t cert; time_t t1, t2; size_t size; unsigned char fingerprint[20]; char *idn_hostname = NULL; if (tls->have_trust_file || tls->have_sha1_fingerprint || tls->have_md5_fingerprint) { error_msg = _("TLS certificate verification failed"); } else { error_msg = _("TLS certificate check failed"); } if (tls->have_sha1_fingerprint || tls->have_md5_fingerprint) { /* If one of these matches, we trust the peer and do not perform any * other checks. */ if (!(cert_list = gnutls_certificate_get_peers( tls->session, &cert_list_size))) { *errstr = xasprintf(_("%s: no certificate was found"), error_msg); return TLS_ECERT; } if (gnutls_x509_crt_init(&cert) < 0) { *errstr = xasprintf( _("%s: cannot initialize certificate structure"), error_msg); return TLS_ECERT; } if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) { *errstr = xasprintf(_("%s: error parsing certificate %u of %u"), error_msg, 0 + 1, cert_list_size); return TLS_ECERT; } if (tls->have_sha1_fingerprint) { size = 20; if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA, fingerprint, &size) != 0) { *errstr = xasprintf(_("%s: error getting SHA1 fingerprint"), error_msg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } if (memcmp(fingerprint, tls->fingerprint, 20) != 0) { *errstr = xasprintf(_("%s: the certificate fingerprint " "does not match"), error_msg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } } else { size = 16; if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_MD5, fingerprint, &size) != 0) { *errstr = xasprintf(_("%s: error getting MD5 fingerprint"), error_msg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } if (memcmp(fingerprint, tls->fingerprint, 16) != 0) { *errstr = xasprintf(_("%s: the certificate fingerprint " "does not match"), error_msg); gnutls_x509_crt_deinit(cert); return TLS_ECERT; } } gnutls_x509_crt_deinit(cert); return TLS_EOK; } /* If 'tls->have_trust_file' is true, this function uses the trusted CAs * in the credentials structure. So you must have installed one or more CA * certificates. */ gnutls_certificate_set_verify_flags(tls->cred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); if ((error_code = gnutls_certificate_verify_peers2(tls->session, &status)) != 0) { *errstr = xasprintf("%s: %s", error_msg, gnutls_strerror(error_code)); return TLS_ECERT; } if (tls->have_trust_file) { if (status & GNUTLS_CERT_REVOKED) { *errstr = xasprintf(_("%s: the certificate has been revoked"), error_msg); return TLS_ECERT; } if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { *errstr = xasprintf( _("%s: the certificate hasn't got a known issuer"), error_msg); return TLS_ECERT; } if (status & GNUTLS_CERT_INVALID) { *errstr = xasprintf(_("%s: the certificate is not trusted"), error_msg); return TLS_ECERT; } } if (gnutls_certificate_type_get(tls->session) != GNUTLS_CRT_X509) { *errstr = xasprintf(_("%s: the certificate type is not X509"), error_msg); return TLS_ECERT; } if (!(cert_list = gnutls_certificate_get_peers( tls->session, &cert_list_size))) { *errstr = xasprintf(_("%s: no certificate was found"), error_msg); return TLS_ECERT; } /* Needed to check times: */ if ((t1 = time(NULL)) < 0) { *errstr = xasprintf("%s: cannot get system time: %s", error_msg, strerror(errno)); return TLS_ECERT; } /* Check the certificate chain. All certificates in the chain must have * valid activation/expiration times. The first certificate in the chain is * the host's certificate; it must match the hostname. */ for (i = 0; i < cert_list_size; i++) { if (gnutls_x509_crt_init(&cert) < 0) { *errstr = xasprintf( _("%s: cannot initialize certificate structure"), error_msg); return TLS_ECERT; } if (gnutls_x509_crt_import(cert, &cert_list[i], GNUTLS_X509_FMT_DER) < 0) { *errstr = xasprintf(_("%s: error parsing certificate %u of %u"), error_msg, i + 1, cert_list_size); return TLS_ECERT; } /* Check hostname */ if (i == 0) { #if GNUTLS_VERSION_NUMBER < 0x030400 && defined(HAVE_LIBIDN) idna_to_ascii_lz(hostname, &idn_hostname, 0); #endif error_code = gnutls_x509_crt_check_hostname(cert, idn_hostname ? idn_hostname : hostname); free(idn_hostname); if (error_code == 0) { *errstr = xasprintf(_("%s: the certificate owner does not " "match hostname %s"), error_msg, hostname); return TLS_ECERT; } } /* Check certificate times */ if ((t2 = gnutls_x509_crt_get_activation_time(cert)) < 0) { *errstr = xasprintf(_("%s: cannot get activation time for " "certificate %u of %u"), error_msg, i + 1, cert_list_size); return TLS_ECERT; } if (t2 > t1) { *errstr = xasprintf( _("%s: certificate %u of %u is not yet activated"), error_msg, i + 1, cert_list_size); return TLS_ECERT; } if ((t2 = gnutls_x509_crt_get_expiration_time(cert)) < 0) { *errstr = xasprintf(_("%s: cannot get expiration time for " "certificate %u of %u"), error_msg, i + 1, cert_list_size); return TLS_ECERT; } if (t2 < t1) { *errstr = xasprintf(_("%s: certificate %u of %u has expired"), error_msg, i + 1, cert_list_size); return TLS_ECERT; } gnutls_x509_crt_deinit(cert); } return TLS_EOK; #endif /* HAVE_LIBGNUTLS */ #ifdef HAVE_LIBSSL X509 *x509cert; long status; const char *error_msg; int i; /* hostname in ASCII format: */ char *idn_hostname = NULL; /* needed to get the common name: */ X509_NAME *x509_subject; char *buf; int length; /* needed to get the DNS subjectAltNames: */ void *subj_alt_names; int subj_alt_names_count; GENERAL_NAME *subj_alt_name; /* did we find a name matching hostname? */ int match_found; /* needed for fingerprint checking */ unsigned int usize; unsigned char fingerprint[20]; if (tls->have_trust_file) { error_msg = _("TLS certificate verification failed"); } else { error_msg = _("TLS certificate check failed"); } /* Get certificate */ if (!(x509cert = SSL_get_peer_certificate(tls->ssl))) { *errstr = xasprintf(_("%s: no certificate was sent"), error_msg); return TLS_ECERT; } if (tls->have_sha1_fingerprint || tls->have_md5_fingerprint) { /* If one of these matches, we trust the peer and do not perform any * other checks. */ if (tls->have_sha1_fingerprint) { usize = 20; if (!X509_digest(x509cert, EVP_sha1(), fingerprint, &usize)) { *errstr = xasprintf(_("%s: error getting SHA1 fingerprint"), error_msg); X509_free(x509cert); return TLS_ECERT; } if (memcmp(fingerprint, tls->fingerprint, 20) != 0) { *errstr = xasprintf(_("%s: the certificate fingerprint " "does not match"), error_msg); X509_free(x509cert); return TLS_ECERT; } } else { usize = 16; if (!X509_digest(x509cert, EVP_md5(), fingerprint, &usize)) { *errstr = xasprintf(_("%s: error getting MD5 fingerprint"), error_msg); X509_free(x509cert); return TLS_ECERT; } if (memcmp(fingerprint, tls->fingerprint, 16) != 0) { *errstr = xasprintf(_("%s: the certificate fingerprint " "does not match"), error_msg); X509_free(x509cert); return TLS_ECERT; } } X509_free(x509cert); return TLS_EOK; } /* Get result of OpenSSL's default verify function */ if ((status = SSL_get_verify_result(tls->ssl)) != X509_V_OK) { if (tls->have_trust_file || (status != X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY && status != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT && status != X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN)) { *errstr = xasprintf("%s: %s", error_msg, X509_verify_cert_error_string(status)); X509_free(x509cert); return TLS_ECERT; } } /* Check if 'hostname' matches the one of the subjectAltName extensions of * type DNS or the Common Name (CN). */ #ifdef HAVE_LIBIDN idna_to_ascii_lz(hostname, &idn_hostname, 0); #endif /* Try the DNS subjectAltNames. */ match_found = 0; if ((subj_alt_names = X509_get_ext_d2i(x509cert, NID_subject_alt_name, NULL, NULL))) { subj_alt_names_count = sk_GENERAL_NAME_num(subj_alt_names); for (i = 0; i < subj_alt_names_count; i++) { subj_alt_name = sk_GENERAL_NAME_value(subj_alt_names, i); if (subj_alt_name->type == GEN_DNS) { if ((size_t)(subj_alt_name->d.ia5->length) != strlen((char *)(subj_alt_name->d.ia5->data))) { *errstr = xasprintf(_("%s: certificate subject " "alternative name contains NUL"), error_msg); X509_free(x509cert); free(idn_hostname); return TLS_ECERT; } if ((match_found = hostname_match( idn_hostname ? idn_hostname : hostname, (char *)(subj_alt_name->d.ia5->data)))) { break; } } } } if (!match_found) { /* Try the common name */ if (!(x509_subject = X509_get_subject_name(x509cert))) { *errstr = xasprintf(_("%s: cannot get certificate subject"), error_msg); X509_free(x509cert); free(idn_hostname); return TLS_ECERT; } length = X509_NAME_get_text_by_NID(x509_subject, NID_commonName, NULL, 0); buf = xmalloc((size_t)length + 1); if (X509_NAME_get_text_by_NID(x509_subject, NID_commonName, buf, length + 1) == -1) { *errstr = xasprintf(_("%s: cannot get certificate common name"), error_msg); X509_free(x509cert); free(idn_hostname); free(buf); return TLS_ECERT; } if ((size_t)length != strlen(buf)) { *errstr = xasprintf(_("%s: certificate common name contains NUL"), error_msg); X509_free(x509cert); free(idn_hostname); free(buf); return TLS_ECERT; } match_found = hostname_match(idn_hostname ? idn_hostname : hostname, buf); free(buf); } X509_free(x509cert); free(idn_hostname); if (!match_found) { *errstr = xasprintf( _("%s: the certificate owner does not match hostname %s"), error_msg, hostname); return TLS_ECERT; } return TLS_EOK; #endif /* HAVE_LIBSSL */ }