4949use pocketmine \Server ;
5050use Ramsey \Uuid \Uuid ;
5151use Ramsey \Uuid \UuidInterface ;
52+ use function base64_decode ;
5253use function chr ;
5354use function count ;
5455use function gettype ;
@@ -84,8 +85,11 @@ private static function calculateUuidFromXuid(string $xuid) : UuidInterface{
8485 }
8586
8687 public function handleLogin (LoginPacket $ packet ) : bool {
87- if ($ this ->session ->getProtocolId () >= ProtocolInfo::PROTOCOL_1_21_90 ){
88+ if ($ this ->session ->getProtocolId () >= ProtocolInfo::PROTOCOL_1_21_93 ){
8889 $ authInfo = $ this ->parseAuthInfo ($ packet ->authInfoJson );
90+ }elseif ($ this ->session ->getProtocolId () >= ProtocolInfo::PROTOCOL_1_21_90 ){
91+ $ authInfo = $ this ->parseAuthInfo ($ packet ->authInfoJson );
92+ $ authInfo ->AuthenticationType = AuthenticationType::SELF_SIGNED ->value ;
8993 }else {
9094 $ authInfo = new AuthenticationInfo ();
9195 $ authInfo ->AuthenticationType = AuthenticationType::SELF_SIGNED ->value ;
@@ -127,17 +131,44 @@ public function handleLogin(LoginPacket $packet) : bool{
127131 }catch (\JsonMapper_Exception $ e ){
128132 throw PacketHandlingException::wrap ($ e , "Error mapping self-signed certificate chain " );
129133 }
130- if (count ($ chain ->chain ) > 1 || !isset ($ chain ->chain [0 ])){
131- throw new PacketHandlingException ("Expected exactly one certificate in self-signed certificate chain, got " . count ($ chain ->chain ));
132- }
133-
134- try {
135- [, $ claimsArray , ] = JwtUtils::parse ($ chain ->chain [0 ]);
136- }catch (JwtException $ e ){
137- throw PacketHandlingException::wrap ($ e , "Error parsing self-signed certificate " );
138- }
139- if (!isset ($ claimsArray ["extraData " ]) || !is_array ($ claimsArray ["extraData " ])){
140- throw new PacketHandlingException ("Expected \"extraData \" to be present in self-signed certificate " );
134+ if ($ this ->session ->getProtocolId () >= ProtocolInfo::PROTOCOL_1_21_93 ){
135+ if (count ($ chain ->chain ) > 1 || !isset ($ chain ->chain [0 ])){
136+ throw new PacketHandlingException ("Expected exactly one certificate in self-signed certificate chain, got " . count ($ chain ->chain ));
137+ }
138+
139+ try {
140+ [, $ claimsArray , ] = JwtUtils::parse ($ chain ->chain [0 ]);
141+ }catch (JwtException $ e ){
142+ throw PacketHandlingException::wrap ($ e , "Error parsing self-signed certificate " );
143+ }
144+ if (!isset ($ claimsArray ["extraData " ]) || !is_array ($ claimsArray ["extraData " ])){
145+ throw new PacketHandlingException ("Expected \"extraData \" to be present in self-signed certificate " );
146+ }
147+ }else {
148+ $ claimsArray = null ;
149+
150+ foreach ($ chain ->chain as $ jwt ){
151+ try {
152+ [, $ claims , ] = JwtUtils::parse ($ jwt );
153+ }catch (JwtException $ e ){
154+ throw PacketHandlingException::wrap ($ e , "Error parsing legacy certificate " );
155+ }
156+ if (isset ($ claims ["extraData " ])){
157+ if ($ claimsArray !== null ){
158+ throw new PacketHandlingException ("Multiple certificates in self-signed certificate chain contain \"extraData \" field " );
159+ }
160+
161+ if (!is_array ($ claims ["extraData " ])){
162+ throw new PacketHandlingException ("'extraData' key should be an array " );
163+ }
164+
165+ $ claimsArray = $ claims ;
166+ }
167+ }
168+
169+ if ($ claimsArray === null ){
170+ throw new PacketHandlingException ("'extraData' not found in legacy chain data " );
171+ }
141172 }
142173
143174 try {
@@ -151,7 +182,7 @@ public function handleLogin(LoginPacket $packet) : bool{
151182 }
152183 $ legacyUuid = Uuid::fromString ($ claims ->identity );
153184 $ username = $ claims ->displayName ;
154- $ xuid = "" ;
185+ $ xuid = $ this -> session -> getProtocolId () >= ProtocolInfo:: PROTOCOL_1_21_93 ? "" : $ claims -> XUID ;
155186
156187 $ authRequired = $ this ->processLoginCommon ($ packet , $ username , $ legacyUuid , $ xuid );
157188 if ($ authRequired === null ){
@@ -334,7 +365,10 @@ function(array $issuerAndKey) use ($token, $clientData, $authRequired) : void{
334365 protected function processSelfSignedLogin (array $ legacyCertificate , string $ clientDataJwt , bool $ authRequired ) : void {
335366 $ this ->session ->setHandler (null ); //drop packets received during login verification
336367
337- $ rootAuthKeyDer = $ this ->session ->getProtocolId () >= ProtocolInfo::PROTOCOL_1_21_90 ? null : ProcessLegacyLoginTask::LEGACY_MOJANG_ROOT_PUBLIC_KEY ;
368+ $ rootAuthKeyDer = $ this ->session ->getProtocolId () >= ProtocolInfo::PROTOCOL_1_21_93 ? null : base64_decode (ProcessLegacyLoginTask::LEGACY_MOJANG_ROOT_PUBLIC_KEY , true );
369+ if ($ rootAuthKeyDer === false ){ //should never happen unless the constant is messed up
370+ throw new \InvalidArgumentException ("Failed to base64-decode hardcoded Mojang root public key " );
371+ }
338372 $ this ->server ->getAsyncPool ()->submitTask (new ProcessLegacyLoginTask ($ legacyCertificate , $ clientDataJwt , rootAuthKeyDer: $ rootAuthKeyDer , authRequired: $ authRequired , onCompletion: $ this ->authCallback ));
339373 }
340374
0 commit comments