about summary refs log tree commit diff
path: root/main.go
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@gmail.com>2017-02-11T11·27+0100
committerVincent Ambo <tazjin@gmail.com>2017-02-11T11·27+0100
commit98e81c2c0edd3d9bb483000d598e07e6dd9da6b0 (patch)
tree030c74862a1ca6990d3a97d6a8ebe85d8b31fb7e /main.go
parent33174cbb80a3147fb7bca9b1ac7f462350e7e0c7 (diff)
feat: Initial working implementation
Diffstat (limited to 'main.go')
-rw-r--r--main.go90
1 files changed, 90 insertions, 0 deletions
diff --git a/main.go b/main.go
new file mode 100644
index 0000000000..11f27260e3
--- /dev/null
+++ b/main.go
@@ -0,0 +1,90 @@
+package main
+
+import (
+	"bufio"
+	"encoding/xml"
+	"fmt"
+	"net/http"
+	"os"
+	"strings"
+)
+
+// The XML response returned by the WatchGuard server
+type Resp struct {
+	Action      string `xml:"action"`
+	LogonStatus int    `xml:"logon_status"`
+	LogonId     int    `xml:"logon_id"`
+	Error       string `xml:"errStr"`
+	Challenge   string `xml:"chaStr"`
+}
+
+func main() {
+	args := os.Args[1:]
+
+	if len(args) != 3 {
+		fmt.Fprintf(os.Stderr, "Usage: watchblob <vpn-host> <username> <password>\n")
+		os.Exit(1)
+	}
+
+	host := args[0]
+	username := args[1]
+	password := args[2]
+
+	challenge, err := triggerChallengeResponse(&host, &username, &password)
+
+	if err != nil || challenge.LogonStatus != 4 {
+		fmt.Fprintln(os.Stderr, "Did not receive challenge from server")
+		fmt.Fprintf(os.Stderr, "Response: %v\nError: %v\n", challenge, err)
+		os.Exit(1)
+	}
+
+	token := getToken(&challenge)
+	err = logon(&host, &challenge, &token)
+
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Logon failed: %v\n", err)
+		os.Exit(1)
+	}
+
+	fmt.Println("Login succeeded, you may now (quickly) authenticate OpenVPN with %s as your password", token)
+}
+
+func triggerChallengeResponse(host *string, username *string, password *string) (r Resp, err error) {
+	return request(templateUrl(host, templateChallengeTriggerUri(username, password)))
+}
+
+func getToken(challenge *Resp) string {
+	fmt.Println(challenge.Challenge)
+
+	reader := bufio.NewReader(os.Stdin)
+	token, _ := reader.ReadString('\n')
+
+	return strings.TrimSpace(token)
+}
+
+func logon(host *string, challenge *Resp, token *string) (err error) {
+	resp, err := request(templateUrl(host, templateResponseUri(challenge.LogonId, token)))
+	if err != nil {
+		return
+	}
+
+	if resp.LogonStatus != 1 {
+		err = fmt.Errorf("Challenge/response authentication failed: %v", resp)
+	}
+
+	return
+}
+
+func request(url string) (r Resp, err error) {
+	fmt.Println(url)
+	resp, err := http.Get(url)
+	if err != nil {
+		return
+	}
+
+	defer resp.Body.Close()
+	decoder := xml.NewDecoder(resp.Body)
+
+	err = decoder.Decode(&r)
+	return
+}