1 /*
2 * ModSecurity, http://www.modsecurity.org/
3 * Copyright (c) 2015 - 2021 Trustwave Holdings, Inc. (http://www.trustwave.com/)
4 *
5 * You may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * If any of the files related to licensing are missing or if you have any
11 * other questions related to licensing please contact Trustwave Holdings, Inc.
12 * directly using the email address security@modsecurity.org.
13 *
14 */
15
16 #include "src/operators/validate_schema.h"
17
18 #include <string>
19
20 #include "src/operators/operator.h"
21 #include "src/request_body_processor/xml.h"
22 #include "src/utils/system.h"
23
24
25 namespace modsecurity {
26 namespace operators {
27
28 #ifdef WITH_LIBXML2
29
init(const std::string & file,std::string * error)30 bool ValidateSchema::init(const std::string &file, std::string *error) {
31 std::string err;
32 m_resource = utils::find_resource(m_param, file, &err);
33 if (m_resource == "") {
34 error->assign("XML: File not found: " + m_param + ". " + err);
35 return false;
36 }
37
38 return true;
39 }
40
41
evaluate(Transaction * t,const std::string & str)42 bool ValidateSchema::evaluate(Transaction *t,
43 const std::string &str) {
44 int rc;
45
46 m_parserCtx = xmlSchemaNewParserCtxt(m_resource.c_str());
47 if (m_parserCtx == NULL) {
48 std::stringstream err;
49 err << "XML: Failed to load Schema from file: ";
50 err << m_resource;
51 err << ". ";
52 if (m_err.empty() == false) {
53 err << m_err;
54 }
55 ms_dbg_a(t, 4, err.str());
56 return true;
57 }
58
59 xmlSchemaSetParserErrors(m_parserCtx,
60 (xmlSchemaValidityErrorFunc)error_load,
61 (xmlSchemaValidityWarningFunc)warn_load, &m_err);
62
63 xmlThrDefSetGenericErrorFunc(m_parserCtx,
64 null_error);
65
66 xmlSetGenericErrorFunc(m_parserCtx,
67 null_error);
68
69 m_schema = xmlSchemaParse(m_parserCtx);
70 if (m_schema == NULL) {
71 std::stringstream err;
72 err << "XML: Failed to load Schema: ";
73 err << m_resource;
74 err << ".";
75 if (m_err.empty() == false) {
76 err << " " << m_err;
77 }
78 ms_dbg_a(t, 4, err.str());
79 xmlSchemaFreeParserCtxt(m_parserCtx);
80 return true;
81 }
82
83 m_validCtx = xmlSchemaNewValidCtxt(m_schema);
84 if (m_validCtx == NULL) {
85 std::stringstream err("XML: Failed to create validation context.");
86 if (m_err.empty() == false) {
87 err << " " << m_err;
88 }
89 ms_dbg_a(t, 4, err.str());
90 return true;
91 }
92
93 /* Send validator errors/warnings to msr_log */
94 xmlSchemaSetValidErrors(m_validCtx,
95 (xmlSchemaValidityErrorFunc)error_runtime,
96 (xmlSchemaValidityWarningFunc)warn_runtime, t);
97
98 if (t->m_xml->m_data.doc == NULL) {
99 ms_dbg_a(t, 4, "XML document tree could not be found for " \
100 "schema validation.");
101 return true;
102 }
103
104 if (t->m_xml->m_data.well_formed != 1) {
105 ms_dbg_a(t, 4, "XML: Schema validation failed because " \
106 "content is not well formed.");
107 return true;
108 }
109
110 /* Make sure there were no other generic processing errors */
111 /*
112 if (msr->msc_reqbody_error) {
113 ms_dbg_a(t, 4, "XML: Schema validation could not proceed due to previous"
114 " processing errors.");
115 return true;
116 }
117 */
118
119 rc = xmlSchemaValidateDoc(m_validCtx, t->m_xml->m_data.doc);
120 if (rc != 0) {
121 ms_dbg_a(t, 4, "XML: Schema validation failed.");
122 xmlSchemaFree(m_schema);
123 xmlSchemaFreeParserCtxt(m_parserCtx);
124 return true; /* No match. */
125 }
126
127 ms_dbg_a(t, 4, "XML: Successfully validated payload against " \
128 "Schema: " + m_resource);
129 xmlSchemaFree(m_schema);
130 xmlSchemaFreeParserCtxt(m_parserCtx);
131
132 return false;
133 }
134
135 #endif
136
137 } // namespace operators
138 } // namespace modsecurity
139