xml.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * OpenConnect (SSL + DTLS) VPN client
  3. *
  4. * Copyright © 2008-2015 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. #include <config.h>
  19. #include "openconnect-internal.h"
  20. #include <libxml/parser.h>
  21. #include <libxml/tree.h>
  22. #include <unistd.h>
  23. #include <fcntl.h>
  24. #include <sys/types.h>
  25. #include <string.h>
  26. #include <ctype.h>
  27. #include <errno.h>
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. static char *fetch_and_trim(xmlNode *node)
  31. {
  32. char *str = (char *)xmlNodeGetContent(node), *p;
  33. int i, len;
  34. if (!str)
  35. return NULL;
  36. len = strlen(str);
  37. for (i = len-1; i >= 0; i--) {
  38. if (isspace((int)(unsigned char)str[i]))
  39. str[i] = 0;
  40. else
  41. break;
  42. }
  43. for (p = str; isspace((int)(unsigned char)*p); p++)
  44. ;
  45. if (p == str)
  46. return str;
  47. p = strdup(p);
  48. free(str);
  49. return p;
  50. }
  51. int config_lookup_host(struct openconnect_info *vpninfo, const char *host)
  52. {
  53. int i;
  54. ssize_t size;
  55. char *xmlfile;
  56. unsigned char sha1[SHA1_SIZE];
  57. xmlDocPtr xml_doc;
  58. xmlNode *xml_node, *xml_node2;
  59. if (!vpninfo->xmlconfig)
  60. return 0;
  61. size = openconnect_read_file(vpninfo, vpninfo->xmlconfig, &xmlfile);
  62. if (size == -ENOENT) {
  63. fprintf(stderr, _("Treating host \"%s\" as a raw hostname\n"), host);
  64. return 0;
  65. } else if (size <= 0) {
  66. return size;
  67. }
  68. if (openconnect_sha1(sha1, xmlfile, size)) {
  69. fprintf(stderr, _("Failed to SHA1 existing file\n"));
  70. free(xmlfile);
  71. return -1;
  72. }
  73. for (i = 0; i < SHA1_SIZE; i++)
  74. snprintf(&vpninfo->xmlsha1[i*2], 3, "%02x", sha1[i]);
  75. vpn_progress(vpninfo, PRG_DEBUG, _("XML config file SHA1: %s\n"),
  76. vpninfo->xmlsha1);
  77. xml_doc = xmlReadMemory(xmlfile, size, "noname.xml", NULL, 0);
  78. free(xmlfile);
  79. if (!xml_doc) {
  80. fprintf(stderr, _("Failed to parse XML config file %s\n"),
  81. vpninfo->xmlconfig);
  82. fprintf(stderr, _("Treating host \"%s\" as a raw hostname\n"),
  83. host);
  84. return 0;
  85. }
  86. xml_node = xmlDocGetRootElement(xml_doc);
  87. for (xml_node = xml_node->children; xml_node; xml_node = xml_node->next) {
  88. if (xml_node->type == XML_ELEMENT_NODE &&
  89. !strcmp((char *)xml_node->name, "ServerList")) {
  90. for (xml_node = xml_node->children; xml_node && !vpninfo->hostname;
  91. xml_node = xml_node->next) {
  92. if (xml_node->type == XML_ELEMENT_NODE &&
  93. !strcmp((char *)xml_node->name, "HostEntry")) {
  94. int match = 0;
  95. for (xml_node2 = xml_node->children;
  96. match >= 0 && xml_node2; xml_node2 = xml_node2->next) {
  97. if (xml_node2->type != XML_ELEMENT_NODE)
  98. continue;
  99. if (!match && !strcmp((char *)xml_node2->name, "HostName")) {
  100. char *content = fetch_and_trim(xml_node2);
  101. if (content && !strcmp(content, host))
  102. match = 1;
  103. else
  104. match = -1;
  105. free(content);
  106. } else if (match &&
  107. !strcmp((char *)xml_node2->name, "HostAddress")) {
  108. char *content = fetch_and_trim(xml_node2);
  109. if (content &&
  110. !openconnect_parse_url(vpninfo, content)) {
  111. printf(_("Host \"%s\" has address \"%s\"\n"),
  112. host, content);
  113. }
  114. free(content);
  115. } else if (match &&
  116. !strcmp((char *)xml_node2->name, "UserGroup")) {
  117. char *content = fetch_and_trim(xml_node2);
  118. if (content) {
  119. free(vpninfo->urlpath);
  120. vpninfo->urlpath = content;
  121. printf(_("Host \"%s\" has UserGroup \"%s\"\n"),
  122. host, content);
  123. }
  124. }
  125. }
  126. }
  127. }
  128. break;
  129. }
  130. }
  131. xmlFreeDoc(xml_doc);
  132. if (!vpninfo->hostname) {
  133. fprintf(stderr, _("Host \"%s\" not listed in config; treating as raw hostname\n"),
  134. host);
  135. }
  136. return 0;
  137. }