예제 #1
0
        public async Task<UserDTO> CreateUser(NPTicket ticket)
        {
            var user = new UserDTO()
            {
                PSNUserId = ticket.OnlineId,
                IPAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString(),
                Nickname = ticket.OnlineId,  // For the first time, the nickname will be the same as the psn name
                Country = ticket.Region.ToString().TrimEnd('\0').Substring(0, 2),
            };

            int id;
            try
            {
                id = (int)await _users.AddAsync(user);
            }
            catch (Exception e)
            {
                _logger.LogError("Failed to create new user for PSN User: {userName}", ticket.OnlineId);
                return null;
            }

            user.Id = id;

            _logger.LogInformation("Created user: {psnUserId} (DB: {id})", ticket.OnlineId, id);
            return user;
        }
예제 #2
0
        public static bool CreateSession(string sessionid, string psnticket, string ipAddr, SQLiteCommand sqlite_cmd)
        {
            //Decode PSN ticket data
            //sessionid = GetSessionID(sessionid);
            NPTicket ticket = DecodePSNTicket(psnticket);

            if (players.ContainsKey(sessionid))
            {
                return(false);
            }
            SQLiteDataReader sqReader = DatabaseManager.GetReader(sqlite_cmd, "SELECT player_id FROM Users WHERE psn_id=@id", new SQLiteParameter("@id", ticket.user_id.ToString()));
            int id = 1;

            if (!sqReader.HasRows)
            {
                sqReader.Close();
                sqReader = DatabaseManager.GetReader(sqlite_cmd, "SELECT player_id FROM Users ORDER BY player_id DESC LIMIT 1;");
                if (sqReader.HasRows)
                {
                    id = sqReader.GetInt32(0) + 1;
                }
                sqReader.Close();
                DatabaseManager.NonQuery(sqlite_cmd, "INSERT INTO Users VALUES (@psn_id,@player_id,@username,@city,@country,@created_at,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,@player_creation_quota,0,@province,@quote,0,0,@skill_level,@skill_level_id,@skill_level_name,@state,0,0,0,0,0)"
                                         , new SQLiteParameter("@psn_id", ticket.user_id.ToString())
                                         , new SQLiteParameter("@player_id", id)
                                         , new SQLiteParameter("@username", ticket.online_id)
                                         , new SQLiteParameter("@city", "")
                                         , new SQLiteParameter("@country", ticket.region)
                                         , new SQLiteParameter("@created_at", DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss"))
                                         , new SQLiteParameter("@player_creation_quota", 30)
                                         , new SQLiteParameter("@province", "")
                                         , new SQLiteParameter("@quote", "")
                                         , new SQLiteParameter("@skill_level", "Newcomer I")
                                         , new SQLiteParameter("@skill_level_id", "1")
                                         , new SQLiteParameter("@skill_level_name", "Newcomer I")
                                         , new SQLiteParameter("@state", ""));
            }
            else
            {
                id = sqReader.GetInt32(0); sqReader.Close();
            }
            SessionPlayer player = new SessionPlayer();

            player.ip_address = ipAddr;
            player.player_id  = (ulong)id;
            player.username   = ticket.online_id;
            player.presence   = "ONLINE";
            player.encoding   = "US-ASCII";
            players.Add(sessionid, player);
            playerTickets.Add(sessionid, ticket);
            return(true);
        }
예제 #3
0
        private bool VerifyTicket(NPTicket ticket)
        {
            // TODO: Log ticket verification problems
            if (ticket.OnlineId.Length > 32)
                return false;

            if (ticket.Region.Length > 2)
                return false;

            if (ticket.Domain.Length > 4)
                return false;

            return true;
        }
예제 #4
0
        private NPTicket ReadTicket(byte[] bytes)
        {
            var ticket = new NPTicket();

            ticket.version = BitConverter.ToInt32(bytes, 0);

            if (ticket.version == 1)
            {
                ticket.clientID = BitConverter.ToUInt64(bytes, 4);
                ticket.serverID = BitConverter.ToUInt64(bytes, 12);
                ticket.time     = BitConverter.ToUInt32(bytes, 20);
            }

            return(ticket);
        }
예제 #5
0
        static NPTicket DecodePSNTicket(string strTicket)
        {
            while (strTicket.Length % 4 != 0)
            {
                strTicket += "=";
            }
            byte[]       binTicket = Convert.FromBase64String(strTicket);
            BinaryReader br        = new BinaryReader(binTicket);
            NPTicket     ticket    = new NPTicket();

            ticket.version = br.popUInt32();
            br.popArray(0x08);  //Skip header
            br.popArray(0x04);
            ticket.serial_vec = br.popArray(0x14);
            br.popArray(0x04);
            ticket.issuer_id = br.popUInt32();
            br.popArray(0x04);
            ticket.issued_date = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(br.popUInt64());
            br.popArray(0x04);
            ticket.expired_date = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(br.popUInt64());
            br.popArray(0x04);
            ticket.user_id = br.popUInt64();
            br.popArray(0x04);
            ticket.online_id = Encoding.ASCII.GetString(br.popArray(0x20)).Trim('\0');
            br.popArray(0x04);
            //ticket.region = Encoding.ASCII.GetString(br.popArray(0x04)).Trim('\0');
            ticket.region = "br";
            br.popArray(0x04);
            ticket.domain = Encoding.ASCII.GetString(br.popArray(0x04)).Trim('\0');
            br.popArray(0x04);
            ticket.service_id = Encoding.ASCII.GetString(br.popArray(0x18)).Trim('\0');
            br.popArray(0x04);
            ticket.status = br.popUInt32();
            br.popArray(0x04);
            ticket.status_duration = br.popUInt32();
            br.popArray(0x04);
            ticket.date_of_birth = br.popUInt32();
            br.popArray(0x04);
            ticket.unk = br.popArray(0x44);
            return(ticket);
        }
예제 #6
0
        public async Task<ActionResult> Post(ulong pfsVersion)
        {
            PFSType pfsType = (PFSType)pfsVersion;
            _logger.LogDebug("Login request from {host} with PFS: {pfsType} ({pfsNum})", Request.Host, pfsType, (long)pfsType);

            if (_gsOptions.EnforceGameVersion && !EnsureVersion(pfsType))
                return Forbid();

            if (Request.ContentLength >= 0x300)
            {
                _logger.LogWarning("Received a ticket too big - {size} from {host}", Request.ContentLength, Request.Host);
                return BadRequest();
            }

            NPTicket ticket;
            try
            {
                byte[] buf = new byte[(int)Request.ContentLength];
                await Request.Body.ReadAsync(buf.AsMemory(0, buf.Length));
                ticket = NPTicket.FromBuffer(buf);
            }
            catch (Exception e)
            {
                _logger.LogWarning(e, "Could not read NP ticket provided by client");
                return BadRequest();
            }

            if (!VerifyTicket(ticket))
                return BadRequest();

            _logger.LogDebug("Auth Request: NP_Ticket -> PFS: {pfsVersion} | OnlineID: {OnlineId} | Region: {Region}", pfsVersion, ticket.OnlineId, ticket.Region);

            // Check if already connected
            if (CheckAlreadyConnected(ticket.OnlineId))
                _logger.LogTrace("Auth Request from OnlineID: {OnlineId} which was already connected", ticket.OnlineId);

            UserDTO user = await _users.GetByPSNUserIdAsync(ticket.OnlineId) ?? await CreateUser(ticket);
            if (user is null)
            {
                _logger.LogError("Failed to get or create user from db: Name: {name}", ticket.OnlineId);
                return Problem();    
            }

            var now = DateTime.Now;


            // From this point, auth is OK
            var resp = new TicketResult()
            {
                Result = "1", // Doesn't seem to do much.
                Nickname = ticket.OnlineId,
                UserId = ticket.OnlineId,
                UserNumber = user.Id,
                ServerTime = now,
            };

            var expiryTime = now.AddHours(1);
            var sToken = new SessionToken(GenerateToken(expiryTime), expiryTime);

            var cookieOptions = new CookieOptions() { Expires = sToken.ExpiryDate };
            Response.Cookies.Append("X-gt-token", sToken.Token, cookieOptions);

            var player = new Player(user, sToken);
            player.LastUpdate = now;
            _players.AddUser(player);

            return Ok(resp);
        }