Add cancellation handling to proxy I/O functions
[platform/upstream/openconnect.git] / xml.c
1 /*
2  * OpenConnect (SSL + DTLS) VPN client
3  *
4  * Copyright © 2008-2010 Intel Corporation.
5  * Copyright © 2008 Nick Andrew <nick@nick-andrew.net>
6  *
7  * Author: David Woodhouse <dwmw2@infradead.org>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * version 2.1, as published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to:
20  *
21  *   Free Software Foundation, Inc.
22  *   51 Franklin Street, Fifth Floor,
23  *   Boston, MA 02110-1301 USA
24  */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <sys/mman.h>
33 #include <libxml/parser.h>
34 #include <libxml/tree.h>
35 #include <string.h>
36
37 #include "openconnect-internal.h"
38
39 int config_lookup_host(struct openconnect_info *vpninfo, const char *host)
40 {
41         int fd, i;
42         struct stat st;
43         char *xmlfile;
44         EVP_MD_CTX c;
45         unsigned char sha1[SHA_DIGEST_LENGTH];
46         xmlDocPtr xml_doc;
47         xmlNode *xml_node, *xml_node2;
48
49         if (!vpninfo->xmlconfig)
50                 return 0;
51
52         fd = open(vpninfo->xmlconfig, O_RDONLY);
53         if (fd < 0) {
54                 perror(_("Open XML config file"));
55                 fprintf(stderr, _("Treating host \"%s\" as a raw hostname\n"),
56                         host);
57                 return 0;
58         }
59
60         if (fstat(fd, &st)) {
61                 perror(_("fstat XML config file"));
62                 return -1;
63         }
64
65         xmlfile = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
66         if (xmlfile == MAP_FAILED) {
67                 perror(_("mmap XML config file"));
68                 close(fd);
69                 return -1;
70         }
71
72         EVP_MD_CTX_init(&c);
73         EVP_Digest(xmlfile, st.st_size, sha1, NULL, EVP_sha1(), NULL);
74         EVP_MD_CTX_cleanup(&c);
75
76         for (i = 0; i < SHA_DIGEST_LENGTH; i++)
77                 sprintf(&vpninfo->xmlsha1[i*2], "%02x", sha1[i]);
78
79         vpn_progress(vpninfo, PRG_TRACE, _("XML config file SHA1: %s\n"),
80                      vpninfo->xmlsha1);
81
82         xml_doc = xmlReadMemory(xmlfile, st.st_size, "noname.xml", NULL, 0);
83         munmap(xmlfile, st.st_size);
84         close(fd);
85         if (!xml_doc) {
86                 fprintf(stderr, _("Failed to parse XML config file %s\n"),
87                         vpninfo->xmlconfig);
88                 fprintf(stderr, _("Treating host \"%s\" as a raw hostname\n"),
89                         host);
90                 return 0;
91         }
92         xml_node = xmlDocGetRootElement(xml_doc);
93
94         for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) {
95                 if (xml_node->type == XML_ELEMENT_NODE &&
96                     !strcmp((char *)xml_node->name, "ServerList")) {
97
98                         for (xml_node = xml_node->children; xml_node && !vpninfo->hostname;
99                              xml_node = xml_node->next) {
100
101                                 if (xml_node->type == XML_ELEMENT_NODE &&
102                                     !strcmp((char *)xml_node->name, "HostEntry")) {
103                                         int match = 0;
104
105                                         for (xml_node2 = xml_node->children;
106                                              match >= 0 && xml_node2; xml_node2 = xml_node2->next) {
107
108                                                 if (xml_node2->type != XML_ELEMENT_NODE)
109                                                         continue;
110
111                                                 if (!match && !strcmp((char *)xml_node2->name, "HostName")) {
112                                                         char *content = (char *)xmlNodeGetContent(xml_node2);
113                                                         if (content && !strcmp(content, host))
114                                                                 match = 1;
115                                                         else
116                                                                 match = -1;
117                                                         free(content);
118                                                 } else if (match &&
119                                                            !strcmp((char *)xml_node2->name, "HostAddress")) {
120                                                         char *content = (char *)xmlNodeGetContent(xml_node2);
121                                                         if (content) {
122                                                                 vpninfo->hostname = content;
123                                                                 printf(_("Host \"%s\" has address \"%s\"\n"),
124                                                                        host, content);
125                                                         }
126                                                 } else if (match &&
127                                                            !strcmp((char *)xml_node2->name, "UserGroup")) {
128                                                         char *content = (char *)xmlNodeGetContent(xml_node2);
129                                                         if (content) {
130                                                                 free(vpninfo->urlpath);
131                                                                 vpninfo->urlpath = content;
132                                                                 printf(_("Host \"%s\" has UserGroup \"%s\"\n"),
133                                                                        host, content);
134                                                         }
135                                                 }
136                                         }
137                                 }
138
139                         }
140                         break;
141                 }
142         }
143         xmlFreeDoc(xml_doc);
144
145         if (!vpninfo->hostname) {
146                 fprintf(stderr, _("Host \"%s\" not listed in config; treating as raw hostname\n"),
147                         host);
148         }
149
150         return 0;
151 }