mirror of
https://github.com/fumiama/go-nd-portal.git
synced 2026-06-12 12:30:24 +08:00
105 lines
2.4 KiB
Go
105 lines
2.4 KiB
Go
package portal
|
|
|
|
import (
|
|
"crypto/hmac"
|
|
"crypto/md5"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"net/url"
|
|
"time"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"github.com/fumiama/go-nd-portal/helper"
|
|
)
|
|
|
|
var (
|
|
ErrIllegalIPv4 = errors.New("illegal ipv4")
|
|
ErrUnexpectedChallengeResponse = errors.New("unexpected challenge response")
|
|
ErrUnexpectedLoginResponse = errors.New("unexpected login response")
|
|
)
|
|
|
|
type Portal struct {
|
|
nam string
|
|
pwd string
|
|
ip net.IP
|
|
}
|
|
|
|
type rsp struct {
|
|
Challenge string `json:"challenge"`
|
|
Error string `json:"error"`
|
|
}
|
|
|
|
func NewPortal(name, password string, ipv4 net.IP) (*Portal, error) {
|
|
if len(ipv4) != 4 {
|
|
return nil, ErrIllegalIPv4
|
|
}
|
|
return &Portal{
|
|
nam: name,
|
|
pwd: password,
|
|
ip: ipv4,
|
|
}, nil
|
|
}
|
|
|
|
func (p *Portal) GetChallenge() (string, error) {
|
|
u := fmt.Sprintf(PortalGetChallenge, "gondportal", url.QueryEscape(p.nam), p.ip, time.Now().UnixMilli())
|
|
logrus.Debugln("GET", u)
|
|
data, err := requestDataWith(u, "GET", PortalHeaderUA)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
logrus.Debugln("get challenge resp:", helper.BytesToString(data))
|
|
if len(data) < 12 {
|
|
return "", ErrUnexpectedChallengeResponse
|
|
}
|
|
var r rsp
|
|
err = json.Unmarshal(data[11:len(data)-1], &r)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if r.Error != "ok" {
|
|
return "", errors.New(r.Error)
|
|
}
|
|
logrus.Debugln("get challenge:", r.Challenge)
|
|
return r.Challenge, nil
|
|
}
|
|
|
|
func (p *Portal) PasswordHMd5(challenge string) string {
|
|
var buf [16]byte
|
|
h := hmac.New(md5.New, helper.StringToBytes(challenge))
|
|
_, _ = h.Write(helper.StringToBytes(p.pwd))
|
|
return hex.EncodeToString(h.Sum(buf[:0]))
|
|
}
|
|
|
|
func (p *Portal) Login(challenge string) error {
|
|
info := EncodeUserInfo(p.String(), challenge)
|
|
hmd5 := p.PasswordHMd5(challenge)
|
|
u := fmt.Sprintf(PortalLogin, "gondportal", url.QueryEscape(p.nam), hmd5, p.ip, p.CheckSum(challenge, hmd5, info), url.QueryEscape(info), time.Now().UnixMilli())
|
|
logrus.Debugln("GET", u)
|
|
data, err := requestDataWith(u, "GET", PortalHeaderUA)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
logrus.Debugln("get login resp:", helper.BytesToString(data))
|
|
if len(data) < 12 {
|
|
return ErrUnexpectedLoginResponse
|
|
}
|
|
var r rsp
|
|
err = json.Unmarshal(data[11:len(data)-1], &r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
logrus.Debugln("login rsp:", &r)
|
|
if r.Error != "ok" {
|
|
return errors.New(r.Error)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *Portal) String() string {
|
|
return fmt.Sprintf(PortalUserInfo, p.nam, p.pwd, p.ip)
|
|
}
|