/******************************************************************************* * Copyright (C) 2004-2006 Intel Corp. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * - Neither the name of Intel Corp. nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ /** * @author Anas Nashif */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include "wsman-xml-api.h" #include "wsman-client-api.h" #include "wsman-soap.h" #include "wsman-dispatcher.h" #include "wsman-xml.h" #include "wsman-xml-serializer.h" #include "wsman-soap-envelope.h" #include "wsman-soap-message.h" #include "wsman-faults.h" #define FAULT_XPATH_EXPR "/s:Envelope/s:Body/s:Fault/s:Code/s:Value" #define FAULT_SUBCODE_VALUE_XPATH "/s:Envelope/s:Body/s:Fault/s:Code/s:Subcode/s:Value" WsmanFaultDetailTable fault_detail_table[] = { { WSMAN_DETAIL_OK, NULL }, { WSMAN_DETAIL_ACK, "Ack" }, { WSMAN_DETAIL_ACTION_MISMATCH, "ActionMismatch" }, { WSMAN_DETAIL_ALREADY_EXISTS, "AlreadyExists" }, { WSMAN_DETAIL_AMBIGUOUS_SELECTORS, "AmbigousSelectors" }, { WSMAN_DETAIL_ASYNCHRONOUS_REQUEST, "AsynchronousRequest" }, { WSMAN_DETAIL_ADDRESSING_MODE, "AddressingMode" }, { WSMAN_DETAIL_AUTHERIZATION_MODE, "AutherizationMode" }, { WSMAN_DETAIL_BOOKMARKS, "Bookmarks" }, { WSMAN_DETAIL_CHARECHTER_SET, "CharechterSet" }, { WSMAN_DETAIL_DELIVERY_RETRIES, "DeliveryRetries" }, { WSMAN_DETAIL_DUPLICATE_SELECTORS, "DuplicateSelectors" }, { WSMAN_DETAIL_ENCODING_TYPE, "EncodingType" }, { WSMAN_DETAIL_ENUMERATION_MODE, "EnumerationMode" }, { WSMAN_DETAIL_EXPIRATION_TIME, "ExpirationTime" }, { WSMAN_DETAIL_EXPIRED, "Expired" }, { WSMAN_DETAIL_FILTERING_REQUIRED, "FilteringRequired" }, { WSMAN_DETAIL_FORMAT_MISMATCH, "FormatMismatch" }, { WSMAN_DETAIL_FORMAT_SECURITY_TOKEN, "FormatSecurityTocken" }, { WSMAN_DETAIL_FRAGMENT_LEVEL_ACCESS, "FragmentLevelAccess" }, { WSMAN_DETAIL_HEARTBEATS, "Heartbeats" }, { WSMAN_DETAIL_INSECURE_ADDRESS, "InsecureAddress" }, { WSMAN_DETAIL_INSUFFICIENT_SELECTORS, "InsufficientSelectors" }, { WSMAN_DETAIL_INVALID, "Invalid" }, { WSMAN_DETAIL_INVALID_ADDRESS, "InvalidAddress" }, { WSMAN_DETAIL_INVALID_FORMAT, "InvalidFormat" }, { WSMAN_DETAIL_INVALID_FRAGMENT, "InvalidFragment" }, { WSMAN_DETAIL_INVALID_NAME, "InvalidName" }, { WSMAN_DETAIL_INVALID_NAMESPACE, "InvalidNamespace" }, { WSMAN_DETAIL_INVALID_RESOURCEURI, "InvalidResourceURI" }, { WSMAN_DETAIL_INVALID_SELECTOR_ASSIGNMENT, "InvalidSelectorAssignment" }, { WSMAN_DETAIL_INVALID_SYSTEM, "InvalidSystem" }, { WSMAN_DETAIL_INVALID_TIMEOUT, "InvalidTimeout" }, { WSMAN_DETAIL_INVALID_VALUE, "InvalidValue" }, { WSMAN_DETAIL_INVALID_VALUES, "InvalidValues" }, { WSMAN_DETAIL_LOCALE, "Locale" }, { WSMAN_DETAIL_MAX_ELEMENTS, "MaxElements" }, { WSMAN_DETAIL_MAX_ENVELOPE_POLICY, "MaxEnvelopePolicy" }, { WSMAN_DETAIL_MAX_ENVELOPE_SIZE, "MaxEnvelopeSize" }, { WSMAN_DETAIL_MAX_TIME, "MaxTime" }, { WSMAN_DETAIL_MINIMUM_ENVELOPE_LIMIT, "MinimumEnvelopeLimit" }, { WSMAN_DETAIL_MISSING_VALUES, "MissingValues" }, { WSMAN_DETAIL_NOT_SUPPORTED, "NotSupported" }, { WSMAN_DETAIL_OPERATION_TIMEOUT, "OperationTimeout" }, { WSMAN_DETAIL_OPTION_LIMIT, "OptionLimit" }, { WSMAN_DETAIL_OPTION_SET, "OptionSet" }, { WSMAN_DETAIL_READ_ONLY, "ReadOnly" }, { WSMAN_DETAIL_RESOURCE_OFFLINE, "ResourceOffline" }, { WSMAN_DETAIL_RENAME, "Rename" }, { WSMAN_DETAIL_SELECTOR_LIMIT, "SelectorLimit" }, { WSMAN_DETAIL_SERVICE_ENVELOPE_LIMIT, "ServiceEnvelopeLimit" }, { WSMAN_DETAIL_TARGET_ALREADY_EXISTS, "TargetAlreadyExists" }, { WSMAN_DETAIL_TYPE_MISMATCH, "TypeMismatch" }, { WSMAN_DETAIL_UNEXPECTED_SELECTORS, "UnexpectedSelectors" }, { WSMAN_DETAIL_UNREPORTABLE_SUCCESS, "UnreportableSuccess" }, { WSMAN_DETAIL_UNUSABLE_ADDRESS, "UnusableAddress" }, { WSMAN_DETAIL_URI_LIMIT_EXCEEDED, "UriLimitExceeded" }, { WSMAN_DETAIL_WHITESPACE, "Whitespace" }, // WS-Addressing { WSA_DETAIL_DUPLICATE_MESSAGE_ID, "DuplicateMessageID" }, // SOAP { SOAP_DETAIL_HEADER_NOT_UNDERSTOOD, "HeaderNotUnderstood" }, // WS-Trust {WST_DETAIL_UNSUPPORTED_TOKENTYPE, "UnsupportedTokenType"}, // OpenWSMAN { OWSMAN_DETAIL_ENDPOINT_ERROR, "Unknown" }, { OWSMAN_NO_DETAILS, "Unknown" } }; WsmanFaultCodeTable fault_code_table[] = { { SOAP_FAULT_MUSTUNDERSTAND, WSMAN_STATUS_BAD_REQUEST, WSA_ACTION_FAULT, XML_NS_SOAP_1_2, FAULT_MUSTUNDERSTAND_CODE, "", "The WS-Management service cannot process a SOAP header in the request that " \ "is marked as mustUnderstand by the client. This could be caused by the use " \ "of a version of the protocol which is not supported, or may be an " \ "incompatibility between the client and server implementations." }, { WSA_ENDPOINT_UNAVAILABLE, WSMAN_STATUS_SERVICE_UNAVAILABLE, WSA_ACTION_FAULT, XML_NS_ADDRESSING, FAULT_SENDER_CODE, "EndpointUnavailable", "" }, { WSMAN_ACCESS_DENIED, WSMAN_STATUS_UNAUTHORIZED, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_SENDER_CODE, "AccessDenied", "The sender was not authorized to access the resource." }, { WSA_ACTION_NOT_SUPPORTED, WSMAN_STATUS_NOT_IMPLEMENTED, WSA_ACTION_FAULT, XML_NS_ADDRESSING, FAULT_SENDER_CODE, "ActionNotSupported", "The action is not supported by the service." }, { WSMAN_ALREADY_EXISTS, WSMAN_STATUS_BAD_REQUEST, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_SENDER_CODE, "AlreadyExists", "The sender attempted to create a resource which already exists." }, { WSEN_CANNOT_PROCESS_FILTER, WSMAN_STATUS_UNPROCESSABLE_ENTITY, WSENUM_ACTION_FAULT, XML_NS_ENUMERATION, FAULT_SENDER_CODE, "CannotProcessFilter", "The requested filter could not be processed." }, { WSMAN_CANNOT_PROCESS_FILTER, WSMAN_STATUS_UNPROCESSABLE_ENTITY, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_SENDER_CODE, "CannotProcessFilter", "The requested filter could not be processed." }, { WSMAN_CONCURRENCY, WSMAN_STATUS_CONFLICT, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_SENDER_CODE, "Concurrency", "The action could not be completed due to concurrency or locking problems." }, { WSA_DESTINATION_UNREACHABLE, WSMAN_STATUS_SERVICE_UNAVAILABLE, WSA_ACTION_FAULT, XML_NS_ADDRESSING, FAULT_SENDER_CODE, "DestinationUnreachable", "No route can be determined to reach the destination role defined by the WS-Addressing To." }, { WSMAN_ENCODING_LIMIT, WSMAN_STATUS_REQUEST_ENTITY_TOO_LARGE, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_SENDER_CODE, "EncodingLimit", "An internal encoding limit was exceeded in a request or would be violated if the message were processed." }, { WSA_ENDPOINT_UNAVAILABLE, WSMAN_STATUS_SERVICE_UNAVAILABLE, WSA_ACTION_FAULT, XML_NS_ADDRESSING, FAULT_RECEIVER_CODE, "EndpointUnavailable", "The specified endpoint is currently unavailable." }, { WSEN_FILTER_DIALECT_REQUESTED_UNAVAILABLE, WSMAN_STATUS_NOT_IMPLEMENTED, WSENUM_ACTION_FAULT, XML_NS_ENUMERATION, FAULT_SENDER_CODE, "FilterDialectRequestedUnavailable", "The requested filtering dialect is not supported." }, { WSEN_FILTERING_NOT_SUPPORTED, WSMAN_STATUS_NOT_IMPLEMENTED, WSENUM_ACTION_FAULT, XML_NS_ENUMERATION, FAULT_SENDER_CODE, "FilteringNotSupported", "Filtered enumeration is not supported." }, { WSMAN_FRAGMENT_DIALECT_NOT_SUPPORTED, WSMAN_STATUS_NOT_IMPLEMENTED, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_RECEIVER_CODE, "FragmentDialectNotSupported", "The requested fragment filtering dialect or language is not supported." }, { WSMAN_INTERNAL_ERROR, WSMAN_STATUS_INTERNAL_SERVER_ERROR, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_RECEIVER_CODE, "InternalError", "The service cannot comply with the request due to internal processing errors." }, { WSEN_INVALID_ENUMERATION_CONTEXT, WSMAN_STATUS_BAD_REQUEST, WSENUM_ACTION_FAULT, XML_NS_ENUMERATION, FAULT_RECEIVER_CODE, "InvalidEnumerationContext", "The supplied enumeration context is invalid." }, { WSA_INVALID_MESSAGE_INFORMATION_HEADER, WSMAN_STATUS_BAD_REQUEST, WSA_ACTION_FAULT, XML_NS_ADDRESSING, FAULT_SENDER_CODE, "InvalidMessageInformationHeader", "A message information header is not valid and the message cannot be processed." }, { WSMAN_INVALID_OPTIONS, WSMAN_STATUS_BAD_REQUEST, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_SENDER_CODE, "InvalidOptions", "One or more options are not valid." }, { WSMAN_INVALID_PARAMETER, WSMAN_STATUS_BAD_REQUEST, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_SENDER_CODE, "InvalidParameter", "An operation parameter is not valid." }, { WXF_INVALID_REPRESENTATION, WSMAN_STATUS_BAD_REQUEST, WSXF_ACTION_FAULT, XML_NS_TRANSFER, FAULT_SENDER_CODE, "InvalidRepresentation", "The XML content is not valid." }, { WSMAN_INVALID_SELECTORS, WSMAN_STATUS_BAD_REQUEST, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_SENDER_CODE, "InvalidSelectors", "The Selectors for the resource are not valid." }, { WSA_MESSAGE_INFORMATION_HEADER_REQUIRED, WSMAN_STATUS_BAD_REQUEST, WSA_ACTION_FAULT, XML_NS_ADDRESSING, FAULT_SENDER_CODE, "MessageInformationHeaderRequired", "A required header is missing." }, { WSMAN_NO_ACK, WSMAN_STATUS_BAD_REQUEST, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_SENDER_CODE, "NoAck", "The receiver did not acknowledge the event delivery." }, { WSMAN_QUOTA_LIMIT, WSMAN_STATUS_BAD_REQUEST, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_SENDER_CODE, "QuotaLimit", "The service is busy servicing other requests." }, { WSMAN_SCHEMA_VALIDATION_ERROR, WSMAN_STATUS_BAD_REQUEST, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_SENDER_CODE, "SchemaValidationError", "The supplied SOAP violates the corresponding XML schema definition." }, { WSEN_TIMED_OUT, WSMAN_STATUS_REQUEST_TIMEOUT, WSENUM_ACTION_FAULT, XML_NS_ENUMERATION, FAULT_RECEIVER_CODE, "TimedOut", "The enumerator has timed out and is no longer valid." }, { WSMAN_TIMED_OUT, WSMAN_STATUS_REQUEST_TIMEOUT, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_RECEIVER_CODE, "TimedOut", "The operation has timed out." }, { WSEN_UNSUPPORTED_EXPIRATION_TYPE, WSMAN_STATUS_BAD_REQUEST, WSENUM_ACTION_FAULT, XML_NS_ENUMERATION, FAULT_RECEIVER_CODE, "UnsupportedExpirationType", "The specified expiration type is not supported." }, { WSMAN_UNSUPPORTED_FEATURE, WSMAN_STATUS_BAD_REQUEST, WSMAN_ACTION_FAULT, XML_NS_WS_MAN, FAULT_SENDER_CODE, "UnsupportedFeature", "The specified feature is not supported." }, { WSMAN_UNSUPPORTED_FEATURE, WSMAN_STATUS_NOT_IMPLEMENTED, WSMAN_ACTION_FAULT, XML_NS_CIM_BINDING, FAULT_RECEIVER_CODE, "PolymorphismModeNotSupported", "The specified feature is not supported." }, { WSMAN_EVENT_DELIVER_TO_UNUSABLE, WSMAN_STATUS_BAD_REQUEST, WSMAN_ACTION_FAULT, XML_NS_CIM_BINDING, FAULT_RECEIVER_CODE, "DevliveryToUnusable", "The wse:NotifyTo address is not usable because it is incorrect" }, { WSMB_POLYMORPHISM_MODE_NOT_SUPPORTED, WSMAN_STATUS_NOT_IMPLEMENTED, WSMB_ACTION_FAULT, XML_NS_WS_MAN, FAULT_RECEIVER_CODE, "UnsupportedFeature", "The specified feature is not supported." }, { WSE_INVALID_EXPIRATION_TIME, WSMAN_STATUS_BAD_REQUEST, WSEVENT_ACTION_FAULT, XML_NS_EVENTING, FAULT_SENDER_CODE, "InvalidExpirationTime", "The expiration time is invalid" }, { WSE_DELIVERY_MODE_REQUESTED_UNAVAILABLE, WSMAN_STATUS_BAD_REQUEST, WSEVENT_ACTION_FAULT, XML_NS_EVENTING, FAULT_SENDER_CODE, "DeliveryModeRequestedUnavailable", "The requested delivery mode is not supported" }, { WSE_FILTERING_NOT_SUPPORTED, WSMAN_STATUS_BAD_REQUEST, WSEVENT_ACTION_FAULT, XML_NS_EVENTING, FAULT_SENDER_CODE, "FilteringNotSupported", "Filtering over the event source is not supported" }, { WSE_INVALID_MESSAGE, WSMAN_STATUS_BAD_REQUEST, WSEVENT_ACTION_FAULT, XML_NS_EVENTING, FAULT_SENDER_CODE, "InvalidMessage", "The request message has unknown or invalid content and cannot be processed." }, { WSMAN_UNKNOWN, WSMAN_STATUS_NOT_FOUND, NULL, NULL, NULL, NULL, NULL } }; void wsman_set_fault( WsmanMessage *msg, WsmanFaultCodeType fault_code, WsmanFaultDetailType fault_detail_code, const char *details) { if (!wsman_fault_occured(msg)) { msg->status.fault_code = fault_code; msg->status.fault_detail_code = fault_detail_code; if (details) msg->status.fault_msg = strdup(details); } return; } int wsman_is_fault_envelope( WsXmlDocH doc ) { WsXmlNodeH node = ws_xml_get_child(ws_xml_get_soap_body(doc), 0 , XML_NS_SOAP_1_2 , SOAP_FAULT); if ( node != NULL ) return 1; else return 0; } WsmanKnownStatusCode wsman_find_httpcode_for_value( WsXmlDocH doc ) { WsmanKnownStatusCode httpcode = 200; char *xp = ws_xml_get_xpath_value(doc, FAULT_XPATH_EXPR ); if (xp != NULL) { if (strcmp(xp, FAULT_RECEIVER_CODE_NS) == 0 ) httpcode = WSMAN_STATUS_INTERNAL_SERVER_ERROR; else if (strcmp(xp, FAULT_SENDER_CODE_NS) == 0 ) httpcode = WSMAN_STATUS_BAD_REQUEST; } u_free(xp); return httpcode; } WsmanKnownStatusCode wsman_find_httpcode_for_fault_code( WsmanFaultCodeType faultCode ) { int i; WsmanKnownStatusCode httpcode = WSMAN_STATUS_INTERNAL_SERVER_ERROR; int nfaults = sizeof (fault_code_table) / sizeof (fault_code_table[0]); for (i = 0; i < nfaults; i++) { if (fault_code_table[i].fault_code == faultCode ) { httpcode = fault_code_table[i].http_code; break; } } return httpcode; } WsXmlDocH wsman_generate_fault( WsXmlDocH in_doc, WsmanFaultCodeType faultCode, WsmanFaultDetailType faultDetail, char *fault_msg) { int i; WsXmlDocH fault = NULL; char *reason, *detail; int nfaults = sizeof (fault_code_table) / sizeof (fault_code_table[0]); for (i = 0; i < nfaults; i++) { if (fault_code_table[i].fault_code == faultCode ) { if (fault_msg!= NULL ) { reason = fault_msg; } else { reason = fault_code_table[i].reason; } if (faultDetail>0) { detail = fault_detail_table[faultDetail].detail; } else detail = NULL; fault = wsman_create_fault_envelope( in_doc, fault_code_table[i].code, fault_code_table[i].subCodeNs, fault_code_table[i].subCode, fault_code_table[i].fault_action, NULL, reason, detail); break; } } return fault; } void wsman_generate_fault_buffer ( WsXmlDocH in_doc, const char *encoding, WsmanFaultCodeType faultCode, WsmanFaultDetailType faultDetail, char * fault_msg, char **buf, int* len) { WsXmlDocH doc = wsman_generate_fault( in_doc, faultCode, faultDetail, fault_msg); debug( "Fault Code: %d", faultCode); ws_xml_dump_memory_enc(doc, buf, len, encoding); ws_xml_destroy_doc(doc); return; } int wsman_fault_occured(WsmanMessage *msg) { return (msg->status.fault_code == WSMAN_RC_OK ) ? 0 : 1; } void wsman_get_fault_status_from_doc (WsXmlDocH doc, WsmanStatus *status) { int i; char *subcode_value = ws_xml_get_xpath_value(doc, FAULT_SUBCODE_VALUE_XPATH); char *subcode_value_msg; char *start_pos; if (strlen(subcode_value) == 0) return; subcode_value_msg = calloc(1, strlen(subcode_value)); if (subcode_value_msg == NULL) { error("Out of memory"); status->fault_code = WSMAN_INTERNAL_ERROR; /* some default values */ status->fault_detail_code = OWSMAN_SYSTEM_ERROR; status->fault_msg = NULL; return; } start_pos = strchr(subcode_value, ':'); if (start_pos != NULL) { strcpy(subcode_value_msg, start_pos+1); int nfaults = sizeof (fault_code_table) / sizeof (fault_code_table[0]); for (i = 0; i < nfaults; i++) { if (strcmp (subcode_value_msg , fault_code_table[i].subCode) == 0) { status->fault_code = fault_code_table[i].fault_code; /* some default values */ status->fault_detail_code = 0; status->fault_msg = NULL; free(subcode_value_msg); return; } } } free(subcode_value_msg); return; }