ckdo / airplay2-receiver

AirPlay 2 receiver - python implementation only for testing
126 stars 7 forks source link

Not compatible with this version of iTunes #2

Open joerg-krause opened 4 years ago

joerg-krause commented 4 years ago

The FairPlay authentification works fine with iOS, but fails with iTunes: The AirPlay device "myap2" is not compatible with this version of iTunes.

Something i noticed: iTunes sends an OPTION request with an "Apple-Challenge".

ckdo commented 4 years ago

@joerg-krause Which version iTunes do you use ? Apple-Challenge refers to RSA Authentication, which is not allowed for AP2

joerg-krause commented 4 years ago

iTunes version is 12.10.7.3. This is the log:

$ python ap2-receiver.py -m myap2 -n wlp5s0
Interface: wlp5s0
IPv4: 192.168.178.118
IPv6: fd00::89a1:4d7b:fa87:7be0

mDNS service registered
Starting RSTP server, press Ctrl-C to exit...
serving at port 7000
Got connection with 192.168.178.33:49339
CSeq: 1
User-Agent: iTunes/12.10.7 (Windows; Microsoft Windows 7 Service Pack 1 x64 Professional Edition (Build 7601); x64) (dt:2)
Client-Instance: 8E6AFF7283B34602
DACP-ID: 8E6AFF7283B34602
Active-Remote: 222309246
Apple-Challenge: 3zeVCckh56X+LikSee2wQg
ckdo commented 4 years ago

Thanks @joerg-krause , Windows version of iTunes does not support FairPlay authentication. It either uses RSA authentication (regular raop devices) or MFi authentication with AP2 devices. I don't know if windows version of iTunes can accept RSA authentication for AP2 (mac version/ios devices does not), and I was actually interested in checking that (branch-RSA..) but it is still pending work.

joerg-krause commented 4 years ago

Thanks @ckdo for sharing the RSA branch. Actually, iTunes on Windows does support FairPlay v2 authentication. I've tested in by advertising the AP2 device as an AP1 device using only the _raop._tcp service. However, if I re-enable the _airplay._tcp service, iTunes sends the "Apple-Challenge" in the OPTIONS request stead of sending an fp-setup request.

ckdo commented 4 years ago

@joerg-krause RSA branch is updated to compute Apple-Response correctly. Apple-Response is accepted for _raop._tcp service, but for _airplay._tcp the dialog is stopping, so I guess RSA auth cannot be used on AP2 devices. In addition, windows version does not seems to support real Airplay2, protocol used is raop (ANNOUNCE for instance does not exist anymore with AP2 protocol) with previous MFi authentication.

joerg-krause commented 4 years ago

Thanks @ckdo ! I wonder, why iTunes on Windows sends the Apple-Challenge. What authentication algorithm does it expect, if not RSA? Looks like an unsolved mystery for now...

joerg-krause commented 4 years ago

@ckdo I managed to get iTunes on Windows to try to connect with the AirPlay 2 receiver using FairPlay v2. The features needs to be set to 0x3004A5D5A00 (The magic bit in the features is bit 25). iTunes needs several seconds before it sends the fp-setup request (so I guess some settings are not optimal yet):

Got connection with 192.168.178.136:49791
CSeq: 1
Content-Type: application/octet-stream
Content-Length: 16
User-Agent: iTunes/12.10.7 (Windows; Microsoft Windows 10 x64 Professional Edition (Build 19041); x64) (dt:2)
Client-Instance: 61A9F4C15E5B4DD7
DACP-ID: 61A9F4C15E5B4DD7
Active-Remote: 616789066

POST /fp-setup
00000000: 46 50 4C 59 02 01 01 00  00 00 00 04 02 00 00 BB  FPLY............

As you can see, the fifth byte send in the request is 02, which is FairPlay v2. As the current code only implements FairPlay v3, further processing fails with an exception...

ckdo commented 4 years ago

Interesting findings ! Once authenticated, unfortunately it will not use Airplay2 protocol: 192.168.128.227 - - [03/Jul/2020 15:58:49] code 501, message Unsupported method ('ANNOUNCE')

Like said in this case ANNOUNCE method is used, so it means raop/ap1. But... it can be interesting to know that for instance to ensure backward compatibility with ap1 with a device publishing only a _airplay._tcp service.

joerg-krause commented 4 years ago

The ANNOUNCE method is advertised as supported method in the OPTIONS request even in AP2 devices. What makes you think the ANNOUNCE is an AP1 method?

ckdo commented 4 years ago

Yes so that AP2 devices ensure AP1 backward compatibility since there is one single enpoint for both protocols. Invano documented the methods used for AP2 here: https://emanuelecozzi.net/docs/airplay2/protocols

You can also quite easily check rtsp streams with a tcpdump since for iTunes/Windows they are not encrypted.

joerg-krause commented 4 years ago

I see!

As I am far more experienced with C than with Python, I fiddled around with the FairPlay v2 feature using shairplay. This is my experimental FP2 branch: https://github.com/joerg-krause/shairplay/tree/fairplay_v2.

iTunes on Windows successfully connects to the AirPlay device, but shairport aborts, while buffering. Something is wrong with the audio decryption. Maybe the audio is not encrypted using AES 128 CBC?

I hope, that adding FairPlay v2 support can be used as a backward compatibility for iTunes on Windows...

ckdo commented 4 years ago

Nice work I will check that... about encryption with Fairplayv2 I don't know but with MFi auth there's no particular change with encryption. Actually my initial goal for this project is to understand the "player" part of AP2... to implement in pulseaudio ( https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/194 ), with all benefits of AP2 and not only in AP1 compatibility mode as this MR does. So having "C" contributions is very welcome :)

ckdo commented 4 years ago

Is your latest code pushed onto shairplay branch ? There are several points I don't understand (only fply_2 is used, fply_header and payload are not used in response)

joerg-krause commented 4 years ago

The branch is named fairplay_v2. It is a single commit https://github.com/joerg-krause/shairplay/commit/d5f0953d2380502366592e30a0a59fe3879f3c59. fply_header and fply_2 are used in fairplay_setup().

ckdo commented 4 years ago

Yes, but I mean there https://github.com/joerg-krause/shairplay/blob/d5f0953d2380502366592e30a0a59fe3879f3c59/src/lib/fairplay_playfair.c#L93-L97 : res only rely on fply_2, which does not use neither fply_header nor payload . Is it normal ?

joerg-krause commented 4 years ago

You're right! The reply needs to be distinguished whether by the request data. Depending on one byte set in the request, the header and payload data are needed for the response. That part is missing. I will add it soon, right now I am quite busy. Thanks for looking into it!

joerg-krause commented 4 years ago

Update: The missing part is not relevant for the fairplay v2 handshake. The main problem seems to be the decryption. I guess, there is a difference between v2 and v3 decryption.

I think the best approach is to use legacy RSA, for iTunes on Windows.

EDIT: RSA is only working when using the _raop._tcp bonjour service. When using the _airplay,_tcp service, it fails. However, if I first use the _raop._tcp service to connect iTunes on Windows with the AP device and then restart AP with the _airplay._tcp service instead of _raop._tcp, the authentification works, too.

systemcrash commented 3 years ago

I took a stab at getting the framework in place for RSA and perhaps also FP. The bits remaining to fix are decryption. There is a nice FP decryptor [1] available in C, so until that gets ported to Python, it's lib time. Was there anything interesting that you discovered when you tried to fix compatibility?

[1] https://github.com/juhovh/shairplay/tree/master/src/lib/playfair

systemcrash commented 2 years ago

I've pushed commits to master https://github.com/openairplay/airplay2-receiver/ which implement ANNOUNCE. This means you can receive audio encrypted using rsaaeskey. If I run: python3 ap2-receiver.py -m myap2 -n en0 -ftxor 12 things seem to work out. But occasionally, (probably some mDNS record lurking around) I need to run python3 ap2-receiver.py -m myap2 -n en0 -ftxor 12 25 and then python3 ap2-receiver.py -m myap2 -n en0 -ftxor 12 again to get iTunes to stop sending:

Apple-Challenge

headers. But my iTunes for Windows never accepts those using your branch here. Perhaps Apple changed what is expected in the Apple-Response? I tried your approach in the RSA branch, using PKCS1_OAEP, with and without hardware ID. Maybe I didn't try every combo. Don't like black-box crypto stuff so much :shrug:

Any ideas @ckdo ?