|
|
@ -63,10 +63,11 @@ func (cfg *LDAPConfig) ToDB() ([]byte, error) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type SMTPConfig struct { |
|
|
|
type SMTPConfig struct { |
|
|
|
Auth string |
|
|
|
Auth string |
|
|
|
Host string |
|
|
|
Host string |
|
|
|
Port int |
|
|
|
Port int |
|
|
|
TLS bool |
|
|
|
TLS bool |
|
|
|
|
|
|
|
SkipVerify bool |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (cfg *SMTPConfig) FromDB(bs []byte) error { |
|
|
|
func (cfg *SMTPConfig) FromDB(bs []byte) error { |
|
|
@ -90,7 +91,7 @@ func (cfg *PAMConfig) ToDB() ([]byte, error) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type LoginSource struct { |
|
|
|
type LoginSource struct { |
|
|
|
Id int64 |
|
|
|
ID int64 `xorm:"pk autoincr"` |
|
|
|
Type LoginType |
|
|
|
Type LoginType |
|
|
|
Name string `xorm:"UNIQUE"` |
|
|
|
Name string `xorm:"UNIQUE"` |
|
|
|
IsActived bool `xorm:"NOT NULL DEFAULT false"` |
|
|
|
IsActived bool `xorm:"NOT NULL DEFAULT false"` |
|
|
@ -100,6 +101,20 @@ type LoginSource struct { |
|
|
|
Updated time.Time `xorm:"UPDATED"` |
|
|
|
Updated time.Time `xorm:"UPDATED"` |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) { |
|
|
|
|
|
|
|
switch colName { |
|
|
|
|
|
|
|
case "type": |
|
|
|
|
|
|
|
switch LoginType((*val).(int64)) { |
|
|
|
|
|
|
|
case LDAP: |
|
|
|
|
|
|
|
source.Cfg = new(LDAPConfig) |
|
|
|
|
|
|
|
case SMTP: |
|
|
|
|
|
|
|
source.Cfg = new(SMTPConfig) |
|
|
|
|
|
|
|
case PAM: |
|
|
|
|
|
|
|
source.Cfg = new(PAMConfig) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (source *LoginSource) TypeString() string { |
|
|
|
func (source *LoginSource) TypeString() string { |
|
|
|
return LoginTypes[source.Type] |
|
|
|
return LoginTypes[source.Type] |
|
|
|
} |
|
|
|
} |
|
|
@ -116,32 +131,17 @@ func (source *LoginSource) PAM() *PAMConfig { |
|
|
|
return source.Cfg.(*PAMConfig) |
|
|
|
return source.Cfg.(*PAMConfig) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) { |
|
|
|
|
|
|
|
if colName == "type" { |
|
|
|
|
|
|
|
ty := (*val).(int64) |
|
|
|
|
|
|
|
switch LoginType(ty) { |
|
|
|
|
|
|
|
case LDAP: |
|
|
|
|
|
|
|
source.Cfg = new(LDAPConfig) |
|
|
|
|
|
|
|
case SMTP: |
|
|
|
|
|
|
|
source.Cfg = new(SMTPConfig) |
|
|
|
|
|
|
|
case PAM: |
|
|
|
|
|
|
|
source.Cfg = new(PAMConfig) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func CreateSource(source *LoginSource) error { |
|
|
|
func CreateSource(source *LoginSource) error { |
|
|
|
_, err := x.Insert(source) |
|
|
|
_, err := x.Insert(source) |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func GetAuths() ([]*LoginSource, error) { |
|
|
|
func GetAuths() ([]*LoginSource, error) { |
|
|
|
var auths = make([]*LoginSource, 0, 5) |
|
|
|
auths := make([]*LoginSource, 0, 5) |
|
|
|
err := x.Find(&auths) |
|
|
|
return auths, x.Find(&auths) |
|
|
|
return auths, err |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func GetLoginSourceById(id int64) (*LoginSource, error) { |
|
|
|
func GetLoginSourceByID(id int64) (*LoginSource, error) { |
|
|
|
source := new(LoginSource) |
|
|
|
source := new(LoginSource) |
|
|
|
has, err := x.Id(id).Get(source) |
|
|
|
has, err := x.Id(id).Get(source) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
@ -153,19 +153,19 @@ func GetLoginSourceById(id int64) (*LoginSource, error) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func DelLoginSource(source *LoginSource) error { |
|
|
|
func DelLoginSource(source *LoginSource) error { |
|
|
|
cnt, err := x.Count(&User{LoginSource: source.Id}) |
|
|
|
cnt, err := x.Count(&User{LoginSource: source.ID}) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
if cnt > 0 { |
|
|
|
if cnt > 0 { |
|
|
|
return ErrAuthenticationUserUsed |
|
|
|
return ErrAuthenticationUserUsed |
|
|
|
} |
|
|
|
} |
|
|
|
_, err = x.Id(source.Id).Delete(&LoginSource{}) |
|
|
|
_, err = x.Id(source.ID).Delete(&LoginSource{}) |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -206,21 +206,21 @@ func UserSignIn(uname, passwd string) (*User, error) { |
|
|
|
for _, source := range sources { |
|
|
|
for _, source := range sources { |
|
|
|
if source.Type == LDAP { |
|
|
|
if source.Type == LDAP { |
|
|
|
u, err := LoginUserLdapSource(nil, uname, passwd, |
|
|
|
u, err := LoginUserLdapSource(nil, uname, passwd, |
|
|
|
source.Id, source.Cfg.(*LDAPConfig), true) |
|
|
|
source.ID, source.Cfg.(*LDAPConfig), true) |
|
|
|
if err == nil { |
|
|
|
if err == nil { |
|
|
|
return u, nil |
|
|
|
return u, nil |
|
|
|
} |
|
|
|
} |
|
|
|
log.Warn("Fail to login(%s) by LDAP(%s): %v", uname, source.Name, err) |
|
|
|
log.Warn("Fail to login(%s) by LDAP(%s): %v", uname, source.Name, err) |
|
|
|
} else if source.Type == SMTP { |
|
|
|
} else if source.Type == SMTP { |
|
|
|
u, err := LoginUserSMTPSource(nil, uname, passwd, |
|
|
|
u, err := LoginUserSMTPSource(nil, uname, passwd, |
|
|
|
source.Id, source.Cfg.(*SMTPConfig), true) |
|
|
|
source.ID, source.Cfg.(*SMTPConfig), true) |
|
|
|
if err == nil { |
|
|
|
if err == nil { |
|
|
|
return u, nil |
|
|
|
return u, nil |
|
|
|
} |
|
|
|
} |
|
|
|
log.Warn("Fail to login(%s) by SMTP(%s): %v", uname, source.Name, err) |
|
|
|
log.Warn("Fail to login(%s) by SMTP(%s): %v", uname, source.Name, err) |
|
|
|
} else if source.Type == PAM { |
|
|
|
} else if source.Type == PAM { |
|
|
|
u, err := LoginUserPAMSource(nil, uname, passwd, |
|
|
|
u, err := LoginUserPAMSource(nil, uname, passwd, |
|
|
|
source.Id, source.Cfg.(*PAMConfig), true) |
|
|
|
source.ID, source.Cfg.(*PAMConfig), true) |
|
|
|
if err == nil { |
|
|
|
if err == nil { |
|
|
|
return u, nil |
|
|
|
return u, nil |
|
|
|
} |
|
|
|
} |
|
|
@ -243,11 +243,11 @@ func UserSignIn(uname, passwd string) (*User, error) { |
|
|
|
|
|
|
|
|
|
|
|
switch u.LoginType { |
|
|
|
switch u.LoginType { |
|
|
|
case LDAP: |
|
|
|
case LDAP: |
|
|
|
return LoginUserLdapSource(u, u.LoginName, passwd, source.Id, source.Cfg.(*LDAPConfig), false) |
|
|
|
return LoginUserLdapSource(u, u.LoginName, passwd, source.ID, source.Cfg.(*LDAPConfig), false) |
|
|
|
case SMTP: |
|
|
|
case SMTP: |
|
|
|
return LoginUserSMTPSource(u, u.LoginName, passwd, source.Id, source.Cfg.(*SMTPConfig), false) |
|
|
|
return LoginUserSMTPSource(u, u.LoginName, passwd, source.ID, source.Cfg.(*SMTPConfig), false) |
|
|
|
case PAM: |
|
|
|
case PAM: |
|
|
|
return LoginUserPAMSource(u, u.LoginName, passwd, source.Id, source.Cfg.(*PAMConfig), false) |
|
|
|
return LoginUserPAMSource(u, u.LoginName, passwd, source.ID, source.Cfg.(*PAMConfig), false) |
|
|
|
} |
|
|
|
} |
|
|
|
return nil, ErrUnsupportedLoginType |
|
|
|
return nil, ErrUnsupportedLoginType |
|
|
|
} |
|
|
|
} |
|
|
@ -311,14 +311,17 @@ func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) { |
|
|
|
return nil, nil |
|
|
|
return nil, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
const ( |
|
|
|
SMTP_PLAIN = "PLAIN" |
|
|
|
SMTP_PLAIN = "PLAIN" |
|
|
|
SMTP_LOGIN = "LOGIN" |
|
|
|
SMTP_LOGIN = "LOGIN" |
|
|
|
SMTPAuths = []string{SMTP_PLAIN, SMTP_LOGIN} |
|
|
|
|
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
func SmtpAuth(host string, port int, a smtp.Auth, useTls bool) error { |
|
|
|
var ( |
|
|
|
c, err := smtp.Dial(fmt.Sprintf("%s:%d", host, port)) |
|
|
|
SMTPAuths = []string{SMTP_PLAIN, SMTP_LOGIN} |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func SMTPAuth(a smtp.Auth, cfg *SMTPConfig) error { |
|
|
|
|
|
|
|
c, err := smtp.Dial(fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
@ -328,10 +331,12 @@ func SmtpAuth(host string, port int, a smtp.Auth, useTls bool) error { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if useTls { |
|
|
|
if cfg.TLS { |
|
|
|
if ok, _ := c.Extension("STARTTLS"); ok { |
|
|
|
if ok, _ := c.Extension("STARTTLS"); ok { |
|
|
|
config := &tls.Config{ServerName: host} |
|
|
|
if err = c.StartTLS(&tls.Config{ |
|
|
|
if err = c.StartTLS(config); err != nil { |
|
|
|
InsecureSkipVerify: cfg.SkipVerify, |
|
|
|
|
|
|
|
ServerName: cfg.Host, |
|
|
|
|
|
|
|
}); err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -361,7 +366,7 @@ func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTP |
|
|
|
return nil, errors.New("Unsupported SMTP auth type") |
|
|
|
return nil, errors.New("Unsupported SMTP auth type") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if err := SmtpAuth(cfg.Host, cfg.Port, auth, cfg.TLS); err != nil { |
|
|
|
if err := SMTPAuth(auth, cfg); err != nil { |
|
|
|
if strings.Contains(err.Error(), "Username and Password not accepted") { |
|
|
|
if strings.Contains(err.Error(), "Username and Password not accepted") { |
|
|
|
return nil, ErrUserNotExist{u.Id, u.Name} |
|
|
|
return nil, ErrUserNotExist{u.Id, u.Name} |
|
|
|
} |
|
|
|
} |
|
|
|