Pārlūkot izejas kodu

add smtp authentication

tags/v0.9.99
Lunny Xiao pirms 10 gadiem
vecāks
revīzija
b33f255c40
1 mainītis faili ar 125 papildinājumiem un 4 dzēšanām
  1. 125
    4
      models/login.go

+ 125
- 4
models/login.go Parādīt failu

@@ -7,6 +7,8 @@ package models
import (
"encoding/json"
"errors"
"fmt"
"net/smtp"
"strings"
"time"

@@ -50,6 +52,22 @@ func (cfg *LDAPConfig) ToDB() ([]byte, error) {
return json.Marshal(cfg.Ldapsource)
}

type SMTPConfig struct {
Auth string
Host string
Post string
TLS bool
}

// implement
func (cfg *SMTPConfig) FromDB(bs []byte) error {
return json.Unmarshal(bs, cfg)
}

func (cfg *SMTPConfig) ToDB() ([]byte, error) {
return json.Marshal(cfg)
}

type LoginSource struct {
Id int64
Type int
@@ -69,6 +87,10 @@ func (source *LoginSource) LDAP() *LDAPConfig {
return source.Cfg.(*LDAPConfig)
}

func (source *LoginSource) SMTP() *SMTPConfig {
return source.Cfg.(*SMTPConfig)
}

// for xorm callback
func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) {
if colName == "type" {
@@ -76,6 +98,8 @@ func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) {
switch ty {
case LT_LDAP:
source.Cfg = new(LDAPConfig)
case LT_SMTP:
source.Cfg = new(SMTPConfig)
}
}
}
@@ -172,10 +196,19 @@ func LoginUser(uname, passwd string) (*User, error) {
}

for _, source := range sources {
u, err := LoginUserLdapSource(nil, u.LoginName, passwd,
source.Id, source.Cfg.(*LDAPConfig), true)
if err == nil {
return u, err
if source.Type == LT_LDAP {
u, err := LoginUserLdapSource(nil, u.LoginName, passwd,
source.Id, source.Cfg.(*LDAPConfig), true)
if err == nil {
return u, err
}
} else if source.Type == LT_SMTP {
u, err := LoginUserSMTPSource(nil, u.LoginName, passwd,
source.Id, source.Cfg.(*SMTPConfig), true)

if err == nil {
return u, err
}
}
}

@@ -200,6 +233,8 @@ func LoginUser(uname, passwd string) (*User, error) {
return LoginUserLdapSource(u, u.LoginName, passwd,
source.Id, source.Cfg.(*LDAPConfig), false)
case LT_SMTP:
return LoginUserSMTPSource(u, u.LoginName, passwd,
source.Id, source.Cfg.(*SMTPConfig), false)
}
return nil, ErrUnsupportedLoginType
}
@@ -232,3 +267,89 @@ func LoginUserLdapSource(user *User, name, passwd string, sourceId int64, cfg *L

return RegisterUser(user)
}

type loginAuth struct {
username, password string
}

func LoginAuth(username, password string) smtp.Auth {
return &loginAuth{username, password}
}

func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
return "LOGIN", []byte(a.username), nil
}

func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
if more {
switch string(fromServer) {
case "Username:":
return []byte(a.username), nil
case "Password:":
return []byte(a.password), nil
}
}
return nil, nil
}

var (
smtpAuths = []string{"plain", "login", ""}
)

func SmtpAuth(addr string, a smtp.Auth) error {
c, err := smtp.Dial(addr)
if err != nil {
return err
}
defer c.Close()

if ok, _ := c.Extension("STARTTLS"); ok {
if err = c.StartTLS(nil); err != nil {
return err
}
}

if ok, _ := c.Extension("AUTH"); ok {
if err = c.Auth(a); err != nil {
return err
}
return nil
} else {
return ErrUnsupportedLoginType
}
}

// Query if name/passwd can login against the LDAP direcotry pool
// Create a local user if success
// Return the same LoginUserPlain semantic
func LoginUserSMTPSource(user *User, name, passwd string, sourceId int64, cfg *SMTPConfig, autoRegister bool) (*User, error) {
var auth smtp.Auth
if cfg.Auth == "plain" {
auth = smtp.PlainAuth("", name, passwd, cfg.Host)
} else if cfg.Auth == "login" {
auth = LoginAuth(name, passwd)
}

err := SmtpAuth(fmt.Sprintf("%s:%d", cfg.Host, cfg.Post), auth)
if err != nil {
return nil, err
}

if !autoRegister {
return user, nil
}

// fake a local user creation
user = &User{
LowerName: strings.ToLower(name),
Name: strings.ToLower(name),
LoginType: LT_SMTP,
LoginSource: sourceId,
LoginName: name,
IsActive: true,
Passwd: passwd,
Email: name,
}

return RegisterUser(user)
}

Notiek ielāde…
Atcelt
Saglabāt