Skip to content

Commit 20e1f68

Browse files
committed
ipn/yegor: use did token if any
1 parent b3df75e commit 20e1f68

1 file changed

Lines changed: 61 additions & 7 deletions

File tree

intra/ipn/rpn/yegor.go

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ const (
3333
svchosttest = "redir.nile.workers.dev"
3434
wsMyIp = "https://checkip.windscribe.com/"
3535
wsMyIp2 = "https://checkip.totallyacdn.com/"
36+
// didTokenHeader is the HTTP response/request header for a device-id token
37+
// issued by svchost / svchosttest. Format: "a hextoken:expiryepochsec".
38+
didTokenHeader = "x-rethink-app-did-token"
3639
)
3740

3841
const (
@@ -711,6 +714,9 @@ type WsEntitlement struct {
711714
AccStatus string `json:"status"` // "valid" | "invalid" | "banned" | "expired" | "unknown"
712715
AllowCrossDevice bool `json:"allowRestore"` // true if this entitlement can be restored
713716
TestDomain bool `json:"test"` // true if this is a test entitlement
717+
// DidToken is the device-id token (x-rethink-app-did-token) issued by svchost,
718+
// format "a hextoken:expiryepochsec".
719+
DidToken string `json:"didtoken,omitempty"`
714720
}
715721

716722
var _ x.RpnAcc = (*WsClient)(nil)
@@ -1051,6 +1057,45 @@ func authHeader(req *http.Request, t string) {
10511057
req.Header.Set("Authorization", "Bearer "+t)
10521058
}
10531059

1060+
// didHeader sets the didTokenHeader request header if tok is non-empty.
1061+
func didHeader(req *http.Request, tok string) {
1062+
if req != nil && len(tok) > 0 {
1063+
req.Header.Set(didTokenHeader, tok)
1064+
}
1065+
}
1066+
1067+
func logDidToken(tok string) {
1068+
if len(tok) <= 0 {
1069+
log.W("ws: didtoken: empty token")
1070+
return
1071+
}
1072+
// token format is "a hextoken:expiryepochsec"; parse the epoch to log expiry.
1073+
parts := strings.SplitN(tok, ":", 2)
1074+
if len(parts) < 2 {
1075+
log.W("ws: didtoken: unknown format")
1076+
return
1077+
}
1078+
expSec, err := strconv.ParseInt(strings.TrimSpace(parts[1]), 10, 64)
1079+
if err != nil {
1080+
log.E("ws: didtoken: cannot parse expiry epoch: %v", err)
1081+
}
1082+
expTime := time.Unix(expSec, 0)
1083+
log.I("ws: didtoken: expiry %s; expired? %t", fmtTime(expTime), expTime.Before(time.Now()))
1084+
}
1085+
1086+
// updateDidTokenIfNeeded reads didTokenHeader from the response, logs its expiry,
1087+
// and – when it differs from ent.DidToken – overwrites it in ent.
1088+
func updateDidTokenIfNeeded(ent *WsEntitlement, res *http.Response) {
1089+
if ent == nil || res == nil {
1090+
return
1091+
}
1092+
incoming := res.Header.Get(didTokenHeader)
1093+
logDidToken(incoming)
1094+
if len(incoming) > 0 && ent.DidToken != incoming {
1095+
ent.DidToken = incoming
1096+
}
1097+
}
1098+
10541099
func wsErr(res *http.Response, op string) error {
10551100
_, err := wsErr2(res, op)
10561101
return err
@@ -1099,7 +1144,11 @@ func wsRes[T any](res *http.Response, out *T, op string) (*T, error) {
10991144
return out, nil
11001145
}
11011146

1102-
func getSession(h *http.Client, cid, did, tok string, test bool) (*WsSession, error) {
1147+
func getSession(h *http.Client, ent *WsEntitlement) (*WsSession, error) {
1148+
if ent == nil {
1149+
return nil, errWsNoSession
1150+
}
1151+
tok := ent.SessionToken
11031152
if len(tok) <= 0 {
11041153
return nil, errWsNoToken
11051154
}
@@ -1108,12 +1157,13 @@ func getSession(h *http.Client, cid, did, tok string, test bool) (*WsSession, er
11081157
curl -x GET '.../Session'
11091158
-H 'Authorization: Bearer id:typ:epochsec:sig1:sig2'
11101159
*/
1111-
u := baseurl(test, cid, did).JoinPath(wssessionpath)
1160+
u := baseurl(ent.TestDomain, ent.Cid, ent.Did).JoinPath(wssessionpath)
11121161
req, err := http.NewRequest("GET", u.String(), nil)
11131162
if err != nil {
11141163
return nil, log.EE("ws: getsess: make req err: %v", err)
11151164
}
11161165
authHeader(req, tok)
1166+
didHeader(req, ent.DidToken)
11171167

11181168
if settings.Debug {
11191169
log.V("ws: getsess: req: %s tok %s", u.String(), tokst)
@@ -1124,6 +1174,7 @@ func getSession(h *http.Client, cid, did, tok string, test bool) (*WsSession, er
11241174
return nil, log.EE("ws: getsess: res err (nil? %t / tok? %s): %v", res == nil, tokst, err)
11251175
}
11261176
defer core.Close(res.Body)
1177+
updateDidTokenIfNeeded(ent, res)
11271178
if res.StatusCode != http.StatusOK {
11281179
return nil, wsErr(res, "getsess/"+tokst)
11291180
}
@@ -1313,6 +1364,7 @@ func getServerList(h *http.Client, sess *WsSession, ent *WsEntitlement) (*WsServ
13131364
if err != nil {
13141365
return nil, log.EE("ws: wgconfs: req err: %v", err)
13151366
}
1367+
didHeader(locreq, ent.DidToken)
13161368

13171369
if settings.Debug {
13181370
log.V("ws: wgconfs: req: %s tok %s", u.String(), tokenState(bearer))
@@ -1324,6 +1376,7 @@ func getServerList(h *http.Client, sess *WsSession, ent *WsEntitlement) (*WsServ
13241376
}
13251377

13261378
defer core.Close(locres.Body)
1379+
updateDidTokenIfNeeded(ent, locres)
13271380
if locres.StatusCode != http.StatusOK {
13281381
return nil, wsErr(locres, "wgconfs")
13291382
}
@@ -1399,6 +1452,7 @@ initagain:
13991452
}
14001453
initreq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
14011454
authHeader(initreq, bearer)
1455+
didHeader(initreq, ent.DidToken)
14021456

14031457
if settings.Debug {
14041458
log.V("ws: wgconfs: init req: %s; tok %s; force %s", u.String(), tokst, force)
@@ -1409,6 +1463,7 @@ initagain:
14091463
if err != nil || initres == nil {
14101464
return nil, nil, log.EE("ws: wgconfs: res err (nil? %t / tok? %s): %v", initres == nil, tokst, err)
14111465
}
1466+
updateDidTokenIfNeeded(ent, initres)
14121467

14131468
if initres.StatusCode != http.StatusOK {
14141469
wserr, err := wsErr2(initres, "wsinit")
@@ -1478,6 +1533,7 @@ initagain:
14781533
}
14791534
creq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
14801535
authHeader(creq, sess.SessionToken)
1536+
didHeader(creq, ent.DidToken)
14811537

14821538
if settings.Debug {
14831539
log.V("ws: wgconfs: connect req: %s tok %s", u.String(), tokst)
@@ -1487,6 +1543,7 @@ initagain:
14871543
if err != nil || cres == nil {
14881544
return nil, nil, log.EE("ws: wgconfs: connect res err (nil? %t / tok? %s): %v", cres == nil, tokst, err)
14891545
}
1546+
updateDidTokenIfNeeded(ent, cres)
14901547
if cres.StatusCode != http.StatusOK {
14911548
wserr, err := wsErr2(cres, "wsconnect")
14921549
core.Close(cres.Body)
@@ -1587,7 +1644,7 @@ func makeWsWg(h *http.Client, ent *WsEntitlement) (*WsClient, error) {
15871644
return nil, errWsNoEntitlement
15881645
}
15891646

1590-
sess, err := getSession(h, ent.Cid, ent.Did, ent.SessionToken, ent.TestDomain)
1647+
sess, err := getSession(h, ent)
15911648
if err != nil {
15921649
return nil, err
15931650
}
@@ -1684,17 +1741,14 @@ func makeWsWgFrom(h *http.Client, existingConf *WsWgConfig, errOnNoUpdate bool)
16841741
return
16851742
}
16861743

1687-
cid := existingEnt.Cid
1688-
did := existingEnt.Did
16891744
tokst := existingConf.tokenState()
16901745
existingToken := existingSess.SessionToken
16911746
existingLocHash := existingSess.LocHash
1692-
existingTestDomain := existingEnt.TestDomain
16931747
if existingEnt.SessionToken != existingToken {
16941748
log.W("ws: make: entitlement does not match session; tok? %s", tokst)
16951749
}
16961750

1697-
newSess, err := getSession(h, cid, did, existingToken, existingTestDomain)
1751+
newSess, err := getSession(h, existingEnt)
16981752
if err == nil {
16991753
existingConf.Session = newSess // update session with the latest info
17001754
refreshedSess = true

0 commit comments

Comments
 (0)