示例#1
0
int openconnect_check_peer_cert_hash(struct openconnect_info *vpninfo,
				     const char *old_hash)
{
	char sha1_text[41];
	const char *fingerprint;

	if (strchr(old_hash, ':')) {
		fingerprint = openconnect_get_peer_cert_hash(vpninfo);
		if (!fingerprint)
			return -EIO;
	} else {
		unsigned char *cert;
		int len, i;
		unsigned char sha1_bin[SHA1_SIZE];

		len = openconnect_get_peer_cert_DER(vpninfo, &cert);
		if (len < 0)
			return len;

		if (openconnect_sha1(sha1_bin, cert, len))
			return -EIO;

		for (i = 0; i < sizeof(sha1_bin); i++)
			sprintf(&sha1_text[i*2], "%02x", sha1_bin[i]);

		fingerprint = sha1_text;
	}

	if (strcasecmp(old_hash, fingerprint))
		return 1;

	return 0;
}
示例#2
0
int openconnect_check_peer_cert_hash(struct openconnect_info *vpninfo,
				     const char *old_hash)
{
	char sha1_text[41];
	const char *fingerprint;
	unsigned min_match_len;
	unsigned real_min_match_len = 4;
	unsigned old_len, fingerprint_len;

	if (strchr(old_hash, ':')) {
		if (strncmp(old_hash, "sha1:", 5) == 0) {
			fingerprint = vpninfo->peer_cert_sha1;
			min_match_len = real_min_match_len + sizeof("sha1:")-1;
		} else if (strncmp(old_hash, "sha256:", 7) == 0) {
			fingerprint = vpninfo->peer_cert_sha256;
			min_match_len = real_min_match_len + sizeof("sha256:")-1;
		} else {
			vpn_progress(vpninfo, PRG_ERR, _("Unknown certificate hash: %s.\n"), old_hash);
			return -EIO;
		}

		if (!fingerprint)
			return -EIO;
	} else {
		unsigned char *cert;
		int len, i;
		unsigned char sha1_bin[SHA1_SIZE];

		len = openconnect_get_peer_cert_DER(vpninfo, &cert);
		if (len < 0)
			return len;

		if (openconnect_sha1(sha1_bin, cert, len))
			return -EIO;

		for (i = 0; i < sizeof(sha1_bin); i++)
			sprintf(&sha1_text[i*2], "%02x", sha1_bin[i]);

		fingerprint = sha1_text;
		min_match_len = real_min_match_len;
	}

	old_len = strlen(old_hash);
	fingerprint_len = strlen(fingerprint);

	/* allow partial matches */
	if (old_len < fingerprint_len) {
		if (strncasecmp(old_hash, fingerprint, MAX(min_match_len, old_len))) {
			if (old_len < min_match_len) {
				vpn_progress(vpninfo, PRG_ERR, _("The size of the provided fingerprint is less than the minimum required (%u).\n"), real_min_match_len);
			}
			return 1;
		}
	} else {
		if (strcasecmp(old_hash, fingerprint))
			return 1;
	}

	return 0;
}
示例#3
0
文件: xml.c 项目: KidFeng/openconnect
int config_lookup_host(struct openconnect_info *vpninfo, const char *host)
{
	int i;
	ssize_t size;
	char *xmlfile;
	unsigned char sha1[SHA1_SIZE];
	xmlDocPtr xml_doc;
	xmlNode *xml_node, *xml_node2;

	if (!vpninfo->xmlconfig)
		return 0;

	size = read_file_into_string(vpninfo, vpninfo->xmlconfig, &xmlfile);
	if (size == -ENOENT) {
		fprintf(stderr, _("Treating host \"%s\" as a raw hostname\n"), host);
		return 0;
	} else if (size <= 0) {
		return size;
	}

	if (openconnect_sha1(sha1, xmlfile, size)) {
		fprintf(stderr, _("Failed to SHA1 existing file\n"));
		return -1;
	}

	for (i = 0; i < SHA1_SIZE; i++)
		snprintf(&vpninfo->xmlsha1[i*2], 3, "%02x", sha1[i]);

	vpn_progress(vpninfo, PRG_DEBUG, _("XML config file SHA1: %s\n"),
		     vpninfo->xmlsha1);

	xml_doc = xmlReadMemory(xmlfile, size, "noname.xml", NULL, 0);

	free(xmlfile);

	if (!xml_doc) {
		fprintf(stderr, _("Failed to parse XML config file %s\n"),
			vpninfo->xmlconfig);
		fprintf(stderr, _("Treating host \"%s\" as a raw hostname\n"),
			host);
		return 0;
	}
	xml_node = xmlDocGetRootElement(xml_doc);

	for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) {
		if (xml_node->type == XML_ELEMENT_NODE &&
		    !strcmp((char *)xml_node->name, "ServerList")) {

			for (xml_node = xml_node->children; xml_node && !vpninfo->hostname;
			     xml_node = xml_node->next) {

				if (xml_node->type == XML_ELEMENT_NODE &&
				    !strcmp((char *)xml_node->name, "HostEntry")) {
					int match = 0;

					for (xml_node2 = xml_node->children;
					     match >= 0 && xml_node2; xml_node2 = xml_node2->next) {

						if (xml_node2->type != XML_ELEMENT_NODE)
							continue;

						if (!match && !strcmp((char *)xml_node2->name, "HostName")) {
							char *content = fetch_and_trim(xml_node2);
							if (content && !strcmp(content, host))
								match = 1;
							else
								match = -1;
							free(content);
						} else if (match &&
							   !strcmp((char *)xml_node2->name, "HostAddress")) {
							char *content = fetch_and_trim(xml_node2);
							if (content &&
							    !openconnect_parse_url(vpninfo, content)) {
								printf(_("Host \"%s\" has address \"%s\"\n"),
								       host, content);
							}
							free(content);
						} else if (match &&
							   !strcmp((char *)xml_node2->name, "UserGroup")) {
							char *content = fetch_and_trim(xml_node2);
							if (content) {
								free(vpninfo->urlpath);
								vpninfo->urlpath = content;
								printf(_("Host \"%s\" has UserGroup \"%s\"\n"),
								       host, content);
							}
						}
					}
				}

			}
			break;
		}
	}
	xmlFreeDoc(xml_doc);

	if (!vpninfo->hostname) {
		fprintf(stderr, _("Host \"%s\" not listed in config; treating as raw hostname\n"),
			host);
	}

	return 0;
}
示例#4
0
int config_lookup_host(struct openconnect_info *vpninfo, const char *host)
{
	int fd, i;
	struct stat st;
	char *xmlfile;
	unsigned char sha1[SHA1_SIZE];
	xmlDocPtr xml_doc;
	xmlNode *xml_node, *xml_node2;

	if (!vpninfo->xmlconfig)
		return 0;

	fd = open(vpninfo->xmlconfig, O_RDONLY);
	if (fd < 0) {
		perror(_("Open XML config file"));
		fprintf(stderr, _("Treating host \"%s\" as a raw hostname\n"),
			host);
		return 0;
	}

	if (fstat(fd, &st)) {
		perror(_("fstat XML config file"));
		close(fd);
		return -1;
	}

	xmlfile = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
	if (xmlfile == MAP_FAILED) {
		perror(_("mmap XML config file"));
		close(fd);
		return -1;
	}

	if (openconnect_sha1(sha1, xmlfile, st.st_size)) {
		fprintf(stderr, _("Failed to SHA1 existing file\n"));
		close(fd);
		return -1;
	}

	for (i = 0; i < SHA1_SIZE; i++)
		sprintf(&vpninfo->xmlsha1[i*2], "%02x", sha1[i]);

	vpn_progress(vpninfo, PRG_TRACE, _("XML config file SHA1: %s\n"),
		     vpninfo->xmlsha1);

	xml_doc = xmlReadMemory(xmlfile, st.st_size, "noname.xml", NULL, 0);
	munmap(xmlfile, st.st_size);
	close(fd);
	if (!xml_doc) {
		fprintf(stderr, _("Failed to parse XML config file %s\n"),
			vpninfo->xmlconfig);
		fprintf(stderr, _("Treating host \"%s\" as a raw hostname\n"),
			host);
		return 0;
	}
	xml_node = xmlDocGetRootElement(xml_doc);

	for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) {
		if (xml_node->type == XML_ELEMENT_NODE &&
		    !strcmp((char *)xml_node->name, "ServerList")) {

			for (xml_node = xml_node->children; xml_node && !vpninfo->hostname;
			     xml_node = xml_node->next) {

				if (xml_node->type == XML_ELEMENT_NODE &&
				    !strcmp((char *)xml_node->name, "HostEntry")) {
					int match = 0;

					for (xml_node2 = xml_node->children;
					     match >= 0 && xml_node2; xml_node2 = xml_node2->next) {

						if (xml_node2->type != XML_ELEMENT_NODE)
							continue;

						if (!match && !strcmp((char *)xml_node2->name, "HostName")) {
							char *content = (char *)xmlNodeGetContent(xml_node2);
							if (content && !strcmp(content, host))
								match = 1;
							else
								match = -1;
							free(content);
						} else if (match &&
							   !strcmp((char *)xml_node2->name, "HostAddress")) {
							char *content = (char *)xmlNodeGetContent(xml_node2);
							if (content) {
								vpninfo->hostname = content;
								printf(_("Host \"%s\" has address \"%s\"\n"),
								       host, content);
							}
						} else if (match &&
							   !strcmp((char *)xml_node2->name, "UserGroup")) {
							char *content = (char *)xmlNodeGetContent(xml_node2);
							if (content) {
								free(vpninfo->urlpath);
								vpninfo->urlpath = content;
								printf(_("Host \"%s\" has UserGroup \"%s\"\n"),
								       host, content);
							}
						}
					}
				}

			}
			break;
		}
	}
	xmlFreeDoc(xml_doc);

	if (!vpninfo->hostname) {
		fprintf(stderr, _("Host \"%s\" not listed in config; treating as raw hostname\n"),
			host);
	}

	return 0;
}