code.pfad.fr/gohmekit@v0.2.1/pairing/pairings.go (about)

     1  package pairing
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  
     8  	"code.pfad.fr/gohmekit/tlv8"
     9  )
    10  
    11  type pairingsRequest struct {
    12  	ktlvState
    13  	Method byte `tlv8:"kTLVType_Method"`
    14  
    15  	// for pairingsAdd and pairingsRemove
    16  	Identifier []byte `tlv8:"kTLVType_Identifier"`
    17  	// for pairingsAdd
    18  	PublicKey []byte `tlv8:"kTLVType_PublicKey"`
    19  }
    20  
    21  func (srv *HTTPServer) pairings(_ *encryptableConn, r io.Reader) ([]byte, error) {
    22  	var req pairingsRequest
    23  	err := tlv8.NewDecoder(r).Decode(&req)
    24  	if err != nil {
    25  		return nil, err
    26  	}
    27  
    28  	if req.State != 1 {
    29  		return nil, fmt.Errorf("unexpected state: %d", req.State)
    30  	}
    31  
    32  	switch req.Method {
    33  	case kTLVMethod_AddPairing:
    34  		return srv.pairingsAdd(req)
    35  	case kTLVMethod_RemovePairing:
    36  		return srv.pairingsRemove(req)
    37  	case kTLVMethod_ListPairings:
    38  		return srv.pairingsList(req)
    39  	default:
    40  		return nil, fmt.Errorf("unexpected method: %d", req.Method)
    41  	}
    42  }
    43  
    44  func (srv *HTTPServer) pairingsAdd(req pairingsRequest) ([]byte, error) {
    45  	saved, err := srv.Database.GetLongTermPublicKey(req.Identifier)
    46  	if err == nil && len(saved) > 0 {
    47  		if !bytes.Equal(saved, req.PublicKey) {
    48  			return ktlvError(2, kTLVError_Unknown)
    49  		}
    50  		// TODO: update permissions?
    51  
    52  		return tlv8.Marshal(ktlvState{2})
    53  	}
    54  
    55  	err = srv.Database.AddLongTermPublicKey(Controller{
    56  		PairingID:         req.Identifier,
    57  		LongTermPublicKey: req.PublicKey,
    58  	})
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  	return tlv8.Marshal(ktlvState{2})
    63  }
    64  
    65  func (srv *HTTPServer) pairingsRemove(req pairingsRequest) ([]byte, error) {
    66  	err := srv.Database.RemoveLongTermPublicKey(req.Identifier)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	return tlv8.Marshal(ktlvState{2})
    72  }
    73  
    74  func (srv *HTTPServer) pairingsList(_ pairingsRequest) ([]byte, error) {
    75  	controllers, err := srv.Database.ListLongTermPublicKey()
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	type controller struct {
    81  		Identifier  []byte   `tlv8:"kTLVType_Identifier"`
    82  		PublicKey   []byte   `tlv8:"kTLVType_PublicKey"`
    83  		Permissions byte     `tlv8:"kTLVType_Permissions"`
    84  		Separator   struct{} `tlv8:"kTLVType_Separator"`
    85  	}
    86  	response := struct {
    87  		ktlvState
    88  		Controllers []controller `tlv8:""`
    89  	}{
    90  		ktlvState:   ktlvState{2},
    91  		Controllers: make([]controller, 0, len(controllers)),
    92  	}
    93  
    94  	for _, c := range controllers {
    95  		response.Controllers = append(response.Controllers, controller{
    96  			Identifier: c.PairingID,
    97  			PublicKey:  c.LongTermPublicKey,
    98  			// Permissions: 0,
    99  		})
   100  	}
   101  
   102  	return tlv8.Marshal(response)
   103  }