rpcserver: accept and send privacy flags

For autopilot session registration, we accept default recommendations
from autopilot in order to weaken privacy obfuscation for the requested
features. Default privacy flags are supplied by ListFeatures and by
flags passed to the AddAutopilotSession request.

Privacy flags are ORed to combine to the weakest aggregated privacy
obfuscation in order to allow for multiple feature registration. In
order to preserve high privacy settings for a feature it should be
registered in an isolated manner.
This commit is contained in:
bitromortac 2023-11-20 16:57:26 +01:00
parent 460dec1779
commit 8248f2650b
No known key found for this signature in database
GPG key ID: 1965063FC13BEBE2
4 changed files with 61 additions and 13 deletions

View file

@ -379,11 +379,12 @@ func (c *Client) ListFeatures(ctx context.Context) (map[string]*Feature,
// Note: this is part of the Autopilot interface.
func (c *Client) RegisterSession(ctx context.Context, pubKey *btcec.PublicKey,
mailboxAddr string, devServer bool, featureConf map[string][]byte,
groupKey *btcec.PublicKey, linkSig []byte) (*btcec.PublicKey, error) {
groupKey *btcec.PublicKey, linkSig []byte,
privacyFlags uint64) (*btcec.PublicKey, error) {
remotePub, err := c.registerSession(
ctx, pubKey, mailboxAddr, devServer, featureConf,
groupKey, linkSig,
groupKey, linkSig, privacyFlags,
)
if err != nil {
log.Errorf("unsuccessful registration of session %x",
@ -429,8 +430,8 @@ func (c *Client) trackClient(pubKey *btcec.PublicKey) {
// public key with the autopilot server.
func (c *Client) registerSession(ctx context.Context, pubKey *btcec.PublicKey,
mailboxAddr string, devServer bool, featureConfig map[string][]byte,
groupLocalPub *btcec.PublicKey, linkSig []byte) (*btcec.PublicKey,
error) {
groupLocalPub *btcec.PublicKey, linkSig []byte,
privacyFlags uint64) (*btcec.PublicKey, error) {
client, cleanup, err := c.getClientConn()
if err != nil {
@ -453,6 +454,7 @@ func (c *Client) registerSession(ctx context.Context, pubKey *btcec.PublicKey,
LndVersion: marshalVersion(c.cfg.LndVersion),
GroupResponderKey: groupKey,
GroupResponderSig: linkSig,
PrivacyFlags: privacyFlags,
},
)
if err != nil {

View file

@ -45,7 +45,9 @@ func TestAutopilotClient(t *testing.T) {
require.ErrorContains(t, err, "no such client")
// Register the client.
_, err = client.RegisterSession(ctx, pubKey, "", false, nil, nil, nil)
_, err = client.RegisterSession(
ctx, pubKey, "", false, nil, nil, nil, 0,
)
require.NoError(t, err)
// Assert that the server sees the new client and has it in the Active

View file

@ -30,7 +30,7 @@ type Autopilot interface {
RegisterSession(ctx context.Context, pubKey *btcec.PublicKey,
mailboxAddr string, devServer bool,
featureConf map[string][]byte, linkedGroupKey *btcec.PublicKey,
linkSig []byte) (*btcec.PublicKey, error)
linkSig []byte, privacyFlags uint64) (*btcec.PublicKey, error)
// ActivateSession attempts to inform the autopilot server that the
// given session is still active. After this is called, the autopilot

View file

@ -934,6 +934,52 @@ func (s *sessionRpcServer) AddAutopilotSession(ctx context.Context,
// Check that each requested feature is a valid autopilot feature and
// that the necessary rules for the feature have been specified.
featureRules := make(map[string]map[string]string, len(req.Features))
// Determine privacy flags to use for session registration.
var privacyFlags session.PrivacyFlags
if req.PrivacyFlagsSet {
// We apply privacy flags from the session request in order to
// to be able to set flags resulting from non-standard feature
// configurations.
privacyFlags, err = session.Deserialize(req.PrivacyFlags)
if err != nil {
return nil, fmt.Errorf("error deserializing privacy "+
"flags (%v) from request: %w",
req.PrivacyFlags, err)
}
} else {
// Otherwise, privacyFlags will contain all the combined (ORed)
// privacy flags for all requested features with defaults from
// the autopilot. This means that if any of the features
// includes a less restrictive privacy flag, this will also
// apply to features that in principle can be run with better
// privacy. Checks for features' privacy flag and previous
// session compatibility are done on the autopilot's side for
// upgrade flexibility.
for f := range req.Features {
// Check that the features is known by the autopilot
// server.
autopilotFeature, ok := autopilotFeatureMap[f]
if !ok {
return nil, fmt.Errorf("%s is not a features "+
"provided by the Autopilot server", f)
}
// Deserialize and check that we know the privacy flags.
featurePrivacyFlags, err := session.Deserialize(
autopilotFeature.PrivacyFlags,
)
if err != nil {
return nil, fmt.Errorf("error deserializing "+
"privacy flags (%v) from autopilot: %w",
autopilotFeature.PrivacyFlags, err)
}
// We combine all privacy flags.
privacyFlags = privacyFlags.Add(featurePrivacyFlags)
}
}
for f, rs := range req.Features {
// Check that the features is known by the autopilot server.
autopilotFeature, ok := autopilotFeatureMap[f]
@ -957,8 +1003,7 @@ func (s *sessionRpcServer) AddAutopilotSession(ctx context.Context,
if privacy {
var privMapPairs map[string]string
v, privMapPairs, err = v.RealToPseudo(
knownPrivMapPairs,
session.PrivacyFlags{},
knownPrivMapPairs, privacyFlags,
)
if err != nil {
return nil, err
@ -1113,7 +1158,7 @@ func (s *sessionRpcServer) AddAutopilotSession(ctx context.Context,
sess, err := session.NewSession(
id, localPrivKey, req.Label, session.TypeAutopilot, expiry,
req.MailboxServerAddr, req.DevServer, perms, caveats,
clientConfig, privacy, linkedGroupID, session.PrivacyFlags{},
clientConfig, privacy, linkedGroupID, privacyFlags,
)
if err != nil {
return nil, fmt.Errorf("error creating new session: %v", err)
@ -1143,8 +1188,7 @@ func (s *sessionRpcServer) AddAutopilotSession(ctx context.Context,
if privacy {
for name, configB := range clientConfig {
configB, privMapPairs, err := firewall.ObfuscateConfig(
knownPrivMapPairs, configB,
session.PrivacyFlags{},
knownPrivMapPairs, configB, privacyFlags,
)
if err != nil {
return nil, err
@ -1188,6 +1232,7 @@ func (s *sessionRpcServer) AddAutopilotSession(ctx context.Context,
remoteKey, err := s.cfg.autopilot.RegisterSession(
ctx, sess.LocalPublicKey, sess.ServerAddr, sess.DevServer,
obfuscatedConfig, prevSessionPub, linkSig,
privacyFlags.Serialize(),
)
if err != nil {
return nil, fmt.Errorf("error registering session with "+
@ -1416,8 +1461,7 @@ func (s *sessionRpcServer) marshalRPCSession(sess *session.Session) (
sess.GroupID,
)
val, err = val.PseudoToReal(
db,
session.PrivacyFlags{},
db, sess.PrivacyFlags,
)
if err != nil {
return nil, err