Skip to content
This repository has been archived by the owner on Jul 30, 2024. It is now read-only.

Commit

Permalink
Merge pull request #30 from TommyIX/main
Browse files Browse the repository at this point in the history
Add Basic TOTP Authentication
  • Loading branch information
lyc8503 authored Jan 28, 2023
2 parents 7a1dc42 + 81319fd commit 7ff2625
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 2 deletions.
13 changes: 13 additions & 0 deletions core/EasyConnectClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,19 @@ func (client *EasyConnectClient) AuthSMSCode(code string) ([]byte, error) {
return client.LoginByTwfId(twfId)
}

func (client *EasyConnectClient) AuthTOTP(code string) ([]byte, error) {
if client.twfId == "" {
return nil, errors.New("TOTP Auth not required")
}

twfId, err := TOTPAuth(client.server, client.username, client.password, client.twfId, code)
if err != nil {
return nil, err
}

return client.LoginByTwfId(twfId)
}

func (client *EasyConnectClient) LoginByTwfId(twfId string) ([]byte, error) {
agentToken, err := ECAgentToken(client.server, twfId)
if err != nil {
Expand Down
47 changes: 46 additions & 1 deletion core/web_login.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import (
utls "github.com/refraction-networking/utls"
)

var ERR_NEXT_AUTH_SMS = errors.New("SMS Code required.")
var ERR_NEXT_AUTH_SMS = errors.New("SMS Code required")
var ERR_NEXT_AUTH_TOTP = errors.New("Current user's TOTP bound")

func WebLogin(server string, username string, password string) (string, error) {
server = "https://" + server
Expand Down Expand Up @@ -138,6 +139,12 @@ func WebLogin(server string, username string, password string) (string, error) {
return twfId, ERR_NEXT_AUTH_SMS
}

// TOTP Authnication Process (Edited by JHong)
if strings.Contains(string(buf[:n]), "<NextService>auth/token</NextService>") || strings.Contains(string(buf[:n]), "<NextServiceSubType>totp</NextServiceSubType>") {
log.Print("TOTP Authnication required.")
return twfId, ERR_NEXT_AUTH_TOTP
}

if strings.Contains(string(buf[:n]), "<NextAuth>-1</NextAuth>") || !strings.Contains(string(buf[:n]), "<NextAuth>") {
log.Print("No NextAuth found.")
} else {
Expand Down Expand Up @@ -198,6 +205,44 @@ func AuthSms(server string, username string, password string, twfId string, smsC
return twfId, nil
}

// JHong Implementing.......
func TOTPAuth(server string, username string, password string, twfId string, TOTPCode string) (string, error) {
c := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}}

buf := make([]byte, 40960)

addr := "https://" + server + "/por/login_token.csp"
log.Printf("TOTP token Request: " + addr)
form := url.Values{
"svpn_inputtoken": {TOTPCode},
}

req, err := http.NewRequest("POST", addr, strings.NewReader(form.Encode()))
req.Header.Set("Cookie", "TWFID="+twfId)

resp, err := c.Do(req)
if err != nil {
debug.PrintStack()
return "", err
}

n, _ := resp.Body.Read(buf)
defer resp.Body.Close()

if !strings.Contains(string(buf[:n]), "suc") {
debug.PrintStack()
return "", errors.New("TOTP token verification FAILED: " + string(buf[:n]))
}

twfId = string(regexp.MustCompile(`<TwfID>(.*)</TwfID>`).FindSubmatch(buf[:n])[1])
log.Print("TOTP verification SUCCESS")

return twfId, nil
}

func ECAgentToken(server string, twfId string) (string, error) {
dialConn, err := net.Dial("tcp", server)
defer dialConn.Close()
Expand Down
8 changes: 7 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
func main() {
// CLI args
host, port, username, password, socksBind, twfId := "", 0, "", "", "", ""
flag.StringVar(&host, "server", "", "EasyConnect server address (e.g. vpn.nju.edu.cn)")
flag.StringVar(&host, "server", "", "EasyConnect server address (e.g. vpn.nju.edu.cn, sslvpn.sysu.edu.cn)")
flag.StringVar(&username, "username", "", "Your username")
flag.StringVar(&password, "password", "", "Your password")
flag.StringVar(&socksBind, "socks-bind", ":1080", "The addr socks5 server listens on (e.g. 0.0.0.0:1080)")
Expand Down Expand Up @@ -43,6 +43,12 @@ func main() {
fmt.Scan(&smsCode)

ip, err = client.AuthSMSCode(smsCode)
} else if err == core.ERR_NEXT_AUTH_TOTP {
fmt.Print(">>>Please enter your TOTP Auth code<<<:")
TOTPCode := ""
fmt.Scan(&TOTPCode)

ip, err = client.AuthTOTP(TOTPCode)
}
}

Expand Down

0 comments on commit 7ff2625

Please sign in to comment.