Skip to content

Commit

Permalink
Only allow a single pair request
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelthomas2774 committed Oct 27, 2019
1 parent e87f774 commit 5babe40
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 6 deletions.
20 changes: 17 additions & 3 deletions src/lib/HAPServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ export class HAPServer extends EventEmitter<Events> {
_httpServer: EventedHTTPServer;
_relayServer?: any;

/** Session currently trying to pair with the server */
_pairing: Session | null = null;

allowInsecureRequest: boolean;
_keepAliveTimerID: NodeJS.Timeout;

Expand Down Expand Up @@ -386,10 +389,18 @@ export class HAPServer extends EventEmitter<Events> {
_handlePair = (request: IncomingMessage, response: ServerResponse, session: Session, events: any, requestData: Buffer) => {
// Can only be directly paired with one iOS device
if (!this.allowInsecureRequest && this.accessoryInfo.paired()) {
response.writeHead(200, {"Content-Type": "application/pairing+tlv8"});
response.end(tlv.encode(TLVValues.STATE, States.M2, TLVValues.ERROR_CODE, Codes.UNAVAILABLE));
return;
response.writeHead(200, {"Content-Type": "application/pairing+tlv8"});
response.end(tlv.encode(TLVValues.STATE, States.M2, TLVValues.ERROR_CODE, Codes.UNAVAILABLE));
return;
}

if (this._pairing && this._pairing !== session && session._connection.connected) {
response.writeHead(200, {"Content-Type": "application/pairing+tlv8"});
response.end(tlv.encode(TLVValues.STATE, States.M2, TLVValues.ERROR_CODE, Codes.BUSY));
return;
}
this._pairing = session;

var objects = tlv.decode(requestData);
var sequence = objects[TLVValues.SEQUENCE_NUM][0]; // value is single byte with sequence number
if (sequence == 0x01)
Expand Down Expand Up @@ -431,6 +442,7 @@ export class HAPServer extends EventEmitter<Events> {
debug("[%s] Error while checking pincode: %s", this.accessoryInfo.username, err.message);
response.writeHead(200, {"Content-Type": "application/pairing+tlv8"});
response.end(tlv.encode(TLVValues.SEQUENCE_NUM, 0x04, TLVValues.ERROR_CODE, Codes.INVALID_REQUEST));
this._pairing = null;
return;
}
// "M2 is the proof that the server actually knows your password."
Expand Down Expand Up @@ -476,6 +488,7 @@ export class HAPServer extends EventEmitter<Events> {
debug("[%s] Invalid signature", this.accessoryInfo.username);
response.writeHead(200, {"Content-Type": "application/pairing+tlv8"});
response.end(tlv.encode(TLVValues.SEQUENCE_NUM, 0x06, TLVValues.ERROR_CODE, Codes.INVALID_REQUEST));
this._pairing = null;
return;
}
this._handlePairStepFive(request, response, session, clientUsername, clientLTPK, hkdfEncKey);
Expand Down Expand Up @@ -503,6 +516,7 @@ export class HAPServer extends EventEmitter<Events> {
debug("[%s] Error adding pairing info: %s", this.accessoryInfo.username, err.message);
response.writeHead(500, "Server Error");
response.end();
this._pairing = null;
return;
}
// send final pairing response to client
Expand Down
11 changes: 8 additions & 3 deletions src/lib/util/eventedhttp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export class EventedHTTPServer extends EventEmitter<Events> {
// Called by net.Server when a new client connects. We will set up a new EventedHTTPServerConnection to manage the
// lifetime of this connection.
_onConnection = (socket: Socket) => {
var connection = new EventedHTTPServerConnection(socket);
var connection = new EventedHTTPServerConnection(this, socket);

// pass on session events to our listeners directly
connection.on(EventedHTTPServerEvents.REQUEST, (request: IncomingMessage, response: ServerResponse, session: Session, events: any) => { this.emit(EventedHTTPServerEvents.REQUEST, request, response, session, events); });
Expand Down Expand Up @@ -219,7 +219,7 @@ export class Session {
* @event 'close' => function() { }
*/
class EventedHTTPServerConnection extends EventEmitter<Events> {

server: EventedHTTPServer;
sessionID: string;
_remoteAddress: string;
_pendingClientSocketData: Nullable<Buffer>;
Expand All @@ -234,9 +234,10 @@ class EventedHTTPServerConnection extends EventEmitter<Events> {
_events: Record<string, boolean>;
_httpPort?: number;

constructor(clientSocket: Socket) {
constructor(server: EventedHTTPServer, clientSocket: Socket) {
super();

this.server = server;
this.sessionID = uuid.generate(clientSocket.remoteAddress + ':' + clientSocket.remotePort);
this._remoteAddress = clientSocket.remoteAddress!; // cache because it becomes undefined in 'onClientSocketClose'
this._pendingClientSocketData = bufferShim.alloc(0); // data received from client before HTTP proxy is fully setup
Expand Down Expand Up @@ -266,6 +267,10 @@ class EventedHTTPServerConnection extends EventEmitter<Events> {
debug("[%s] New connection from client", this._remoteAddress);
}

get connected() {
return this.server._connections.includes(this);
}

sendEvent = (event: string, data: Buffer | string, contentType: string, excludeEvents?: Record<string, boolean>) => {
// has this connection subscribed to the given event? if not, nothing to do!
if (!this._events[event]) {
Expand Down

0 comments on commit 5babe40

Please sign in to comment.