From: ejurgensen Date: Tue, 13 Jul 2021 20:28:34 +0000 (+0200) Subject: Update pair_ap to 0.8 (fixes incorrect pair-list response) X-Git-Tag: 4.1-dev~4^2~63^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=978862c2ec2c1c141ef2ed235057a024a7dbc46d;p=thirdparty%2Fshairport-sync.git Update pair_ap to 0.8 (fixes incorrect pair-list response) --- diff --git a/pair_ap/README.md b/pair_ap/README.md index 1c855444..d6b00d65 100644 --- a/pair_ap/README.md +++ b/pair_ap/README.md @@ -2,9 +2,10 @@ C client implementation of pairing for: * Apple TV device verification, which became mandatory with tvOS 10.2 (this is called fruit mode in pair_ap) -* Homekit pairing (for AirPlay 2, not working for Home app) +* Homekit pairing (also for AirPlay 2) Credit goes to @funtax and @ViktoriiaKh for doing some of the heavy lifting. + ## Requirements - libsodium - libgcrypt or libopenssl @@ -33,7 +34,7 @@ The controller uses `/pair-add` to make sure that all devices on a network get the ID and public key of all the other devices, so that the user only needs to pair a device once. -### Normal pairing +### Normal pairing with one-time code For a normal first-time pairing, the client needs a one-time code (the device announces via mDNS whether a code is required). The client calls `/pair-pin-start` and the device displays the code. There is also QR-based @@ -42,12 +43,12 @@ pairing, which is (probably?) an encoded code. After obtaining the code, the client initiates a three step `/pair-setup` sequence, which results in both peers registering each other's ID and public key. Henceforth, a pairing is verified with the two step `/pair-verify`, where -the parties check each-others identify. Saving the peer's ID + public key isn't +the parties check eachothers identify. Saving the peer's ID + public key isn't strictly necessary if client or server doesn't care about verifying the peer, i.e. that `/pair-setup` has actually been completed. The result of `/pair-verify` is a shared secret that is used for symmetric -encryption of the following communinacation between the parties. +encryption of the following communication between the parties. ### Transient pairing Some devices don't require a code from the user for pairing (e.g. an Airport @@ -55,8 +56,7 @@ Express 2). If so, the client just needs to go through a two-step `/pair-setup` sequence which results in a shared secret, which is then used for encrypted communication. A fixed code of 3939 is used. -Such devices don't appear to be fully Homekit compatible - they will not, for -instance - appear in the Home app. +The controller can still use `/pair-add` etc. towards such devices. ## "fruit" pairing Like normal Homekit pairing, this consists of first requesting a code with @@ -69,4 +69,5 @@ shared secret. - [AirPlayAuth](https://github.com/funtax/AirPlayAuth) - [AirPlayAuth-ObjC](https://github.com/ViktoriiaKh/AirPlayAuth-ObjC) - [ap2-sender](https://github.com/ViktoriiaKh/ap2-sender) +- [airplay2-receiver](https://github.com/ckdo/airplay2-receiver) - [csrp](https://github.com/cocagne/csrp) diff --git a/pair_ap/pair.h b/pair_ap/pair.h index 6324bc15..3877e2bb 100644 --- a/pair_ap/pair.h +++ b/pair_ap/pair.h @@ -4,7 +4,7 @@ #include #define PAIR_AP_VERSION_MAJOR 0 -#define PAIR_AP_VERSION_MINOR 5 +#define PAIR_AP_VERSION_MINOR 8 #define PAIR_AP_DEVICE_ID_LEN_MAX 64 diff --git a/pair_ap/pair_homekit.c b/pair_ap/pair_homekit.c index 076ea14a..ed59807e 100644 --- a/pair_ap/pair_homekit.c +++ b/pair_ap/pair_homekit.c @@ -2679,6 +2679,7 @@ server_add_remove_request(pair_cb cb, void *cb_arg, const uint8_t *in, size_t in pair_tlv_t *device_id; pair_tlv_t *pk; char id_str[PAIR_AP_DEVICE_ID_LEN_MAX] = { 0 }; + uint8_t *public_key = NULL; request = message_process(in, in_len, &errmsg); if (!request) @@ -2687,15 +2688,21 @@ server_add_remove_request(pair_cb cb, void *cb_arg, const uint8_t *in, size_t in } device_id = pair_tlv_get_value(request, TLVType_Identifier); - pk = pair_tlv_get_value(request, TLVType_PublicKey); - if (!device_id || device_id->size >= sizeof(id_str) || !pk || pk->size != crypto_sign_PUBLICKEYBYTES) + if (!device_id || device_id->size >= sizeof(id_str)) { goto error; } + // Only present when adding + pk = pair_tlv_get_value(request, TLVType_PublicKey); + if (pk && pk->size == crypto_sign_PUBLICKEYBYTES) + { + public_key = pk->value; + } + memcpy(id_str, device_id->value, device_id->size); - cb(pk->value, id_str, cb_arg); + cb(public_key, id_str, cb_arg); pair_tlv_free(request); return 0; @@ -2757,9 +2764,18 @@ static int server_list_cb(uint8_t public_key[crypto_sign_PUBLICKEYBYTES], const char *device_id, void *cb_arg) { pair_tlv_values_t *response = cb_arg; + pair_tlv_t *previous_id; + uint8_t permissions = 1; // Means admin (TODO don't hardcode - let caller set) + + // If this isn't the first iteration (item) then we must add a separator + previous_id = pair_tlv_get_value(response, TLVType_Identifier); + if (previous_id) + pair_tlv_add_value(response, TLVType_Separator, NULL, 0); pair_tlv_add_value(response, TLVType_Identifier, (unsigned char *)device_id, strlen(device_id)); pair_tlv_add_value(response, TLVType_PublicKey, public_key, crypto_sign_PUBLICKEYBYTES); + pair_tlv_add_value(response, TLVType_Permissions, &permissions, sizeof(permissions)); + return 0; }