[httpd] Fix for password-based auth for Apple Music

Adds handling of the username from Apple Music that contain colon. Example:
iTunes_Music/1.4.5 (Macintosh; OS X 14.5) AppleWebKit/618.2.12.11.6 build/36 (dt:1):password

Closes #1778
This commit is contained in:
ejurgensen 2024-08-02 16:34:57 +02:00
parent 59bba5e261
commit cab0204d29

View File

@ -207,6 +207,40 @@ content_type_from_profile(enum transcode_profile profile)
return NULL; return NULL;
} }
static int
basic_auth_cred_extract(char **user, char **pwd, const char *auth)
{
char *decoded = NULL;
regex_t preg = { 0 };
regmatch_t matchptr[3]; // Room for entire string, username substring and password substring
int ret;
decoded = (char *)b64_decode(NULL, auth);
if (!decoded)
goto error;
// Apple Music gives is "(dt:1):password", which we need to support even if it
// isn't according to the basic auth RFC that says the username cannot include
// a colon
ret = regcomp(&preg, "(\\(.*?\\)|[^:]*):(.*)", REG_EXTENDED);
if (ret != 0)
goto error;
ret = regexec(&preg, decoded, ARRAY_SIZE(matchptr), matchptr, 0);
if (ret != 0 || matchptr[1].rm_so == -1 || matchptr[2].rm_so == -1)
goto error;
*user = strndup(decoded + matchptr[1].rm_so, matchptr[1].rm_eo - matchptr[1].rm_so);
*pwd = strndup(decoded + matchptr[2].rm_so, matchptr[2].rm_eo - matchptr[2].rm_so);
free(decoded);
return 0;
error:
free(decoded);
return -1;
}
/* --------------------------- MODULES INTERFACE ---------------------------- */ /* --------------------------- MODULES INTERFACE ---------------------------- */
@ -1432,26 +1466,14 @@ httpd_basic_auth(struct httpd_request *hreq, const char *user, const char *passw
auth += strlen("Basic "); auth += strlen("Basic ");
authuser = (char *)b64_decode(NULL, auth); ret = basic_auth_cred_extract(&authuser, &authpwd, auth);
if (!authuser) if (ret < 0)
{
DPRINTF(E_LOG, L_HTTPD, "Could not decode Authentication header\n");
goto need_auth;
}
authpwd = strchr(authuser, ':');
if (!authpwd)
{ {
DPRINTF(E_LOG, L_HTTPD, "Malformed Authentication header\n"); DPRINTF(E_LOG, L_HTTPD, "Malformed Authentication header\n");
free(authuser);
goto need_auth; goto need_auth;
} }
*authpwd = '\0';
authpwd++;
if (user) if (user)
{ {
if (strcmp(user, authuser) != 0) if (strcmp(user, authuser) != 0)
@ -1459,6 +1481,7 @@ httpd_basic_auth(struct httpd_request *hreq, const char *user, const char *passw
DPRINTF(E_LOG, L_HTTPD, "Username mismatch\n"); DPRINTF(E_LOG, L_HTTPD, "Username mismatch\n");
free(authuser); free(authuser);
free(authpwd);
goto need_auth; goto need_auth;
} }
} }
@ -1468,11 +1491,12 @@ httpd_basic_auth(struct httpd_request *hreq, const char *user, const char *passw
DPRINTF(E_LOG, L_HTTPD, "Bad password\n"); DPRINTF(E_LOG, L_HTTPD, "Bad password\n");
free(authuser); free(authuser);
free(authpwd);
goto need_auth; goto need_auth;
} }
free(authuser); free(authuser);
free(authpwd);
return 0; return 0;
need_auth: need_auth: