From de46393a7c72f6102516b7bc9e3fe25767f4a9e7 Mon Sep 17 00:00:00 2001 From: Pascal Fischer Date: Mon, 23 Oct 2023 18:31:40 +0200 Subject: [PATCH] updated --- client/internal/dns/host_ios.go | 25 +++- client/internal/dns/server.go | 2 +- client/internal/engine.go | 1 + client/ios/{netbird => NetBirdSDK}/client.go | 121 ++++++++++-------- .../ios/{netbird => NetBirdSDK}/gomobile.go | 2 +- client/ios/NetBirdSDK/logger.go | 16 +++ client/ios/{netbird => NetBirdSDK}/login.go | 48 +------ .../{netbird => NetBirdSDK}/peer_notifier.go | 26 +++- .../{netbird => NetBirdSDK}/preferences.go | 2 +- .../preferences_test.go | 2 +- client/ios/netbird/dns_list.go | 26 ---- client/ios/netbird/dns_list_test.go | 24 ---- client/ios/netbird/logger.go | 31 ----- client/system/info.go | 24 ++++ client/system/info_ios.go | 13 +- 15 files changed, 170 insertions(+), 193 deletions(-) rename client/ios/{netbird => NetBirdSDK}/client.go (57%) rename client/ios/{netbird => NetBirdSDK}/gomobile.go (87%) create mode 100644 client/ios/NetBirdSDK/logger.go rename client/ios/{netbird => NetBirdSDK}/login.go (81%) rename client/ios/{netbird => NetBirdSDK}/peer_notifier.go (53%) rename client/ios/{netbird => NetBirdSDK}/preferences.go (99%) rename client/ios/{netbird => NetBirdSDK}/preferences_test.go (99%) delete mode 100644 client/ios/netbird/dns_list.go delete mode 100644 client/ios/netbird/dns_list_test.go delete mode 100644 client/ios/netbird/logger.go diff --git a/client/internal/dns/host_ios.go b/client/internal/dns/host_ios.go index 3dd93fa07..fa143dc7a 100644 --- a/client/internal/dns/host_ios.go +++ b/client/internal/dns/host_ios.go @@ -1,5 +1,12 @@ package dns +import ( + "strconv" + "strings" + + log "github.com/sirupsen/logrus" +) + type iosHostManager struct { dnsManager IosDnsManager config HostDNSConfig @@ -12,7 +19,23 @@ func newHostManager(wgInterface WGIface, dnsManager IosDnsManager) (hostManager, } func (a iosHostManager) applyDNSConfig(config HostDNSConfig) error { - a.dnsManager.applyDns("bla") + var configAsString []string + configAsString = append(configAsString, config.serverIP) + configAsString = append(configAsString, strconv.Itoa(config.serverPort)) + configAsString = append(configAsString, strconv.FormatBool(config.routeAll)) + var domainConfigAsString []string + for _, domain := range config.domains { + var domainAsString []string + domainAsString = append(domainAsString, strconv.FormatBool(domain.disabled)) + domainAsString = append(domainAsString, domain.domain) + domainAsString = append(domainAsString, strconv.FormatBool(domain.matchOnly)) + domainConfigAsString = append(domainConfigAsString, strings.Join(domainAsString, "|")) + } + domainConfig := strings.Join(domainConfigAsString, ";") + configAsString = append(configAsString, domainConfig) + outputString := strings.Join(configAsString, ",") + log.Debug("applyDNSConfig: " + outputString) + a.dnsManager.ApplyDns(outputString) return nil } diff --git a/client/internal/dns/server.go b/client/internal/dns/server.go index 389d882ad..03ba6f717 100644 --- a/client/internal/dns/server.go +++ b/client/internal/dns/server.go @@ -21,7 +21,7 @@ type ReadyListener interface { // IosDnsManager is a dns manager interface for iosß type IosDnsManager interface { - applyDns(string) + ApplyDns(string) } // Server is a dns server interface diff --git a/client/internal/engine.go b/client/internal/engine.go index 585e9a5a5..9d041031e 100644 --- a/client/internal/engine.go +++ b/client/internal/engine.go @@ -217,6 +217,7 @@ func (e *Engine) Start() error { log.Debugf("Initial routes contain %d routes", len(routes)) e.routeManager = routemanager.NewManager(e.ctx, e.config.WgPrivateKey.PublicKey().String(), e.wgInterface, e.statusRecorder, routes) e.mobileDep.RouteListener.SetInterfaceIP(wgAddr) + e.routeManager.SetRouteChangeListener(e.mobileDep.RouteListener) switch runtime.GOOS { diff --git a/client/ios/netbird/client.go b/client/ios/NetBirdSDK/client.go similarity index 57% rename from client/ios/netbird/client.go rename to client/ios/NetBirdSDK/client.go index 73d565d46..5cea91b38 100644 --- a/client/ios/netbird/client.go +++ b/client/ios/NetBirdSDK/client.go @@ -1,12 +1,14 @@ -package netbird +package NetBirdSDK import ( "context" "sync" + "time" log "github.com/sirupsen/logrus" "github.com/netbirdio/netbird/client/internal" + "github.com/netbirdio/netbird/client/internal/auth" "github.com/netbirdio/netbird/client/internal/dns" "github.com/netbirdio/netbird/client/internal/peer" "github.com/netbirdio/netbird/client/internal/routemanager" @@ -14,11 +16,6 @@ import ( "github.com/netbirdio/netbird/formatter" ) -// ConnectionListener export internal Listener for mobile -type ConnectionListener interface { - peer.Listener -} - // RouteListener export internal RouteListener for mobile type RouteListener interface { routemanager.RouteListener @@ -47,16 +44,21 @@ type Client struct { ctxCancel context.CancelFunc ctxCancelLock *sync.Mutex deviceName string + osName string + osVersion string routeListener routemanager.RouteListener onHostDnsFn func([]string) dnsManager dns.IosDnsManager + loginComplete bool } // NewClient instantiate a new Client -func NewClient(cfgFile, deviceName string, routeListener RouteListener, dnsManager DnsManager) *Client { +func NewClient(cfgFile, deviceName string, osVersion string, osName string, routeListener RouteListener, dnsManager DnsManager) *Client { return &Client{ cfgFile: cfgFile, deviceName: deviceName, + osName: osName, + osVersion: osVersion, recorder: peer.NewRecorder(""), ctxCancelLock: &sync.Mutex{}, routeListener: routeListener, @@ -78,14 +80,15 @@ func (c *Client) Run(fd int32) error { var ctx context.Context //nolint ctxWithValues := context.WithValue(context.Background(), system.DeviceNameCtxKey, c.deviceName) + ctxWithValues = context.WithValue(ctxWithValues, system.OsNameCtxKey, c.osName) + ctxWithValues = context.WithValue(ctxWithValues, system.OsVersionCtxKey, c.osVersion) c.ctxCancelLock.Lock() ctx, c.ctxCancel = context.WithCancel(ctxWithValues) defer c.ctxCancel() c.ctxCancelLock.Unlock() auth := NewAuthWithConfig(ctx, cfg) - // err = auth.login(urlOpener) - auth.loginWithSetupKeyAndSaveConfig("C3803F45-435B-4333-96EB-50F9EC723355", "iPhone") + err = auth.Login() if err != nil { return err } @@ -97,32 +100,6 @@ func (c *Client) Run(fd int32) error { return internal.RunClientiOS(ctx, cfg, c.recorder, fd, c.routeListener, c.dnsManager) } -func (c *Client) Auth(urlOpener URLOpener) error { - cfg, err := internal.UpdateOrCreateConfig(internal.ConfigInput{ - ConfigPath: c.cfgFile, - }) - if err != nil { - return err - } - c.recorder.UpdateManagementAddress(cfg.ManagementURL.String()) - - var ctx context.Context - //nolint - ctxWithValues := context.WithValue(context.Background(), system.DeviceNameCtxKey, c.deviceName) - c.ctxCancelLock.Lock() - ctx, c.ctxCancel = context.WithCancel(ctxWithValues) - defer c.ctxCancel() - c.ctxCancelLock.Unlock() - - auth := NewAuthWithConfig(ctx, cfg) - err = auth.login(urlOpener) - if err != nil { - return err - } - - return nil -} - // Stop the internal client and free the resources func (c *Client) Stop() { c.ctxCancelLock.Lock() @@ -139,8 +116,8 @@ func (c *Client) SetTraceLogLevel() { log.SetLevel(log.TraceLevel) } -// PeersList return with the list of the PeerInfos -func (c *Client) PeersList() *PeerInfoArray { +// getStatusDetails return with the list of the PeerInfos +func (c *Client) GetStatusDetails() *StatusDetails { fullStatus := c.recorder.GetFullStatus() @@ -153,26 +130,70 @@ func (c *Client) PeersList() *PeerInfoArray { } peerInfos[n] = pi } - return &PeerInfoArray{items: peerInfos} + return &StatusDetails{items: peerInfos, fqdn: fullStatus.LocalPeerState.FQDN, ip: fullStatus.LocalPeerState.IP} } -// OnUpdatedHostDNS update the DNS servers addresses for root zones -func (c *Client) OnUpdatedHostDNS(list *DNSList) error { - dnsServer, err := dns.GetServerDns() +func (c *Client) GetManagementStatus() bool { + return c.recorder.GetFullStatus().ManagementState.Connected +} + +func (c *Client) IsLoginRequired() bool { + var ctx context.Context + ctxWithValues := context.WithValue(context.Background(), system.DeviceNameCtxKey, c.deviceName) + c.ctxCancelLock.Lock() + defer c.ctxCancelLock.Unlock() + ctx, c.ctxCancel = context.WithCancel(ctxWithValues) + + cfg, _ := internal.UpdateOrCreateConfig(internal.ConfigInput{ + ConfigPath: c.cfgFile, + }) + + needsLogin, _ := internal.IsLoginRequired(ctx, cfg.PrivateKey, cfg.ManagementURL, cfg.SSHKey) + return needsLogin +} + +func (c *Client) LoginForMobile() string { + var ctx context.Context + ctxWithValues := context.WithValue(context.Background(), system.DeviceNameCtxKey, c.deviceName) + c.ctxCancelLock.Lock() + defer c.ctxCancelLock.Unlock() + ctx, c.ctxCancel = context.WithCancel(ctxWithValues) + + cfg, _ := internal.UpdateOrCreateConfig(internal.ConfigInput{ + ConfigPath: c.cfgFile, + }) + + oAuthFlow, err := auth.NewOAuthFlow(ctx, cfg, false) if err != nil { - return err + return err.Error() } - dnsServer.OnUpdatedHostDNSServer(list.items) - return nil + flowInfo, err := oAuthFlow.RequestAuthInfo(context.TODO()) + if err != nil { + return err.Error() + } + + // This could cause a potential race condition with loading the extension which need to be handled on swift side + go func() { + waitTimeout := time.Duration(flowInfo.ExpiresIn) + waitCTX, cancel := context.WithTimeout(ctx, waitTimeout*time.Second) + defer cancel() + tokenInfo, err := oAuthFlow.WaitToken(waitCTX, flowInfo) + if err != nil { + return + } + jwtToken := tokenInfo.GetTokenToUse() + _ = internal.Login(ctx, cfg, "", jwtToken) + c.loginComplete = true + }() + + return flowInfo.VerificationURIComplete } -// SetConnectionListener set the network connection listener -func (c *Client) SetConnectionListener(listener ConnectionListener) { - c.recorder.SetConnectionListener(listener) +func (c *Client) IsLoginComplete() bool { + return c.loginComplete } -// RemoveConnectionListener remove connection listener -func (c *Client) RemoveConnectionListener() { - c.recorder.RemoveConnectionListener() +func (c *Client) ClearLoginComplete() { + c.loginComplete = false } diff --git a/client/ios/netbird/gomobile.go b/client/ios/NetBirdSDK/gomobile.go similarity index 87% rename from client/ios/netbird/gomobile.go rename to client/ios/NetBirdSDK/gomobile.go index 76b4f7e35..9eadd6a7f 100644 --- a/client/ios/netbird/gomobile.go +++ b/client/ios/NetBirdSDK/gomobile.go @@ -1,4 +1,4 @@ -package netbird +package NetBirdSDK import _ "golang.org/x/mobile/bind" diff --git a/client/ios/NetBirdSDK/logger.go b/client/ios/NetBirdSDK/logger.go new file mode 100644 index 000000000..674e296fb --- /dev/null +++ b/client/ios/NetBirdSDK/logger.go @@ -0,0 +1,16 @@ +package NetBirdSDK + +import ( + "os" + + "github.com/netbirdio/netbird/util" +) + +var logFile *os.File + +// InitializeLog initializes the log file. +func InitializeLog(logLevel string, filePath string) error { + var err error + err = util.InitLog(logLevel, filePath) + return err +} diff --git a/client/ios/netbird/login.go b/client/ios/NetBirdSDK/login.go similarity index 81% rename from client/ios/netbird/login.go rename to client/ios/NetBirdSDK/login.go index 3aaa24af2..50a042538 100644 --- a/client/ios/netbird/login.go +++ b/client/ios/NetBirdSDK/login.go @@ -1,4 +1,4 @@ -package netbird +package NetBirdSDK import ( "context" @@ -70,18 +70,7 @@ func NewAuthWithConfig(ctx context.Context, config *internal.Config) *Auth { // SaveConfigIfSSOSupported test the connectivity with the management server by retrieving the server device flow info. // If it returns a flow info than save the configuration and return true. If it gets a codes.NotFound, it means that SSO // is not supported and returns false without saving the configuration. For other errors return false. -func (a *Auth) SaveConfigIfSSOSupported(listener SSOListener) { - go func() { - sso, err := a.saveConfigIfSSOSupported() - if err != nil { - listener.OnError(err) - } else { - listener.OnSuccess(sso) - } - }() -} - -func (a *Auth) saveConfigIfSSOSupported() (bool, error) { +func (a *Auth) SaveConfigIfSSOSupported() (bool, error) { supportsSSO := true err := a.withBackOff(a.ctx, func() (err error) { _, err = internal.GetDeviceAuthorizationFlowInfo(a.ctx, a.config.PrivateKey, a.config.ManagementURL) @@ -111,18 +100,7 @@ func (a *Auth) saveConfigIfSSOSupported() (bool, error) { } // LoginWithSetupKeyAndSaveConfig test the connectivity with the management server with the setup key. -func (a *Auth) LoginWithSetupKeyAndSaveConfig(resultListener ErrListener, setupKey string, deviceName string) { - go func() { - err := a.loginWithSetupKeyAndSaveConfig(setupKey, deviceName) - if err != nil { - resultListener.OnError(err) - } else { - resultListener.OnSuccess() - } - }() -} - -func (a *Auth) loginWithSetupKeyAndSaveConfig(setupKey string, deviceName string) error { +func (a *Auth) LoginWithSetupKeyAndSaveConfig(setupKey string, deviceName string) error { //nolint ctxWithValues := context.WithValue(a.ctx, system.DeviceNameCtxKey, deviceName) @@ -141,19 +119,7 @@ func (a *Auth) loginWithSetupKeyAndSaveConfig(setupKey string, deviceName string return internal.WriteOutConfig(a.cfgPath, a.config) } -// Login try register the client on the server -func (a *Auth) Login(resultListener ErrListener, urlOpener URLOpener) { - go func() { - err := a.login(urlOpener) - if err != nil { - resultListener.OnError(err) - } else { - resultListener.OnSuccess() - } - }() -} - -func (a *Auth) login(urlOpener URLOpener) error { +func (a *Auth) Login() error { var needsLogin bool // check if we need to generate JWT token @@ -167,11 +133,7 @@ func (a *Auth) login(urlOpener URLOpener) error { jwtToken := "" if needsLogin { - tokenInfo, err := a.foregroundGetTokenInfo(urlOpener) - if err != nil { - return fmt.Errorf("interactive sso login failed: %v", err) - } - jwtToken = tokenInfo.GetTokenToUse() + return fmt.Errorf("Not authenticated") } err = a.withBackOff(a.ctx, func() error { diff --git a/client/ios/netbird/peer_notifier.go b/client/ios/NetBirdSDK/peer_notifier.go similarity index 53% rename from client/ios/netbird/peer_notifier.go rename to client/ios/NetBirdSDK/peer_notifier.go index a23af2a29..e52008d9f 100644 --- a/client/ios/netbird/peer_notifier.go +++ b/client/ios/NetBirdSDK/peer_notifier.go @@ -1,4 +1,4 @@ -package netbird +package NetBirdSDK // PeerInfo describe information about the peers. It designed for the UI usage type PeerInfo struct { @@ -12,25 +12,39 @@ type PeerInfoCollection interface { Add(s string) PeerInfoCollection Get(i int) string Size() int + GetFQDN() string + GetIP() string } -// PeerInfoArray is the implementation of the PeerInfoCollection -type PeerInfoArray struct { +// StatusDetails is the implementation of the PeerInfoCollection +type StatusDetails struct { items []PeerInfo + fqdn string + ip string } // Add new PeerInfo to the collection -func (array PeerInfoArray) Add(s PeerInfo) PeerInfoArray { +func (array StatusDetails) Add(s PeerInfo) StatusDetails { array.items = append(array.items, s) return array } // Get return an element of the collection -func (array PeerInfoArray) Get(i int) *PeerInfo { +func (array StatusDetails) Get(i int) *PeerInfo { return &array.items[i] } // Size return with the size of the collection -func (array PeerInfoArray) Size() int { +func (array StatusDetails) Size() int { return len(array.items) } + +// GetFQDN return with the FQDN of the local peer +func (array StatusDetails) GetFQDN() string { + return array.fqdn +} + +// GetIP return with the IP of the local peer +func (array StatusDetails) GetIP() string { + return array.ip +} diff --git a/client/ios/netbird/preferences.go b/client/ios/NetBirdSDK/preferences.go similarity index 99% rename from client/ios/netbird/preferences.go rename to client/ios/NetBirdSDK/preferences.go index d565029e7..297d53ff0 100644 --- a/client/ios/netbird/preferences.go +++ b/client/ios/NetBirdSDK/preferences.go @@ -1,4 +1,4 @@ -package netbird +package NetBirdSDK import ( "github.com/netbirdio/netbird/client/internal" diff --git a/client/ios/netbird/preferences_test.go b/client/ios/NetBirdSDK/preferences_test.go similarity index 99% rename from client/ios/netbird/preferences_test.go rename to client/ios/NetBirdSDK/preferences_test.go index ee7e1c029..bb4531b61 100644 --- a/client/ios/netbird/preferences_test.go +++ b/client/ios/NetBirdSDK/preferences_test.go @@ -1,4 +1,4 @@ -package netbird +package NetBirdSDK import ( "path/filepath" diff --git a/client/ios/netbird/dns_list.go b/client/ios/netbird/dns_list.go deleted file mode 100644 index 49e3b2f71..000000000 --- a/client/ios/netbird/dns_list.go +++ /dev/null @@ -1,26 +0,0 @@ -package netbird - -import "fmt" - -// DNSList is a wrapper of []string -type DNSList struct { - items []string -} - -// Add new DNS address to the collection -func (array *DNSList) Add(s string) { - array.items = append(array.items, s) -} - -// Get return an element of the collection -func (array *DNSList) Get(i int) (string, error) { - if i >= len(array.items) || i < 0 { - return "", fmt.Errorf("out of range") - } - return array.items[i], nil -} - -// Size return with the size of the collection -func (array *DNSList) Size() int { - return len(array.items) -} diff --git a/client/ios/netbird/dns_list_test.go b/client/ios/netbird/dns_list_test.go deleted file mode 100644 index d88373dd8..000000000 --- a/client/ios/netbird/dns_list_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package netbird - -import "testing" - -func TestDNSList_Get(t *testing.T) { - l := DNSList{ - items: make([]string, 1), - } - - _, err := l.Get(0) - if err != nil { - t.Errorf("invalid error: %s", err) - } - - _, err = l.Get(-1) - if err == nil { - t.Errorf("expected error but got nil") - } - - _, err = l.Get(1) - if err == nil { - t.Errorf("expected error but got nil") - } -} diff --git a/client/ios/netbird/logger.go b/client/ios/netbird/logger.go deleted file mode 100644 index 96b75d7d3..000000000 --- a/client/ios/netbird/logger.go +++ /dev/null @@ -1,31 +0,0 @@ -package netbird - -import ( - "os" - - "github.com/netbirdio/netbird/util" -) - -var logFile *os.File - -// InitializeLog initializes the log file. -func InitializeLog(logLevel string, filePath string) error { - var err error - err = util.InitLog(logLevel, filePath) - return err -} - -// // CloseLog closes the log file. -// func CloseLog() { -// if logFile != nil { -// logFile.Close() -// } -// } -// -// // Log writes a message to the log file. -// func Log(message string) { -// if logFile != nil { -// ts := time.Now().Format(time.RFC3339) -// fmt.Fprintf(logFile, "%s: %s\n", ts, message) -// } -// } diff --git a/client/system/info.go b/client/system/info.go index a495ed1e9..b6254ef47 100644 --- a/client/system/info.go +++ b/client/system/info.go @@ -12,6 +12,12 @@ import ( // DeviceNameCtxKey context key for device name const DeviceNameCtxKey = "deviceName" +// OsVersionCtxKey context key for operating system version +const OsVersionCtxKey = "OsVersion" + +// OsNameCtxKey context key for operating system name +const OsNameCtxKey = "OsName" + // Info is an object that contains machine information // Most of the code is taken from https://github.com/matishsiao/goInfo type Info struct { @@ -52,6 +58,24 @@ func extractDeviceName(ctx context.Context, defaultName string) string { return v } +// extractOsVersion extracts operating system version from context or returns the default +func extractOsVersion(ctx context.Context, defaultName string) string { + v, ok := ctx.Value(OsVersionCtxKey).(string) + if !ok { + return defaultName + } + return v +} + +// extractOsName extracts operating system name from context or returns the default +func extractOsName(ctx context.Context, defaultName string) string { + v, ok := ctx.Value(OsNameCtxKey).(string) + if !ok { + return defaultName + } + return v +} + // GetDesktopUIUserAgent returns the Desktop ui user agent func GetDesktopUIUserAgent() string { return "netbird-desktop-ui/" + version.NetbirdVersion() diff --git a/client/system/info_ios.go b/client/system/info_ios.go index 967c69a83..762117afa 100644 --- a/client/system/info_ios.go +++ b/client/system/info_ios.go @@ -5,7 +5,6 @@ package system import ( "context" - "os" "runtime" "github.com/netbirdio/netbird/version" @@ -15,14 +14,12 @@ import ( func GetInfo(ctx context.Context) *Info { // Convert fixed-size byte arrays to Go strings - sysName := "iOS" - machine := "machine" - release := "release" - swversion := "swversion" + sysName := extractOsName(ctx, "sysName") + swVersion := extractOsVersion(ctx, "swVersion") - gio := &Info{Kernel: sysName, OSVersion: swversion, Core: release, Platform: machine, OS: sysName, GoOS: runtime.GOOS, CPUs: runtime.NumCPU()} - systemHostname, _ := os.Hostname() - gio.Hostname = extractDeviceName(ctx, systemHostname) + gio := &Info{Kernel: sysName, OSVersion: swVersion, Core: swVersion, Platform: "unknown", OS: sysName, GoOS: runtime.GOOS, CPUs: runtime.NumCPU()} + // systemHostname, _ := os.Hostname() + gio.Hostname = extractDeviceName(ctx, "hostname") gio.WiretrusteeVersion = version.NetbirdVersion() gio.UIVersion = extractUserAgent(ctx)