summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar m0gg2006-11-28 23:45:57 +0000
committerGravatar m0gg2006-11-28 23:45:57 +0000
commit9a0670ad01e00ab01cfb4f308f1b124941968fa2 (patch)
tree616729b1bcd2c837eee563e904faac091f5cb813
parent17d9b98c8525c74cd83a421f151062825fe66890 (diff)
downloadcsoap-9a0670ad01e00ab01cfb4f308f1b124941968fa2.tar.gz
csoap-9a0670ad01e00ab01cfb4f308f1b124941968fa2.tar.bz2
XML signature improvements
-rw-r--r--TODO3
-rw-r--r--examples/csoap/simpleclient.c4
-rw-r--r--examples/csoap/simpleserver.c4
-rw-r--r--libcsoap/soap-addressing.c4
-rw-r--r--libcsoap/soap-addressing.h6
-rw-r--r--libcsoap/soap-client.c67
-rw-r--r--libcsoap/soap-env.h3
-rw-r--r--libcsoap/soap-nhttp.c8
-rw-r--r--libcsoap/soap-server.c21
-rw-r--r--libcsoap/soap-transport.c37
-rw-r--r--libcsoap/soap-xmlsec.c830
-rw-r--r--libcsoap/soap-xmlsec.h84
-rw-r--r--nanohttp/nanohttp-base64.c25
-rw-r--r--nanohttp/nanohttp-base64.h35
-rw-r--r--nanohttp/nanohttp-client.c4
-rwxr-xr-xnanohttp/nanohttp-mime.h14
-rw-r--r--nanohttp/nanohttp-server.c4
-rw-r--r--nanohttp/nanohttp-server.h4
18 files changed, 1044 insertions, 113 deletions
diff --git a/TODO b/TODO
index 86305a1..3a3801c 100644
--- a/TODO
+++ b/TODO
@@ -1,4 +1,4 @@
-$Id: TODO,v 1.4 2006/11/27 12:47:27 m0gg Exp $
+$Id: TODO,v 1.5 2006/11/28 23:45:57 m0gg Exp $
-------------------------------------------------------------------------------
- Get rid of #ifdef HAVE_SSL in nanohttp-socket.c
@@ -12,4 +12,5 @@ $Id: TODO,v 1.4 2006/11/27 12:47:27 m0gg Exp $
- XML encryption/signature verification
- Check portability to Win32/Linux/MaxOS (only tested on FreeBSD 6.2)
- API documentation
+- Add reference to http://www.w3.org/TR/SOAP-attachments
diff --git a/examples/csoap/simpleclient.c b/examples/csoap/simpleclient.c
index 10924d2..03beaae 100644
--- a/examples/csoap/simpleclient.c
+++ b/examples/csoap/simpleclient.c
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: simpleclient.c,v 1.18 2006/11/26 20:13:05 m0gg Exp $
+ * $Id: simpleclient.c,v 1.19 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: CSOAP examples project
* Copyright (C) 2003-2004 Ferhat Ayaz
@@ -42,7 +42,7 @@ main(int argc, char **argv)
struct SoapCtx *ctx, *ctx2;
herror_t err;
- hlog_set_level(HLOG_VERBOSE);
+ // hlog_set_level(HLOG_VERBOSE);
err = soap_client_init_args(argc, argv);
if (err != H_OK)
diff --git a/examples/csoap/simpleserver.c b/examples/csoap/simpleserver.c
index 5803a33..676be5f 100644
--- a/examples/csoap/simpleserver.c
+++ b/examples/csoap/simpleserver.c
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: simpleserver.c,v 1.26 2006/11/26 20:13:05 m0gg Exp $
+ * $Id: simpleserver.c,v 1.27 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: CSOAP examples project
* Copyright (C) 2003-2004 Ferhat Ayaz
@@ -89,7 +89,7 @@ main(int argc, char **argv)
herror_t err;
struct SoapRouter *router;
- hlog_set_level(HLOG_VERBOSE);
+ // hlog_set_level(HLOG_VERBOSE);
if ((err = soap_server_init_args(argc, argv)) != H_OK)
{
diff --git a/libcsoap/soap-addressing.c b/libcsoap/soap-addressing.c
index 2069bd7..cde31ec 100644
--- a/libcsoap/soap-addressing.c
+++ b/libcsoap/soap-addressing.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: soap-addressing.c,v 1.7 2006/11/26 20:13:05 m0gg Exp $
+* $Id: soap-addressing.c,v 1.8 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2006 Heiko Ronsdorf
@@ -451,7 +451,7 @@ soap_addressing_set_from(struct SoapEnv *envelope, xmlNodePtr address)
}
xmlNodePtr
-soap_addressing_set_from_string(struct SoapEnv *envelope, const char *from)
+soap_addressing_set_from_address_string(struct SoapEnv *envelope, const char *from)
{
xmlURI *uri;
xmlNodePtr ret;
diff --git a/libcsoap/soap-addressing.h b/libcsoap/soap-addressing.h
index 7b6aed1..fa04038 100644
--- a/libcsoap/soap-addressing.h
+++ b/libcsoap/soap-addressing.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: soap-addressing.h,v 1.7 2006/11/27 12:47:27 m0gg Exp $
+ * $Id: soap-addressing.h,v 1.8 2006/11/28 23:45:57 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.7 $
+ * @version $Revision: 1.8 $
*
* @see http://www.w3.org/TR/ws-addr-core/,
* http://www.w3.org/TR/REC-xml-names/
@@ -233,7 +233,7 @@ xmlURI *soap_addressing_get_from_address(struct SoapEnv *envelope);
xmlNodePtr soap_addressing_set_from(struct SoapEnv *envelope, xmlNodePtr address);
xmlNodePtr soap_addressing_set_from_address(struct SoapEnv *envelope, xmlURI *address);
-xmlNodePtr soap_addressing_set_from_string(struct SoapEnv *envelope, const char *from);
+xmlNodePtr soap_addressing_set_from_address_string(struct SoapEnv *envelope, const char *from);
xmlNodePtr soap_addressing_get_fault_to(struct SoapEnv *envelope);
xmlURI *soap_addressing_get_fault_to_address(struct SoapEnv *envelope);
diff --git a/libcsoap/soap-client.c b/libcsoap/soap-client.c
index 5d34f8f..416054c 100644
--- a/libcsoap/soap-client.c
+++ b/libcsoap/soap-client.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: soap-client.c,v 1.31 2006/11/25 15:06:57 m0gg Exp $
+* $Id: soap-client.c,v 1.32 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -38,12 +38,31 @@
#include "soap-service.h"
#include "soap-router.h"
#include "soap-transport.h"
+#ifdef HAVE_XMLSEC1
+#include "soap-xmlsec.h"
+#endif
#include "soap-client.h"
herror_t
soap_client_init_args(int argc, char **argv)
{
- return soap_transport_client_init_args(argc, argv);
+ herror_t status;
+
+#ifdef HAVE_XMLSEC1
+ if ((status = soap_xmlsec_client_init_args(argc, argv)) != H_OK)
+ {
+ log_error2("soap_xmlsec_client_init_args failed (%s)", herror_message(status));
+ return status;
+ }
+#endif
+
+ if ((status = soap_transport_client_init_args(argc, argv)) != H_OK)
+ {
+ log_error2("soap_transport_client_init_args failed (%s)", herror_message(status));
+ return status;
+ }
+
+ return H_OK;
}
void
@@ -57,6 +76,7 @@ soap_client_destroy(void)
herror_t
soap_client_invoke(struct SoapCtx *req, struct SoapCtx **res, const char *url, const char *action)
{
+ herror_t status;
char *id;
log_verbose2("action = \"%s\"", action);
@@ -65,10 +85,49 @@ soap_client_invoke(struct SoapCtx *req, struct SoapCtx **res, const char *url, c
log_verbose2("url = \"%s\"", url);
soap_addressing_set_to_address_string(req->env, url);
+ log_verbose2("from = \"%s\"", soap_transport_get_name());
+ soap_addressing_set_from_address_string(req->env, soap_transport_get_name());
+
soap_addressing_set_message_id_string(req->env, NULL);
id = soap_addressing_get_message_id_string(req->env);
- log_verbose2("message id = \"%s\"", id);
+ log_verbose2("generated message id = \"%s\"", id);
free(id);
- return soap_transport_client_invoke(req, res);
+#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 ((status = soap_xmlsec_sign(req)) != H_OK)
+ {
+ log_error2("soap_xmlsec_sign failed (%s)", herror_message(status));
+ return status;
+ }
+#endif
+
+ if ((status = soap_transport_client_invoke(req, res)) != H_OK)
+ {
+ log_error2("soap_transport_client_invoke failed (%s)", herror_message(status));
+ return status;
+ }
+
+#ifdef HAVE_XMLSEC1
+ if ((status = soap_xmlsec_verify(*res)) != H_OK)
+ {
+ log_error2("soap_xmlsec_verify failed (%s)", herror_message(status));
+ return status;
+ }
+
+ if ((status = soap_xmlsec_decrypt(*res)) != H_OK)
+ {
+ log_error2("soap_xmlsec_decrypt failed (%s)", herror_message(status));
+ return status;
+ }
+#endif
+
+ return H_OK;
}
diff --git a/libcsoap/soap-env.h b/libcsoap/soap-env.h
index d1c0d3e..45f013a 100644
--- a/libcsoap/soap-env.h
+++ b/libcsoap/soap-env.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: soap-env.h,v 1.19 2006/11/27 10:49:57 m0gg Exp $
+ * $Id: soap-env.h,v 1.20 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -372,7 +372,6 @@ extern void soap_env_free(struct SoapEnv *env);
*/
extern xmlNodePtr soap_env_get_body(struct SoapEnv * env);
-
/**
*
* Get the xml node pointing to SOAP method (call)
diff --git a/libcsoap/soap-nhttp.c b/libcsoap/soap-nhttp.c
index 84a9ddc..fe5539d 100644
--- a/libcsoap/soap-nhttp.c
+++ b/libcsoap/soap-nhttp.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: soap-nhttp.c,v 1.5 2006/11/26 20:13:05 m0gg Exp $
+* $Id: soap-nhttp.c,v 1.6 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -195,12 +195,12 @@ soap_nhttp_process(httpd_conn_t * conn, struct hrequest_t * req)
xmlFree(uri);
}
- xmlDocDump(stdout, ctx->env->root->doc);
+ xmlDocFormatDump(stdout, ctx->env->root->doc, 1);
soap_ctx_add_files(ctx, req->attachments);
/* only local part is interesting... */
- soap_addressing_set_to_address_string(ctx->env, req->path);
+ // soap_addressing_set_to_address_string(ctx->env, req->path);
soap_transport_process(ctx, &response);
@@ -285,7 +285,7 @@ _soap_nhttp_client_invoke(void *unused, struct SoapCtx *request, struct SoapCtx
xmlNodeDump(buffer, request->env->root->doc, request->env->root, 1, 0);
content = (char *) xmlBufferContent(buffer);
- xmlDocDump(stdout, request->env->root->doc);
+ xmlDocFormatDump(stdout, request->env->root->doc, 1);
/* Transport via HTTP */
if (!(conn = httpc_new()))
diff --git a/libcsoap/soap-server.c b/libcsoap/soap-server.c
index cee9643..e40c798 100644
--- a/libcsoap/soap-server.c
+++ b/libcsoap/soap-server.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: soap-server.c,v 1.33 2006/11/26 20:13:05 m0gg Exp $
+* $Id: soap-server.c,v 1.34 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -118,7 +118,7 @@ _soap_server_fillup_header(struct SoapEnv *envelope)
xmlFreeURI(uri);
if (!(uri = soap_addressing_get_from_address(envelope)))
- soap_addressing_set_from_string(envelope, soap_server_get_name());
+ soap_addressing_set_from_address_string(envelope, soap_server_get_name());
else
xmlFreeURI(uri);
@@ -144,8 +144,8 @@ soap_server_process(struct SoapCtx *request, struct SoapCtx **response)
{
char buffer[1054];
const char *urn;
+ xmlURI *uri;
const char *method;
- char *to;
struct SoapRouter *router;
SoapService *service;
herror_t err;
@@ -161,10 +161,10 @@ soap_server_process(struct SoapCtx *request, struct SoapCtx **response)
if ((urn = soap_env_find_urn(request->env)))
{
log_verbose2("urn: \"%s\"", urn);
- if ((to = soap_addressing_get_to_address_string(request->env)))
+ if ((uri = soap_addressing_get_to_address(request->env)))
{
- log_verbose2("searching router for \"%s\"", to);
- if ((router = soap_server_find_router(to)))
+ log_verbose2("searching router for \"%s\"", uri->path);
+ if ((router = soap_server_find_router(uri->path)))
{
log_verbose2("router: %p", router);
if ((service = soap_router_find_service(router, urn, method)))
@@ -193,11 +193,10 @@ soap_server_process(struct SoapCtx *request, struct SoapCtx **response)
}
else
{
- sprintf(buffer, "no router for context \"%s\" found", to);
+ sprintf(buffer, "no router for context \"%s\" found", uri->path);
_soap_server_env_new_with_fault(buffer, "The method is unknown by the server", &((*response)->env));
- free(to);
}
- free(to);
+ xmlFreeURI(uri);
}
else
{
@@ -231,9 +230,9 @@ soap_server_init_args(int argc, char **argv)
}
#ifdef HAVE_XMLSEC1
- if ((status = soap_xmlsec_init_args(argc, argv)) != H_OK)
+ if ((status = soap_xmlsec_server_init_args(argc, argv)) != H_OK)
{
- log_error2("soap_xmlsec_init_args failed (%s)", herror_message(status));
+ log_error2("soap_xmlsec_server_init_args failed (%s)", herror_message(status));
return status;
}
#endif
diff --git a/libcsoap/soap-transport.c b/libcsoap/soap-transport.c
index 3cd46e8..7d54ced 100644
--- a/libcsoap/soap-transport.c
+++ b/libcsoap/soap-transport.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: soap-transport.c,v 1.5 2006/11/26 20:13:05 m0gg Exp $
+* $Id: soap-transport.c,v 1.6 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2007 Heiko Ronsdorf
@@ -110,11 +110,27 @@ soap_transport_process(struct SoapCtx *request, struct SoapCtx **response)
return soap_server_process(request, response);
}
+static herror_t
+_soap_transport_set_name(void)
+{
+ static int set = 0;
+ char hostname[256];
+
+ if (set)
+ return H_OK;
+
+ gethostname(hostname, 256);
+ sprintf(soap_transport_name, "%s://%s:%i", soap_nhttp_get_protocol(), hostname, soap_nhttp_get_port());
+
+ set = 1;
+
+ return H_OK;
+}
+
herror_t
soap_transport_server_init_args(int argc, char **argv)
{
herror_t status;
- char hostname[256];
if ((status = soap_nhttp_server_init_args(argc, argv)) != H_OK)
{
@@ -128,8 +144,11 @@ soap_transport_server_init_args(int argc, char **argv)
return status;
}
- gethostname(hostname, 256);
- sprintf(soap_transport_name, "%s://%s:%i", soap_nhttp_get_protocol(), hostname, soap_nhttp_get_port());
+ if ((status = _soap_transport_set_name()) != H_OK)
+ {
+ log_error2("_soap_transport_set_name failed (%s)", herror_message(status));
+ return status;
+ }
return H_OK;
}
@@ -233,6 +252,12 @@ soap_transport_client_init_args(int argc, char **argv)
return status;
}
+ if ((status = _soap_transport_set_name()) != H_OK)
+ {
+ log_error2("_soap_transport_set_name failed (%s)", herror_message(status));
+ return status;
+ }
+
return H_OK;
}
@@ -244,7 +269,7 @@ soap_transport_client_invoke(struct SoapCtx *request, struct SoapCtx **response)
xmlURI *dest;
log_verbose1(__FUNCTION__);
- xmlDocDump(stdout, request->env->root->doc);
+ xmlDocFormatDump(stdout, request->env->root->doc, 1);
dest = soap_addressing_get_to_address(request->env);
@@ -260,8 +285,10 @@ soap_transport_client_invoke(struct SoapCtx *request, struct SoapCtx **response)
return ret;
}
}
+
ret = herror_new("soap_transport_client_invoke", 0, "no transport service found for \"%s\"", dest->scheme);
xmlFreeURI(dest);
+
return ret;
}
diff --git a/libcsoap/soap-xmlsec.c b/libcsoap/soap-xmlsec.c
index 07e12fe..75cc187 100644
--- a/libcsoap/soap-xmlsec.c
+++ b/libcsoap/soap-xmlsec.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: soap-xmlsec.c,v 1.3 2006/11/25 17:03:20 m0gg Exp $
+* $Id: soap-xmlsec.c,v 1.4 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -25,6 +25,14 @@
#include <config.h>
#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
@@ -33,6 +41,22 @@
#include <string.h>
#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#endif
@@ -40,30 +64,50 @@
#include <libxml/tree.h>
#include <libxml/uri.h>
#include <libxml/parser.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/xmlstring.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
+#ifndef XMLSEC_NO_XSLT
+#include <libxslt/xslt.h>
+#endif
+
#include <xmlsec/xmlsec.h>
#include <xmlsec/xmltree.h>
+#include <xmlsec/xmlenc.h>
#include <xmlsec/xmldsig.h>
#include <xmlsec/templates.h>
#include <xmlsec/crypto.h>
#include <xmlsec/errors.h>
-#include <nanohttp/nanohttp-error.h>
#include <nanohttp/nanohttp-logging.h>
+#include <nanohttp/nanohttp-error.h>
+#include <nanohttp/nanohttp-common.h>
+#include <nanohttp/nanohttp-stream.h>
+#include <nanohttp/nanohttp-request.h>
+#include <nanohttp/nanohttp-response.h>
+#include <nanohttp/nanohttp-client.h>
+#include <nanohttp/nanohttp-server.h>
#include "soap-env.h"
#include "soap-ctx.h"
#include "soap-service.h"
#include "soap-router.h"
#include "soap-server.h"
+#include "soap-transport.h"
#include "soap-addressing.h"
#include "soap-xmlsec.h"
+static int _soap_xmlsec_enabled = 0;
static pthread_mutex_t _soap_xmlsec_lock;
-static xmlSecKeyPtr _soap_xmlsec_sign_key;
-static int _soap_xmlsec_enabled;
+
+static char *_soap_xmlsec_keyfile = NULL;
+static char *_soap_xmlsec_password = NULL;
+static char *_soap_xmlsec_certfile = NULL;
+
+static xmlSecKeysMngrPtr _soap_xmlsec_key_manager = NULL;
+static xmlSecKeyPtr _soap_xmlsec_key = NULL;
static void _soap_xmlsec_error_callback(const char *file, int line, const char *func, const char *errorObject, const char *errorSubject, int reason, const char *msg)
{
@@ -72,62 +116,544 @@ static void _soap_xmlsec_error_callback(const char *file, int line, const char *
return;
}
+/**
+ *
+ * decrypt_file:
+ *
+ * @mngr: the pointer to keys manager.
+ * @enc_file: the encrypted XML file name.
+ *
+ * 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.
+ *
+ */
+static xmlSecKeyPtr
+_soap_xmlsec_files_keys_store_find_key(xmlSecKeyStorePtr store, const xmlChar * name, xmlSecKeyInfoCtxPtr keyInfoCtx)
+{
+ xmlSecKeyPtr key;
+ xmlURI *uri;
+ char *file;
+
+ fprintf(stderr, "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
+ */
+ if (name == NULL)
+ {
+ printf("key name is NULL\n");
+ return NULL;
+ }
+
+ if (keyInfoCtx->keyReq.keyId == xmlSecKeyDataIdUnknown)
+ {
+ printf("keyReq.keyID == xmlSecKeyDataIdUnkown\n");
+ return NULL;
+ }
+
+ if (!(uri = xmlParseURI(name)))
+ {
+ printf("xmlParseURI failed\n");
+ return NULL;
+ }
+
+ // printf("uri->scheme=\"%s\"\n", uri->scheme);
+ // printf("uri->server=\"%s\"\n", uri->server);
+ // printf("uri->port=\"%i\"\n", uri->port);
+ // printf("uri->path=\"%s\"\n", uri->path);
+
+ {
+ char *tmp;
+ char buf[4096];
+ FILE *fp;
+
+ if (!(tmp = getenv("CSOAP_TEMP")))
+ {
+ tmp = "/tmp";
+ }
+ // printf("tmp = \"%s\"\n", tmp);
+
+ sprintf(buf, "%s/csoap-XXXXXX-key.pem", tmp);
+ // printf("buf = \"%s\"\n", buf);
+
+ if (mkstemps(buf, 8) < 0)
+ {
+ printf("mkstemps failed (%s)", strerror(errno));
+ return NULL;
+ }
+
+ // printf("fopen(\"%s\")\n", buf);
+ file = strdup(buf);
+
+ if (!(fp = fopen(buf, "w")))
+ {
+ printf("fopen failed (%s)\n", strerror(errno));
+ return NULL;
+ }
+
+ if (!strcmp("https", uri->scheme) || !strcmp("http", uri->scheme))
+ {
+ size_t len;
+ httpc_conn_t *conn;
+ hresponse_t *res;
+ herror_t status;
+
+ conn = httpc_new();
+
+ if ((status = (httpc_get(conn, &res, name))) != H_OK)
+ {
+ log_error2("httpc_get failed (%s)", herror_message(status));
+ herror_release(status);
+ return NULL;
+ }
+
+ while (http_input_stream_is_ready(res->in))
+ {
+ len = http_input_stream_read(res->in, buf, 4096);
+ fwrite(buf, len, 1, fp);
+ }
+ hresponse_free(res);
+
+ httpc_free(conn);
+ }
+ fclose(fp);
+ }
+
+ if ((keyInfoCtx->keyReq.keyId == xmlSecKeyDataDsaId) || (keyInfoCtx->keyReq.keyId == xmlSecKeyDataRsaId)) {
+ /*
+ * load key from a pem file, if key is not found then it's an
+ * error (is it?)
+ */
+ key = xmlSecCryptoAppKeyLoad(file, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
+ if (key == NULL) {
+ fprintf(stderr, "Error: failed to load public pem key from \"%s\"\n", name);
+ return (NULL);
+ }
+ }
+ else {
+ /*
+ * otherwise it's a binary key, if key is not found then it's
+ * an error (is it?)
+ */
+ key = xmlSecKeyReadBinaryFile(keyInfoCtx->keyReq.keyId, file);
+ if (key == NULL) {
+ fprintf(stderr, "Error: failed to load key from binary file \"%s\"\n", name);
+ return (NULL);
+ }
+ }
+
+ /* set key name */
+ if (xmlSecKeySetName(key, name) < 0) {
+ fprintf(stderr, "Error: failed to set key name for key from \"%s\"\n", name);
+ xmlSecKeyDestroy(key);
+ return (NULL);
+ }
+
+ if (unlink(file) < 0)
+ {
+ log_error2("unlink file failed (%s)", strerror(errno));
+ }
+ free(file);
+
+ return (key);
+}
+
+static xmlSecKeyStoreKlass _soap_xmlsec_files_keys_store_klass =
+{
+ sizeof(xmlSecKeyStoreKlass),
+ sizeof(xmlSecKeyStore),
+ BAD_CAST "uri-based-keys-store", /* const xmlChar* name; */
+ NULL, /* xmlSecKeyStoreInitializeMethod initialize; */
+ NULL, /* xmlSecKeyStoreFinalizeMethod finalize; */
+ _soap_xmlsec_files_keys_store_find_key, /* xmlSecKeyStoreFindKeyMethod findKey; */
+ /* reserved for the future */
+ NULL, /* void* reserved0; */
+ NULL, /* void* reserved1; */
+};
+
+static inline xmlSecKeyStoreId
+_soap_xmlsec_files_keys_store_get_klass(void)
+{
+ return (&_soap_xmlsec_files_keys_store_klass);
+}
+
+static herror_t
+_soap_xmlsec_create_key_manager(void)
+{
+ xmlSecKeyStorePtr keysStore;
+
+ /* create files based keys store */
+ keysStore = xmlSecKeyStoreCreate(_soap_xmlsec_files_keys_store_get_klass());
+ if (keysStore == NULL)
+ {
+ log_error1("failed to create keys store");
+ return herror_new("_soap_xmlxec_create_key_manager", 0, "failed to create keys store");
+ }
+
+ /* create keys manager */
+ if ((_soap_xmlsec_key_manager = xmlSecKeysMngrCreate()) == NULL)
+ {
+ log_error1("failed to create keys manager");
+ xmlSecKeyStoreDestroy(keysStore);
+ return herror_new("_soap_xmlsec_key_manager", 0, "failed to create keys manager");
+ }
+
+ /*
+ * add store to keys manager, from now on keys manager destroys the
+ * store if needed
+ */
+ if (xmlSecKeysMngrAdoptKeysStore(_soap_xmlsec_key_manager, keysStore) < 0)
+ {
+ log_error1("failed to add keys store to keys manager");
+ 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");
+ }
+
+ /* initialize crypto library specific data in keys manager */
+ if (xmlSecCryptoKeysMngrInit(_soap_xmlsec_key_manager) < 0)
+ {
+ 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");
+ }
+
+ /* set the get key callback */
+ _soap_xmlsec_key_manager->getKey = xmlSecKeysMngrGetKey;
+
+ return H_OK;
+}
+
static herror_t
_soap_xmlsec_load_key(void)
{
- char *key = "key.pem";
- char *cert = "cert.pem";
+ int err;
+ xmlChar keyName[256];
- if ((_soap_xmlsec_sign_key = xmlSecCryptoAppKeyLoad(key, xmlSecKeyDataFormatPem, "password", NULL, NULL)) == NULL)
+ if ((_soap_xmlsec_key = xmlSecCryptoAppKeyLoad(_soap_xmlsec_keyfile, xmlSecKeyDataFormatPem, _soap_xmlsec_password, NULL, NULL)) == NULL)
{
- log_error2("xmlSecCryptoAppKeyLoad(\"%s\") failed", key);
- return herror_new("_soap_xmlsec_load_key", 0, "xmlSecCryptoAppKeyLoad(\"%s\") failed", key);
+ log_error2("xmlSecCryptoAppKeyLoad(\"%s\") failed", _soap_xmlsec_keyfile);
+ return herror_new("_soap_xmlsec_load_key", 0, "xmlSecCryptoAppKeyLoad(\"%s\") failed", _soap_xmlsec_keyfile);
}
- if (xmlSecCryptoAppKeyCertLoad(_soap_xmlsec_sign_key, cert, xmlSecKeyDataFormatPem) < 0)
+ if (_soap_xmlsec_certfile)
{
- log_error2("xmlSecCryptoAppKeyCertLoad(\"%s\") failed", cert);
- return herror_new("_soap_xmlsec_load_key", 0, "xmlSecCryptoAppKeyCertLoad(\"%s\") failed", cert);
+ if (xmlSecCryptoAppKeyCertLoad(_soap_xmlsec_key, _soap_xmlsec_certfile, xmlSecKeyDataFormatPem) < 0)
+ {
+ 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);
+ }
}
- if (xmlSecKeySetName(_soap_xmlsec_sign_key, soap_server_get_name()) < 0)
+ xmlStrPrintf(keyName, 256, "%s/key.pem", soap_server_get_name());
+ log_error2("keyName is \"%s\"", keyName);
+ if ((err = xmlSecKeySetName(_soap_xmlsec_key, keyName)) < 0)
{
- log_error1("xmlSecKeySetName failed");
- return herror_new("_soap_xmlsec_load_key", 0, "xmlSecKeySetName failed");
+ 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);
}
+ xmlSecKeyDebugXmlDump(_soap_xmlsec_key, stdout);
+ xmlSecKeyDataDebugXmlDump(xmlSecKeyGetValue(_soap_xmlsec_key), stdout);
+
return H_OK;
}
-herror_t
-soap_xmlsec_init_args(int argc, char **argv)
+static void
+_soap_xmlsec_key_service(httpd_conn_t *conn, struct hrequest_t *req)
+{
+ char buf[4096];
+ size_t len;
+ int fd;
+
+ httpd_set_header(conn, HEADER_CONTENT_TYPE, "text/plain");
+ if (!(fd = open(_soap_xmlsec_keyfile, O_RDONLY)))
+ {
+ httpd_send_header(conn, 404, HTTP_STATUS_404_REASON_PHRASE);
+ http_output_stream_write_string(conn->out, "Public key not found!\n");
+ }
+ else
+ {
+ httpd_send_header(conn, 200, HTTP_STATUS_200_REASON_PHRASE);
+
+ while ((len = read(fd, buf, 4096)) > 0)
+ http_output_stream_write(conn->out, buf, len);
+ }
+
+ return;
+}
+
+static herror_t
+_soap_xmlsec_publish_key(void)
{
- int err, i;
herror_t status;
- _soap_xmlsec_enabled = 0;
- for (i=0; i<argc; i++)
- if (!strcmp(argv[i], CSOAP_ENABLE_XMLSEC))
+ if ((status = httpd_register("/key.pem", _soap_xmlsec_key_service)) != H_OK)
+ {
+ log_error2("Cannot register key service (%s)", herror_message(status));
+ return status;
+ }
+
+ return H_OK;
+}
+
+static inline void
+_soap_xmlsec_parse_arguments(int argc, char **argv)
+{
+ int i;
+
+ for (i=1; i<=argc; i++)
+ {
+ if (!strcmp(argv[i-1], CSOAP_ENABLE_XMLSEC))
+ {
_soap_xmlsec_enabled = 1;
+ }
+ else if (!strcmp(argv[i-1], CSOAP_XMLSEC_KEYFILE))
+ {
+ _soap_xmlsec_keyfile = strdup(argv[i]);
+ }
+ else if (!strcmp(argv[i-1], CSOAP_XMLSEC_PASSWORD))
+ {
+ _soap_xmlsec_password = strdup(argv[i]);
+ }
+ else if (!strcmp(argv[i-1], CSOAP_XMLSEC_CERTFILE))
+ {
+ _soap_xmlsec_certfile = strdup(argv[i]);
+ }
+ }
+ return;
+}
- if (!_soap_xmlsec_enabled)
+herror_t
+_soap_xmlsec_init(void)
+{
+ static int initialized = 0;
+ int err;
+ herror_t status;
+
+ if (initialized)
return H_OK;
log_info1("initializing xmlsec1");
- xmlSecErrorsDefaultCallbackEnableOutput(0);
+ xmlSecErrorsDefaultCallbackEnableOutput(1);
xmlSecErrorsSetCallback(_soap_xmlsec_error_callback);
if (xmlSecInit() < 0)
{
log_error1("xmlSecInit failed");
- return herror_new("soap_xmlsec_init_args", 0, "xmlSecInit failed");
+ return herror_new("soap_xmlsec_init", 0, "xmlSecInit failed");
}
if (xmlSecCheckVersion() != 1)
{
log_error1("xmlSecCheckVersion failed, wrong xmlsec version");
- return herror_new("soap_xmlsec_init_args", 0, "Wrong xmlsec version");
+ return herror_new("soap_xmlsec_init", 0, "Wrong xmlsec version");
}
#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
@@ -135,108 +661,322 @@ soap_xmlsec_init_args(int argc, char **argv)
if (xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0)
{
log_error1("xmlSecCryptoDLLoadLibrary failed");
- return herror_new("soap_xmlsec_init_args", 0, "xmlSecCryptoDLLoadLibrary failed");
+ return herror_new("soap_xmlsec_init", 0, "xmlSecCryptoDLLoadLibrary failed");
}
#endif
if (xmlSecCryptoAppInit(NULL) < 0)
{
log_error1("xmlSecCryptoAppInit failed");
- return herror_new("soap_xmlsec_init_args", 0, "xmlSecCryptoAppInit failed");
+ return herror_new("soap_xmlsec_init", 0, "xmlSecCryptoAppInit failed");
}
if (xmlSecCryptoInit() < 0)
{
log_error1("xmlSecCryptoInit failed");
- return herror_new("soap_xmlsec_init_args", 0, "xmlSecCryptoInit failed");
+ return herror_new("soap_xmlsec_init", 0, "xmlSecCryptoInit failed");
+ }
+
+ if ((status = _soap_xmlsec_create_key_manager()) != H_OK)
+ {
+ log_error2("_soap_xmlsec_create_key_manager failed (%s)", herror_message(status));
+ return status;
}
if ((err = pthread_mutex_init(&_soap_xmlsec_lock, NULL)) < 0)
{
- log_error1("pthread_mutex_init failed");
- return herror_new("soap_xmlsec_init_args", 0, "pthread_mutex_init failed %s", strerror(err));
+ log_error2("pthread_mutex_init failed (%s)", strerror(err));
+ return herror_new("soap_xmlsec_init", 0, "pthread_mutex_init failed (%s)", strerror(err));
}
if ((status = _soap_xmlsec_load_key()) != H_OK)
{
- log_error1("_soap_xmlsec_create_sign_context failed");
+ log_error2("_soap_xmlsec_load_key failed (%s)", herror_message(status));
return status;
}
+ initialized = 1;
+
return H_OK;
}
-herror_t soap_xmlsec_sign(struct SoapEnv *envelope)
+herror_t
+soap_xmlsec_client_init_args(int argc, char **argv)
{
+ _soap_xmlsec_parse_arguments(argc, argv);
+
+ if (!_soap_xmlsec_enabled)
+ return H_OK;
+
+ return _soap_xmlsec_init();
+}
+
+herror_t
+soap_xmlsec_server_init_args(int argc, char **argv)
+{
+ herror_t status;
+
+ _soap_xmlsec_parse_arguments(argc, argv);
+
+ if (!_soap_xmlsec_enabled)
+ return H_OK;
+
+ if ((status = _soap_xmlsec_init()) != H_OK)
+ {
+ log_error2("_soap_xmlsec_init failed (%s)", herror_message(status));
+ return status;
+ }
+
+ if ((status = _soap_xmlsec_publish_key()) != H_OK)
+ {
+ log_error2("_soap_xmlsec_publish_key failed (%s)", herror_message(status));
+ return status;
+ }
+
+ return H_OK;
+}
+
+herror_t soap_xmlsec_sign(struct SoapCtx *context)
+{
+ xmlNodePtr signature;
+ xmlNsPtr ns;
xmlNodePtr signNode;
xmlNodePtr refNode;
xmlNodePtr keyInfoNode;
xmlSecDSigCtxPtr dsigCtx;
+ herror_t ret;
+ struct SoapEnv *envelope;
if (!_soap_xmlsec_enabled)
return H_OK;
+ envelope = context->env;
+
+ ret = H_OK;
+
pthread_mutex_lock(&_soap_xmlsec_lock);
if (!(signNode = xmlSecTmplSignatureCreate(envelope->root->doc, xmlSecTransformExclC14NId, xmlSecTransformRsaSha1Id, NULL)))
{
log_error1("xmlSecTmplSignatureCreate failed");
- return herror_new("soap_xmlsec_sign", 0, "xmlSecTmplSignatureCreate failed");
+ ret = herror_new("soap_xmlsec_sign", 0, "xmlSecTmplSignatureCreate failed");
+ goto out;
}
- if (!(refNode = xmlSecTmplSignatureAddReference(signNode, xmlSecTransformSha1Id, NULL, NULL, NULL)))
+ signature = xmlNewNode(NULL, "Signature");
+ ns = xmlNewNs(signature, SOAP_SECURITY_NAMESPACE, SOAP_SECURITY_PREFIX);
+ xmlSetNs(signature, ns);
+
+ xmlSetNsProp(signature, envelope->root->ns, BAD_CAST "actor", soap_transport_get_name());
+ xmlSetNsProp(signature, envelope->root->ns, BAD_CAST "mustUnderstand", BAD_CAST "1");
+
+ xmlAddChild(envelope->header, signature);
+
+ xmlAddChild(signature, signNode);
+
+ if (!(refNode = xmlSecTmplSignatureAddReference(signNode, xmlSecTransformSha1Id, "#Body", NULL, NULL)))
{
log_error1("xmlSecTmplSignatureAddReference failed");
- return herror_new("soap_xmlsec_sign", 0, "xmlSecTmplSignatureAddReference failed");
+ ret = herror_new("soap_xmlsec_sign", 0, "xmlSecTmplSignatureAddReference failed");
+ goto out;
}
if (!(keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, NULL)))
{
log_error1("xmlSecTmplSignatureEnsureKeyInfo failed");
- return herror_new("soap_xmlsec_sign", 0, "xmlSecTmplSignatureEnsureKeyInfo failed");
+ ret = herror_new("soap_xmlsec_sign", 0, "xmlSecTmplSignatureEnsureKeyInfo failed");
+ goto out;
}
- if (xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL)
+ if (xmlSecTmplKeyInfoAddKeyName(keyInfoNode, soap_server_get_name()) == NULL)
{
log_error1("xmlSecTmplKeyInfoAddKeyName failed");
- return herror_new("soap_xmlsec_sign", 0, "xmlSecTmplKeyInfoAddKeyName failed");
+ ret = herror_new("soap_xmlsec_sign", 0, "xmlSecTmplKeyInfoAddKeyName failed");
+ goto out;
}
- if (!(dsigCtx = xmlSecDSigCtxCreate(NULL)))
+ if (!(dsigCtx = xmlSecDSigCtxCreate(_soap_xmlsec_key_manager)))
{
log_error1("xmlSecDSigCtxCreate failed");
- return herror_new("soap_xmlsec_sign", 0, "xmlSecDSigCtxCreate failed");
+ ret = herror_new("soap_xmlsec_sign", 0, "xmlSecDSigCtxCreate failed");
+ goto out;
}
- dsigCtx->signKey = _soap_xmlsec_sign_key;
-
+ dsigCtx->signKey = _soap_xmlsec_key;
+
if (xmlSecDSigCtxSign(dsigCtx, signNode) < 0)
{
log_error1("xmlSecDSigCtxSign failed");
- return herror_new("soap_xmlsec_sign", 0, "xmlSecDSigCtxSign failed");
+ ret = herror_new("soap_xmlsec_sign", 0, "xmlSecDSigCtxSign failed");
+ goto out;
}
- xmlAddChild(envelope->header, signNode);
+
+out:
pthread_mutex_unlock(&_soap_xmlsec_lock);
return H_OK;
}
-herror_t soap_xmlsec_encrypt(struct SoapEnv *envelope)
+herror_t soap_xmlsec_encrypt(struct SoapCtx *context)
{
+ struct SoapEnv *envelope;
+ xmlNodePtr encDataNode = NULL;
+ xmlNodePtr keyInfoNode = NULL;
+ xmlNodePtr encKeyNode = NULL;
+ xmlNodePtr keyInfoNode2 = NULL;
+ xmlSecEncCtxPtr encCtx = NULL;
+ xmlURI *to;
+ xmlChar buf[256];
+ xmlDocPtr doc;
+
if (!_soap_xmlsec_enabled)
return H_OK;
+ envelope = context->env;
+
+ doc = context->env->root->doc;
+
+ 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");
+ }
+
+ if (xmlSecTmplEncDataEnsureCipherValue(encDataNode) == NULL)
+ {
+ log_error1("failed to add CipherValue node");
+ return herror_new("soap_xmlsec_encrypt", 0, "failed to add CipherValue node");
+ }
+
+ 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");
+ }
+
+ 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");
+ }
+
+ if (xmlSecTmplEncDataEnsureCipherValue(encKeyNode) == NULL)
+ {
+ log_error1("failed to add CipherValue node");
+ return herror_new("soap_xmlsec_encrypt", 0, "failed to add CipherValue node");
+ }
+
+ 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)");
+ }
+
+ to = soap_addressing_get_to_address(envelope);
+ xmlStrPrintf(buf, 256, "http://%s:%i/key.pem", to->server, to->port);
+ log_error2("adding key \"%s\"", buf);
+ xmlFreeURI(to);
+
+ 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);
+ }
+
+ 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");
+ }
+
+ 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");
+ }
+
+ 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");
+ }
+
+/* {
+ 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);
+
return H_OK;
}
+herror_t soap_xmlsec_decrypt(struct SoapCtx *context)
+{
+ struct SoapEnv *envelope;
+
+ if (!_soap_xmlsec_enabled)
+ return H_OK;
+
+ envelope = context->env;
+
+ log_error1("not implemented");
+ return herror_new("soap_xmlsec_decrupt", 0, "not implemented");
+}
+
+herror_t soap_xmlsec_verify(struct SoapCtx *context)
+{
+ struct SoapEnv *envelope;
+
+ if (!_soap_xmlsec_enabled)
+ return H_OK;
+
+ envelope = context->env;
+
+ log_error1("not implemented");
+ return herror_new("soap_xmlsec_verify", 0, "not implemented");
+}
+
void soap_xmlsec_destroy(void)
{
+ if (!_soap_xmlsec_enabled)
+ return;
+
+ xmlSecKeysMngrDestroy(_soap_xmlsec_key_manager);
+
xmlSecCryptoShutdown();
xmlSecCryptoAppShutdown();
xmlSecShutdown();
+#ifndef XMLSEC_NO_XSLT
+ xsltCleanupGlobals();
+#endif
+
return;
}
diff --git a/libcsoap/soap-xmlsec.h b/libcsoap/soap-xmlsec.h
index fc24fc5..9943498 100644
--- a/libcsoap/soap-xmlsec.h
+++ b/libcsoap/soap-xmlsec.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: soap-xmlsec.h,v 1.2 2006/11/27 11:15:27 m0gg Exp $
+ * $Id: soap-xmlsec.h,v 1.3 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: A SOAP client/server library in C
* Copyright (C) 2006 Heiko Ronsdorf
@@ -31,13 +31,17 @@
* This module is implemented using the xmlsec1 library.
*
* @author H. Ronsdorf
- * @version $Revision: 1.2 $
+ * @version $Revision: 1.3 $
*
- * @see http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wss
- * http://www.aleksey.com/xmlsec/,
+ * @see http://www.w3.org/TR/SOAP-dsig/,
+ * http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wss,
+ * http://www.aleksey.com/xmlsec/
*
*/
+#define SOAP_SECURITY_NAMESPACE "http://schemas.xmlsoap.org/soap/security/2000-12"
+#define SOAP_SECURITY_PREFIX "SOAP-SEC"
+
/**
*
* Commandline argument to enabled WS-Security.
@@ -45,6 +49,28 @@
*/
#define CSOAP_ENABLE_XMLSEC "-CSOAPxmlsec"
+/**
+ *
+ * Commandline argument to set the keyfile. If this argument is not specified a
+ * random key will be used.
+ *
+ */
+#define CSOAP_XMLSEC_KEYFILE "-CSOAPkeyfile"
+
+/**
+ *
+ * Commandline argument to set the password of the key.
+ *
+ */
+#define CSOAP_XMLSEC_PASSWORD "-CSOAPpassword"
+
+/**
+ *
+ * Commandline argument to set a file of certificates.
+ *
+ */
+#define CSOAP_XMLSEC_CERTFILE "-CSOAPcertfile"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -56,19 +82,45 @@ extern "C" {
* @param argc commandline arg count
* @param argv commandline arg vector
*
- * @returns H_OK on success
+ * @return H_OK on success
*
*/
-extern herror_t soap_xmlsec_init_args(int argc, char **argv);
+extern herror_t soap_xmlsec_server_init_args(int argc, char **argv);
/**
*
- * Sign a XML document contained in a SOAP Envelope
+ * Initializes the WS-Security subsystem.
+ *
+ * @param argc commandline arg count
+ * @param argv commandline arg vector
+ *
+ * @return H_OK on success
+ *
+ */
+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.
*
* @param envelope The SOAP envelope to be signed.
*
+ * @return H_OK on success
+ *
*/
-extern herror_t soap_xmlsec_sign(struct SoapEnv *envelope);
+extern herror_t soap_xmlsec_sign(struct SoapCtx *context);
+
+/**
+ *
+ * Verify a XML documents signature contained in a SOAP Envelope.
+ *
+ * @param envelope The SOAP envelope to be verified.
+ *
+ * @return H_OK on success
+ *
+ */
+extern herror_t soap_xmlsec_verify(struct SoapCtx *context);
/**
*
@@ -76,8 +128,22 @@ extern herror_t soap_xmlsec_sign(struct SoapEnv *envelope);
*
* @param envelope The SOAP envelope to be encrypted.
*
+ * @return H_OK on success
+ *
+ */
+extern herror_t soap_xmlsec_encrypt(struct SoapCtx *context);
+
+/**
+ *
+ * Decrupt a XML document contained in a SOAP envelope.
+ *
+ * @param envelope The SOAP envelope to be decrypted.
+ *
+ * @return H_OK on success
+ *
*/
-extern herror_t soap_xmlsec_encrypt(struct SoapEnv *envelope);
+extern herror_t soap_xmlsec_decrypt(struct SoapCtx *context);
+
/**
*
diff --git a/nanohttp/nanohttp-base64.c b/nanohttp/nanohttp-base64.c
index 8abee35..0e887d6 100644
--- a/nanohttp/nanohttp-base64.c
+++ b/nanohttp/nanohttp-base64.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: nanohttp-base64.c,v 1.2 2006/02/25 10:09:29 snowdrop Exp $
+* $Id: nanohttp-base64.c,v 1.3 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -32,9 +32,11 @@ static const char cb64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
static const char cd64[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
/**
+ *
* encode 3 8-bit binary bytes as 4 '6-bit' characters
+ *
*/
-static void encodeblock(unsigned char in[3], unsigned char out[4], int len)
+static void _encodeblock(unsigned char in[3], unsigned char out[4], int len)
{
out[0] = cb64[in[0] >> 2];
@@ -45,10 +47,7 @@ static void encodeblock(unsigned char in[3], unsigned char out[4], int len)
return;
}
-/**
- * base64 encode a string.
- */
-void base64_encode(const unsigned char *instr, unsigned char *outstr)
+void base64_encode_string(const unsigned char *instr, unsigned char *outstr)
{
unsigned char in[3], out[4];
int i, len;
@@ -66,7 +65,7 @@ void base64_encode(const unsigned char *instr, unsigned char *outstr)
}
if (len)
{
- encodeblock(in, out, len);
+ _encodeblock(in, out, len);
for (i = 0; i < 4; i++)
*outstr++ = out[i];
}
@@ -74,9 +73,11 @@ void base64_encode(const unsigned char *instr, unsigned char *outstr)
}
/**
+ *
* decode 4 '6-bit' characters into 3 8-bit binary bytes
+ *
*/
-static void decodeblock(unsigned char in[4], unsigned char out[3])
+static void _decodeblock(unsigned char in[4], unsigned char out[3])
{
out[0] = (unsigned char)(in[0] << 2 | in[1] >> 4);
out[1] = (unsigned char)(in[1] << 4 | in[2] >> 2);
@@ -88,7 +89,7 @@ static void decodeblock(unsigned char in[4], unsigned char out[3])
/**
* decode a base64 encoded string (maybe broken...)
*/
-void base64_decode(const unsigned char *instr, unsigned char *outstr)
+void base64_decode_string(const unsigned char *instr, unsigned char *outstr)
{
unsigned char in[4], out[3], v;
int i, len;
@@ -118,7 +119,7 @@ void base64_decode(const unsigned char *instr, unsigned char *outstr)
}
if (len)
{
- decodeblock(in, out);
+ _decodeblock(in, out);
for (i = 0; i < len - 1; i++)
*outstr++ = out[i];
}
@@ -135,7 +136,7 @@ int main(int argc, char **argv) {
unsigned char outstr[80];
bzero(outstr, 80);
- base64_decode(instr, outstr);
+ base64_decode_string(instr, outstr);
printf("\"%s\" => \"%s\"\n", instr, outstr);
if (strcmp(outstr, result))
@@ -144,7 +145,7 @@ int main(int argc, char **argv) {
strcpy(instr2, outstr);
bzero(outstr, 80);
- base64_encode(instr2, outstr);
+ base64_encode_string(instr2, outstr);
printf("\"%s\" => \"%s\"\n", instr2, outstr);
if (strcmp(outstr, instr))
diff --git a/nanohttp/nanohttp-base64.h b/nanohttp/nanohttp-base64.h
index 69f5dfa..6556acf 100644
--- a/nanohttp/nanohttp-base64.h
+++ b/nanohttp/nanohttp-base64.h
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: nanohttp-base64.h,v 1.2 2006/05/02 09:12:50 m0gg Exp $
+* $Id: nanohttp-base64.h,v 1.3 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -24,6 +24,31 @@
#ifndef __nanohttp_base64_h
#define __nanohttp_base64_h
+/** @file
+ *
+ * Base64 data encoding
+ *
+ * Base encoding of data is used in many situations to store or transfer data in
+ * environments that, perhaps for legacy reasons, are restricted to US-ASCII
+ * data. Base64 encoding can also be used in new applications that do not have
+ * legacy restrictions, simply because it makes it possible to manipulate objects
+ * with text editors.
+ *
+ * In the past, different applications have had different requirements and thus
+ * sometimes implemented base encodings in slightly different ways. Today,
+ * protocol specifications sometimes use base encodings in general, and "base64"
+ * in particular, without a precise description or reference. Multipurpose
+ * Internet Mail Extensions (MIME) is often used as a reference for base64
+ * without considering the consequences for line-wrapping or non-alphabet
+ * characters.
+ *
+ * @author H. Ronsdorf
+ * @version $Revision: 1.3 $
+ *
+ * @see http://www.ietf.org/rfc/rfc4648.txt
+ *
+ */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -35,10 +60,10 @@ extern "C" {
* @param instr Pointer to the input string.
* @param outstr Pointer to the output destination.
*
- * @see base64_decode
+ * @see base64_decode_string
*
*/
-extern void base64_encode(const unsigned char *instr, unsigned char *outstr);
+extern void base64_encode_string(const unsigned char *instr, unsigned char *outstr);
/**
*
@@ -47,10 +72,10 @@ extern void base64_encode(const unsigned char *instr, unsigned char *outstr);
* @param instr Pointer to the input string.
* @param outstr Pointer to the output destination.
*
- * @see base64_encode
+ * @see base64_encode_string
*
*/
-extern void base64_decode(const unsigned char *instr, unsigned char *outstr);
+extern void base64_decode_string(const unsigned char *instr, unsigned char *outstr);
#ifdef __cplusplus
}
diff --git a/nanohttp/nanohttp-client.c b/nanohttp/nanohttp-client.c
index d9bf113..2392d81 100644
--- a/nanohttp/nanohttp-client.c
+++ b/nanohttp/nanohttp-client.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: nanohttp-client.c,v 1.46 2006/11/25 15:06:58 m0gg Exp $
+* $Id: nanohttp-client.c,v 1.47 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -261,7 +261,7 @@ _httpc_set_basic_authorization_header(httpc_conn_t *conn, const char *key, const
sprintf(in, "%s:%s", user, password);
- base64_encode(in, out);
+ base64_encode_string(in, out);
sprintf(in, "Basic %s", out);
diff --git a/nanohttp/nanohttp-mime.h b/nanohttp/nanohttp-mime.h
index d6ce17d..894f6ce 100755
--- a/nanohttp/nanohttp-mime.h
+++ b/nanohttp/nanohttp-mime.h
@@ -3,7 +3,7 @@
* | \/ | | | | \/ | | _/
* |_''_| |_| |_''_| |_'/ PARSER
*
-* $Id: nanohttp-mime.h,v 1.11 2006/11/25 15:06:58 m0gg Exp $
+* $Id: nanohttp-mime.h,v 1.12 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003-2004 Ferhat Ayaz
@@ -29,6 +29,18 @@
#ifndef __nanohttp_mime_h
#define __nanohttp_mime_h
+/** @file
+ *
+ * @author Ferhat Ayaz
+ * @version $Revision: 1.12 $
+ *
+ * @see http://www.ietf.org/rfc/rfc2045.txt,
+ * http://www.ietf.org/rfc/rfc2046.txt,
+ * http://www.ietf.org/rfc/rfc4288.txt,
+ * http://www.ietf.org/rfc/rfc4289.txt,
+ *
+ */
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/nanohttp/nanohttp-server.c b/nanohttp/nanohttp-server.c
index 8c16e5f..4c31421 100644
--- a/nanohttp/nanohttp-server.c
+++ b/nanohttp/nanohttp-server.c
@@ -1,5 +1,5 @@
/******************************************************************
-* $Id: nanohttp-server.c,v 1.70 2006/11/27 12:47:27 m0gg Exp $
+* $Id: nanohttp-server.c,v 1.71 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -558,7 +558,7 @@ _httpd_decode_authorization(const char *value, char **user, char **pass)
log_verbose2("Authorization (base64) = \"%s\"", value);
- base64_decode(value, tmp);
+ base64_decode_string(value, tmp);
log_verbose2("Authorization (ascii) = \"%s\"", tmp);
diff --git a/nanohttp/nanohttp-server.h b/nanohttp/nanohttp-server.h
index be48005..e85c64a 100644
--- a/nanohttp/nanohttp-server.h
+++ b/nanohttp/nanohttp-server.h
@@ -1,5 +1,5 @@
/******************************************************************
- * $Id: nanohttp-server.h,v 1.24 2006/11/23 15:27:33 m0gg Exp $
+ * $Id: nanohttp-server.h,v 1.25 2006/11/28 23:45:57 m0gg Exp $
*
* CSOAP Project: A http client/server library in C
* Copyright (C) 2003 Ferhat Ayaz
@@ -118,6 +118,8 @@ extern "C"
extern hservice_t *httpd_get_services(void);
extern hservice_t *httpd_find_service(const char *name);
+ extern void httpd_response_set_content_type(httpd_conn_t * res, const char *content_type);
+
extern herror_t httpd_send_header(httpd_conn_t * res, int code, const char *text);
extern int httpd_set_header(httpd_conn_t * conn, const char *key, const char *value);