diff options
Diffstat (limited to 'pkg/vpn/launcher_windows.go')
-rw-r--r-- | pkg/vpn/launcher_windows.go | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/pkg/vpn/launcher_windows.go b/pkg/vpn/launcher_windows.go new file mode 100644 index 0000000..be5ef83 --- /dev/null +++ b/pkg/vpn/launcher_windows.go @@ -0,0 +1,158 @@ +// +build windows +// Copyright (C) 2018-2021 LEAP +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. + +package vpn + +import ( + "errors" + "log" + "os" + "strings" + "bufio" + "fmt" + "unicode/utf16" + "bytes" + "time" + "encoding/binary" + + "github.com/natefinch/npipe" + "0xacab.org/leap/bitmask-vpn/pkg/vpn/bonafide" +) + +const pipeName = `\\.\pipe\openvpn\service` + +type launcher struct { + mngPass string +} + +func newLauncher() (*launcher, error) { + l := launcher{} + return &l, nil +} + +func (l *launcher) close() error { + return nil +} + +func (l *launcher) check() (helpers bool, privilege bool, err error) { + // TODO check if the named pipe exists + return true, true, nil +} + +func (l *launcher) openvpnStart(flags ...string) error { + var b bytes.Buffer + var filtered []string + for _, v := range flags { + if v != "--tun-ipv6" { + filtered = append(filtered, v) + } + } + + cwd, _ := os.Getwd() + opts := `--client --dev tun --block-outside-dns --redirect-gateway --script-security 0 ` + strings.Join(filtered, " ") + log.Println("openvpn start: ", opts) + + timeout := 3 * time.Second + conn, err := npipe.DialTimeout(pipeName, timeout) + if err != nil { + fmt.Println("ERROR opening pipe") + return errors.New("cannot open openvpn pipe") + + } + defer conn.Close() + + writeUTF16Bytes(&b, cwd) + writeUTF16Bytes(&b, opts) + writeUTF16Bytes(&b, `\n`) + encoded := b.Bytes() + + rw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) + + _, err = rw.Write(encoded) + if err != nil { + fmt.Println("ERROR writing to pipe") + return errors.New("cannot write to openvpn pipe") + } + rw.Flush() + pid, err := getCommandResponse(rw) + if err != nil { + fmt.Println("ERROR getting pid") + } + fmt.Println("OpenVPN PID:", pid) + return nil +} + +func (l *launcher) openvpnStop() error { + return nil +} + +// TODO we will have to bring our helper back to do firewall + +func (l *launcher) firewallStart(gateways []bonafide.Gateway) error { + log.Println("NO firewall in windows") + return nil +} + +func (l *launcher) firewallStop() error { + log.Println("NO firewall in windows") + return nil +} + +func (l *launcher) firewallIsUp() bool { + log.Println("NO firewall in windows") + return true +} + + +func writeUTF16Bytes(b *bytes.Buffer, in string) { + var u16 []uint16 = utf16.Encode([]rune(in + "\x00")) + binary.Write(b, binary.LittleEndian, u16) +} + +func decodeUTF16String(s string) int { + var code int + var dec []byte + for _, v := range []byte(s) { + if byte(v) != byte(0) { + dec = append(dec, v) + } + } + _, err := fmt.Sscanf(string(dec), "%v", &code) + if err != nil { + fmt.Println("ERROR decoding") + } + return code +} + +func getCommandResponse(rw *bufio.ReadWriter) (int, error) { + msg, err := rw.ReadString('\n') + if err != nil { + fmt.Println("ERROR reading") + } + ok := decodeUTF16String(msg) + if ok != 0 { + return -1, errors.New("command failed") + } + msg, err = rw.ReadString('\n') + if err != nil { + fmt.Println("ERROR reading") + } + pid := decodeUTF16String(msg) + if pid == 0 { + return -1, errors.New("command failed") + } + return pid, nil +} |