diff --git a/README.md b/README.md index e160754..0a6c466 100644 --- a/README.md +++ b/README.md @@ -58,10 +58,14 @@ HTTPDirFS options: for HTTP range requests For mounting a Airsonic / Subsonic server: + --sonic-username The username for your Airsonic / Subsonic server - --sonic-password The username for your Airsonic / Subsonic server + --sonic-password The password for your Airsonic / Subsonic server --sonic-id3 Enable ID3 mode - this present the server content in Artist/Album/Song layout + --sonic-insecure Authenticate against your Airsonic / Subsonic server + using the insecure username / hex encoded password + scheme FUSE options: diff --git a/src/main.c b/src/main.c index 55c6110..cd4a81a 100644 --- a/src/main.c +++ b/src/main.c @@ -153,6 +153,7 @@ parse_arg_list(int argc, char **argv, char ***fuse_argv, int *fuse_argc) {"sonic-password", required_argument, NULL, 'L'}, /* 16 */ {"sonic-id3", no_argument, NULL, 'L'}, /* 17 */ {"no-range-check", no_argument, NULL, 'L'}, /* 18 */ + {"sonic-insecure", no_argument, NULL, 'L'}, /* 19 */ {0, 0, 0, 0} }; while ((c = @@ -232,6 +233,9 @@ parse_arg_list(int argc, char **argv, char ***fuse_argv, int *fuse_argc) case 18: CONFIG.no_range_check = 1; break; + case 19: + CONFIG.sonic_insecure = 1; + break; default: fprintf(stderr, "see httpdirfs -h for usage\n"); return 1; @@ -312,5 +316,8 @@ HTTPDirFS options:\n\ --sonic-password The username for your Airsonic / Subsonic server\n\ --sonic-id3 Enable ID3 mode - this present the server content in\n\ Artist/Album/Song layout \n\ + --sonic-insecure Authenticate against your Airsonic / Subsonic server\n\ + using the insecure username / hex encoded password\n\ + scheme\n\ \n"); } diff --git a/src/sonic.c b/src/sonic.c index a818e3d..f1f2f88 100644 --- a/src/sonic.c +++ b/src/sonic.c @@ -36,11 +36,19 @@ void sonic_config_init(const char *server, const char *username, SONIC_CONFIG.username = strndup(username, MAX_FILENAME_LEN); SONIC_CONFIG.password = strndup(password, MAX_FILENAME_LEN); SONIC_CONFIG.client = DEFAULT_USER_AGENT; - /* - * API 1.13.0 is the minimum version that supports - * salt authentication scheme - */ - SONIC_CONFIG.api_version = "1.13.0"; + + if (!CONFIG.sonic_insecure) { + /* + * API 1.13.0 is the minimum version that supports + * salt authentication scheme + */ + SONIC_CONFIG.api_version = "1.13.0"; + } else { + /* + * API 1.8.0 is the minimum version that supports ID3 mode + */ + SONIC_CONFIG.api_version = "1.8.0"; + } } /** @@ -48,21 +56,32 @@ void sonic_config_init(const char *server, const char *username, */ static char *sonic_gen_auth_str(void) { - char *salt = generate_salt(); - size_t password_len = strnlen(SONIC_CONFIG.password, MAX_FILENAME_LEN); - size_t password_salt_len = password_len + strnlen(salt, MAX_FILENAME_LEN); - char *password_salt = CALLOC(password_salt_len + 1, sizeof(char)); - strncat(password_salt, SONIC_CONFIG.password, MAX_FILENAME_LEN); - strncat(password_salt + password_len, salt, MAX_FILENAME_LEN); - char *token = generate_md5sum(password_salt); - char *auth_str = CALLOC(MAX_PATH_LEN + 1, sizeof(char)); - snprintf(auth_str, MAX_PATH_LEN, - ".view?u=%s&t=%s&s=%s&v=%s&c=%s", - SONIC_CONFIG.username, token, salt, - SONIC_CONFIG.api_version, SONIC_CONFIG.client); - free(salt); - free(token); - return auth_str; + if (!CONFIG.sonic_insecure) { + char *salt = generate_salt(); + size_t pwd_len = strnlen(SONIC_CONFIG.password, MAX_FILENAME_LEN); + size_t pwd_salt_len = pwd_len + strnlen(salt, MAX_FILENAME_LEN); + char *pwd_salt = CALLOC(pwd_salt_len + 1, sizeof(char)); + strncat(pwd_salt, SONIC_CONFIG.password, MAX_FILENAME_LEN); + strncat(pwd_salt + pwd_len, salt, MAX_FILENAME_LEN); + char *token = generate_md5sum(pwd_salt); + char *auth_str = CALLOC(MAX_PATH_LEN + 1, sizeof(char)); + snprintf(auth_str, MAX_PATH_LEN, + ".view?u=%s&t=%s&s=%s&v=%s&c=%s", + SONIC_CONFIG.username, token, salt, + SONIC_CONFIG.api_version, SONIC_CONFIG.client); + free(salt); + free(token); + return auth_str; + } else { + char *pwd_hex = str_to_hex(SONIC_CONFIG.password); + char *auth_str = CALLOC(MAX_PATH_LEN + 1, sizeof(char)); + snprintf(auth_str, MAX_PATH_LEN, + ".view?u=%s&p=enc:%s&v=%s&c=%s", + SONIC_CONFIG.username, pwd_hex, SONIC_CONFIG.api_version, + SONIC_CONFIG.client); + free(pwd_hex); + return auth_str; + } } /** @@ -144,6 +163,13 @@ static char *sonic_stream_link(const int id) static void XMLCALL XML_parser_index(void *data, const char *elem, const char **attr) { + if (!strcmp(elem, "error")) { + fprintf(stderr, "XML_parser_index() error:\n"); + for (int i = 0; attr[i]; i += 2) { + fprintf(stderr, "%s: %s\n", attr[i], attr[i+1]); + } + exit(EXIT_FAILURE); + } LinkTable *linktbl = (LinkTable *) data; Link *link; if (!strcmp(elem, "child") || !strcmp(elem, "artist")) { @@ -283,6 +309,14 @@ LinkTable *sonic_LinkTable_new_index(const int id) static void XMLCALL XML_parser_id3_root(void *data, const char *elem, const char **attr) { + if (!strcmp(elem, "error")) { + fprintf(stderr, "XML_parser_id3_root() error:\n"); + for (int i = 0; attr[i]; i += 2) { + fprintf(stderr, "%s: %s\n", attr[i], attr[i+1]); + } + exit(EXIT_FAILURE); + } + LinkTable *root_linktbl = (LinkTable *) data; LinkTable *this_linktbl = NULL; @@ -347,6 +381,14 @@ static void XMLCALL XML_parser_id3_root(void *data, const char *elem, static void XMLCALL XML_parser_id3(void *data, const char *elem, const char **attr) { + if (!strcmp(elem, "error")) { + fprintf(stderr, "XML_parser_id3() error:\n"); + for (int i = 0; attr[i]; i += 2) { + fprintf(stderr, "%s: %s\n", attr[i], attr[i+1]); + } + exit(EXIT_FAILURE); + } + LinkTable *linktbl = (LinkTable *) data; Link *link; diff --git a/src/util.c b/src/util.c index 7c723a8..3832e67 100644 --- a/src/util.c +++ b/src/util.c @@ -91,6 +91,8 @@ void Config_init(void) CONFIG.sonic_password = NULL; CONFIG.sonic_id3 = 0; + + CONFIG.sonic_insecure = 0; } char *path_append(const char *path, const char *filename) @@ -204,3 +206,11 @@ void *CALLOC(size_t nmemb, size_t size) return ptr; } +char *str_to_hex(char *s) +{ + char *hex = CALLOC(strlen(s) * 2 + 1, sizeof(char)); + for (char *c = s, *h = hex; *c; c++, h+=2) { + sprintf(h, "%x", *c); + } + return hex; +} diff --git a/src/util.h b/src/util.h index 2b87ce3..28c68d1 100644 --- a/src/util.h +++ b/src/util.h @@ -71,8 +71,10 @@ typedef struct { char *sonic_username; /** \brief The Sonic server password */ char *sonic_password; - /** \brief Whether we are using Sonic mode ID3 extension */ + /** \brief Whether we are using sonic mode ID3 extension */ int sonic_id3; + /** \brief Whether we use the legacy sonic authentication mode */ + int sonic_insecure; } ConfigStruct; /** @@ -132,6 +134,11 @@ char *generate_md5sum(const char *str); */ void *CALLOC(size_t nmemb, size_t size); +/** + * \brief Convert a string to hex + */ +char *str_to_hex(char *s); + /** * \brief initialise the configuration data structure */