1
0
mirror of https://github.com/fumiama/go-nd-portal.git synced 2026-06-22 03:20:23 +08:00
Files
go-nd-portal/portal.go
源文雨 8743bf9b5d init
2022-11-26 00:39:38 +08:00

104 lines
2.1 KiB
Go

package gondportal
import (
"crypto/hmac"
"crypto/md5"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"net"
"time"
"github.com/FloatTech/floatbox/web"
)
var (
ErrIllegalIPv4 = errors.New("illegal ipv4")
ErrUnexpectedChallengeResponse = errors.New("unexpected challenge response")
)
type Portal struct {
nam string
pwd string
ip net.IP
}
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) {
data, err := web.RequestDataWith(
web.NewDefaultClient(),
fmt.Sprintf(PortalGetChallenge, "gondportal", p.nam, p.ip, time.Now().UnixMilli()),
"GET", "", PortalHeaderUA,
)
if err != nil {
return "", err
}
if len(data) < 12 {
return "", ErrUnexpectedChallengeResponse
}
type rsp struct {
Challenge string `json:"challenge"`
Ecode int `json:"ecode"`
Msg string `json:"error_msg"`
}
var r rsp
err = json.Unmarshal(data[11:len(data)-1], &r)
if err != nil {
return "", err
}
if r.Ecode != 0 {
return "", errors.New(r.Msg)
}
return r.Challenge, nil
}
func (p *Portal) PasswordHMd5(challenge string) string {
var buf [16]byte
h := hmac.New(md5.New, StringToBytes(challenge))
_, _ = h.Write(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)
data, err := web.RequestDataWith(
web.NewDefaultClient(),
fmt.Sprintf(PortalLogin, "gondportal", p.nam, hmd5, p.ip, p.CheckSum(challenge, hmd5, info), info, time.Now().UnixMilli()),
"GET", "", PortalHeaderUA,
)
if err != nil {
return err
}
if len(data) < 12 {
return ErrUnexpectedChallengeResponse
}
type rsp struct {
Error string `json:"error"`
}
var r rsp
err = json.Unmarshal(data[11:len(data)-1], &r)
if err != nil {
return err
}
if r.Error == "ok" {
return nil
}
return errors.New(r.Error)
}
func (p *Portal) String() string {
return fmt.Sprintf(PortalUserInfo, p.nam, p.pwd, p.ip)
}