Ver código fonte

Use SecurityProtocol to replace UseSSL in LDAP config

Initially proposed by #2376 and fixes #3068 as well.
Unknwon 8 anos atrás
pai
commit
401bf944ef

+ 1 - 1
README.md

@@ -3,7 +3,7 @@ Gogs - Go Git Service [![Build Status](https://travis-ci.org/gogits/gogs.svg?bra
 
 ![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true)
 
-##### Current tip version: 0.9.36 (see [Releases](https://github.com/gogits/gogs/releases) for binary versions)
+##### Current tip version: 0.9.37 (see [Releases](https://github.com/gogits/gogs/releases) for binary versions)
 
 | Web | UI  | Preview  |
 |:-------------:|:-------:|:-------:|

+ 1 - 0
conf/locale/locale_en-US.ini

@@ -919,6 +919,7 @@ auths.enabled = Enabled
 auths.updated = Updated
 auths.auth_type = Authentication Type
 auths.auth_name = Authentication Name
+auths.security_protocol = Security Protocol
 auths.domain = Domain
 auths.host = Host
 auths.port = Port

+ 1 - 1
glide.lock

@@ -6,7 +6,7 @@ imports:
   subpackages:
   - memcache
 - name: github.com/codegangsta/cli
-  version: e5bef42c62aa7d25aba4880dc02b7624f01e9e19
+  version: 1efa31f08b9333f1bd4882d61f9d668a70cd902e
 - name: github.com/go-macaron/binding
   version: bd00823a7e9aa00cb3b1738fde244573ba7cce2c
 - name: github.com/go-macaron/cache

+ 1 - 1
gogs.go

@@ -17,7 +17,7 @@ import (
 	"github.com/gogits/gogs/modules/setting"
 )
 
-const APP_VER = "0.9.36.0704"
+const APP_VER = "0.9.37.0708"
 
 func init() {
 	runtime.GOMAXPROCS(runtime.NumCPU())

+ 22 - 6
models/login.go

@@ -23,6 +23,11 @@ import (
 	"github.com/gogits/gogs/modules/log"
 )
 
+var (
+	ErrAuthenticationAlreadyExist = errors.New("Authentication already exist")
+	ErrAuthenticationUserUsed     = errors.New("Authentication has been used by some users")
+)
+
 type LoginType int
 
 // Note: new type must be added at the end of list to maintain compatibility.
@@ -35,11 +40,6 @@ const (
 	LOGIN_DLDAP            // 5
 )
 
-var (
-	ErrAuthenticationAlreadyExist = errors.New("Authentication already exist")
-	ErrAuthenticationUserUsed     = errors.New("Authentication has been used by some users")
-)
-
 var LoginNames = map[LoginType]string{
 	LOGIN_LDAP:  "LDAP (via BindDN)",
 	LOGIN_DLDAP: "LDAP (simple auth)", // Via direct bind
@@ -47,6 +47,12 @@ var LoginNames = map[LoginType]string{
 	LOGIN_PAM:   "PAM",
 }
 
+var SecurityProtocolNames = map[ldap.SecurityProtocol]string{
+	ldap.SECURITY_PROTOCOL_UNENCRYPTED: "Unencrypted",
+	ldap.SECURITY_PROTOCOL_LDAPS:       "LDAPS",
+	ldap.SECURITY_PROTOCOL_START_TLS:   "StartTLS",
+}
+
 // Ensure structs implemented interface.
 var (
 	_ core.Conversion = &LDAPConfig{}
@@ -66,6 +72,10 @@ func (cfg *LDAPConfig) ToDB() ([]byte, error) {
 	return json.Marshal(cfg)
 }
 
+func (cfg *LDAPConfig) SecurityProtocolName() string {
+	return SecurityProtocolNames[cfg.SecurityProtocol]
+}
+
 type SMTPConfig struct {
 	Auth           string
 	Host           string
@@ -173,10 +183,16 @@ func (source *LoginSource) IsPAM() bool {
 	return source.Type == LOGIN_PAM
 }
 
+func (source *LoginSource) HasTLS() bool {
+	return ((source.IsLDAP() || source.IsDLDAP()) &&
+		source.LDAP().SecurityProtocol > ldap.SECURITY_PROTOCOL_UNENCRYPTED) ||
+		source.IsSMTP()
+}
+
 func (source *LoginSource) UseTLS() bool {
 	switch source.Type {
 	case LOGIN_LDAP, LOGIN_DLDAP:
-		return source.LDAP().UseSSL
+		return source.LDAP().SecurityProtocol != ldap.SECURITY_PROTOCOL_UNENCRYPTED
 	case LOGIN_SMTP:
 		return source.SMTP().TLS
 	}

+ 10 - 8
models/migrations/migrations.go

@@ -59,14 +59,15 @@ type Version struct {
 // If you want to "retire" a migration, remove it from the top of the list and
 // update _MIN_VER_DB accordingly
 var migrations = []Migration{
-	NewMigration("fix locale file load panic", fixLocaleFileLoadPanic),                 // V4 -> V5:v0.6.0
-	NewMigration("trim action compare URL prefix", trimCommitActionAppUrlPrefix),       // V5 -> V6:v0.6.3
-	NewMigration("generate issue-label from issue", issueToIssueLabel),                 // V6 -> V7:v0.6.4
-	NewMigration("refactor attachment table", attachmentRefactor),                      // V7 -> V8:v0.6.4
-	NewMigration("rename pull request fields", renamePullRequestFields),                // V8 -> V9:v0.6.16
-	NewMigration("clean up migrate repo info", cleanUpMigrateRepoInfo),                 // V9 -> V10:v0.6.20
-	NewMigration("generate rands and salt for organizations", generateOrgRandsAndSalt), // V10 -> V11:v0.8.5
-	NewMigration("convert date to unix timestamp", convertDateToUnix),                  // V11 -> V12:v0.9.2
+	NewMigration("fix locale file load panic", fixLocaleFileLoadPanic),                           // V4 -> V5:v0.6.0
+	NewMigration("trim action compare URL prefix", trimCommitActionAppUrlPrefix),                 // V5 -> V6:v0.6.3
+	NewMigration("generate issue-label from issue", issueToIssueLabel),                           // V6 -> V7:v0.6.4
+	NewMigration("refactor attachment table", attachmentRefactor),                                // V7 -> V8:v0.6.4
+	NewMigration("rename pull request fields", renamePullRequestFields),                          // V8 -> V9:v0.6.16
+	NewMigration("clean up migrate repo info", cleanUpMigrateRepoInfo),                           // V9 -> V10:v0.6.20
+	NewMigration("generate rands and salt for organizations", generateOrgRandsAndSalt),           // V10 -> V11:v0.8.5
+	NewMigration("convert date to unix timestamp", convertDateToUnix),                            // V11 -> V12:v0.9.2
+	NewMigration("convert LDAP UseSSL option to SecurityProtocol", ldapUseSSLToSecurityProtocol), // V12 -> V13:v0.9.37
 }
 
 // Migrate database to current version
@@ -580,6 +581,7 @@ type TWebhook struct {
 func (t *TWebhook) TableName() string { return "webhook" }
 
 func convertDateToUnix(x *xorm.Engine) (err error) {
+	log.Info("This migration could take up to minutes, please be patient.")
 	type Bean struct {
 		ID         int64 `xorm:"pk autoincr"`
 		Created    time.Time

+ 52 - 0
models/migrations/v13.go

@@ -0,0 +1,52 @@
+// Copyright 2016 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package migrations
+
+import (
+	"encoding/json"
+	"fmt"
+	"strings"
+
+	"github.com/Unknwon/com"
+	"github.com/go-xorm/xorm"
+)
+
+func ldapUseSSLToSecurityProtocol(x *xorm.Engine) error {
+	results, err := x.Query("SELECT `id`,`cfg` FROM `login_source` WHERE `type` = 2 OR `type` = 5")
+	if err != nil {
+		if strings.Contains(err.Error(), "no such column") {
+			return nil
+		}
+		return fmt.Errorf("select LDAP login sources: %v", err)
+	}
+
+	sess := x.NewSession()
+	defer sessionRelease(sess)
+	if err = sess.Begin(); err != nil {
+		return err
+	}
+
+	for _, result := range results {
+		cfg := map[string]interface{}{}
+		if err = json.Unmarshal(result["cfg"], &cfg); err != nil {
+			return fmt.Errorf("decode JSON config: %v", err)
+		}
+		if com.ToStr(cfg["UseSSL"]) == "true" {
+			cfg["SecurityProtocol"] = 1 // LDAPS
+		}
+		delete(cfg, "UseSSL")
+
+		data, err := json.Marshal(&cfg)
+		if err != nil {
+			return fmt.Errorf("encode JSON config: %v", err)
+		}
+
+		if _, err = sess.Exec("UPDATE `login_source` SET `cfg`=? WHERE `id`=?",
+			string(data), com.StrTo(result["id"]).MustInt64()); err != nil {
+			return fmt.Errorf("update config column: %v", err)
+		}
+	}
+	return sess.Commit()
+}

+ 1 - 0
modules/auth/auth_form.go

@@ -31,6 +31,7 @@ type AuthenticationForm struct {
 	SMTPHost          string
 	SMTPPort          int
 	AllowedDomains    string
+	SecurityProtocol  int `binding:"Range(0,2)"`
 	TLS               bool
 	SkipVerify        bool
 	PAMServiceName    string

+ 48 - 25
modules/auth/ldap/ldap.go

@@ -16,12 +16,21 @@ import (
 	"github.com/gogits/gogs/modules/log"
 )
 
+type SecurityProtocol int
+
+// Note: new type must be added at the end of list to maintain compatibility.
+const (
+	SECURITY_PROTOCOL_UNENCRYPTED SecurityProtocol = iota
+	SECURITY_PROTOCOL_LDAPS
+	SECURITY_PROTOCOL_START_TLS
+)
+
 // Basic LDAP authentication service
 type Source struct {
 	Name              string // canonical name (ie. corporate.ad)
 	Host              string // LDAP host
 	Port              int    // port number
-	UseSSL            bool   // Use SSL
+	SecurityProtocol  SecurityProtocol
 	SkipVerify        bool
 	BindDN            string // DN to bind with
 	BindPassword      string // Bind DN password
@@ -102,9 +111,46 @@ func (ls *Source) findUserDN(l *ldap.Conn, name string) (string, bool) {
 	return userDN, true
 }
 
+func dial(ls *Source) (*ldap.Conn, error) {
+	log.Trace("Dialing LDAP with security protocol (%v) without verifying: %v", ls.SecurityProtocol, ls.SkipVerify)
+
+	tlsCfg := &tls.Config{
+		ServerName:         ls.Host,
+		InsecureSkipVerify: ls.SkipVerify,
+	}
+	if ls.SecurityProtocol == SECURITY_PROTOCOL_LDAPS {
+		return ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port), tlsCfg)
+	}
+
+	conn, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port))
+	if err != nil {
+		return nil, fmt.Errorf("Dial: %v", err)
+	}
+
+	if ls.SecurityProtocol == SECURITY_PROTOCOL_START_TLS {
+		if err = conn.StartTLS(tlsCfg); err != nil {
+			conn.Close()
+			return nil, fmt.Errorf("StartTLS: %v", err)
+		}
+	}
+
+	return conn, nil
+}
+
+func bindUser(l *ldap.Conn, userDN, passwd string) error {
+	log.Trace("Binding with userDN: %s", userDN)
+	err := l.Bind(userDN, passwd)
+	if err != nil {
+		log.Debug("LDAP auth. failed for %s, reason: %v", userDN, err)
+		return err
+	}
+	log.Trace("Bound successfully with userDN: %s", userDN)
+	return err
+}
+
 // searchEntry : search an LDAP source if an entry (name, passwd) is valid and in the specific filter
 func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, string, string, string, bool, bool) {
-	l, err := ldapDial(ls)
+	l, err := dial(ls)
 	if err != nil {
 		log.Error(4, "LDAP Connect error, %s:%v", ls.Host, err)
 		ls.Enabled = false
@@ -197,26 +243,3 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, str
 
 	return username_attr, name_attr, sn_attr, mail_attr, admin_attr, true
 }
-
-func bindUser(l *ldap.Conn, userDN, passwd string) error {
-	log.Trace("Binding with userDN: %s", userDN)
-	err := l.Bind(userDN, passwd)
-	if err != nil {
-		log.Debug("LDAP auth. failed for %s, reason: %v", userDN, err)
-		return err
-	}
-	log.Trace("Bound successfully with userDN: %s", userDN)
-	return err
-}
-
-func ldapDial(ls *Source) (*ldap.Conn, error) {
-	if ls.UseSSL {
-		log.Debug("Using TLS for LDAP without verifying: %v", ls.SkipVerify)
-		return ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port), &tls.Config{
-			ServerName:         ls.Host,
-			InsecureSkipVerify: ls.SkipVerify,
-		})
-	} else {
-		return ldap.Dial("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port))
-	}
-}

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
modules/bindata/bindata.go


+ 21 - 0
public/js/gogs.js

@@ -612,6 +612,13 @@ function initAdmin() {
         });
     }
 
+    function onSecurityProtocolChange() {
+        if ($('#security_protocol').val() > 0) {
+            $('.has-tls').show();
+        } else {
+            $('.has-tls').hide();
+        }
+    }
 
     // New authentication
     if ($('.admin.new.authentication').length > 0) {
@@ -620,6 +627,7 @@ function initAdmin() {
             $('.dldap').hide();
             $('.smtp').hide();
             $('.pam').hide();
+            $('.has-tls').hide();
 
             var auth_type = $(this).val();
             switch (auth_type) {
@@ -628,6 +636,7 @@ function initAdmin() {
                     break;
                 case '3':     // SMTP
                     $('.smtp').show();
+                    $('.has-tls').show();
                     break;
                 case '4':     // PAM
                     $('.pam').show();
@@ -636,7 +645,19 @@ function initAdmin() {
                     $('.dldap').show();
                     break;
             }
+
+            if (auth_type == '2' || auth_type == '5') {
+                onSecurityProtocolChange()
+            }
         });
+        $('#security_protocol').change(onSecurityProtocolChange)
+    }
+    // Edit authentication
+    if ($('.admin.edit.authentication').length > 0) {
+        var auth_type = $('#auth_type').val();
+        if (auth_type == '2' || auth_type == '5') {
+            $('#security_protocol').change(onSecurityProtocolChange);
+        }
     }
 
     // Notice

+ 35 - 16
routers/admin/auths.go

@@ -41,17 +41,24 @@ func Authentications(ctx *context.Context) {
 	ctx.HTML(200, AUTHS)
 }
 
-type AuthSource struct {
+type dropdownItem struct {
 	Name string
-	Type models.LoginType
+	Type interface{}
 }
 
-var authSources = []AuthSource{
-	{models.LoginNames[models.LOGIN_LDAP], models.LOGIN_LDAP},
-	{models.LoginNames[models.LOGIN_DLDAP], models.LOGIN_DLDAP},
-	{models.LoginNames[models.LOGIN_SMTP], models.LOGIN_SMTP},
-	{models.LoginNames[models.LOGIN_PAM], models.LOGIN_PAM},
-}
+var (
+	authSources = []dropdownItem{
+		{models.LoginNames[models.LOGIN_LDAP], models.LOGIN_LDAP},
+		{models.LoginNames[models.LOGIN_DLDAP], models.LOGIN_DLDAP},
+		{models.LoginNames[models.LOGIN_SMTP], models.LOGIN_SMTP},
+		{models.LoginNames[models.LOGIN_PAM], models.LOGIN_PAM},
+	}
+	securityProtocols = []dropdownItem{
+		{models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_UNENCRYPTED], ldap.SECURITY_PROTOCOL_UNENCRYPTED},
+		{models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_LDAPS], ldap.SECURITY_PROTOCOL_LDAPS},
+		{models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_START_TLS], ldap.SECURITY_PROTOCOL_START_TLS},
+	}
+)
 
 func NewAuthSource(ctx *context.Context) {
 	ctx.Data["Title"] = ctx.Tr("admin.auths.new")
@@ -59,10 +66,12 @@ func NewAuthSource(ctx *context.Context) {
 	ctx.Data["PageIsAdminAuthentications"] = true
 
 	ctx.Data["type"] = models.LOGIN_LDAP
-	ctx.Data["CurTypeName"] = models.LoginNames[models.LOGIN_LDAP]
+	ctx.Data["CurrentTypeName"] = models.LoginNames[models.LOGIN_LDAP]
+	ctx.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_UNENCRYPTED]
 	ctx.Data["smtp_auth"] = "PLAIN"
 	ctx.Data["is_active"] = true
 	ctx.Data["AuthSources"] = authSources
+	ctx.Data["SecurityProtocols"] = securityProtocols
 	ctx.Data["SMTPAuths"] = models.SMTPAuths
 	ctx.HTML(200, AUTH_NEW)
 }
@@ -73,7 +82,7 @@ func parseLDAPConfig(form auth.AuthenticationForm) *models.LDAPConfig {
 			Name:              form.Name,
 			Host:              form.Host,
 			Port:              form.Port,
-			UseSSL:            form.TLS,
+			SecurityProtocol:  ldap.SecurityProtocol(form.SecurityProtocol),
 			SkipVerify:        form.SkipVerify,
 			BindDN:            form.BindDN,
 			UserDN:            form.UserDN,
@@ -107,21 +116,21 @@ func NewAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) {
 	ctx.Data["PageIsAdmin"] = true
 	ctx.Data["PageIsAdminAuthentications"] = true
 
-	ctx.Data["CurTypeName"] = models.LoginNames[models.LoginType(form.Type)]
+	ctx.Data["CurrentTypeName"] = models.LoginNames[models.LoginType(form.Type)]
+	ctx.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SecurityProtocol(form.SecurityProtocol)]
 	ctx.Data["AuthSources"] = authSources
+	ctx.Data["SecurityProtocols"] = securityProtocols
 	ctx.Data["SMTPAuths"] = models.SMTPAuths
 
-	if ctx.HasError() {
-		ctx.HTML(200, AUTH_NEW)
-		return
-	}
-
+	hasTLS := false
 	var config core.Conversion
 	switch models.LoginType(form.Type) {
 	case models.LOGIN_LDAP, models.LOGIN_DLDAP:
 		config = parseLDAPConfig(form)
+		hasTLS = ldap.SecurityProtocol(form.SecurityProtocol) > ldap.SECURITY_PROTOCOL_UNENCRYPTED
 	case models.LOGIN_SMTP:
 		config = parseSMTPConfig(form)
+		hasTLS = true
 	case models.LOGIN_PAM:
 		config = &models.PAMConfig{
 			ServiceName: form.PAMServiceName,
@@ -130,6 +139,12 @@ func NewAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) {
 		ctx.Error(400)
 		return
 	}
+	ctx.Data["HasTLS"] = hasTLS
+
+	if ctx.HasError() {
+		ctx.HTML(200, AUTH_NEW)
+		return
+	}
 
 	if err := models.CreateSource(&models.LoginSource{
 		Type:      models.LoginType(form.Type),
@@ -152,6 +167,7 @@ func EditAuthSource(ctx *context.Context) {
 	ctx.Data["PageIsAdmin"] = true
 	ctx.Data["PageIsAdminAuthentications"] = true
 
+	ctx.Data["SecurityProtocols"] = securityProtocols
 	ctx.Data["SMTPAuths"] = models.SMTPAuths
 
 	source, err := models.GetLoginSourceByID(ctx.ParamsInt64(":authid"))
@@ -160,6 +176,8 @@ func EditAuthSource(ctx *context.Context) {
 		return
 	}
 	ctx.Data["Source"] = source
+	ctx.Data["HasTLS"] = source.HasTLS()
+
 	ctx.HTML(200, AUTH_EDIT)
 }
 
@@ -176,6 +194,7 @@ func EditAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) {
 		return
 	}
 	ctx.Data["Source"] = source
+	ctx.Data["HasTLS"] = source.HasTLS()
 
 	if ctx.HasError() {
 		ctx.HTML(200, AUTH_EDIT)

+ 1 - 1
templates/.VERSION

@@ -1 +1 @@
-0.9.36.0704
+0.9.37.0708

+ 16 - 3
templates/admin/auth/edit.tmpl

@@ -14,7 +14,7 @@
 						<input type="hidden" name="id" value="{{.Source.ID}}">
 						<div class="inline field">
 							<label>{{$.i18n.Tr "admin.auths.auth_type"}}</label>
-							<input type="hidden" name="type" value="{{.Source.Type}}">
+							<input type="hidden" id="auth_type" name="type" value="{{.Source.Type}}">
 							<span>{{.Source.TypeName}}</span>
 						</div>
 						<div class="required inline field {{if .Err_Name}}error{{end}}">
@@ -25,6 +25,19 @@
 						<!-- LDAP and DLDAP -->
 						{{if or .Source.IsLDAP .Source.IsDLDAP}}
 							{{ $cfg:=.Source.LDAP }}
+							<div class="inline required field {{if .Err_SecurityProtocol}}error{{end}}">
+								<label>{{.i18n.Tr "admin.auths.security_protocol"}}</label>
+								<div class="ui selection security-protocol dropdown">
+									<input type="hidden" id="security_protocol" name="security_protocol" value="{{$cfg.SecurityProtocol}}">
+									<div class="text">{{$cfg.SecurityProtocolName}}</div>
+									<i class="dropdown icon"></i>
+									<div class="menu">
+										{{range .SecurityProtocols}}
+											<div class="item" data-value="{{.Type}}">{{.Name}}</div>
+										{{end}}
+									</div>
+								</div>
+							</div>
 							<div class="required field">
 								<label for="host">{{.i18n.Tr "admin.auths.host"}}</label>
 								<input id="host" name="host" value="{{$cfg.Host}}" placeholder="e.g. mydomain.com" required>
@@ -129,13 +142,13 @@
 							</div>
 						{{end}}
 
-						<div class="inline field {{if not (or (or .Source.IsLDAP .Source.IsDLDAP) .Source.IsSMTP)}}hide{{end}}">
+						<div class="inline field {{if not .Source.IsSMTP}}hide{{end}}">
 							<div class="ui checkbox">
 								<label><strong>{{.i18n.Tr "admin.auths.enable_tls"}}</strong></label>
 								<input name="tls" type="checkbox" {{if .Source.UseTLS}}checked{{end}}>
 							</div>
 						</div>
-						<div class="inline field {{if not (or (or .Source.IsLDAP .Source.IsDLDAP) .Source.IsSMTP)}}hide{{end}}">
+						<div class="has-tls inline field {{if not .HasTLS}}hide{{end}}">
 							<div class="ui checkbox">
 								<label><strong>{{.i18n.Tr "admin.auths.skip_tls_verify"}}</strong></label>
 								<input name="skip_verify" type="checkbox" {{if .Source.SkipVerify}}checked{{end}}>

+ 16 - 3
templates/admin/auth/new.tmpl

@@ -16,7 +16,7 @@
 							<label>{{.i18n.Tr "admin.auths.auth_type"}}</label>
 							<div class="ui selection type dropdown">
 								<input type="hidden" id="auth_type" name="type" value="{{.type}}">
-								<div class="text">{{.CurTypeName}}</div>
+								<div class="text">{{.CurrentTypeName}}</div>
 								<i class="dropdown icon"></i>
 								<div class="menu">
 									{{range .AuthSources}}
@@ -32,6 +32,19 @@
 
 						<!-- LDAP and DLDAP -->
 						<div class="ldap dldap field {{if not (or (eq .type 2) (eq .type 5))}}hide{{end}}">
+							<div class="inline required field {{if .Err_SecurityProtocol}}error{{end}}">
+								<label>{{.i18n.Tr "admin.auths.security_protocol"}}</label>
+								<div class="ui selection security-protocol dropdown">
+									<input type="hidden" id="security_protocol" name="security_protocol" value="{{.security_protocol}}">
+									<div class="text">{{.CurrentSecurityProtocol}}</div>
+									<i class="dropdown icon"></i>
+									<div class="menu">
+										{{range .SecurityProtocols}}
+											<div class="item" data-value="{{.Type}}">{{.Name}}</div>
+										{{end}}
+									</div>
+								</div>
+							</div>
 							<div class="required field">
 								<label for="host">{{.i18n.Tr "admin.auths.host"}}</label>
 								<input id="host" name="host" value="{{.host}}" placeholder="e.g. mydomain.com">
@@ -126,13 +139,13 @@
 								<input name="attributes_in_bind" type="checkbox" {{if .attributes_in_bind}}checked{{end}}>
 							</div>
 						</div>
-						<div class="ldap dldap smtp inline field {{if not (or (or (eq .type 2) (eq .type 5)) (eq .type 3))}}hide{{end}}">
+						<div class="smtp inline field {{if not (eq .type 3)}}hide{{end}}">
 							<div class="ui checkbox">
 								<label><strong>{{.i18n.Tr "admin.auths.enable_tls"}}</strong></label>
 								<input name="tls" type="checkbox" {{if .tls}}checked{{end}}>
 							</div>
 						</div>
-						<div class="ldap dldap smtp inline field {{if not (or (or (eq .type 2) (eq .type 5)) (eq .type 3))}}hide{{end}}">
+						<div class="has-tls inline field {{if not .HasTLS}}hide{{end}}">
 							<div class="ui checkbox">
 								<label><strong>{{.i18n.Tr "admin.auths.skip_tls_verify"}}</strong></label>
 								<input name="skip_verify" type="checkbox" {{if .skip_verify}}checked{{end}}>

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff