tools: reimplement xmlURIEscapeStr to respect RFC3986 (#45581)

Bugfix by Emmanuel Dreyfus.

License: MIT
This commit is contained in:
Benjamin Dauvergne 2020-08-11 11:30:51 +02:00
parent 15b8cd7ab1
commit 0b742b1f6d
5 changed files with 64 additions and 11 deletions

View File

@ -21,6 +21,7 @@ Core
contributed under MIT license by XCG consulting contributed under MIT license by XCG consulting
- Simo Sorce <simo@redhat.com>, code review using Coverity and related - Simo Sorce <simo@redhat.com>, code review using Coverity and related
bugfixes, contributed under MIT license by Redhat Inc. bugfixes, contributed under MIT license by Redhat Inc.
- Emmanuel Dreyfus <manu@netbsd.org>, bug fixes, contributed under MIT license.
Unit Tests Unit Tests
========== ==========

View File

@ -988,11 +988,11 @@ lasso_login_build_artifact_msg(LassoLogin *login, LassoHttpMethod http_method)
} }
b64_samlArt = xmlStrdup((xmlChar*)login->assertionArtifact); b64_samlArt = xmlStrdup((xmlChar*)login->assertionArtifact);
relayState = xmlURIEscapeStr( relayState = lasso_xmlURIEscapeStr(
(xmlChar*)LASSO_LIB_AUTHN_REQUEST(profile->request)->RelayState, NULL); (xmlChar*)LASSO_LIB_AUTHN_REQUEST(profile->request)->RelayState, NULL);
if (http_method == LASSO_HTTP_METHOD_REDIRECT) { 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; gchar *query = NULL;
if (relayState == NULL) { if (relayState == NULL) {

View File

@ -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_get_relaystate_from_query(const char *query);
char * lasso_url_add_parameters(char *url, gboolean free, ...); 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_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, xmlSecKey* lasso_xmlsec_load_private_key(const char *filename_or_buffer, const char *password,
LassoSignatureMethod signature_method, const char *certificate); LassoSignatureMethod signature_method, const char *certificate);

View File

@ -36,6 +36,7 @@
#define _BSD_SOURCE #define _BSD_SOURCE
#include "private.h" #include "private.h"
#include <string.h> #include <string.h>
#include <strings.h>
#include <time.h> #include <time.h>
#include <ctype.h> #include <ctype.h>
#include <stdarg.h> #include <stdarg.h>
@ -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); new_query = g_strdup_printf("%s&SigAlg=%s", query, t);
xmlFree(BAD_CAST t); xmlFree(BAD_CAST t);
} }
@ -662,7 +663,7 @@ lasso_query_sign(char *query, LassoSignatureContext context)
/* Base64 encode the signature value */ /* Base64 encode the signature value */
b64_sigret = xmlSecBase64Encode(sigret, sigret_size, 0); b64_sigret = xmlSecBase64Encode(sigret, sigret_size, 0);
/* escape b64_sigret */ /* escape b64_sigret */
e_b64_sigret = xmlURIEscapeStr((xmlChar*)b64_sigret, NULL); e_b64_sigret = lasso_xmlURIEscapeStr((xmlChar*)b64_sigret, NULL);
/* add signature */ /* add signature */
switch (sign_method) { switch (sign_method) {
@ -1307,7 +1308,7 @@ lasso_xmlnode_build_deflated_query(xmlNode *xmlnode)
b64_ret = xmlSecBase64Encode(ret, stream.total_out, 0); b64_ret = xmlSecBase64Encode(ret, stream.total_out, 0);
lasso_release(ret); lasso_release(ret);
ret = xmlURIEscapeStr(b64_ret, NULL); ret = lasso_xmlURIEscapeStr(b64_ret, NULL);
rret = g_strdup((char*)ret); rret = g_strdup((char*)ret);
xmlFree(b64_ret); xmlFree(b64_ret);
xmlFree(ret); xmlFree(ret);
@ -2329,7 +2330,7 @@ lasso_url_add_parameters(char *url,
if (! key) { if (! key) {
break; break;
} }
encoded_key = xmlURIEscapeStr((xmlChar*)key, NULL); encoded_key = lasso_xmlURIEscapeStr((xmlChar*)key, NULL);
goto_cleanup_if_fail(encoded_key); goto_cleanup_if_fail(encoded_key);
value = va_arg(ap, char*); 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 !!"); message(G_LOG_LEVEL_CRITICAL, "lasso_url_add_parameter: key without a value !!");
break; break;
} }
encoded_value = xmlURIEscapeStr((xmlChar*)value, NULL); encoded_value = lasso_xmlURIEscapeStr((xmlChar*)value, NULL);
goto_cleanup_if_fail(encoded_value); goto_cleanup_if_fail(encoded_value);
if (old_url) { if (old_url) {
@ -2480,6 +2481,56 @@ lasso_base64_decode(const char *from, char **buffer, int *buffer_len)
return TRUE; 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: * lasso_xmlsec_load_private_key_from_buffer:
* @buffer: a buffer containing a key in any format * @buffer: a buffer containing a key in any format

View File

@ -3120,7 +3120,7 @@ get_value_by_path(LassoNode *node, char *path, struct XmlSnippet *xml_snippet)
s = xmlGetProp(t, a->name); s = xmlGetProp(t, a->name);
g_string_append(result, a->name); g_string_append(result, a->name);
g_string_append(result, "="); g_string_append(result, "=");
s2 = xmlURIEscapeStr(s, NULL); s2 = lasso_xmlURIEscapeStr(s, NULL);
g_string_append(result, s2); g_string_append(result, s2);
xmlFree(s2); xmlFree(s2);
xmlFree(s); 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, (char*)c->name);
g_string_append(result, "="); g_string_append(result, "=");
s = xmlNodeGetContent(c); s = xmlNodeGetContent(c);
s2 = xmlURIEscapeStr(s, NULL); s2 = lasso_xmlURIEscapeStr(s, NULL);
g_string_append(result, (char*)s2); g_string_append(result, (char*)s2);
xmlFree(s2); xmlFree(s2);
xmlFree(s); xmlFree(s);
@ -3263,7 +3263,7 @@ lasso_node_build_query_from_snippets(LassoNode *node)
g_string_append(s, "&"); g_string_append(s, "&");
g_string_append(s, field_name); g_string_append(s, field_name);
g_string_append(s, "="); g_string_append(s, "=");
t = xmlURIEscapeStr((xmlChar*)v, NULL); t = lasso_xmlURIEscapeStr((xmlChar*)v, NULL);
g_string_append(s, (char*)t); g_string_append(s, (char*)t);
xmlFree(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); value = lasso_node_build_deflated_query(node);
if (! value) if (! value)
goto cleanup; goto cleanup;
encoded_param = xmlURIEscapeStr(BAD_CAST param_name, NULL); encoded_param = lasso_xmlURIEscapeStr(BAD_CAST param_name, NULL);
if (! encoded_param) if (! encoded_param)
goto cleanup; goto cleanup;
query = g_strdup_printf("%s=%s", encoded_param, value); query = g_strdup_printf("%s=%s", encoded_param, value);