/* **************************************************************************** * * Entity::check - */ std::string Entity::check(ConnectionInfo* ciP, RequestType requestType) { if ((requestType == EntitiesRequest) && (id == "")) { return "No Entity ID"; } if (forbiddenChars(id.c_str())) { LM_W(("Bad Input (found a forbidden character in the id of an entity")); return "Invalid characters in entity id"; } if (forbiddenChars(type.c_str())) { LM_W(("Bad Input (found a forbidden character in the type of an entity")); return "Invalid characters in entity type"; } if (forbiddenChars(isPattern.c_str())) { LM_W(("Bad Input (found a forbidden character in the pattern of an entity")); return "Invalid characters in entity isPattern"; } return attributeVector.check(requestType, JSON, "", "", 0); }
/* **************************************************************************** * * treat - * * This is the function that actually treats a node, bu calling its treat function * provided by src/lib/xmlRequest - the entry point of XML parsing. * * It simple compares the current path with the paths in the incoming vector 'parseVector' * and if a hit is found calls the 'treat' function of that hit (the instance of the vector). * * If no hit is found it means that the path of the current XML node is unknown. * This will result in either a 'PARSE ERROR' or thatthe node is part of a Compound. */ static bool treat(ConnectionInfo* ciP, xml_node<>* node, const std::string& path, XmlNode* parseVector, ParseData* parseDataP) { for (unsigned int ix = 0; parseVector[ix].path != "LAST"; ++ix) { if (path == parseVector[ix].path) { int r; // // Before treating a node, a check is made that the value of the node has no forbidden // characters. // However, if the the node has attributes, then the values of the attributes are checked instead // if (node->first_attribute() == NULL) { if (forbiddenChars(node->value()) == true) { LM_E(("Found a forbidden value in '%s'", node->value())); ciP->httpStatusCode = SccBadRequest; ciP->answer = std::string("Illegal value for XML attribute"); return true; } } else { for (xml_attribute<> *attr = node->first_attribute(); attr; attr = attr->next_attribute()) { if (forbiddenChars(attr->value()) == true) { LM_E(("Found a forbidden value in attribute: '%s'", node->value())); ciP->httpStatusCode = SccBadRequest; ciP->answer = std::string("Illegal value for XML attribute"); return true; } } } if ((r = parseVector[ix].treat(node, parseDataP)) != 0) { LM_W(("Bad Input (xml parse error %d)", r)); } return true; // Node has been treated } } return false; // Node was not found in the parse vector }
/* **************************************************************************** * * urlCheck - * * Returns 'true' if the URL is OK, 'false' otherwise. * ciP->answer and ciP->httpStatusCode are set if an error is encountered. * */ bool urlCheck(ConnectionInfo* ciP, const std::string& url) { if (forbiddenChars(url.c_str()) == true) { OrionError error(SccBadRequest, "invalid character in URI"); ciP->httpStatusCode = SccBadRequest; ciP->answer = error.render(ciP->outFormat, ""); return false; } return true; }
/* **************************************************************************** * * Entity::check - */ std::string Entity::check(ConnectionInfo* ciP, RequestType requestType) { ssize_t len; char errorMsg[128]; if ((requestType == EntitiesRequest) && (id == "")) { return "No Entity ID"; } if ( (len = strlen(id.c_str())) > MAX_ID_LEN) { snprintf(errorMsg, sizeof errorMsg, "entity id length: %zd, max length supported: %d", len, MAX_ID_LEN); alarmMgr.badInput(clientIp, errorMsg); return std::string(errorMsg); } if (forbiddenIdChars(ciP->apiVersion, id.c_str())) { alarmMgr.badInput(clientIp, "found a forbidden character in the id of an entity"); return "Invalid characters in entity id"; } if ( (len = strlen(type.c_str())) > MAX_ID_LEN) { snprintf(errorMsg, sizeof errorMsg, "entity type length: %zd, max length supported: %d", len, MAX_ID_LEN); alarmMgr.badInput(clientIp, errorMsg); return std::string(errorMsg); } if (ciP->apiVersion == "v2" && (len = strlen(type.c_str())) < MIN_ID_LEN) { snprintf(errorMsg, sizeof errorMsg, "entity type length: %zd, min length supported: %d", len, MIN_ID_LEN); alarmMgr.badInput(clientIp, errorMsg); return std::string(errorMsg); } if (forbiddenIdChars(ciP->apiVersion, type.c_str())) { alarmMgr.badInput(clientIp, "found a forbidden character in the type of an entity"); return "Invalid characters in entity type"; } if (forbiddenChars(isPattern.c_str())) { alarmMgr.badInput(clientIp, "found a forbidden character in the pattern of an entity"); return "Invalid characters in entity isPattern"; } return attributeVector.check(ciP, requestType, "", "", 0); }
/* **************************************************************************** * * Metadata::check - */ std::string Metadata::check ( RequestType requestType, Format format, const std::string& indent, const std::string& predetectedError, int counter ) { if (name == "") { return "missing metadata name"; } if (forbiddenChars(name.c_str())) { return "Invalid characters in metadata name"; } if (forbiddenChars(type.c_str())) { return "Invalid characters in metadata type"; } if (valueType == orion::ValueTypeString) { if (forbiddenChars(stringValue.c_str())) { return "Invalid characters in metadata value"; } if ((stringValue == "") && (type != "Association")) { return "missing metadata value"; } } if (type == "Association") { return association.check(requestType, format, indent, predetectedError, counter); } return "OK"; }
/* **************************************************************************** * * urlCheck - check for forbidden characters and remove trailing slashes * * Returns 'true' if the URL is OK, 'false' otherwise. * ciP->answer and ciP->httpStatusCode are set if an error is encountered. * */ bool urlCheck(ConnectionInfo* ciP, const std::string& url) { if (forbiddenChars(url.c_str()) == true) { OrionError error(SccBadRequest, "invalid character in URI"); ciP->httpStatusCode = SccBadRequest; ciP->answer = error.render(ciP->outFormat, ""); return false; } // // Remove '/' at end of URL path // char* s = (char*) url.c_str(); while (s[strlen(s) - 1] == '/') { s[strlen(s) - 1] = 0; } return true; }
/* **************************************************************************** * * uriArgumentGet - */ static int uriArgumentGet(void* cbDataP, MHD_ValueKind kind, const char* ckey, const char* val) { ConnectionInfo* ciP = (ConnectionInfo*) cbDataP; std::string key = ckey; std::string value = (val == NULL)? "" : val; if (val == NULL || *val == 0) { OrionError error(SccBadRequest, std::string("Empty right-hand-side for URI param /") + ckey + "/"); ciP->httpStatusCode = SccBadRequest; ciP->answer = error.render(ciP, ""); return MHD_YES; } if (key == URI_PARAM_PAGINATION_OFFSET) { char* cP = (char*) val; while (*cP != 0) { if ((*cP < '0') || (*cP > '9')) { OrionError error(SccBadRequest, std::string("Bad pagination offset: /") + value + "/ [must be a decimal number]"); ciP->httpStatusCode = SccBadRequest; ciP->answer = error.render(ciP, ""); return MHD_YES; } ++cP; } } else if (key == URI_PARAM_PAGINATION_LIMIT) { char* cP = (char*) val; while (*cP != 0) { if ((*cP < '0') || (*cP > '9')) { OrionError error(SccBadRequest, std::string("Bad pagination limit: /") + value + "/ [must be a decimal number]"); ciP->httpStatusCode = SccBadRequest; ciP->answer = error.render(ciP, ""); return MHD_YES; } ++cP; } int limit = atoi(val); if (limit > atoi(MAX_PAGINATION_LIMIT)) { OrionError error(SccBadRequest, std::string("Bad pagination limit: /") + value + "/ [max: " + MAX_PAGINATION_LIMIT + "]"); ciP->httpStatusCode = SccBadRequest; ciP->answer = error.render(ciP, ""); return MHD_YES; } else if (limit == 0) { OrionError error(SccBadRequest, std::string("Bad pagination limit: /") + value + "/ [a value of ZERO is unacceptable]"); ciP->httpStatusCode = SccBadRequest; ciP->answer = error.render(ciP, ""); return MHD_YES; } } else if (key == URI_PARAM_PAGINATION_DETAILS) { if ((strcasecmp(value.c_str(), "on") != 0) && (strcasecmp(value.c_str(), "off") != 0)) { OrionError error(SccBadRequest, std::string("Bad value for /details/: /") + value + "/ [accepted: /on/, /ON/, /off/, /OFF/. Default is /off/]"); ciP->httpStatusCode = SccBadRequest; ciP->answer = error.render(ciP, ""); return MHD_YES; } } else if (key == URI_PARAM_ATTRIBUTES_FORMAT) { // If URI_PARAM_ATTRIBUTES_FORMAT used, set URI_PARAM_ATTRIBUTE_FORMAT as well ciP->uriParam[URI_PARAM_ATTRIBUTE_FORMAT] = value; } else if (key == URI_PARAM_ATTRIBUTE_FORMAT) { // If URI_PARAM_ATTRIBUTE_FORMAT used, set URI_PARAM_ATTRIBUTES_FORMAT as well ciP->uriParam[URI_PARAM_ATTRIBUTES_FORMAT] = value; } else if (key == URI_PARAM_OPTIONS) { ciP->uriParam[URI_PARAM_OPTIONS] = value; if (uriParamOptionsParse(ciP, val) != 0) { OrionError error(SccBadRequest, "Invalid value for URI param /options/"); ciP->httpStatusCode = SccBadRequest; ciP->answer = error.render(ciP, ""); } } else if (key == URI_PARAM_TYPE) { ciP->uriParam[URI_PARAM_TYPE] = value; if (strstr(val, ",")) // More than ONE type? { uriParamTypesParse(ciP, val); } else { ciP->uriParamTypes.push_back(val); } } else if (key != URI_PARAM_Q) // FIXME P1: possible more known options here ... { LM_T(LmtUriParams, ("Received unrecognized URI parameter: '%s'", key.c_str())); } if (val != NULL) { ciP->uriParam[key] = value; } else { ciP->uriParam[key] = "SET"; } LM_T(LmtUriParams, ("URI parameter: %s: %s", key.c_str(), ciP->uriParam[key].c_str())); // // Now check the URI param has no invalid characters // Except for the URI params 'q' and 'idPattern' that are not to be checked for invalid characters // // Another exception: 'geometry' and 'coords' has a relaxed check for forbidden characters that // doesn't check for '=' and ';' as those characters are part of the syntaxis for the parameters. // bool containsForbiddenChars = false; if ((key == "geometry") || (key == "georel")) { containsForbiddenChars = forbiddenChars(val, "=;"); } else if (key == "coords") { containsForbiddenChars = forbiddenChars(val, ";"); } else if ((key != "q") && (key != "idPattern")) { containsForbiddenChars = forbiddenChars(ckey) || forbiddenChars(val); } if (containsForbiddenChars == true) { std::string details = std::string("found a forbidden character in URI param '") + key + "'"; OrionError error(SccBadRequest, "invalid character in URI parameter"); alarmMgr.badInput(clientIp, details); ciP->httpStatusCode = SccBadRequest; ciP->answer = error.render(ciP, ""); } return MHD_YES; }
/* **************************************************************************** * * eatCompound - consume the compound tree * * Three types of tree nodes here (4 actually); * - toplevel node * - string * - object node * - vector node */ void eatCompound(ConnectionInfo* ciP, orion::CompoundValueNode* containerP, xml_node<>* node, const std::string& indent) { if (containerP == NULL) // toplevel { std::string xmlAttribute = xmlTypeAttributeGet(node); if (xmlAttribute == "vector") { containerP = new CompoundValueNode(orion::CompoundValueNode::Vector); } else if (xmlAttribute =="") { containerP = new CompoundValueNode(orion::CompoundValueNode::Object); } else { ciP->httpStatusCode = SccBadRequest; ciP->answer = std::string("Bad value for XML attribute /type/ for /") + node->name() + "/: " + xmlAttribute; LM_W(("Bad Input (%s)", ciP->answer.c_str())); return; } ciP->compoundValueRoot = containerP; } else { std::string value = wsStrip(node->value()); std::string name = wsStrip(node->name()); if (value == "") // Object OR Vector { std::string xmlAttribute = xmlTypeAttributeGet(node); if (xmlAttribute == "vector") { containerP = containerP->add(orion::CompoundValueNode::Vector, name); } else if (xmlAttribute == "") { containerP = containerP->add(orion::CompoundValueNode::Object, name); } else { ciP->httpStatusCode = SccBadRequest; ciP->answer = std::string("Bad value for XML attribute /type/ for /") + name + "/: " + xmlAttribute; LM_W(("Bad Input (%s)", ciP->answer.c_str())); return; } } else // String { if (forbiddenChars(value.c_str()) == true) { LM_E(("Found a forbidden value in '%s'", value.c_str())); ciP->httpStatusCode = SccBadRequest; ciP->answer = std::string("Illegal value for XML attribute"); return; } containerP->add(orion::CompoundValueNode::String, name, value); } } xml_node<>* child = node->first_node(); while (child != NULL) { if (child->name()[0] != 0) { eatCompound(ciP, containerP, child, indent + " "); } child = child->next_sibling(); } }