RAOP auth quirk for old (802.11g) AirPort Express

This commit is contained in:
Julien BLACHE 2010-09-21 22:29:17 +02:00
parent cc4e271de1
commit 50a9a3690f
3 changed files with 29 additions and 6 deletions

View File

@ -2893,6 +2893,7 @@ raop_device_cb(const char *name, const char *type, const char *domain, const cha
uint64_t id; uint64_t id;
int has_password; int has_password;
int encrypt; int encrypt;
int auth_quirk_itunes;
int last_active; int last_active;
int ret; int ret;
@ -3047,11 +3048,15 @@ raop_device_cb(const char *name, const char *type, const char *domain, const cha
} }
encrypt = 1; encrypt = 1;
auth_quirk_itunes = 0;
p = keyval_get(txt, "am"); p = keyval_get(txt, "am");
if (!p) if (!p)
{ {
DPRINTF(E_LOG, L_PLAYER, "AirTunes %s: no am field in TXT record!\n", name); DPRINTF(E_LOG, L_PLAYER, "AirTunes %s: no am field in TXT record!\n", name);
/* Old AirPort Express */
auth_quirk_itunes = 1;
goto no_am; goto no_am;
} }
@ -3140,6 +3145,7 @@ raop_device_cb(const char *name, const char *type, const char *domain, const cha
rd->name = strdup(at_name); rd->name = strdup(at_name);
rd->encrypt = encrypt; rd->encrypt = encrypt;
rd->auth_quirk_itunes = auth_quirk_itunes;
rd->has_password = has_password; rd->has_password = has_password;
rd->password = password; rd->password = password;

View File

@ -87,6 +87,7 @@ struct raop_session
unsigned req_in_flight:1; unsigned req_in_flight:1;
unsigned req_has_auth:1; unsigned req_has_auth:1;
unsigned encrypt:1; unsigned encrypt:1;
unsigned auth_quirk_itunes:1;
int cseq; int cseq;
char *session; char *session;
@ -671,6 +672,8 @@ raop_add_auth(struct raop_session *rs, struct evrtsp_request *req, const char *m
char ha2[33]; char ha2[33];
char ebuf[64]; char ebuf[64];
char auth[256]; char auth[256];
const char *hash_fmt;
const char *username;
uint8_t *hash_bytes; uint8_t *hash_bytes;
size_t hashlen; size_t hashlen;
gcry_md_hd_t hd; gcry_md_hd_t hd;
@ -690,6 +693,17 @@ raop_add_auth(struct raop_session *rs, struct evrtsp_request *req, const char *m
return -2; return -2;
} }
if (rs->auth_quirk_itunes)
{
hash_fmt = "%02X"; /* Uppercase hex */
username = "iTunes";
}
else
{
hash_fmt = "%02x";
username = ""; /* No username */
}
gc_err = gcry_md_open(&hd, GCRY_MD_MD5, 0); gc_err = gcry_md_open(&hd, GCRY_MD_MD5, 0);
if (gc_err != GPG_ERR_NO_ERROR) if (gc_err != GPG_ERR_NO_ERROR)
{ {
@ -704,7 +718,8 @@ raop_add_auth(struct raop_session *rs, struct evrtsp_request *req, const char *m
hashlen = gcry_md_get_algo_dlen(GCRY_MD_MD5); hashlen = gcry_md_get_algo_dlen(GCRY_MD_MD5);
/* HA 1 */ /* HA 1 */
/* No username */
gcry_md_write(hd, username, strlen(username));
gcry_md_write(hd, ":", 1); gcry_md_write(hd, ":", 1);
gcry_md_write(hd, rs->realm, strlen(rs->realm)); gcry_md_write(hd, rs->realm, strlen(rs->realm));
gcry_md_write(hd, ":", 1); gcry_md_write(hd, ":", 1);
@ -719,7 +734,7 @@ raop_add_auth(struct raop_session *rs, struct evrtsp_request *req, const char *m
} }
for (i = 0; i < hashlen; i++) for (i = 0; i < hashlen; i++)
sprintf(ha1 + (2 * i), "%02x", hash_bytes[i]); sprintf(ha1 + (2 * i), hash_fmt, hash_bytes[i]);
/* RESET */ /* RESET */
gcry_md_reset(hd); gcry_md_reset(hd);
@ -738,7 +753,7 @@ raop_add_auth(struct raop_session *rs, struct evrtsp_request *req, const char *m
} }
for (i = 0; i < hashlen; i++) for (i = 0; i < hashlen; i++)
sprintf(ha2 + (2 * i), "%02x", hash_bytes[i]); sprintf(ha2 + (2 * i), hash_fmt, hash_bytes[i]);
/* RESET */ /* RESET */
gcry_md_reset(hd); gcry_md_reset(hd);
@ -759,13 +774,13 @@ raop_add_auth(struct raop_session *rs, struct evrtsp_request *req, const char *m
} }
for (i = 0; i < hashlen; i++) for (i = 0; i < hashlen; i++)
sprintf(ha1 + (2 * i), "%02x", hash_bytes[i]); sprintf(ha1 + (2 * i), hash_fmt, hash_bytes[i]);
gcry_md_close(hd); gcry_md_close(hd);
/* Build header */ /* Build header */
ret = snprintf(auth, sizeof(auth), "Digest username=\"\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"", ret = snprintf(auth, sizeof(auth), "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"",
rs->realm, rs->nonce, uri, ha1); username, rs->realm, rs->nonce, uri, ha1);
if ((ret < 0) || (ret >= sizeof(auth))) if ((ret < 0) || (ret >= sizeof(auth)))
{ {
DPRINTF(E_LOG, L_RAOP, "Authorization value header exceeds buffer size\n"); DPRINTF(E_LOG, L_RAOP, "Authorization value header exceeds buffer size\n");
@ -1456,6 +1471,7 @@ raop_session_make(struct raop_device *rd, int family, raop_status_cb cb)
rs->server_fd = -1; rs->server_fd = -1;
rs->encrypt = rd->encrypt; rs->encrypt = rd->encrypt;
rs->auth_quirk_itunes = rd->auth_quirk_itunes;
rs->password = rd->password; rs->password = rd->password;

View File

@ -31,6 +31,7 @@ struct raop_device
unsigned selected:1; unsigned selected:1;
unsigned advertised:1; unsigned advertised:1;
unsigned encrypt:1; unsigned encrypt:1;
unsigned auth_quirk_itunes:1;
unsigned has_password:1; unsigned has_password:1;
const char *password; const char *password;