-
Notifications
You must be signed in to change notification settings - Fork 1
/
auth.go
150 lines (124 loc) · 3.06 KB
/
auth.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package main
import (
"bytes"
"crypto/rand"
"crypto/rsa"
"encoding/hex"
"encoding/json"
"errors"
"io"
"math/big"
"net/http"
"strings"
)
// Authenticate Function to make authentication request
func (client *Client) Authenticate(username, encryptedPassword string) error {
// Get Request
req, err := prepareAuthRequest(username, encryptedPassword, client.BaseAPIURL)
if err != nil {
return err
}
// Close Request
defer req.Body.Close()
// Make Authentication
resp, err := client.Client.Do(req)
if err != nil {
return err
}
// Close Response
defer resp.Body.Close()
// Read Response Body
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
// Convert JSON response to struct
authResponse := &SangforAuthResponse{}
err = json.Unmarshal(respBody, authResponse)
if err != nil {
return err
}
// Check Token
if authResponse.Data.Access.Token.ID != "" {
// Set Token
client.Token = authResponse.Data.Access.Token.ID
return nil
}
return errors.New("token is not available")
}
// GetPublicKey Gets Sangfor API Public Key
func GetPublicKey(client *Client) (string, error) {
// Get Public Key
resp, err := client.Client.Get(client.BaseAPIURL + "/public-key")
if err != nil {
return "", err
}
// Close Response
defer resp.Body.Close()
// Check Response Code
if resp.StatusCode != 200 {
return "", errors.New(resp.Status)
}
// Read Response Body
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
// Convert JSON Response to Struct
sangforPK := &SangforPK{}
err = json.Unmarshal(respBody, sangforPK)
if err != nil {
return "", err
}
return sangforPK.Data.PublicKey, nil
}
// GetEncryptedPassword Gets Sangfor Encrypted Password
func GetEncryptedPassword(password, publicKey string) (string, error) {
// Get Properties
N := strings.TrimSuffix(publicKey, "\n")
E := 65537
// Convert Public Key
bigN := new(big.Int)
_, ok := bigN.SetString(N, 16)
if !ok {
return "", errors.New("can not convert public key")
}
// Get Public Key
pub := rsa.PublicKey{
N: bigN,
E: E,
}
// Encrypt Password
cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, &pub, []byte(password))
if err != nil {
return "", err
}
// Encode Encrypted Password
return hex.EncodeToString(cipherText), nil
}
func prepareAuthRequest(uname, encpass, baseurl string) (*http.Request, error) {
// Create Auth Body
authRequest := SangforAuthReq{}
authRequest.Auth.PasswordCredentials.Username = uname
authRequest.Auth.PasswordCredentials.Password = encpass
// Convert Struct to JSON Data
reqBody, err := json.Marshal(authRequest)
if err != nil {
return nil, err
}
// Create Request for Authentication
req, err := http.NewRequest("POST", baseurl+"/authenticate", bytes.NewReader(reqBody))
if err != nil {
return nil, err
}
// Set Request Headers
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Cookie", "aCMPAuthToken="+getUUID())
return req, nil
}
// SangforPK represents Sangfor Public Key Format
type SangforPK struct {
Data struct {
PublicKey string `json:"public_key"`
} `json:"data"`
}