Add logging, including the json one
get infos from I've been pwned and the API on install.dm.gg/vpn-log.php and send mail if there is anything strange
This commit is contained in:
parent
44cfdea6ed
commit
68de442333
2
go.mod
2
go.mod
|
@ -1,6 +1,8 @@
|
||||||
module gitlab.dm.gg/vwf/openvpn-dm-mgt-server
|
module gitlab.dm.gg/vwf/openvpn-dm-mgt-server
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/mattevans/pwned-passwords v0.0.0-20190611210716-1da592be4a34
|
||||||
|
github.com/onsi/gomega v1.5.0 // indirect
|
||||||
github.com/pyke369/golang-support v0.0.0-20190703174728-34ca97aa79e9
|
github.com/pyke369/golang-support v0.0.0-20190703174728-34ca97aa79e9
|
||||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
|
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
|
||||||
gopkg.in/ldap.v2 v2.5.1
|
gopkg.in/ldap.v2 v2.5.1
|
||||||
|
|
28
go.sum
28
go.sum
|
@ -1,6 +1,34 @@
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/mattevans/pwned-passwords v0.0.0-20190611210716-1da592be4a34 h1:cl/axA6OJFqTmZ573VUw9TTQ6/vbb+DIBFNFNPRFNaw=
|
||||||
|
github.com/mattevans/pwned-passwords v0.0.0-20190611210716-1da592be4a34/go.mod h1:lTBNMS5Uc86U2A2Cps0gWoo091FA0YH5FMXhTvL0ZPI=
|
||||||
|
github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
|
||||||
|
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/pyke369/golang-support v0.0.0-20190703174728-34ca97aa79e9 h1:H1vjQ+Mfc8dFAOTuF541/tScdKoynzll9iKuWgaLLxM=
|
github.com/pyke369/golang-support v0.0.0-20190703174728-34ca97aa79e9 h1:H1vjQ+Mfc8dFAOTuF541/tScdKoynzll9iKuWgaLLxM=
|
||||||
github.com/pyke369/golang-support v0.0.0-20190703174728-34ca97aa79e9/go.mod h1:0XGrzgrEp0fa/+JSV8XZePUwyjnU6C3bMc7Xz2bHHKI=
|
github.com/pyke369/golang-support v0.0.0-20190703174728-34ca97aa79e9/go.mod h1:0XGrzgrEp0fa/+JSV8XZePUwyjnU6C3bMc7Xz2bHHKI=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
|
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
|
||||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
|
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/ldap.v2 v2.5.1 h1:wiu0okdNfjlBzg6UWvd1Hn8Y+Ux17/u/4nlk4CQr6tU=
|
gopkg.in/ldap.v2 v2.5.1 h1:wiu0okdNfjlBzg6UWvd1Hn8Y+Ux17/u/4nlk4CQr6tU=
|
||||||
gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk=
|
gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
11
ldap.go
11
ldap.go
|
@ -111,8 +111,7 @@ func (conf *ldapConfig) Auth(logins []string, pass string) (e error, userOk, pas
|
||||||
return err, false, false, nil
|
return err, false, false, nil
|
||||||
}
|
}
|
||||||
if len(sr.Entries) != 1 {
|
if len(sr.Entries) != 1 {
|
||||||
log.Println("User does not exist or too many entries returned")
|
return errors.New("User does not exist or too many entries returned"), false, false, nil
|
||||||
return nil, false, false, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the attributes requested in the search
|
// check the attributes requested in the search
|
||||||
|
@ -128,12 +127,12 @@ func (conf *ldapConfig) Auth(logins []string, pass string) (e error, userOk, pas
|
||||||
|
|
||||||
// user must have both primary and secondary attributes
|
// user must have both primary and secondary attributes
|
||||||
if len(primary) == 0 {
|
if len(primary) == 0 {
|
||||||
log.Printf("User has no %s attribute", conf.primaryAttribute)
|
log.Printf("User %s has no %s attribute", logins[0], conf.primaryAttribute)
|
||||||
return nil, false, false, nil
|
return nil, false, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(secondary) == 0 {
|
if len(secondary) == 0 {
|
||||||
log.Printf("User has no %s attribute", conf.secondaryAttribute)
|
log.Printf("User %s has no %s attribute", logins[0], conf.secondaryAttribute)
|
||||||
return nil, false, false, nil
|
return nil, false, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +149,7 @@ func (conf *ldapConfig) Auth(logins []string, pass string) (e error, userOk, pas
|
||||||
attributes = secondary
|
attributes = secondary
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("User has a valid account on %s", s)
|
log.Printf("User %s has a valid account on %s", logins[0], s)
|
||||||
|
|
||||||
userdn := sr.Entries[0].DN
|
userdn := sr.Entries[0].DN
|
||||||
|
|
||||||
|
@ -165,7 +164,7 @@ func (conf *ldapConfig) Auth(logins []string, pass string) (e error, userOk, pas
|
||||||
}
|
}
|
||||||
|
|
||||||
// everything is fine,
|
// everything is fine,
|
||||||
log.Printf("User has a valid password on %s", s)
|
log.Printf("User %s has a valid password on %s", logins[0], s)
|
||||||
return nil, true, true, attributes
|
return nil, true, true, attributes
|
||||||
}
|
}
|
||||||
// if we are here, no server is responding, rejectif auth
|
// if we are here, no server is responding, rejectif auth
|
||||||
|
|
144
logs.go
144
logs.go
|
@ -1,11 +1,149 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"net/smtp"
|
||||||
|
"text/template"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *vpnSession) Log() error {
|
func (c *vpnSession) LogPrintln(v ...interface{}) {
|
||||||
//TODO get asname & shit
|
log.Println(c.Login, c.IP, v)
|
||||||
log.Println(c)
|
}
|
||||||
|
|
||||||
|
func (s *OpenVpnMgt) Log(c *vpnSession) error {
|
||||||
|
if s.vpnlogUrl != "" {
|
||||||
|
if err := c.getASInfos(s.vpnlogUrl); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
jsonStr, err := json.Marshal(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Println(string(jsonStr))
|
||||||
|
|
||||||
|
if err := s.SendMail(c); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *vpnSession) getASInfos(vpnlogUrl string) error {
|
||||||
|
jsonStr, err := json.Marshal(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", vpnlogUrl, bytes.NewBuffer(jsonStr))
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
timeout := time.Duration(3 * time.Second)
|
||||||
|
client := http.Client{
|
||||||
|
Timeout: timeout,
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
err = json.Unmarshal(body, c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *OpenVpnMgt) MailTemplate(c *vpnSession) error {
|
||||||
|
var buf1 bytes.Buffer
|
||||||
|
var buf2 bytes.Buffer
|
||||||
|
|
||||||
|
tmpl, err := template.New("pwnTemplate").Parse(s.pwnTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := tmpl.Execute(&buf1, c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.pwnMail = buf1.String()
|
||||||
|
|
||||||
|
tmpl, err = template.New("newAsTemplate").Parse(s.newAsTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := tmpl.Execute(&buf2, c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.newAsMail = buf2.String()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *OpenVpnMgt) SendMail(c *vpnSession) error {
|
||||||
|
if c.Mail == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.newAsTemplate == "" || !c.NewAS) &&
|
||||||
|
(s.pwnTemplate == "" || !c.PwnedPasswd) {
|
||||||
|
// can not send mail without template or cause
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// needed for the templating
|
||||||
|
c.MailFrom = s.MailFrom
|
||||||
|
c.CcPwnPassword = s.CcPwnPassword
|
||||||
|
|
||||||
|
// complete the templates
|
||||||
|
if err := s.MailTemplate(c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mail, err := smtp.Dial(s.mailRelay)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer mail.Close()
|
||||||
|
|
||||||
|
if c.PwnedPasswd {
|
||||||
|
mail.Mail(s.MailFrom)
|
||||||
|
mail.Rcpt(c.Mail)
|
||||||
|
if c.TooMuchPwn && s.CcPwnPassword != "" {
|
||||||
|
mail.Rcpt(s.CcPwnPassword)
|
||||||
|
}
|
||||||
|
wc, err := mail.Data()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer wc.Close()
|
||||||
|
buf := bytes.NewBufferString(c.pwnMail)
|
||||||
|
if _, err = buf.WriteTo(wc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
wc.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.NewAS {
|
||||||
|
mail.Mail(s.MailFrom)
|
||||||
|
mail.Rcpt(c.Mail)
|
||||||
|
wc, err := mail.Data()
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer wc.Close()
|
||||||
|
buf := bytes.NewBufferString(c.newAsMail)
|
||||||
|
if _, err = buf.WriteTo(wc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
wc.Close()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
2
main.go
2
main.go
|
@ -42,7 +42,7 @@ func main() {
|
||||||
if *logToSyslog {
|
if *logToSyslog {
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
server.syslog = true
|
server.syslog = true
|
||||||
logWriter, e := syslog.New(syslog.LOG_NOTICE, "")
|
logWriter, e := syslog.New(syslog.LOG_NOTICE, "vpnauth")
|
||||||
if e == nil {
|
if e == nil {
|
||||||
log.SetOutput(logWriter)
|
log.SetOutput(logWriter)
|
||||||
defer logWriter.Close()
|
defer logWriter.Close()
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
sudo: false
|
||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- 1.11.x
|
||||||
|
- tip
|
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright (C) 2018 by Matt Evans
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
|
@ -0,0 +1,62 @@
|
||||||
|
# pwned-passwords
|
||||||
|
|
||||||
|
[![GoDoc](https://godoc.org/github.com/mattevans/pwned-passwords?status.svg)](https://godoc.org/github.com/mattevans/pwned-passwords)
|
||||||
|
[![Build Status](https://travis-ci.org/mattevans/pwned-passwords.svg?branch=master)](https://travis-ci.org/mattevans/pwned-passwords)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/mattevans/pwned-passwords)](https://goreportcard.com/report/github.com/mattevans/pwned-passwords)
|
||||||
|
[![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/mattevans/pwned-passwords/blob/master/LICENSE)
|
||||||
|
|
||||||
|
A simple [Go](http://golang.org) client library for checking compromised passwords against [HIBP Pwned Passwords](https://haveibeenpwned.com/Passwords).
|
||||||
|
|
||||||
|
Upon request, results will be cached (in-memory), keyed by hash. With a two hour expiry window, subsequent requests will use cached data or fetch fresh data accordingly.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
`go get -u github.com/mattevans/pwned-passwords`
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
hibp "github.com/mattevans/pwned-passwords"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Init a client.
|
||||||
|
client := hibp.NewClient()
|
||||||
|
|
||||||
|
// Check to see if your given string is compromised.
|
||||||
|
pwned, err := client.Pwned.Compromised("string to check")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Pwned failed")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pwned {
|
||||||
|
// Oh dear!
|
||||||
|
// You should avoid using that password
|
||||||
|
} else {
|
||||||
|
// Woo!
|
||||||
|
// All clear!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expire in-memory cache**
|
||||||
|
|
||||||
|
```go
|
||||||
|
client.Cache.Expire(HASHED_VALUE)
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
client.Cache.ExpireAll()
|
||||||
|
```
|
||||||
|
|
||||||
|
Contributing
|
||||||
|
-----------------
|
||||||
|
If you've found a bug or would like to contribute, please create an issue here on GitHub, or better yet fork the project and submit a pull request!
|
|
@ -0,0 +1,65 @@
|
||||||
|
package hibp
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// cache holds our our cached hash/compromised pairs results.
|
||||||
|
var cache map[string]*PwnedStore
|
||||||
|
|
||||||
|
// cacheTTL stores the time to live of our cache (2 hours).
|
||||||
|
var cacheTTL = 2 * time.Hour
|
||||||
|
|
||||||
|
// CacheService handles in-memory caching of our hash/compromised pairs.
|
||||||
|
type CacheService service
|
||||||
|
|
||||||
|
// Get will return our stored in-memory hash/compromised pairs, if we have them.
|
||||||
|
func (s *CacheService) Get(hash string) *PwnedStore {
|
||||||
|
// Is our cache expired?
|
||||||
|
if s.IsExpired(hash) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use stored results.
|
||||||
|
return cache[hash]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store will save our hash/compromised pairs to a PwnedStore.
|
||||||
|
func (s *CacheService) Store(hash string, compromised bool) {
|
||||||
|
// No cache? Initialize it.
|
||||||
|
if cache == nil {
|
||||||
|
cache = map[string]*PwnedStore{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store
|
||||||
|
tn := time.Now()
|
||||||
|
cache[hash] = &PwnedStore{
|
||||||
|
Hash: hash,
|
||||||
|
Compromised: compromised,
|
||||||
|
UpdatedAt: &tn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsExpired checks if we have cached hash and that it isn't expired.
|
||||||
|
func (s *CacheService) IsExpired(hash string) bool {
|
||||||
|
// No cache? bail.
|
||||||
|
if cache[hash] == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expired cache? bail.
|
||||||
|
lastUpdated := cache[hash].UpdatedAt
|
||||||
|
if lastUpdated != nil && lastUpdated.Add(cacheTTL).Before(time.Now()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expire will expire the cache for a given hash.
|
||||||
|
func (s *CacheService) Expire(hash string) {
|
||||||
|
cache[hash] = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExpireAll will expire all cache.
|
||||||
|
func (s *CacheService) ExpireAll() {
|
||||||
|
cache = nil
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
package hibp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
packageVersion = "0.0.1"
|
||||||
|
backendURL = "https://api.pwnedpasswords.com"
|
||||||
|
userAgent = "pwned-passwords-golang/" + packageVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
// Client holds a connection to the HIBP API.
|
||||||
|
type Client struct {
|
||||||
|
client *http.Client
|
||||||
|
AppID string
|
||||||
|
UserAgent string
|
||||||
|
BackendURL *url.URL
|
||||||
|
|
||||||
|
// Services used for communicating with the API.
|
||||||
|
Pwned *PwnedService
|
||||||
|
Cache *CacheService
|
||||||
|
}
|
||||||
|
|
||||||
|
type service struct {
|
||||||
|
client *Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient creates a new Client with the appropriate connection details and
|
||||||
|
// services used for communicating with the API.
|
||||||
|
func NewClient() *Client {
|
||||||
|
// Init new http.Client.
|
||||||
|
httpClient := http.DefaultClient
|
||||||
|
|
||||||
|
// Parse BE URL.
|
||||||
|
baseURL, _ := url.Parse(backendURL)
|
||||||
|
|
||||||
|
c := &Client{
|
||||||
|
client: httpClient,
|
||||||
|
BackendURL: baseURL,
|
||||||
|
UserAgent: userAgent,
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Pwned = &PwnedService{client: c}
|
||||||
|
c.Cache = &CacheService{client: c}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRequest creates an API request. A relative URL can be provided in urlPath,
|
||||||
|
// which will be resolved to the BackendURL of the Client.
|
||||||
|
func (c *Client) NewRequest(method, urlPath string, body interface{}) (*http.Request, error) {
|
||||||
|
// Parse our URL.
|
||||||
|
rel, err := url.Parse(urlPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolve to absolute URI.
|
||||||
|
u := c.BackendURL.ResolveReference(rel)
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
if body != nil {
|
||||||
|
err = json.NewEncoder(buf).Encode(body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the request.
|
||||||
|
req, err := http.NewRequest(method, u.String(), buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add our packages UA.
|
||||||
|
req.Header.Add("User-Agent", c.UserAgent)
|
||||||
|
|
||||||
|
return req, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do sends an API request and returns the API response.
|
||||||
|
func (c *Client) Do(req *http.Request) ([]string, error) {
|
||||||
|
resp, err := c.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if rerr := resp.Body.Close(); err == nil {
|
||||||
|
err = rerr
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Error if anything else but 200.
|
||||||
|
// The API should always return a 200 (unless something is wrong) as per
|
||||||
|
// https://haveibeenpwned.com/API/v2#SearchingPwnedPasswordsByRange
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("Unexpected API response status: %v", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse our resp.Body.
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response is returned as new-line'd string, split and return.
|
||||||
|
return strings.Split(string(body), "\r\n"), err
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package hibp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha1"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PwnedService handles retrieving pwned hashes from in-memory cache or
|
||||||
|
// by fetching fresh results.
|
||||||
|
type PwnedService service
|
||||||
|
|
||||||
|
// PwnedStore holds our pwned password hashes and compromised status.
|
||||||
|
type PwnedStore struct {
|
||||||
|
Hash string `json:"hash"`
|
||||||
|
Compromised bool `json:"compromised"`
|
||||||
|
UpdatedAt *time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compromised will build and execute a request to HIBP to check to see
|
||||||
|
// if the passed value is compromised or not.
|
||||||
|
func (s *PwnedService) Compromised(value string) (bool, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Our value being checked is empty, we don't want that.
|
||||||
|
if value == "" {
|
||||||
|
return false, errors.New("Value for compromised check cannot be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SHA-1 hash our input value.
|
||||||
|
hashedStr := _hashString(value)
|
||||||
|
|
||||||
|
// If we have cached results, use them.
|
||||||
|
cache := s.client.Cache.Get(hashedStr)
|
||||||
|
if cache != nil {
|
||||||
|
hashedStr = cache.Hash
|
||||||
|
return cache.Compromised, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop our prefix and suffix.
|
||||||
|
prefix := strings.ToUpper(hashedStr[:5])
|
||||||
|
suffix := strings.ToUpper(hashedStr[5:])
|
||||||
|
|
||||||
|
// Build request.
|
||||||
|
request, err := s.client.NewRequest("GET", fmt.Sprintf("range/%s", prefix), nil)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make request.
|
||||||
|
response, err := s.client.Do(request)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Range our response ([]string).
|
||||||
|
for _, target := range response {
|
||||||
|
// If our target, minus the compromised count matches our suffix.
|
||||||
|
if string(target[:35]) == suffix {
|
||||||
|
_, err = strconv.ParseInt(target[36:], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store in cache as compromised.
|
||||||
|
s.client.Cache.Store(hashedStr, true)
|
||||||
|
|
||||||
|
// Return.
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store in cache as non-compromised.
|
||||||
|
s.client.Cache.Store(hashedStr, false)
|
||||||
|
|
||||||
|
// Return.
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// _hashString will return a sha1 hash of the given value.
|
||||||
|
func _hashString(value string) string {
|
||||||
|
alg := sha1.New()
|
||||||
|
alg.Write([]byte(value))
|
||||||
|
return strings.ToUpper(hex.EncodeToString(alg.Sum(nil)))
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
# github.com/mattevans/pwned-passwords v0.0.0-20190611210716-1da592be4a34
|
||||||
|
github.com/mattevans/pwned-passwords
|
||||||
# github.com/pyke369/golang-support v0.0.0-20190703174728-34ca97aa79e9
|
# github.com/pyke369/golang-support v0.0.0-20190703174728-34ca97aa79e9
|
||||||
github.com/pyke369/golang-support/uconfig
|
github.com/pyke369/golang-support/uconfig
|
||||||
github.com/pyke369/golang-support/rcache
|
github.com/pyke369/golang-support/rcache
|
||||||
|
|
53
vpnserver.go
53
vpnserver.go
|
@ -71,12 +71,12 @@ func (s *OpenVpnMgt) Run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send a command to the server. Set the channel to receive the response
|
||||||
func (s *OpenVpnMgt) sendCommand(msg []string, remote string) (error, []string) {
|
func (s *OpenVpnMgt) sendCommand(msg []string, remote string) (error, []string) {
|
||||||
if len(s.buf) == 0 {
|
if len(s.buf) == 0 {
|
||||||
return errors.New("No openvpn server present"), nil
|
return errors.New("No openvpn server present"), nil
|
||||||
}
|
}
|
||||||
for _, line := range msg {
|
for _, line := range msg {
|
||||||
log.Println(line)
|
|
||||||
if _, err := s.buf[remote].WriteString(line + "\r\n"); err != nil {
|
if _, err := s.buf[remote].WriteString(line + "\r\n"); err != nil {
|
||||||
return err, nil
|
return err, nil
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,7 @@ func (s *OpenVpnMgt) sendCommand(msg []string, remote string) (error, []string)
|
||||||
return nil, ret
|
return nil, ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send the help command on all vpn servers. Kind of useless
|
||||||
func (s *OpenVpnMgt) Help() (error, map[string]map[string]string) {
|
func (s *OpenVpnMgt) Help() (error, map[string]map[string]string) {
|
||||||
ret := make(map[string]map[string]string)
|
ret := make(map[string]map[string]string)
|
||||||
re := regexp.MustCompile("^(.*[^ ]) *: (.*)$")
|
re := regexp.MustCompile("^(.*[^ ]) *: (.*)$")
|
||||||
|
@ -112,6 +113,7 @@ func (s *OpenVpnMgt) Help() (error, map[string]map[string]string) {
|
||||||
return nil, ret
|
return nil, ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send the verson command on all vpn servers. Kind of useless
|
||||||
func (s *OpenVpnMgt) Version() (error, map[string][]string) {
|
func (s *OpenVpnMgt) Version() (error, map[string][]string) {
|
||||||
ret := make(map[string][]string)
|
ret := make(map[string][]string)
|
||||||
for remote := range s.buf {
|
for remote := range s.buf {
|
||||||
|
@ -124,20 +126,34 @@ func (s *OpenVpnMgt) Version() (error, map[string][]string) {
|
||||||
return nil, ret
|
return nil, ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// internal DHCP
|
||||||
|
func (s *OpenVpnMgt) getIP(c *vpnSession) (string, error) {
|
||||||
|
// TODO implement
|
||||||
|
ip := s.ldap[c.Profile].ipMin
|
||||||
|
|
||||||
|
return ip.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// called after a client is confirmed connected and authenticated
|
||||||
func (s *OpenVpnMgt) ClientValidated(line, remote string) {
|
func (s *OpenVpnMgt) ClientValidated(line, remote string) {
|
||||||
err, c := s.getClient(line, remote)
|
err, c := s.getClient(line, remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err, line)
|
log.Println(err, line)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
<-s.ret
|
|
||||||
|
|
||||||
c.Status = "success"
|
c.Status = "success"
|
||||||
|
infos := <-s.ret
|
||||||
|
|
||||||
log.Println(c)
|
if err := c.ParseEnv(&infos); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Log(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// called after a client is disconnected, including for auth issues
|
||||||
func (s *OpenVpnMgt) ClientDisconnect(line, remote string) {
|
func (s *OpenVpnMgt) ClientDisconnect(line, remote string) {
|
||||||
|
//TODO free the IP
|
||||||
err, c := s.getClient(line, remote)
|
err, c := s.getClient(line, remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
|
@ -153,31 +169,25 @@ func (s *OpenVpnMgt) ClientDisconnect(line, remote string) {
|
||||||
|
|
||||||
// Don't log the initial auth failure due to absence of OTP code
|
// Don't log the initial auth failure due to absence of OTP code
|
||||||
if c.Status != "Need OTP Code" {
|
if c.Status != "Need OTP Code" {
|
||||||
c.Log()
|
s.Log(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
defer delete(s.clients[remote], c.cID)
|
defer delete(s.clients[remote], c.cID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OpenVpnMgt) getIP(c *vpnSession) (string, error) {
|
// called at the initial connexion
|
||||||
// TODO implement
|
|
||||||
ip := s.ldap[c.Profile].ipMin
|
|
||||||
|
|
||||||
return ip.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *OpenVpnMgt) ClientConnect(line, remote string) {
|
func (s *OpenVpnMgt) ClientConnect(line, remote string) {
|
||||||
client := NewVPNSession("log in")
|
c := NewVPNSession("log in")
|
||||||
client.vpnserver = remote
|
c.vpnserver = remote
|
||||||
client.ParseSessionId(line)
|
c.ParseSessionId(line)
|
||||||
s.clients[remote][client.cID] = client
|
s.clients[remote][c.cID] = c
|
||||||
infos := <-s.ret
|
infos := <-s.ret
|
||||||
if err := client.ParseEnv(&infos); err != nil {
|
if err := c.ParseEnv(&infos); err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
client.Auth(s)
|
c.Auth(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// find a client among all registered sessions
|
// find a client among all registered sessions
|
||||||
|
@ -200,6 +210,7 @@ func (s *OpenVpnMgt) getClient(line, remote string) (error, *vpnSession) {
|
||||||
return errors.New("unknown vpn client"), nil
|
return errors.New("unknown vpn client"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// main loop for a given openvpn server
|
||||||
func (s *OpenVpnMgt) handleConn(conn net.Conn) {
|
func (s *OpenVpnMgt) handleConn(conn net.Conn) {
|
||||||
remote := conn.RemoteAddr().String()
|
remote := conn.RemoteAddr().String()
|
||||||
|
|
||||||
|
@ -207,6 +218,8 @@ func (s *OpenVpnMgt) handleConn(conn net.Conn) {
|
||||||
defer delete(s.buf, remote)
|
defer delete(s.buf, remote)
|
||||||
defer delete(s.clients, remote)
|
defer delete(s.clients, remote)
|
||||||
|
|
||||||
|
// TODO : free all IPs if disconnected
|
||||||
|
|
||||||
// we store the buffer pointer in the struct, to be accessed from other methods
|
// we store the buffer pointer in the struct, to be accessed from other methods
|
||||||
s.buf[remote] = bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
s.buf[remote] = bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn))
|
||||||
s.clients[remote] = make(map[int]*vpnSession)
|
s.clients[remote] = make(map[int]*vpnSession)
|
||||||
|
@ -240,7 +253,7 @@ func (s *OpenVpnMgt) handleConn(conn net.Conn) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("Valid openvpn connected from %s", remote)
|
log.Printf("Valid openvpn connected from %s\n", remote)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
line, err := s.buf[remote].ReadString('\n')
|
line, err := s.buf[remote].ReadString('\n')
|
||||||
|
@ -299,7 +312,7 @@ func (s *OpenVpnMgt) handleConn(conn net.Conn) {
|
||||||
response = append(response, line)
|
response = append(response, line)
|
||||||
}
|
}
|
||||||
// TODO remove this
|
// TODO remove this
|
||||||
if strings.Index(line, "password") == -1 {
|
if false && strings.Index(line, "password") == -1 {
|
||||||
log.Print(line)
|
log.Print(line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,32 +11,38 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
hibp "github.com/mattevans/pwned-passwords"
|
||||||
)
|
)
|
||||||
|
|
||||||
type vpnSession struct {
|
type vpnSession struct {
|
||||||
Time time.Time `json:"time"`
|
Time time.Time `json:"time"`
|
||||||
Login string `json:"username"`
|
Login string `json:"username"`
|
||||||
Operation string `json:"operation"`
|
Operation string `json:"operation"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Profile string `json:"profile"`
|
Profile string `json:"profile"`
|
||||||
TwoFA bool `json:"2fa_auth"`
|
TwoFA bool `json:"2fa_auth"`
|
||||||
IP string `json:"client_ip"`
|
IP string `json:"client_ip"`
|
||||||
PrivIP string `json:"private_ip"`
|
PrivIP string `json:"private_ip"`
|
||||||
AsNumber string `json:"as_number"`
|
AsNumber string `json:"as_number"`
|
||||||
AsName string `json:"as_name"`
|
AsName string `json:"as_name"`
|
||||||
NewAS bool `json:"as_new"`
|
NewAS bool `json:"as_new"`
|
||||||
PwnedPasswd bool `json:"pwned_passwd"`
|
PwnedPasswd bool `json:"pwned_passwd"`
|
||||||
Hostname string `json:"hostname"`
|
Hostname string `json:"hostname"`
|
||||||
TooMuchPwn bool `json:"too_much_pwn"`
|
TooMuchPwn bool `json:"too_much_pwn"`
|
||||||
Mail string `json:"-"`
|
Mail string `json:"-"`
|
||||||
cID int `json:"-"`
|
cID int `json:"-"`
|
||||||
kID int `json:"-"`
|
kID int `json:"-"`
|
||||||
port int `json:"-"`
|
port int `json:"-"`
|
||||||
dev string `json:"-"`
|
dev string `json:"-"`
|
||||||
password string `json:"-"`
|
password string `json:"-"`
|
||||||
otpCode string `json:"-"`
|
otpCode string `json:"-"`
|
||||||
localIP string `json:"-"`
|
localIP string `json:"-"`
|
||||||
vpnserver string `json:"-"`
|
vpnserver string `json:"-"`
|
||||||
|
pwnMail string `json:"-"`
|
||||||
|
newAsMail string `json:"-"`
|
||||||
|
MailFrom string `json:"-"`
|
||||||
|
CcPwnPassword string `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVPNSession(operation string) *vpnSession {
|
func NewVPNSession(operation string) *vpnSession {
|
||||||
|
@ -73,6 +79,16 @@ func (c *vpnSession) ParseSessionId(line string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *vpnSession) CheckPwn(password string) error {
|
||||||
|
client := hibp.NewClient()
|
||||||
|
pwned, err := client.Pwned.Compromised(password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.PwnedPasswd = pwned
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *vpnSession) ParseEnv(infos *[]string) error {
|
func (c *vpnSession) ParseEnv(infos *[]string) error {
|
||||||
var err error
|
var err error
|
||||||
r := regexp.MustCompile("[^a-zA-Z0-9./_@-]")
|
r := regexp.MustCompile("[^a-zA-Z0-9./_@-]")
|
||||||
|
@ -92,6 +108,8 @@ func (c *vpnSession) ParseEnv(infos *[]string) error {
|
||||||
c.IP = r.ReplaceAllString(p[1], "")
|
c.IP = r.ReplaceAllString(p[1], "")
|
||||||
case "untrusted_ip":
|
case "untrusted_ip":
|
||||||
c.IP = r.ReplaceAllString(p[1], "")
|
c.IP = r.ReplaceAllString(p[1], "")
|
||||||
|
case "ifconfig_pool_remote_ip":
|
||||||
|
c.PrivIP = r.ReplaceAllString(p[1], "")
|
||||||
case "ifconfig_local":
|
case "ifconfig_local":
|
||||||
c.localIP = r.ReplaceAllString(p[1], "")
|
c.localIP = r.ReplaceAllString(p[1], "")
|
||||||
case "password":
|
case "password":
|
||||||
|
@ -106,6 +124,7 @@ func (c *vpnSession) ParseEnv(infos *[]string) error {
|
||||||
if c.otpCode == "" {
|
if c.otpCode == "" {
|
||||||
c.otpCode = "***"
|
c.otpCode = "***"
|
||||||
}
|
}
|
||||||
|
go c.CheckPwn(c.password)
|
||||||
|
|
||||||
case strings.HasPrefix(p[1], "SCRV1"):
|
case strings.HasPrefix(p[1], "SCRV1"):
|
||||||
split := strings.Split(p[1], ":")
|
split := strings.Split(p[1], ":")
|
||||||
|
@ -132,6 +151,7 @@ func (c *vpnSession) ParseEnv(infos *[]string) error {
|
||||||
default:
|
default:
|
||||||
c.password = p[1]
|
c.password = p[1]
|
||||||
c.otpCode = ""
|
c.otpCode = ""
|
||||||
|
go c.CheckPwn(c.password)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "username":
|
case "username":
|
||||||
|
@ -180,7 +200,7 @@ func (c *vpnSession) Auth(s *OpenVpnMgt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err, _ := s.sendCommand(cmd, c.vpnserver); err != nil {
|
if err, _ := s.sendCommand(cmd, c.vpnserver); err != nil {
|
||||||
log.Println(err)
|
c.LogPrintln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -235,7 +255,7 @@ func (c *vpnSession) auth(s *OpenVpnMgt) (error, int) {
|
||||||
|
|
||||||
// if there is an error, try the other configurations
|
// if there is an error, try the other configurations
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
c.LogPrintln(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue