cleanup the -pw (no argument) random pw option

This commit is contained in:
F. Duncanh
2025-08-06 07:14:33 -04:00
parent a08c51e662
commit 2b0da9125a
2 changed files with 23 additions and 17 deletions

View File

@@ -216,6 +216,8 @@ httpd_remove_connection(httpd_t *httpd, http_connection_t *connection)
int ret = closesocket(connection->socket_fd); int ret = closesocket(connection->socket_fd);
if (ret == -1) { if (ret == -1) {
logger_log(httpd->logger, LOGGER_ERR, "httpd error in closesocket (close): %d %s", errno, strerror(errno)); logger_log(httpd->logger, LOGGER_ERR, "httpd error in closesocket (close): %d %s", errno, strerror(errno));
} else {
logger_log(httpd->logger, LOGGER_INFO, "Connection closed on socket %d", connection->socket_fd);
} }
connection->socket_fd = 0; connection->socket_fd = 0;
} }
@@ -464,7 +466,7 @@ httpd_thread(void *arg)
while (readstart < 8) { while (readstart < 8) {
ret = recv(connection->socket_fd, buffer + readstart, sizeof(buffer) - 1 - readstart, 0); ret = recv(connection->socket_fd, buffer + readstart, sizeof(buffer) - 1 - readstart, 0);
if (ret == 0) { if (ret == 0) {
logger_log(httpd->logger, LOGGER_INFO, "Connection closed for socket %d", logger_log(httpd->logger, LOGGER_DEBUG, "client closed connection on socket %d",
connection->socket_fd); connection->socket_fd);
break; break;
} else if (ret == -1) { } else if (ret == -1) {
@@ -487,8 +489,6 @@ httpd_thread(void *arg)
} else { } else {
ret = recv(connection->socket_fd, buffer, sizeof(buffer) - 1, 0); ret = recv(connection->socket_fd, buffer, sizeof(buffer) - 1, 0);
if (ret == 0) { if (ret == 0) {
logger_log(httpd->logger, LOGGER_INFO, "Connection closed for socket %d",
connection->socket_fd);
httpd_remove_connection(httpd, connection); httpd_remove_connection(httpd, connection);
continue; continue;
} }

View File

@@ -26,7 +26,7 @@
#define AUDIO_SAMPLE_RATE 44100 /* all supported AirPlay audio format use this sample rate */ #define AUDIO_SAMPLE_RATE 44100 /* all supported AirPlay audio format use this sample rate */
#define SECOND_IN_USECS 1000000 #define SECOND_IN_USECS 1000000
#define SECOND_IN_NSECS 1000000000 #define SECOND_IN_NSECS 1000000000
#define MAX_PW_ATTEMPTS 5 #define MAX_PW_ATTEMPTS 3
typedef void (*raop_handler_t)(raop_conn_t *, http_request_t *, typedef void (*raop_handler_t)(raop_conn_t *, http_request_t *,
http_response_t *, char **, int *); http_response_t *, char **, int *);
@@ -593,15 +593,21 @@ raop_handler_setup(raop_conn_t *conn,
/* RFC2617 Digest authentication (md5 hash) of uxplay client-access password, if set */ /* RFC2617 Digest authentication (md5 hash) of uxplay client-access password, if set */
if (!conn->authenticated && conn->raop->callbacks.passwd) { if (!conn->authenticated && conn->raop->callbacks.passwd) {
size_t pin_len = 4; size_t pin_len = 4;
if (conn->raop->random_pw && strncmp(conn->raop->random_pw + pin_len + 1, deviceID, 17)) { const char *authorization = NULL;
conn->raop->auth_fail_count = MAX_PW_ATTEMPTS; authorization = http_request_get_header(request, "Authorization");
if (!authorization) {
// if random_pw is set, but client has changed, unset it
if (conn->raop->random_pw && strncmp(conn->raop->random_pw + pin_len + 1, deviceID, 17)) {
free(conn->raop->random_pw);
conn->raop->random_pw = NULL;
}
} }
int len; int len;
const char *password = conn->raop->callbacks.passwd(conn->raop->callbacks.cls, &len); const char *password = conn->raop->callbacks.passwd(conn->raop->callbacks.cls, &len);
// len = -1 means use a random password for this connection; len = 0 means no password // len = -1 means use a random password for this connection; len = 0 means no password
if (len == -1 && conn->raop->random_pw && conn->raop->auth_fail_count >= MAX_PW_ATTEMPTS) { if (len == -1 && conn->raop->random_pw && conn->raop->auth_fail_count >= MAX_PW_ATTEMPTS) {
// change random_pw after MAX_PW_ATTEMPTS failed authentication attempts // change random_pw after MAX_PW_ATTEMPTS failed authentication attempts
logger_log(conn->raop->logger, LOGGER_INFO, "Too many authentication failures or new client: generate new random password"); logger_log(conn->raop->logger, LOGGER_INFO, "Too many authentication failures: generate new random password");
free(conn->raop->random_pw); free(conn->raop->random_pw);
conn->raop->random_pw = NULL; conn->raop->random_pw = NULL;
} }
@@ -618,10 +624,13 @@ raop_handler_setup(raop_conn_t *conn,
pin[pin_len] = '\0'; pin[pin_len] = '\0';
snprintf(pin + pin_len + 1, 18, "%s", deviceID); snprintf(pin + pin_len + 1, 18, "%s", deviceID);
conn->raop->auth_fail_count = 0; conn->raop->auth_fail_count = 0;
}
if (len == -1 && !authorization && conn->raop->random_pw) {
if (conn->raop->callbacks.display_pin) { if (conn->raop->callbacks.display_pin) {
conn->raop->callbacks.display_pin(conn->raop->callbacks.cls, pin); conn->raop->callbacks.display_pin(conn->raop->callbacks.cls, conn->raop->random_pw);
} }
logger_log(conn->raop->logger, LOGGER_INFO, "*** CLIENT MUST NOW ENTER PIN = \"%s\" AS AIRPLAY PASSWORD", pin); logger_log(conn->raop->logger, LOGGER_INFO, "*** CLIENT MUST NOW ENTER PIN = \"%s\" AS AIRPLAY PASSWORD", conn->raop->random_pw);
conn->raop->auth_fail_count++;
} }
if (len && !conn->authenticated) { if (len && !conn->authenticated) {
if (len == -1) { if (len == -1) {
@@ -629,20 +638,17 @@ raop_handler_setup(raop_conn_t *conn,
} }
char nonce_string[33] = { '\0' }; char nonce_string[33] = { '\0' };
//bool stale = false; //not implemented //bool stale = false; //not implemented
const char *authorization = NULL; if (len && authorization) {
authorization = http_request_get_header(request, "Authorization");
if (authorization) {
char *ptr = strstr(authorization, "nonce=\"") + strlen("nonce=\""); char *ptr = strstr(authorization, "nonce=\"") + strlen("nonce=\"");
strncpy(nonce_string, ptr, 32); strncpy(nonce_string, ptr, 32);
const char *method = http_request_get_method(request); const char *method = http_request_get_method(request);
conn->authenticated = pairing_digest_verify(method, authorization, password); conn->authenticated = pairing_digest_verify(method, authorization, password);
if (!conn->authenticated) { if (!conn->authenticated) {
conn->raop->auth_fail_count++; // if random_pw is used, the auth_fail_count will be the number of times it is displayed after creation
logger_log(conn->raop->logger, LOGGER_INFO, "*** authentication failure: count = %u", conn->raop->auth_fail_count); if (len != -1) {
if (conn->raop->callbacks.display_pin && conn->raop->auth_fail_count > 1) { conn->raop->auth_fail_count++;
conn->raop->callbacks.display_pin(conn->raop->callbacks.cls, conn->raop->random_pw);
} }
logger_log(conn->raop->logger, LOGGER_INFO, "*** CLIENT MUST NOW ENTER PIN = \"%s\" AS AIRPLAY PASSWORD", conn->raop->random_pw); logger_log(conn->raop->logger, LOGGER_INFO, "*** authentication failure: count = %u", conn->raop->auth_fail_count);
} }
if (conn->authenticated) { if (conn->authenticated) {
//printf("initial authenticatication OK\n"); //printf("initial authenticatication OK\n");