Example #1
0
/*
 * ssl_version_supported - Check that the specified `version` is supported by
 * `SSL *` instance
 *
 * @s: The SSL handle for the candidate method
 * @version: Protocol version to test against
 *
 * Returns 1 when supported, otherwise 0
 */
int ssl_version_supported(const SSL *s, int version)
{
    const version_info *vent;
    const version_info *table;

    switch (s->method->version) {
    default:
        /* Version should match method version for non-ANY method */
        return version_cmp(s, version, s->version) == 0;
    case TLS_ANY_VERSION:
        table = tls_version_table;
        break;
    case DTLS_ANY_VERSION:
        table = dtls_version_table;
        break;
    }

    for (vent = table;
         vent->version != 0 && version_cmp(s, version, vent->version) <= 0;
         ++vent) {
        if (vent->cmeth != NULL &&
            version_cmp(s, version, vent->version) == 0 &&
            ssl_method_error(s, vent->cmeth()) == 0) {
            return 1;
        }
    }
    return 0;
}
Example #2
0
/**
 * Free version string.
 */
void G_COLD
version_close(void)
{
	if (version_cmp(&our_version, &last_rel_version) < 0)
		g_warning("upgrade recommended: most recent released version seen: %s",
			version_str(&last_rel_version));
	else if (version_cmp(&our_version, &last_dev_version) < 0)
		g_warning("upgrade possible: most recent development version seen: %s",
			version_str(&last_dev_version));
}
Example #3
0
/*
 * ssl_choose_server_version - Choose server (D)TLS version.  Called when the
 * client HELLO is received to select the final server protocol version and
 * the version specific method.
 *
 * @s: server SSL handle.
 *
 * Returns 0 on success or an SSL error reason number on failure.
 */
int ssl_choose_server_version(SSL *s)
{
    /*-
     * With version-flexible methods we have an initial state with:
     *
     *   s->method->version == (D)TLS_ANY_VERSION,
     *   s->version == (D)TLS_MAX_VERSION.
     *
     * So we detect version-flexible methods via the method version, not the
     * handle version.
     */
    int server_version = s->method->version;
    int client_version = s->client_version;
    const version_info *vent;
    const version_info *table;
    int disabled = 0;

    switch (server_version) {
    default:
        if (version_cmp(s, client_version, s->version) < 0)
            return SSL_R_WRONG_SSL_VERSION;
        /*
         * If this SSL handle is not from a version flexible method we don't
         * (and never did) check min/max FIPS or Suite B constraints.  Hope
         * that's OK.  It is up to the caller to not choose fixed protocol
         * versions they don't want.  If not, then easy to fix, just return
         * ssl_method_error(s, s->method)
         */
        return 0;
    case TLS_ANY_VERSION:
        table = tls_version_table;
        break;
    case DTLS_ANY_VERSION:
        table = dtls_version_table;
        break;
    }

    for (vent = table; vent->version != 0; ++vent) {
        const SSL_METHOD *method;

        if (vent->smeth == NULL ||
            version_cmp(s, client_version, vent->version) < 0)
            continue;
        method = vent->smeth();
        if (ssl_method_error(s, method) == 0) {
            s->version = vent->version;
            s->method = method;
            return 0;
        }
        disabled = 1;
    }
    return disabled ? SSL_R_UNSUPPORTED_PROTOCOL : SSL_R_VERSION_TOO_LOW;
}
Example #4
0
/**
 * Based on the timestamp and their advertised version, find out the
 * token key they used.
 *
 * @return NULL if we cannot locate any suitable keys.
 */
static const struct tokkey *
find_tokkey_version(const version_t *ver, time_t now)
{
	uint i;

	/*
	 * All versions before r16370 used the first key set when they expired.
	 * If we're more recent, we probably have a stripped list of past key
	 * sets, and therefore cannot validate their token.
	 *
	 * All versions after we switched to git can be checked provided we still
	 * have a copy of the keys that they had at the time they were released.
	 */

	if (
		ver->timestamp < GIT_SWITCH &&			/* Before we switched to git */
		ver->build != 0 && ver->build < 16370
	)
		return find_tokkey(now);

	if (GNET_PROPERTY(version_debug) > 4) {
		g_debug("%s: looking for proper keyset (theirs is %u.%u.%u)",
			G_STRFUNC, ver->major, ver->minor, ver->patchlevel);
	}

	/*
	 * Expired servents will always use their last key set.  Even if we're
	 * more recent, we can try to validate by mimicing the behaviour of
	 * these servents.
	 *
	 * We determine the index of the last key set that they must know about
	 * and we look for the token up to that index only.
	 */

	for (i = 0; i < G_N_ELEMENTS(token_keys); i++) {
		const struct tokkey *tk = &token_keys[i];
		if (version_cmp(ver, &tk->ver) <= 0) {
			if (GNET_PROPERTY(version_debug) > 4) {
				g_debug("%s: matched at %u.%u.%u, index=%u", G_STRFUNC,
					tk->ver.major, tk->ver.minor, tk->ver.patchlevel, i);
			}
			break;
		}
	}

	if (GNET_PROPERTY(version_debug) > 4) {
		g_debug("%s: fallback max=%u (/%zu)",
			G_STRFUNC, i, G_N_ELEMENTS(token_keys));
	}

	i++;									/* We need a count, not an index */
	i = MIN(i, G_N_ELEMENTS(token_keys));	/* In case loop did not match */

	return find_tokkey_upto_fallback(now, i);
}
Example #5
0
int
main()
{
  version v1, v2, v3;
  char c[64];

  version_init(&v1, 1, 2, 6);
  version_parse(&v2, "2.1.6");
  version_init(&v3, 1, 2, 5);

  int count = version_to_string(&c[0], &v1);
  printf("version: %s\n", c);
  printf("count: %i\n", count);
  int b;
  b = version_cmp(&v1, &v2);
  printf("b1: %i\n", b);
  b = version_cmp(&v1, &v3);
  printf("b2: %i\n", b);
  b = version_cmp(&v2, &v3);
  printf("b3: %i\n", b);
}
Example #6
0
/*
 * ssl_method_error - Check whether an SSL_METHOD is enabled.
 *
 * @s: The SSL handle for the candidate method
 * @method: the intended method.
 *
 * Returns 0 on success, or an SSL error reason on failure.
 */
static int ssl_method_error(const SSL *s, const SSL_METHOD *method)
{
    int version = method->version;

    if ((s->min_proto_version != 0 &&
         version_cmp(s, version, s->min_proto_version) < 0) ||
        ssl_security(s, SSL_SECOP_VERSION, 0, version, NULL) == 0)
        return SSL_R_VERSION_TOO_LOW;

    if (s->max_proto_version != 0 &&
        version_cmp(s, version, s->max_proto_version) > 0)
        return SSL_R_VERSION_TOO_HIGH;

    if ((s->options & method->mask) != 0)
        return SSL_R_UNSUPPORTED_PROTOCOL;
    if ((method->flags & SSL_METHOD_NO_SUITEB) != 0 && tls1_suiteb(s))
        return SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE;
    else if ((method->flags & SSL_METHOD_NO_FIPS) != 0 && FIPS_mode())
        return SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE;

    return 0;
}
Example #7
0
void
version_require(const char* package,
                const version* package_version,
                const char* dependency,
                const version* dependency_version,
                const version* required_version)
{
  int c = version_cmp(dependency_version, required_version);
  if (c < 0)
  {
    char pvs[64];
    char rvs[64];
    char dvs[64];
    version_to_string(pvs, package_version);
    version_to_string(rvs, required_version);
    version_to_string(dvs, dependency_version);
    printf("package %s %s requires %s %s but found version: %s\n",
           package, pvs, dependency, rvs, dvs);
    exit(1);
  }
}
Example #8
0
void http_request_h(struct http_conn *conn, const struct http_msg *msg, void *arg)
{
    int err;
    enum app_cmd cmd;
    const struct http_hdr * expect_hdr;
    struct mbuf *mb = msg->mb;
    uint8_t *ret_buf;
    size_t ret_len;

    if(pl_strcmp(&msg->met, "POST")) {
        http_creply(conn, 405, "Method not allowed", "text/plain", "EMET");
        return;
    }

    expect_hdr = http_msg_hdr(msg, HTTP_HDR_EXPECT);
    if(expect_hdr != NULL && version_cmp(version, &expect_hdr->val) < 0) {
        http_creply(conn, 417, "Expectation Failed", "text/plain", "%s", version);
        return;
    }

    cmd = (enum app_cmd)(hash_joaat_ci(msg->path.p, msg->path.l) & 0xfff);
    err = app_handle(cmd, mbuf_buf(mb), mbuf_get_left(mb), &ret_buf, &ret_len);
    if(err < 0) {
        http_creply(conn, 500, "Internal Server Error", "text/plain", "EINT");
        return;
    }

    if(err > 200) {
        http_creply(conn, err, "Error", "text/plain", "NO", 2);
        return;
    }

    if(err == 0) {
        http_creply(conn, 200, "OK", "text/plain; charset=utf-8", "%b", ret_buf, ret_len);
    } else {
        http_creply(conn, 403, "Forbidden", "text/plain", "%b", ret_buf, ret_len);
    }

    free(ret_buf);
}
Example #9
0
static int compare_ref_name(const void *a_, const void *b_)
{
	const char * const*a = a_, * const*b = b_;
	return version_cmp(*a, *b);
}
Example #10
0
int
main(int argc, char **argv)
{
    int ch, cmp = 0;

    if (argc == 4 && !strcmp(argv[1], "-t")) {
	cmp = version_cmp(argv[2], argv[3]);
	printf(cmp > 0 ? ">\n" : (cmp < 0 ? "<\n" : "=\n"));
	exit(0);
    }
    else if (argc == 4 && !strcmp(argv[1], "-T")) {
	cmp = version_match(argv[3], argv[2]);
	exit(cmp == 1 ? 0 : 1);
    }
    else while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1) {
	switch(ch) {
	case 'v':
	    Verbose++;
	    break;

	case 'I':
	    UseINDEXOnly = TRUE;
	    break;

	case 'l':
	    LimitChars = optarg;
	    break;

	case 'L':
	    PreventChars = optarg;
	    break;

	case 'q':
	    Quiet = TRUE;
	    break;

	case 's':
	    MatchName = optarg;
	    break;

	case 'O':
	    LookUpOrigin = optarg;
	    break;

	case 'o':
	    ShowOrigin = TRUE;
	    break;

	case 't':
	    errx(2, "Invalid -t usage.");
	    break;

	case 'T':
	    errx(2, "Invalid -T usage.");
	    break;

	case 'X':
	    RegexExtended = TRUE;
	    break;

	case 'h':
	default:
	    usage();
	    break;
	}
    }

    argc -= optind;
    argv += optind;

    return pkg_perform(argv);
}
Example #11
0
/*
 * ssl_choose_server_version - Choose server (D)TLS version.  Called when the
 * client HELLO is received to select the final server protocol version and
 * the version specific method.
 *
 * @s: server SSL handle.
 *
 * Returns 0 on success or an SSL error reason number on failure.
 */
int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello)
{
    /*-
     * With version-flexible methods we have an initial state with:
     *
     *   s->method->version == (D)TLS_ANY_VERSION,
     *   s->version == (D)TLS_MAX_VERSION.
     *
     * So we detect version-flexible methods via the method version, not the
     * handle version.
     */
    int server_version = s->method->version;
    int client_version = hello->legacy_version;
    const version_info *vent;
    const version_info *table;
    int disabled = 0;
    RAW_EXTENSION *suppversions;

    s->client_version = client_version;

    switch (server_version) {
    default:
        /*
         * TODO(TLS1.3): This check will fail if someone attempts to do
         * renegotiation in TLS1.3 at the moment. We need to ensure we disable
         * renegotiation for TLS1.3
         */
        if (version_cmp(s, client_version, s->version) < 0)
            return SSL_R_WRONG_SSL_VERSION;
        /*
         * If this SSL handle is not from a version flexible method we don't
         * (and never did) check min/max FIPS or Suite B constraints.  Hope
         * that's OK.  It is up to the caller to not choose fixed protocol
         * versions they don't want.  If not, then easy to fix, just return
         * ssl_method_error(s, s->method)
         */
        return 0;
    case TLS_ANY_VERSION:
        table = tls_version_table;
        break;
    case DTLS_ANY_VERSION:
        table = dtls_version_table;
        break;
    }

    suppversions = tls_get_extension_by_type(hello->pre_proc_exts,
                                             hello->num_extensions,
                                             TLSEXT_TYPE_supported_versions);

    if (suppversions != NULL && !SSL_IS_DTLS(s)) {
        unsigned int candidate_vers = 0;
        unsigned int best_vers = 0;
        const SSL_METHOD *best_method = NULL;
        PACKET versionslist;

        if (!PACKET_as_length_prefixed_1(&suppversions->data, &versionslist)) {
            /* Trailing or invalid data? */
            return SSL_R_LENGTH_MISMATCH;
        }

        while (PACKET_get_net_2(&versionslist, &candidate_vers)) {
            /* TODO(TLS1.3): Remove this before release */
            if (candidate_vers == TLS1_3_VERSION_DRAFT)
                candidate_vers = TLS1_3_VERSION;
            /*
             * TODO(TLS1.3): There is some discussion on the TLS list about
             * wheter to ignore versions <TLS1.2 in supported_versions. At the
             * moment we honour them if present. To be reviewed later
             */
            if (version_cmp(s, candidate_vers, best_vers) <= 0)
                continue;
            for (vent = table;
                 vent->version != 0 && vent->version != (int)candidate_vers;
                 ++vent)
                continue;
            if (vent->version != 0 && vent->smeth != NULL) {
                const SSL_METHOD *method;

                method = vent->smeth();
                if (ssl_method_error(s, method) == 0) {
                    best_vers = candidate_vers;
                    best_method = method;
                }
            }
        }
        if (PACKET_remaining(&versionslist) != 0) {
            /* Trailing data? */
            return SSL_R_LENGTH_MISMATCH;
        }

        if (best_vers > 0) {
            s->version = best_vers;
            s->method = best_method;
            return 0;
        }
        return SSL_R_UNSUPPORTED_PROTOCOL;
    }

    /*
     * If the supported versions extension isn't present, then the highest
     * version we can negotiate is TLSv1.2
     */
    if (version_cmp(s, client_version, TLS1_3_VERSION) >= 0)
        client_version = TLS1_2_VERSION;

    /*
     * No supported versions extension, so we just use the version supplied in
     * the ClientHello.
     */
    for (vent = table; vent->version != 0; ++vent) {
        const SSL_METHOD *method;

        if (vent->smeth == NULL ||
            version_cmp(s, client_version, vent->version) < 0)
            continue;
        method = vent->smeth();
        if (ssl_method_error(s, method) == 0) {
            s->version = vent->version;
            s->method = method;
            return 0;
        }
        disabled = 1;
    }
    return disabled ? SSL_R_UNSUPPORTED_PROTOCOL : SSL_R_VERSION_TOO_LOW;
}
Example #12
0
/**
 * Check version of servent, and if it's a gtk-gnutella more recent than we
 * are, record that fact and change the status bar.
 *
 * The `addr' is being passed solely for the tok_version_valid() call.
 *
 * @returns TRUE if we properly checked the version, FALSE if we got something
 * looking as gtk-gnutella but which failed the token-based sanity checks.
 */
bool
version_check(const char *str, const char *token, const host_addr_t addr)
{
	version_t their_version;
	version_ext_t their_version_ext;
	version_t *target_version;
	int cmp;
	const char *version;
	const char *end;
	bool extended;

	if (!version_parse(str, &their_version, &end))
		return TRUE;			/* Not gtk-gnutella, or unparseable */

	/*
	 * Check for extended version information (git commit ID, dirty status).
	 */

	ZERO(&their_version_ext);
	extended = version_ext_parse(end, &their_version_ext);
	if (!extended) {
		/* Structure could have been partially filled */
		ZERO(&their_version_ext);
	}

	/*
	 * Is their version a development one, or a release?
	 */

	if (their_version.tag == 'u')
		target_version = &last_dev_version;
	else
		target_version = &last_rel_version;

	cmp = version_cmp(target_version, &their_version);

	if (GNET_PROPERTY(version_debug) > 1)
		version_dump(str, &their_version,
			cmp == 0 ? "=" :
			cmp > 0 ? "-" : "+");

	/*
	 * Check timestamp.
	 */

	version_stamp(str, &their_version);
	their_version_ext.version = their_version;		/* Struct copy */

	if (GNET_PROPERTY(version_debug) > 3)
		g_debug("VERSION time=%d", (int) their_version.timestamp);

	/*
	 * If version claims something older than TOKEN_START_DATE, then
	 * there must be a token present.
	 */

	if (delta_time(their_version.timestamp, 0) >= TOKEN_START_DATE) {
		tok_error_t error;

		if (token == NULL) {
            if (GNET_PROPERTY(version_debug)) {
                g_debug("got GTKG vendor string \"%s\" without token!", str);
            }
			return FALSE;	/* Can't be correct */
		}

		error = tok_version_valid(str, token, strlen(token), addr);

		/*
		 * Unfortunately, if our token has expired, we can no longer
		 * validate the tokens of the remote peers, since they are using
		 * a different set of keys.
		 *
		 * This means an expired GTKG will blindly trust well-formed remote
		 * tokens at face value.  But it's their fault, they should not run
		 * an expired version!
		 *		--RAM, 2005-12-21
		 */

		if (error == TOK_BAD_KEYS && tok_is_ancient(tm_time()))
			error = TOK_OK;		/* Our keys have expired, cannot validate */

		if (error != TOK_OK) {
            if (GNET_PROPERTY(version_debug)) {
                g_debug("vendor string \"%s\" [%s] has wrong token "
                    "\"%s\": %s ", str, host_addr_to_string(addr), token,
                    tok_strerror(error));
            }
			return FALSE;
		}

		/*
		 * OK, so now we know we can "trust" this version string as being
		 * probably genuine.  It makes sense to extract version information
		 * out of it.
		 */
	}

	if (cmp > 0)			/* We're more recent */
		return TRUE;

	/*
	 * If timestamp is greater and we were comparing against a stable
	 * release, and cmp == 0, then this means an update in SVN about
	 * a "released" version, probably alpha/beta.
	 */

	if (
		cmp == 0 &&
		(delta_time(their_version.timestamp, target_version->timestamp) > 0
			|| their_version.build > target_version->build) &&
		target_version == &last_rel_version
	) {
		if (GNET_PROPERTY(version_debug) > 3)
			g_debug("VERSION is a SVN update of a release");

		if (version_build_cmp(&last_dev_version, &their_version) > 0) {
			if (GNET_PROPERTY(version_debug) > 3)
				g_debug("VERSION is less recent than latest dev we know");
			return TRUE;
		}
		target_version = &last_dev_version;
	}

	/*
	 * Their version is more recent, but is unstable -- only continue if
	 * our version is also unstable.
	 */

	if (cmp < 0 && their_version.tag == 'u' && our_version.tag != 'u')
		return TRUE;

	if (
		delta_time(their_version.timestamp, target_version->timestamp) < 0 ||
		their_version.build <= target_version->build
	)
		return TRUE;

	if (
		delta_time(their_version.timestamp, our_version.timestamp) == 0 &&
		their_version.build <= our_version.build
	)
		return TRUE;

	/*
	 * We found a more recent version than the last version seen.
	 */

	if (GNET_PROPERTY(version_debug) > 1)
		g_debug("more recent %s VERSION \"%s\"",
			target_version == &last_dev_version ? "dev" : "rel", str);

	*target_version = their_version;		/* struct copy */

	/*
	 * Signal new version to user.
	 *
	 * Unless they run a development version, don't signal development
	 * updates to them: they're probably not interested.
	 */

	version =  version_ext_str(&their_version_ext, FALSE);	/* No OS name */

	g_message("more recent %s version of gtk-gnutella: %s",
		target_version == &last_dev_version ? "development" : "released",
		version);

	if (target_version == &last_rel_version)
		version_new_found(version, TRUE);
	else if (our_version.tag == 'u')
		version_new_found(version, FALSE);

	return TRUE;
}
Example #13
0
/**
 * Compare two gtk-gnutella versions, including build number (but not
 * the version timestamps).  In theory, we could simply compare build numbers
 * but we can't ensure they won't ever be reset one day.
 *
 * @returns -1, 0 or +1 depending on the sign of "a - b".
 */
int
version_build_cmp(const version_t *a, const version_t *b)
{
	int cmp = version_cmp(a, b);
	return 0 == cmp ? CMP(a->build, b->build) : cmp;
}