HTTPAuthentificationOverXMPP/http/http.go

173 lines
3.9 KiB
Go

package http
import (
"git.kingpenguin.tk/chteufleur/HTTPAuthentificationOverXMPP.git/xmpp"
"fmt"
"log"
"math/rand"
"net/http"
"strconv"
"strings"
"time"
)
const (
LogInfo = "\t[HTTP INFO]\t"
LogError = "\t[HTTP ERROR]\t"
LogDebug = "\t[HTTP DEBUG]\t"
PARAM_JID = "jid"
METHOD_ACCESS = "method"
DOMAIN_ACCESS = "domain"
TRANSACTION_ID = "transaction_id"
TIMEOUTE = "timeout"
ROUTE_ROOT = "/"
ROUTE_AUTH = "/auth"
RETURN_VALUE_OK = "OK"
RETURN_VALUE_NOK = "NOK"
MAX_PORT_VAL = 65535
StatusUnknownError = 520
StatusUnreachable = 523
)
var (
HttpPortBind = -1
HttpsPortBind = -1
CertPath = "./cert.pem"
KeyPath = "./key.pem"
ChanRequest = make(chan interface{}, 5)
TimeoutSec = 60 // 1 min
MaxTimeout = 300 // 5 min
BindAddressIPv4 = "127.0.0.1"
BindAddressIPv6 = "[::1]"
)
func init() {
rand.Seed(time.Now().UTC().UnixNano())
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to HTTP authentification over XMPP")
}
func authHandler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
jid := strings.Join(r.Form[PARAM_JID], "")
method := strings.Join(r.Form[METHOD_ACCESS], "")
domain := strings.Join(r.Form[DOMAIN_ACCESS], "")
if jid == "" || method == "" || domain == "" {
// If mandatory params is missing
log.Printf("%sMandatory params is missing", LogInfo)
w.WriteHeader(http.StatusBadRequest)
return
}
transaction := strings.Join(r.Form[TRANSACTION_ID], "")
timeoutStr := strings.Join(r.Form[TIMEOUTE], "")
log.Printf("%sAuth %s", LogInfo, jid)
timeout, err := strconv.Atoi(timeoutStr)
if err != nil || timeout <= 0 {
timeout = TimeoutSec
}
if timeout > MaxTimeout {
timeout = MaxTimeout
}
chanAnswer := make(chan string)
confirmation := new(xmpp.Confirmation)
confirmation.JID = jid
confirmation.Method = method
confirmation.Domain = domain
confirmation.Transaction = transaction
confirmation.ChanReply = chanAnswer
confirmation.SendConfirmation()
select {
case answer := <-chanAnswer:
switch answer {
case xmpp.REPLY_OK:
w.WriteHeader(http.StatusOK)
case xmpp.REPLY_DENY:
w.WriteHeader(http.StatusUnauthorized)
case xmpp.REPLY_UNREACHABLE:
w.WriteHeader(StatusUnreachable)
default:
w.WriteHeader(StatusUnknownError)
}
case <-time.After(time.Duration(timeout) * time.Second):
w.WriteHeader(http.StatusUnauthorized)
}
switch confirmation.TypeSend {
case xmpp.TYPE_SEND_IQ:
log.Printf("%sDelete IQ", LogDebug)
delete(xmpp.WaitIqMessages, confirmation.IdMap)
case xmpp.TYPE_SEND_MESSAGE:
log.Printf("%sDelete Message", LogDebug)
delete(xmpp.WaitMessageAnswers, confirmation.IdMap)
}
}
func Run() {
log.Printf("%sRunning", LogInfo)
http.HandleFunc(ROUTE_ROOT, indexHandler)
http.HandleFunc(ROUTE_AUTH, authHandler)
if HttpPortBind > 0 {
go runHttp(BindAddressIPv4)
if BindAddressIPv4 != "0.0.0.0" {
go runHttp(BindAddressIPv6)
}
} else if HttpPortBind == 0 {
HttpPortBind = rand.Intn(MAX_PORT_VAL)
go runHttp(BindAddressIPv4)
if BindAddressIPv4 != "0.0.0.0" {
go runHttp(BindAddressIPv6)
}
}
if HttpsPortBind > 0 {
go runHttps(BindAddressIPv4)
if BindAddressIPv6 != "0.0.0.0" {
go runHttps(BindAddressIPv6)
}
} else if HttpsPortBind == 0 {
HttpsPortBind = rand.Intn(MAX_PORT_VAL)
go runHttps(BindAddressIPv4)
if BindAddressIPv6 != "0.0.0.0" {
go runHttps(BindAddressIPv6)
}
}
}
func runHttp(bindAddress string) {
port := strconv.Itoa(HttpPortBind)
log.Printf("%sHTTP listenning on %s:%s", LogInfo, bindAddress, port)
err := http.ListenAndServe(bindAddress+":"+port, nil)
if err != nil {
log.Fatal("%sListenAndServe: ", LogError, err)
}
}
func runHttps(bindAddress string) {
port := strconv.Itoa(HttpsPortBind)
log.Printf("%sHTTPS listenning on %s:%s", LogInfo, bindAddress, port)
err := http.ListenAndServeTLS(bindAddress+":"+port, CertPath, KeyPath, nil)
if err != nil {
log.Fatal("%sListenAndServe: ", LogError, err)
}
}