Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
/* 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;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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;

}
Ejemplo n.º 5
0
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;
		}
	}
Ejemplo n.º 6
0
/* 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;
}
Ejemplo n.º 7
0
Archivo: tls.c Proyecto: yomei-o/msmtp
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 */
}