Skip to content

Commit d7650ac

Browse files
committed
session_rpcserver: allow sessions with custom permissions
1 parent 32568bd commit d7650ac

File tree

1 file changed

+76
-19
lines changed

1 file changed

+76
-19
lines changed

session_rpcserver.go

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import (
1111
"github.com/lightninglabs/lightning-node-connect/mailbox"
1212
"github.com/lightninglabs/lightning-terminal/litrpc"
1313
"github.com/lightninglabs/lightning-terminal/session"
14+
"github.com/lightningnetwork/lnd/macaroons"
1415
"google.golang.org/grpc"
16+
"gopkg.in/macaroon-bakery.v2/bakery"
1517
"gopkg.in/macaroon-bakery.v2/bakery/checkers"
1618
"gopkg.in/macaroon.v2"
1719
)
@@ -124,15 +126,40 @@ func (s *sessionRpcServer) AddSession(_ context.Context,
124126
}
125127

126128
if typ != session.TypeMacaroonAdmin &&
127-
typ != session.TypeMacaroonReadonly {
129+
typ != session.TypeMacaroonReadonly &&
130+
typ != session.TypeMacaroonCustom {
128131

129-
return nil, fmt.Errorf("invalid session type, only admin " +
130-
"and readonly macaroon types supported in LiT")
132+
return nil, fmt.Errorf("invalid session type, only admin, " +
133+
"readonly and custom macaroon types supported in LiT")
134+
}
135+
136+
var perms []bakery.Op
137+
if typ == session.TypeMacaroonCustom {
138+
if len(req.MacaroonCustomPermissions) == 0 {
139+
return nil, fmt.Errorf("custom macaroon " +
140+
"permissions must be specified for the " +
141+
"custom macaroon session type")
142+
}
143+
144+
for _, op := range req.MacaroonCustomPermissions {
145+
if op.Entity == macaroons.PermissionEntityCustomURI {
146+
_, ok := s.cfg.permMgr.URIPermissions(op.Action)
147+
if !ok {
148+
return nil, fmt.Errorf("URI %s is "+
149+
"unknown to LiT", op.Action)
150+
}
151+
}
152+
153+
perms = append(perms, bakery.Op{
154+
Entity: op.Entity,
155+
Action: op.Action,
156+
})
157+
}
131158
}
132159

133160
sess, err := session.NewSession(
134161
req.Label, typ, expiry, req.MailboxServerAddr, req.DevServer,
135-
nil, nil,
162+
perms, nil,
136163
)
137164
if err != nil {
138165
return nil, fmt.Errorf("error creating new session: %v", err)
@@ -185,16 +212,17 @@ func (s *sessionRpcServer) resumeSession(sess *session.Session) error {
185212
}
186213

187214
if sess.Type != session.TypeMacaroonAdmin &&
188-
sess.Type != session.TypeMacaroonReadonly {
215+
sess.Type != session.TypeMacaroonReadonly &&
216+
sess.Type != session.TypeMacaroonCustom {
189217

190218
log.Debugf("Not resuming session %x with type %d", pubKeyBytes,
191219
sess.Type)
192220
return nil
193221
}
194222

195223
var (
196-
caveats []macaroon.Caveat
197-
readOnly = sess.Type == session.TypeMacaroonReadonly
224+
caveats []macaroon.Caveat
225+
perms []bakery.Op
198226
)
199227

200228
// Add the session expiry as a macaroon caveat.
@@ -203,10 +231,17 @@ func (s *sessionRpcServer) resumeSession(sess *session.Session) error {
203231
Id: []byte(macExpiry.Condition),
204232
})
205233

234+
if sess.Type == session.TypeMacaroonCustom {
235+
perms = sess.MacaroonRecipe.Permissions
236+
} else {
237+
readOnly := sess.Type == session.TypeMacaroonReadonly
238+
perms = s.cfg.permMgr.ActivePermissions(readOnly)
239+
}
240+
206241
mac, err := s.cfg.superMacBaker(
207242
context.Background(), sess.MacaroonRootKey,
208243
&session.MacaroonRecipe{
209-
Permissions: s.cfg.permMgr.ActivePermissions(readOnly),
244+
Permissions: perms,
210245
Caveats: caveats,
211246
},
212247
)
@@ -380,21 +415,43 @@ func marshalRPCSession(sess *session.Session) (*litrpc.Session, error) {
380415
return nil, err
381416
}
382417

418+
var customPerms []*litrpc.MacaroonPermission
419+
if sess.MacaroonRecipe != nil {
420+
customPerms = marshalRPCCustomPerms(
421+
sess.MacaroonRecipe.Permissions,
422+
)
423+
}
424+
383425
return &litrpc.Session{
384-
Label: sess.Label,
385-
SessionState: rpcState,
386-
SessionType: rpcType,
387-
ExpiryTimestampSeconds: uint64(sess.Expiry.Unix()),
388-
MailboxServerAddr: sess.ServerAddr,
389-
DevServer: sess.DevServer,
390-
PairingSecret: sess.PairingSecret[:],
391-
PairingSecretMnemonic: strings.Join(mnemonic[:], " "),
392-
LocalPublicKey: sess.LocalPublicKey.SerializeCompressed(),
393-
RemotePublicKey: remotePubKey,
394-
CreatedAt: uint64(sess.CreatedAt.Unix()),
426+
Label: sess.Label,
427+
SessionState: rpcState,
428+
SessionType: rpcType,
429+
ExpiryTimestampSeconds: uint64(sess.Expiry.Unix()),
430+
MailboxServerAddr: sess.ServerAddr,
431+
DevServer: sess.DevServer,
432+
PairingSecret: sess.PairingSecret[:],
433+
PairingSecretMnemonic: strings.Join(mnemonic[:], " "),
434+
LocalPublicKey: sess.LocalPublicKey.SerializeCompressed(),
435+
RemotePublicKey: remotePubKey,
436+
CreatedAt: uint64(sess.CreatedAt.Unix()),
437+
MacaroonCustomPermissions: customPerms,
395438
}, nil
396439
}
397440

441+
// marshalRPCCustomPerms converts a list of macaroon permissions into their RPC
442+
// counterpart.
443+
func marshalRPCCustomPerms(ops []bakery.Op) []*litrpc.MacaroonPermission {
444+
rpcOps := make([]*litrpc.MacaroonPermission, len(ops))
445+
for i, op := range ops {
446+
rpcOps[i] = &litrpc.MacaroonPermission{
447+
Entity: op.Entity,
448+
Action: op.Action,
449+
}
450+
}
451+
452+
return rpcOps
453+
}
454+
398455
// marshalRPCState converts a session state to its RPC counterpart.
399456
func marshalRPCState(state session.State) (litrpc.SessionState, error) {
400457
switch state {

0 commit comments

Comments
 (0)