PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/src/os_xml/os_xml.c

https://gitlab.com/Blueprint-Marketing/ossec-hids
C | 536 lines | 432 code | 71 blank | 33 comment | 194 complexity | 45d43cdaf5605d32025dfe3551a4cef6 MD5 | raw file
  1. /* Copyright (C) 2009 Trend Micro Inc.
  2. * All rights reserved.
  3. *
  4. * This program is a free software; you can redistribute it
  5. * and/or modify it under the terms of the GNU General Public
  6. * License (version 2) as published by the FSF - Free Software
  7. * Foundation
  8. */
  9. /* os_xml Library */
  10. #include <stdio.h>
  11. #include <stdarg.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <ctype.h>
  15. #include "os_xml.h"
  16. #include "os_xml_internal.h"
  17. /* Prototypes */
  18. static int _oscomment(FILE *fp) __attribute__((nonnull));
  19. static int _writecontent(const char *str, size_t size, unsigned int parent, OS_XML *_lxml) __attribute__((nonnull));
  20. static int _writememory(const char *str, XML_TYPE type, size_t size,
  21. unsigned int parent, OS_XML *_lxml) __attribute__((nonnull));
  22. static int _xml_fgetc(FILE *fp) __attribute__((nonnull));
  23. static int _ReadElem(FILE *fp, unsigned int parent, OS_XML *_lxml) __attribute__((nonnull));
  24. static int _getattributes(FILE *fp, unsigned int parent, OS_XML *_lxml) __attribute__((nonnull));
  25. static void xml_error(OS_XML *_lxml, const char *msg, ...) __attribute__((format(printf, 2, 3), nonnull));
  26. /* Current line */
  27. static unsigned int _line;
  28. /* Local fgetc */
  29. static int _xml_fgetc(FILE *fp)
  30. {
  31. int c;
  32. c = fgetc(fp);
  33. if (c == '\n') { /* add newline */
  34. _line++;
  35. }
  36. return (c);
  37. }
  38. static void xml_error(OS_XML *_lxml, const char *msg, ...)
  39. {
  40. va_list args;
  41. va_start(args, msg);
  42. memset(_lxml->err, '\0', XML_ERR_LENGTH);
  43. vsnprintf(_lxml->err, XML_ERR_LENGTH - 1, msg, args);
  44. va_end(args);
  45. _lxml->err_line = _line;
  46. }
  47. /* Clear memory */
  48. void OS_ClearXML(OS_XML *_lxml)
  49. {
  50. unsigned int i;
  51. for (i = 0; i < _lxml->cur; i++) {
  52. free(_lxml->el[i]);
  53. free(_lxml->ct[i]);
  54. }
  55. _lxml->cur = 0;
  56. _lxml->fol = 0;
  57. _lxml->err_line = 0;
  58. free(_lxml->el);
  59. _lxml->el = NULL;
  60. free(_lxml->ct);
  61. _lxml->ct = NULL;
  62. free(_lxml->rl);
  63. _lxml->rl = NULL;
  64. free(_lxml->tp);
  65. _lxml->tp = NULL;
  66. free(_lxml->ck);
  67. _lxml->ck = NULL;
  68. free(_lxml->ln);
  69. _lxml->ln = NULL;
  70. memset(_lxml->err, '\0', XML_ERR_LENGTH);
  71. }
  72. /* Read na XML file and generate the necessary structs */
  73. int OS_ReadXML(const char *file, OS_XML *_lxml)
  74. {
  75. int r;
  76. unsigned int i;
  77. FILE *fp;
  78. /* Initialize xml structure */
  79. _lxml->cur = 0;
  80. _lxml->fol = 0;
  81. _lxml->el = NULL;
  82. _lxml->ct = NULL;
  83. _lxml->tp = NULL;
  84. _lxml->rl = NULL;
  85. _lxml->ck = NULL;
  86. _lxml->ln = NULL;
  87. _lxml->err_line = 0;
  88. memset(_lxml->err, '\0', XML_ERR_LENGTH);
  89. fp = fopen(file, "r");
  90. if (!fp) {
  91. xml_error(_lxml, "XMLERR: File '%s' not found.", file);
  92. return (-2);
  93. }
  94. /* Zero the line */
  95. _line = 1;
  96. if ((r = _ReadElem(fp, 0, _lxml)) < 0) { /* First position */
  97. if (r != LEOF) {
  98. fclose(fp);
  99. return (-1);
  100. }
  101. }
  102. for (i = 0; i < _lxml->cur; i++) {
  103. if (_lxml->ck[i] == 0) {
  104. xml_error(_lxml, "XMLERR: Element '%s' not closed.", _lxml->el[i]);
  105. fclose(fp);
  106. return (-1);
  107. }
  108. }
  109. fclose(fp);
  110. return (0);
  111. }
  112. static int _oscomment(FILE *fp)
  113. {
  114. int c;
  115. if ((c = fgetc(fp)) == _R_COM) {
  116. while ((c = _xml_fgetc(fp)) != EOF) {
  117. if (c == _R_COM) {
  118. if ((c = fgetc(fp)) == _R_CONFE) {
  119. return (1);
  120. }
  121. ungetc(c, fp);
  122. } else if (c == '-') { /* W3C way of finishing comments */
  123. if ((c = _xml_fgetc(fp)) == '-') {
  124. if ((c = fgetc(fp)) == _R_CONFE) {
  125. return (1);
  126. }
  127. ungetc(c, fp);
  128. }
  129. ungetc(c, fp);
  130. } else {
  131. continue;
  132. }
  133. }
  134. return (-1);
  135. } else {
  136. ungetc(c, fp);
  137. }
  138. return (0);
  139. }
  140. static int _ReadElem(FILE *fp, unsigned int parent, OS_XML *_lxml)
  141. {
  142. int c;
  143. unsigned int count = 0;
  144. unsigned int _currentlycont = 0;
  145. short int location = -1;
  146. int prevv = 0;
  147. char elem[XML_MAXSIZE + 1];
  148. char cont[XML_MAXSIZE + 1];
  149. char closedelem[XML_MAXSIZE + 1];
  150. memset(elem, '\0', XML_MAXSIZE + 1);
  151. memset(cont, '\0', XML_MAXSIZE + 1);
  152. memset(closedelem, '\0', XML_MAXSIZE + 1);
  153. while ((c = _xml_fgetc(fp)) != EOF) {
  154. if (c == '\\') {
  155. prevv = c;
  156. } else if (prevv == '\\') {
  157. if (c != _R_CONFS) {
  158. prevv = 0;
  159. }
  160. }
  161. /* Max size */
  162. if (count >= XML_MAXSIZE) {
  163. xml_error(_lxml, "XMLERR: String overflow.");
  164. return (-1);
  165. }
  166. /* Check for comments */
  167. if (c == _R_CONFS) {
  168. int r = 0;
  169. if ((r = _oscomment(fp)) < 0) {
  170. xml_error(_lxml, "XMLERR: Comment not closed.");
  171. return (-1);
  172. } else if (r == 1) {
  173. continue;
  174. }
  175. }
  176. /* Real checking */
  177. if ((location == -1) && (prevv == 0)) {
  178. if (c == _R_CONFS) {
  179. if ((c = fgetc(fp)) == '/') {
  180. xml_error(_lxml, "XMLERR: Element not opened.");
  181. return (-1);
  182. } else {
  183. ungetc(c, fp);
  184. }
  185. location = 0;
  186. } else {
  187. continue;
  188. }
  189. }
  190. else if ((location == 0) && ((c == _R_CONFE) || isspace(c))) {
  191. int _ge = 0;
  192. int _ga = 0;
  193. elem[count] = '\0';
  194. /* Remove the / at the end of the element name */
  195. if (count > 0 && elem[count - 1] == '/') {
  196. _ge = '/';
  197. elem[count - 1] = '\0';
  198. }
  199. if (_writememory(elem, XML_ELEM, count + 1, parent, _lxml) < 0) {
  200. return (-1);
  201. }
  202. _currentlycont = _lxml->cur - 1;
  203. if (isspace(c)) {
  204. if ((_ga = _getattributes(fp, parent, _lxml)) < 0) {
  205. return (-1);
  206. }
  207. }
  208. /* If the element is closed already (finished in />) */
  209. if ((_ge == '/') || (_ga == '/')) {
  210. if (_writecontent("\0", 2, _currentlycont, _lxml) < 0) {
  211. return (-1);
  212. }
  213. _lxml->ck[_currentlycont] = 1;
  214. _currentlycont = 0;
  215. count = 0;
  216. location = -1;
  217. memset(elem, '\0', XML_MAXSIZE);
  218. memset(closedelem, '\0', XML_MAXSIZE);
  219. memset(cont, '\0', XML_MAXSIZE);
  220. if (parent > 0) {
  221. return (0);
  222. }
  223. } else {
  224. count = 0;
  225. location = 1;
  226. }
  227. }
  228. else if ((location == 2) && (c == _R_CONFE)) {
  229. closedelem[count] = '\0';
  230. if (strcmp(closedelem, elem) != 0) {
  231. xml_error(_lxml, "XMLERR: Element '%s' not closed.", elem);
  232. return (-1);
  233. }
  234. if (_writecontent(cont, strlen(cont) + 1, _currentlycont, _lxml) < 0) {
  235. return (-1);
  236. }
  237. _lxml->ck[_currentlycont] = 1;
  238. memset(elem, '\0', XML_MAXSIZE);
  239. memset(closedelem, '\0', XML_MAXSIZE);
  240. memset(cont, '\0', XML_MAXSIZE);
  241. _currentlycont = 0;
  242. count = 0;
  243. location = -1;
  244. if (parent > 0) {
  245. return (0);
  246. }
  247. } else if ((location == 1) && (c == _R_CONFS) && (prevv == 0)) {
  248. if ((c = fgetc(fp)) == '/') {
  249. cont[count] = '\0';
  250. count = 0;
  251. location = 2;
  252. } else {
  253. ungetc(c, fp);
  254. ungetc(_R_CONFS, fp);
  255. if (_ReadElem(fp, parent + 1, _lxml) < 0) {
  256. return (-1);
  257. }
  258. count = 0;
  259. }
  260. } else {
  261. if (location == 0) {
  262. elem[count++] = (char) c;
  263. } else if (location == 1) {
  264. cont[count++] = (char) c;
  265. } else if (location == 2) {
  266. closedelem[count++] = (char) c;
  267. }
  268. if ((_R_CONFS == c) && (prevv != 0)) {
  269. prevv = 0;
  270. }
  271. }
  272. }
  273. if (location == -1) {
  274. return (LEOF);
  275. }
  276. xml_error(_lxml, "XMLERR: End of file and some elements were not closed.");
  277. return (-1);
  278. }
  279. static int _writememory(const char *str, XML_TYPE type, size_t size,
  280. unsigned int parent, OS_XML *_lxml)
  281. {
  282. char **tmp;
  283. int *tmp2;
  284. unsigned int *tmp3;
  285. XML_TYPE *tmp4;
  286. /* Allocate for the element */
  287. tmp = (char **)realloc(_lxml->el, (_lxml->cur + 1) * sizeof(char *));
  288. if (tmp == NULL) {
  289. goto fail;
  290. }
  291. _lxml->el = tmp;
  292. _lxml->el[_lxml->cur] = (char *)calloc(size, sizeof(char));
  293. if (_lxml->el[_lxml->cur] == NULL) {
  294. goto fail;
  295. }
  296. strncpy(_lxml->el[_lxml->cur], str, size - 1);
  297. /* Allocate for the content */
  298. tmp = (char **)realloc(_lxml->ct, (_lxml->cur + 1) * sizeof(char *));
  299. if (tmp == NULL) {
  300. goto fail;
  301. }
  302. _lxml->ct = tmp;
  303. _lxml->ct[_lxml->cur] = NULL;
  304. /* Allocate for the type */
  305. tmp4 = (XML_TYPE *) realloc(_lxml->tp, (_lxml->cur + 1) * sizeof(XML_TYPE));
  306. if (tmp4 == NULL) {
  307. goto fail;
  308. }
  309. _lxml->tp = tmp4;
  310. _lxml->tp[_lxml->cur] = type;
  311. /* Allocate for the relation */
  312. tmp3 = (unsigned int *) realloc(_lxml->rl, (_lxml->cur + 1) * sizeof(unsigned int));
  313. if (tmp3 == NULL) {
  314. goto fail;
  315. }
  316. _lxml->rl = tmp3;
  317. _lxml->rl[_lxml->cur] = parent;
  318. /* Allocate for the "check" */
  319. tmp2 = (int *) realloc(_lxml->ck, (_lxml->cur + 1) * sizeof(int));
  320. if (tmp2 == NULL) {
  321. goto fail;
  322. }
  323. _lxml->ck = tmp2;
  324. _lxml->ck[_lxml->cur] = 0;
  325. /* Allocate for the line */
  326. tmp3 = (unsigned int *) realloc(_lxml->ln, (_lxml->cur + 1) * sizeof(unsigned int));
  327. if (tmp3 == NULL) {
  328. goto fail;
  329. }
  330. _lxml->ln = tmp3;
  331. _lxml->ln[_lxml->cur] = _line;
  332. /* Attributes does not need to be closed */
  333. if (type == XML_ATTR) {
  334. _lxml->ck[_lxml->cur] = 1;
  335. }
  336. /* Check if it is a variable */
  337. if (strcasecmp(XML_VAR, str) == 0) {
  338. _lxml->tp[_lxml->cur] = XML_VARIABLE_BEGIN;
  339. }
  340. _lxml->cur++;
  341. return (0);
  342. fail:
  343. snprintf(_lxml->err, XML_ERR_LENGTH, "XMLERR: Memory error.");
  344. return (-1);
  345. }
  346. static int _writecontent(const char *str, size_t size, unsigned int parent, OS_XML *_lxml)
  347. {
  348. _lxml->ct[parent] = (char *)calloc(size, sizeof(char));
  349. if ( _lxml->ct[parent] == NULL) {
  350. snprintf(_lxml->err, XML_ERR_LENGTH, "XMLERR: Memory error.");
  351. return (-1);
  352. }
  353. strncpy(_lxml->ct[parent], str, size - 1);
  354. return (0);
  355. }
  356. /* Read the attributes of an element */
  357. static int _getattributes(FILE *fp, unsigned int parent, OS_XML *_lxml)
  358. {
  359. int location = 0;
  360. unsigned int count = 0;
  361. int c;
  362. int c_to_match = 0;
  363. char attr[XML_MAXSIZE + 1];
  364. char value[XML_MAXSIZE + 1];
  365. memset(attr, '\0', XML_MAXSIZE + 1);
  366. memset(value, '\0', XML_MAXSIZE + 1);
  367. while ((c = _xml_fgetc(fp)) != EOF) {
  368. if (count >= XML_MAXSIZE) {
  369. attr[count - 1] = '\0';
  370. xml_error(_lxml,
  371. "XMLERR: Overflow attempt at attribute '%.20s'.", attr);
  372. return (-1);
  373. }
  374. else if ((c == _R_CONFE) || ((location == 0) && (c == '/'))) {
  375. if (location == 1) {
  376. xml_error(_lxml, "XMLERR: Attribute '%s' not closed.",
  377. attr);
  378. return (-1);
  379. } else if ((location == 0) && (count > 0)) {
  380. xml_error(_lxml, "XMLERR: Attribute '%s' has no value.",
  381. attr);
  382. return (-1);
  383. } else if (c == '/') {
  384. return (c);
  385. } else {
  386. return (0);
  387. }
  388. } else if ((location == 0) && (c == '=')) {
  389. attr[count] = '\0';
  390. /* Check for existing attribute with same name */
  391. unsigned int i = _lxml->cur - 1;
  392. /* Search attributes backwards in same parent */
  393. while (_lxml->rl[i] == parent && _lxml->tp[i] == XML_ATTR) {
  394. if (strcmp(_lxml->el[i], attr) == 0) {
  395. xml_error(_lxml, "XMLERR: Attribute '%s' already defined.", attr);
  396. return (-1);
  397. }
  398. /* Continue with previous element */
  399. if (i == 0) {
  400. break;
  401. }
  402. i--;
  403. }
  404. c = _xml_fgetc(fp);
  405. if ((c != '"') && (c != '\'')) {
  406. unsigned short int _err = 1;
  407. if (isspace(c)) {
  408. while ((c = _xml_fgetc(fp)) != EOF) {
  409. if (isspace(c)) {
  410. continue;
  411. } else if ((c == '"') || (c == '\'')) {
  412. _err = 0;
  413. break;
  414. } else {
  415. break;
  416. }
  417. }
  418. }
  419. if (_err != 0) {
  420. xml_error(_lxml,
  421. "XMLERR: Attribute '%s' not followed by a \" or \'."
  422. , attr);
  423. return (-1);
  424. }
  425. }
  426. c_to_match = c;
  427. location = 1;
  428. count = 0;
  429. } else if ((location == 0) && (isspace(c))) {
  430. if (count == 0) {
  431. continue;
  432. } else {
  433. xml_error(_lxml, "XMLERR: Attribute '%s' has no value.", attr);
  434. return (-1);
  435. }
  436. } else if ((location == 1) && (c == c_to_match)) {
  437. value[count] = '\0';
  438. if (_writememory(attr, XML_ATTR, strlen(attr) + 1,
  439. parent, _lxml) < 0) {
  440. return (-1);
  441. }
  442. if (_writecontent(value, count + 1, _lxml->cur - 1, _lxml) < 0) {
  443. return (-1);
  444. }
  445. c = _xml_fgetc(fp);
  446. if (isspace(c)) {
  447. return (_getattributes(fp, parent, _lxml));
  448. } else if (c == _R_CONFE) {
  449. return (0);
  450. } else if (c == '/') {
  451. return (c);
  452. }
  453. xml_error(_lxml,
  454. "XMLERR: Bad attribute closing for '%s'='%s'.",
  455. attr, value);
  456. return (-1);
  457. } else if (location == 0) {
  458. attr[count++] = (char) c;
  459. } else if (location == 1) {
  460. value[count++] = (char) c;
  461. }
  462. }
  463. xml_error(_lxml, "XMLERR: End of file while reading an attribute.");
  464. return (-1);
  465. }