summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/Doxyfile.api4
-rw-r--r--examples/csoap/simpleclient.c30
-rw-r--r--libcsoap/soap-addressing.c29
-rw-r--r--libcsoap/soap-addressing.h5
-rw-r--r--libcsoap/soap-client.c72
-rw-r--r--libcsoap/soap-client.h47
-rw-r--r--libcsoap/soap-nudp.c22
-rw-r--r--libcsoap/soap-server.c47
-rw-r--r--libcsoap/soap-server.h26
-rw-r--r--libcsoap/soap-transport.c23
-rw-r--r--libcsoap/soap-xmlsec.c443
-rw-r--r--libcsoap/soap-xmlsec.h68
12 files changed, 482 insertions, 334 deletions
diff --git a/doc/Doxyfile.api b/doc/Doxyfile.api
index ae52f80..0614bb7 100644
--- a/doc/Doxyfile.api
+++ b/doc/Doxyfile.api
@@ -1005,7 +1005,7 @@ INCLUDE_FILE_PATTERNS =
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
-PREDEFINED =
+PREDEFINED = __CSOAP_INTERNAL=1 __NHTTP_INTERNAL=1
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
@@ -1141,7 +1141,7 @@ INCLUDED_BY_GRAPH = YES
# So in most cases it will be better to enable call graphs for selected
# functions only using the \callgraph command.
-CALL_GRAPH = NO
+CALL_GRAPH = YES
# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will graphical hierarchy of all classes instead of a textual one.
diff --git a/examples/csoap/simpleclient.c b/examples/csoap/simpleclient.c
index 03beaae..757b2cf 100644
--- a/examples/csoap/simpleclient.c
+++ b/examples/csoap/simpleclient.c
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: simpleclient.c,v 1.19 2006/11/28 23:45:57 m0gg Exp $
+ * $Id: simpleclient.c,v 1.20 2006/11/29 11:04:24 m0gg Exp $
*
* CSOAP Project: CSOAP examples project
* Copyright (C) 2003-2004 Ferhat Ayaz
@@ -24,12 +24,14 @@
#include <stdlib.h>
#include <libxml/tree.h>
+#include <libxml/uri.h>
#include <nanohttp/nanohttp-error.h>
#include <nanohttp/nanohttp-logging.h>
#include <libcsoap/soap-ctx.h>
#include <libcsoap/soap-env.h>
+#include <libcsoap/soap-addressing.h>
#include <libcsoap/soap-client.h>
static char *url = "http://localhost:10000/csoapserver";
@@ -39,7 +41,8 @@ static char *method = "sayHello";
int
main(int argc, char **argv)
{
- struct SoapCtx *ctx, *ctx2;
+ struct SoapCtx *request;
+ struct SoapCtx *response;
herror_t err;
// hlog_set_level(HLOG_VERBOSE);
@@ -52,7 +55,7 @@ main(int argc, char **argv)
exit(1);
}
- err = soap_ctx_new_with_method(urn, method, &ctx);
+ err = soap_ctx_new_with_method(urn, method, &request);
if (err != H_OK)
{
printf("%s():%s [%d]\n", herror_func(err), herror_message(err), herror_code(err));
@@ -60,28 +63,27 @@ main(int argc, char **argv)
exit(1);
}
- soap_env_add_item(ctx->env, "xsd:string", "name", "Jonny B. Good");
-
- printf("**** sending ****\n");
- xmlDocDump(stderr, ctx->env->root->doc);
+ soap_env_add_item(request->env, "xsd:string", "name", "Jonny B. Good");
if (argc > 1)
url = argv[1];
- printf("destination: \"%s\"\n", url);
- if ((err = soap_client_invoke(ctx, &ctx2, url, "")) != H_OK)
+ printf("**** sending to \"%s\" ****\n", url);
+ xmlDocFormatDump(stderr, request->env->root->doc, 1);
+
+ if ((err = soap_client_invoke(request, &response, url, "")) != H_OK)
{
printf("[%d] %s(): %s\n", herror_code(err), herror_func(err), herror_message(err));
herror_release(err);
- soap_ctx_free(ctx);
+ soap_ctx_free(request);
exit(1);
}
- printf("**** received ****\n");
- xmlDocDump(stdout, ctx2->env->root->doc);
+ printf("**** received from \"%s\" ****\n", soap_addressing_get_from_address_string(response->env));
+ xmlDocFormatDump(stdout, response->env->root->doc, 1);
- soap_ctx_free(ctx2);
- soap_ctx_free(ctx);
+ soap_ctx_free(response);
+ soap_ctx_free(request);
soap_client_destroy();
diff --git a/libcsoap/soap-addressing.c b/libcsoap/soap-addressing.c
index cde31ec..8cb11b8 100644
--- a/libcsoap/soap-addressing.c
+++ b/libcsoap/soap-addressing.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: soap-addressing.c,v 1.8 2006/11/28 23:45:57 m0gg Exp $
+* $Id: soap-addressing.c,v 1.9 2006/11/29 11:04:24 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2006 Heiko Ronsdorf
@@ -424,12 +424,6 @@ soap_addressing_set_reply_to_address(struct SoapEnv *envelope, xmlURI *address)
}
xmlNodePtr
-soap_addressing_get_from(struct SoapEnv *envelope)
-{
- return _soap_addressing_get_child_element(envelope->header, WSA_FROM);
-}
-
-xmlNodePtr
soap_addressing_set_from(struct SoapEnv *envelope, xmlNodePtr address)
{
xmlNodePtr ret;
@@ -463,6 +457,12 @@ soap_addressing_set_from_address_string(struct SoapEnv *envelope, const char *fr
return ret;
}
+xmlNodePtr
+soap_addressing_get_from(struct SoapEnv *envelope)
+{
+ return _soap_addressing_get_child_element(envelope->header, WSA_FROM);
+}
+
xmlURI *
soap_addressing_get_from_address(struct SoapEnv *envelope)
{
@@ -475,6 +475,21 @@ soap_addressing_get_from_address(struct SoapEnv *envelope)
return soap_addressing_get_address(from);
}
+xmlChar *
+soap_addressing_get_from_address_string(struct SoapEnv *envelope)
+{
+ xmlURI *uri;
+ xmlChar *ret;
+
+ if (!(uri = soap_addressing_get_from_address(envelope)))
+ return NULL;
+
+ ret = xmlSaveUri(uri);
+ xmlFreeURI(uri);
+
+ return ret;
+}
+
xmlNodePtr
soap_addressing_set_from_address(struct SoapEnv *envelope, xmlURI *address)
{
diff --git a/libcsoap/soap-addressing.h b/libcsoap/soap-addressing.h
index fa04038..fb31286 100644
--- a/libcsoap/soap-addressing.h
+++ b/libcsoap/soap-addressing.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: soap-addressing.h,v 1.8 2006/11/28 23:45:57 m0gg Exp $
+ * $Id: soap-addressing.h,v 1.9 2006/11/29 11:04:24 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2006 Heiko Ronsdorf
@@ -37,7 +37,7 @@
* in a transport-neutral manner.
*
* @author H. Ronsdorf
- * @version $Revision: 1.8 $
+ * @version $Revision: 1.9 $
*
* @see http://www.w3.org/TR/ws-addr-core/,
* http://www.w3.org/TR/REC-xml-names/
@@ -230,6 +230,7 @@ xmlNodePtr soap_addressing_set_reply_to_address(struct SoapEnv *envelope, xmlURI
xmlNodePtr soap_addressing_get_from(struct SoapEnv *envelope);
xmlURI *soap_addressing_get_from_address(struct SoapEnv *envelope);
+xmlChar *soap_addressing_get_from_address_string(struct SoapEnv *envelope);
xmlNodePtr soap_addressing_set_from(struct SoapEnv *envelope, xmlNodePtr address);
xmlNodePtr soap_addressing_set_from_address(struct SoapEnv *envelope, xmlURI *address);
diff --git a/libcsoap/soap-client.c b/libcsoap/soap-client.c
index 416054c..cf2479f 100644
--- a/libcsoap/soap-client.c
+++ b/libcsoap/soap-client.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: soap-client.c,v 1.32 2006/11/28 23:45:57 m0gg Exp $
+* $Id: soap-client.c,v 1.33 2006/11/29 11:04:24 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -25,6 +25,10 @@
#include <config.h>
#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
#include <libxml/tree.h>
#include <libxml/uri.h>
@@ -43,12 +47,48 @@
#endif
#include "soap-client.h"
+#ifdef HAVE_XMLSEC1
+static int _soap_client_force_sign = 0;
+static int _soap_client_force_verify = 0;
+static int _soap_client_force_encrypt = 0;
+static int _soap_client_force_decrypt = 0;
+
+static inline void
+_soap_client_parse_arguments(int argc, char **argv)
+{
+ int i;
+
+ for (i=0; i<argc; i++)
+ {
+ if (!strcmp(CSOAP_CLIENT_FORCE_ENCRYPT, argv[i]))
+ {
+ _soap_client_force_encrypt = 1;
+ }
+ else if (!strcmp(CSOAP_CLIENT_FORCE_DECRYPT, argv[i]))
+ {
+ _soap_client_force_decrypt = 1;
+ }
+ else if (!strcmp(CSOAP_CLIENT_FORCE_VERIFY, argv[i]))
+ {
+ _soap_client_force_verify = 1;
+ }
+ else if (!strcmp(CSOAP_CLIENT_FORCE_SIGN, argv[i]))
+ {
+ _soap_client_force_sign = 1;
+ }
+ }
+ return;
+}
+#endif
+
herror_t
soap_client_init_args(int argc, char **argv)
{
herror_t status;
#ifdef HAVE_XMLSEC1
+ _soap_client_parse_arguments(argc, argv);
+
if ((status = soap_xmlsec_client_init_args(argc, argv)) != H_OK)
{
log_error2("soap_xmlsec_client_init_args failed (%s)", herror_message(status));
@@ -94,18 +134,26 @@ soap_client_invoke(struct SoapCtx *req, struct SoapCtx **res, const char *url, c
free(id);
#ifdef HAVE_XMLSEC1
- log_error1("trying encryption and signation");
-
if ((status = soap_xmlsec_encrypt(req)) != H_OK)
{
log_error2("soap_xmlsec_encrypt failed (%s)", herror_message(status));
- return status;
+ if (_soap_client_force_encrypt)
+ return status;
+ }
+ else
+ {
+ log_verbose1("soap_xmlsec_encrypt succeed");
}
if ((status = soap_xmlsec_sign(req)) != H_OK)
{
log_error2("soap_xmlsec_sign failed (%s)", herror_message(status));
- return status;
+ if (_soap_client_force_sign)
+ return status;
+ }
+ else
+ {
+ log_verbose1("soap_xmlsec_encrypt succeed");
}
#endif
@@ -119,13 +167,23 @@ soap_client_invoke(struct SoapCtx *req, struct SoapCtx **res, const char *url, c
if ((status = soap_xmlsec_verify(*res)) != H_OK)
{
log_error2("soap_xmlsec_verify failed (%s)", herror_message(status));
- return status;
+ if (_soap_client_force_verify)
+ return status;
+ }
+ else
+ {
+ log_verbose1("soap_xmlsec_verify succeed");
}
if ((status = soap_xmlsec_decrypt(*res)) != H_OK)
{
log_error2("soap_xmlsec_decrypt failed (%s)", herror_message(status));
- return status;
+ if (_soap_client_force_decrypt)
+ return status;
+ }
+ else
+ {
+ log_verbose1("soap_xmlsec_decrypt succeed");
}
#endif
diff --git a/libcsoap/soap-client.h b/libcsoap/soap-client.h
index f74d881..30d2f00 100644
--- a/libcsoap/soap-client.h
+++ b/libcsoap/soap-client.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: soap-client.h,v 1.14 2006/11/23 15:27:33 m0gg Exp $
+ * $Id: soap-client.h,v 1.15 2006/11/29 11:04:25 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -24,7 +24,45 @@
#ifndef __csoap_client_h
#define __csoap_client_h
-#define SOAP_ERROR_CLIENT_INIT 5001
+#define SOAP_ERROR_CLIENT 5000
+#define SOAP_ERROR_CLIENT_GENERIC (SOAP_ERROR_CLIENT + 0)
+#define SOAP_ERROR_CLIENT_INIT (SOAP_ERROR_CLIENT + 1)
+
+/**
+ *
+ * Commandline argument to force encryption of outgoing messages.
+ *
+ * @see soap_xmlsec_encrypt
+ *
+ */
+#define CSOAP_CLIENT_FORCE_ENCRYPT "-CSOAPencrypt"
+
+/**
+ *
+ * Commandline argument to force decryption of incoming messages.
+ *
+ * @see soap_xmlsec_decrypt
+ *
+ */
+#define CSOAP_CLIENT_FORCE_DECRYPT "-CSOAPdecrypt"
+
+/**
+ *
+ * Commandline argument to force signature on outgoing messages.
+ *
+ * @see soap_xmlsec_sign
+ *
+ */
+#define CSOAP_CLIENT_FORCE_SIGN "-CSOAPsign"
+
+/**
+ *
+ * Commandline argument to force signature on incoming messages.
+ *
+ * @see soap_xmlsec_verify
+ *
+ */
+#define CSOAP_CLIENT_FORCE_VERIFY "-CSOAPverify"
#ifdef __cplusplus
extern "C" {
@@ -44,9 +82,10 @@ extern herror_t soap_client_init_args(int argc, char **argv);
* @param env envelope to send
* @param response the result envelope
* @param url url to the soap server
- * @soap_action value for "SoapAction:" in the HTTP request header.
*
- * @returns H_OK if success
+ * @param soap_action value for "SoapAction:" in the HTTP request header.
+ *
+ * @return H_OK if success
*
*/
extern herror_t soap_client_invoke(struct SoapCtx * ctx, struct SoapCtx **response, const char *url, const char *soap_action);
diff --git a/libcsoap/soap-nudp.c b/libcsoap/soap-nudp.c
index 3c0cf70..fb4475d 100644
--- a/libcsoap/soap-nudp.c
+++ b/libcsoap/soap-nudp.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: soap-nudp.c,v 1.5 2006/11/26 20:13:05 m0gg Exp $
+* $Id: soap-nudp.c,v 1.6 2006/11/29 11:04:25 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2006 Heiko Ronsdorf
@@ -89,6 +89,7 @@ static short _soap_nudp_port = NUDP_DEFAULT_PORT;
static int _soap_nudp_socket;
static pthread_t _soap_nudp_thread;
static pthread_attr_t _soap_nudp_attr;
+static volatile int _soap_nudp_running = 0;
static short
_soap_nudp_server_set_port(void)
@@ -97,8 +98,8 @@ _soap_nudp_server_set_port(void)
if (!(entry = getservbyname("soap", "udp")))
{
- log_warn1("getservbyname returned NULL");
- _soap_nudp_port = NUDP_DEFAULT_PORT;
+ log_warn1("getservbyname(\"soap\", \"udp\") returned NULL, please edit services database");
+ _soap_nudp_port = NUDP_DEFAULT_PORT;
}
else
{
@@ -259,11 +260,14 @@ soap_nudp_server_run(void *unused)
struct SoapCtx *res;
xmlURI *to;
- for(;;)
+ while (_soap_nudp_running)
{
+ /* XXX: select with timeout */
+
_soap_nudp_receive_document(_soap_nudp_socket, &doc, &addr, &addr_len);
- xmlDocFormatDump(stdout, doc, 1);
+ // log_error1(__FUNCTION__);
+ // xmlDocFormatDump(stdout, doc, 1);
req = soap_ctx_new(NULL);
@@ -284,6 +288,8 @@ soap_nudp_server_run(void *unused)
soap_ctx_free(req);
}
+ close(_soap_nudp_socket);
+
return NULL;
}
@@ -292,6 +298,8 @@ soap_nudp_server_run_threaded(void)
{
int err;
+ _soap_nudp_running = 1;
+
if ((err = pthread_create(&_soap_nudp_thread, &_soap_nudp_attr, soap_nudp_server_run, NULL)) < 0)
{
log_error2("pthread_create failed (%s)", strerror(err));
@@ -304,13 +312,13 @@ soap_nudp_server_run_threaded(void)
void
soap_nudp_server_destroy(void)
{
+ _soap_nudp_running = 0;
- close(_soap_nudp_socket);
+ /* XXX: sleep for timeout, wait for select */
return;
}
-
herror_t
soap_nudp_client_init_args(int argc, char **argv)
{
diff --git a/libcsoap/soap-server.c b/libcsoap/soap-server.c
index e40c798..b21688b 100644
--- a/libcsoap/soap-server.c
+++ b/libcsoap/soap-server.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: soap-server.c,v 1.34 2006/11/28 23:45:57 m0gg Exp $
+* $Id: soap-server.c,v 1.35 2006/11/29 11:04:25 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -50,22 +50,9 @@
#include "soap-router.h"
#include "soap-addressing.h"
#include "soap-transport.h"
-
#ifdef HAVE_XMLSEC1
#include "soap-xmlsec.h"
-static inline herror_t
-_soap_server_xmlsec_sign(struct SoapEnv *envelope)
-{
- return soap_xmlsec_sign(envelope);
-}
-#else
-static inline herror_t
-_soap_server_xmlsec_sign(struct SoapEnv *envelope)
-{
- return H_OK;
-}
#endif
-
#include "soap-server.h"
static SoapRouterNode *head = NULL;
@@ -139,6 +126,8 @@ soap_server_find_router(const char *context)
return NULL;
}
+/* XXX: rewrite this function */
+
herror_t
soap_server_process(struct SoapCtx *request, struct SoapCtx **response)
{
@@ -150,11 +139,31 @@ soap_server_process(struct SoapCtx *request, struct SoapCtx **response)
SoapService *service;
herror_t err;
- log_verbose1("processing");
+ log_verbose1("**** processing ****");
xmlDocDump(stdout, request->env->root->doc);
+ log_verbose1("********************");
*response = soap_ctx_new(NULL);
+#ifdef HAVE_XMLSEC1
+ if ((err = soap_xmlsec_verify(request)) != H_OK)
+ {
+ log_error2("soap_xmlsec_verify failed (%s)", herror_message(err));
+ sprintf(buffer, "Verification of message signature failed (%s)", herror_message(err));
+
+ _soap_server_env_new_with_fault("Internal server error", buffer, &((*response)->env));
+ return H_OK;
+ }
+
+ if ((err = soap_xmlsec_decrypt(request)) != H_OK)
+ {
+ log_error2("soap_xmlsec_decrypt failed (%s)", herror_message(err));
+ sprintf(buffer, "Decryption of message body failed (%s)", herror_message(err));
+ _soap_server_env_new_with_fault("Internal server error", buffer, &((*response)->env));
+ return H_OK;
+ }
+#endif
+
if ((method = soap_env_find_methodname(request->env)))
{
log_verbose2("method: \"%s\"", method);
@@ -215,7 +224,13 @@ soap_server_process(struct SoapCtx *request, struct SoapCtx **response)
_soap_server_fillup_header((*response)->env);
- return _soap_server_xmlsec_sign((*response)->env);
+#ifdef HAVE_XMLSEC1
+ soap_xmlsec_encrypt(*response);
+
+ soap_xmlsec_sign(*response);
+#endif
+
+ return H_OK;
}
herror_t
diff --git a/libcsoap/soap-server.h b/libcsoap/soap-server.h
index cafa9a5..afb3a3a 100644
--- a/libcsoap/soap-server.h
+++ b/libcsoap/soap-server.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: soap-server.h,v 1.13 2006/11/23 15:27:33 m0gg Exp $
+ * $Id: soap-server.h,v 1.14 2006/11/29 11:04:25 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -24,6 +24,30 @@
#ifndef __csoap_server_h
#define __csoap_server_h
+/**
+ *
+ * @mainpage Project overview
+ *
+ * @section seq_intro Introduction
+ *
+ * cSOAP is a client/server SOAP library implemented in pure C. It comes with
+ * embedded transport servers for UDP and HTTP (nanohttp). The transferred XML
+ * structures are handled by libxml2.
+ *
+ * @section seq_features Features
+ *
+ * - different transport services
+ * -- client/server HTTP transport service (with SSL)
+ * -- client/server UDP transport service (multicast)
+ * - attachments via MIME
+ * - message based security (encryption/signation)
+ * - automatic generation of WS-Inspection
+ *
+ * @author Ferhat Ayaz
+ * @version $Revision: 1.14 $
+ *
+ */
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/libcsoap/soap-transport.c b/libcsoap/soap-transport.c
index 7d54ced..5cbdc46 100644
--- a/libcsoap/soap-transport.c
+++ b/libcsoap/soap-transport.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: soap-transport.c,v 1.6 2006/11/28 23:45:57 m0gg Exp $
+* $Id: soap-transport.c,v 1.7 2006/11/29 11:04:25 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2007 Heiko Ronsdorf
@@ -84,7 +84,7 @@ _soap_transport_new(const char *scheme, void *data, msg_exchange invoke)
ret->data = data;
ret->invoke = invoke;
- log_verbose4("scheme=%s, data=%p, invoke=%p", ret->scheme, ret->data, ret->invoke);
+ log_verbose4("scheme=\"%s\", data=%p, invoke=%p", ret->scheme, ret->data, ret->invoke);
return ret;
}
@@ -268,15 +268,26 @@ soap_transport_client_invoke(struct SoapCtx *request, struct SoapCtx **response)
herror_t ret;
xmlURI *dest;
- log_verbose1(__FUNCTION__);
- xmlDocFormatDump(stdout, request->env->root->doc, 1);
+ // log_verbose1(__FUNCTION__);
+ // xmlDocFormatDump(stdout, request->env->root->doc, 1);
- dest = soap_addressing_get_to_address(request->env);
+ if (!(dest = soap_addressing_get_to_address(request->env)))
+ {
+ log_verbose1("soap_addressing_get_to_address failed");
+ return herror_new("soap_transport_client_invoke", 0, "cannot find to address in SOAP envelope");
+ }
+
+ if (!dest->scheme)
+ {
+ log_verbose1("missing scheme (protocol) in to address");
+ return herror_new("soap_transport_client_invoke", 0, "cannot find protocol in destination address");
+ }
log_verbose2("trying to contact \"%s\"", soap_addressing_get_to_address_string(request->env));
- for (walker = head; walker; walker = walker->next)
+ for (walker=head; walker; walker=walker->next)
{
+ log_verbose3("testing transport server \"%s\" for \"%s\"", walker->scheme, dest->scheme);
if (!strcmp(walker->scheme, dest->scheme))
{
log_verbose3("found transport layer for \"%s\" (%p)", dest->scheme, walker->invoke);
diff --git a/libcsoap/soap-xmlsec.c b/libcsoap/soap-xmlsec.c
index 75cc187..55c341b 100644
--- a/libcsoap/soap-xmlsec.c
+++ b/libcsoap/soap-xmlsec.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: soap-xmlsec.c,v 1.4 2006/11/28 23:45:57 m0gg Exp $
+* $Id: soap-xmlsec.c,v 1.5 2006/11/29 11:04:25 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -118,213 +118,14 @@ static void _soap_xmlsec_error_callback(const char *file, int line, const char *
/**
*
- * decrypt_file:
+ * Lookups key in the @store. The caller is responsible for destroying returned
+ * key with #xmlSecKeyDestroy function.
*
- * @mngr: the pointer to keys manager.
- * @enc_file: the encrypted XML file name.
+ * @param store the pointer to simple keys store.
+ * @param name the desired key name.
+ * @param keyInfoCtx the pointer to <dsig:KeyInfo/> node processing context.
*
- * Decrypts the XML file #enc_file using DES key from #key_file and
- * prints results to stdout.
- *
- * @Returns 0 on success or a negative value if an error occurs.
- *
- */
-static int _soap_xmlsec_decrypt_file(xmlSecKeysMngrPtr mngr, const char *enc_file)
-{
- xmlDocPtr doc = NULL;
- xmlNodePtr node = NULL;
- xmlSecEncCtxPtr encCtx = NULL;
- int res = -1;
-
- /* load template */
- doc = xmlParseFile(enc_file);
- if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)) {
- fprintf(stderr, "Error: unable to parse file \"%s\"\n", enc_file);
- goto done;
- }
-
- /* find start node */
- node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeEncryptedData, xmlSecEncNs);
- if (node == NULL) {
- fprintf(stderr, "Error: start node not found in \"%s\"\n", enc_file);
- goto done;
- }
-
- /* create encryption context */
- encCtx = xmlSecEncCtxCreate(mngr);
- if (encCtx == NULL) {
- fprintf(stderr, "Error: failed to create encryption context\n");
- goto done;
- }
-
- /* decrypt the data */
- if ((xmlSecEncCtxDecrypt(encCtx, node) < 0) || (encCtx->result == NULL)) {
- fprintf(stderr, "Error: decryption failed\n");
- goto done;
- }
-
- /* print decrypted data to stdout */
- if (encCtx->resultReplaced != 0) {
-
- fprintf(stdout, "*** after decryption ***\n");
- xmlDocFormatDump(stdout, doc, 1);
- fprintf(stdout, "************************\n");
-
- }
- else {
- fprintf(stdout, "Decrypted binary data (%d bytes):\n", xmlSecBufferGetSize(encCtx->result));
- if (xmlSecBufferGetData(encCtx->result) != NULL) {
- fwrite(xmlSecBufferGetData(encCtx->result),
- 1,
- xmlSecBufferGetSize(encCtx->result),
- stdout);
- }
- }
- fprintf(stdout, "\n");
-
- /* success */
- res = 0;
-
-done:
- /* cleanup */
- if (encCtx != NULL) {
- xmlSecEncCtxDestroy(encCtx);
- }
-
- if (doc != NULL) {
- xmlFreeDoc(doc);
- }
- return (res);
-}
-
-static int _soap_xmlsec_encrypt_file(xmlSecKeysMngrPtr mngr, const char *enc_file, const char *key_name)
-{
- xmlDocPtr doc = NULL;
- xmlNodePtr encDataNode = NULL;
- xmlNodePtr keyInfoNode = NULL;
- xmlNodePtr encKeyNode = NULL;
- xmlNodePtr keyInfoNode2 = NULL;
- xmlSecEncCtxPtr encCtx = NULL;
-
- doc = xmlParseFile(enc_file);
- if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL))
- {
- log_error2("xmlParseFile failed (%s)", enc_file);
- return -1;
- }
-
- fprintf(stdout, "*** before encryption ***\n");
- xmlDocFormatDump(stdout, doc, 1);
- fprintf(stdout, "*************************\n");
-
- encDataNode = xmlSecTmplEncDataCreate(doc, xmlSecTransformDes3CbcId, NULL, xmlSecTypeEncElement, NULL, NULL);
- if (encDataNode == NULL)
- {
- log_error1("xmlSecTmplEnvDataCreate failed");
- return -1;
- }
-
- if (xmlSecTmplEncDataEnsureCipherValue(encDataNode) == NULL)
- {
- log_error1("failed to add CipherValue node");
- return -1;
- }
-
- keyInfoNode = xmlSecTmplEncDataEnsureKeyInfo(encDataNode, NULL);
- if (keyInfoNode == NULL)
- {
- log_error1("failed to add KeyInfo node");
- return -1;
- }
-
- encKeyNode = xmlSecTmplKeyInfoAddEncryptedKey(keyInfoNode, xmlSecTransformRsaOaepId, NULL, NULL, NULL);
- if (encKeyNode == NULL)
- {
- log_error1("failed to add KeyInfo");
- return -1;
- }
-
- if (xmlSecTmplEncDataEnsureCipherValue(encKeyNode) == NULL)
- {
- log_error1("failed to add CipherValue node");
- return -1;
- }
-
- keyInfoNode2 = xmlSecTmplEncDataEnsureKeyInfo(encKeyNode, NULL);
- if (keyInfoNode2 == NULL)
- {
- log_error1("failed to add key info (2)\n");
- return -1;
- }
-
- // log_error2("adding key \"%s\"", key_name);
- if (xmlSecTmplKeyInfoAddKeyName(keyInfoNode2, key_name) == NULL)
- {
-
- log_error1("failed to add key name");
- return -1;
- }
-
- encCtx = xmlSecEncCtxCreate(mngr);
- if (encCtx == NULL)
- {
- log_error1("failed to create encryption context");
- return -1;
- }
-
- encCtx->encKey = xmlSecKeyGenerate(xmlSecKeyDataDesId, 192, xmlSecKeyDataTypeSession);
- if (encCtx->encKey == NULL)
- {
- log_error1("failed to generate session key");
- return -1;
- }
-
- fprintf(stdout, "*** before encryption ***\n");
- xmlDocFormatDump(stdout, doc, 1);
- fprintf(stdout, "*************************\n");
-
- if (xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, xmlDocGetRootElement(doc)) < 0)
- // if (xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, get_soap_body_content(xmlDocGetRootElement(doc))) < 0)
- {
- log_error1("encryption failed");
- return -1;
- }
-
- {
- FILE *fp;
-
- fp = fopen("test-enc-new.xml", "w");
- xmlDocDump(fp, doc);
- fclose(fp);
- }
- fprintf(stdout, "*** after encryption ***\n");
- xmlDocFormatDump(stdout, doc, 1);
- fprintf(stdout, "************************\n");
-
- if (encCtx != NULL)
- xmlSecEncCtxDestroy(encCtx);
-
- if (encDataNode != NULL)
- xmlFreeNode(encDataNode);
-
- if (doc != NULL)
- xmlFreeDoc(doc);
-
- return 0;
-}
-
-/**
- *
- * files_keys_store_find_key:
- *
- * @store: the pointer to simple keys store.
- * @name: the desired key name.
- * @keyInfoCtx: the pointer to <dsig:KeyInfo/> node processing context.
- *
- * Lookups key in the @store. The caller is responsible for destroying
- * returned key with #xmlSecKeyDestroy function.
- *
- * Returns pointer to key or NULL if key not found or an error occurs.
+ * @return pointer to key or NULL if key not found or an error occurs.
*
*/
static xmlSecKeyPtr
@@ -334,11 +135,12 @@ _soap_xmlsec_files_keys_store_find_key(xmlSecKeyStorePtr store, const xmlChar *
xmlURI *uri;
char *file;
- fprintf(stderr, "trying to find key \"%s\"\n", name);
+ log_info2("trying to find key \"%s\"\n", name);
/*
- * it's possible to do not have the key name or desired key type *
- * but we could do nothing in this case
+ * it's possible to do not have the key name or desired key type but we could
+ * do nothing in this case
+ *
*/
if (name == NULL)
{
@@ -488,7 +290,7 @@ _soap_xmlsec_create_key_manager(void)
if (keysStore == NULL)
{
log_error1("failed to create keys store");
- return herror_new("_soap_xmlxec_create_key_manager", 0, "failed to create keys store");
+ return herror_new("_soap_xmlxec_create_key_manager", XMLSEC_ERROR_KEYSTORE, "failed to create keys store");
}
/* create keys manager */
@@ -496,7 +298,7 @@ _soap_xmlsec_create_key_manager(void)
{
log_error1("failed to create keys manager");
xmlSecKeyStoreDestroy(keysStore);
- return herror_new("_soap_xmlsec_key_manager", 0, "failed to create keys manager");
+ return herror_new("_soap_xmlsec_key_manager", XMLSEC_ERROR_KEYMANAGER, "failed to create keys manager");
}
/*
@@ -509,7 +311,7 @@ _soap_xmlsec_create_key_manager(void)
xmlSecKeyStoreDestroy(keysStore);
xmlSecKeysMngrDestroy(_soap_xmlsec_key_manager);
_soap_xmlsec_key_manager = NULL;
- return herror_new("_soap_xmlsec_create_key_manager", 0, "failed to add keys store to keys manager");
+ return herror_new("_soap_xmlsec_create_key_manager", XMLSEC_ERROR_KEYMANAGER, "failed to add keys store to keys manager");
}
/* initialize crypto library specific data in keys manager */
@@ -518,7 +320,7 @@ _soap_xmlsec_create_key_manager(void)
log_error1("failed to initialize crypto data in keys manager");
xmlSecKeysMngrDestroy(_soap_xmlsec_key_manager);
_soap_xmlsec_key_manager = NULL;
- return herror_new("_soap_xmlsec_create_key_manager", 0, "failed to initialize crypto data in keys manager");
+ return herror_new("_soap_xmlsec_create_key_manager", XMLSEC_ERROR_KEYMANAGER, "failed to initialize crypto data in keys manager");
}
/* set the get key callback */
@@ -536,7 +338,7 @@ _soap_xmlsec_load_key(void)
if ((_soap_xmlsec_key = xmlSecCryptoAppKeyLoad(_soap_xmlsec_keyfile, xmlSecKeyDataFormatPem, _soap_xmlsec_password, NULL, NULL)) == NULL)
{
log_error2("xmlSecCryptoAppKeyLoad(\"%s\") failed", _soap_xmlsec_keyfile);
- return herror_new("_soap_xmlsec_load_key", 0, "xmlSecCryptoAppKeyLoad(\"%s\") failed", _soap_xmlsec_keyfile);
+ return herror_new("_soap_xmlsec_load_key", XMLSEC_ERROR_KEY, "xmlSecCryptoAppKeyLoad(\"%s\") failed", _soap_xmlsec_keyfile);
}
if (_soap_xmlsec_certfile)
@@ -545,7 +347,7 @@ _soap_xmlsec_load_key(void)
{
log_error2("xmlSecCryptoAppKeyCertLoad(\"%s\") failed", _soap_xmlsec_certfile);
xmlSecKeyDestroy(_soap_xmlsec_key);
- return herror_new("_soap_xmlsec_load_key", 0, "xmlSecCryptoAppKeyCertLoad(\"%s\") failed", _soap_xmlsec_certfile);
+ return herror_new("_soap_xmlsec_load_key", XMLSEC_ERROR_CERTIFICATE, "xmlSecCryptoAppKeyCertLoad(\"%s\") failed", _soap_xmlsec_certfile);
}
}
@@ -555,11 +357,11 @@ _soap_xmlsec_load_key(void)
{
xmlSecKeyDestroy(_soap_xmlsec_key);
log_error3("xmlSecKeySetName(\"%s\") failed (%i)", keyName, err);
- return herror_new("_soap_xmlsec_load_key", 0, "xmlSecKeySetName(\"%s\") failed (%i)", keyName, err);
+ return herror_new("_soap_xmlsec_load_key", XMLSEC_ERROR_KEY, "xmlSecKeySetName(\"%s\") failed (%i)", keyName, err);
}
- xmlSecKeyDebugXmlDump(_soap_xmlsec_key, stdout);
- xmlSecKeyDataDebugXmlDump(xmlSecKeyGetValue(_soap_xmlsec_key), stdout);
+// xmlSecKeyDebugXmlDump(_soap_xmlsec_key, stdout);
+// xmlSecKeyDataDebugXmlDump(xmlSecKeyGetValue(_soap_xmlsec_key), stdout);
return H_OK;
}
@@ -647,13 +449,13 @@ _soap_xmlsec_init(void)
if (xmlSecInit() < 0)
{
log_error1("xmlSecInit failed");
- return herror_new("soap_xmlsec_init", 0, "xmlSecInit failed");
+ return herror_new("soap_xmlsec_init", XMLSEC_ERROR_INIT, "xmlSecInit failed");
}
if (xmlSecCheckVersion() != 1)
{
log_error1("xmlSecCheckVersion failed, wrong xmlsec version");
- return herror_new("soap_xmlsec_init", 0, "Wrong xmlsec version");
+ return herror_new("soap_xmlsec_init", XMLSEC_ERROR_VERSION, "Wrong xmlsec version");
}
#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
@@ -661,20 +463,20 @@ _soap_xmlsec_init(void)
if (xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0)
{
log_error1("xmlSecCryptoDLLoadLibrary failed");
- return herror_new("soap_xmlsec_init", 0, "xmlSecCryptoDLLoadLibrary failed");
+ return herror_new("soap_xmlsec_init", XMLSEC_ERROR_DLLOAD, "xmlSecCryptoDLLoadLibrary failed");
}
#endif
if (xmlSecCryptoAppInit(NULL) < 0)
{
log_error1("xmlSecCryptoAppInit failed");
- return herror_new("soap_xmlsec_init", 0, "xmlSecCryptoAppInit failed");
+ return herror_new("soap_xmlsec_init", XMLSEC_ERROR_INIT, "xmlSecCryptoAppInit failed");
}
if (xmlSecCryptoInit() < 0)
{
log_error1("xmlSecCryptoInit failed");
- return herror_new("soap_xmlsec_init", 0, "xmlSecCryptoInit failed");
+ return herror_new("soap_xmlsec_init", XMLSEC_ERROR_INIT, "xmlSecCryptoInit failed");
}
if ((status = _soap_xmlsec_create_key_manager()) != H_OK)
@@ -686,7 +488,7 @@ _soap_xmlsec_init(void)
if ((err = pthread_mutex_init(&_soap_xmlsec_lock, NULL)) < 0)
{
log_error2("pthread_mutex_init failed (%s)", strerror(err));
- return herror_new("soap_xmlsec_init", 0, "pthread_mutex_init failed (%s)", strerror(err));
+ return herror_new("soap_xmlsec_init", XMLSEC_ERROR_INIT, "pthread_mutex_init failed (%s)", strerror(err));
}
if ((status = _soap_xmlsec_load_key()) != H_OK)
@@ -759,7 +561,7 @@ herror_t soap_xmlsec_sign(struct SoapCtx *context)
if (!(signNode = xmlSecTmplSignatureCreate(envelope->root->doc, xmlSecTransformExclC14NId, xmlSecTransformRsaSha1Id, NULL)))
{
log_error1("xmlSecTmplSignatureCreate failed");
- ret = herror_new("soap_xmlsec_sign", 0, "xmlSecTmplSignatureCreate failed");
+ ret = herror_new("soap_xmlsec_sign", XMLSEC_ERROR_SIGN_INIT, "xmlSecTmplSignatureCreate failed");
goto out;
}
@@ -777,28 +579,28 @@ herror_t soap_xmlsec_sign(struct SoapCtx *context)
if (!(refNode = xmlSecTmplSignatureAddReference(signNode, xmlSecTransformSha1Id, "#Body", NULL, NULL)))
{
log_error1("xmlSecTmplSignatureAddReference failed");
- ret = herror_new("soap_xmlsec_sign", 0, "xmlSecTmplSignatureAddReference failed");
+ ret = herror_new("soap_xmlsec_sign", XMLSEC_ERROR_SIGN_INIT, "xmlSecTmplSignatureAddReference failed");
goto out;
}
if (!(keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL)))
{
log_error1("xmlSecTmplSignatureEnsureKeyInfo failed");
- ret = herror_new("soap_xmlsec_sign", 0, "xmlSecTmplSignatureEnsureKeyInfo failed");
+ ret = herror_new("soap_xmlsec_sign", XMLSEC_ERROR_SIGN_INIT, "xmlSecTmplSignatureEnsureKeyInfo failed");
goto out;
}
if (xmlSecTmplKeyInfoAddKeyName(keyInfoNode, soap_server_get_name()) == NULL)
{
log_error1("xmlSecTmplKeyInfoAddKeyName failed");
- ret = herror_new("soap_xmlsec_sign", 0, "xmlSecTmplKeyInfoAddKeyName failed");
+ ret = herror_new("soap_xmlsec_sign", XMLSEC_ERROR_SIGN_INIT, "xmlSecTmplKeyInfoAddKeyName failed");
goto out;
}
if (!(dsigCtx = xmlSecDSigCtxCreate(_soap_xmlsec_key_manager)))
{
log_error1("xmlSecDSigCtxCreate failed");
- ret = herror_new("soap_xmlsec_sign", 0, "xmlSecDSigCtxCreate failed");
+ ret = herror_new("soap_xmlsec_sign", XMLSEC_ERROR_SIGN_INIT, "xmlSecDSigCtxCreate failed");
goto out;
}
@@ -807,7 +609,7 @@ herror_t soap_xmlsec_sign(struct SoapCtx *context)
if (xmlSecDSigCtxSign(dsigCtx, signNode) < 0)
{
log_error1("xmlSecDSigCtxSign failed");
- ret = herror_new("soap_xmlsec_sign", 0, "xmlSecDSigCtxSign failed");
+ ret = herror_new("soap_xmlsec_sign", XMLSEC_ERROR_SIGN, "xmlSecDSigCtxSign failed");
goto out;
}
@@ -821,6 +623,7 @@ out:
herror_t soap_xmlsec_encrypt(struct SoapCtx *context)
{
struct SoapEnv *envelope;
+ herror_t ret;
xmlNodePtr encDataNode = NULL;
xmlNodePtr keyInfoNode = NULL;
xmlNodePtr encKeyNode = NULL;
@@ -833,55 +636,70 @@ herror_t soap_xmlsec_encrypt(struct SoapCtx *context)
if (!_soap_xmlsec_enabled)
return H_OK;
+ ret = H_OK;
+
+ pthread_mutex_lock(&_soap_xmlsec_lock);
+
envelope = context->env;
doc = context->env->root->doc;
- fprintf(stdout, "*** before encryption ***\n");
- xmlDocFormatDump(stdout, doc, 1);
- fprintf(stdout, "*************************\n");
+ // fprintf(stdout, "*** before encryption ***\n");
+ // xmlDocFormatDump(stdout, doc, 1);
+ // fprintf(stdout, "*************************\n");
encDataNode = xmlSecTmplEncDataCreate(doc, xmlSecTransformDes3CbcId, NULL, xmlSecTypeEncElement, NULL, NULL);
if (encDataNode == NULL)
{
log_error1("xmlSecTmplEnvDataCreate failed");
- return herror_new("soap_xmlsec_encrypt", 0, "xmlSecTmplEnvDataCreate failed");
+ ret = herror_new("soap_xmlsec_encrypt", XMLSEC_ERROR_ENCRYPT_INIT, "xmlSecTmplEnvDataCreate failed");
+ goto out;
}
if (xmlSecTmplEncDataEnsureCipherValue(encDataNode) == NULL)
{
log_error1("failed to add CipherValue node");
- return herror_new("soap_xmlsec_encrypt", 0, "failed to add CipherValue node");
+ ret = herror_new("soap_xmlsec_encrypt", XMLSEC_ERROR_ENCRYPT_INIT, "failed to add CipherValue node");
+ goto out;
}
keyInfoNode = xmlSecTmplEncDataEnsureKeyInfo(encDataNode, NULL);
if (keyInfoNode == NULL)
{
log_error1("failed to add KeyInfo node");
- return herror_new("soap_xmlsec_encrypt", 0, "failed to add KeyInfo node");
+ ret = herror_new("soap_xmlsec_encrypt", XMLSEC_ERROR_ENCRYPT_INIT, "failed to add KeyInfo node");
+ goto out;
}
encKeyNode = xmlSecTmplKeyInfoAddEncryptedKey(keyInfoNode, xmlSecTransformRsaOaepId, NULL, NULL, NULL);
if (encKeyNode == NULL)
{
log_error1("failed to add KeyInfo");
- return herror_new("soap_xmlsec_encrypt", 0, "failed to add KeyInfo");
+ ret = herror_new("soap_xmlsec_encrypt", XMLSEC_ERROR_ENCRYPT_INIT, "failed to add KeyInfo");
+ goto out;
}
if (xmlSecTmplEncDataEnsureCipherValue(encKeyNode) == NULL)
{
log_error1("failed to add CipherValue node");
- return herror_new("soap_xmlsec_encrypt", 0, "failed to add CipherValue node");
+ ret = herror_new("soap_xmlsec_encrypt", XMLSEC_ERROR_ENCRYPT_INIT, "failed to add CipherValue node");
+ goto out;
}
keyInfoNode2 = xmlSecTmplEncDataEnsureKeyInfo(encKeyNode, NULL);
if (keyInfoNode2 == NULL)
{
log_error1("failed to add key info (2)\n");
- return herror_new("soap_xmlsec_enrypt", 0, "failed to add key info (2)");
+ ret = herror_new("soap_xmlsec_encrypt", XMLSEC_ERROR_ENCRYPT_INIT, "failed to add key info (2)");
+ goto out;
}
- to = soap_addressing_get_to_address(envelope);
+ if (!(to = soap_addressing_get_to_address(envelope)))
+ {
+ log_error1("cannot get to address");
+ ret = herror_new("soap_xmlsec_encrypt", XMLSEC_ERROR_ENCRYPT, "cannot get to address");
+ goto out;
+ }
xmlStrPrintf(buf, 256, "http://%s:%i/key.pem", to->server, to->port);
log_error2("adding key \"%s\"", buf);
xmlFreeURI(to);
@@ -889,76 +707,175 @@ herror_t soap_xmlsec_encrypt(struct SoapCtx *context)
if (xmlSecTmplKeyInfoAddKeyName(keyInfoNode2, buf) == NULL)
{
log_error2("failed to add key name \"%s\"", buf);
- return herror_new("soap_xmlsec_encrypt", 0, "failed to add key name \"%s\"", buf);
+ ret = herror_new("soap_xmlsec_encrypt", XMLSEC_ERROR_ENCRYPT_INIT, "failed to add key name \"%s\"", buf);
+ goto out;
}
encCtx = xmlSecEncCtxCreate(_soap_xmlsec_key_manager);
if (encCtx == NULL)
{
log_error1("failed to create encryption context");
- return herror_new("soap_xmlsec_encrypt", 0, "failed to create encryption context");
+ ret = herror_new("soap_xmlsec_encrypt", XMLSEC_ERROR_ENCRYPT_INIT, "failed to create encryption context");
+ goto out;
}
encCtx->encKey = xmlSecKeyGenerate(xmlSecKeyDataDesId, 192, xmlSecKeyDataTypeSession);
if (encCtx->encKey == NULL)
{
log_error1("failed to generate session key");
- return herror_new("soap_xmlsec_encrypt", 0, "failed to generate session key");
+ ret = herror_new("soap_xmlsec_encrypt", XMLSEC_ERROR_ENCRYPT_INIT, "failed to generate session key");
+ goto out;
}
- fprintf(stdout, "*** before encryption ***\n");
- xmlDocFormatDump(stdout, doc, 1);
- fprintf(stdout, "*************************\n");
+ // fprintf(stdout, "*** before encryption ***\n");
+ // xmlDocFormatDump(stdout, doc, 1);
+ // fprintf(stdout, "*************************\n");
if (xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, soap_env_get_method(envelope)) < 0)
- // if (xmlSecEncCtxXmlEncrypt(encCtx, encDataNode, get_soap_body_content(xmlDocGetRootElement(doc))) < 0)
{
log_error1("encryption failed");
- return herror_new("soap_xmlsec_encrypt", 0, "encryption failed");
+ ret = herror_new("soap_xmlsec_encrypt", XMLSEC_ERROR_ENCRYPT, "encryption failed");
+ goto out;
}
-/* {
- FILE *fp;
-
- fp = fopen("test-enc-new.xml", "w");
- xmlDocDump(fp, doc);
- fclose(fp);
- } */
+ // fprintf(stdout, "*** after encryption ***\n");
+ // xmlDocFormatDump(stdout, doc, 1);
+ // fprintf(stdout, "************************\n");
- fprintf(stdout, "*** after encryption ***\n");
- xmlDocFormatDump(stdout, doc, 1);
- fprintf(stdout, "************************\n");
+out:
if (encCtx != NULL)
xmlSecEncCtxDestroy(encCtx);
- return H_OK;
+ pthread_mutex_unlock(&_soap_xmlsec_lock);
+
+ return ret;
}
herror_t soap_xmlsec_decrypt(struct SoapCtx *context)
{
struct SoapEnv *envelope;
+ herror_t ret;
+ xmlNodePtr method;
+ xmlDocPtr doc = NULL;
+ xmlNodePtr node = NULL;
+ xmlSecEncCtxPtr encCtx = NULL;
if (!_soap_xmlsec_enabled)
return H_OK;
+ ret = H_OK;
+
envelope = context->env;
- log_error1("not implemented");
- return herror_new("soap_xmlsec_decrupt", 0, "not implemented");
+ if (!(method = soap_env_get_method(envelope)))
+ {
+ log_error1("cannot find messages method");
+ return herror_new("soap_xmlsec_decrypt", 0, "cannot find message method");
+ }
+
+ if (xmlStrcmp(method->name, BAD_CAST "EncryptedData"))
+ {
+ log_error2("message doesn't contain encrypted data (%s)", method->name);
+ return H_OK;
+ }
+
+ if (xmlStrcmp(method->ns->href, "http://www.w3.org/2001/04/xmlenc#"))
+ {
+ log_error2("message encryption isn't understood (%s)", method->ns->href);
+ return herror_new("soap_xmlsec_decrypt", 0, "message encryption isn't understood (%s)", method->ns->href);
+ }
+
+ doc = envelope->root->doc;
+
+ /* XXX already checked... */
+ node = xmlSecFindNode(envelope->root, xmlSecNodeEncryptedData, xmlSecEncNs);
+ if (node == NULL)
+ {
+ log_error1("start node not found");
+ ret = herror_new("soap_xmlsec_decrypt", 0, "start node not found");
+ goto done;
+ }
+
+ /* create encryption context */
+ encCtx = xmlSecEncCtxCreate(_soap_xmlsec_key_manager);
+ if (encCtx == NULL)
+ {
+ log_error1("failed to create encryption context");
+ ret = herror_new("soap_xmlsec_decrypt", 0, "failed to create encryption context");
+ goto done;
+ }
+
+ /* decrypt the data */
+ if ((xmlSecEncCtxDecrypt(encCtx, node) < 0) || (encCtx->result == NULL))
+ {
+ log_error1("decryption failed");
+ ret = herror_new("soap_xmlsec_decrypt", 0, "decryption failed");
+ goto done;
+ }
+
+ /* print decrypted data to stdout */
+ /* if (encCtx->resultReplaced != 0)
+ {
+ fprintf(stdout, "*** after decryption ***\n");
+ xmlDocFormatDump(stdout, doc, 1);
+ fprintf(stdout, "************************\n");
+ }
+ else
+ {
+ fprintf(stdout, "Decrypted binary data (%d bytes):\n", xmlSecBufferGetSize(encCtx->result));
+ if (xmlSecBufferGetData(encCtx->result) != NULL)
+ {
+ fwrite(xmlSecBufferGetData(encCtx->result), 1, xmlSecBufferGetSize(encCtx->result), stdout);
+ }
+ }
+ fprintf(stdout, "\n"); */
+
+done:
+
+ if (encCtx != NULL)
+ {
+ xmlSecEncCtxDestroy(encCtx);
+ }
+
+ return ret;
}
herror_t soap_xmlsec_verify(struct SoapCtx *context)
{
struct SoapEnv *envelope;
+ xmlNodePtr walker;
if (!_soap_xmlsec_enabled)
return H_OK;
envelope = context->env;
- log_error1("not implemented");
- return herror_new("soap_xmlsec_verify", 0, "not implemented");
+ if (!envelope->header)
+ {
+ log_error1("message doesn't contain a SOAP header");
+ return herror_new("soap_xmlsec_verify", 0, "message doesn't contain a SOAP header");
+ }
+
+ for (walker=envelope->header->children; walker; walker=walker->next)
+ {
+ if (walker->type == XML_ELEMENT_NODE)
+ {
+ if (!xmlStrcmp(walker->name, "Signature"))
+ {
+ if (!xmlStrcmp(walker->ns->href, "http://schemas.xmlsoap.org/soap/security/2000-12"))
+ {
+ /* XXX do it */
+ }
+ else
+ {
+ log_error2("message signature isn't understood (%s)", walker->ns->href);
+ return herror_new("soap_xmlsec_verify", 0, "message signature isn't understood (%s)", walker->ns->href);
+ }
+ }
+ }
+ }
+ return H_OK;
}
void soap_xmlsec_destroy(void)
diff --git a/libcsoap/soap-xmlsec.h b/libcsoap/soap-xmlsec.h
index 9943498..4a6209c 100644
--- a/libcsoap/soap-xmlsec.h
+++ b/libcsoap/soap-xmlsec.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: soap-xmlsec.h,v 1.3 2006/11/28 23:45:57 m0gg Exp $
+ * $Id: soap-xmlsec.h,v 1.4 2006/11/29 11:04:25 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2006 Heiko Ronsdorf
@@ -31,7 +31,7 @@
* This module is implemented using the xmlsec1 library.
*
* @author H. Ronsdorf
- * @version $Revision: 1.3 $
+ * @version $Revision: 1.4 $
*
* @see http://www.w3.org/TR/SOAP-dsig/,
* http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wss,
@@ -71,6 +71,20 @@
*/
#define CSOAP_XMLSEC_CERTFILE "-CSOAPcertfile"
+#define XMLSEC_ERROR 5100
+#define XMLSEC_ERROR_GENERIC (XMLSEC_ERROR + 0)
+#define XMLSEC_ERROR_KEYSTORE (XMLSEC_ERROR + 10)
+#define XMLSEC_ERROR_KEYMANAGER (XMLSEC_ERROR + 20)
+#define XMLSEC_ERROR_KEY (XMLSEC_ERROR + 30)
+#define XMLSEC_ERROR_CERTIFICATE (XMLSEC_ERROR + 40)
+#define XMLSEC_ERROR_INIT (XMLSEC_ERROR + 50)
+#define XMLSEC_ERROR_VERSION (XMLSEC_ERROR + 60)
+#define XMLSEC_ERROR_DLLOAD (XMLSEC_ERROR + 70)
+#define XMLSEC_ERROR_SIGN (XMLSEC_ERROR + 80)
+#define XMLSEC_ERROR_SIGN_INIT (XMLSEC_ERROR + 90)
+#define XMLSEC_ERROR_ENCRYPT (XMLSEC_ERROR + 100)
+#define XMLSEC_ERROR_ENCRYPT_INIT (XMLSEC_ERROR + 110)
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -101,24 +115,68 @@ extern herror_t soap_xmlsec_client_init_args(int argc, char **argv);
/**
*
- * Sign a XML document contained in a SOAP Envelope. The key specified on the
- * commandline is used for signating the document.
+ * Sign a XML document contained in a SOAP Envelope with the key specified on
+ * the commandline. Our way to create a <SOAP-SEC:Signature> header entry is as
+ * follows:
+ *
+ * # Prepare the target SOAP Envelope with the body and necessary headers.
+ * # Create a template of a <ds:Signature> element. The template is assumed to
+ * contain empty contents for <ds:DigestValue> or <ds:SignatureValue> elements,
+ * but contains appropriate values for the elements such as
+ * <ds:SignatureMethod> and <ds:Reference> required to calculate them.
+ * # Create a new header entry <SOAP-SEC:Signature> and add the template to this
+ * entry.
+ * # Add the header entry <SOAP-SEC:Signature> to the SOAP Header.
+ * # Add the SOAP "actor" and "mustUnderstand" attributes to the entry, if
+ * necessary.
+ * # Calculate the <ds:DigestValue> and <ds:SignatureValue> elements according
+ * to the core generation of the XML-Signature specification.
+ *
+ * XPath filtering can be used to specify objects to be signed, as described in
+ * the XML-Signature specification. However, since the SOAP message exchange
+ * model allows intermediate applications to modify the Envelope (add or delete
+ * a header entry, for example), XPath filtering does not always result in the
+ * same objects after message delivery. Care should be taken in using XPath
+ * filtering so that there is no subsequent validation failure due to such
+ * modifications.
+ *
+ * The transform http://www.w3.org/2000/09/xmldsig#enveloped-signature defined
+ * in the XML-Signature specification may be useful when signing the entire
+ * Envelope including other header entries, if any.
*
* @param envelope The SOAP envelope to be signed.
*
* @return H_OK on success
*
+ * @see http://www.w3.org/TR/SOAP-dsig/,
+ * http://www.w3.org/TR/xmldsig-core/
+ *
*/
extern herror_t soap_xmlsec_sign(struct SoapCtx *context);
/**
*
- * Verify a XML documents signature contained in a SOAP Envelope.
+ * Verify a XML documents signature contained in a SOAP Envelope. The validation
+ * of a <SOAP-SEC:Signature> header entry fails if:
+ *
+ * # The syntax of the content of the header entry does not conform to SOAP
+ * Security Extensions: Digital Signature specification, or
+ * # The validation of the signature contained in the header entry fails
+ * according to the core validation of the XML-Signature specification, or
+ * # The receiving application program rejects the signature for some reason
+ * (e.g., the signature is created by an untrusted key).
+ *
+ * If the validation of the signature header entry fails, applications MAY report
+ * the failure to the sender. It is out of the scope of this library how to deal
+ * with it.
*
* @param envelope The SOAP envelope to be verified.
*
* @return H_OK on success
*
+ * @see http://www.w3.org/TR/SOAP-dsig/,
+ * http://www.w3.org/TR/xmldsig-core/
+ *
*/
extern herror_t soap_xmlsec_verify(struct SoapCtx *context);