resetting manifest requested domain to floor
[platform/upstream/openconnect.git] / xml.c
1 /*
2  * OpenConnect (SSL + DTLS) VPN client
3  *
4  * Copyright © 2008-2011 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         unsigned char sha1[SHA1_SIZE];
45         xmlDocPtr xml_doc;
46         xmlNode *xml_node, *xml_node2;
47
48         if (!vpninfo->xmlconfig)
49                 return 0;
50
51         fd = open(vpninfo->xmlconfig, O_RDONLY);
52         if (fd < 0) {
53                 perror(_("Open XML config file"));
54                 fprintf(stderr, _("Treating host \"%s\" as a raw hostname\n"),
55                         host);
56                 return 0;
57         }
58
59         if (fstat(fd, &st)) {
60                 perror(_("fstat XML config file"));
61                 close(fd);
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         if (openconnect_sha1(sha1, xmlfile, st.st_size)) {
73                 fprintf(stderr, _("Failed to SHA1 existing file\n"));
74                 close(fd);
75                 return -1;
76         }
77
78         for (i = 0; i < SHA1_SIZE; i++)
79                 sprintf(&vpninfo->xmlsha1[i*2], "%02x", sha1[i]);
80
81         vpn_progress(vpninfo, PRG_TRACE, _("XML config file SHA1: %s\n"),
82                      vpninfo->xmlsha1);
83
84         xml_doc = xmlReadMemory(xmlfile, st.st_size, "noname.xml", NULL, 0);
85         munmap(xmlfile, st.st_size);
86         close(fd);
87         if (!xml_doc) {
88                 fprintf(stderr, _("Failed to parse XML config file %s\n"),
89                         vpninfo->xmlconfig);
90                 fprintf(stderr, _("Treating host \"%s\" as a raw hostname\n"),
91                         host);
92                 return 0;
93         }
94         xml_node = xmlDocGetRootElement(xml_doc);
95
96         for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) {
97                 if (xml_node->type == XML_ELEMENT_NODE &&
98                     !strcmp((char *)xml_node->name, "ServerList")) {
99
100                         for (xml_node = xml_node->children; xml_node && !vpninfo->hostname;
101                              xml_node = xml_node->next) {
102
103                                 if (xml_node->type == XML_ELEMENT_NODE &&
104                                     !strcmp((char *)xml_node->name, "HostEntry")) {
105                                         int match = 0;
106
107                                         for (xml_node2 = xml_node->children;
108                                              match >= 0 && xml_node2; xml_node2 = xml_node2->next) {
109
110                                                 if (xml_node2->type != XML_ELEMENT_NODE)
111                                                         continue;
112
113                                                 if (!match && !strcmp((char *)xml_node2->name, "HostName")) {
114                                                         char *content = (char *)xmlNodeGetContent(xml_node2);
115                                                         if (content && !strcmp(content, host))
116                                                                 match = 1;
117                                                         else
118                                                                 match = -1;
119                                                         free(content);
120                                                 } else if (match &&
121                                                            !strcmp((char *)xml_node2->name, "HostAddress")) {
122                                                         char *content = (char *)xmlNodeGetContent(xml_node2);
123                                                         if (content) {
124                                                                 vpninfo->hostname = content;
125                                                                 printf(_("Host \"%s\" has address \"%s\"\n"),
126                                                                        host, content);
127                                                         }
128                                                 } else if (match &&
129                                                            !strcmp((char *)xml_node2->name, "UserGroup")) {
130                                                         char *content = (char *)xmlNodeGetContent(xml_node2);
131                                                         if (content) {
132                                                                 free(vpninfo->urlpath);
133                                                                 vpninfo->urlpath = content;
134                                                                 printf(_("Host \"%s\" has UserGroup \"%s\"\n"),
135                                                                        host, content);
136                                                         }
137                                                 }
138                                         }
139                                 }
140
141                         }
142                         break;
143                 }
144         }
145         xmlFreeDoc(xml_doc);
146
147         if (!vpninfo->hostname) {
148                 fprintf(stderr, _("Host \"%s\" not listed in config; treating as raw hostname\n"),
149                         host);
150         }
151
152         return 0;
153 }