parent
f975a19f65
commit
274e824630
10
ldap.go
10
ldap.go
|
@ -21,11 +21,12 @@ type ldapConfig struct {
|
|||
primaryAttribute string
|
||||
secondaryAttribute string
|
||||
validGroups []string
|
||||
otpType string
|
||||
mfaType string
|
||||
certAuth string
|
||||
ipMin net.IP
|
||||
ipMax net.IP
|
||||
upgradeFrom string
|
||||
routes []string
|
||||
}
|
||||
|
||||
func (l *ldapConfig) addIPRange(s string) error {
|
||||
|
@ -69,11 +70,12 @@ func (conf *ldapConfig) Auth(logins []string, pass string) (e error, userOk, pas
|
|||
}
|
||||
}
|
||||
|
||||
if len(logins) != 1 {
|
||||
return errors.New("invalid login"), false, false, nil
|
||||
// no server ldap or multiple login should not happen here
|
||||
if len(logins) != 1 || len(conf.servers) == 0 {
|
||||
return nil, false, false, nil
|
||||
}
|
||||
attributes = logins
|
||||
|
||||
attributes = logins
|
||||
for _, s := range conf.servers {
|
||||
// we force ldaps because we can
|
||||
l, err := myDialTLS("tcp", s+":636", &tls.Config{ServerName: s})
|
||||
|
|
5
main.go
5
main.go
|
@ -31,8 +31,6 @@ func main() {
|
|||
server.CcPwnPassword = config.GetString("config.ccPwnPassword", "")
|
||||
server.pwnTemplate = config.GetString("config.pwnTemplate", "")
|
||||
server.newAsTemplate = config.GetString("config.newAsTemplate", "")
|
||||
server.slackTemplate = config.GetString("config.slackTemplate", "")
|
||||
server.slackTemplate2 = config.GetString("config.slackTemplate2", "")
|
||||
server.cacheDir = config.GetString("config.cacheDir", "")
|
||||
server.authCa = config.GetString("config.authCa", "")
|
||||
server.otpMasterSecrets = parseConfigArray(config, "config.masterSecrets")
|
||||
|
@ -62,7 +60,8 @@ func main() {
|
|||
primaryAttribute: config.GetString(profile+".primaryAttribute", ""),
|
||||
secondaryAttribute: config.GetString(profile+".secondaryAttribute", ""),
|
||||
validGroups: parseConfigArray(config, profile+".validGroups"),
|
||||
otpType: config.GetString(profile+".otp", ""),
|
||||
routes: parseConfigArray(config, profile+".routes"),
|
||||
mfaType: config.GetString(profile+".mfa", ""),
|
||||
certAuth: config.GetString(profile+".cert", "optionnal"),
|
||||
upgradeFrom: config.GetString(profile+".upgradeFrom", ""),
|
||||
}
|
||||
|
|
11
notes.txt
11
notes.txt
|
@ -1,11 +0,0 @@
|
|||
|
||||
|
||||
client-deny 0 0 "Need OTP" "CRV1:R:blabla:ZXVjbGlkZQ==:OTP Code "
|
||||
|
||||
|
||||
client-auth 1 0
|
||||
ifconfig-push 10.8.66.3 10.8.66.1
|
||||
push "dhcp-option DNS 10.190.32.2"
|
||||
push "dhcp-option DNS 10.190.32.20"
|
||||
END
|
||||
|
|
@ -15,9 +15,9 @@ config
|
|||
[
|
||||
"CN=SEC_VPN_Users_External,OU=Security,OU=Groups,OU=Dailymotion,DC=office,DC=daily",
|
||||
]
|
||||
otp: "okta"
|
||||
mfa: "okta"
|
||||
cert: "ignore"
|
||||
ip_range: "192.168.207.1 - 192.168.207.254",
|
||||
IPRange: "192.168.207.1 - 192.168.207.254",
|
||||
routes:
|
||||
[
|
||||
"10.189.10.9 255.255.255.255",
|
||||
|
@ -45,10 +45,9 @@ config
|
|||
[
|
||||
"CN=SEC_VPN,OU=Security,OU=Groups,OU=Dailymotion,DC=office,DC=daily",
|
||||
]
|
||||
otp: "okta"
|
||||
mfa: "okta"
|
||||
cert: "optionnal"
|
||||
upgrade-to: "DEV"
|
||||
ip_range: "192.168.201.1 - 192.168.203.254"
|
||||
IPRange: "192.168.201.1-192.168.203.254"
|
||||
}
|
||||
DEV:
|
||||
{
|
||||
|
@ -59,37 +58,41 @@ config
|
|||
searchFilter: "(&(mail=%s))"
|
||||
primaryAttribute: "description"
|
||||
secondaryAttribute: "sshPublicKey"
|
||||
upgrade-from: "CORP"
|
||||
upgrade-to: "ADMINS"
|
||||
otp: "okta"
|
||||
upgradeFrom: "CORP"
|
||||
mfa: ""
|
||||
cert: "optionnal"
|
||||
ip_range: "192.168.204.1 - 192.168.206.254"
|
||||
IPRange: "192.168.204.1-192.168.206.254"
|
||||
routes:
|
||||
[
|
||||
"10.190.32.51 255.255.255.255",
|
||||
]
|
||||
}
|
||||
ADMINS:
|
||||
{
|
||||
validGroups:
|
||||
[
|
||||
"infra",
|
||||
"infra2",
|
||||
"net",
|
||||
"datacenter",
|
||||
]
|
||||
upgrade-from: "DEV"
|
||||
otp: [ "internal", "slack" ]
|
||||
upgradeFrom: "DEV"
|
||||
mfa: "internal"
|
||||
cert: "mandatory"
|
||||
ip_range: "192.168.200.2 - 192.168.200.254"
|
||||
IPRange: "192.168.200.2-192.168.200.254"
|
||||
}
|
||||
}
|
||||
openvpnPort: "127.0.0.1:4000"
|
||||
httpPort: ":8443"
|
||||
httpCa: "/usr/local/share/ca-certificates/Dailymotion.crt"
|
||||
httpKey: "/etc/ssl/private/server-key.pem"
|
||||
httpCert: "/etc/ssl/certs/server-bundle.pem"
|
||||
cacheDir: "/var/run/openvpn/"
|
||||
masterSecrets: [ "*******************************J" ]
|
||||
authCa: "/usr/local/share/ca-certificates/Dailymotion.crt"
|
||||
masterSecrets: [ "********************************"]
|
||||
vpnLogUrl: "https://install.dm.gg/vpn-log.php"
|
||||
slackToken: "*************************************************************************"
|
||||
slackChannels: [ "#squad-it-office" ]
|
||||
configParser: "/etc/openvpn/roadwarrior_([a-zA-Z0-9]*).conf"
|
||||
mailRelay: "mailrelay.dailymotion.com:25"
|
||||
mailFrom: "engineering-infra@dailymotion.com"
|
||||
ccPwnPassword: "security-incident-report@dailymotion.com"
|
||||
pwnTemplate: "Mime-Version: 1.0;\nContent-Type: text/html; charset=\"ISO-8859-1\";\nContent-Transfer-Encoding: 7bit;\nFrom: {{.MailFrom}}\nSubject: [Dailymotion] Your current okta password is compromised\nTo: {{.Mail}}\nCc: {{.CcPwnPassword}}\n\n<html><body>Hello<br>\n<br>\nWe have detected that you recently connected to the dailymotion's corporate VPN with login {{.Login}} and a password which was part a password-related breach - possibly related to your own account on a third party website - and which is now widely known to hackers.<br>\n<br>\nPlease contact the security team and go to the Okta homepage to change your password immediately : <a href=\"https://dailymotion.okta.com\">https://dailymotion.okta.com</a>/<br>\n<br>\nIf you were using the same unsafe password anywhere else, you should change it everywhere and make sure you use a unique password for every service (password managers make this feasible).<br>\n<br>\nWe remind you that you should always keep your passwords strong and strictly unique, especially when it comes to your dailymotion accounts. A robust password can, for example, be generated using an easily remembered phrase and retaining certain letters: for example, the phrase \"a bird in the hand is worth two in the bush\" would give the password \"1bitH=2itB\" (this example must not be used as a password).<br>\n<br>\nRegards,<br>\n<br>\n--<br>\nThe Dailymotion Security Team</body></html>"
|
||||
newAsTemplate: "From: {{.MailFrom}}\nSubject: A new connection from you to the Dailymotion VPN\nTo: {{.Mail}}\n\nHello\n\nWe have detected a new connection to the vpn from {{.Login}}.\nIt was detected the {{.Time}} coming from the ip {{.IP}} ({{.AsName}}).\n\nIt's not the usual internet provider you connect to the Dailymotion VPN from.\nOr maybe it's the first time you use the VPN from this location.\n\nIf you think there is something suspicious, please contact {{.CcPwnPassword}}\nIf it's you who connected to the VPN, we are sorry for the spam. You won't receive another mail if you connect from this location.\n\nRegards,\n\n--\nThe Dailymotion Infra and Security Teams"
|
||||
slackTemplate: "Hello.\nYou tried to connect to the VPN without an OTP code from your phone app.\nIf you have a Mac, use `{{.Login}}@{{.OTP}}` as your login.\nIf you have a PC with windows or linux, the VPN application should ask you for an OTP code after your login and password.\nThe OTP code is `{{.OTP}}`\n\nPS : you can check <https://wiki.dailymotion.com/display/officeit/OpenVPN#OpenVPN-OneTimePassword|the documentation> to learn how to use a proper OTP application and get rid of these messages"
|
||||
slackTemplate2: "User *{{.Login}}* required the slack OTP token"
|
||||
}
|
||||
|
|
7
otp.go
7
otp.go
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -10,9 +9,9 @@ func (s *OpenVpnMgt) GenerateOTP(user string) ([]string, error) {
|
|||
}
|
||||
|
||||
// alternative OTP generator, not used at the moment
|
||||
func (s *OpenVpnMgt) GenerateSlackOTP(user string) ([]string, error) {
|
||||
return s.GenerateOTPGeneric(user, 60, "sha256", 30, 8)
|
||||
}
|
||||
// func (s *OpenVpnMgt) GenerateSlackOTP(user string) ([]string, error) {
|
||||
// return s.GenerateOTPGeneric(user, 60, "sha256", 30, 8)
|
||||
// }
|
||||
|
||||
func (s *OpenVpnMgt) GenerateOTPGeneric(user string, period int, algo string, secretLen int, digits int) ([]string, error) {
|
||||
codes := []string{}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
#script-security 3
|
||||
auth-user-pass-optional
|
||||
ca /usr/local/share/ca-certificates/Dailymotion.crt
|
||||
cert /etc/ssl/certs/vpn.dailymotion.com-cert.pem
|
||||
user openvpn
|
||||
cipher aes-128-cbc
|
||||
dev vpnroadwarrior
|
||||
dev-type tun
|
||||
dh dh2048.pem
|
||||
ifconfig 192.168.200.0 192.168.207.255
|
||||
ifconfig-nowarn
|
||||
keepalive 10 120
|
||||
key /etc/ssl/private/vpn.dailymotion.com-key.pem
|
||||
management 127.0.0.1 4000
|
||||
management-client
|
||||
management-client-auth
|
||||
mode server
|
||||
group openvpn
|
||||
persist-key
|
||||
persist-remote-ip
|
||||
persist-tun
|
||||
port 41690
|
||||
proto tcp-server
|
||||
push "dhcp-option DNS 10.190.32.2"
|
||||
push "dhcp-option DNS 10.190.32.20"
|
||||
push "topology p2p"
|
||||
reneg-sec 43200
|
||||
tls-auth tlsauth.key
|
||||
tls-server
|
||||
topology p2p
|
||||
username-as-common-name
|
||||
verb 4
|
||||
client-cert-not-required
|
154
vpnserver.go
154
vpnserver.go
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
|
@ -26,8 +27,6 @@ type OpenVpnMgt struct {
|
|||
CcPwnPassword string
|
||||
pwnTemplate string
|
||||
newAsTemplate string
|
||||
slackTemplate string
|
||||
slackTemplate2 string
|
||||
cacheDir string
|
||||
syslog bool
|
||||
otpMasterSecrets []string
|
||||
|
@ -69,31 +68,40 @@ func (s *OpenVpnMgt) Run() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *OpenVpnMgt) TokenPassword(c *vpnSession) bool {
|
||||
return false
|
||||
func (s *OpenVpnMgt) TokenPassword(c *vpnSession) (bool, string) {
|
||||
//TODO implement that correcly
|
||||
if c.password == "maith1wiePuw3ieb4heiNie5y" {
|
||||
return true, "maith1wiePuw3ieb4heiNie5y"
|
||||
}
|
||||
return false, "maith1wiePuw3ieb4heiNie5y"
|
||||
}
|
||||
|
||||
func (s *OpenVpnMgt) Auth(c *vpnSession) (error, bool) {
|
||||
// main authentication function.
|
||||
// returns 0 if auth is valid
|
||||
// returns 1 if an TOTP code is necessary
|
||||
// returns a negative if auth is not valid
|
||||
func (s *OpenVpnMgt) Auth(c *vpnSession) (error, int) {
|
||||
// an empty password is not good
|
||||
if c.password == "" {
|
||||
return nil, false
|
||||
return errors.New("Empty Password"), -1
|
||||
}
|
||||
|
||||
// check if the password is a valid token validated for TOTP 2FA
|
||||
tokenPassword := s.TokenPassword(c)
|
||||
// If this is the case, empty the password to avoid checking it against the
|
||||
// ldap server
|
||||
if tokenPassword {
|
||||
// check if the password is a valid token (see TOTP request)
|
||||
tokenPasswordOk, tokenPassword := s.TokenPassword(c)
|
||||
|
||||
// password is a token. We remove it from the session object to
|
||||
// avoid checking it against the ldap
|
||||
if tokenPasswordOk {
|
||||
c.password = ""
|
||||
}
|
||||
|
||||
// if the otp is indicated, we check it against the valid codes as soon as
|
||||
// if the otp is not empty, we check it against the valid codes as soon as
|
||||
// possible
|
||||
otpvalidated := false
|
||||
if c.otpCode != "" {
|
||||
codes, err := s.GenerateOTP(c.Login)
|
||||
if err != nil {
|
||||
return err, false
|
||||
return err, -2
|
||||
}
|
||||
for _, possible := range codes {
|
||||
if possible == c.otpCode {
|
||||
|
@ -102,8 +110,6 @@ func (s *OpenVpnMgt) Auth(c *vpnSession) (error, bool) {
|
|||
}
|
||||
}
|
||||
|
||||
log.Println(otpvalidated)
|
||||
|
||||
c.Profile = ""
|
||||
login := []string{c.Login}
|
||||
pass := c.password
|
||||
|
@ -114,8 +120,6 @@ func (s *OpenVpnMgt) Auth(c *vpnSession) (error, bool) {
|
|||
if ldap.upgradeFrom != c.Profile {
|
||||
continue
|
||||
}
|
||||
log.Printf("try %s with login %s\n", k, login)
|
||||
|
||||
err, userOk, passOk, secondary := ldap.Auth(login, pass)
|
||||
|
||||
// if there is an error, try the other configurations
|
||||
|
@ -141,20 +145,38 @@ func (s *OpenVpnMgt) Auth(c *vpnSession) (error, bool) {
|
|||
}
|
||||
|
||||
// we have either a positive auth ok a previous valid one
|
||||
if passOk || c.Profile != "" || tokenPassword {
|
||||
if passOk || c.Profile != "" || tokenPasswordOk {
|
||||
c.Profile = k
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no profile update this turn, no need to continue
|
||||
if n == c.Profile {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
log.Println(c)
|
||||
log.Println(s.ldap[c.Profile])
|
||||
return nil, false
|
||||
// no profile validated, we stop here
|
||||
if c.Profile == "" {
|
||||
return errors.New("Authentication Failed"), -3
|
||||
}
|
||||
|
||||
// check the MFA requested by the secured profile
|
||||
switch s.ldap[c.Profile].mfaType {
|
||||
case "internal":
|
||||
if otpvalidated {
|
||||
return nil, 0
|
||||
}
|
||||
c.password = tokenPassword
|
||||
return errors.New("Need OTP Code"), 1
|
||||
case "okta":
|
||||
//TODO implement okta MFA
|
||||
return nil, -4
|
||||
}
|
||||
|
||||
// no MFA requested, the login is valid
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
func (s *OpenVpnMgt) sendCommand(msg []string) (error, []string) {
|
||||
|
@ -162,6 +184,7 @@ func (s *OpenVpnMgt) sendCommand(msg []string) (error, []string) {
|
|||
return errors.New("No openvpn server present"), nil
|
||||
}
|
||||
for _, line := range msg {
|
||||
log.Println(line)
|
||||
if _, err := s.buf.WriteString(line + "\r\n"); err != nil {
|
||||
return err, nil
|
||||
}
|
||||
|
@ -192,36 +215,73 @@ func (s *OpenVpnMgt) Version() (error, []string) {
|
|||
return nil, msg
|
||||
}
|
||||
|
||||
func (s *OpenVpnMgt) ClientValidated(line string) {
|
||||
//TODO manage that : find the client, log stuff
|
||||
<-s.ret
|
||||
}
|
||||
|
||||
func (s *OpenVpnMgt) ClientDisconnect(line string) {
|
||||
msg := <-s.ret
|
||||
log.Println(msg)
|
||||
//TODO manage that : find the client, log stuff
|
||||
<-s.ret
|
||||
}
|
||||
|
||||
func (s *OpenVpnMgt) getIP(c *vpnSession) (string, error) {
|
||||
// TODO implement
|
||||
ip := s.ldap[c.Profile].ipMin
|
||||
|
||||
return ip.String(), nil
|
||||
}
|
||||
|
||||
func (s *OpenVpnMgt) ClientConnect(line string) {
|
||||
var cmd []string
|
||||
var ip string
|
||||
var errIP error
|
||||
|
||||
client := NewVPNSession("log in")
|
||||
|
||||
client.ParseSessionId(line)
|
||||
|
||||
infos := <-s.ret
|
||||
|
||||
client.ParseEnv(&infos)
|
||||
if err := client.ParseEnv(&infos); err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
err, ok := s.Auth(client)
|
||||
|
||||
if err != nil {
|
||||
// if auth is ok, time to get an IP address
|
||||
if ok == 0 {
|
||||
ip, errIP = s.getIP(client)
|
||||
if errIP != nil {
|
||||
ok = -10
|
||||
err = errIP
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case ok == 0:
|
||||
cmd = []string{
|
||||
fmt.Sprintf("client-auth %d %d", client.cID, client.kID),
|
||||
fmt.Sprintf("ifconfig-push %s %s", ip, client.localIP),
|
||||
}
|
||||
for _, r := range s.ldap[client.Profile].routes {
|
||||
cmd = append(cmd, fmt.Sprintf("push \"route %s vpn_gateway\"", r))
|
||||
}
|
||||
cmd = append(cmd, "END")
|
||||
|
||||
case ok < 0:
|
||||
cmd = []string{fmt.Sprintf("client-deny %d %d \"%s\" \"%s\"",
|
||||
client.cID, client.kID, err, err)}
|
||||
|
||||
case ok == 1:
|
||||
cmd = []string{fmt.Sprintf(
|
||||
"client-deny %d %d \"Need OTP\" \"CRV1:R,E:%s:%s:OTP Code \"",
|
||||
client.cID, client.kID, client.password, client.b64Login())}
|
||||
}
|
||||
|
||||
if err, _ := s.sendCommand(cmd); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
if ok {
|
||||
log.Println("auth ok")
|
||||
}
|
||||
|
||||
// err, msg := s.sendCommand([]string{fmt.Sprintf("client-deny %d %d \"Need OTP\" \"CRV1:R:blabla:eC5oZW5uZXI=:OTP Code \"", client.cID, client.kID)})
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// log.Println(msg)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *OpenVpnMgt) handleConn(conn net.Conn) {
|
||||
|
@ -259,6 +319,15 @@ func (s *OpenVpnMgt) handleConn(conn net.Conn) {
|
|||
}
|
||||
line = strings.Trim(line, "\n\r ")
|
||||
|
||||
// manage all "terminator" lines
|
||||
for _, terminator := range []string{"END", ">CLIENT:ENV,END", "SUCCESS"} {
|
||||
if strings.HasPrefix(line, terminator) {
|
||||
s.ret <- response
|
||||
response = nil
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
// a new openvpn server is connected
|
||||
case strings.HasPrefix(line, ">INFO"):
|
||||
|
@ -272,16 +341,15 @@ func (s *OpenVpnMgt) handleConn(conn net.Conn) {
|
|||
|
||||
// new bloc for a connect event.
|
||||
// We start the receiving handler, which will wait for the Channel message
|
||||
case strings.HasPrefix(line, ">CLIENT:ADDRESS"):
|
||||
go s.ClientValidated(line)
|
||||
|
||||
case strings.HasPrefix(line, ">CLIENT:CONNECT"):
|
||||
go s.ClientConnect(line)
|
||||
|
||||
// write the cumulated lines into the channel to the current handler
|
||||
case strings.HasPrefix(line, "END") || strings.HasPrefix(line, ">CLIENT:ENV,END"):
|
||||
s.ret <- response
|
||||
response = nil
|
||||
default:
|
||||
response = append(response, line)
|
||||
}
|
||||
//log.Print(line)
|
||||
log.Print(line)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -31,6 +32,7 @@ type vpnSession struct {
|
|||
dev string `json:"-"`
|
||||
password string `json:"-"`
|
||||
otpCode string `json:"-"`
|
||||
localIP string `json:"-"`
|
||||
}
|
||||
|
||||
func NewVPNSession(operation string) *vpnSession {
|
||||
|
@ -44,6 +46,10 @@ func NewVPNSession(operation string) *vpnSession {
|
|||
return &v
|
||||
}
|
||||
|
||||
func (c *vpnSession) b64Login() string {
|
||||
return base64.StdEncoding.EncodeToString([]byte(c.Login))
|
||||
}
|
||||
|
||||
func (c *vpnSession) ParseSessionId(line string) error {
|
||||
var err error
|
||||
client_id := strings.Split(strings.Replace(line, ">CLIENT:CONNECT,", "", 1), ",")
|
||||
|
@ -56,30 +62,39 @@ func (c *vpnSession) ParseSessionId(line string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *vpnSession) ParseEnv(infos *[]string) {
|
||||
func (c *vpnSession) ParseEnv(infos *[]string) error {
|
||||
var err error
|
||||
r := regexp.MustCompile("[^a-zA-Z0-9./_@-]")
|
||||
|
||||
for _, line := range *infos {
|
||||
p := strings.Split(strings.Replace(line, ">CLIENT:ENV,", "", 1), "=")
|
||||
switch p[0] {
|
||||
case "trusted_port":
|
||||
c.port, _ = strconv.Atoi(p[1])
|
||||
case "trusted_ip":
|
||||
c.IP = p[1]
|
||||
if c.port, err = strconv.Atoi(r.ReplaceAllString(p[1], "")); err != nil {
|
||||
return err
|
||||
}
|
||||
case "untrusted_port":
|
||||
c.port, _ = strconv.Atoi(p[1])
|
||||
if c.port, err = strconv.Atoi(r.ReplaceAllString(p[1], "")); err != nil {
|
||||
return err
|
||||
}
|
||||
case "trusted_ip":
|
||||
c.IP = r.ReplaceAllString(p[1], "")
|
||||
case "untrusted_ip":
|
||||
c.IP = p[1]
|
||||
c.IP = r.ReplaceAllString(p[1], "")
|
||||
case "ifconfig_local":
|
||||
c.localIP = r.ReplaceAllString(p[1], "")
|
||||
case "password":
|
||||
switch {
|
||||
case strings.HasPrefix(c.password, "CRV1"):
|
||||
split := strings.Split(c.password, ":")
|
||||
case strings.HasPrefix(p[1], "CRV1"):
|
||||
split := strings.Split(p[1], ":")
|
||||
if len(split) != 5 {
|
||||
break
|
||||
}
|
||||
c.password = split[2]
|
||||
c.otpCode = split[4]
|
||||
|
||||
case strings.HasPrefix(c.password, "SCRV1"):
|
||||
split := strings.Split(c.password, ":")
|
||||
case strings.HasPrefix(p[1], "SCRV1"):
|
||||
split := strings.Split(p[1], ":")
|
||||
if len(split) != 3 {
|
||||
break
|
||||
}
|
||||
|
@ -101,11 +116,12 @@ func (c *vpnSession) ParseEnv(infos *[]string) {
|
|||
}
|
||||
|
||||
case "username":
|
||||
c.Login = p[1]
|
||||
c.Login = r.ReplaceAllString(p[1], "")
|
||||
case "dev":
|
||||
c.dev = p[1]
|
||||
c.dev = r.ReplaceAllString(p[1], "")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *vpnSession) String() string {
|
||||
|
|
Loading…
Reference in New Issue