diff --git a/lasso/id-ff/login.c b/lasso/id-ff/login.c index 0f4e8926..68693ffe 100644 --- a/lasso/id-ff/login.c +++ b/lasso/id-ff/login.c @@ -988,11 +988,11 @@ lasso_login_build_artifact_msg(LassoLogin *login, LassoHttpMethod http_method) } b64_samlArt = xmlStrdup((xmlChar*)login->assertionArtifact); - relayState = xmlURIEscapeStr( + relayState = lasso_xmlURIEscapeStr( (xmlChar*)LASSO_LIB_AUTHN_REQUEST(profile->request)->RelayState, NULL); if (http_method == LASSO_HTTP_METHOD_REDIRECT) { - xmlChar *escaped_artifact = xmlURIEscapeStr(b64_samlArt, NULL); + xmlChar *escaped_artifact = lasso_xmlURIEscapeStr(b64_samlArt, NULL); gchar *query = NULL; if (relayState == NULL) { diff --git a/lasso/xml/private.h b/lasso/xml/private.h index 52a21e56..a2b47aa4 100644 --- a/lasso/xml/private.h +++ b/lasso/xml/private.h @@ -287,6 +287,7 @@ gboolean lasso_eval_xpath_expression(xmlXPathContextPtr xpath_ctx, const char *e char * lasso_get_relaystate_from_query(const char *query); char * lasso_url_add_parameters(char *url, gboolean free, ...); +xmlChar * lasso_xmlURIEscapeStr(const xmlChar *from, const xmlChar *list); xmlSecKey* lasso_xmlsec_load_private_key_from_buffer(const char *buffer, size_t length, const char *password, LassoSignatureMethod signature_method, const char *certificate); xmlSecKey* lasso_xmlsec_load_private_key(const char *filename_or_buffer, const char *password, LassoSignatureMethod signature_method, const char *certificate); diff --git a/lasso/xml/tools.c b/lasso/xml/tools.c index 53d7d37b..589a795d 100644 --- a/lasso/xml/tools.c +++ b/lasso/xml/tools.c @@ -36,6 +36,7 @@ #define _BSD_SOURCE #include "private.h" #include +#include #include #include #include @@ -540,7 +541,7 @@ lasso_query_sign(char *query, LassoSignatureContext context) } { - const char *t = (char*)xmlURIEscapeStr(algo_href, NULL); + const char *t = (char*)lasso_xmlURIEscapeStr(algo_href, NULL); new_query = g_strdup_printf("%s&SigAlg=%s", query, t); xmlFree(BAD_CAST t); } @@ -662,7 +663,7 @@ lasso_query_sign(char *query, LassoSignatureContext context) /* Base64 encode the signature value */ b64_sigret = xmlSecBase64Encode(sigret, sigret_size, 0); /* escape b64_sigret */ - e_b64_sigret = xmlURIEscapeStr((xmlChar*)b64_sigret, NULL); + e_b64_sigret = lasso_xmlURIEscapeStr((xmlChar*)b64_sigret, NULL); /* add signature */ switch (sign_method) { @@ -1307,7 +1308,7 @@ lasso_xmlnode_build_deflated_query(xmlNode *xmlnode) b64_ret = xmlSecBase64Encode(ret, stream.total_out, 0); lasso_release(ret); - ret = xmlURIEscapeStr(b64_ret, NULL); + ret = lasso_xmlURIEscapeStr(b64_ret, NULL); rret = g_strdup((char*)ret); xmlFree(b64_ret); xmlFree(ret); @@ -2329,7 +2330,7 @@ lasso_url_add_parameters(char *url, if (! key) { break; } - encoded_key = xmlURIEscapeStr((xmlChar*)key, NULL); + encoded_key = lasso_xmlURIEscapeStr((xmlChar*)key, NULL); goto_cleanup_if_fail(encoded_key); value = va_arg(ap, char*); @@ -2337,7 +2338,7 @@ lasso_url_add_parameters(char *url, message(G_LOG_LEVEL_CRITICAL, "lasso_url_add_parameter: key without a value !!"); break; } - encoded_value = xmlURIEscapeStr((xmlChar*)value, NULL); + encoded_value = lasso_xmlURIEscapeStr((xmlChar*)value, NULL); goto_cleanup_if_fail(encoded_value); if (old_url) { @@ -2480,6 +2481,56 @@ lasso_base64_decode(const char *from, char **buffer, int *buffer_len) return TRUE; } +/** + * lasso_xmlURIEscapeStr: + * @from: the source URI string + * @list: optional list of characters not to escape + * + * Drop-in replacement for libxml2 xmlURIEscapeStr(), but encoding + * everything but [A-Za-z0-9._~-] which are the unreserved chartacters + * for RFC3986 section 2.3 + * + * Return value: a buffer containing the URL-encoded string or NULL on error + */ +xmlChar * +lasso_xmlURIEscapeStr(const xmlChar *from, const xmlChar *list) +{ + size_t len = 0; + const xmlChar *fp; + xmlChar *result; + int ri; + + if (list == NULL) + list = ""; + + for (fp = from; *fp; fp++) { + if (isalnum(*fp) || index("._~-", *fp) || index(list, *fp)) + len++; + else + len += 3; + } + + result = g_malloc0(len + 1); + ri = 0; + + for (fp = from; *fp; fp++) { + if (isalnum(*fp) || index("._~-", *fp) || index(list, *fp)) { + result[ri++] = *fp; + } else { + int msb = (*fp & 0xf0) >> 4; + int lsb = *fp & 0x0f; + + result[ri++] = '%'; + result[ri++] = (msb > 9) ? 'A' + msb - 10 : '0' + msb; + result[ri++] = (lsb > 9) ? 'A' + lsb - 10 : '0' + lsb; + } + } + + result[ri++] = '\0'; + + return result; +} + /** * lasso_xmlsec_load_private_key_from_buffer: * @buffer: a buffer containing a key in any format diff --git a/lasso/xml/xml.c b/lasso/xml/xml.c index 565172e1..938844ba 100644 --- a/lasso/xml/xml.c +++ b/lasso/xml/xml.c @@ -3120,7 +3120,7 @@ get_value_by_path(LassoNode *node, char *path, struct XmlSnippet *xml_snippet) s = xmlGetProp(t, a->name); g_string_append(result, a->name); g_string_append(result, "="); - s2 = xmlURIEscapeStr(s, NULL); + s2 = lasso_xmlURIEscapeStr(s, NULL); g_string_append(result, s2); xmlFree(s2); xmlFree(s); @@ -3140,7 +3140,7 @@ get_value_by_path(LassoNode *node, char *path, struct XmlSnippet *xml_snippet) g_string_append(result, (char*)c->name); g_string_append(result, "="); s = xmlNodeGetContent(c); - s2 = xmlURIEscapeStr(s, NULL); + s2 = lasso_xmlURIEscapeStr(s, NULL); g_string_append(result, (char*)s2); xmlFree(s2); xmlFree(s); @@ -3263,7 +3263,7 @@ lasso_node_build_query_from_snippets(LassoNode *node) g_string_append(s, "&"); g_string_append(s, field_name); g_string_append(s, "="); - t = xmlURIEscapeStr((xmlChar*)v, NULL); + t = lasso_xmlURIEscapeStr((xmlChar*)v, NULL); g_string_append(s, (char*)t); xmlFree(t); } @@ -3634,7 +3634,7 @@ lasso_node_export_to_saml2_query(LassoNode *node, const char *param_name, const value = lasso_node_build_deflated_query(node); if (! value) goto cleanup; - encoded_param = xmlURIEscapeStr(BAD_CAST param_name, NULL); + encoded_param = lasso_xmlURIEscapeStr(BAD_CAST param_name, NULL); if (! encoded_param) goto cleanup; query = g_strdup_printf("%s=%s", encoded_param, value);