@@ -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
685687impl < 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 ?;
0 commit comments