|
|
@ -24,6 +24,7 @@ import ( |
|
|
|
"code.gitea.io/gitea/modules/log" |
|
|
|
"code.gitea.io/gitea/modules/log" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// LoginType represents an login type.
|
|
|
|
type LoginType int |
|
|
|
type LoginType int |
|
|
|
|
|
|
|
|
|
|
|
// Note: new type must append to the end of list to maintain compatibility.
|
|
|
|
// Note: new type must append to the end of list to maintain compatibility.
|
|
|
@ -36,6 +37,7 @@ const ( |
|
|
|
LoginDLDAP // 5
|
|
|
|
LoginDLDAP // 5
|
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// LoginNames contains the name of LoginType values.
|
|
|
|
var LoginNames = map[LoginType]string{ |
|
|
|
var LoginNames = map[LoginType]string{ |
|
|
|
LoginLDAP: "LDAP (via BindDN)", |
|
|
|
LoginLDAP: "LDAP (via BindDN)", |
|
|
|
LoginDLDAP: "LDAP (simple auth)", // Via direct bind
|
|
|
|
LoginDLDAP: "LDAP (simple auth)", // Via direct bind
|
|
|
@ -43,6 +45,7 @@ var LoginNames = map[LoginType]string{ |
|
|
|
LoginPAM: "PAM", |
|
|
|
LoginPAM: "PAM", |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SecurityProtocolNames contains the name of SecurityProtocol values.
|
|
|
|
var SecurityProtocolNames = map[ldap.SecurityProtocol]string{ |
|
|
|
var SecurityProtocolNames = map[ldap.SecurityProtocol]string{ |
|
|
|
ldap.SecurityProtocolUnencrypted: "Unencrypted", |
|
|
|
ldap.SecurityProtocolUnencrypted: "Unencrypted", |
|
|
|
ldap.SecurityProtocolLDAPS: "LDAPS", |
|
|
|
ldap.SecurityProtocolLDAPS: "LDAPS", |
|
|
@ -56,22 +59,28 @@ var ( |
|
|
|
_ core.Conversion = &PAMConfig{} |
|
|
|
_ core.Conversion = &PAMConfig{} |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// LDAPConfig holds configuration for LDAP login source.
|
|
|
|
type LDAPConfig struct { |
|
|
|
type LDAPConfig struct { |
|
|
|
*ldap.Source |
|
|
|
*ldap.Source |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// FromDB fills up a LDAPConfig from serialized format.
|
|
|
|
func (cfg *LDAPConfig) FromDB(bs []byte) error { |
|
|
|
func (cfg *LDAPConfig) FromDB(bs []byte) error { |
|
|
|
return json.Unmarshal(bs, &cfg) |
|
|
|
return json.Unmarshal(bs, &cfg) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ToDB exports a LDAPConfig to a serialized format.
|
|
|
|
func (cfg *LDAPConfig) ToDB() ([]byte, error) { |
|
|
|
func (cfg *LDAPConfig) ToDB() ([]byte, error) { |
|
|
|
return json.Marshal(cfg) |
|
|
|
return json.Marshal(cfg) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SecurityProtocolName returns the name of configured security
|
|
|
|
|
|
|
|
// protocol.
|
|
|
|
func (cfg *LDAPConfig) SecurityProtocolName() string { |
|
|
|
func (cfg *LDAPConfig) SecurityProtocolName() string { |
|
|
|
return SecurityProtocolNames[cfg.SecurityProtocol] |
|
|
|
return SecurityProtocolNames[cfg.SecurityProtocol] |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SMTPConfig holds configuration for the SMTP login source.
|
|
|
|
type SMTPConfig struct { |
|
|
|
type SMTPConfig struct { |
|
|
|
Auth string |
|
|
|
Auth string |
|
|
|
Host string |
|
|
|
Host string |
|
|
@ -81,22 +90,27 @@ type SMTPConfig struct { |
|
|
|
SkipVerify bool |
|
|
|
SkipVerify bool |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// FromDB fills up an SMTPConfig from serialized format.
|
|
|
|
func (cfg *SMTPConfig) FromDB(bs []byte) error { |
|
|
|
func (cfg *SMTPConfig) FromDB(bs []byte) error { |
|
|
|
return json.Unmarshal(bs, cfg) |
|
|
|
return json.Unmarshal(bs, cfg) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ToDB exports an SMTPConfig to a serialized format.
|
|
|
|
func (cfg *SMTPConfig) ToDB() ([]byte, error) { |
|
|
|
func (cfg *SMTPConfig) ToDB() ([]byte, error) { |
|
|
|
return json.Marshal(cfg) |
|
|
|
return json.Marshal(cfg) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// PAMConfig holds configuration for the PAM login source.
|
|
|
|
type PAMConfig struct { |
|
|
|
type PAMConfig struct { |
|
|
|
ServiceName string // pam service (e.g. system-auth)
|
|
|
|
ServiceName string // pam service (e.g. system-auth)
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// FromDB fills up a PAMConfig from serialized format.
|
|
|
|
func (cfg *PAMConfig) FromDB(bs []byte) error { |
|
|
|
func (cfg *PAMConfig) FromDB(bs []byte) error { |
|
|
|
return json.Unmarshal(bs, &cfg) |
|
|
|
return json.Unmarshal(bs, &cfg) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ToDB exports a PAMConfig to a serialized format.
|
|
|
|
func (cfg *PAMConfig) ToDB() ([]byte, error) { |
|
|
|
func (cfg *PAMConfig) ToDB() ([]byte, error) { |
|
|
|
return json.Marshal(cfg) |
|
|
|
return json.Marshal(cfg) |
|
|
|
} |
|
|
|
} |
|
|
@ -115,13 +129,15 @@ type LoginSource struct { |
|
|
|
UpdatedUnix int64 |
|
|
|
UpdatedUnix int64 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *LoginSource) BeforeInsert() { |
|
|
|
// BeforeInsert is invoked from XORM before inserting an object of this type.
|
|
|
|
s.CreatedUnix = time.Now().Unix() |
|
|
|
func (source *LoginSource) BeforeInsert() { |
|
|
|
s.UpdatedUnix = s.CreatedUnix |
|
|
|
source.CreatedUnix = time.Now().Unix() |
|
|
|
|
|
|
|
source.UpdatedUnix = source.CreatedUnix |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *LoginSource) BeforeUpdate() { |
|
|
|
// BeforeUpdate is invoked from XORM before updating this object.
|
|
|
|
s.UpdatedUnix = time.Now().Unix() |
|
|
|
func (source *LoginSource) BeforeUpdate() { |
|
|
|
|
|
|
|
source.UpdatedUnix = time.Now().Unix() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Cell2Int64 converts a xorm.Cell type to int64,
|
|
|
|
// Cell2Int64 converts a xorm.Cell type to int64,
|
|
|
@ -135,6 +151,7 @@ func Cell2Int64(val xorm.Cell) int64 { |
|
|
|
return (*val).(int64) |
|
|
|
return (*val).(int64) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// BeforeSet is invoked from XORM before setting the value of a field of this object.
|
|
|
|
func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) { |
|
|
|
func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) { |
|
|
|
switch colName { |
|
|
|
switch colName { |
|
|
|
case "type": |
|
|
|
case "type": |
|
|
@ -151,41 +168,49 @@ func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *LoginSource) AfterSet(colName string, _ xorm.Cell) { |
|
|
|
// AfterSet is invoked from XORM after setting the value of a field of this object.
|
|
|
|
|
|
|
|
func (source *LoginSource) AfterSet(colName string, _ xorm.Cell) { |
|
|
|
switch colName { |
|
|
|
switch colName { |
|
|
|
case "created_unix": |
|
|
|
case "created_unix": |
|
|
|
s.Created = time.Unix(s.CreatedUnix, 0).Local() |
|
|
|
source.Created = time.Unix(source.CreatedUnix, 0).Local() |
|
|
|
case "updated_unix": |
|
|
|
case "updated_unix": |
|
|
|
s.Updated = time.Unix(s.UpdatedUnix, 0).Local() |
|
|
|
source.Updated = time.Unix(source.UpdatedUnix, 0).Local() |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TypeName return name of this login source type.
|
|
|
|
func (source *LoginSource) TypeName() string { |
|
|
|
func (source *LoginSource) TypeName() string { |
|
|
|
return LoginNames[source.Type] |
|
|
|
return LoginNames[source.Type] |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// IsLDAP returns true of this source is of the LDAP type.
|
|
|
|
func (source *LoginSource) IsLDAP() bool { |
|
|
|
func (source *LoginSource) IsLDAP() bool { |
|
|
|
return source.Type == LoginLDAP |
|
|
|
return source.Type == LoginLDAP |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// IsDLDAP returns true of this source is of the DLDAP type.
|
|
|
|
func (source *LoginSource) IsDLDAP() bool { |
|
|
|
func (source *LoginSource) IsDLDAP() bool { |
|
|
|
return source.Type == LoginDLDAP |
|
|
|
return source.Type == LoginDLDAP |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// IsSMTP returns true of this source is of the SMTP type.
|
|
|
|
func (source *LoginSource) IsSMTP() bool { |
|
|
|
func (source *LoginSource) IsSMTP() bool { |
|
|
|
return source.Type == LoginSMTP |
|
|
|
return source.Type == LoginSMTP |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// IsPAM returns true of this source is of the PAM type.
|
|
|
|
func (source *LoginSource) IsPAM() bool { |
|
|
|
func (source *LoginSource) IsPAM() bool { |
|
|
|
return source.Type == LoginPAM |
|
|
|
return source.Type == LoginPAM |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// HasTLS returns true of this source supports TLS.
|
|
|
|
func (source *LoginSource) HasTLS() bool { |
|
|
|
func (source *LoginSource) HasTLS() bool { |
|
|
|
return ((source.IsLDAP() || source.IsDLDAP()) && |
|
|
|
return ((source.IsLDAP() || source.IsDLDAP()) && |
|
|
|
source.LDAP().SecurityProtocol > ldap.SecurityProtocolUnencrypted) || |
|
|
|
source.LDAP().SecurityProtocol > ldap.SecurityProtocolUnencrypted) || |
|
|
|
source.IsSMTP() |
|
|
|
source.IsSMTP() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// UseTLS returns true of this source is configured to use TLS.
|
|
|
|
func (source *LoginSource) UseTLS() bool { |
|
|
|
func (source *LoginSource) UseTLS() bool { |
|
|
|
switch source.Type { |
|
|
|
switch source.Type { |
|
|
|
case LoginLDAP, LoginDLDAP: |
|
|
|
case LoginLDAP, LoginDLDAP: |
|
|
@ -197,6 +222,8 @@ func (source *LoginSource) UseTLS() bool { |
|
|
|
return false |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SkipVerify returns true if this source is configured to skip SSL
|
|
|
|
|
|
|
|
// verification.
|
|
|
|
func (source *LoginSource) SkipVerify() bool { |
|
|
|
func (source *LoginSource) SkipVerify() bool { |
|
|
|
switch source.Type { |
|
|
|
switch source.Type { |
|
|
|
case LoginLDAP, LoginDLDAP: |
|
|
|
case LoginLDAP, LoginDLDAP: |
|
|
@ -208,17 +235,23 @@ func (source *LoginSource) SkipVerify() bool { |
|
|
|
return false |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// LDAP returns LDAPConfig for this source, if of LDAP type.
|
|
|
|
func (source *LoginSource) LDAP() *LDAPConfig { |
|
|
|
func (source *LoginSource) LDAP() *LDAPConfig { |
|
|
|
return source.Cfg.(*LDAPConfig) |
|
|
|
return source.Cfg.(*LDAPConfig) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SMTP returns SMTPConfig for this source, if of SMTP type.
|
|
|
|
func (source *LoginSource) SMTP() *SMTPConfig { |
|
|
|
func (source *LoginSource) SMTP() *SMTPConfig { |
|
|
|
return source.Cfg.(*SMTPConfig) |
|
|
|
return source.Cfg.(*SMTPConfig) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// PAM returns PAMConfig for this source, if of PAM type.
|
|
|
|
func (source *LoginSource) PAM() *PAMConfig { |
|
|
|
func (source *LoginSource) PAM() *PAMConfig { |
|
|
|
return source.Cfg.(*PAMConfig) |
|
|
|
return source.Cfg.(*PAMConfig) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// CreateLoginSource inserts a LoginSource in the DB if not already
|
|
|
|
|
|
|
|
// existing with the given name.
|
|
|
|
func CreateLoginSource(source *LoginSource) error { |
|
|
|
func CreateLoginSource(source *LoginSource) error { |
|
|
|
has, err := x.Get(&LoginSource{Name: source.Name}) |
|
|
|
has, err := x.Get(&LoginSource{Name: source.Name}) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
@ -231,6 +264,7 @@ func CreateLoginSource(source *LoginSource) error { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// LoginSources returns a slice of all login sources found in DB.
|
|
|
|
func LoginSources() ([]*LoginSource, error) { |
|
|
|
func LoginSources() ([]*LoginSource, error) { |
|
|
|
auths := make([]*LoginSource, 0, 5) |
|
|
|
auths := make([]*LoginSource, 0, 5) |
|
|
|
return auths, x.Find(&auths) |
|
|
|
return auths, x.Find(&auths) |
|
|
@ -248,11 +282,13 @@ func GetLoginSourceByID(id int64) (*LoginSource, error) { |
|
|
|
return source, nil |
|
|
|
return source, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// UpdateSource updates a LoginSource record in DB.
|
|
|
|
func UpdateSource(source *LoginSource) error { |
|
|
|
func UpdateSource(source *LoginSource) error { |
|
|
|
_, err := x.Id(source.ID).AllCols().Update(source) |
|
|
|
_, err := x.Id(source.ID).AllCols().Update(source) |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// DeleteSource deletes a LoginSource record in DB.
|
|
|
|
func DeleteSource(source *LoginSource) error { |
|
|
|
func DeleteSource(source *LoginSource) error { |
|
|
|
count, err := x.Count(&User{LoginSource: source.ID}) |
|
|
|
count, err := x.Count(&User{LoginSource: source.ID}) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
@ -357,13 +393,16 @@ func (auth *smtpLoginAuth) Next(fromServer []byte, more bool) ([]byte, error) { |
|
|
|
return nil, nil |
|
|
|
return nil, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SMTP authentication type names.
|
|
|
|
const ( |
|
|
|
const ( |
|
|
|
SMTPPlain = "PLAIN" |
|
|
|
SMTPPlain = "PLAIN" |
|
|
|
SMTPLogin = "LOGIN" |
|
|
|
SMTPLogin = "LOGIN" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SMTPAuths contains available SMTP authentication type names.
|
|
|
|
var SMTPAuths = []string{SMTPPlain, SMTPLogin} |
|
|
|
var SMTPAuths = []string{SMTPPlain, SMTPLogin} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SMTPAuth performs an SMTP authentication.
|
|
|
|
func SMTPAuth(a smtp.Auth, cfg *SMTPConfig) error { |
|
|
|
func SMTPAuth(a smtp.Auth, cfg *SMTPConfig) error { |
|
|
|
c, err := smtp.Dial(fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)) |
|
|
|
c, err := smtp.Dial(fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
@ -487,6 +526,7 @@ func LoginViaPAM(user *User, login, password string, sourceID int64, cfg *PAMCon |
|
|
|
return user, CreateUser(user) |
|
|
|
return user, CreateUser(user) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ExternalUserLogin attempts a login using external source types.
|
|
|
|
func ExternalUserLogin(user *User, login, password string, source *LoginSource, autoRegister bool) (*User, error) { |
|
|
|
func ExternalUserLogin(user *User, login, password string, source *LoginSource, autoRegister bool) (*User, error) { |
|
|
|
if !source.IsActived { |
|
|
|
if !source.IsActived { |
|
|
|
return nil, ErrLoginSourceNotActived |
|
|
|
return nil, ErrLoginSourceNotActived |
|
|
|