diff --git a/src/middleware/console-status-verification.ts b/src/middleware/console-status-verification.ts index 90d5cb3..a8c98a4 100644 --- a/src/middleware/console-status-verification.ts +++ b/src/middleware/console-status-verification.ts @@ -68,70 +68,88 @@ async function consoleStatusVerificationMiddleware(request: express.Request, res return; } - // * This is kinda temp for now. Needs to be redone to handle linking this data to existing 3DS devices in the DB - // TODO - 3DS consoles are created in the NASC middleware. They need special handling to link them up with the data in the NNID API! - if (request.certificate.consoleType === 'wiiu') { - const certificateDeviceID = parseInt(request.certificate.certificateName.slice(2), 16); + let device = await Device.findOne({ + serial: serialNumber, + }); - if (deviceID !== certificateDeviceID) { - // TODO - Change this to a different error - response.status(400).send(xmlbuilder.create({ - error: { - cause: 'Bad Request', - code: '1600', - message: 'Unable to process request' - } - }).end()); + if (!device && request.certificate.consoleType === '3ds') { + // * A 3DS console document will ALWAYS be created by NASC before + // * Hitting the NNAS server. NASC stores the serial number at + // * the time the device document was created. Therefore we can + // * know that serial tampering happened on the 3DS if this fails + // * to find a device document. + response.status(400).send(xmlbuilder.create({ + error: { + code: '0002', + message: 'serialNumber format is invalid' + } + }).end()); - return; - } - - // * Only store a hash of the certificate in case of a breach - const certificateHash = crypto.createHash('sha256').update(request.certificate._certificate).digest('base64'); - - let device = await Device.findOne({ - certificate_hash: certificateHash, - }); - - if (!device) { - device = await Device.create({ - model: 'wup', - device_id: deviceID, - serial: serialNumber, - linked_pids: [], - certificate_hash: certificateHash - }); - } - - if (device.serial !== serialNumber) { - // TODO - Change this to a different error - response.status(400).send(xmlbuilder.create({ - error: { - cause: 'Bad Request', - code: '1600', - message: 'Unable to process request' - } - }).end()); - - return; - } - - if (device.access_level < 0) { - response.status(400).send(xmlbuilder.create({ - errors: { - error: { - code: '0012', - message: 'Device has been banned by game server' // TODO - This is not the right error message - } - } - }).end()); - - return; - } - - request.device = device; + return; } + const certificateHash = crypto.createHash('sha256').update(request.certificate._certificate).digest('base64'); + + if (!device) { + // * Device must be a fresh Wii U + device = await Device.create({ + model: 'wup', + device_id: deviceID, + serial: serialNumber, + linked_pids: [], + certificate_hash: certificateHash + }); + } + + if (!device.certificate_hash && request.certificate.consoleType === '3ds') { + device.certificate_hash = certificateHash; + + await device.save(); + } + + if (device.serial !== serialNumber) { + // TODO - Change this to a different error + response.status(400).send(xmlbuilder.create({ + error: { + cause: 'Bad Request', + code: '1600', + message: 'Unable to process request' + } + }).end()); + + return; + } + + const certificateDeviceID = parseInt(request.certificate.certificateName.slice(2).split('-')[0], 16); + + if (deviceID !== certificateDeviceID) { + // TODO - Change this to a different error + response.status(400).send(xmlbuilder.create({ + error: { + cause: 'Bad Request', + code: '1600', + message: 'Unable to process request' + } + }).end()); + + return; + } + + if (device.access_level < 0) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0012', + message: 'Device has been banned by game server' // TODO - This is not the right error message + } + } + }).end()); + + return; + } + + request.device = device; + return next(); }