Skip to content

Commit

Permalink
Search for the shared secret of the switch
Browse files Browse the repository at this point in the history
  • Loading branch information
fdurand committed Mar 7, 2025
1 parent f5b5e95 commit 7d80a9b
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 48 deletions.
2 changes: 2 additions & 0 deletions go/chisel/server/server_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ func (s *Server) handleWebsocket(w http.ResponseWriter, req *http.Request) {

localSecret := pfconfigdriver.LocalSecret{}
pfconfigdriver.FetchDecodeSocket(req.Context(), &localSecret)

//
//successfuly validated config!
r.Reply(true, nil)
//tunnel per ssh connection
Expand Down
31 changes: 15 additions & 16 deletions go/chisel/server/server_listen.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"crypto/x509"
"errors"
"fmt"
"io/ioutil"
"net"
"os"
"os/user"
Expand All @@ -15,7 +14,7 @@ import (
"golang.org/x/crypto/acme/autocert"
)

//TLSConfig enables configures TLS
// TLSConfig enables configures TLS
type TLSConfig struct {
Key string
Cert string
Expand Down Expand Up @@ -44,12 +43,12 @@ func (s *Server) listener(host, port string) (net.Listener, error) {
extra = " (WARNING: LetsEncrypt will attempt to connect to your domain on port 443)"
}
}
//tcp listen
// tcp listen
l, err := net.Listen("tcp", host+":"+port)
if err != nil {
return nil, err
}
//optionally wrap in tls
// optionally wrap in tls
proto := "http"
if tlsConf != nil {
proto += "s"
Expand All @@ -64,7 +63,7 @@ func (s *Server) listener(host, port string) (net.Listener, error) {
}

func (s *Server) tlsLetsEncrypt(domains []string) *tls.Config {
//prepare cert manager
// prepare cert manager
m := &autocert.Manager{
Prompt: func(tosURL string) bool {
s.Infof("Accepting LetsEncrypt TOS and fetching certificate...")
Expand All @@ -73,7 +72,7 @@ func (s *Server) tlsLetsEncrypt(domains []string) *tls.Config {
Email: settings.Env("LE_EMAIL"),
HostPolicy: autocert.HostWhitelist(domains...),
}
//configure file cache
// configure file cache
c := settings.Env("LE_CACHE")
if c == "" {
h := os.Getenv("HOME")
Expand All @@ -88,7 +87,7 @@ func (s *Server) tlsLetsEncrypt(domains []string) *tls.Config {
s.Infof("LetsEncrypt cache directory %s", c)
m.Cache = autocert.DirCache(c)
}
//return lets-encrypt tls config
// return lets-encrypt tls config
return m.TLSConfig()
}

Expand All @@ -97,11 +96,11 @@ func (s *Server) tlsKeyCert(key, cert string, ca string) (*tls.Config, error) {
if err != nil {
return nil, err
}
//file based tls config using tls defaults
// file based tls config using tls defaults
c := &tls.Config{
Certificates: []tls.Certificate{keypair},
}
//mTLS requires server's CA
// mTLS requires server's CA
if ca != "" {
if err := addCA(ca, c); err != nil {
return nil, err
Expand All @@ -118,37 +117,37 @@ func addCA(ca string, c *tls.Config) error {
}
clientCAPool := x509.NewCertPool()
if fileInfo.IsDir() {
//this is a directory holding CA bundle files
files, err := ioutil.ReadDir(ca)
// this is a directory holding CA bundle files
files, err := os.ReadDir(ca)
if err != nil {
return err
}
//add all cert files from path
// add all cert files from path
for _, file := range files {
f := file.Name()
if err := addPEMFile(filepath.Join(ca, f), clientCAPool); err != nil {
return err
}
}
} else {
//this is a CA bundle file
// this is a CA bundle file
if err := addPEMFile(ca, clientCAPool); err != nil {
return err
}
}
//set client CAs and enable cert verification
// set client CAs and enable cert verification
c.ClientCAs = clientCAPool
c.ClientAuth = tls.RequireAndVerifyClientCert
return nil
}

func addPEMFile(path string, pool *x509.CertPool) error {
content, err := ioutil.ReadFile(path)
content, err := os.ReadFile(path)
if err != nil {
return err
}
if !pool.AppendCertsFromPEM(content) {
return errors.New("Fail to load certificates from : " + path)
return fmt.Errorf("fail to load certificates from : %s", path)
}
return nil
}
78 changes: 74 additions & 4 deletions go/chisel/share/radius_proxy/proxy.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package radius_proxy

import (
"context"
"crypto/hmac"
"crypto/md5"
"errors"
"net"
"strings"
"time"

"github.com/google/uuid"
"github.com/inverse-inc/packetfence/go/chisel/share/cio"
"github.com/inverse-inc/packetfence/go/pfconfigdriver"
"layeh.com/radius"
"layeh.com/radius/rfc2865"
"layeh.com/radius/rfc2869"
Expand Down Expand Up @@ -95,10 +99,17 @@ func (rp *Proxy) ProxyPacket(payload []byte, connectorID string) ([]byte, string
}

packet.Attributes.Add(26, vsa)
// err = addMessageAuthenticator(packet, []byte(rp.secret))
// if err != nil {
// return nil, "", err
// }

secret, err := rp.foundSecret(context.Background(), packet)

if err != nil {
secret = string(rp.secret)
}

err = addMessageAuthenticator(packet, []byte(secret))
if err != nil {
return nil, "", err
}

b2, err := packet.Encode()
if err != nil {
Expand Down Expand Up @@ -131,3 +142,62 @@ func addMessageAuthenticator(p *radius.Packet, secret []byte) error {
rfc2869.MessageAuthenticator_Set(p, hash.Sum(nil))
return nil
}

func (rp *Proxy) foundSecret(ctx context.Context, packet *radius.Packet) (string, error) {

var SwitchID []string
SwitchMAC := rfc2865.CallingStationID_GetString(packet)
if SwitchMAC != "" {
MacHW, err := net.ParseMAC(SwitchMAC)
if err == nil {
SwitchMAC = MacHW.String()
SwitchID = append(SwitchID, SwitchMAC)
}
}

SwitchNasIP := rfc2865.NASIPAddress_Get(packet)
if SwitchNasIP != nil {
SwitchID = append(SwitchID, SwitchNasIP.String())
}

switches := pfconfigdriver.PfSwitches{}
pfconfigdriver.FetchDecodeSocket(ctx, &switches)

for _, switchID := range SwitchID {

// Find the switch with the given ID
for _, sw := range switches.PfconfigKeys.Keys {
if sw != switchID {
continue
}
switche := pfconfigdriver.PfConfSwitch{}
switche.PfconfigHashNS = sw
pfconfigdriver.FetchDecodeSocket(ctx, &switche)
if switche.RadiusSecret.String() != "" {
return switche.RadiusSecret.String(), nil
}
}
// Find the switch within the ip ranges
if IsIPv4(net.ParseIP(switchID)) {
for _, sw := range switches.PfconfigKeys.Keys {
_, network, err := net.ParseCIDR(sw)
if err != nil {
continue
}
if network.Contains(net.ParseIP(switchID)) {
switche := pfconfigdriver.PfConfSwitch{}
switche.PfconfigHashNS = sw
pfconfigdriver.FetchDecodeSocket(ctx, &switche)
if switche.RadiusSecret.String() != "" {
return switche.RadiusSecret.String(), nil
}
}
}
}
}
return "", errors.New("No secret found")
}

func IsIPv4(address net.IP) bool {
return strings.Count(address.String(), ":") < 2
}
151 changes: 123 additions & 28 deletions go/pfconfigdriver/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -579,34 +579,34 @@ type ClusterSummary struct {

type PfConfAdvanced struct {
StructConfig
PfconfigMethod string `val:"hash_element"`
PfconfigNS string `val:"config::Pf"`
PfconfigHashNS string `val:"advanced"`
HashingCost string `json:"hashing_cost"`
ScanOnAccounting string `json:"scan_on_accounting"`
PffilterProcesses string `json:"pffilter_processes"`
UpdateIplogWithAccounting string `json:"update_iplog_with_accounting"`
UpdateIplogWithAuthentication string `json:"update_iplog_with_authentication"`
AdminCspSecurityHeaders string `json:"admin_csp_security_headers"`
Multihost string `json:"multihost"`
SsoOnAccessReevaluation string `json:"sso_on_access_reevaluation"`
DisablePfDomainAuth string `json:"disable_pf_domain_auth"`
TimingStatsLevel string `json:"timing_stats_level"`
SsoOnDhcp string `json:"sso_on_dhcp"`
Language string `json:"language"`
StatsdListenPort string `json:"statsd_listen_port"`
SsoOnAccounting string `json:"sso_on_accounting"`
LocationlogCloseOnAccountingStop string `json:"locationlog_close_on_accounting_stop"`
PortalCspSecurityHeaders string `json:"portal_csp_security_headers"`
HashPasswords string `json:"hash_passwords"`
SourceToSendSmsWhenCreatingUsers string `json:"source_to_send_sms_when_creating_users"`
ActiveDirectoryOsJoinCheckBypass string `json:"active_directory_os_join_check_bypass"`
PfperlApiTimeout string `json:"pfperl_api_timeout"`
LdapAttributes []string `json:"ldap_attributes"`
ApiInactivityTimeout int `json:"api_inactivity_timeout"`
ApiMaxExpiration int `json:"api_max_expiration"`
NetFlowOnAllNetworks string `json:"netflow_on_all_networks"`
AccountingTimebucketSize int `json:"accounting_timebucket_size"`
PfconfigMethod string `val:"hash_element"`
PfconfigNS string `val:"config::Pf"`
PfconfigHashNS string `val:"advanced"`
HashingCost string `json:"hashing_cost"`
ScanOnAccounting string `json:"scan_on_accounting"`
PffilterProcesses string `json:"pffilter_processes"`
UpdateIplogWithAccounting string `json:"update_iplog_with_accounting"`
UpdateIplogWithAuthentication string `json:"update_iplog_with_authentication"`
AdminCspSecurityHeaders string `json:"admin_csp_security_headers"`
Multihost string `json:"multihost"`
SsoOnAccessReevaluation string `json:"sso_on_access_reevaluation"`
DisablePfDomainAuth string `json:"disable_pf_domain_auth"`
TimingStatsLevel string `json:"timing_stats_level"`
SsoOnDhcp string `json:"sso_on_dhcp"`
Language string `json:"language"`
StatsdListenPort string `json:"statsd_listen_port"`
SsoOnAccounting string `json:"sso_on_accounting"`
LocationlogCloseOnAccountingStop string `json:"locationlog_close_on_accounting_stop"`
PortalCspSecurityHeaders string `json:"portal_csp_security_headers"`
HashPasswords string `json:"hash_passwords"`
SourceToSendSmsWhenCreatingUsers string `json:"source_to_send_sms_when_creating_users"`
ActiveDirectoryOsJoinCheckBypass string `json:"active_directory_os_join_check_bypass"`
PfperlApiTimeout string `json:"pfperl_api_timeout"`
LdapAttributes []string `json:"ldap_attributes"`
ApiInactivityTimeout int `json:"api_inactivity_timeout"`
ApiMaxExpiration int `json:"api_max_expiration"`
NetFlowOnAllNetworks string `json:"netflow_on_all_networks"`
AccountingTimebucketSize int `json:"accounting_timebucket_size"`
}

type PfConfDns struct {
Expand Down Expand Up @@ -967,3 +967,98 @@ type FingerbankSettings struct {
}

var FingerbankConf = FingerbankSettings{}

type PfConfSwitch struct {
StructConfig
PfconfigMethod string `val:"hash_element"`
PfconfigNS string `val:"config::Switch"`
PfconfigHashNS string `val:"-"` // Will be the switch IP

// Basic Information
Type string `json:"type"`
Description string `json:"description"`
Group string `json:"group"`

// VLANs
Vlans map[string]string `json:"vlans"`
VlanMap string `json:"VlanMap"`

// Interfaces
Interfaces map[string]interface{} `json:"interfaces"`

//Roles
Roles map[string]string `json:"roles"`
RoleMap string `json:"RoleMap"`

// Network Related
Networks map[string]interface{} `json:"networks"`
NetworksFrom map[string]interface{} `json:"networks_from"`

// Access Control
AccessLists map[string]interface{} `json:"access_lists"`
AccessListMap string `json:"AccessListMap"`
ACLsLimit string `json:"ACLsLimit"`
DownloadableACLsLimit string `json:"DownloadableACLsLimit"`
UsePushACLs string `json:"UsePushACLs"`
UseDownloadableACLs string `json:"UseDownloadableACLs"`
PushACLs string `json:"pushACLs"`

// WebAuth
UrlMap string `json:"UrlMap"`
Urls map[string]interface{} `json:"urls"`
ExternalPortalEnforcement string `json:"ExternalPortalEnforcement"`

// VPN
Vpn map[string]interface{} `json:"vpn"`
VpnMap string `json:"VpnMap"`

// MFA
PostMfaValidation string `json:"PostMfaValidation"`

// SNMP
SNMPUseConnector string `json:"SNMPUseConnector"`
SNMPVersion string `json:"SNMPVersion"`
SNMPVersionTrap string `json:"SNMPVersionTrap"`
SNMPCommunityRead string `json:"SNMPCommunityRead"`
SNMPCommunityWrite string `json:"SNMPCommunityWrite"`
SNMPCommunityTrap string `json:"SNMPCommunityTrap"`

// CLI
CliAccess string `json:"cliAccess"`
CliUser string `json:"cliUser"`
CliPwd pfcrypt.CryptString `json:"cliPwd"`
CliEnablePwd pfcrypt.CryptString `json:"cliEnablePwd"`
CliTransport string `json:"cliTransport"`

// Web Services
WsTransport string `json:"wsTransport"`
WsUser string `json:"wsUser"`
WsPwd pfcrypt.CryptString `json:"wsPwd"`

// VoIP Detection
VoIPEnabled int `json:"VoIPEnabled"`
VoIPCDPDetect string `json:"VoIPCDPDetect"`
VoIPDHCPDetect string `json:"VoIPDHCPDetect"`
VoIPLLDPDetect string `json:"VoIPLLDPDetect"`

// RADIUS
UseCoA string `json:"useCoA"`
RadiusSecret pfcrypt.CryptString `json:"radiusSecret"`
RadiusDeauthUseConnector string `json:"radiusDeauthUseConnector"`

//Advanced
InlineTrigger []interface{} `json:"inlineTrigger"`
Mode string `json:"mode"`
MacSearchesMaxNb string `json:"macSearchesMaxNb"`
MacSearchesSleepInterval string `json:"macSearchesSleepInterval"`
DeauthOnPrevious string `json:"deauthOnPrevious"`
Uplink []string `json:"uplink"`
}

// PfSwitch struct that will help when fetching multiple switch config from config::Switch
type PfSwitches struct {
PfconfigKeys
PfconfigMethod string `val:"keys"`
PfconfigNS string `val:"config::Switch"`
Keys []string
}

0 comments on commit 7d80a9b

Please sign in to comment.