summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Dauvergne <bdauvergne@entrouvert.com>2010-02-10 00:33:45 +0000
committerBenjamin Dauvergne <bdauvergne@entrouvert.com>2010-02-10 00:33:45 +0000
commit72dc2ff63d72e2db7d94034331b4f1ba280fad1c (patch)
tree8f37e0ea53912fde5e1bbf70783bb3e404b2771a
parentc74224c5c9264ac6f703e26416a43a4034cd5d04 (diff)
downloadlasso-72dc2ff63d72e2db7d94034331b4f1ba280fad1c.tar.gz
lasso-72dc2ff63d72e2db7d94034331b4f1ba280fad1c.tar.xz
lasso-72dc2ff63d72e2db7d94034331b4f1ba280fad1c.zip
Add a function to validate query signatures using SAML 2.0 semantic
* lasso/xml/tools.c: this new function is a placeholder for the new SAML 2.0 semantic following query signature validation function. It will start with the old code of lasso_query_verify_signature.
-rw-r--r--lasso/xml/private.h2
-rw-r--r--lasso/xml/tools.c119
2 files changed, 121 insertions, 0 deletions
diff --git a/lasso/xml/private.h b/lasso/xml/private.h
index df2e46f7..a8711b70 100644
--- a/lasso/xml/private.h
+++ b/lasso/xml/private.h
@@ -128,6 +128,8 @@ char* lasso_query_sign(char *query, LassoSignatureMethod sign_method,
int lasso_query_verify_signature(const char *query, const xmlSecKey *public_key);
+int lasso_saml2_query_verify_signature(const char *query, const xmlSecKey *sender_public_key);
+
char* lasso_sha1(const char *str);
char** urlencoded_to_strings(const char *str);
diff --git a/lasso/xml/tools.c b/lasso/xml/tools.c
index 18a5eb3a..c0bcaa9a 100644
--- a/lasso/xml/tools.c
+++ b/lasso/xml/tools.c
@@ -668,6 +668,125 @@ done:
}
/**
+ * lasso_saml2_query_verify_signature(const char *query, const xmlSecKey *sender_public_key):
+ * @query: a query string
+ * @sender_public_key: the #xmlSecKey for the sender
+ *
+ * Verify a query signature following SAML 2.0 semantic.
+ *
+ * Return value: 0 if signature is validated, an error code otherwise.
+ */
+int
+lasso_saml2_query_verify_signature(const char *query, const xmlSecKey *sender_public_key)
+{
+ RSA *rsa = NULL;
+ DSA *dsa = NULL;
+ gchar **str_split = NULL;
+ char *digest = NULL, *b64_signature = NULL;
+ xmlSecByte *signature = NULL;
+ int key_size, status = 0, ret = 0;
+ char *sig_alg, *usig_alg = NULL;
+
+ g_return_val_if_fail(query != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
+
+ if (lasso_flag_verify_signature == FALSE) {
+ return 0;
+ }
+
+ g_return_val_if_fail(sender_public_key != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
+ g_return_val_if_fail(sender_public_key->value != NULL, LASSO_PARAM_ERROR_INVALID_VALUE);
+
+ /* split query, the signature MUST be the last param of the query
+ * actually there could be more params in the URL; but they wouldn't be
+ * covered by the signature */
+
+ str_split = g_strsplit(query, "&Signature=", 0);
+ if (str_split[0] == NULL || str_split[1] == NULL) {
+ g_strfreev(str_split);
+ return LASSO_DS_ERROR_SIGNATURE_NOT_FOUND;
+ }
+
+ if (sender_public_key->value->id == xmlSecOpenSSLKeyDataRsaId) {
+ } else {
+ /* no key; it will fail later */
+ }
+
+ sig_alg = strstr(str_split[0], "&SigAlg=");
+ if (sig_alg == NULL) {
+ ret = critical_error(LASSO_DS_ERROR_INVALID_SIGALG);
+ goto done;
+ }
+ sig_alg = strchr(sig_alg, '=')+1;
+
+ usig_alg = xmlURIUnescapeString(sig_alg, 0, NULL);
+ if (strcmp(usig_alg, (char*)xmlSecHrefRsaSha1) == 0) {
+ if (sender_public_key->value->id != xmlSecOpenSSLKeyDataRsaId) {
+ ret = critical_error(LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED);
+ goto done;
+ }
+ rsa = xmlSecOpenSSLKeyDataRsaGetRsa(sender_public_key->value);
+ if (rsa == NULL) {
+ ret = critical_error(LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED);
+ goto done;
+ }
+ key_size = RSA_size(rsa);
+ } else if (strcmp(usig_alg, (char*)xmlSecHrefDsaSha1) == 0) {
+ if (sender_public_key->value->id != xmlSecOpenSSLKeyDataDsaId) {
+ ret = critical_error(LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED);
+ goto done;
+ }
+ dsa = xmlSecOpenSSLKeyDataDsaGetDsa(sender_public_key->value);
+ if (dsa == NULL) {
+ ret = critical_error(LASSO_DS_ERROR_PUBLIC_KEY_LOAD_FAILED);
+ goto done;
+ }
+ key_size = DSA_size(dsa);
+ } else {
+ ret = critical_error(LASSO_DS_ERROR_INVALID_SIGALG);
+ goto done;
+ }
+
+ /* insure there is only the signature in str_split[1] */
+ if (strchr(str_split[1], '&')) {
+ strchr(str_split[1], '&')[0] = 0;
+ }
+
+ /* get signature (unescape + base64 decode) */
+ signature = xmlMalloc(key_size+1);
+ b64_signature = (char*)xmlURIUnescapeString(str_split[1], 0, NULL);
+ if (b64_signature == NULL || xmlSecBase64Decode((xmlChar*)b64_signature, signature, key_size+1) < 0) {
+ ret = LASSO_DS_ERROR_INVALID_SIGNATURE;
+ goto done;
+ }
+
+ /* compute signature digest */
+ digest = lasso_sha1(str_split[0]);
+ if (digest == NULL) {
+ ret = critical_error(LASSO_DS_ERROR_DIGEST_COMPUTE_FAILED);
+ goto done;
+ }
+
+ if (rsa) {
+ status = RSA_verify(NID_sha1, (unsigned char*)digest, 20, signature, key_size, rsa);
+ } else if (dsa) {
+ status = DSA_verify(NID_sha1, (unsigned char*)digest, 20, signature, key_size, dsa);
+ }
+
+ if (status != 1) {
+ ret = LASSO_DS_ERROR_INVALID_SIGNATURE;
+ }
+
+done:
+ xmlFree(b64_signature);
+ xmlFree(signature);
+ xmlFree(digest);
+ xmlFree(usig_alg);
+ g_strfreev(str_split);
+
+ return ret;
+}
+
+/**
* lasso_sha1:
* @str: a string
*