@@ -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.
399456func marshalRPCState (state session.State ) (litrpc.SessionState , error ) {
400457 switch state {
0 commit comments