@@ -307,9 +307,11 @@ func (p *rpcProxy) director(ctx context.Context,
307
307
308
308
outCtx := metadata .NewOutgoingContext (ctx , mdCopy )
309
309
310
- // Is there a basic auth set?
310
+ // Is there a basic auth or super macaroon set?
311
311
authHeaders := md .Get ("authorization" )
312
- if len (authHeaders ) == 1 {
312
+ macHeader := md .Get (HeaderMacaroon )
313
+ switch {
314
+ case len (authHeaders ) == 1 :
313
315
macBytes , err := p .basicAuthToMacaroon (
314
316
authHeaders [0 ], requestURI , nil ,
315
317
)
@@ -319,6 +321,20 @@ func (p *rpcProxy) director(ctx context.Context,
319
321
if len (macBytes ) > 0 {
320
322
mdCopy .Set (HeaderMacaroon , hex .EncodeToString (macBytes ))
321
323
}
324
+
325
+ case len (macHeader ) == 1 && session .IsSuperMacaroon (macHeader [0 ]):
326
+ // If we have a macaroon, and it's a super macaroon, then we
327
+ // need to convert it into the actual daemon macaroon if they're
328
+ // running in remote mode.
329
+ macBytes , err := p .convertSuperMacaroon (
330
+ ctx , macHeader [0 ], requestURI ,
331
+ )
332
+ if err != nil {
333
+ return outCtx , nil , err
334
+ }
335
+ if len (macBytes ) > 0 {
336
+ mdCopy .Set (HeaderMacaroon , hex .EncodeToString (macBytes ))
337
+ }
322
338
}
323
339
324
340
// Direct the call to the correct backend. All gRPC calls end up here
@@ -549,6 +565,56 @@ func (p *rpcProxy) basicAuthToMacaroon(basicAuth, requestURI string,
549
565
}
550
566
}
551
567
568
+ // convertSuperMacaroon converts a super macaroon into a daemon specific
569
+ // macaroon, but only if the super macaroon contains all required permissions
570
+ // and the target daemon is actually running in remote mode.
571
+ func (p * rpcProxy ) convertSuperMacaroon (ctx context.Context , macHex string ,
572
+ fullMethod string ) ([]byte , error ) {
573
+
574
+ requiredPermissions , ok := p .permissionMap [fullMethod ]
575
+ if ! ok {
576
+ return nil , fmt .Errorf ("%s: unknown permissions required for " +
577
+ "method" , fullMethod )
578
+ }
579
+
580
+ // We have a super macaroon, from here on out we'll return errors if
581
+ // something isn't the way we expect it to be.
582
+ macBytes , err := hex .DecodeString (macHex )
583
+ if err != nil {
584
+ return nil , err
585
+ }
586
+
587
+ // Make sure the super macaroon is valid and contains all the required
588
+ // permissions.
589
+ err = p .superMacValidator (
590
+ ctx , macBytes , requiredPermissions , fullMethod ,
591
+ )
592
+ if err != nil {
593
+ return nil , err
594
+ }
595
+
596
+ // Is this actually a request that goes to a daemon that is running
597
+ // remotely?
598
+ switch {
599
+ case isFaradayURI (fullMethod ) && p .cfg .faradayRemote :
600
+ return readMacaroon (lncfg .CleanAndExpandPath (
601
+ p .cfg .Remote .Faraday .MacaroonPath ,
602
+ ))
603
+
604
+ case isLoopURI (fullMethod ) && p .cfg .loopRemote :
605
+ return readMacaroon (lncfg .CleanAndExpandPath (
606
+ p .cfg .Remote .Loop .MacaroonPath ,
607
+ ))
608
+
609
+ case isPoolURI (fullMethod ) && p .cfg .poolRemote :
610
+ return readMacaroon (lncfg .CleanAndExpandPath (
611
+ p .cfg .Remote .Pool .MacaroonPath ,
612
+ ))
613
+ }
614
+
615
+ return nil , nil
616
+ }
617
+
552
618
// dialBufConnBackend dials an in-memory connection to an RPC listener and
553
619
// ignores any TLS certificate mismatches.
554
620
func dialBufConnBackend (listener * bufconn.Listener ) (* grpc.ClientConn , error ) {
0 commit comments