diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2024-01-14 14:27:26 +0100 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2024-02-01 21:39:21 +0100 |
commit | f126255d6ab62704d96a1fe490661969afc5a51e (patch) | |
tree | b637e98f51e6027fce4fb72cd4db2af4f128c532 /src | |
parent | 6cfb31c306b9deb120a9fb5c564a1456a72af665 (diff) | |
download | weechat-f126255d6ab62704d96a1fe490661969afc5a51e.zip |
core: add support of base64url in encode/decode functions (issue #2066)
Diffstat (limited to 'src')
-rw-r--r-- | src/core/wee-eval.c | 20 | ||||
-rw-r--r-- | src/core/wee-network.c | 2 | ||||
-rw-r--r-- | src/core/wee-string.c | 128 | ||||
-rw-r--r-- | src/core/wee-string.h | 8 | ||||
-rw-r--r-- | src/gui/curses/gui-curses-window.c | 2 | ||||
-rw-r--r-- | src/plugins/irc/irc-sasl.c | 20 | ||||
-rw-r--r-- | src/plugins/relay/relay-auth.c | 10 | ||||
-rw-r--r-- | src/plugins/relay/relay-config.c | 2 | ||||
-rw-r--r-- | src/plugins/relay/relay-http.c | 2 | ||||
-rw-r--r-- | src/plugins/relay/relay-websocket.c | 2 | ||||
-rw-r--r-- | src/plugins/script/script-repo.c | 2 | ||||
-rw-r--r-- | src/plugins/weechat-plugin.h | 6 |
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); |