예제 #1
0
// Handle processes a container to pair with a new client without going through the pairing process.
func (c *PairingController) Handle(cont util.Container) (util.Container, error) {
	method := pairMethodType(cont.GetByte(TagPairingMethod))
	username := cont.GetString(TagUsername)
	publicKey := cont.GetBytes(TagPublicKey)

	log.Println("[VERB] ->   Method:", method)
	log.Println("[VERB] -> Username:"******"[VERB] ->     LTPK:", publicKey)

	entity := db.NewEntity(username, publicKey, nil)

	switch method {
	case PairingMethodDelete:
		log.Printf("[INFO] Remove LTPK for client '%s'\n", username)
		c.database.DeleteEntity(entity)
	case PairingMethodAdd:
		err := c.database.SaveEntity(entity)
		if err != nil {
			log.Println("[ERRO]", err)
			return nil, err
		}
	default:
		return nil, fmt.Errorf("Invalid pairing method type %v", method)
	}

	out := util.NewTLV8Container()
	out.SetByte(TagSequence, 0x2)

	return out, nil
}
예제 #2
0
// Handle processes a container to verify if a client is paired correctly.
func (verify *VerifyServerController) Handle(in util.Container) (util.Container, error) {
	var out util.Container
	var err error

	method := PairMethodType(in.GetByte(TagPairingMethod))

	// It is valid that method is not sent
	// If method is sent then it must be 0x00
	if method != PairingMethodDefault {
		return nil, errInvalidPairMethod(method)
	}

	seq := VerifyStepType(in.GetByte(TagSequence))

	switch seq {
	case VerifyStepStartRequest:
		if verify.step != VerifyStepWaiting {
			verify.reset()
			return nil, errInvalidInternalVerifyStep(verify.step)
		}
		out, err = verify.handlePairVerifyStart(in)
	case VerifyStepFinishRequest:
		if verify.step != VerifyStepStartResponse {
			verify.reset()
			return nil, errInvalidInternalVerifyStep(verify.step)
		}

		out, err = verify.handlePairVerifyFinish(in)
	default:
		return nil, errInvalidVerifyStep(seq)
	}

	return out, err
}
예제 #3
0
파일: pairings.go 프로젝트: smitterson/hc
func (endpoint *Pairing) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	log.Printf("[VERB] %v POST /pairings", request.RemoteAddr)
	response.Header().Set("Content-Type", netio.HTTPContentTypePairingTLV8)

	var err error
	var in util.Container
	var out util.Container

	if in, err = util.NewTLV8ContainerFromReader(request.Body); err == nil {
		out, err = endpoint.controller.Handle(in)
	}

	if err != nil {
		log.Println(err)
		response.WriteHeader(http.StatusInternalServerError)
	} else {
		io.Copy(response, out.BytesBuffer())

		// Send events based on pairing method type
		b := in.GetByte(pair.TagPairingMethod)
		switch pair.PairMethodType(b) {
		case pair.PairingMethodDelete: // pairing removed
			endpoint.emitter.Emit(event.DeviceUnpaired{})

		case pair.PairingMethodAdd: // pairing added
			endpoint.emitter.Emit(event.DevicePaired{})

		}
	}
}
예제 #4
0
// Server -> Client
// - only error ocde (optional)
func (verify *VerifyClientController) handlePairVerifyStepFinishResponse(in util.Container) (util.Container, error) {
	code := errCode(in.GetByte(TagErrCode))
	if code != ErrCodeNo {
		fmt.Printf("Unexpected error %v\n", code)
	}

	return nil, nil
}
예제 #5
0
func (endpoint *PairVerify) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	log.Printf("[VERB] %v POST /pair-verify", request.RemoteAddr)
	response.Header().Set("Content-Type", netio.HTTPContentTypePairingTLV8)

	key := endpoint.context.GetConnectionKey(request)
	session := endpoint.context.Get(key).(netio.Session)
	ctlr := session.PairVerifyHandler()
	if ctlr == nil {
		log.Println("[VERB] Create new pair verify controller")
		ctlr = pair.NewVerifyServerController(endpoint.database, endpoint.context)
		session.SetPairVerifyHandler(ctlr)
	}

	var err error
	var in util.Container
	var out util.Container
	var secSession crypto.Cryptographer

	if in, err = util.NewTLV8ContainerFromReader(request.Body); err == nil {
		out, err = ctlr.Handle(in)
	}

	if err != nil {
		log.Println(err)
		response.WriteHeader(http.StatusInternalServerError)
	} else {
		io.Copy(response, out.BytesBuffer())

		// When key verification is done, switch to a secure session
		// based on the negotiated shared session key
		b := out.GetByte(pair.TagSequence)
		switch pair.VerifyStepType(b) {
		case pair.VerifyStepFinishResponse:
			if secSession, err = crypto.NewSecureSessionFromSharedKey(ctlr.SharedKey()); err == nil {
				log.Println("[VERB] Setup secure session")
				session.SetCryptographer(secSession)
			} else {
				log.Println("[ERRO] Could not setup secure session.", err)
			}
		}
	}
}
예제 #6
0
// Handle processes a container to pair (exchange keys) with an accessory.
func (setup *SetupClientController) Handle(in util.Container) (util.Container, error) {
	method := pairMethodType(in.GetByte(TagPairingMethod))

	// It is valid that method is not sent
	// If method is sent then it must be 0x00
	if method != PairingMethodDefault {
		return nil, errInvalidPairMethod(method)
	}

	code := errCode(in.GetByte(TagErrCode))
	if code != ErrCodeNo {
		log.Println("[ERRO]", code)
		return nil, code.Error()
	}

	seq := pairStepType(in.GetByte(TagSequence))

	var out util.Container
	var err error

	switch seq {
	case PairStepStartResponse:
		out, err = setup.handlePairStepStartResponse(in)
	case PairStepVerifyResponse:
		out, err = setup.handlePairStepVerifyResponse(in)
	case PairStepKeyExchangeResponse:
		out, err = setup.handleKeyExchange(in)
	default:
		return nil, errInvalidPairStep(seq)
	}

	return out, err
}
예제 #7
0
// Handle processes a container to pair (exchange keys) with a client.
func (setup *SetupServerController) Handle(in util.Container) (out util.Container, err error) {
	method := PairMethodType(in.GetByte(TagPairingMethod))

	// It is valid that pair method is not sent
	// If method set then it must be 0x00
	if method != PairingMethodDefault {
		return nil, errInvalidPairMethod(method)
	}

	seq := PairStepType(in.GetByte(TagSequence))

	switch seq {
	case PairStepStartRequest:
		if setup.step != PairStepWaiting {
			setup.reset()
			return nil, errInvalidInternalPairStep(setup.step)
		}

		out, err = setup.handlePairStart(in)
	case PairStepVerifyRequest:
		if setup.step != PairStepStartResponse {
			setup.reset()
			return nil, errInvalidInternalPairStep(setup.step)
		}

		out, err = setup.handlePairVerify(in)
	case PairStepKeyExchangeRequest:
		if setup.step != PairStepVerifyResponse {
			setup.reset()
			return nil, errInvalidInternalPairStep(setup.step)
		}

		out, err = setup.handleKeyExchange(in)
	default:
		return nil, errInvalidPairStep(seq)
	}

	return out, err
}
예제 #8
0
func (endpoint *PairSetup) ServeHTTP(response http.ResponseWriter, request *http.Request) {
	log.Debug.Printf("%v POST /pair-setup", request.RemoteAddr)
	response.Header().Set("Content-Type", hap.HTTPContentTypePairingTLV8)

	var err error
	var in util.Container
	var out util.Container

	key := endpoint.context.GetConnectionKey(request)
	session := endpoint.context.Get(key).(hap.Session)
	ctrl := session.PairSetupHandler()
	if ctrl == nil {
		log.Debug.Println("Create new pair setup controller")

		if ctrl, err = pair.NewSetupServerController(endpoint.device, endpoint.database); err != nil {
			log.Info.Panic(err)
		}

		session.SetPairSetupHandler(ctrl)
	}

	if in, err = util.NewTLV8ContainerFromReader(request.Body); err == nil {
		out, err = ctrl.Handle(in)
	}

	if err != nil {
		log.Info.Println(err)
		response.WriteHeader(http.StatusInternalServerError)
	} else {
		io.Copy(response, out.BytesBuffer())

		// Send event when key exchange is done
		b := out.GetByte(pair.TagSequence)
		switch pair.PairStepType(b) {
		case pair.PairStepKeyExchangeResponse:
			endpoint.emitter.Emit(event.DevicePaired{})
		}
	}
}
예제 #9
0
// Handle processes a container to verify if an accessory is paired correctly.
func (verify *VerifyClientController) Handle(in util.Container) (util.Container, error) {
	var out util.Container
	var err error

	method := pairMethodType(in.GetByte(TagPairingMethod))

	// It is valid that method is not sent
	// If method is sent then it must be 0x00
	if method != PairingMethodDefault {
		return nil, errInvalidPairMethod(method)
	}

	seq := VerifyStepType(in.GetByte(TagSequence))
	switch seq {
	case VerifyStepStartResponse:
		out, err = verify.handlePairStepVerifyResponse(in)
	case VerifyStepFinishResponse:
		out, err = verify.handlePairVerifyStepFinishResponse(in)
	default:
		return nil, errInvalidVerifyStep(seq)
	}

	return out, err
}