blob: 108c458e22337cc809cc2df0b0b87cc2023edc18 [file] [log] [blame]
/*******************************************************************************
* 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 <wsman_config.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <u/libu.h>
#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 (!subcode_value || 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;
}