/* * OpenConnect (SSL + DTLS) VPN client * * Copyright © 2008-2011 Intel Corporation. * Copyright © 2008 Nick Andrew * * Author: David Woodhouse * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to: * * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include #include "openconnect-internal.h" 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; }