25
25
#include <lasso/id-wsf/wsf_profile.h>
26
26
#include <lasso/xml/disco_modify.h>
27
#include <lasso/xml/soap_fault.h>
27
28
#include <lasso/xml/soap_binding_correlation.h>
29
#include <lasso/xml/soap_binding_provider.h>
30
#include <lasso/xml/wsse_security.h>
31
#include <lasso/xml/saml_assertion.h>
33
#include <lasso/id-ff/server.h>
34
#include <lasso/id-ff/providerprivate.h>
36
#include <xmlsec/xmltree.h>
37
#include <xmlsec/xmldsig.h>
38
#include <xmlsec/templates.h>
39
#include <xmlsec/crypto.h>
41
struct _LassoWsfProfilePrivate
43
gboolean dispose_has_run;
44
char *security_mech_id;
45
LassoSoapFault *fault;
29
48
/*****************************************************************************/
30
49
/* private methods */
31
50
/*****************************************************************************/
53
lasso_wsf_profile_get_fault(LassoWsfProfile *profile)
55
return profile->private_data->fault;
59
lasso_security_mech_id_is_x509_authentication(const gchar *security_mech_id)
61
if (!security_mech_id)
64
if (strcmp(security_mech_id, LASSO_SECURITY_MECH_X509) == 0 || \
65
strcmp(security_mech_id, LASSO_SECURITY_MECH_TLS_X509) == 0 || \
66
strcmp(security_mech_id, LASSO_SECURITY_MECH_CLIENT_TLS_X509) == 0)
73
lasso_security_mech_id_is_saml_authentication(const gchar *security_mech_id)
75
if (!security_mech_id)
78
if (strcmp(security_mech_id, LASSO_SECURITY_MECH_SAML) == 0 || \
79
strcmp(security_mech_id, LASSO_SECURITY_MECH_TLS_SAML) == 0 || \
80
strcmp(security_mech_id, LASSO_SECURITY_MECH_CLIENT_TLS_SAML) == 0)
86
void lasso_wsf_profile_set_security_mech_id(LassoWsfProfile *profile,
87
const gchar *security_mech_id)
89
profile->private_data->security_mech_id = g_strdup(security_mech_id);
93
lasso_wsf_profile_add_x509_authentication(LassoWsfProfile *profile, LassoNode *envelope,
94
LassoSignatureMethod sign_method)
96
xmlNode *envelope_node, *signature = NULL, *sign_tmpl, *reference, *key_info, *t;
97
xmlNode *header, *correlation = NULL, *security = NULL, *body = NULL;
98
xmlSecDSigCtx *dsigCtx;
101
LassoSignatureType sign_type = LASSO_SIGNATURE_TYPE_WITHX509;
103
envelope_node = lasso_node_get_xmlNode(envelope, 1);
105
doc = xmlNewDoc((xmlChar*)"1.0");
106
xmlDocSetRootElement(doc, envelope_node);
108
/* Get correlation, body and security elements */
109
t = envelope_node->children;
111
if (strcmp((char *) t->name, "Header") == 0)
113
else if (strcmp((char *) t->name, "Body") == 0)
122
t = header->children;
124
if (strcmp((char *) t->name, "Correlation") == 0)
126
else if (strcmp((char *) t->name, "Security") == 0)
130
if (correlation == NULL)
132
if (security == NULL)
135
/* Add signature template */
136
if (sign_method == LASSO_SIGNATURE_METHOD_RSA_SHA1) {
137
signature = xmlSecTmplSignatureCreate(NULL,
138
xmlSecTransformExclC14NId,
139
xmlSecTransformRsaSha1Id, NULL);
141
signature = xmlSecTmplSignatureCreate(NULL,
142
xmlSecTransformExclC14NId,
143
xmlSecTransformDsaSha1Id, NULL);
146
xmlAddChild(security, signature);
148
/* FIXME: add real reference on SOAP elements */
149
/*id = G_STRUCT_MEMBER(char*, node, snippet_signature->offset);
150
uri = g_strdup_printf("#%s", id);
151
reference = xmlSecTmplSignatureAddReference(signature,
152
xmlSecTransformSha1Id, NULL, (xmlChar*)uri, NULL);
155
reference = xmlSecTmplSignatureAddReference(signature, xmlSecTransformSha1Id,
157
xmlSecTmplReferenceAddTransform(reference, xmlSecTransformEnvelopedId);
158
xmlSecTmplReferenceAddTransform(reference, xmlSecTransformExclC14NId);
160
/* FIXME: X509 authentication needs X509 signature type */
161
if (profile->server->certificate != NULL && profile->server->certificate[0] != 0) {
162
key_info = xmlSecTmplSignatureEnsureKeyInfo(signature, NULL);
163
xmlSecTmplKeyInfoAddX509Data(key_info);
166
/* Sign SOAP message */
167
sign_tmpl = xmlSecFindNode(security, xmlSecNodeSignature, xmlSecDSigNs);
168
if (sign_tmpl == NULL)
171
dsigCtx = xmlSecDSigCtxCreate(NULL);
172
dsigCtx->signKey = xmlSecCryptoAppKeyLoad(profile->server->private_key,
173
xmlSecKeyDataFormatPem, NULL, NULL, NULL);
174
if (dsigCtx->signKey == NULL) {
175
xmlSecDSigCtxDestroy(dsigCtx);
178
if (profile->server->certificate != NULL && profile->server->certificate[0] != 0) {
179
if (xmlSecCryptoAppKeyCertLoad(dsigCtx->signKey, profile->server->certificate,
180
xmlSecKeyDataFormatPem) < 0) {
181
xmlSecDSigCtxDestroy(dsigCtx);
185
if (xmlSecDSigCtxSign(dsigCtx, sign_tmpl) < 0) {
186
xmlSecDSigCtxDestroy(dsigCtx);
189
xmlSecDSigCtxDestroy(dsigCtx);
191
return envelope_node;
195
lasso_wsf_profile_verify_x509_authentication(LassoWsfProfile *profile, xmlDoc *doc)
197
LassoProvider *provider;
198
char *providerID = NULL;
200
xmlNode *provider_node, *security, *signature, *x509data, *node;
201
xmlSecKeysMngr *keys_mngr = NULL;
202
xmlSecDSigCtx *dsigCtx;
204
xmlXPathContext *xpathCtx = NULL;
205
xmlXPathObject *xpathObj;
207
xpathCtx = xmlXPathNewContext(doc);
210
xmlXPathRegisterNs(xpathCtx, (xmlChar*)"sb", (xmlChar*)LASSO_SOAP_BINDING_HREF);
211
xpathObj = xmlXPathEvalExpression((xmlChar*)"//sb:Provider", xpathCtx);
212
if (xpathObj->nodesetval && xpathObj->nodesetval->nodeNr) {
213
provider_node = xpathObj->nodesetval->nodeTab[0];
215
providerID = (char *) xmlGetProp(provider_node, (xmlChar *) "providerID");
216
provider = lasso_server_get_provider(profile->server, providerID);
218
node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
220
return LASSO_DS_ERROR_SIGNATURE_NOT_FOUND;
222
x509data = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeX509Data, xmlSecDSigNs);
223
if (x509data != NULL && provider->ca_cert_chain != NULL) {
224
keys_mngr = lasso_load_certs_from_pem_certs_chain_file(
225
provider->ca_cert_chain);
226
if (keys_mngr == NULL) {
228
return LASSO_DS_ERROR_CA_CERT_CHAIN_LOAD_FAILED;
232
dsigCtx = xmlSecDSigCtxCreate(keys_mngr);
233
if (keys_mngr == NULL) {
234
dsigCtx->signKey = lasso_provider_get_public_key(provider);
235
if (dsigCtx->signKey == NULL) {
236
xmlSecDSigCtxDestroy(dsigCtx);
238
return LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED;
242
if(xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
243
xmlSecDSigCtxDestroy(dsigCtx);
245
xmlSecKeysMngrDestroy(keys_mngr);
246
return LASSO_DS_ERROR_SIGNATURE_VERIFICATION_FAILED;
250
xmlSecKeysMngrDestroy(keys_mngr);
252
if (dsigCtx->status != xmlSecDSigStatusSucceeded) {
253
xmlSecDSigCtxDestroy(dsigCtx);
254
return LASSO_DS_ERROR_INVALID_SIGNATURE;
256
fprintf(stdout, "Signature is OK\n");
262
lasso_wsf_profile_add_saml_authentication(LassoWsfProfile *profile,
263
LassoSamlAssertion *credential)
265
LassoSoapHeader *header;
266
LassoWsseSecurity *security;
269
security = lasso_wsse_security_new();
270
security->any = g_list_append(security->any, credential);
271
header = profile->soap_envelope_request->Header;
272
header->Other = g_list_append(header->Other, security);
33
277
LassoSoapEnvelope*
34
lasso_wsf_profile_build_soap_envelope(const char *refToMessageId)
278
lasso_wsf_profile_build_soap_envelope(const char *refToMessageId, const char *providerId)
36
280
LassoSoapEnvelope *envelope;
37
281
LassoSoapHeader *header;
55
299
correlation->refToMessageID = g_strdup(refToMessageId);
56
300
header->Other = g_list_append(header->Other, correlation);
304
LassoSoapBindingProvider *provider = lasso_soap_binding_provider_new(providerId);
305
header->Other = g_list_append(header->Other, provider);
312
lasso_wsf_profile_verify_saml_authentication(LassoWsfProfile *profile)
314
LassoSoapHeader *header;
315
LassoWsseSecurity *security = NULL;
316
LassoSamlAssertion *credential;
319
header = profile->soap_envelope_request->Header;
322
iter = header->Other;
324
if (LASSO_IS_WSSE_SECURITY(iter->data) == TRUE) {
325
security = LASSO_WSSE_SECURITY(iter->data);
334
iter = security->any;
336
if (LASSO_IS_SAML_ASSERTION(iter->data) == TRUE) {
337
credential = LASSO_SAML_ASSERTION(iter->data);
61
348
/*****************************************************************************/
62
349
/* public methods */
63
350
/*****************************************************************************/
353
* lasso_wsf_profile_get_identity:
354
* @profile: a #LassoWsfProfile
356
* Gets the identity bound to @profile.
358
* Return value: the identity or NULL if it none was found. The #LassoIdentity
359
* object is internally allocated and must not be freed by the caller.
362
lasso_wsf_profile_get_identity(LassoWsfProfile *profile)
364
if (profile->identity && g_hash_table_size(profile->identity->federations))
365
return profile->identity;
371
* lasso_wsf_profile_get_session:
372
* @profile: a #LassoWsfProfile
374
* Gets the session bound to @profile.
376
* Return value: the session or NULL if it none was found. The #LassoSession
377
* object is internally allocated and must not be freed by the caller.
380
lasso_wsf_profile_get_session(LassoWsfProfile *profile)
382
if (profile->session == NULL)
385
if (lasso_session_is_empty(profile->session))
388
return profile->session;
393
* lasso_wsf_profile_is_identity_dirty:
394
* @profile: a #LassoWsfProfile
396
* Checks whether identity has been modified (and should therefore be saved).
398
* Return value: %TRUE if identity has changed
401
lasso_wsf_profile_is_identity_dirty(LassoWsfProfile *profile)
403
return (profile->identity && profile->identity->is_dirty);
408
* lasso_wsf_profile_is_session_dirty:
409
* @profile: a #LassoWsfProfile
411
* Checks whether session has been modified (and should therefore be saved).
413
* Return value: %TRUE if session has changed
416
lasso_wsf_profile_is_session_dirty(LassoWsfProfile *profile)
418
return (profile->session && profile->session->is_dirty);
423
* lasso_wsf_profile_set_identity_from_dump:
424
* @profile: a #LassoWsfProfile
425
* @dump: XML identity dump
427
* Builds a new #LassoIdentity object from XML dump and binds it to @profile.
429
* Return value: 0 on success; or a negative value otherwise.
432
lasso_wsf_profile_set_identity_from_dump(LassoWsfProfile *profile, const gchar *dump)
434
g_return_val_if_fail(dump != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
436
profile->identity = lasso_identity_new_from_dump(dump);
437
if (profile->identity == NULL)
438
return critical_error(LASSO_PROFILE_ERROR_BAD_IDENTITY_DUMP);
445
* lasso_wsf_profile_set_session_from_dump:
446
* @profile: a #LassoWsfProfile
447
* @dump: XML session dump
449
* Builds a new #LassoSession object from XML dump and binds it to @profile.
451
* Return value: 0 on success; or a negative value otherwise.
454
lasso_wsf_profile_set_session_from_dump(LassoWsfProfile *profile, const gchar *dump)
456
g_return_val_if_fail(dump != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
458
profile->session = lasso_session_new_from_dump(dump);
459
if (profile->session == NULL)
460
return critical_error(LASSO_PROFILE_ERROR_BAD_SESSION_DUMP);
461
profile->session->is_dirty = FALSE;
66
469
lasso_wsf_profile_init_soap_request(LassoWsfProfile *profile, LassoNode *request)
68
471
LassoSoapEnvelope *envelope;
70
envelope = lasso_wsf_profile_build_soap_envelope(NULL);
473
envelope = lasso_wsf_profile_build_soap_envelope(NULL,
474
LASSO_PROVIDER(profile->server)->ProviderID);
71
475
LASSO_WSF_PROFILE(profile)->soap_envelope_request = envelope;
72
476
envelope->Body->any = g_list_append(envelope->Body->any, request);
78
482
lasso_wsf_profile_build_soap_request_msg(LassoWsfProfile *profile)
484
LassoSoapEnvelope *envelope;
485
LassoSoapHeader *header;
486
LassoWsseSecurity *security;
487
xmlNode *xmlnode = NULL;
489
xmlOutputBuffer *buf;
490
xmlCharEncodingHandler *handler;
80
492
g_return_val_if_fail(LASSO_IS_WSF_PROFILE(profile),
81
493
LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
83
/* FIXME : set keys */
84
if (LASSO_IS_SOAP_ENVELOPE(profile->soap_envelope_request) == TRUE) {
85
profile->msg_body = lasso_node_dump(LASSO_NODE(profile->soap_envelope_request));
87
else if (LASSO_IS_NODE(profile->request) == TRUE) {
88
profile->msg_body = lasso_node_export_to_soap(profile->request);
495
envelope = profile->soap_envelope_request;
497
if (lasso_security_mech_id_is_x509_authentication(
498
profile->private_data->security_mech_id) == TRUE) {
499
security = lasso_wsse_security_new();
500
header = envelope->Header;
501
header->Other = g_list_append(header->Other, security);
502
xmlnode = lasso_wsf_profile_add_x509_authentication(profile, LASSO_NODE(envelope),
503
LASSO_SIGNATURE_METHOD_RSA_SHA1);
506
/* dump soap request */
508
xmlnode = lasso_node_get_xmlNode(LASSO_NODE(envelope), FALSE);
510
handler = xmlFindCharEncodingHandler("utf-8");
511
buf = xmlAllocOutputBuffer(handler);
512
xmlNodeDumpOutput(buf, NULL, xmlnode, 0, 0, "utf-8");
513
xmlOutputBufferFlush(buf);
514
profile->msg_body = g_strdup(
515
(char*)(buf->conv ? buf->conv->content : buf->buffer->content));
516
xmlOutputBufferClose(buf);
517
xmlFreeNode(xmlnode);
95
523
lasso_wsf_profile_build_soap_response_msg(LassoWsfProfile *profile)
97
g_return_val_if_fail(LASSO_IS_WSF_PROFILE(profile),
98
LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
100
/* FIXME : set keys */
101
if (LASSO_IS_SOAP_ENVELOPE(profile->soap_envelope_response) == TRUE) {
102
profile->msg_body = lasso_node_dump(LASSO_NODE(profile->soap_envelope_response));
104
else if (LASSO_IS_NODE(profile->response) == TRUE) {
105
profile->msg_body = lasso_node_export_to_soap(profile->response);
525
LassoSoapEnvelope *envelope;
526
LassoSoapHeader *header;
527
LassoWsseSecurity *security;
529
xmlNode *xmlnode = NULL;
531
xmlOutputBuffer *buf;
532
xmlCharEncodingHandler *handler;
534
g_return_val_if_fail(LASSO_IS_WSF_PROFILE(profile), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
536
envelope = profile->soap_envelope_response;
538
if (lasso_security_mech_id_is_x509_authentication(
539
profile->private_data->security_mech_id) == TRUE) {
540
security = lasso_wsse_security_new();
541
header = envelope->Header;
542
header->Other = g_list_append(header->Other, security);
544
xmlnode = lasso_wsf_profile_add_x509_authentication(profile,
545
LASSO_NODE(envelope), LASSO_SIGNATURE_METHOD_RSA_SHA1);
548
/* dump soap request */
550
xmlnode = lasso_node_get_xmlNode(LASSO_NODE(envelope), TRUE);
552
handler = xmlFindCharEncodingHandler("utf-8");
553
buf = xmlAllocOutputBuffer(handler);
554
xmlNodeDumpOutput(buf, NULL, xmlnode, 0, 0, "utf-8");
555
xmlOutputBufferFlush(buf);
556
profile->msg_body = g_strdup(
557
(char*)(buf->conv ? buf->conv->content : buf->buffer->content));
558
xmlOutputBufferClose(buf);
559
xmlFreeNode(xmlnode);
112
lasso_wsf_profile_process_soap_request_msg(LassoWsfProfile *profile, const gchar *message)
565
lasso_wsf_profile_process_soap_request_msg(LassoWsfProfile *profile,
566
const gchar *message, const gchar *security_mech_id)
114
568
LassoSoapBindingCorrelation *correlation;
115
LassoSoapEnvelope *envelope;
569
LassoSoapEnvelope *envelope = NULL;
570
LassoSoapFault *fault = NULL;
116
572
gchar *messageId;
118
g_return_val_if_fail(LASSO_IS_WSF_PROFILE(profile),
119
LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
576
g_return_val_if_fail(LASSO_IS_WSF_PROFILE(profile), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ);
120
577
g_return_val_if_fail(message != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
122
envelope = LASSO_SOAP_ENVELOPE(lasso_node_new_from_dump(message));
579
profile->private_data->security_mech_id = g_strdup(security_mech_id);
581
doc = xmlParseMemory(message, strlen(message));
583
/* If X509 authentication mecanism, then verify signature */
584
if (lasso_security_mech_id_is_x509_authentication(security_mech_id) == TRUE) {
585
res = lasso_wsf_profile_verify_x509_authentication(profile, doc);
588
fault = lasso_soap_fault_new();
589
fault->faultstring = "Invalid signature";
592
/* FIXME: Remove Signature element if exists, it seg fault when a call to
593
lasso_node_new_from_xmlNode() */
595
xmlNode *xmlnode = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature,
598
xmlUnlinkNode(xmlnode);
599
xmlFreeNode(xmlnode);
603
envelope = LASSO_SOAP_ENVELOPE(lasso_node_new_from_xmlNode(xmlDocGetRootElement(doc)));
123
604
profile->soap_envelope_request = envelope;
124
profile->request = LASSO_NODE(envelope->Body->any->data);
126
/* FIXME: Process mustUnderstand attribute */
128
correlation = envelope->Header->Other->data;
605
profile->request = LASSO_NODE(envelope->Body->any->data);
606
correlation = LASSO_SOAP_BINDING_CORRELATION(envelope->Header->Other->data);
130
607
messageId = correlation->messageID;
131
envelope = lasso_wsf_profile_build_soap_envelope(messageId);
608
envelope = lasso_wsf_profile_build_soap_envelope(messageId,
609
LASSO_PROVIDER(profile->server)->ProviderID);
132
610
LASSO_WSF_PROFILE(profile)->soap_envelope_response = envelope;
613
envelope->Body->any = g_list_append(envelope->Body->any, fault);
614
profile->private_data->fault = fault;