commit 50705614759a8daead0fad31999ee592be999b83 from: Omar Polo date: Tue May 16 19:41:12 2023 UTC for completeness, percent-decode the secret if needed it shouldn't EVER be needed, but since we handle URIs we should tick this box too. commit - 44703d29ff87d414604a05fc14a5621d34ba1c39 commit + 50705614759a8daead0fad31999ee592be999b83 blob - a5f580c44536a6a92993a9db1baf2d6493695f83 blob + 6958e6f56a5247866110c446af6b926966ef5f0c --- totp.c +++ totp.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, 2023 Omar Polo + * Copyright (c) 2014 Reyk Floeter * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -95,6 +96,43 @@ b32decode(const char *s, char *q, size_t qlen) return (q - t); } +/* adapted from httpd(8) */ +static char * +url_decode(char *url, char *dst) +{ + char *p, *q; + char hex[3]; + unsigned long x; + + hex[2] = '\0'; + p = url; + q = dst; + + while (*p != '\0') { + if (*p != '%') { + *q++ = *p++; + continue; + } + + if (!isxdigit((unsigned char)p[1]) || + !isxdigit((unsigned char)p[2])) + return (NULL); + + hex[0] = p[1]; + hex[1] = p[2]; + + /* + * We don't have to validate "hex" because it is + * guaranteed to include two hex chars followed by nul. + */ + x = strtoul(hex, NULL, 16); + *q++ = (char)x; + p += 3; + } + *q = '\0'; + return (url); +} + static int uri2secret(char *s) { @@ -111,7 +149,8 @@ uri2secret(char *s) if (secret == NULL) return (-1); - memmove(s, secret, strlen(secret) + 1); + if (url_decode(secret, s) == NULL) + errx(1, "failed to percent-decode the secret"); return (0); }