diff --git a/controllers/ext_client.go b/controllers/ext_client.go index e963a644a..e82648042 100644 --- a/controllers/ext_client.go +++ b/controllers/ext_client.go @@ -92,18 +92,23 @@ func getNetworkExtClients(w http.ResponseWriter, r *http.Request) { } err := user.Get(r.Context()) if err == nil { - userRole := &schema.UserRole{ - ID: user.PlatformRoleID, - } - err := userRole.Get(r.Context()) - if err != nil || !userRole.FullAccess { - filtered := []models.ExtClient{} - for _, ec := range extclients { - if logic.IsUserAllowedAccessToExtClient(username, ec) { - filtered = append(filtered, ec) + if user.PlatformRoleID != schema.Auditor { + userRole := &schema.UserRole{ + ID: user.PlatformRoleID, + } + err := userRole.Get(r.Context()) + if err != nil || !userRole.FullAccess { + if (user.PlatformRoleID == schema.PlatformUser && !logic.IsNetworkAdmin(user, network)) || + user.PlatformRoleID != schema.PlatformUser { + var filtered []models.ExtClient + for _, ec := range extclients { + if logic.IsUserAllowedAccessToExtClient(username, ec) { + filtered = append(filtered, ec) + } + } + extclients = filtered } } - extclients = filtered } } } @@ -212,6 +217,24 @@ func getExtClientConf(w http.ResponseWriter, r *http.Request) { return } + username := r.Header.Get("user") + if r.Header.Get("ismaster") != "yes" { + user := &schema.User{ + Username: username, + } + err := user.Get(r.Context()) + if err == nil { + if user.PlatformRoleID != schema.SuperAdminRole && + user.PlatformRoleID != schema.AdminRole && + !(user.PlatformRoleID == schema.PlatformUser && logic.IsNetworkAdmin(user, networkid)) && + user.Username != client.OwnerID { + err = fmt.Errorf("access denied") + logic.ReturnErrorResponse(w, r, logic.FormatError(err, logic.Forbidden)) + return + } + } + } + gwnode, err := logic.GetNodeByID(client.IngressGatewayID) if err != nil { logger.Log( @@ -389,10 +412,17 @@ Endpoint = %s ) if params["type"] == "qr" { - bytes, err := qrcode.Encode(config, qrcode.Medium, -5) + bytes, err := qrcode.Encode(config, qrcode.Low, -5) if err != nil { logger.Log(1, r.Header.Get("user"), "failed to encode qr code: ", err.Error()) - logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) + if strings.Contains(err.Error(), "content too long to encode") { + logic.ReturnErrorResponse(w, r, logic.FormatError( + fmt.Errorf("config is too large to encode as a QR code; please use the file download instead"), + "badrequest", + )) + } else { + logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal")) + } return } w.Header().Set("Content-Type", "image/png") diff --git a/logic/settings.go b/logic/settings.go index 9b00ff5aa..262eaa8d1 100644 --- a/logic/settings.go +++ b/logic/settings.go @@ -345,6 +345,10 @@ func GetSmtpPort() int { return GetServerSettings().SmtpPort } +func SmtpSkipTlsVerify() bool { + return GetServerSettings().SmtpSkipTlsVerify +} + func GetSenderEmail() string { return GetServerSettings().EmailSenderAddr } diff --git a/logic/user_mgmt.go b/logic/user_mgmt.go index 1288332ea..7d4a5e6e1 100644 --- a/logic/user_mgmt.go +++ b/logic/user_mgmt.go @@ -87,6 +87,7 @@ var AddGlobalGroupOnRoleUpgrade = func(oldRole, newRole schema.UserRoleID, group var PlatformRoleRequiresGroupEnforcement = func(role schema.UserRoleID) bool { return false } var UserHasGlobalNetworksAdminMembership = func(user *schema.User) bool { return false } var UserHasNetworkGroupAccess = func(user *schema.User, networkID string) bool { return false } +var IsNetworkAdmin = func(user *schema.User, networkID string) bool { return false } var CanUserCreateNetwork = func(ctx context.Context, username string) bool { return true } var EmailInit = func() {} diff --git a/migrate/migrate.go b/migrate/migrate.go index fec52c70c..0e0ec83a0 100644 --- a/migrate/migrate.go +++ b/migrate/migrate.go @@ -564,6 +564,13 @@ func migrateSettings() { if settings.StunServers == "" { settings.StunServers = servercfg.GetStunServers() } + if settings.SmtpHost != "" { + _, ok := settingsD["smtp_skip_tls_verify"] + if !ok { + // skip tls verification for older deployments when tls verification wasn't configurable. + settings.SmtpSkipTlsVerify = true + } + } logic.UpsertServerSettings(settings) } diff --git a/models/settings.go b/models/settings.go index 8cb52d6d7..d35ebb0d9 100644 --- a/models/settings.go +++ b/models/settings.go @@ -41,6 +41,7 @@ type ServerSettings struct { EmailSenderPassword string `json:"email_sender_password"` SmtpHost string `json:"smtp_host"` SmtpPort int `json:"smtp_port"` + SmtpSkipTlsVerify bool `json:"smtp_skip_tls_verify"` MetricInterval string `json:"metric_interval"` MetricsPort int `json:"metrics_port"` // IPDetectionInterval is the interval (in seconds) at which devices check for changes in public ip. diff --git a/pro/email/email.go b/pro/email/email.go index 12870c6ad..f3dc24ecf 100644 --- a/pro/email/email.go +++ b/pro/email/email.go @@ -24,6 +24,7 @@ func Init() { SenderEmail: logic.GetSenderEmail(), SendUser: logic.GetSenderUser(), SenderPass: logic.GetEmaiSenderPassword(), + SkipVerify: logic.SmtpSkipTlsVerify(), } if smtpSender.SendUser == "" { smtpSender.SendUser = smtpSender.SenderEmail diff --git a/pro/email/smtp.go b/pro/email/smtp.go index 4c96e5b09..209af22da 100644 --- a/pro/email/smtp.go +++ b/pro/email/smtp.go @@ -13,6 +13,7 @@ type SmtpSender struct { SenderEmail string SendUser string SenderPass string + SkipVerify bool } func (s *SmtpSender) SendEmail(ctx context.Context, n Notification, e Mail) error { @@ -30,9 +31,10 @@ func (s *SmtpSender) SendEmail(ctx context.Context, n Notification, e Mail) erro // Settings for SMTP server d := gomail.NewDialer(s.SmtpHost, s.SmtpPort, s.SendUser, s.SenderPass) - // This is only needed when SSL/TLS certificate is not valid on server. - // In production this should be set to false. - d.TLSConfig = &tls.Config{InsecureSkipVerify: true} + d.TLSConfig = &tls.Config{ + ServerName: s.SmtpHost, + InsecureSkipVerify: s.SkipVerify, + } // Now send E-Mail if err := d.DialAndSend(m); err != nil { diff --git a/pro/initialize.go b/pro/initialize.go index 26bbea938..57037eaff 100644 --- a/pro/initialize.go +++ b/pro/initialize.go @@ -179,6 +179,7 @@ func InitPro() { logic.PlatformRoleRequiresGroupEnforcement = proLogic.PlatformRoleRequiresGroupEnforcement logic.UserHasGlobalNetworksAdminMembership = proLogic.UserHasGlobalNetworksAdminMembership logic.UserHasNetworkGroupAccess = proLogic.UserHasNetworkGroupAccess + logic.IsNetworkAdmin = proLogic.IsNetworkAdmin logic.CanUserCreateNetwork = proLogic.CanUserCreateNetwork logic.GetUserGroup = proLogic.GetUserGroup diff --git a/pro/logic/tags.go b/pro/logic/tags.go index 01ab56bfd..c5e2b5c13 100644 --- a/pro/logic/tags.go +++ b/pro/logic/tags.go @@ -200,11 +200,7 @@ func UpdateTag(req models.UpdateTagReq, newID models.TagID) { } // unassign old tag - if _, ok := extclient.Tags[req.ID]; ok { - if newID != "" { - delete(extclient.Tags, req.ID) - } - } + delete(extclient.Tags, req.ID) // assign tag if in taggedExtclientIDs. if _, ok := taggedExtclientIDs[extclient.ClientID]; ok {