blank state

This commit is contained in:
2019-07-21 19:23:13 +02:00
parent 2c289f8125
commit 0e72c3a242
48 changed files with 14 additions and 5874 deletions

View File

@@ -3,50 +3,33 @@ package main
import (
"bufio"
"errors"
"fmt"
"io"
"log"
"net"
"os"
"strconv"
"strings"
"sync"
hibp "github.com/mattevans/pwned-passwords"
"github.com/pyke369/golang-support/rcache"
)
// Server represents the server
type OpenVpnMgt struct {
port string
buf map[string]*bufio.ReadWriter
m sync.RWMutex
ret chan []string
ldap map[string]ldapConfig
clients map[string]map[int]*vpnSession
authCa string
vpnlogUrl string
mailRelay string
MailFrom string
CcPwnPassword string
pwnTemplate string
newAsTemplate string
cacheDir string
syslog bool
otpMasterSecrets []string
hibpClient *hibp.Client
debug bool
port string
buf map[string]*bufio.ReadWriter
m sync.RWMutex
ret chan []string
syslog bool
debug bool
hold bool
}
// NewServer returns a pointer to a new server
func NewVPNServer(port string) *OpenVpnMgt {
return &OpenVpnMgt{
port: port,
ret: make(chan []string),
ldap: make(map[string]ldapConfig),
buf: make(map[string]*bufio.ReadWriter),
clients: make(map[string]map[int]*vpnSession),
hibpClient: hibp.NewClient(),
port: port,
ret: make(chan []string),
buf: make(map[string]*bufio.ReadWriter),
}
}
@@ -77,16 +60,6 @@ func (s *OpenVpnMgt) Run() {
}
}
func (s *OpenVpnMgt) CheckPwn(c *vpnSession) error {
c.LogPrintln("checking pwn password")
pwned, err := s.hibpClient.Pwned.Compromised(c.password)
if err != nil {
return err
}
c.PwnedPasswd = pwned
return nil
}
// send a command to the server. Set the channel to receive the response
func (s *OpenVpnMgt) sendCommand(msg []string, remote string) (error, []string) {
if len(s.buf) == 0 {
@@ -117,23 +90,6 @@ func (s *OpenVpnMgt) sendCommand(msg []string, remote string) (error, []string)
return nil, ret
}
// send the list of all connected clients
func (s *OpenVpnMgt) Stats() map[string]map[int]*vpnSession {
return s.clients
}
func (s *OpenVpnMgt) Kill(session string, id int, killer string) error {
if _, ok := s.clients[session]; !ok {
return errors.New("unknown session")
}
if _, ok := s.clients[session][id]; !ok {
return errors.New("unknown session id")
}
log.Printf("user %s's session killed from the web by %s\n", s.clients[session][id].Login, killer)
err, _ := s.sendCommand([]string{fmt.Sprintf("client-kill %d", id)}, session)
return err
}
// send the help command on all vpn servers. Kind of useless
func (s *OpenVpnMgt) Help() (error, map[string]map[string]string) {
ret := make(map[string]map[string]string)
@@ -169,133 +125,15 @@ func (s *OpenVpnMgt) Version() (error, map[string][]string) {
return nil, ret
}
// called after a client is confirmed connected and authenticated
func (s *OpenVpnMgt) ClientValidated(line, remote string) {
err, c := s.getClient(line, remote)
if err != nil {
log.Println(err, line)
return
}
c.Status = "success"
infos := <-s.ret
if err := c.ParseEnv(s, &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) {
err, c := s.getClient(line, remote)
if err != nil {
log.Println(err)
return
}
<-s.ret
// if the disconnect is due to an auth failure, don't change the status
if c.Status == "success" {
c.Operation = "log out"
}
// Don't log the initial auth failure due to absence of OTP code
// And don't log the auth failure during re auth
if c.Operation != "re auth" && c.Status != "Need OTP Code" {
s.Log(c)
}
defer delete(s.clients[remote], c.cID)
}
// called at the initial connexion
func (s *OpenVpnMgt) ClientConnect(line, remote string) {
c := NewVPNSession()
c.vpnserver = remote
c.ParseSessionId(line)
s.clients[remote][c.cID] = c
infos := <-s.ret
if err := c.ParseEnv(s, &infos); err != nil {
log.Println(err)
return
}
c.Auth(s)
}
func (s *OpenVpnMgt) ClientReAuth(line, remote string) {
err, c := s.getClient(line, remote)
if err != nil {
log.Println(err, line)
return
}
c.ParseSessionId(line)
infos := <-s.ret
if err := c.ParseEnv(s, &infos); err != nil {
log.Println(err)
return
}
// reset some values
c.Profile = ""
c.Status = "system failure"
c.Operation = "re auth"
c.Auth(s)
}
// find a client among all registered sessions
func (s *OpenVpnMgt) getClient(line, remote string) (error, *vpnSession) {
re := rcache.Get("^[^0-9]*,([0-9]+)[^0-9]*")
match := re.FindStringSubmatch(line)
if len(match) == 0 {
return errors.New("invalid message"), nil
}
id, err := strconv.Atoi(match[1])
if err != nil {
return err, nil
}
if _, ok := s.clients[remote]; !ok {
return errors.New("unknown vpn server"), nil
}
if c, ok := s.clients[remote][id]; ok {
return nil, c
}
return errors.New("unknown vpn client"), nil
}
// update counters
func (s *OpenVpnMgt) updateCounters(line, remote string) {
p := strings.Split(strings.Replace(line, ":", ",", 1), ",")
err, c := s.getClient(p[0]+","+p[1], remote)
if err != nil {
log.Println(err, line)
return
}
if c.BwWrite, err = strconv.Atoi(p[2]); err != nil {
c.LogPrintln(err)
return
}
if c.BwRead, err = strconv.Atoi(p[3]); err != nil {
c.LogPrintln(err)
return
}
return
}
// main loop for a given openvpn server
func (s *OpenVpnMgt) handleConn(conn net.Conn) {
remote := conn.RemoteAddr().String()
defer conn.Close()
defer delete(s.buf, remote)
defer delete(s.clients, remote)
// 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.clients[remote] = make(map[int]*vpnSession)
// most response are multilined, use response to concatenate them
response := []string{}
@@ -311,21 +149,6 @@ func (s *OpenVpnMgt) handleConn(conn net.Conn) {
return
}
// ask for statistics
if _, err := s.buf[remote].WriteString("bytecount 30\r\n"); err != nil {
log.Println(err)
return
}
if err := s.buf[remote].Flush(); err != nil {
log.Println(err)
return
}
if line, err := s.buf[remote].ReadString('\n'); err != nil ||
line != "SUCCESS: bytecount interval changed\r\n" {
log.Println("Bogus Client")
return
}
log.Printf("Valid openvpn connected from %s\n", remote)
for {
@@ -364,27 +187,6 @@ func (s *OpenVpnMgt) handleConn(conn net.Conn) {
// command successfull, we can ignore
case strings.HasPrefix(line, ">SUCCESS: client-deny command succeeded"):
// trafic stats
case strings.HasPrefix(line, ">BYTECOUNT_CLI"):
go s.updateCounters(line, remote)
// new bloc for a disconnect event.
// We start the receiving handler, which will wait for the Channel message
case strings.HasPrefix(line, ">CLIENT:DISCONNECT"):
go s.ClientDisconnect(line, remote)
// new bloc for a connect event.
// We start the receiving handler, which will wait for the Channel message
case strings.HasPrefix(line, ">CLIENT:ADDRESS"):
case strings.HasPrefix(line, ">CLIENT:ESTABLISHED"):
go s.ClientValidated(line, remote)
case strings.HasPrefix(line, ">CLIENT:CONNECT"):
go s.ClientConnect(line, remote)
case strings.HasPrefix(line, ">CLIENT:REAUTH"):
go s.ClientReAuth(line, remote)
default:
response = append(response, line)
}