package main import ( "encoding/base64" "flag" "fmt" "html/template" "io/ioutil" "log" "net/http" "os" "regexp" "strings" "github.com/gorilla/mux" ) var ( port *int // port the http server listens on usernames []string // list of usernames currentVpnRemotePort *int ) // Credentials stores user credentials type Credentials struct { Username string Accesscode string Hostname string } func registerHTTPFlags() { port = flag.Int("port", 8081, "The port the http server should listen on") currentVpnRemotePort = flag.Int("initialVPNPort", 1194, "the initial vpn port") } func setupHTTPServer() http.Server { r := mux.NewRouter() r.HandleFunc("/", indexHandler) r.HandleFunc("/register", registerGetHandler).Methods("GET") r.HandleFunc("/register", registerPostHandler).Methods("POST") r.HandleFunc("/credentials", credentialsGetHandler).Methods("GET") return http.Server{ Addr: fmt.Sprintf("0.0.0.0:%d", *port), Handler: r, } } // Host of the index file func indexHandler(w http.ResponseWriter, r *http.Request) { readFileToReponse(w, "/index.html") } // Read register page func registerGetHandler(w http.ResponseWriter, r *http.Request) { readFileToReponse(w, "/register.html") } // Process a registration func registerPostHandler(w http.ResponseWriter, r *http.Request) { r.ParseForm() username := r.Form.Get("username") // test if the username has already been chosen if !isUniq(username) { log.Println("redirecting to usernameTaken") usernameTakenGetHandler(w, r) return } if !isValid(username) { return } // add the new username to the list of usernames usernames = append(usernames, username) // generate a new accesscode accesscode := newAccessCode(16) log.Printf("Generated a new AccessCode for user \"%s\": \"%s\"", username, accesscode) // generate a new companion spawnCompanion(username, accesscode) log.Println("---") log.Println("Done generating the containers, filling the credentials page using a template") usernameBytes := []byte(username) usernameBase64 := base64.StdEncoding.EncodeToString(usernameBytes) accesscodeBytes := []byte(accesscode) accesscodeBase64 := base64.StdEncoding.EncodeToString(accesscodeBytes) // insert the username and the accesscode into the http request parameters r.Form["username"] = []string{usernameBase64} r.Form["accesscode"] = []string{accesscodeBase64} credentialsGetHandler(w, r) } func usernameTakenGetHandler(w http.ResponseWriter, r *http.Request) { log.Println("[usernameTaken]") readFileToReponse(w, "/usernameTaken.html") } func isUniq(username string) bool { for _, user := range usernames { if username == user { return false } } return true } func isValid(username string) bool { // reserved subdomains if username == "traefik" || username == "register" || username == "scoreboard" || username == "grafana" { return false } // valid Format var validFormat = regexp.MustCompile("^[a-zA-Z0-9]{1,60}$") if validFormat.MatchString(username) == false { return false } return true } func readFileToReponse(w http.ResponseWriter, path string) { requestedFile := strings.Replace(path, "..", "", -1) contents, readError := ioutil.ReadFile(fmt.Sprintf("hosted/%s", requestedFile)) if readError != nil { w.Write([]byte(fmt.Sprintf("unable to read %s", requestedFile))) } else { w.Write([]byte(contents)) } } func credentialsGetHandler(w http.ResponseWriter, r *http.Request) { r.ParseForm() usernameBase64 := r.Form.Get("username") username, err := base64.StdEncoding.DecodeString(usernameBase64) if err != nil { fmt.Println("error decoding username base64:", err) } accesscodeBase64 := r.Form.Get("accesscode") accesscode, err := base64.StdEncoding.DecodeString(accesscodeBase64) if err != nil { fmt.Println("error decoding accesscode base64:", err) } log.Println("[ ] Credentials GET Handler") log.Println("%#v", r.Form) log.Printf("username: %s", username) log.Printf("accesscode: %s", accesscode) // create a new template reading the credentials template file // the template then gets executed inserting the username and the accesscode log.Println("creating new template") t := template.New("") log.Println("parsing template file") t, err = t.ParseFiles("./hosted/credentials.html") if err != nil { log.Println(err) } log.Println("creating a credentials struct") creds := Credentials{ Username: string(username), Accesscode: string(accesscode), Hostname: string(os.Getenv("HOSTNAME")), } log.Println("executing the template") t.ExecuteTemplate(w, "credentials", creds) log.Println("done executing the template") }