-
Notifications
You must be signed in to change notification settings - Fork 1
/
portal.go
104 lines (93 loc) · 2.4 KB
/
portal.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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(u string) (string, error) {
u = fmt.Sprintf(u, "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(u, domain, challenge string) error {
info := EncodeUserInfo(p.String(), challenge)
hmd5 := p.PasswordHMd5(challenge)
u = fmt.Sprintf(u, "gondportal", url.QueryEscape(p.nam), hmd5, p.ip, p.CheckSum(domain, 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)
}