<commit_before>// Copyright © 2017 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package router

import (
	"fmt"
	"time"

	pb_gateway "github.com/TheThingsNetwork/api/gateway"
	pb "github.com/TheThingsNetwork/api/router"
	"github.com/TheThingsNetwork/api/router/routerclient"
	"github.com/TheThingsNetwork/go-account-lib/claims"
	"github.com/TheThingsNetwork/go-utils/grpc/ttnctx"
	"github.com/TheThingsNetwork/ttn/api/ratelimit"
	"github.com/TheThingsNetwork/ttn/core/router/gateway"
	"github.com/TheThingsNetwork/ttn/utils/errors"
	"github.com/TheThingsNetwork/ttn/utils/random"
	"github.com/spf13/viper"
	"golang.org/x/net/context" // See https://github.com/grpc/grpc-go/issues/711"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
)

type routerRPC struct {
	router *router
	routerclient.RouterStreamServer

	uplinkRate *ratelimit.Registry
	statusRate *ratelimit.Registry
}

func (r *routerRPC) gatewayFromMetadata(md metadata.MD) (gtw *gateway.Gateway, err error) {
	gatewayID, err := ttnctx.IDFromMetadata(md)
	if err != nil {
		return nil, err
	}

	authErr := errors.NewErrPermissionDenied("Gateway not authenticated")
	authenticated := false
	token, _ := ttnctx.TokenFromMetadata(md)

	if token != "" {
		if r.router.TokenKeyProvider == nil {
			return nil, errors.NewErrInternal("No token provider configured")
		}
		claims, err := claims.FromGatewayToken(r.router.TokenKeyProvider, token)
		if err != nil {
			authErr = errors.NewErrPermissionDenied(fmt.Sprintf("Gateway token invalid: %s", err))
		} else {
			if claims.Subject != gatewayID {
				authErr = errors.NewErrPermissionDenied(fmt.Sprintf("Token subject \"%s\" not consistent with gateway ID \"%s\"", claims.Subject, gatewayID))
			} else {
				authErr = nil
				authenticated = true
			}
		}
	}

	if authErr != nil && !viper.GetBool("router.skip-verify-gateway-token") {
		return nil, authErr
	}

	gtw = r.router.getGateway(gatewayID)
	gtw.SetAuth(token, authenticated)

	return gtw, nil
}

func (r *routerRPC) gatewayFromContext(ctx context.Context) (gtw *gateway.Gateway, err error) {
	md := ttnctx.MetadataFromIncomingContext(ctx)<commit_msg>Only store gateway token if authenticated<commit_after>// Copyright © 2017 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package router

import (
	"fmt"
	"time"

	pb_gateway "github.com/TheThingsNetwork/api/gateway"
	pb "github.com/TheThingsNetwork/api/router"
	"github.com/TheThingsNetwork/api/router/routerclient"
	"github.com/TheThingsNetwork/go-account-lib/claims"
	"github.com/TheThingsNetwork/go-utils/grpc/ttnctx"
	"github.com/TheThingsNetwork/ttn/api/ratelimit"
	"github.com/TheThingsNetwork/ttn/core/router/gateway"
	"github.com/TheThingsNetwork/ttn/utils/errors"
	"github.com/TheThingsNetwork/ttn/utils/random"
	"github.com/spf13/viper"
	"golang.org/x/net/context" // See https://github.com/grpc/grpc-go/issues/711"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
)

type routerRPC struct {
	router *router
	routerclient.RouterStreamServer

	uplinkRate *ratelimit.Registry
	statusRate *ratelimit.Registry
}

func (r *routerRPC) gatewayFromMetadata(md metadata.MD) (gtw *gateway.Gateway, err error) {
	gatewayID, err := ttnctx.IDFromMetadata(md)
	if err != nil {
		return nil, err
	}

	authErr := errors.NewErrPermissionDenied("Gateway not authenticated")
	authenticated := false
	token, _ := ttnctx.TokenFromMetadata(md)

	if token != "" {
		if r.router.TokenKeyProvider == nil {
			return nil, errors.NewErrInternal("No token provider configured")
		}
		claims, err := claims.FromGatewayToken(r.router.TokenKeyProvider, token)
		if err != nil {
			authErr = errors.NewErrPermissionDenied(fmt.Sprintf("Gateway token invalid: %s", err))
		} else {
			if claims.Subject != gatewayID {
				authErr = errors.NewErrPermissionDenied(fmt.Sprintf("Token subject \"%s\" not consistent with gateway ID \"%s\"", claims.Subject, gatewayID))
			} else {
				authErr = nil
				authenticated = true
			}
		}
	}

	if authErr != nil && !viper.GetBool("router.skip-verify-gateway-token") {
		return nil, authErr
	}

	gtw = r.router.getGateway(gatewayID)
	if authenticated {
		gtw.SetAuth(token, authenticated)
	}

	return gtw, nil
}

func (r *routerRPC) gatewayFromContext(ctx context.Context) (gtw *gateway.Gateway, err error) {
	md := ttnctx.MetadataFromIncomingContext(ctx)
{'fraction_non_alphanumeric': 0.1271036315323295, 'fraction_numerical': 0.003985828166519044, 'mean_word_length': 4.528763769889841, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4400743', 'n_tokens_mistral': 1670, 'n_tokens_neox': 1550, 'n_words': 316}