1
0
mirror of https://github.com/fumiama/go-nd-portal.git synced 2026-06-12 12:30:24 +08:00
Files
go-nd-portal/portal/portal.go
源文雨 7c9d2e2901 drop fb
2022-11-26 16:38:43 +08:00

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)
}