Skip to content

Commit d7f4aa1

Browse files
committed
Circle fixes
1 parent 5d59544 commit d7f4aa1

File tree

2 files changed

+47
-17
lines changed

2 files changed

+47
-17
lines changed

src/auth.rs

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -680,28 +680,33 @@ pub struct CircleClientSession<P: AnisetteProvider> {
680680
channel: Option<CircleEncryptedChannel>,
681681
saved_password: Option<String>,
682682
saved_device_password: Option<Vec<u8>>,
683+
pub session_id: Option<String>,
684+
atxid: String,
683685
}
684686

685687
impl<P: AnisetteProvider> CircleClientSession<P> {
688+
// WARN: you, the caller, are responsible for advertising a BLE GATT service with the uuid of session_id
689+
// modern OSes may refuse to add you to the circle if you are not in physical proximity
686690
pub async fn new(dsid: u64, account: Arc<Mutex<AppleAccount<P>>>, push_token: [u8; 32]) -> Result<Self, PushError> {
691+
// note, -0 is the attempt number. Each time there is another attempt (send new code) the -0 increments by 1
687692
let atxid = format!("{}-0", rand::random::<u32>() / 2);
688693

689694
let srp_client = SrpClient::<Sha256>::new(&G_3072);
690695

691696
let a: [u8; 32] = rand::random();
692697
let a_pub = srp_client.compute_public_ephemeral(&a);
693698

694-
account.lock().await.circle(&CircleSendMessage {
699+
let response = account.lock().await.circle(&CircleSendMessage {
695700
atxid: atxid.clone(),
696701
circlestep: 0,
697702
idmsdata: None,
698-
pakedata: base64_encode(&rasn::der::encode(&CircleStep0 {
703+
pakedata: Some(base64_encode(&rasn::der::encode(&CircleStep0 {
699704
circle_step: 0.into(),
700705
public_ephermeral: a_pub.into(),
701706
unk3: 1.into(),
702707
req_uuid: Uuid::new_v4().into_bytes().to_vec().into(),
703708
tag: "o".as_bytes().into(),
704-
}).unwrap()),
709+
}).unwrap())),
705710
ptkn: encode_hex(&push_token).to_uppercase(),
706711
ec: None,
707712
}, true).await?;
@@ -717,6 +722,8 @@ impl<P: AnisetteProvider> CircleClientSession<P> {
717722
trusted_peers: None,
718723
channel: None,
719724
saved_device_password: None,
725+
session_id: response.sid,
726+
atxid
720727
})
721728
}
722729

@@ -748,21 +755,37 @@ impl<P: AnisetteProvider> CircleClientSession<P> {
748755
atxid: request.atxnid.clone(),
749756
circlestep: 2,
750757
idmsdata: Some(request.idmsdata.clone()),
751-
pakedata: base64_encode(&step2),
758+
pakedata: Some(base64_encode(&step2)),
752759
ptkn: encode_hex(&self.push_token).to_uppercase(),
753760
ec: None,
754761
}, true).await?;
755762

756763
Ok(())
757764
}
758765

766+
pub async fn cancel(&self) -> Result<(), PushError> {
767+
self.account.lock().await.circle(&CircleSendMessage {
768+
atxid: self.atxid.clone(),
769+
circlestep: 0,
770+
ptkn: encode_hex(&self.push_token).to_uppercase(),
771+
ec: Some(-9004),
772+
idmsdata: None,
773+
pakedata: None,
774+
}, true).await?;
775+
return Ok(());
776+
}
777+
759778
pub async fn handle_circle_request(&mut self, request: &IdmsCircleMessage) -> Result<Option<LoginState>, PushError> {
760779
if let Some(ec) = &request.ec {
761-
if *ec == -9003 {
762-
// bad password
763-
return Err(PushError::Bad2FaCode);
780+
if *ec != -9005 {
781+
if *ec == -9003 {
782+
// bad password
783+
return Err(PushError::Bad2FaCode);
784+
}
785+
return Err(PushError::IdmsCircleError(*ec))
764786
}
765-
return Err(PushError::IdmsCircleError(*ec))
787+
// 9005 is proximity check failed which is expected since we don't support proximity checks.
788+
// We can continue anyways, it is a soft error.
766789
}
767790
let Some(pake) = &request.pake else { return Err(PushError::IdmsCircleError(50)) };
768791
match request.step {
@@ -816,6 +839,11 @@ impl<P: AnisetteProvider> CircleClientSession<P> {
816839
return Err(PushError::WrongStep(request.step))
817840
}
818841

842+
if request.ec.is_some() {
843+
// we failed the proximity check
844+
return Err(PushError::CircleOver)
845+
}
846+
819847
let state = peers.state.read().await;
820848
let identity = state.user_identity.as_ref().unwrap();
821849
let stable_info = identity.sign_payload(peers.generate_stable_info(&state), "TPPB.PeerStableInfo")?;
@@ -848,7 +876,7 @@ impl<P: AnisetteProvider> CircleClientSession<P> {
848876
atxid: request.atxnid.clone(),
849877
circlestep: 4,
850878
idmsdata: Some(request.idmsdata.clone()),
851-
pakedata: base64_encode(&message),
879+
pakedata: Some(base64_encode(&message)),
852880
ptkn: encode_hex(&self.push_token).to_uppercase(),
853881
ec: None,
854882
}, true).await?;
@@ -937,7 +965,7 @@ impl<P: AnisetteProvider> CircleServerSession<P> {
937965
atxid: request.atxnid.clone(),
938966
circlestep: 1,
939967
idmsdata: Some(request.idmsdata.clone()),
940-
pakedata: base64_encode(&step1),
968+
pakedata: Some(base64_encode(&step1)),
941969
ptkn: encode_hex(&self.push_token).to_uppercase(),
942970
ec: None,
943971
}, false).await?;
@@ -951,10 +979,10 @@ impl<P: AnisetteProvider> CircleServerSession<P> {
951979
atxid: request.atxnid.clone(),
952980
circlestep: 3,
953981
idmsdata: Some(request.idmsdata.clone()),
954-
pakedata: base64_encode(&rasn::der::encode(&CircleError {
982+
pakedata: Some(base64_encode(&rasn::der::encode(&CircleError {
955983
extra_code: 0.into(),
956984
meta: vec![].into()
957-
}).unwrap()),
985+
}).unwrap())),
958986
ptkn: encode_hex(&self.push_token).to_uppercase(),
959987
ec: Some(-9003),
960988
}, false).await?;
@@ -977,7 +1005,7 @@ impl<P: AnisetteProvider> CircleServerSession<P> {
9771005
atxid: request.atxnid.clone(),
9781006
circlestep: 3,
9791007
idmsdata: Some(request.idmsdata.clone()),
980-
pakedata: base64_encode(&message),
1008+
pakedata: Some(base64_encode(&message)),
9811009
ptkn: encode_hex(&self.push_token).to_uppercase(),
9821010
ec: None,
9831011
}, false).await?;
@@ -1003,10 +1031,10 @@ impl<P: AnisetteProvider> CircleServerSession<P> {
10031031
atxid: request.atxnid.clone(),
10041032
circlestep: 5,
10051033
idmsdata: Some(request.idmsdata.clone()),
1006-
pakedata: base64_encode(&rasn::der::encode(&CircleStep5 {
1034+
pakedata: Some(base64_encode(&rasn::der::encode(&CircleStep5 {
10071035
circle_step: 5.into(),
10081036
voucher: vec![].into(),
1009-
}).expect("outer encoding failed")),
1037+
}).expect("outer encoding failed"))),
10101038
ptkn: encode_hex(&self.push_token).to_uppercase(),
10111039
ec: None,
10121040
}, false).await?;
@@ -1033,7 +1061,7 @@ impl<P: AnisetteProvider> CircleServerSession<P> {
10331061
atxid: request.atxnid.clone(),
10341062
circlestep: 5,
10351063
idmsdata: Some(request.idmsdata.clone()),
1036-
pakedata: base64_encode(&rasn::der::encode(&CircleStep5 {
1064+
pakedata: Some(base64_encode(&rasn::der::encode(&CircleStep5 {
10371065
circle_step: 5.into(),
10381066
voucher: OctagonPairingMessage {
10391067
step1: None,
@@ -1045,7 +1073,7 @@ impl<P: AnisetteProvider> CircleServerSession<P> {
10451073
supports_octagon: Some(Default::default()),
10461074
supports_sos: Some(Default::default()),
10471075
}.encode_to_vec().into(),
1048-
}).expect("outer encoding failed")),
1076+
}).expect("outer encoding failed"))),
10491077
ptkn: encode_hex(&self.push_token).to_uppercase(),
10501078
ec: None,
10511079
}, false).await?;

src/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,6 @@ pub enum PushError {
179179
Bad2FaCode,
180180
#[error("PCS record key id not found!")]
181181
PCSRecordKeyMissing,
182+
#[error("Circle is over!")]
183+
CircleOver,
182184
}

0 commit comments

Comments
 (0)