openairplay / airplay2-receiver

AirPlay 2 Receiver - Python implementation
2.13k stars 133 forks source link

Implement Persistent HomeKit Pairing #41

Closed TheSpookyCat closed 3 years ago

TheSpookyCat commented 3 years ago

This PR and branch contains fixes that will hopefully ultimately lead to fixing #38. At the minute, HomeKit Pairing works as expected, as does audio streaming.

This is a draft PR whilst I implement the rest of the HK Pairing spec as it's currently missing half of what it should.

Based on @ckdo's branch persistentpairing and @systemcrash's branch pair-add

TheSpookyCat commented 3 years ago

Tested locally and seems to be working so far. Using it to listen to music right now. Paired with HomeKit successfully. I think the statusFlags of the info dict need to be updated to show tha accessorycontrol has been setup for this speaker, though it doesn't seem to be affecting my usage of this.

systemcrash commented 3 years ago

I look forward to merging this - apparently my fix and this PR attempt to do the same thing - but this PR stores the LTK to disk so that it persists across restarts. One thing: can you test whether b88bcc6961a9eada664b7c19ef1526eefbfa7e23 alone can manage persistent pairing? I suspect it's not the case, but nice to verify. It seems with PK and PI, they need to match what the HK device has in its store over the longer term.

TheSpookyCat commented 3 years ago

I look forward to merging this - apparently my fix and this PR attempt to do the same thing - but this PR stores the LTK to disk so that it persists across restarts. One thing: can you test whether b88bcc6 alone can manage persistent pairing? I suspect it's not the case, but nice to verify. It seems with PK and PI, they need to match what the HK device has in its store over the longer term.

Sure, I'll test in a little bit. I'll also leave it to you to resolve the merge conflicts.

TheSpookyCat commented 3 years ago

@systemcrash How do you plan on merging our two fixes?

systemcrash commented 3 years ago

@systemcrash How do you plan on merging our two fixes?

Good question. I might have to stage them locally, to reconcile my latest commit, which fixes "pk" for non-transient pairing.

systemcrash commented 3 years ago

Can you try one thing before I merge this?

Set the header HTTP_CT_PAIR for all pair-x methods and see how it works. The docs state that header should be there....

self.send_header("Content-Type", HTTP_CT_PAIR)

TheSpookyCat commented 3 years ago

Can you try one thing before I merge this?

Set the header HTTP_CT_PAIR for all pair-x methods and see how it works. The docs state that header should be there....

self.send_header("Content-Type", HTTP_CT_PAIR)

Yes, please push this to master for pair_add/list/remove.

systemcrash commented 3 years ago

I think also with a bit of post-commit tweaking, we can remove the nacl dependency (for now).

See #24

In my commit, I got it working using just Ed25519.

TheSpookyCat commented 3 years ago

I think also with a bit of post-commit tweaking, we can remove the nacl dependency (for now).

See #24

In my commit, I got it working using just Ed25519.

Isn't Curve25519 required for transient pairing, though?

TheSpookyCat commented 3 years ago

By the way @systemcrash do you have any information on this entire repository/organization? For example, you and one other are the only 'People' in the openairplay org, though it seems rhere are many repositories with many different primary owners/maintainers going so far as 10 years back. Even then, there's no out-of-github platform setup for communication, so I'm just curious as to how everything has ended up how it is. :) Hope you don't mind me asking.

Neustradamus commented 3 years ago

@LewdNeko: In the org, there are several devs linked to AirPlay, some are active, others not. You are welcome in the team ^^

TheSpookyCat commented 3 years ago

@LewdNeko: In the org, there are several devs linked to AirPlay, some are active, others not. You are welcome in the team ^^

Ah I see, some members of the org were private - I could only see 2 people. Thank you for the invite & information.

Neustradamus commented 3 years ago

Because by default the option is private but you can manually change private to public.

systemcrash commented 3 years ago

I think also with a bit of post-commit tweaking, we can remove the nacl dependency (for now). See #24 In my commit, I got it working using just Ed25519.

Isn't Curve25519 required for transient pairing, though?

It worked for me with Transient and Non, using Ed25519.

systemcrash commented 3 years ago

Can you try one thing before I merge this? Set the header HTTP_CT_PAIR for all pair-x methods and see how it works. The docs state that header should be there.... self.send_header("Content-Type", HTTP_CT_PAIR)

Yes, please push this to master for pair_add/list/remove.

@LewdNeko could you test the local pair-x branch, please? Did a refactor, want to be sure it works before I commit.

systemcrash commented 3 years ago

@LewdNeko could you test the local pair-x branch, please? Did a refactor, want to be sure it works before I commit. @LewdNeko

ping. Check the branch and see whether it works the same, plz.

TheSpookyCat commented 3 years ago

Apologies, didn't see this. See #47 for latest information.

Also, got any information on where/how we can respect a password being set by HomeKit? If I configure a password, I see the following:

POST: /configure
Content-Length: 93
Content-Type: application/x-apple-binary-plist
CSeq: 9
User-Agent: AirPlay/566.15.1

configure /configure
Content-Length: 93
Content-Type: application/x-apple-binary-plist
CSeq: 9
User-Agent: AirPlay/566.15.1

{'ConfigurationDictionary': {'Password': 'ABCDEF'}}
{'Access_Control_Level': 0,
 'Device_Name': 'NEWBORNE',
 'Enable_HK_Access_Control': False,
 'Identifier': 'aa5cb8df-7f14-4249-901a-5e748ce57a93',
 'Password': '091002',
 'PublicKey': b'\xf1\xc5y\xae\xd5O\x89f\xa9Lr\xee2&\xf40\xcd\x8c*I\xee\x15L\xbf'
              b'\xcc\xf4W\x94(\xc2\xb6|'}
TEARDOWN rtsp://192.168.1.167/4497135955938921972
Content-Length: 42
Content-Type: application/x-apple-binary-plist
CSeq: 10
User-Agent: AirPlay/566.15.1

{}

When a password is set via HomeKit, it gets sent via POST /configure. I could very easily store this when provided via handle_configure(), however the problem I'm having is understanding where/how we would "ask" for this password. Maybe I'm just not looking in the right place, but I definitely couldn't find anything.

systemcrash commented 3 years ago

I also don't yet know how homekit in its entirety is meant to work with the password. But have a peek at hap-python project. It might give you some pointers as to how and when the password is utilized. The SDK might also help. One guess is the SRP part. I could flesh that out, since comments indicate it is incomplete.

Reuse the json bits and store the password globally.

it seems that password checks happen at connect time. But because there can currently only be one device connected via HAP, a sticky controller or iPhone might prevent connection anyway.