github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/services/openvpn/service/auth_handler.go (about)

     1  /*
     2   * Copyright (C) 2018 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package service
    19  
    20  import (
    21  	"github.com/mysteriumnetwork/go-openvpn/openvpn/middlewares/server"
    22  	"github.com/mysteriumnetwork/go-openvpn/openvpn/middlewares/server/credentials"
    23  	"github.com/mysteriumnetwork/node/identity"
    24  	"github.com/mysteriumnetwork/node/services/openvpn"
    25  	"github.com/mysteriumnetwork/node/session"
    26  	"github.com/rs/zerolog/log"
    27  )
    28  
    29  // authHandler authorizes incoming clients by registering a callback to check auth primitives.
    30  // username - provider's sessionId
    31  // password - consumer's identity signature
    32  type authHandler struct {
    33  	*credentials.Middleware
    34  
    35  	clientMap         *clientMap
    36  	identityExtractor identity.Extractor
    37  }
    38  
    39  // newAuthHandler return authHandler instance
    40  func newAuthHandler(clientMap *clientMap, extractor identity.Extractor) *authHandler {
    41  	ah := new(authHandler)
    42  	ah.Middleware = credentials.NewMiddleware(ah.validate)
    43  	ah.Middleware.ClientsSubscribe(ah.handleClientEvent)
    44  	ah.clientMap = clientMap
    45  	ah.identityExtractor = extractor
    46  	return ah
    47  }
    48  
    49  func (ah *authHandler) handleClientEvent(event server.ClientEvent) {
    50  	switch event.EventType {
    51  	case server.Connect:
    52  		ah.clientMap.Add(event.ClientID, session.ID(event.Env["username"]))
    53  	case server.Disconnect:
    54  		ah.clientMap.Remove(event.ClientID)
    55  	}
    56  }
    57  
    58  // handleAuthorisation provides glue code for openvpn management interface to validate incoming client login request,
    59  // it expects session id as username, and session signature signed by client as password
    60  func (ah *authHandler) validate(_ int, username, password string) (bool, error) {
    61  	sessionID := session.ID(username)
    62  	currentSession, currentSessionFound := ah.clientMap.GetSession(sessionID)
    63  	if !currentSessionFound {
    64  		log.Warn().Msgf("Possible break-in attempt. No established session exists: %s", sessionID)
    65  		return false, nil
    66  	}
    67  
    68  	signature := identity.SignatureBase64(password)
    69  	signerID, err := ah.identityExtractor.Extract([]byte(openvpn.AuthSignaturePrefix+username), signature)
    70  	if err != nil {
    71  		log.Warn().Err(err).Msgf("Possible break-in attempt. Invalid session %s signature", sessionID)
    72  		return false, nil
    73  	}
    74  	if signerID != currentSession.ConsumerID {
    75  		log.Warn().Msgf("Possible break-in attempt. Invalid session %s consumer %s", sessionID, signerID)
    76  		return false, nil
    77  	}
    78  
    79  	return true, nil
    80  }