summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2024-01-14 14:27:26 +0100
committerSébastien Helleu <flashcode@flashtux.org>2024-02-01 21:39:21 +0100
commitf126255d6ab62704d96a1fe490661969afc5a51e (patch)
treeb637e98f51e6027fce4fb72cd4db2af4f128c532 /src
parent6cfb31c306b9deb120a9fb5c564a1456a72af665 (diff)
downloadweechat-f126255d6ab62704d96a1fe490661969afc5a51e.zip
core: add support of base64url in encode/decode functions (issue #2066)
Diffstat (limited to 'src')
-rw-r--r--src/core/wee-eval.c20
-rw-r--r--src/core/wee-network.c2
-rw-r--r--src/core/wee-string.c128
-rw-r--r--src/core/wee-string.h8
-rw-r--r--src/gui/curses/gui-curses-window.c2
-rw-r--r--src/plugins/irc/irc-sasl.c20
-rw-r--r--src/plugins/relay/relay-auth.c10
-rw-r--r--src/plugins/relay/relay-config.c2
-rw-r--r--src/plugins/relay/relay-http.c2
-rw-r--r--src/plugins/relay/relay-websocket.c2
-rw-r--r--src/plugins/script/script-repo.c2
-rw-r--r--src/plugins/weechat-plugin.h6
12 files changed, 122 insertions, 82 deletions
diff --git a/src/core/wee-eval.c b/src/core/wee-eval.c
index 4f0f928ef..d1422500e 100644
--- a/src/core/wee-eval.c
+++ b/src/core/wee-eval.c
@@ -890,8 +890,7 @@ char *
eval_string_base_encode (const char *text)
{
const char *ptr_string;
- char *value, *base, *error, *result;
- long number;
+ char *value, *base, *result;
int length;
base = NULL;
@@ -905,18 +904,13 @@ eval_string_base_encode (const char *text)
if (!base)
goto end;
- error = NULL;
- number = strtol (base, &error, 10);
- if (!error || error[0])
- goto end;
-
ptr_string++;
length = strlen (ptr_string);
result = malloc ((length * 4) + 1);
if (!result)
goto end;
- if (string_base_encode (number, ptr_string, length, result) < 0)
+ if (string_base_encode (base, ptr_string, length, result) < 0)
{
free (result);
result = NULL;
@@ -941,8 +935,7 @@ char *
eval_string_base_decode (const char *text)
{
const char *ptr_string;
- char *value, *base, *error, *result;
- long number;
+ char *value, *base, *result;
base = NULL;
result = NULL;
@@ -955,17 +948,12 @@ eval_string_base_decode (const char *text)
if (!base)
goto end;
- error = NULL;
- number = strtol (base, &error, 10);
- if (!error || error[0])
- goto end;
-
ptr_string++;
result = malloc (strlen (ptr_string) + 1);
if (!result)
goto end;
- if (string_base_decode (number, ptr_string, result) < 0)
+ if (string_base_decode (base, ptr_string, result) < 0)
{
free (result);
result = NULL;
diff --git a/src/core/wee-network.c b/src/core/wee-network.c
index 0e3a995d3..dc26a38a5 100644
--- a/src/core/wee-network.c
+++ b/src/core/wee-network.c
@@ -448,7 +448,7 @@ network_pass_httpproxy (struct t_proxy *proxy, int sock, const char *address,
snprintf (authbuf, sizeof (authbuf), "%s:%s", username, password);
free (username);
free (password);
- if (string_base64_encode (authbuf, strlen (authbuf), authbuf_base64) < 0)
+ if (string_base64_encode (0, authbuf, strlen (authbuf), authbuf_base64) < 0)
return 0;
length = snprintf (buffer, sizeof (buffer),
"CONNECT %s:%d HTTP/1.0\r\nProxy-Authorization: "
diff --git a/src/core/wee-string.c b/src/core/wee-string.c
index 3087c4900..72a826502 100644
--- a/src/core/wee-string.c
+++ b/src/core/wee-string.c
@@ -3635,20 +3635,32 @@ string_base32_decode (const char *from, char *to)
*/
void
-string_convbase64_8x3_to_6x4 (const char *from, char *to)
+string_convbase64_8x3_to_6x4 (int url, const char *from, char *to)
{
unsigned char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz0123456789+/";
+ unsigned char base64_table_url[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz0123456789-_";
+ const unsigned char *ptr_table;
- to[0] = base64_table [ (from[0] & 0xfc) >> 2 ];
- to[1] = base64_table [ ((from[0] & 0x03) << 4) + ((from[1] & 0xf0) >> 4) ];
- to[2] = base64_table [ ((from[1] & 0x0f) << 2) + ((from[2] & 0xc0) >> 6) ];
- to[3] = base64_table [ from[2] & 0x3f ];
+ ptr_table = (url) ? base64_table_url : base64_table;
+
+ to[0] = ptr_table [ (from[0] & 0xfc) >> 2 ];
+ to[1] = ptr_table [ ((from[0] & 0x03) << 4) + ((from[1] & 0xf0) >> 4) ];
+ to[2] = ptr_table [ ((from[1] & 0x0f) << 2) + ((from[2] & 0xc0) >> 6) ];
+ to[3] = ptr_table [ from[2] & 0x3f ];
}
/*
* Encodes a string in base64.
*
+ * If url == 1, base64url is decoded, otherwise standard base64.
+ *
+ * Base64url is the same as base64 with these chars replaced:
+ * “+” --> “-” (minus)
+ * "/" --> “_” (underline)
+ * no padding char ("=")
+ *
* Argument "length" is number of bytes in "from" to convert (commonly
* strlen(from)).
*
@@ -3657,7 +3669,7 @@ string_convbase64_8x3_to_6x4 (const char *from, char *to)
*/
int
-string_base64_encode (const char *from, int length, char *to)
+string_base64_encode (int url, const char *from, int length, char *to)
{
const char *ptr_from;
char rest[3];
@@ -3671,7 +3683,7 @@ string_base64_encode (const char *from, int length, char *to)
while (length >= 3)
{
- string_convbase64_8x3_to_6x4 (ptr_from, to + count);
+ string_convbase64_8x3_to_6x4 (url, ptr_from, to + count);
ptr_from += 3;
count += 4;
length -= 3;
@@ -3686,21 +3698,28 @@ string_base64_encode (const char *from, int length, char *to)
{
case 1 :
rest[0] = ptr_from[0];
- string_convbase64_8x3_to_6x4 (rest, to + count);
+ string_convbase64_8x3_to_6x4 (url, rest, to + count);
count += 2;
- to[count] = '=';
- count++;
- to[count] = '=';
+ if (!url)
+ {
+ to[count] = '=';
+ count++;
+ to[count] = '=';
+ count++;
+ }
break;
case 2 :
rest[0] = ptr_from[0];
rest[1] = ptr_from[1];
- string_convbase64_8x3_to_6x4 (rest, to + count);
+ string_convbase64_8x3_to_6x4 (url, rest, to + count);
count += 3;
- to[count] = '=';
+ if (!url)
+ {
+ to[count] = '=';
+ count++;
+ }
break;
}
- count++;
to[count] = '\0';
}
else
@@ -3724,18 +3743,25 @@ string_convbase64_6x4_to_8x3 (const unsigned char *from, unsigned char *to)
/*
* Decodes a base64 string.
*
+ * If url == 1, base64url is decoded, otherwise standard base64.
+ *
+ * Base64url is the same as base64 with these chars replaced:
+ * “+” --> “-” (minus)
+ * "/" --> “_” (underline)
+ * no padding char ("=")
+ *
* Returns length of string in "*to" (it does not count final \0),
* -1 if error.
*/
int
-string_base64_decode (const char *from, char *to)
+string_base64_decode (int url, const char *from, char *to)
{
const char *ptr_from;
int length, to_length, i;
char *ptr_to;
unsigned char c, in[4], out[3];
- unsigned char base64_table[]="|$$$}rstuvwxyz{$$$$$$$>?"
+ unsigned char base64_table[] = "|$$$}rstuvwxyz{$$$$$$$>?"
"@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
if (!from || !to)
@@ -3759,6 +3785,10 @@ string_base64_decode (const char *from, char *to)
if (!ptr_from[0])
break;
c = (unsigned char) ptr_from[0];
+ if (url && (c == '-'))
+ c = '+';
+ else if (url && (c == '_'))
+ c = '/';
ptr_from++;
c = ((c < 43) || (c > 122)) ? 0 : base64_table[c - 43];
if (c)
@@ -3789,46 +3819,68 @@ string_base64_decode (const char *from, char *to)
}
/*
- * Encodes a string in base 16, 32, or 64.
+ * Encodes a string, according to "base" parameter:
+ * - "16": base16
+ * - "32": base32
+ * - "64": base64
+ * - "64url": base64url: same as base64 with no padding ("="), chars replaced:
+ * “+” --> “-” and "/" --> “_”
*
* Returns length of string in "*to" (it does not count final \0),
* -1 if error.
*/
int
-string_base_encode (int base, const char *from, int length, char *to)
+string_base_encode (const char *base, const char *from, int length, char *to)
{
- switch (base)
- {
- case 16:
- return string_base16_encode (from, length, to);
- case 32:
- return string_base32_encode (from, length, to);
- case 64:
- return string_base64_encode (from, length, to);
- }
+ if (!base || !from || (length <= 0) || !to)
+ return -1;
+
+ if (strcmp (base, "16") == 0)
+ return string_base16_encode (from, length, to);
+
+ if (strcmp (base, "32") == 0)
+ return string_base32_encode (from, length, to);
+
+ if (strcmp (base, "64") == 0)
+ return string_base64_encode (0, from, length, to);
+
+ if (strcmp (base, "64url") == 0)
+ return string_base64_encode (1, from, length, to);
+
return -1;
}
/*
- * Decodes a string encoded in base 16, 32, or 64.
+ * Decodes a string, according to "base" parameter:
+ * - "16": base16
+ * - "32": base32
+ * - "64": base64
+ * - "64url": base64url: same as base64 with no padding ("="), chars replaced:
+ * “+” --> “-” and "/" --> “_”
*
* Returns length of string in "*to" (it does not count final \0),
* -1 if error.
*/
int
-string_base_decode (int base, const char *from, char *to)
+string_base_decode (const char *base, const char *from, char *to)
{
- switch (base)
- {
- case 16:
- return string_base16_decode (from, to);
- case 32:
- return string_base32_decode (from, to);
- case 64:
- return string_base64_decode (from, to);
- }
+ if (!base || !from || !to)
+ return -1;
+
+ if (strcmp (base, "16") == 0)
+ return string_base16_decode (from, to);
+
+ if (strcmp (base, "32") == 0)
+ return string_base32_decode (from, to);
+
+ if (strcmp (base, "64") == 0)
+ return string_base64_decode (0, from, to);
+
+ if (strcmp (base, "64url") == 0)
+ return string_base64_decode (1, from, to);
+
return -1;
}
diff --git a/src/core/wee-string.h b/src/core/wee-string.h
index d98dd2d56..e79ce6279 100644
--- a/src/core/wee-string.h
+++ b/src/core/wee-string.h
@@ -129,11 +129,11 @@ extern int string_base16_encode (const char *from, int length, char *to);
extern int string_base16_decode (const char *from, char *to);
extern int string_base32_encode (const char *from, int length, char *to);
extern int string_base32_decode (const char *from, char *to);
-extern int string_base64_encode (const char *from, int length, char *to);
-extern int string_base64_decode (const char *from, char *to);
-extern int string_base_encode (int base, const char *from, int length,
+extern int string_base64_encode (int url, const char *from, int length, char *to);
+extern int string_base64_decode (int url, const char *from, char *to);
+extern int string_base_encode (const char *base, const char *from, int length,
char *to);
-extern int string_base_decode (int base, const char *from, char *to);
+extern int string_base_decode (const char *base, const char *from, char *to);
extern char *string_hex_dump (const char *data, int data_size,
int bytes_per_line,
const char *prefix, const char *suffix);
diff --git a/src/gui/curses/gui-curses-window.c b/src/gui/curses/gui-curses-window.c
index 6935fddb6..f7d9fe482 100644
--- a/src/gui/curses/gui-curses-window.c
+++ b/src/gui/curses/gui-curses-window.c
@@ -2646,7 +2646,7 @@ gui_window_send_clipboard (const char *storage_unit, const char *text)
text_base64 = malloc ((length * 4) + 1);
if (text_base64)
{
- if (string_base64_encode (text, length, text_base64) >= 0)
+ if (string_base64_encode (0, text, length, text_base64) >= 0)
{
fprintf (stderr, "\033]52;%s;%s\a",
(storage_unit) ? storage_unit : "",
diff --git a/src/plugins/irc/irc-sasl.c b/src/plugins/irc/irc-sasl.c
index 8a586ec05..9ae598c8a 100644
--- a/src/plugins/irc/irc-sasl.c
+++ b/src/plugins/irc/irc-sasl.c
@@ -75,7 +75,7 @@ irc_sasl_mechanism_plain (const char *sasl_username, const char *sasl_password)
answer_base64 = malloc (length * 4);
if (answer_base64)
{
- if (weechat_string_base_encode (64, string, length - 1,
+ if (weechat_string_base_encode ("64", string, length - 1,
answer_base64) < 0)
{
free (answer_base64);
@@ -148,7 +148,7 @@ irc_sasl_mechanism_scram (struct t_irc_server *server,
/* send username and nonce with form: "n,,n=username,r=nonce" */
gcry_create_nonce (nonce_client, sizeof (nonce_client));
length = weechat_string_base_encode (
- 64,
+ "64",
nonce_client, sizeof (nonce_client),
nonce_client_base64);
if (length != sizeof (nonce_client_base64) - 1)
@@ -176,7 +176,7 @@ irc_sasl_mechanism_scram (struct t_irc_server *server,
data = malloc (strlen (data_base64) + 1);
if (!data)
goto memory_error;
- if (weechat_string_base_decode (64, data_base64, data) <= 0)
+ if (weechat_string_base_decode ("64", data_base64, data) <= 0)
goto base64_decode_error;
/* split attributes */
@@ -239,7 +239,7 @@ irc_sasl_mechanism_scram (struct t_irc_server *server,
verifier = malloc (strlen (verifier_base64) + 1);
if (!verifier)
goto memory_error;
- verifier_size = weechat_string_base_decode (64, verifier_base64,
+ verifier_size = weechat_string_base_decode ("64", verifier_base64,
verifier);
if (verifier_size <= 0)
goto base64_decode_error;
@@ -292,7 +292,7 @@ irc_sasl_mechanism_scram (struct t_irc_server *server,
salt = malloc (strlen (salt_base64) + 1);
if (!salt)
goto memory_error;
- salt_size = weechat_string_base_decode (64, salt_base64, salt);
+ salt_size = weechat_string_base_decode ("64", salt_base64, salt);
if (salt_size <= 0)
goto base64_decode_error;
/* RFC: SaltedPassword := Hi(Normalize(password), salt, i) */
@@ -370,7 +370,7 @@ irc_sasl_mechanism_scram (struct t_irc_server *server,
client_proof[i] = ((unsigned char)client_key[i] ^
(unsigned char)client_signature[i]);
}
- if (weechat_string_base_encode (64, client_proof, client_key_size,
+ if (weechat_string_base_encode ("64", client_proof, client_key_size,
client_proof_base64) < 0)
goto base64_encode_error;
/* final message: auth_no_proof + "," + proof */
@@ -422,7 +422,7 @@ end:
answer_base64 = malloc ((length + 1) * 4);
if (answer_base64)
{
- if (weechat_string_base_encode (64, string, length,
+ if (weechat_string_base_encode ("64", string, length,
answer_base64) < 0)
{
free (answer_base64);
@@ -565,7 +565,7 @@ irc_sasl_mechanism_ecdsa_nist256p_challenge (struct t_irc_server *server,
data = malloc (strlen (data_base64) + 1);
if (!data)
return NULL;
- length_data = weechat_string_base_decode (64, data_base64, data);
+ length_data = weechat_string_base_decode ("64", data_base64, data);
/* read file with private key */
str_privkey = irc_sasl_get_key_content (sasl_key, sasl_error);
@@ -613,7 +613,7 @@ irc_sasl_mechanism_ecdsa_nist256p_challenge (struct t_irc_server *server,
pubkey_base64 = malloc ((x.size + 1 + 1) * 4);
if (pubkey_base64)
{
- if (weechat_string_base_encode (64, pubkey, x.size + 1,
+ if (weechat_string_base_encode ("64", pubkey, x.size + 1,
pubkey_base64) >= 0)
{
weechat_printf (
@@ -690,7 +690,7 @@ irc_sasl_mechanism_ecdsa_nist256p_challenge (struct t_irc_server *server,
answer_base64 = malloc ((length + 1) * 4);
if (answer_base64)
{
- if (weechat_string_base_encode (64, string, length,
+ if (weechat_string_base_encode ("64", string, length,
answer_base64) < 0)
{
free (answer_base64);
diff --git a/src/plugins/relay/relay-auth.c b/src/plugins/relay/relay-auth.c
index f86b1aeb1..76bdf35a7 100644
--- a/src/plugins/relay/relay-auth.c
+++ b/src/plugins/relay/relay-auth.c
@@ -92,7 +92,7 @@ relay_auth_generate_nonce (int size)
}
gcry_create_nonce ((unsigned char *)nonce, size);
- weechat_string_base_encode (16, nonce, size, nonce_hexa);
+ weechat_string_base_encode ("16", nonce, size, nonce_hexa);
free (nonce);
@@ -177,7 +177,7 @@ relay_auth_parse_sha (const char *parameters,
*salt = malloc (strlen (argv[0]) + 1);
if (*salt)
{
- *salt_size = weechat_string_base_decode (16, argv[0], *salt);
+ *salt_size = weechat_string_base_decode ("16", argv[0], *salt);
if (*salt_size > 0)
*salt_hexa = strdup (argv[0]);
else
@@ -236,7 +236,7 @@ relay_auth_parse_pbkdf2 (const char *parameters,
*salt = malloc (strlen (argv[0]) + 1);
if (*salt)
{
- *salt_size = weechat_string_base_decode (16, argv[0], *salt);
+ *salt_size = weechat_string_base_decode ("16", argv[0], *salt);
if (*salt_size > 0)
*salt_hexa = strdup (argv[0]);
else
@@ -315,7 +315,7 @@ relay_auth_check_hash_sha (const char *hash_algo,
hash_algo,
hash, &hash_size))
{
- weechat_string_base_encode (16, hash, hash_size,
+ weechat_string_base_encode ("16", hash, hash_size,
hash_hexa);
if (weechat_strcasecmp (hash_hexa, hash_sha) == 0)
rc = 1;
@@ -357,7 +357,7 @@ relay_auth_check_hash_pbkdf2 (const char *hash_pbkdf2_algo,
iterations,
hash, &hash_size))
{
- weechat_string_base_encode (16, hash, hash_size, hash_hexa);
+ weechat_string_base_encode ("16", hash, hash_size, hash_hexa);
if (weechat_strcasecmp (hash_hexa, hash_pbkdf2) == 0)
rc = 1;
}
diff --git a/src/plugins/relay/relay-config.c b/src/plugins/relay/relay-config.c
index 634868282..b0f6beeca 100644
--- a/src/plugins/relay/relay-config.c
+++ b/src/plugins/relay/relay-config.c
@@ -382,7 +382,7 @@ relay_config_check_network_totp_secret (const void *pointer, void *data,
secret = malloc (strlen (totp_secret) + 1);
if (!secret)
goto error;
- length = weechat_string_base_decode (32, totp_secret, secret);
+ length = weechat_string_base_decode ("32", totp_secret, secret);
if (length < 0)
goto error;
}
diff --git a/src/plugins/relay/relay-http.c b/src/plugins/relay/relay-http.c
index a4a9a4050..a59552599 100644
--- a/src/plugins/relay/relay-http.c
+++ b/src/plugins/relay/relay-http.c
@@ -558,7 +558,7 @@ relay_http_check_auth (struct t_relay_http_request *request)
rc = -5;
goto end;
}
- length = weechat_string_base_decode (64, pos, user_pass);
+ length = weechat_string_base_decode ("64", pos, user_pass);
if (length < 0)
{
rc = -2;
diff --git a/src/plugins/relay/relay-websocket.c b/src/plugins/relay/relay-websocket.c
index 4ea3208a5..760128c01 100644
--- a/src/plugins/relay/relay-websocket.c
+++ b/src/plugins/relay/relay-websocket.c
@@ -404,7 +404,7 @@ relay_websocket_build_handshake (struct t_relay_http_request *request)
free (key);
return NULL;
}
- if (weechat_string_base_encode (64, hash, hash_size,
+ if (weechat_string_base_encode ("64", hash, hash_size,
sec_websocket_accept) < 0)
{
sec_websocket_accept[0] = '\0';
diff --git a/src/plugins/script/script-repo.c b/src/plugins/script/script-repo.c
index 446896f0b..5c45ab5a0 100644
--- a/src/plugins/script/script-repo.c
+++ b/src/plugins/script/script-repo.c
@@ -765,7 +765,7 @@ script_repo_sha512sum_file (const char *filename)
if (!weechat_crypto_hash_file (filename, "sha512", hash, &hash_size))
return NULL;
- weechat_string_base_encode (16, hash, hash_size, hash_hexa);
+ weechat_string_base_encode ("16", hash, hash_size, hash_hexa);
return weechat_string_tolower (hash_hexa);
}
diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h
index 398d41f5a..3711fab1d 100644
--- a/src/plugins/weechat-plugin.h
+++ b/src/plugins/weechat-plugin.h
@@ -71,7 +71,7 @@ struct timeval;
* please change the date with current one; for a second change at same
* date, increment the 01, otherwise please keep 01.
*/
-#define WEECHAT_PLUGIN_API_VERSION "20240105-01"
+#define WEECHAT_PLUGIN_API_VERSION "20240114-01"
/* macros for defining plugin infos */
#define WEECHAT_PLUGIN_NAME(__name) \
@@ -371,9 +371,9 @@ struct t_weechat_plugin
unsigned long long (*string_parse_size) (const char *size);
int (*string_color_code_size) (const char *string);
char *(*string_remove_color) (const char *string, const char *replacement);
- int (*string_base_encode) (int base, const char *from, int length,
+ int (*string_base_encode) (const char *base, const char *from, int length,
char *to);
- int (*string_base_decode) (int base, const char *from, char *to);
+ int (*string_base_decode) (const char *base, const char *from, char *to);
char *(*string_hex_dump) (const char *data, int data_size,
int bytes_per_line, const char *prefix,
const char *suffix);