-
Notifications
You must be signed in to change notification settings - Fork 51
/
tokenaccessor.go
130 lines (103 loc) · 4.58 KB
/
tokenaccessor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package tokenaccessor
import (
"bytes"
"crypto/ecdsa"
"errors"
"fmt"
"time"
enforcerconstants "go.aporeto.io/enforcerd/trireme-lib/controller/internal/enforcer/constants"
"go.aporeto.io/enforcerd/trireme-lib/controller/internal/enforcer/utils/ephemeralkeys"
"go.aporeto.io/enforcerd/trireme-lib/controller/pkg/claimsheader"
"go.aporeto.io/enforcerd/trireme-lib/controller/pkg/pkiverifier"
"go.aporeto.io/enforcerd/trireme-lib/controller/pkg/secrets"
"go.aporeto.io/enforcerd/trireme-lib/controller/pkg/tokens"
)
// tokenAccessor is a wrapper around tokenEngine to provide locks for accessing
type tokenAccessor struct {
tokens tokens.TokenEngine
serverID string
validity time.Duration
}
// New creates a new instance of TokenAccessor interface
func New(serverID string, validity time.Duration, secret secrets.Secrets) (TokenAccessor, error) {
var tokenEngine tokens.TokenEngine
var err error
tokenEngine, err = tokens.NewBinaryJWT(validity, serverID)
if err != nil {
return nil, err
}
return &tokenAccessor{
tokens: tokenEngine,
serverID: serverID,
validity: validity,
}, nil
}
// GetTokenValidity returns the duration the token is valid for
func (t *tokenAccessor) GetTokenValidity() time.Duration {
return t.validity
}
// GetTokenServerID returns the server ID which is used the generate the token.
func (t *tokenAccessor) GetTokenServerID() string {
return t.serverID
}
// CreateAckPacketToken creates the authentication token
func (t *tokenAccessor) CreateAckPacketToken(proto314 bool, secretKey []byte, claims *tokens.ConnectionClaims, encodedBuf []byte) ([]byte, error) {
token, err := t.tokens.CreateAckToken(proto314, secretKey, claims, encodedBuf, claimsheader.NewClaimsHeader())
if err != nil {
return nil, fmt.Errorf("unable to create ack token: %v", err)
}
return token, nil
}
func (t *tokenAccessor) Randomize(token []byte, nonce []byte) error {
return t.tokens.Randomize(token, nonce)
}
func (t *tokenAccessor) Sign(buf []byte, key *ecdsa.PrivateKey) ([]byte, error) {
return t.tokens.Sign(buf, key)
}
// createSynPacketToken creates the authentication token
func (t *tokenAccessor) CreateSynPacketToken(claims *tokens.ConnectionClaims, encodedBuf []byte, nonce []byte, claimsHeader *claimsheader.ClaimsHeader, secrets secrets.Secrets) ([]byte, error) {
token, err := t.tokens.CreateSynToken(claims, encodedBuf, nonce, claimsHeader, secrets)
if err != nil {
return nil, fmt.Errorf("unable to create syn token: %v", err)
}
return token, nil
}
// createSynAckPacketToken creates the authentication token for SynAck packets
// We need to sign the received token. No caching possible here
func (t *tokenAccessor) CreateSynAckPacketToken(proto314 bool, claims *tokens.ConnectionClaims, encodedBuf []byte, nonce []byte, claimsHeader *claimsheader.ClaimsHeader, secrets secrets.Secrets, secretKey []byte) ([]byte, error) {
token, err := t.tokens.CreateSynAckToken(proto314, claims, encodedBuf, nonce, claimsHeader, secrets, secretKey)
if err != nil {
return nil, fmt.Errorf("unable to create synack token: %v", err)
}
return token, nil
}
// parsePacketToken parses the packet token and populates the right state.
// Returns an error if the token cannot be parsed or the signature fails
func (t *tokenAccessor) ParsePacketToken(privateKey *ephemeralkeys.PrivateKey, data []byte, secrets secrets.Secrets, claims *tokens.ConnectionClaims, isSynAck bool) ([]byte, *claimsheader.ClaimsHeader, *pkiverifier.PKIControllerInfo, []byte, string, bool, error) {
// Validate the certificate and parse the token
secretKey, header, nonce, controller, proto314, err := t.tokens.DecodeSyn(isSynAck, data, privateKey, secrets, claims)
if err != nil {
return nil, nil, nil, nil, "", false, err
}
// We always a need a valid remote context ID
if claims.T == nil {
return nil, nil, nil, nil, "", false, errors.New("no claims found")
}
remoteContextID, ok := claims.T.Get(enforcerconstants.TransmitterLabel)
if !ok {
return nil, nil, nil, nil, "", false, errors.New("no transmitter label")
}
return secretKey, header, controller, nonce, remoteContextID, proto314, nil
}
// parseAckToken parses the tokens in Ack packets. They don't carry all the state context
// and it needs to be recovered
func (t *tokenAccessor) ParseAckToken(proto314 bool, secretKey []byte, nonce []byte, data []byte, connClaims *tokens.ConnectionClaims) error {
// Validate the certificate and parse the token
if err := t.tokens.DecodeAck(proto314, secretKey, data, connClaims); err != nil {
return err
}
if !bytes.Equal(connClaims.RMT, nonce) {
return errors.New("failed to match context in ack packet")
}
return nil
}