clean up digest verification in pairing,c

This commit is contained in:
F. Duncanh
2025-04-23 03:12:59 -04:00
parent e731140515
commit f8ad47d9b4
4 changed files with 44 additions and 31 deletions

View File

@@ -1,9 +1,9 @@
# UxPlay 1.72 (beta): AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix (now also runs on Windows).
# UxPlay 1.72 (beta): AirPlay-Mirror and AirPlay-Audio server for Linux, macOS, and Unix (also runs on Windows).
### **Now developed at the GitHub site <https://github.com/FDH2/UxPlay> (where ALL user issues should be posted, and latest versions can be found).**
- ***NEW in v1.72**: Improved Support for (YouTube) HLS (HTTP Live Streaming)
video with the new "-hls" option.* **Only streaming from the YouTube iOS app
video with the new "-hls" option (introduced in 1.71).* **Only streaming from the YouTube iOS app
(in \"m3u8\" protocol) is currently supported**: (streaming using the AirPlay icon in a browser window
is **not** yet supported).Click on the airplay icon in the
YouTube app to stream video.
@@ -13,10 +13,10 @@
GStreamer playbin v3: use "-hls 2" to revert to playbin v2 if
some videos fail to play_.
* added support for setting a password (as an alternative to on-screen
* user-requested features: added support for setting a password (as an alternative to on-screen
pin codes) to control client access (-pw option); added support for
setting initial audion volume (--vol option), and output of audio-mode
metatdate to file (for display, -md option).
setting initial client audio-streaming volume (-vol option), and output of audio-mode
metadata to file (for display by some external process, -md option).
## Highlights:

View File

@@ -246,9 +246,10 @@ char *get_token(char **cursor, char *token_name, char start_char, char end_char)
bool
pairing_digest_verify(const char *method, const char * authorization, const char *password) {
/* RFC 2617 HTTP md5 Digest password authentication */
char *sentence = (char *) calloc(strlen(authorization) + 1, sizeof(char));
strncpy(sentence, authorization, strlen(authorization));
size_t authlen = strlen(authorization);
char *sentence = (char *) malloc(authlen + 1);
memcpy(sentence, authorization, authlen);
*(sentence + authlen) = '\0';
char *username = NULL;
char *realm = NULL;
char *nonce = NULL;
@@ -309,35 +310,50 @@ pairing_digest_verify(const char *method, const char * authorization, const char
/* H1 = H(username : realm : password ) */
len = strlen(username) + strlen(realm) + strlen(pwd) + 3;
raw = (char *) calloc(len, sizeof(char));
snprintf(raw, len, "%s:%s:%s", username, realm, pwd);
strncat(raw, username, len - strlen(raw) - 1);
strncat(raw, ":", len - strlen(raw) - 1);
strncat(raw, realm, len - strlen(raw) - 1);
strncat(raw, ":", len - strlen(raw) - 1);
strncat(raw, pwd, len - strlen(raw) - 1);
char *hash1 = get_md5(raw);
free (raw);
#ifdef test_digest
printf("hash1: should be %s, was: %s\n ", HA1, hash1_str);
printf("hash1: should be %s, was: %s\n", HA1, hash1);
#endif
/* H2 = H(method : uri) */
len = strlen(mthd) + strlen(uri) + 2;
raw = (char *) calloc(len, sizeof(char));
snprintf(raw, len, "%s:%s", mthd, uri);
strncat(raw, mthd, len - strlen(raw) - 1);
strncat(raw, ":", len - strlen(raw) - 1);
strncat(raw, uri, len - strlen(raw) - 1);
char *hash2 = get_md5(raw);
free (raw);
#ifdef test_digest
printf("hash2: should be %s, was: %s\n", HA2, hash2_str);
printf("hash2: should be %s, was: %s\n", HA2, hash2);
#endif
/* result = H(H1 : nonce (or nonce:nc:cnonce:qop) : H2) */
len = strlen(hash1) + strlen(nonce) + strlen(hash2) + 3;
if (qop) {
len += strlen(nc) + strlen(cnonce) + strlen(qop) + 3;
raw = (char *) calloc(len, sizeof(char));
snprintf(raw, len, "%s:%s:%s:%s:%s:%s", hash1, nonce, nc, cnonce, qop, hash2);
} else {
raw = (char *) calloc(len, sizeof(char));
snprintf(raw, len, "%s:%s:%s", hash1, nonce, hash2);
}
raw = (char *) calloc(len, sizeof(char));
strncat(raw, hash1, len - strlen(raw) - 1);
strncat(raw, ":", len - strlen(raw) - 1);
strncat(raw, nonce, len - strlen(raw) - 1);
strncat(raw, ":", len - strlen(raw) - 1);
if (qop) {
strncat(raw, nc, len - strlen(raw) - 1);
strncat(raw, ":", len - strlen(raw) - 1);
strncat(raw, cnonce, len - strlen(raw) - 1);
strncat(raw, ":", len - strlen(raw) - 1);
strncat(raw, qop, len - strlen(raw) - 1);
strncat(raw, ":", len - strlen(raw) - 1);
}
strncat(raw, hash2, len - strlen(raw) - 1);
free (hash1);
free (hash2);
char *result = get_md5(raw);

View File

@@ -597,18 +597,16 @@ raop_handler_setup(raop_conn_t *conn,
}
char pin[6] = {'\0'};
snprintf(pin, 5, "%04u", pin_4 % 10000);
printf("*** set new pin = [%s]\n", pin);
conn->raop->random_pw = strndup((const char *) pin, 6);
printf("*** stored new pin = [%s]\n", conn->raop->random_pw);
}
if (len == -1 && conn->raop->callbacks.display_pin) {
char *pin = conn->raop->random_pw;
assert(pin);
if (conn->raop->callbacks.display_pin) {
conn->raop->callbacks.display_pin(conn->raop->callbacks.cls, pin);
}
logger_log(conn->raop->logger, LOGGER_INFO, "*** CLIENT MUST NOW ENTER PIN = \"%s\" AS AIRPLAY PASSWORD", pin);
password = (const char *) pin;
}
if (len && !conn->authenticated) {
if (len == -1) {
password = (const char *) conn->raop->random_pw;
}
char nonce_string[33] = { '\0' };
//bool stale = false; //not implemented
const char *authorization = NULL;
@@ -627,7 +625,6 @@ raop_handler_setup(raop_conn_t *conn,
}
}
if (conn->authenticated && conn->raop->random_pw) {
printf("*********free random_pw\n");
free (conn->raop->random_pw);
conn->raop->random_pw = NULL;
}
@@ -649,8 +646,8 @@ raop_handler_setup(raop_conn_t *conn,
}
conn->raop->nonce = utils_hex_to_string(nonce, len);
char response_text[80] = "Digest realm=\"raop\", nonce=\"";
strncat(response_text, conn->raop->nonce, strlen(conn->raop->nonce));
strncat(response_text, "\"", 1);
strncat(response_text, conn->raop->nonce, 80 - strlen(response_text) - 1);
strncat(response_text, "\"", 80 - strlen(response_text) - 1);
http_response_init(response, "RTSP/1.0", 401, "Unauthorized");
http_response_add_header(response, "WWW-Authenticate", response_text);
return;

View File

@@ -1232,9 +1232,7 @@ static void parse_arguments (int argc, char *argv[]) {
}
} else if (arg == "-pw") {
setup_legacy_pairing = false;
if (!option_has_value(i, argc, arg, argv[i+1])) {
pin_pw = 3;
} else if (i < argc - 1 && *argv[i+1] != '-') {
if (i < argc - 1 && *argv[i+1] != '-') {
password.erase();
password.append(argv[++i]);
pin_pw = 2;
@@ -1242,6 +1240,8 @@ static void parse_arguments (int argc, char *argv[]) {
fprintf(stderr, "invalid client-access password \"%s\": length must be at least %u characters\n", password.c_str(), min_password_length);
exit(1);
}
} else {
pin_pw = 3; //a random password (pin) will be displayed at each connection
}
} else if (arg == "-dacp") {
dacpfile.erase();