bool cMojangAPI::SecureRequest(const AString & a_ServerName, const AString & a_Request, AString & a_Response) { // Connect the socket: cBlockingSslClientSocket Socket; Socket.SetTrustedRootCertsFromString(StarfieldCACert(), a_ServerName); if (!Socket.Connect(a_ServerName, 443)) { LOGWARNING("%s: Can't connect to %s: %s", __FUNCTION__, a_ServerName.c_str(), Socket.GetLastErrorText().c_str()); return false; } if (!Socket.Send(a_Request.c_str(), a_Request.size())) { LOGWARNING("%s: Writing SSL data failed: %s", __FUNCTION__, Socket.GetLastErrorText().c_str()); return false; } // Read the HTTP response: int ret; unsigned char buf[1024]; for (;;) { ret = Socket.Receive(buf, sizeof(buf)); if ((ret == POLARSSL_ERR_NET_WANT_READ) || (ret == POLARSSL_ERR_NET_WANT_WRITE)) { // This value should never be returned, it is handled internally by cBlockingSslClientSocket LOGWARNING("%s: SSL reading failed internally", __FUNCTION__); return false; } if (ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) { break; } if (ret < 0) { LOGWARNING("%s: SSL reading failed: -0x%x", __FUNCTION__, -ret); return false; } if (ret == 0) { break; } a_Response.append((const char *)buf, (size_t)ret); } Socket.Disconnect(); return true; }
bool cAuthenticator::AuthWithYggdrasil(AString & a_UserName, const AString & a_ServerId, AString & a_UUID, Json::Value & a_Properties) { LOGD("Trying to authenticate user %s", a_UserName.c_str()); // Create the GET request: AString ActualAddress = m_Address; ReplaceString(ActualAddress, "%USERNAME%", a_UserName); ReplaceString(ActualAddress, "%SERVERID%", a_ServerId); AString Request; Request += "GET " + ActualAddress + " HTTP/1.0\r\n"; Request += "Host: " + m_Server + "\r\n"; Request += "User-Agent: MCServer\r\n"; Request += "Connection: close\r\n"; Request += "\r\n"; AString Response; if (!SecureGetFromAddress(StarfieldCACert(), m_Server, Request, Response)) { return false; } // Check the HTTP status line: const AString Prefix("HTTP/1.1 200 OK"); AString HexDump; if (Response.compare(0, Prefix.size(), Prefix)) { LOGINFO("User %s failed to auth, bad HTTP status line received", a_UserName.c_str()); LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str()); return false; } // Erase the HTTP headers from the response: size_t idxHeadersEnd = Response.find("\r\n\r\n"); if (idxHeadersEnd == AString::npos) { LOGINFO("User %s failed to authenticate, bad HTTP response header received", a_UserName.c_str()); LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str()); return false; } Response.erase(0, idxHeadersEnd + 4); // Parse the Json response: if (Response.empty()) { return false; } Json::Value root; Json::Reader reader; if (!reader.parse(Response, root, false)) { LOGWARNING("cAuthenticator: Cannot parse received data (authentication) to JSON!"); return false; } a_UserName = root.get("name", "Unknown").asString(); a_UUID = root.get("id", "").asString(); a_Properties = root["properties"]; // If the UUID doesn't contain the hashes, insert them at the proper places: if (a_UUID.size() == 32) { a_UUID.insert(8, "-"); a_UUID.insert(13, "-"); a_UUID.insert(18, "-"); a_UUID.insert(23, "-"); } return true; }