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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
|
// package server defines public types that have to deal with the VPN server
package server
import (
"encoding/json"
"fmt"
"github.com/eduvpn/eduvpn-common/types/cookie"
"github.com/eduvpn/eduvpn-common/types/protocol"
)
// Type gives the type of server
type Type int8
const (
// TypeUnknown means the server is unknown
TypeUnknown Type = iota
// TypeInstituteAccess means the server is of type Institute Access
TypeInstituteAccess
// TypeSecureInternet means the server is of type Secure Internet
TypeSecureInternet
// TypeCustom means the server is of type Custom Server
TypeCustom
)
// This is here to support V1 configs which had the server type as a string
func (t *Type) UnmarshalJSON(data []byte) error {
// First try to just unmarshal the type
var num int8
if err := json.Unmarshal(data, &num); err == nil {
if num < int8(TypeUnknown) || num > int8(TypeCustom) {
return fmt.Errorf("invalid server type: %d", num)
}
*t = Type(num)
return nil
}
// unmarshal the old way, as a string
var str string
if err := json.Unmarshal(data, &str); err != nil {
return err
}
switch str {
case "secure_internet":
*t = TypeSecureInternet
case "institute_access":
*t = TypeInstituteAccess
case "custom_server":
*t = TypeCustom
default:
return fmt.Errorf("invalid server type: %s", str)
}
return nil
}
// RequiredAskTransition represents the data that is sent when a transition is required to be handled and the go library needs data from the client
// This data can be a profile selection or secure internet location selection
type RequiredAskTransition struct {
// C is the cookie which is needed for replying to the library, see CookieReply in exports/exports.go
// If this cookie is omitted, it is a protocol error
C *cookie.Cookie `json:"cookie,omitempty"`
// Data is the data associated to the transition, e.g. the list of profiles (Profiles struct)
// or the list of secure internet locations ([]string)
Data interface{} `json:"data"`
}
// Expiry is the struct that gives the time at which certain expiry elements should be shown
type Expiry struct {
// StartTime is the start time of the VPN in Unix
StartTime int64 `json:"start_time"`
// EndTime is the end time of the VPN in Unix.
EndTime int64 `json:"end_time"`
// ButtonTime is the Unix time at which to start showing the renew button in the UI
ButtonTime int64 `json:"button_time"`
// CountdownTime is the Unix time at which to start showing more detailed countdown timer.
// E.g. first start with days (7 days left), and when the current time is after this time, show e.g. 9 minutes and 59 seconds
CountdownTime int64 `json:"countdown_time"`
// NotificationTimes is the slice/list of times at which to show a notification that the VPN is about to expire
NotificationTimes []int64 `json:"notification_times"`
}
// Profile is the profile for the VPN, to show in the UI where the user can switch to it to get a different VPN configuration
type Profile struct {
// DisplayName is the display name of the profile as a map
// It is a map where country codes are mapped to names, this is to be consistent with the format of other display names
// E.g. {"en": "Default Profile"}
// If this is empty, the field is omitted from the JSON
DisplayName map[string]string `json:"display_name,omitempty"`
}
// Profiles is the map of profiles with the current defined
type Profiles struct {
// Map, the map of profiles from profile ID to the profile contents
// If this is empty, the field is omitted from the JSON
// Note that it can be empty if the profiles have not been initialized
// This could happen if a config is not obtained yet
Map map[string]Profile `json:"map,omitempty"`
// Current is the current profile ID that is defined
Current string `json:"current"`
}
// Tokens are the OAuth tokens for the server
type Tokens struct {
// Access is the access token
Access string `json:"access_token"`
// Refresh is the refresh token
Refresh string `json:"refresh_token"`
// Expires is the Unix timestamp when the token expires
Expires int64 `json:"expires_at"`
}
// Server is the basic type for a server. This is the base for secure internet and institute access. Custom servers are equal to this type
type Server struct {
// DisplayName is the map from language tags to display name. If this is empty, the field is omitted from the JSON
DisplayName map[string]string `json:"display_name,omitempty"`
// Identifier is the Base URL for Institute Access and Custom Server. For Secure Internet this is the organization ID
// This identifier should be passed to the Go library for e.g. getting a config
Identifier string `json:"identifier"`
// Profiles is the profiles that this server has defined
// It could be that this is empty if the library has not discovered the profiles just yet
Profiles Profiles `json:"profiles"`
}
// Institute defines an institute access server
type Institute struct {
// Server is the embedded server struct
Server
// SupportContacts are the list of support contacts
SupportContacts []string `json:"support_contacts,omitempty"`
// Delisted is a boolean that indicates whether or not this server is delisted from discovery
// If it is, the UI should show a warning symbol or move the server to a new category, which is up to the client
Delisted bool `json:"delisted"`
}
// SecureInternet is a secure internet server
type SecureInternet struct {
// Server is the embedded server struct
Server
// CountryCode is the country code of the currently configured location, e.g. "nl"
CountryCode string `json:"country_code"`
// Locations is the list of available secure internet locations
Locations []string `json:"locations,omitempty"`
// SupportContacts are the list of support contacts
SupportContacts []string `json:"support_contacts,omitempty"`
// Delisted is a boolean that indicates whether or not this server is delisted from discovery
// If it is, the UI should show a warning symbol or move the server to a new category, which is up to the client
Delisted bool `json:"delisted"`
}
// List is the list of servers
type List struct {
// Institutes is the list/slice of institute access servers. If none are defined, this is omitted in the JSON
Institutes []Institute `json:"institute_access_servers,omitempty"`
// Secure Internet is the secure internet server if any. If none is there, it is omitted in the JSON
SecureInternet *SecureInternet `json:"secure_internet_server,omitempty"`
// Custom is the list/slice of custom servers. If none are defined, this is omitted in the JSON
Custom []Server `json:"custom_servers,omitempty"`
}
// Proxy defines the structure with the arguments that should be passed to start proxyguard
type Proxy struct {
// SourcePort is the source port for the client TCP connection
SourcePort int `json:"source_port"`
// Listen is the ip:port for the client UDP connection, this is the value that is replaced in the config
Listen string `json:"listen"`
// Peer is the ip:port of the upstream server
Peer string `json:"peer"`
}
// Configuration is the configuration that you get back when you call the get config function
type Configuration struct {
// VPNConfig is the VPN Configuration, a WireGuard or OpenVPN Configuration
// In case of OpenVPN, we append "script-security 0" to disable scripts from being run by default.
// A client may override this, e.g. for, very trusted, pre-provisioned VPNs
VPNConfig string `json:"config"`
// Protocol defines which protocol the configuration is for, OpenVPN or WireGuard
Protocol protocol.Protocol `json:"protocol"`
// DefaultGateway is a boolean that indicates whether or not this configuration should be configured as a default gateway
DefaultGateway bool `json:"default_gateway"`
// DNSSearchDomains are the list of dns search domains
DNSSearchDomains []string `json:"dns_search_domains,omitempty"`
// ShouldFailover returns whether or not the client should attempt to failover
ShouldFailover bool `json:"should_failover"`
// Proxy returns information for proxied VPN connections
// If this is non-nil a proxy must be started using StartProxyguard
Proxy *Proxy `json:"proxy,omitempty"`
}
// Current is the struct that defines the current server
// It has different fields where only two are always filled in
type Current struct {
// The following three are mutually exclusive
// Institute is the institute access server if any, if none is there this field is omitted in the JSON
Institute *Institute `json:"institute_access_server,omitempty"`
// Secure Internet is the secure internet server if any, if none is there this field is omitted in the JSON
SecureInternet *SecureInternet `json:"secure_internet_server,omitempty"`
// Custom is the custom server if any, if none is there this field is omitted in the JSON
Custom *Server `json:"custom_server,omitempty"`
// Type is the type of server that is there to check which of the three types should be non-nil
Type Type `json:"server_type"`
}
|