You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
3.3 KiB
119 lines
3.3 KiB
4 years ago
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"math/rand"
|
||
|
"net/http"
|
||
|
"strings"
|
||
|
"time"
|
||
|
|
||
|
"github.com/gorilla/mux"
|
||
|
)
|
||
|
|
||
|
func reqPass(w http.ResponseWriter, r *http.Request) {
|
||
|
username := r.FormValue("UserName")
|
||
|
ipaddr := r.Header.Get("X-Real-IP")
|
||
|
log.LogInfo(fmt.Sprintf("reqPass called:```username: %s\nip : %s```", username, ipaddr))
|
||
|
sendPassword(username, ipaddr)
|
||
|
http.Redirect(w, r, "/login", 302)
|
||
|
}
|
||
|
|
||
|
func tryLogin(w http.ResponseWriter, r *http.Request) {
|
||
|
session, err := store.Get(r, "2fa")
|
||
|
if err != nil {
|
||
|
log.LogWarn("Error opening session for 2fa store")
|
||
|
}
|
||
|
vars := mux.Vars(r)
|
||
|
username := vars["username"]
|
||
|
password := vars["password"]
|
||
|
ip := r.Header.Get("X-Real-IP")
|
||
|
if len(username) == 0 {
|
||
|
username = r.FormValue("UserName")
|
||
|
password = r.FormValue("TempPass")
|
||
|
}
|
||
|
access, _ := detectUser(r, "tryLogin")
|
||
|
if !access {
|
||
|
log.LogDebug(fmt.Sprintf("%s is attempting login", getSessionIdentifier(r)))
|
||
|
access = usePassword(username, password, ip)
|
||
|
if access {
|
||
|
log.LogInfo(fmt.Sprintf("%s has successfully logged in from %s", username, ip))
|
||
|
log.LogDebug(fmt.Sprintf("```%+v```", session.Values))
|
||
|
session.Values["username"] = username
|
||
|
session.Values["ip"] = ip
|
||
|
session.Values["timestamp"] = fmt.Sprintf("%+v", time.Now())
|
||
|
err = session.Save(r, w)
|
||
|
if err != nil {
|
||
|
log.LogWarn(fmt.Sprintf("Error saving cookie. ```%+v```", err))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fmt.Fprintf(w, "<br><p>Login Success: %+v</p><br>Session: %+v", access, session.Values)
|
||
|
}
|
||
|
|
||
|
func usePassword(user string, pass string, ip string) bool {
|
||
|
tok := toks[user]
|
||
|
delete(toks, user)
|
||
|
if time.Since(tok.timestamp) > (time.Minute * 5) {
|
||
|
log.LogWarn(fmt.Sprintf("%s attempted to use expired token.", user))
|
||
|
return false
|
||
|
}
|
||
|
if tok.ip != ip {
|
||
|
log.LogWarn(fmt.Sprintf("%s attempted to use an improper IP.", user))
|
||
|
return false
|
||
|
}
|
||
|
if tok.password != pass {
|
||
|
log.LogWarn(fmt.Sprintf("%s attempted to use an improper password. %s vs %s", user, tok.password, pass))
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func genPassword(length int) string {
|
||
|
rand.Seed(time.Now().UnixNano())
|
||
|
chars := []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
|
||
|
"abcdefghijklmnopqrstuvwxyz" +
|
||
|
"0123456789")
|
||
|
var b strings.Builder
|
||
|
for i := 0; i < length; i++ {
|
||
|
b.WriteRune(chars[rand.Intn(len(chars))])
|
||
|
}
|
||
|
return b.String() // E.g. "ExcbsVQs"
|
||
|
}
|
||
|
func sendPassword(user string, ipaddr string) {
|
||
|
str := genPassword(8)
|
||
|
m, _ := dg.GuildMember(config.GuildID, user)
|
||
|
toks[m.User.Username] = tokens{
|
||
|
username: user,
|
||
|
ip: ipaddr,
|
||
|
password: str,
|
||
|
timestamp: time.Now(),
|
||
|
}
|
||
|
pmChann, _ := dg.UserChannelCreate(user)
|
||
|
dg.ChannelMessageSend(pmChann.ID, fmt.Sprintf("A temporary password was requested from %s:", ipaddr))
|
||
|
dg.ChannelMessageSend(pmChann.ID, fmt.Sprintf("```%s```", str))
|
||
|
|
||
|
}
|
||
|
|
||
|
func getSessionIdentifier(r *http.Request) string {
|
||
|
ipaddr := r.Header.Get("X-Real-IP")
|
||
|
if ipaddr == "" {
|
||
|
ipaddr = r.RemoteAddr
|
||
|
}
|
||
|
uri := r.URL.Path
|
||
|
return fmt.Sprintf("%s:%s", ipaddr, uri)
|
||
|
}
|
||
|
|
||
|
func detectUser(r *http.Request, callFunc string) (bool, string) {
|
||
|
log.LogInfo(fmt.Sprintf("%s called detectUser", getSessionIdentifier(r)))
|
||
|
session, err := store.Get(r, "2fa")
|
||
|
if err != nil {
|
||
|
log.LogDebug(fmt.Sprintf("Unable to open 2fa session in %s", callFunc))
|
||
|
}
|
||
|
if session.Values["username"] != nil {
|
||
|
return true, fmt.Sprintf("%s", session.Values["username"])
|
||
|
}
|
||
|
return false, ""
|
||
|
}
|