Tag version 4.00
[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                 return -1;
62         }
63
64         xmlfile = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
65         if (xmlfile == MAP_FAILED) {
66                 perror(_("mmap XML config file"));
67                 close(fd);
68                 return -1;
69         }
70
71         if (openconnect_sha1(sha1, xmlfile, st.st_size)) {
72                 fprintf(stderr, _("Failed to SHA1 existing file\n"));
73                 close(fd);
74                 return -1;
75         }
76
77         for (i = 0; i < SHA1_SIZE; i++)
78                 sprintf(&vpninfo->xmlsha1[i*2], "%02x", sha1[i]);
79
80         vpn_progress(vpninfo, PRG_TRACE, _("XML config file SHA1: %s\n"),
81                      vpninfo->xmlsha1);
82
83         xml_doc = xmlReadMemory(xmlfile, st.st_size, "noname.xml", NULL, 0);
84         munmap(xmlfile, st.st_size);
85         close(fd);
86         if (!xml_doc) {
87                 fprintf(stderr, _("Failed to parse XML config file %s\n"),
88                         vpninfo->xmlconfig);
89                 fprintf(stderr, _("Treating host \"%s\" as a raw hostname\n"),
90                         host);
91                 return 0;
92         }
93         xml_node = xmlDocGetRootElement(xml_doc);
94
95         for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) {
96                 if (xml_node->type == XML_ELEMENT_NODE &&
97                     !strcmp((char *)xml_node->name, "ServerList")) {
98
99                         for (xml_node = xml_node->children; xml_node && !vpninfo->hostname;
100                              xml_node = xml_node->next) {
101
102                                 if (xml_node->type == XML_ELEMENT_NODE &&
103                                     !strcmp((char *)xml_node->name, "HostEntry")) {
104                                         int match = 0;
105
106                                         for (xml_node2 = xml_node->children;
107                                              match >= 0 && xml_node2; xml_node2 = xml_node2->next) {
108
109                                                 if (xml_node2->type != XML_ELEMENT_NODE)
110                                                         continue;
111
112                                                 if (!match && !strcmp((char *)xml_node2->name, "HostName")) {
113                                                         char *content = (char *)xmlNodeGetContent(xml_node2);
114                                                         if (content && !strcmp(content, host))
115                                                                 match = 1;
116                                                         else
117                                                                 match = -1;
118                                                         free(content);
119                                                 } else if (match &&
120                                                            !strcmp((char *)xml_node2->name, "HostAddress")) {
121                                                         char *content = (char *)xmlNodeGetContent(xml_node2);
122                                                         if (content) {
123                                                                 vpninfo->hostname = content;
124                                                                 printf(_("Host \"%s\" has address \"%s\"\n"),
125                                                                        host, content);
126                                                         }
127                                                 } else if (match &&
128                                                            !strcmp((char *)xml_node2->name, "UserGroup")) {
129                                                         char *content = (char *)xmlNodeGetContent(xml_node2);
130                                                         if (content) {
131                                                                 free(vpninfo->urlpath);
132                                                                 vpninfo->urlpath = content;
133                                                                 printf(_("Host \"%s\" has UserGroup \"%s\"\n"),
134                                                                        host, content);
135                                                         }
136                                                 }
137                                         }
138                                 }
139
140                         }
141                         break;
142                 }
143         }
144         xmlFreeDoc(xml_doc);
145
146         if (!vpninfo->hostname) {
147                 fprintf(stderr, _("Host \"%s\" not listed in config; treating as raw hostname\n"),
148                         host);
149         }
150
151         return 0;
152 }