blob: 4fea28f887ccf04840085cbf0f589bbc1ba4b491 [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,cl
* 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 NEGLIGclE 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 <stdbool.h>
#include "u/libu.h"
#include "wsman-xml-api.h"
#include "wsman-soap.h"
#include "wsman-dispatcher.h"
#include "wsman-soap-envelope.h"
#include "wsman-xml.h"
#include "wsman-xml-serialize.h"
#include "wsman-filter.h"
#include "wsman-client-transport.h"
#include "wsman-faults.h"
#include "wsman-client.h"
void
wsmc_set_dumpfile( WsManClient *cl, FILE *f )
{
if (f)
cl->dumpfile = f;
return;
}
FILE *
wsmc_get_dumpfile(WsManClient *cl)
{
return cl->dumpfile;
}
#ifndef _WIN32
void
wsmc_set_conffile(WsManClient *cl, char *f )
{
u_free(cl->client_config_file);
cl->client_config_file = (f != NULL) ? u_strdup(f): NULL;
}
char *
wsmc_get_conffile(WsManClient *cl)
{
return cl->client_config_file;
}
#endif
static char*
wsman_make_action(const char *uri, const char *op_name)
{
if (uri && op_name) {
size_t len = strlen(uri) + strlen(op_name) + 2;
char *ptr = (char *)u_malloc(len);
if (ptr) {
int ret = snprintf(ptr, len, "%s/%s", uri, op_name);
if (ret < 0 || ret >= len) {
error("Error: formating action");
u_free(ptr);
return NULL;
}
return ptr;
}
}
return NULL;
}
/*
* find key in property list
* callback for list_find()
*/
static int
_list_key_compare(const void *node1, const void *key)
{
const char *key1 = ((key_value_t *)node1)->key;
const char *key2 = (const char *)key;
return strcmp(key1, key2);
}
static WsXmlDocH
wsmc_build_envelope(WsSerializerContextH serctx,
const char *action,
const char *reply_to_uri,
const char *resource_uri,
const char *to_uri,
client_opt_t *options)
{
WsXmlNodeH node;
char uuidBuf[100];
WsXmlNodeH header;
WsXmlDocH doc = ws_xml_create_envelope();
if (!doc) {
error("Error while creating envelope");
return NULL;
}
header = ws_xml_get_soap_header(doc);
if (header == NULL) {
return NULL;
}
generate_uuid(uuidBuf, sizeof(uuidBuf), 0);
if (reply_to_uri == NULL) {
reply_to_uri = WSA_TO_ANONYMOUS;
}
if (to_uri == NULL) {
to_uri = WSA_TO_ANONYMOUS;
}
if (action != NULL) {
ws_serialize_str(serctx, header,
(char *)action, XML_NS_ADDRESSING, WSA_ACTION, 1);
}
if (to_uri) {
ws_serialize_str(serctx, header, (char *)to_uri,
XML_NS_ADDRESSING, WSA_TO, 1);
}
if (resource_uri) {
ws_serialize_str(serctx, header, (char *)resource_uri,
XML_NS_WS_MAN, WSM_RESOURCE_URI, 1);
}
if (uuidBuf[0] != 0) {
ws_serialize_str(serctx, header, uuidBuf,
XML_NS_ADDRESSING, WSA_MESSAGE_ID, 1);
}
if (options->timeout) {
/* FIXME: see wsman-xml-serialize.c */
char buf[20];
int ret;
ret = snprintf(buf, sizeof(buf), "PT%u.%uS",
(unsigned int) options->timeout / 1000,
(unsigned int) options->timeout % 1000);
if (ret < 0 || ret >= sizeof(buf)) {
error("Error: formating time");
return NULL;
}
ws_serialize_str(serctx, header, buf,
XML_NS_WS_MAN, WSM_OPERATION_TIMEOUT, 0);
}
if (options->max_envelope_size) {
ws_serialize_uint32(serctx, header, options->max_envelope_size,
XML_NS_WS_MAN, WSM_MAX_ENVELOPE_SIZE,
options->flags & FLAG_MUND_MAX_ESIZE);
}
if (options->fragment) {
/* FIXME: mu set but unused
int mu = 0;
if ((options->flags & FLAG_MUND_FRAGMENT) ==
FLAG_MUND_FRAGMENT)
mu = 1;
*/
ws_serialize_str(serctx, header, options->fragment,
XML_NS_WS_MAN, WSM_FRAGMENT_TRANSFER,
1);
}
if (options->locale) {
node = ws_xml_add_child(header, XML_NS_WS_MAN, WSM_LOCALE, NULL);
ws_xml_set_node_lang(node, options->locale);
ws_xml_add_node_attr(node, XML_NS_SOAP_1_2, SOAP_MUST_UNDERSTAND, "false");
}
node = ws_xml_add_child(header, XML_NS_ADDRESSING, WSA_REPLY_TO, NULL);
if (node == NULL) {
return NULL;
}
ws_xml_add_child(node, XML_NS_ADDRESSING, WSA_ADDRESS, (char *)reply_to_uri);
/* Do not add the selectors to the header for reference instances */
if ((options->flags & FLAG_CIM_REFERENCES) != FLAG_CIM_REFERENCES) {
wsmc_add_selector_from_options(doc, options);
if (options->cim_ns) {
/* don't add CIM_NAMESPACE_SELECTOR twice */
if (options->selectors && list_count(options->selectors) > 0) {
if (!list_find(options->selectors, CIM_NAMESPACE_SELECTOR, _list_key_compare)) {
wsman_add_selector(header, CIM_NAMESPACE_SELECTOR, options->cim_ns);
}
}
else {
wsman_add_selector(header, CIM_NAMESPACE_SELECTOR, options->cim_ns);
}
}
}
return doc;
}
// Access to client elements
WS_LASTERR_Code
wsmc_get_last_error(WsManClient * cl)
{
return cl->last_error;
}
long
wsmc_get_response_code(WsManClient * cl)
{
return cl->response_code;
}
char*
wsmc_get_fault_string(WsManClient * cl)
{
return cl->fault_string;
}
WsSerializerContextH
wsmc_get_serialization_context(WsManClient * cl)
{
return cl->serctx;
}
char *
wsmc_get_hostname(WsManClient * cl)
{
return cl->data.hostname? u_strdup (cl->data.hostname) : NULL;
}
unsigned int
wsmc_get_port(WsManClient * cl)
{
return cl->data.port;
}
char *
wsmc_get_scheme(WsManClient * cl)
{
return cl->data.scheme ? u_strdup ( cl->data.scheme) : NULL;
}
char *
wsmc_get_path(WsManClient * cl)
{
return cl->data.path ? u_strdup( cl->data.path ) : NULL;
}
char *
wsmc_get_user(WsManClient * cl)
{
return cl->data.user ? u_strdup( cl->data.user ) : NULL;
}
char *
wsmc_get_encoding(WsManClient *cl)
{
return cl->content_encoding;
}
char *
wsmc_get_password(WsManClient * cl)
{
return cl->data.pwd ? u_strdup( cl->data.pwd ) : NULL;
}
char *
wsmc_get_endpoint(WsManClient * cl)
{
return cl->data.endpoint ? cl->data.endpoint : NULL;
}
WsXmlDocH
wsmc_read_file( const char *filename,
const char *encoding, unsigned long options)
{
return ws_xml_read_file( filename, encoding, options);
}
WsXmlDocH
wsmc_read_memory( char *buf,
size_t size, const char *encoding, unsigned long options)
{
return ws_xml_read_memory( buf, size, encoding, options);
}
client_opt_t *
wsmc_options_init(void)
{
client_opt_t *op = u_malloc(sizeof(client_opt_t));
if (op)
memset(op, 0, sizeof(client_opt_t));
else
return NULL;
return op;
}
/*
* Destroy list of key_value_t
*
*/
static void
_wsmc_kvl_destroy(list_t *kvl)
{
if (!kvl)
return;
while (!list_isempty(kvl)) {
lnode_t *node;
key_value_t *kv;
node = list_del_last(kvl);
if (!node)
break;
kv = (key_value_t *)node->list_data;
lnode_destroy(node);
key_value_destroy(kv, 0);
}
list_destroy(kvl);
}
void
wsmc_options_destroy(client_opt_t * op)
{
if (op->options) {
hash_free(op->options);
}
_wsmc_kvl_destroy(op->selectors);
_wsmc_kvl_destroy(op->properties);
u_free(op->fragment);
u_free(op->cim_ns);
u_free(op->delivery_uri);
u_free(op->reference);
u_free(op);
return;
}
void
wsmc_set_action_option(client_opt_t * options, unsigned int flag)
{
options->flags |= flag;
return;
}
unsigned int
wsmc_get_action_option(client_opt_t * options)
{
return options->flags;
}
void
wsmc_clear_action_option(client_opt_t * options, unsigned int flag)
{
options->flags &= ~flag;
return;
}
/*
* (static function)
* Add key/value to list_t (e.g. options->properties or ->selectors)
* either as char* (string set, epr == NULL)
* or as epr_t (string == NULL, epr set)
* if (useArray == true) then value will be added without duplicate key checking
*/
static void
_wsmc_add_key_value(list_t **list_ptr,
const char *key,
const char *string,
const epr_t *epr,
bool useArray)
{
key_value_t *kv;
list_t *list = *list_ptr;
lnode_t *lnode;
if ((string != NULL) && (epr != NULL)) {
error("Ambiguous call to add_key_value");
return;
}
if (key == NULL) {
error("Can't add_key_value with NULL key");
return;
}
if (list == NULL) {
list = list_create(LISTCOUNT_T_MAX);
if (list == NULL) {
error("list_create returned NULL");
return;
}
*list_ptr = list;
}
if (!useArray && list_find(list, key, _list_key_compare)) {
error("duplicate key not added to list");
return;
}
kv = key_value_create(key, string, epr, NULL);
if (!kv) {
error("No memory for key/value pair");
return;
}
lnode = lnode_create(kv);
if (!lnode) {
error("No memory for key/value node");
return;
}
list_append(list, lnode);
}
/*
* add a char* as an array type property (an array item)
*
*/
void
wsmc_add_property_array_item(client_opt_t * options,
const char *key,
const char *value)
{
_wsmc_add_key_value(&(options->properties), key, value, NULL, true);
}
/*
* add a char* as property
*
*/
void
wsmc_add_property(client_opt_t * options,
const char *key,
const char *value)
{
_wsmc_add_key_value(&(options->properties), key, value, NULL, false);
}
/*
* add an EndpointReference as property
*
*/
void
wsmc_add_property_epr(client_opt_t * options,
const char *key,
const epr_t *value)
{
_wsmc_add_key_value(&(options->properties), key, NULL, value, false);
}
/*
* add key/value pair to WSM_OPTION_SET
*
*/
void
wsmc_add_option(client_opt_t * options,
const char *key,
const char *value)
{
if (options->options == NULL) {
options->options = hash_create3(HASHCOUNT_T_MAX, 0, 0);
if (options->options == NULL) {
error("hash_create3 failed");
return;
}
}
if (!hash_lookup(options->options, key)) {
char *k = u_strdup(key);
char *v = u_strdup(value);
if (!hash_alloc_insert(options->options, k, v)) {
error( "hash_alloc_insert failed");
u_free(v);
u_free(k);
}
} else {
error( "duplicate not added to hash");
}
}
void
wsmc_add_selector(client_opt_t *options,
const char *key,
const char *value)
{
_wsmc_add_key_value(&(options->selectors), key, value, NULL, false);
}
void
wsmc_add_selector_epr(client_opt_t *options,
const char *key,
const epr_t *value)
{
_wsmc_add_key_value(&(options->selectors), key, NULL, value, false);
}
static void
_wsmc_add_uri_to_list(list_t **list_ptr, const char *query_string)
{
hash_t *query;
if (!query_string || !list_ptr)
return;
query = u_parse_query(query_string);
if (query) {
/* convert query hash to property list */
hscan_t hs;
hnode_t *hn;
list_t *list = *list_ptr;
_wsmc_kvl_destroy(list);
*list_ptr = NULL;
hash_scan_begin(&hs, query);
while ((hn = hash_scan_next(&hs))) {
_wsmc_add_key_value(list_ptr,
(char *)hnode_getkey(hn),
(char *)hnode_get(hn),
NULL, false);
}
hash_free(query);
}
}
void
wsmc_add_selectors_from_str(client_opt_t * options,
const char *query_string)
{
_wsmc_add_uri_to_list(&(options->selectors), query_string);
}
void
wsmc_add_prop_from_str(client_opt_t * options,
const char *query_string)
{
_wsmc_add_uri_to_list(&(options->properties), query_string);
}
void
wsmc_add_selector_from_options(WsXmlDocH doc, client_opt_t *options)
{
WsXmlNodeH header;
lnode_t *node;
if (!options->selectors || list_count(options->selectors) == 0)
return;
header = ws_xml_get_soap_header(doc);
if (header == NULL) {
return;
}
node = list_first(options->selectors);
while (node) {
key_value_t *kv;
kv = (key_value_t *)node->list_data;
if (kv->type == 0) {
wsman_add_selector(header, kv->key, kv->v.text);
}
else {
wsman_add_selector_epr(header, kv->key, kv->v.epr);
}
node = list_next(options->selectors, node);
}
}
void
wsmc_set_selectors_from_uri(const char *resource_uri, client_opt_t * options)
{
if (options->selectors) {
list_destroy_nodes(options->selectors);
list_destroy(options->selectors);
options->selectors = NULL;
}
u_uri_t *uri = u_malloc(sizeof(u_uri_t));
u_uri_parse(resource_uri, &uri);
wsmc_add_selectors_from_str(options, uri->query);
u_uri_free(uri);
}
/* Err: should be wsmc_set_selectors_from_uri() */
void
wsmc_set_options_from_uri(const char *resource_uri, client_opt_t * options)
{
error("Call to deprecated 'wsmc_set_options_from_uri', use 'wsmc_set_selectors_from_uri' instead");
wsmc_set_selectors_from_uri(resource_uri, options);
}
void
wsmc_set_delivery_uri(const char *delivery_uri, client_opt_t * options)
{
u_free(options->delivery_uri);
options->delivery_uri = delivery_uri ? u_strdup(delivery_uri) : NULL;
}
void
wsmc_set_cim_ns(const char *ns, client_opt_t * options)
{
u_free(options->cim_ns);
options->cim_ns = ns ? u_strdup(ns) : NULL;
}
void
wsmc_set_fragment(const char *fragment, client_opt_t * options)
{
u_free(options->fragment);
options->fragment = fragment ? u_strdup(fragment) : NULL;
}
void
wsmc_set_reference(const char *reference, client_opt_t * options)
{
u_free(options->reference);
options->reference = reference ? u_strdup(reference) : NULL;
}
void
wsmc_set_sub_expiry(int event_subscription_expire, client_opt_t * options)
{
options->expires = event_subscription_expire;
}
void
wsmc_set_heartbeat_interval(int heartbeat_interval, client_opt_t * options)
{
options->heartbeat_interval = heartbeat_interval;
}
void
wsmc_set_delivery_mode(WsmanDeliveryMode delivery_mode, client_opt_t * options)
{
options->delivery_mode = delivery_mode;
}
void
wsmc_set_delivery_security_mode(WsManDeliverySecurityMode delivery_sec_mode, client_opt_t * options)
{
options->delivery_sec_mode = delivery_sec_mode;
}
void
wsmc_set_locale(client_opt_t * options, const char *locale)
{
u_free(options->locale);
options->locale = locale ? u_strdup(locale) : NULL;
}
char *
wsmc_get_locale(client_opt_t * options)
{
return options->locale;
}
void
wsmc_add_selector_from_uri(WsXmlDocH doc,
const char *resource_uri)
{
u_uri_t *uri = NULL;
WsXmlNodeH header = ws_xml_get_soap_header(doc);
hash_t *query;
hnode_t *hn;
hscan_t hs;
if (header == NULL) {
return;
}
if (resource_uri == NULL) {
return;
}
if (u_uri_parse((const char *) resource_uri, &uri) != 0) {
return;
} else if (!uri->query) {
goto cleanup;
}
query = u_parse_query(uri->query);
if (query == NULL) {
goto cleanup;
}
hash_scan_begin(&hs, query);
while ((hn = hash_scan_next(&hs))) {
wsman_add_selector(header,
(char *) hnode_getkey(hn),
(char *) hnode_get(hn));
debug("key=%s value=%s", (char *) hnode_getkey(hn),
(char *) hnode_get(hn));
}
hash_free_nodes(query);
hash_destroy(query);
cleanup:
if (uri) {
u_uri_free(uri);
}
}
static char*
wsmc_create_action_str(WsmanAction action)
{
char *action_str = NULL;
switch (action) {
case WSMAN_ACTION_ASSOCIATORS:
case WSMAN_ACTION_REFERENCES:
case WSMAN_ACTION_ENUMERATION:
action_str = wsman_make_action(XML_NS_ENUMERATION, WSENUM_ENUMERATE);
break;
case WSMAN_ACTION_PULL:
action_str = wsman_make_action(XML_NS_ENUMERATION, WSENUM_PULL);
break;
case WSMAN_ACTION_RELEASE:
action_str = wsman_make_action(XML_NS_ENUMERATION, WSENUM_RELEASE);
break;
case WSMAN_ACTION_TRANSFER_CREATE:
action_str = wsman_make_action(XML_NS_TRANSFER, TRANSFER_CREATE);
break;
case WSMAN_ACTION_TRANSFER_DELETE:
action_str = wsman_make_action(XML_NS_TRANSFER, TRANSFER_DELETE);
break;
case WSMAN_ACTION_TRANSFER_GET:
action_str = wsman_make_action(XML_NS_TRANSFER, TRANSFER_GET);
break;
case WSMAN_ACTION_TRANSFER_PUT:
action_str = wsman_make_action(XML_NS_TRANSFER, TRANSFER_PUT);
break;
case WSMAN_ACTION_SUBSCRIBE:
action_str = wsman_make_action(XML_NS_EVENTING, WSEVENT_SUBSCRIBE);
break;
case WSMAN_ACTION_UNSUBSCRIBE:
action_str = wsman_make_action(XML_NS_EVENTING, WSEVENT_UNSUBSCRIBE);
break;
case WSMAN_ACTION_RENEW:
action_str = wsman_make_action(XML_NS_EVENTING, WSEVENT_RENEW);
break;
case WSMAN_ACTION_NONE:
case WSMAN_ACTION_IDENTIFY:
case WSMAN_ACTION_ANON_IDENTIFY:
case WSMAN_ACTION_TEST:
case WSMAN_ACTION_CUSTOM:
break;
}
return action_str;
}
static char *
wsmc_create_delivery_mode_str(WsmanDeliveryMode mode)
{
char * str = NULL;
switch(mode) {
case WSMAN_DELIVERY_PUSH:
str = u_strdup(WSEVENT_DELIVERY_MODE_PUSH);
break;
case WSMAN_DELIVERY_PUSHWITHACK:
str = u_strdup(WSEVENT_DELIVERY_MODE_PUSHWITHACK);
break;
case WSMAN_DELIVERY_EVENTS:
str = u_strdup(WSEVENT_DELIVERY_MODE_EVENTS);
break;
case WSMAN_DELIVERY_PULL:
str = u_strdup(WSEVENT_DELIVERY_MODE_PULL);
}
return str;
}
static char *
wsmc_create_delivery_sec_mode_str(WsManDeliverySecurityMode mode)
{
char * str = NULL;
switch(mode) {
case WSMAN_DELIVERY_SEC_HTTP_BASIC:
str = u_strdup(WSMAN_SECURITY_PROFILE_HTTP_BASIC);
break;
case WSMAN_DELIVERY_SEC_HTTP_DIGEST:
str = u_strdup(WSMAN_SECURITY_PROFILE_HTTP_DIGEST);
break;
case WSMAN_DELIVERY_SEC_HTTPS_BASIC:
str = u_strdup(WSMAN_SECURITY_PROFILE_HTTPS_BASIC);
break;
case WSMAN_DELIVERY_SEC_HTTPS_DIGEST:
str = u_strdup(WSMAN_SECURITY_PROFILE_HTTPS_DIGEST);
break;
case WSMAN_DELIVERY_SEC_HTTPS_MUTUAL:
str = u_strdup(WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL);
break;
case WSMAN_DELIVERY_SEC_HTTPS_MUTUAL_BASIC:
str = u_strdup(WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL_BASIC);
break;
case WSMAN_DELIVERY_SEC_HTTPS_MUTUAL_DIGEST:
str = u_strdup(WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL_DIGEST);
break;
case WSMAN_DELIVERY_SEC_HTTPS_SPNEGO_KERBEROS:
str = u_strdup(WSMAN_SECURITY_PROFILE_HTTPS_SPNEGO_KERBEROS);
break;
case WSMAN_DELIVERY_SEC_HTTPS_MUTUAL_SPNEGO_KERBEROS:
str = u_strdup(WSMAN_SECURITY_PROFILE_HTTPS_MUTUAL_SPNEGO_KERBEROS);
break;
case WSMAN_DELIVERY_SEC_HTTP_SPNEGO_KERBEROS:
str = u_strdup(WSMAN_SECURITY_PROFILE_HTTP_SPNEGO_KERBEROS);
break;
default:
break;
}
return str;
}
static void
wsman_set_enumeration_options(WsManClient * cl, WsXmlNodeH body, const char* resource_uri,
client_opt_t *options, filter_t *filter)
{
WsXmlNodeH node = ws_xml_get_child(body, 0, NULL, NULL);
if (node == NULL) {
return;
}
if ((options->flags & FLAG_ENUMERATION_OPTIMIZATION) ==
FLAG_ENUMERATION_OPTIMIZATION) {
ws_xml_add_child(node, XML_NS_WS_MAN, WSM_OPTIMIZE_ENUM, NULL);
}
if ((options->flags & FLAG_ENUMERATION_ENUM_EPR) ==
FLAG_ENUMERATION_ENUM_EPR) {
ws_xml_add_child(node, XML_NS_WS_MAN, WSM_ENUM_MODE, WSM_ENUM_EPR);
} else if ((options->flags & FLAG_ENUMERATION_ENUM_OBJ_AND_EPR) ==
FLAG_ENUMERATION_ENUM_OBJ_AND_EPR) {
ws_xml_add_child(node, XML_NS_WS_MAN, WSM_ENUM_MODE,
WSM_ENUM_OBJ_AND_EPR);
}
// Polymorphism
if ((options->flags & FLAG_IncludeSubClassProperties)
== FLAG_IncludeSubClassProperties) {
ws_xml_add_child(node, XML_NS_CIM_BINDING,
WSMB_POLYMORPHISM_MODE, WSMB_INCLUDE_SUBCLASS_PROP);
} else if ((options->flags & FLAG_ExcludeSubClassProperties) ==
FLAG_ExcludeSubClassProperties) {
ws_xml_add_child(node, XML_NS_CIM_BINDING,
WSMB_POLYMORPHISM_MODE, WSMB_EXCLUDE_SUBCLASS_PROP);
} else if ((options->flags & FLAG_POLYMORPHISM_NONE)
== FLAG_POLYMORPHISM_NONE) {
ws_xml_add_child(node, XML_NS_CIM_BINDING,
WSMB_POLYMORPHISM_MODE, "None");
}
if (filter != NULL) {
filter_serialize(node, filter, XML_NS_WS_MAN);
}
return;
}
static void
wsman_set_subscribe_options(WsManClient * cl,
WsXmlDocH request,
const char* resource_uri,
client_opt_t *options,
filter_t *filter)
{
WsXmlNodeH body = ws_xml_get_soap_body(request);
WsXmlNodeH header = ws_xml_get_soap_header(request);
WsXmlNodeH node = NULL, temp = NULL, node2 = NULL, node3 = NULL;
char buf[32];
if (header == NULL || body == NULL) {
return;
}
if(options->delivery_certificatethumbprint ||options->delivery_password ||
options->delivery_password) {
node = ws_xml_add_child(header, XML_NS_TRUST, WST_ISSUEDTOKENS, NULL);
if (node == NULL) {
return;
}
ws_xml_add_node_attr(node, XML_NS_SOAP_1_2, SOAP_MUST_UNDERSTAND, "true");
if(options->delivery_certificatethumbprint) {
if (node == NULL) {
return;
}
node2 = ws_xml_add_child(node, XML_NS_TRUST, WST_REQUESTSECURITYTOKENRESPONSE, NULL);
if (node2 == NULL) {
return;
}
ws_xml_add_child(node2, XML_NS_TRUST, WST_TOKENTYPE,WST_CERTIFICATETHUMBPRINT );
node3 = ws_xml_add_child(node2, XML_NS_TRUST, WST_REQUESTEDSECURITYTOKEN, NULL);
if (node3 == NULL) {
return;
}
ws_xml_add_child(node3, XML_NS_WS_MAN, WSM_CERTIFICATETHUMBPRINT,
options->delivery_certificatethumbprint);
node3 = ws_xml_add_child(node2, XML_NS_POLICY, WSP_APPLIESTO, NULL);
if (node3 == NULL) {
return;
}
node3 = ws_xml_add_child(node3, XML_NS_ADDRESSING, WSA_EPR, NULL);
if (node3 == NULL) {
return;
}
ws_xml_add_child(node3, XML_NS_ADDRESSING, WSA_ADDRESS, options->delivery_uri);
}
if(options->delivery_username || options->delivery_password) {
node2 = ws_xml_add_child(node, XML_NS_TRUST, WST_REQUESTSECURITYTOKENRESPONSE, NULL);
if (node2 == NULL) {
return;
}
ws_xml_add_child(node2, XML_NS_TRUST, WST_TOKENTYPE,WST_USERNAMETOKEN);
node3 = ws_xml_add_child(node2, XML_NS_TRUST, WST_REQUESTEDSECURITYTOKEN, NULL);
if (node3 == NULL) {
return;
}
node3 = ws_xml_add_child(node3, XML_NS_SE, WSSE_USERNAMETOKEN, NULL);
if (options->delivery_username) {
if (node3 == NULL) {
return;
}
ws_xml_add_child(node3, XML_NS_SE, WSSE_USERNAME, options->delivery_username);
}
if (options->delivery_password) {
if (node3 == NULL) {
return;
}
ws_xml_add_child(node3, XML_NS_SE, WSSE_PASSWORD, options->delivery_password);
}
node3 = ws_xml_add_child(node2, XML_NS_POLICY, WSP_APPLIESTO, NULL);
if (node3 == NULL) {
return;
}
node3 = ws_xml_add_child(node3, XML_NS_ADDRESSING, WSA_EPR, NULL);
if (node3 == NULL) {
return;
}
ws_xml_add_child(node3, XML_NS_ADDRESSING, WSA_ADDRESS, options->delivery_uri);
}
}
node = ws_xml_add_child(body,
XML_NS_EVENTING, WSEVENT_SUBSCRIBE,NULL);
if (node == NULL) {
return;
}
temp = ws_xml_add_child(node, XML_NS_EVENTING, WSEVENT_DELIVERY, NULL);
if(temp) {
char *mode = wsmc_create_delivery_mode_str(options->delivery_mode);
ws_xml_add_node_attr(temp, NULL, WSEVENT_DELIVERY_MODE, mode);
u_free(mode);
if(options->delivery_uri) {
node2 = ws_xml_add_child(temp, XML_NS_EVENTING, WSEVENT_NOTIFY_TO, NULL);
if (node2 == NULL) {
return;
}
ws_xml_add_child(node2, XML_NS_ADDRESSING, WSA_ADDRESS, options->delivery_uri);
}
if(options->delivery_sec_mode) {
temp = ws_xml_add_child(temp, XML_NS_WS_MAN, WSM_AUTH, NULL);
if (temp == NULL) {
return;
}
char *mode = wsmc_create_delivery_sec_mode_str(options->delivery_sec_mode);
ws_xml_add_node_attr(temp, NULL, WSM_PROFILE, mode);
u_free(mode);
}
if(options->heartbeat_interval) {
snprintf(buf, 32, "PT%fS", options->heartbeat_interval);
ws_xml_add_child(temp, XML_NS_WS_MAN, WSM_HEARTBEATS, buf);
}
if(options->reference) {
WsXmlDocH doc = ws_xml_read_memory( options->reference, strlen(options->reference), "UTF-8", 0);
node3 = ws_xml_get_doc_root(doc);
temp = ws_xml_add_child(node2, XML_NS_ADDRESSING, WSA_REFERENCE_PROPERTIES, NULL);
if(temp)
ws_xml_duplicate_tree(temp, node3);
}
}
if (options->expires) {
snprintf(buf, 32, "PT%fS", options->expires);
ws_xml_add_child(node, XML_NS_EVENTING, WSEVENT_EXPIRES, buf);
}
if (filter) {
filter_serialize(node, filter, XML_NS_WS_MAN);
}
if (options->flags & FLAG_EVENT_SENDBOOKMARK) {
ws_xml_add_child(node, XML_NS_WS_MAN, WSM_SENDBOOKMARKS, NULL);
}
}
static void
wsmc_set_put_prop(WsXmlDocH get_response,
WsXmlDocH put_request,
client_opt_t *options)
{
WsXmlNodeH resource_node;
char *ns_uri;
WsXmlNodeH get_body = ws_xml_get_soap_body(get_response);
WsXmlNodeH put_body = ws_xml_get_soap_body(put_request);
ws_xml_copy_node(ws_xml_get_child(get_body, 0, NULL, NULL), put_body);
resource_node = ws_xml_get_child(put_body, 0, NULL, NULL);
ns_uri = ws_xml_get_node_name_ns_uri(resource_node);
if (!list_isempty(options->properties)) {
lnode_t *node = list_first(options->properties);
while (node) {
key_value_t *property = (key_value_t *)node->list_data;
WsXmlNodeH n = ws_xml_get_child(resource_node, 0, ns_uri, property->key);
if (n != NULL) {
if (property->type == 0) {
ws_xml_set_node_text(n, property->v.text);
}
else {
epr_serialize(n, ns_uri, property->key, property->v.epr, 1);
}
}
node = list_next(options->properties, node);
}
}
}
void
wsmc_node_to_buf(WsXmlNodeH node, char **buf) {
int len;
WsXmlDocH doc = ws_xml_create_doc_by_import( node);
ws_xml_dump_memory_enc(doc, buf, &len, "UTF-8");
ws_xml_destroy_doc(doc);
return;
}
char*
wsmc_node_to_formatbuf(WsXmlNodeH node) {
char *buf;
int len;
WsXmlDocH doc = ws_xml_create_doc_by_import( node);
ws_xml_dump_memory_node_tree(ws_xml_get_doc_root(doc), &buf, &len);
ws_xml_destroy_doc(doc);
return buf;
}
static void
add_subscription_context(WsXmlNodeH node, char *context)
{
WsXmlNodeH subsnode;
WsXmlDocH doc = ws_xml_read_memory(context, strlen(context), "UTF-8", 0);
if(doc == NULL) return;
subsnode = ws_xml_get_doc_root(doc);
ws_xml_duplicate_children(node, subsnode);
}
WsXmlDocH
wsmc_create_request(WsManClient * cl, const char *resource_uri,
client_opt_t *options, filter_t *filter,
WsmanAction action, char *method, void *data)
{
WsXmlDocH request;
WsXmlNodeH body;
WsXmlNodeH header;
WsXmlNodeH node;
char *_action = NULL;
if (action == WSMAN_ACTION_IDENTIFY) {
request = ws_xml_create_envelope();
} else {
if (method) {
/* WSA_ACTION is a URI */
if (strchr(method, '/'))
_action = u_strdup(method);
else /* 'invoke' action */
_action = wsman_make_action((char *)resource_uri, method);
} else {
_action = wsmc_create_action_str(action);
}
if (options && _action) {
request = wsmc_build_envelope(cl->serctx, _action,
WSA_TO_ANONYMOUS, (char *)resource_uri,
cl->data.endpoint, options);
} else {
u_free(_action);
return NULL;
}
u_free(_action);
}
body = ws_xml_get_soap_body(request);
header = ws_xml_get_soap_header(request);
if (!body || !header )
return NULL;
/*
* flags to be passed as <w:OptionSet ...> <w:Option Name="..." ...> >
*/
if (options) {
WsXmlNodeH opset = NULL;
if (options->flags & (FLAG_CIM_EXTENSIONS|FLAG_EXCLUDE_NIL_PROPS)) {
/* need WSM_OPTION_SET */
opset = ws_xml_add_child(header,
XML_NS_WS_MAN, WSM_OPTION_SET, NULL);
if (opset == NULL) {
return NULL;
}
if ((options->flags & FLAG_CIM_EXTENSIONS) == FLAG_CIM_EXTENSIONS) {
WsXmlNodeH op = ws_xml_add_child(opset,
XML_NS_WS_MAN, WSM_OPTION, NULL);
ws_xml_add_node_attr(op, NULL, WSM_NAME, WSMB_SHOW_EXTENSION);
}
if ((options->flags & FLAG_EXCLUDE_NIL_PROPS) == FLAG_EXCLUDE_NIL_PROPS) {
/* ExcludeNilProperties is non-standard, so put it under an openwsman namespace */
WsXmlNodeH op = ws_xml_add_child(opset,
XML_NS_OPENWSMAN, WSM_OPTION, NULL);
ws_xml_add_node_attr(op, NULL, WSM_NAME, WSMB_EXCLUDE_NIL_PROPS);
}
}
if (options->options && hash_count(options->options) > 0) {
hnode_t *hn;
hscan_t hs;
hash_scan_begin(&hs, options->options);
if (!opset) {
opset = ws_xml_add_child(header,
XML_NS_WS_MAN, WSM_OPTION_SET, NULL);
}
while ((hn = hash_scan_next(&hs))) {
if (opset == NULL) {
return NULL;
}
WsXmlNodeH op = ws_xml_add_child(opset,
XML_NS_WS_MAN, WSM_OPTION, NULL);
ws_xml_add_node_attr(op, NULL, WSM_NAME, (char *) hnode_getkey(hn));
ws_xml_set_node_text(op, (char *) hnode_get(hn));
}
}
}
switch (action) {
case WSMAN_ACTION_IDENTIFY:
case WSMAN_ACTION_ANON_IDENTIFY:
ws_xml_add_child(body,
XML_NS_WSMAN_ID, WSMID_IDENTIFY, NULL);
break;
case WSMAN_ACTION_CUSTOM:
break;
case WSMAN_ACTION_ENUMERATION:
case WSMAN_ACTION_ASSOCIATORS:
case WSMAN_ACTION_REFERENCES:
node = ws_xml_add_child(body,
XML_NS_ENUMERATION, WSENUM_ENUMERATE, NULL);
if (options) {
wsman_set_enumeration_options(cl, body, resource_uri, options, filter);
}
break;
case WSMAN_ACTION_PULL:
node = ws_xml_add_child(body,
XML_NS_ENUMERATION, WSENUM_PULL, NULL);
if (node == NULL) {
return NULL;
}
if (data) {
ws_xml_add_child(node, XML_NS_ENUMERATION,
WSENUM_ENUMERATION_CONTEXT, (char *) data);
}
break;
case WSMAN_ACTION_RELEASE:
node = ws_xml_add_child(body,
XML_NS_ENUMERATION, WSENUM_RELEASE, NULL);
if (node == NULL) {
return NULL;
}
if (data) {
ws_xml_add_child(node, XML_NS_ENUMERATION,
WSENUM_ENUMERATION_CONTEXT, (char *) data);
}
break;
case WSMAN_ACTION_SUBSCRIBE:
if (options) {
wsman_set_subscribe_options(cl, request, resource_uri, options, filter);
}
break;
case WSMAN_ACTION_UNSUBSCRIBE:
node = ws_xml_add_child(body,
XML_NS_EVENTING, WSEVENT_UNSUBSCRIBE,NULL);
if(data) {
if(((char *)data)[0] != 0)
add_subscription_context(ws_xml_get_soap_header(request), (char *)data);
}
break;
case WSMAN_ACTION_RENEW:
{
char buf[20];
node = ws_xml_add_child(body,
XML_NS_EVENTING, WSEVENT_RENEW, NULL);
if (node == NULL) {
return NULL;
}
/* %f default precision is 6 -> [-]ddd.ddd */
snprintf(buf, 20, "PT%fS", (options) ? options->expires : 0);
ws_xml_add_child(node, XML_NS_EVENTING, WSEVENT_EXPIRES, buf);
if(data) {
if(((char *)data)[0] != 0)
add_subscription_context(ws_xml_get_soap_header(request), (char *)data);
}
}
break;
case WSMAN_ACTION_NONE:
case WSMAN_ACTION_TRANSFER_CREATE:
case WSMAN_ACTION_TEST:
case WSMAN_ACTION_TRANSFER_GET:
case WSMAN_ACTION_TRANSFER_PUT:
case WSMAN_ACTION_TRANSFER_DELETE:
break;
}
if (action == WSMAN_ACTION_PULL || action == WSMAN_ACTION_ENUMERATION) {
if (options && options->max_elements > 0 ) {
node = ws_xml_get_child(body, 0, NULL, NULL);
if (action == WSMAN_ACTION_ENUMERATION) {
if ((options->flags & FLAG_ENUMERATION_OPTIMIZATION) ==
FLAG_ENUMERATION_OPTIMIZATION ) {
if (node == NULL) {
return NULL;
}
/* wsman:MaxElements is for Enumerate */
ws_xml_add_child_format(node, XML_NS_WS_MAN,
WSENUM_MAX_ELEMENTS, "%d", options->max_elements);
}
} else {
if (node == NULL) {
return NULL;
}
/* wsen:MaxElements is for Pull */
ws_xml_add_child_format(node, XML_NS_ENUMERATION,
WSENUM_MAX_ELEMENTS, "%d", options->max_elements);
}
}
if (options && (options->flags & FLAG_ENUMERATION_COUNT_ESTIMATION) ==
FLAG_ENUMERATION_COUNT_ESTIMATION) {
ws_xml_add_child(header, XML_NS_WS_MAN, WSM_REQUEST_TOTAL, NULL);
}
}
if (action != WSMAN_ACTION_TRANSFER_CREATE &&
action != WSMAN_ACTION_TRANSFER_PUT &&
action != WSMAN_ACTION_CUSTOM) {
if (options && (options->flags & FLAG_DUMP_REQUEST) == FLAG_DUMP_REQUEST) {
ws_xml_dump_node_tree(cl->dumpfile, ws_xml_get_doc_root(request));
}
}
return request;
}
static void
handle_resource_request(WsManClient * cl, WsXmlDocH request,
void *data,
void *typeInfo,
char *resource_uri)
{
if (data && typeInfo) {
char *class = u_strdup(strrchr(resource_uri, '/') + 1);
ws_serialize(cl->serctx, ws_xml_get_soap_body(request),
data, (XmlSerializerInfo *) typeInfo,
class, resource_uri, NULL, 1);
ws_serializer_free_mem(cl->serctx, data,
(XmlSerializerInfo *) typeInfo);
u_free(class);
} else if (data != NULL) {
if (wsman_is_valid_xml_envelope((WsXmlDocH) data)) {
WsXmlNodeH body = ws_xml_get_soap_body((WsXmlDocH) data);
ws_xml_duplicate_tree(ws_xml_get_soap_body(request),
ws_xml_get_child(body, 0, NULL, NULL));
} else {
ws_xml_duplicate_tree(ws_xml_get_soap_body(request),
ws_xml_get_doc_root((WsXmlDocH) data));
}
}
}
static WsXmlDocH
_wsmc_action_create(WsManClient * cl,
char *resource_uri,
void *data,
void *typeInfo,
client_opt_t *options)
{
WsXmlDocH response;
WsXmlDocH request = wsmc_create_request(cl, (char *)resource_uri, options, NULL,
WSMAN_ACTION_TRANSFER_CREATE, NULL, NULL);
if (!request)
return NULL;
handle_resource_request(cl, request, data, typeInfo, (char *)resource_uri);
if ((options->flags & FLAG_DUMP_REQUEST) == FLAG_DUMP_REQUEST) {
ws_xml_dump_node_tree(cl->dumpfile, ws_xml_get_doc_root(request));
}
if (wsman_send_request(cl, request)) {
ws_xml_destroy_doc(request);
return NULL;
}
response = wsmc_build_envelope_from_response(cl);
ws_xml_destroy_doc(request);
return response;
}
WsXmlDocH
wsmc_action_create(WsManClient * cl,
const char *resource_uri,
client_opt_t *options,
WsXmlDocH source_doc)
{
return _wsmc_action_create(cl, (char *)resource_uri,
source_doc, NULL, options);
}
WsXmlDocH
wsmc_action_create_fromtext(WsManClient * cl,
const char *resource_uri,
client_opt_t *options,
const char *data, size_t size, const char *encoding)
{
WsXmlDocH source_doc = wsmc_read_memory( (char *)data, size,
(char *)encoding, 0);
WsXmlDocH response;
if (source_doc == NULL) {
error("could not convert XML text to doc");
return NULL;
}
response = _wsmc_action_create(cl, (char *)resource_uri,
source_doc, NULL, options);
ws_xml_destroy_doc(source_doc);
return response;
}
WsXmlDocH
wsmc_action_create_serialized(WsManClient * cl,
const char *resource_uri,
client_opt_t *options,
void *data,
void *typeInfo)
{
return _wsmc_action_create(cl, (char *)resource_uri, data, typeInfo, options);
}
static WsXmlDocH
_wsmc_action_put(WsManClient * cl,
char *resource_uri,
void *data,
void *typeInfo,
client_opt_t *options)
{
WsXmlDocH response;
WsXmlDocH request = wsmc_create_request(cl, resource_uri, options, NULL,
WSMAN_ACTION_TRANSFER_PUT, NULL, NULL);
if (!request)
return NULL;
handle_resource_request(cl, request, data, typeInfo, resource_uri);
if ((options->flags & FLAG_DUMP_REQUEST) == FLAG_DUMP_REQUEST) {
ws_xml_dump_node_tree(cl->dumpfile, ws_xml_get_doc_root(request));
}
if (wsman_send_request(cl, request)) {
ws_xml_destroy_doc(request);
return NULL;
}
response = wsmc_build_envelope_from_response(cl);
ws_xml_destroy_doc(request);
return response;
}
WsXmlDocH
wsmc_action_put(WsManClient * cl,
const char *resource_uri,
client_opt_t *options,
WsXmlDocH source_doc)
{
return _wsmc_action_put(cl, (char *)resource_uri, source_doc, NULL, options);
}
WsXmlDocH
wsmc_action_put_fromtext(WsManClient * cl,
const char *resource_uri,
client_opt_t *options,
const char *data, size_t size, const char *encoding)
{
WsXmlDocH source_doc = wsmc_read_memory( (char *)data, size,
(char *)encoding, 0);
WsXmlDocH response;
if (source_doc == NULL) {
error("could not convert XML text to doc");
return NULL;
}
response = _wsmc_action_put(cl, (char *)resource_uri, source_doc, NULL, options);
ws_xml_destroy_doc(source_doc);
return response;
}
WsXmlDocH
wsmc_action_put_serialized(WsManClient * cl,
const char *resource_uri,
client_opt_t *options,
void *data,
void *typeInfo)
{
return _wsmc_action_put(cl, (char *)resource_uri, data, typeInfo, options);
}
WsXmlDocH
wsmc_action_delete(WsManClient * cl,
const char *resource_uri,
client_opt_t *options)
{
WsXmlDocH response;
WsXmlDocH request = wsmc_create_request(cl, resource_uri, options, NULL,
WSMAN_ACTION_TRANSFER_DELETE, NULL, NULL);
if (!request)
return NULL;
if (wsman_send_request(cl, request)) {
ws_xml_destroy_doc(request);
return NULL;
}
response = wsmc_build_envelope_from_response(cl);
ws_xml_destroy_doc(request);
return response;
}
static int add_selectors_from_epr(void *options, const key_value_t *kv)
{
client_opt_t *op = (client_opt_t *)options;
if (kv->type == 0)
wsmc_add_selector(op, kv->key, kv->v.text);
else
wsmc_add_selector_epr(op, kv->key, kv->v.epr);
return 0;
}
WsXmlDocH
wsmc_action_delete_from_epr(WsManClient *cl, epr_t *epr,
client_opt_t *options)
{
char *resource_uri = epr_get_resource_uri(epr);
wsman_epr_selector_cb(epr, add_selectors_from_epr, options);
return wsmc_action_delete(cl, resource_uri, options);
}
WsXmlDocH
wsmc_action_get_from_epr(WsManClient *cl, epr_t *epr,
client_opt_t *options)
{
char *resource_uri = epr_get_resource_uri(epr);
wsman_epr_selector_cb(epr, add_selectors_from_epr, options);
return wsmc_action_get(cl, resource_uri, options);
}
WsXmlDocH
wsmc_action_get(WsManClient * cl,
const char *resource_uri,
client_opt_t *options)
{
WsXmlDocH response;
WsXmlDocH request = wsmc_create_request(cl, resource_uri, options, NULL,
WSMAN_ACTION_TRANSFER_GET, NULL, NULL);
if (!request)
return NULL;
if (wsman_send_request(cl, request)) {
ws_xml_destroy_doc(request);
return NULL;
}
response = wsmc_build_envelope_from_response(cl);
ws_xml_destroy_doc(request);
return response;
}
WsXmlDocH
wsmc_action_get_and_put(WsManClient * cl,
const char *resource_uri,
client_opt_t *options)
{
WsXmlDocH put_request;
WsXmlDocH put_response;
WsXmlDocH get_response = wsmc_action_get(cl, resource_uri, options);
if (!get_response) {
error("wsmc_action_get returned NULL doc");
return NULL;
}
if (wsman_is_fault_envelope(get_response)) {
return get_response;
}
put_request = wsmc_create_request(cl, resource_uri, options, NULL,
WSMAN_ACTION_TRANSFER_PUT, NULL, (void *) get_response);
if (!put_request)
return NULL;
wsmc_set_put_prop(get_response, put_request, options);
//ws_xml_destroy_doc(get_response);
if (wsman_send_request(cl, put_request)) {
ws_xml_destroy_doc(put_request);
return NULL;
}
put_response = wsmc_build_envelope_from_response(cl);
//ws_xml_destroy_doc(put_request);
return put_response;
}
WsXmlDocH
wsmc_action_invoke(WsManClient * cl,
const char *resource_uri,
client_opt_t *options,
const char *method,
WsXmlDocH data)
{
WsXmlDocH response;
WsXmlNodeH body = NULL;
WsXmlDocH request = wsmc_create_request(cl, resource_uri, options, NULL,
WSMAN_ACTION_CUSTOM, (char *)method, NULL);
if (!request)
return NULL;
body = ws_xml_get_soap_body(request);
if (body == NULL) {
ws_xml_destroy_doc(request);
return NULL;
}
if (list_isempty(options->properties) &&
data != NULL) {
WsXmlNodeH n = ws_xml_get_doc_root(data);
ws_xml_duplicate_tree(ws_xml_get_soap_body(request), n);
} else if (!list_isempty(options->properties)) {
if (method) {
WsXmlNodeH xnode = ws_xml_add_empty_child_format(body,
(char *)resource_uri, "%s_INPUT", method);
if (xnode == NULL) {
return NULL;
}
lnode_t *lnode = list_first(options->properties);
while (lnode) {
key_value_t *property = (key_value_t *)lnode->list_data;
if (property->type == 0) {
ws_xml_add_child(xnode, (char *)resource_uri, (char *)property->key, (char *)property->v.text);
}
else {
epr_serialize(xnode, (char *)resource_uri, property->key, property->v.epr, 1);
}
lnode = list_next(options->properties, lnode);
}
}
} else if (!strchr(method, '/')) { /* non-custom method without parameters */
ws_xml_add_empty_child_format(body,
(char *)resource_uri, "%s_INPUT", method);
} else {
/* empty body */
}
if ((options->flags & FLAG_DUMP_REQUEST) == FLAG_DUMP_REQUEST) {
ws_xml_dump_node_tree(cl->dumpfile, ws_xml_get_doc_root(request));
}
if (wsman_send_request(cl, request)) {
ws_xml_destroy_doc(request);
return NULL;
}
response = wsmc_build_envelope_from_response(cl);
ws_xml_destroy_doc(request);
return response;
}
WsXmlDocH
wsmc_action_invoke_fromtext(WsManClient * cl,
const char *resourceUri,
client_opt_t *options,
const char *method,
const char *data,
size_t size,
const char *encoding)
{
WsXmlDocH response;
WsXmlDocH request = wsmc_create_request(cl, resourceUri, options, NULL,
WSMAN_ACTION_CUSTOM,
(char *)method, NULL);
if (request == NULL) {
error("could not create request");
return NULL;
}
if ( data != NULL) {
WsXmlDocH doc = wsmc_read_memory(
(char *)data, size, (char *)encoding, 0);
WsXmlNodeH n;
if (doc == NULL) {
error("could not wsmc_read_memory");
ws_xml_destroy_doc(request);
return NULL;
}
n = ws_xml_get_doc_root(doc);
ws_xml_duplicate_tree(ws_xml_get_soap_body(request), n);
ws_xml_destroy_doc(doc);
} else {
warning("No XML provided");
}
if ((options->flags & FLAG_DUMP_REQUEST) == FLAG_DUMP_REQUEST) {
ws_xml_dump_node_tree(cl->dumpfile, ws_xml_get_doc_root(request));
}
if (wsman_send_request(cl, request)) {
ws_xml_destroy_doc(request);
return NULL;
}
response = wsmc_build_envelope_from_response(cl);
ws_xml_destroy_doc(request);
return response;
}
WsXmlDocH
wsmc_action_invoke_serialized(WsManClient * cl,
const char *resourceUri,
client_opt_t *options,
const char *method,
void *typeInfo, void *data)
{
WsXmlDocH response;
WsXmlDocH request = wsmc_create_request(cl, resourceUri, options, NULL,
WSMAN_ACTION_CUSTOM, (char *)method, NULL);
if (request == NULL) {
error("could not create request");
return NULL;
}
if (data != NULL) {
handle_resource_request(cl, request, data, typeInfo, (char *)resourceUri);
}
if ((options->flags & FLAG_DUMP_REQUEST) == FLAG_DUMP_REQUEST) {
ws_xml_dump_node_tree(cl->dumpfile, ws_xml_get_doc_root(request));
}
if (wsman_send_request(cl, request)) {
ws_xml_destroy_doc(request);
return NULL;
}
response = wsmc_build_envelope_from_response(cl);
ws_xml_destroy_doc(request);
return response;
}
WsXmlDocH
wsmc_action_identify(WsManClient * cl,
client_opt_t *options)
{
WsXmlDocH response;
WsXmlDocH request = wsmc_create_request(cl, NULL, options, NULL,
WSMAN_ACTION_IDENTIFY, NULL, NULL);
if (!request)
return NULL;
if (wsman_send_request(cl, request)) {
ws_xml_destroy_doc(request);
return NULL;
}
response = wsmc_build_envelope_from_response(cl);
ws_xml_destroy_doc(request);
return response;
}
int
wsmc_action_enumerate_and_pull(WsManClient * cl,
const char *resource_uri,
client_opt_t *options,
filter_t *filter,
SoapResponseCallback callback,
void *callback_data)
{
WsXmlDocH doc;
char *enumContext = NULL;
WsXmlDocH enum_response = wsmc_action_enumerate(cl,
resource_uri, options, filter);
if (enum_response) {
long rc = wsmc_get_response_code(cl);
if (rc == 200 || rc == 400 || rc == 500) {
callback(cl, enum_response, callback_data);
} else {
return 0;
}
enumContext = wsmc_get_enum_context(enum_response);
ws_xml_destroy_doc(enum_response);
} else {
return 0;
}
while (enumContext != NULL && enumContext[0] != 0) {
long rc = wsmc_get_response_code(cl);
doc = wsmc_action_pull(cl, resource_uri, options, filter, enumContext);
if (rc != 200 && rc != 400 && rc != 500) {
wsmc_free_enum_context(enumContext);
return 0;
}
callback(cl, doc, callback_data);
wsmc_free_enum_context(enumContext);
enumContext = wsmc_get_enum_context(doc);
if (doc) {
ws_xml_destroy_doc(doc);
}
}
wsmc_free_enum_context(enumContext);
return 1;
}
WsXmlDocH
wsmc_action_enumerate(WsManClient * cl,
const char *resource_uri,
client_opt_t *options,
filter_t *filter)
{
WsXmlDocH response;
WsXmlDocH request = wsmc_create_request(cl,
resource_uri, options, filter,
WSMAN_ACTION_ENUMERATION, NULL, NULL);
if (!request)
return NULL;
if (wsman_send_request(cl, request)) {
ws_xml_destroy_doc(request);
return NULL;
}
response = wsmc_build_envelope_from_response(cl);
ws_xml_destroy_doc(request);
return response;
}
WsXmlDocH
wsmc_action_pull(WsManClient * cl,
const char *resource_uri,
client_opt_t *options,
filter_t *filter,
const char *enumContext)
{
WsXmlDocH response;
WsXmlNodeH node;
if (enumContext || (enumContext && enumContext[0] == 0)) {
WsXmlDocH request = wsmc_create_request(cl, resource_uri, options, filter,
WSMAN_ACTION_PULL, NULL, (char *)enumContext);
if (wsman_send_request(cl, request)) {
ws_xml_destroy_doc(request);
return NULL;
}
response = wsmc_build_envelope_from_response(cl);
ws_xml_destroy_doc(request);
} else {
error("No enumeration context ???");
return NULL;
}
node = ws_xml_get_child(ws_xml_get_soap_body(response),
0, NULL, NULL);
if (node == NULL ||
(strcmp(ws_xml_get_node_local_name(node), WSENUM_PULL_RESP)) != 0) {
error("no Pull response");
}
return response;
}
WsXmlDocH
wsmc_action_release(WsManClient * cl,
const char *resource_uri,
client_opt_t *options,
const char *enumContext)
{
WsXmlDocH response;
if (enumContext || (enumContext && enumContext[0] == 0)) {
WsXmlDocH request = wsmc_create_request(cl, resource_uri, options, NULL,
WSMAN_ACTION_RELEASE,
NULL, (char *)enumContext);
if (!request)
return NULL;
if (wsman_send_request(cl, request)) {
ws_xml_destroy_doc(request);
return NULL;
}
response = wsmc_build_envelope_from_response(cl);
ws_xml_destroy_doc(request);
} else {
return NULL;
}
return response;
}
WsXmlDocH wsmc_action_subscribe(WsManClient * cl, const char *resource_uri,
client_opt_t * options, filter_t *filter)
{
WsXmlDocH response;
WsXmlDocH request = wsmc_create_request(cl, resource_uri, options, filter,
WSMAN_ACTION_SUBSCRIBE, NULL, NULL);
if (!request)
return NULL;
if (wsman_send_request(cl, request)) {
ws_xml_destroy_doc(request);
return NULL;
}
response = wsmc_build_envelope_from_response(cl);
ws_xml_destroy_doc(request);
return response;
}
WsXmlDocH wsmc_action_unsubscribe(WsManClient * cl, const char *resource_uri,
client_opt_t * options,
const char *subsContext)
{
WsXmlDocH response;
WsXmlDocH request = wsmc_create_request(cl, resource_uri, options, NULL,
WSMAN_ACTION_UNSUBSCRIBE, NULL, (void *)subsContext);
if (!request)
return NULL;
if (wsman_send_request(cl, request)) {
ws_xml_destroy_doc(request);
return NULL;
}
response = wsmc_build_envelope_from_response(cl);
ws_xml_destroy_doc(request);
return response;
}
WsXmlDocH wsmc_action_renew(WsManClient * cl, const char *resource_uri,
client_opt_t * options,
const char *subsContext)
{
WsXmlDocH response;
WsXmlDocH request = wsmc_create_request(cl, resource_uri, options, NULL,
WSMAN_ACTION_RENEW, NULL, (void *)subsContext);
if (!request)
return NULL;
if (wsman_send_request(cl, request)) {
ws_xml_destroy_doc(request);
return NULL;
}
response = wsmc_build_envelope_from_response(cl);
ws_xml_destroy_doc(request);
return response;
}
char*
wsmc_get_enum_context(WsXmlDocH doc)
{
char *enumContext = NULL;
char *text = NULL;
WsXmlNodeH enumStartNode = ws_xml_get_child(ws_xml_get_soap_body(doc),
0, NULL, NULL);
if (enumStartNode) {
WsXmlNodeH cntxNode = ws_xml_get_child(enumStartNode, 0,
XML_NS_ENUMERATION,
WSENUM_ENUMERATION_CONTEXT);
if (!cntxNode) {
return NULL;
}
text = ws_xml_get_node_text(cntxNode);
if (text) {
enumContext = u_strdup(text);
}
}
return enumContext;
}
char *
wsmc_get_event_enum_context(WsXmlDocH doc)
{
char *enumContext = NULL;
char *text = NULL;
WsXmlNodeH node = ws_xml_get_child(ws_xml_get_soap_body(doc),
0, XML_NS_EVENTING, WSEVENT_SUBSCRIBE_RESP);
if (node) {
node = ws_xml_get_child(node, 0,
XML_NS_ENUMERATION,
WSENUM_ENUMERATION_CONTEXT);
if (!node)
return NULL;
text = ws_xml_get_node_text(node);
if (text) {
enumContext = u_strdup(text);
}
}
return enumContext;
}
void
wsmc_free_enum_context(char *enumcontext)
{
u_free(enumcontext);
}
/**
* Buid Inbound Envelope from Response
* @param cl Client Handler
* @return XML document with Envelope
*/
WsXmlDocH
wsmc_build_envelope_from_response(WsManClient * cl)
{
WsXmlDocH doc = NULL;
u_buf_t *buffer = cl->connection->response;
if (!buffer || !u_buf_ptr(buffer)) {
error("NULL response");
return NULL;
}
doc = ws_xml_read_memory( u_buf_ptr(buffer), u_buf_len(buffer), cl->content_encoding, 0);
if (doc == NULL) {
error("could not create xmldoc from response");
}
return doc;
}
static void
wsmc_release_conn(WsManConnection * conn)
{
if (conn == NULL) {
return;
}
if (conn->request) {
u_buf_free(conn->request);
conn->request = NULL;
}
if (conn->response) {
u_buf_free(conn->response);
conn->response = NULL;
}
u_free(conn);
}
void
wsmc_reinit_conn(WsManClient * cl)
{
u_buf_clear(cl->connection->response);
u_buf_clear(cl->connection->request);
cl->response_code = 0;
cl->last_error = 0;
if (cl->fault_string) {
u_free(cl->fault_string);
cl->fault_string = NULL;
}
}
static void
init_client_connection(WsManClient * cl)
{
WsManConnection *conn = (WsManConnection *) u_zalloc(sizeof(WsManConnection));
u_buf_create(&conn->response);
u_buf_create(&conn->request);
cl->response_code = 0;
cl->connection = conn;
}
WsManClient*
wsmc_create_from_uri(const char* endpoint)
{
u_uri_t *uri = NULL;
WsManClient* cl;
if (!endpoint) {
return NULL;
}
if (u_uri_parse((const char *) endpoint, &uri) != 0 ) {
return NULL;
}
if (!uri) {
return NULL;
}
cl = wsmc_create( uri->host,
uri->port,
uri->path,
uri->scheme,
uri->user,
uri->pwd);
u_uri_free(uri);
return cl;
}
int
wsmc_set_encoding(WsManClient *cl, const char *encoding)
{
u_free(cl->content_encoding);
cl->content_encoding = encoding ? u_strdup(encoding) : NULL;
return 0;
}
int
wsmc_set_namespace(WsManClient *cl, const char *ns)
{
u_free(cl->cim_ns);
cl->cim_ns = ns ? u_strdup(ns) : NULL;
return 0;
}
char *wsmc_get_namespace(WsManClient *cl)
{
return cl->cim_ns;
}
int
wsmc_check_for_fault(WsXmlDocH doc )
{
return wsman_is_fault_envelope(doc);
}
WsManFault *
wsmc_fault_new(void)
{
WsManFault *fault =
(WsManFault *) u_zalloc(sizeof(WsManFault));
if (fault)
return fault;
else
return NULL;
}
void wsmc_fault_destroy(WsManFault *fault)
{
/*
if (fault->code)
u_free(fault->code);
if (fault->subcode)
u_free(fault->subcode);
if (fault->reason)
u_free(fault->reason);
if (fault->fault_detail)
u_free(fault->fault_detail);
*/
u_free(fault);
return;
}
void
wsmc_get_fault_data(WsXmlDocH doc,
WsManFault *fault)
{
WsXmlNodeH body;
WsXmlNodeH fault_node;
WsXmlNodeH code;
WsXmlNodeH reason;
WsXmlNodeH detail;
if (wsmc_check_for_fault(doc) == 0 || !fault )
return;
body = ws_xml_get_soap_body(doc);
fault_node = ws_xml_get_child(body, 0, XML_NS_SOAP_1_2, SOAP_FAULT);
if (!fault_node)
return;
code = ws_xml_get_child(fault_node, 0, XML_NS_SOAP_1_2, SOAP_CODE);
if (code) {
WsXmlNodeH code_v = ws_xml_get_child(code, 0 , XML_NS_SOAP_1_2, SOAP_VALUE);
WsXmlNodeH subcode = ws_xml_get_child(code, 0 , XML_NS_SOAP_1_2, SOAP_SUBCODE);
WsXmlNodeH subcode_v = ws_xml_get_child(subcode, 0 , XML_NS_SOAP_1_2, SOAP_VALUE);
fault->code = ws_xml_get_node_text(code_v);
fault->subcode = ws_xml_get_node_text(subcode_v);
}
reason = ws_xml_get_child(fault_node, 0, XML_NS_SOAP_1_2, SOAP_REASON);
if (reason) {
WsXmlNodeH reason_text = ws_xml_get_child(reason, 0 , XML_NS_SOAP_1_2, SOAP_TEXT);
fault->reason = ws_xml_get_node_text(reason_text);
}
detail = ws_xml_get_child(fault_node, 0, XML_NS_SOAP_1_2, SOAP_DETAIL);
if (detail) {
// FIXME
// WsXmlNodeH fault_detail = ws_xml_get_child(detail, 0 , XML_NS_WS_MAN, SOAP_FAULT_DETAIL);
// fault->fault_detail = ws_xml_get_node_text(fault_detail);
fault->fault_detail = ws_xml_get_node_text(detail);
}
return;
}
WsManClient*
wsmc_create(const char *hostname,
const int port,
const char *path,
const char *scheme,
const char *username,
const char *password)
{
#ifndef _WIN32
dictionary *ini;
#endif
WsManClient *wsc = (WsManClient *) calloc(1, sizeof(WsManClient));
if (wsc == NULL) {
error("Can't alloc WsManClient");
return NULL;
}
wsc->hdl = &wsc->data;
if (pthread_mutex_init(&wsc->mutex, NULL)) {
u_free(wsc);
return NULL;
}
#ifndef _WIN32
wsmc_set_conffile(wsc, DEFAULT_CLIENT_CONFIG_FILE);
ini = iniparser_new(wsmc_get_conffile(wsc));
if (ini) {
char *user_agent = iniparser_getstr(ini, "client:agent");
if (user_agent) {
wsman_transport_set_agent(wsc, user_agent);
}
iniparser_free(ini);
}
#endif
wsc->serctx = ws_serializer_init();
wsc->dumpfile = stdout;
wsc->data.scheme = u_strdup(scheme ? scheme : "http");
wsc->data.hostname = hostname ? u_strdup(hostname) : u_strdup("localhost");
wsc->data.port = port;
wsc->data.path = u_strdup(path ? path : "/wsman");
wsc->data.user = username ? u_strdup(username) : NULL;
wsc->data.pwd = password ? u_strdup(password) : NULL;
wsc->data.auth_set = 0;
wsc->initialized = 0;
wsc->transport_timeout = 0;
wsc->content_encoding = u_strdup("UTF-8");
#ifdef _WIN32
wsc->session_handle = 0;
#endif
wsc->data.endpoint = u_strdup_printf("%s://%s:%d%s%s",
wsc->data.scheme, wsc->data.hostname,
wsc->data.port,
(*wsc->data.path == '/') ? "" : "/",
wsc->data.path);
debug("Endpoint: %s", wsc->data.endpoint);
wsc->authentication.verify_host = 1; //verify CN in server certicates by default
wsc->authentication.verify_peer = 1; //validate server certificates by default
#ifndef _WIN32
wsc->authentication.crl_check = 0; // No CRL check by default
wsc->authentication.crl_file = NULL;
#endif
init_client_connection(wsc);
return wsc;
}
void
wsmc_release(WsManClient * cl)
{
#ifndef _WIN32
if (cl->client_config_file) {
u_free(cl->client_config_file);
cl->client_config_file = NULL;
}
#endif
if (cl->data.scheme) {
u_free(cl->data.scheme);
cl->data.scheme = NULL;
}
if (cl->data.hostname) {
u_free(cl->data.hostname);
cl->data.hostname = NULL;
}
if (cl->data.path) {
u_free(cl->data.path);
cl->data.path = NULL;
}
if (cl->data.user) {
u_free(cl->data.user);
cl->data.user = NULL;
}
if (cl->data.pwd) {
u_free(cl->data.pwd);
cl->data.pwd = NULL;
}
if (cl->data.endpoint) {
u_free(cl->data.endpoint);
cl->data.endpoint = NULL;
}
if (cl->fault_string) {
u_free(cl->fault_string);
cl->fault_string = NULL;
}
if (cl->connection) {
wsmc_release_conn(cl->connection);
cl->connection = NULL;
}
if (cl->serctx) {
ws_serializer_cleanup(cl->serctx);
cl->serctx = NULL;
}
if (cl->content_encoding) {
u_free(cl->content_encoding);
cl->content_encoding = NULL;
}
if (cl->cim_ns) {
u_free(cl->cim_ns);
cl->cim_ns = NULL;
}
if (cl->authentication.crl_file != NULL) {
u_free(cl->authentication.crl_file);
cl->authentication.crl_file = NULL;
}
if (cl->authentication.method != NULL) {
u_free(cl->authentication.method);
cl->authentication.method = NULL;
}
if (cl->authentication.cainfo != NULL) {
u_free(cl->authentication.cainfo);
cl->authentication.cainfo = NULL;
}
if (cl->authentication.caoid != NULL) {
u_free(cl->authentication.caoid);
cl->authentication.caoid = NULL;
}
if (cl->proxy_data.proxy_username != NULL) {
u_free(cl->proxy_data.proxy_username);
cl->proxy_data.proxy_username = NULL;
}
if (cl->proxy_data.proxy_password != NULL) {
u_free(cl->proxy_data.proxy_password);
cl->proxy_data.proxy_password = NULL;
}
pthread_mutex_destroy(&cl->mutex);
wsman_transport_close_transport(cl);
u_free(cl);
}
int
wsmc_lock(WsManClient * cl)
{
if (pthread_mutex_lock(&cl->mutex))
return 1;
if (cl->flags & WSMAN_CLIENT_BUSY) {
pthread_mutex_unlock(&cl->mutex);
return 1;
}
cl->flags |= WSMAN_CLIENT_BUSY;
pthread_mutex_unlock(&cl->mutex);
return 0;
}
void
wsmc_unlock(WsManClient * cl)
{
if (pthread_mutex_lock(&cl->mutex))
return;
cl->flags &= ~WSMAN_CLIENT_BUSY;
pthread_mutex_unlock(&cl->mutex);
}
void
wsmc_remove_query_string(const char *s, char **result)
{
char *r = 0;
const char *q;
char *buf = 0;
buf = u_strndup(s, strlen(s));
if (!buf) {
*result = NULL;
return;
}
if ((q = strchr(buf, '?')) != NULL) {
r = u_strndup(s, q - buf);
*result = r;
} else {
*result = (char *)s;
}
u_free(buf);
}