Change Client struct to Confirmation struct in order to be more clear
This commit is contained in:
parent
5ae82dfff6
commit
20dc1ee9e8
|
|
@ -34,7 +34,7 @@ HTTP
|
||||||
* http_timeoute_sec : Define a timeout if user did not give an answer to the request (default: 60)
|
* http_timeoute_sec : Define a timeout if user did not give an answer to the request (default: 60)
|
||||||
|
|
||||||
|
|
||||||
### Utilization
|
### Usage
|
||||||
To ask authorization, just send an HTTP request to the path ``/auth`` with parameters:
|
To ask authorization, just send an HTTP request to the path ``/auth`` with parameters:
|
||||||
* __jid__ : JID of the user (user@host/resource or user@host)
|
* __jid__ : JID of the user (user@host/resource or user@host)
|
||||||
* __domain__ : Domain you want to access
|
* __domain__ : Domain you want to access
|
||||||
|
|
|
||||||
20
http/http.go
20
http/http.go
|
|
@ -74,13 +74,13 @@ func authHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
chanAnswer := make(chan string)
|
chanAnswer := make(chan string)
|
||||||
|
|
||||||
client := new(xmpp.Client)
|
confirmation := new(xmpp.Confirmation)
|
||||||
client.JID = jid
|
confirmation.JID = jid
|
||||||
client.Method = method
|
confirmation.Method = method
|
||||||
client.Domain = domain
|
confirmation.Domain = domain
|
||||||
client.Transaction = transaction
|
confirmation.Transaction = transaction
|
||||||
client.ChanReply = chanAnswer
|
confirmation.ChanReply = chanAnswer
|
||||||
client.QueryClient()
|
confirmation.SendConfirmation()
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case answer := <-chanAnswer:
|
case answer := <-chanAnswer:
|
||||||
|
|
@ -101,14 +101,14 @@ func authHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch client.TypeSend {
|
switch confirmation.TypeSend {
|
||||||
case xmpp.TYPE_SEND_IQ:
|
case xmpp.TYPE_SEND_IQ:
|
||||||
log.Printf("%sDelete IQ", LogDebug)
|
log.Printf("%sDelete IQ", LogDebug)
|
||||||
delete(xmpp.WaitIqMessages, client.IdMap)
|
delete(xmpp.WaitIqMessages, confirmation.IdMap)
|
||||||
|
|
||||||
case xmpp.TYPE_SEND_MESSAGE:
|
case xmpp.TYPE_SEND_MESSAGE:
|
||||||
log.Printf("%sDelete Message", LogDebug)
|
log.Printf("%sDelete Message", LogDebug)
|
||||||
delete(xmpp.WaitMessageAnswers, client.IdMap)
|
delete(xmpp.WaitMessageAnswers, confirmation.IdMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
package xmpp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.kingpenguin.tk/chteufleur/go-xmpp.git/src/xmpp"
|
|
||||||
|
|
||||||
"crypto/rand"
|
|
||||||
"log"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
dictionary = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
|
||||||
|
|
||||||
REPLY_UNREACHABLE = "reply_unreachable"
|
|
||||||
REPLY_DENY = "reply_deny"
|
|
||||||
REPLY_OK = "reply_ok"
|
|
||||||
|
|
||||||
TYPE_SEND_MESSAGE = "type_send_message"
|
|
||||||
TYPE_SEND_IQ = "type_send_iq"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Client struct {
|
|
||||||
JID string
|
|
||||||
Method string
|
|
||||||
Domain string
|
|
||||||
Transaction string
|
|
||||||
|
|
||||||
TypeSend string
|
|
||||||
IdMap string
|
|
||||||
|
|
||||||
ChanReply chan string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *Client) QueryClient() {
|
|
||||||
log.Printf("%sQuery JID %s", LogInfo, client.JID)
|
|
||||||
isAutoGeneratedTranctionID := false
|
|
||||||
if client.Transaction == "" {
|
|
||||||
// Random transaction ID generation
|
|
||||||
client.Transaction = TransactionID()
|
|
||||||
isAutoGeneratedTranctionID = true
|
|
||||||
}
|
|
||||||
clientJID, _ := xmpp.ParseJID(client.JID)
|
|
||||||
if clientJID.Resource == "" {
|
|
||||||
client.askViaMessage(isAutoGeneratedTranctionID)
|
|
||||||
} else {
|
|
||||||
client.askViaIQ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *Client) askViaIQ() {
|
|
||||||
stanzaID++
|
|
||||||
stanzaIDstr := strconv.Itoa(stanzaID)
|
|
||||||
m := xmpp.Iq{Type: xmpp.IQTypeGet, To: client.JID, From: jid.Domain, Id: stanzaIDstr}
|
|
||||||
confirm := &xmpp.Confirm{Id: client.Transaction, Method: client.Method, URL: client.Domain}
|
|
||||||
m.PayloadEncode(confirm)
|
|
||||||
WaitIqMessages[stanzaIDstr] = client
|
|
||||||
comp.Out <- m
|
|
||||||
|
|
||||||
client.TypeSend = TYPE_SEND_IQ
|
|
||||||
client.IdMap = stanzaIDstr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *Client) askViaMessage(isAutoGeneratedTranctionID bool) {
|
|
||||||
m := xmpp.Message{From: jid.Domain, To: client.JID, Type: xmpp.MessageTypeNormal}
|
|
||||||
|
|
||||||
m.Thread = xmpp.SessionID()
|
|
||||||
m.Body = client.Domain + " (with method " + client.Method + ") need to validate your identity, do you agree ?"
|
|
||||||
m.Body += "\nValidation code : " + client.Transaction
|
|
||||||
if !isAutoGeneratedTranctionID {
|
|
||||||
// Send only if the transaction ID is not autogenerated
|
|
||||||
m.Body += "\nPlease check that this code is the same as on " + client.Domain
|
|
||||||
}
|
|
||||||
m.Body += "\n\nIf your client doesn't support that functionnality, please send back the validation code to confirm the request."
|
|
||||||
m.Confir = &xmpp.Confirm{Id: client.Transaction, Method: client.Method, URL: client.Domain}
|
|
||||||
|
|
||||||
log.Printf("%sSend message %v", LogInfo, m)
|
|
||||||
WaitMessageAnswers[client.Transaction] = client
|
|
||||||
comp.Out <- m
|
|
||||||
|
|
||||||
client.TypeSend = TYPE_SEND_MESSAGE
|
|
||||||
client.IdMap = client.Transaction
|
|
||||||
}
|
|
||||||
|
|
||||||
func TransactionID() string {
|
|
||||||
var bytes = make([]byte, 8)
|
|
||||||
if _, err := rand.Read(bytes); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
for k, v := range bytes {
|
|
||||||
bytes[k] = dictionary[v%byte(len(dictionary))]
|
|
||||||
}
|
|
||||||
return string(bytes)
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
package xmpp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.kingpenguin.tk/chteufleur/go-xmpp.git/src/xmpp"
|
||||||
|
|
||||||
|
"crypto/rand"
|
||||||
|
"log"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
dictionary = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
REPLY_UNREACHABLE = "reply_unreachable"
|
||||||
|
REPLY_DENY = "reply_deny"
|
||||||
|
REPLY_OK = "reply_ok"
|
||||||
|
|
||||||
|
TYPE_SEND_MESSAGE = "type_send_message"
|
||||||
|
TYPE_SEND_IQ = "type_send_iq"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Confirmation struct {
|
||||||
|
JID string
|
||||||
|
Method string
|
||||||
|
Domain string
|
||||||
|
Transaction string
|
||||||
|
|
||||||
|
TypeSend string
|
||||||
|
IdMap string
|
||||||
|
|
||||||
|
ChanReply chan string
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
type Transport interface {
|
||||||
|
Run()
|
||||||
|
Out(chan interface{})
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
func (confirmation *Confirmation) SendConfirmation() {
|
||||||
|
log.Printf("%sQuery JID %s", LogInfo, confirmation.JID)
|
||||||
|
isAutoGeneratedTranctionID := false
|
||||||
|
if confirmation.Transaction == "" {
|
||||||
|
// Random transaction ID generation
|
||||||
|
confirmation.Transaction = TransactionID()
|
||||||
|
isAutoGeneratedTranctionID = true
|
||||||
|
}
|
||||||
|
clientJID, _ := xmpp.ParseJID(confirmation.JID)
|
||||||
|
if clientJID.Resource == "" {
|
||||||
|
confirmation.askViaMessage(isAutoGeneratedTranctionID)
|
||||||
|
} else {
|
||||||
|
confirmation.askViaIQ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (confirmation *Confirmation) askViaIQ() {
|
||||||
|
stanzaID++
|
||||||
|
stanzaIDstr := strconv.Itoa(stanzaID)
|
||||||
|
m := xmpp.Iq{Type: xmpp.IQTypeGet, To: confirmation.JID, From: jid.Domain, Id: stanzaIDstr}
|
||||||
|
confirm := &xmpp.Confirm{Id: confirmation.Transaction, Method: confirmation.Method, URL: confirmation.Domain}
|
||||||
|
m.PayloadEncode(confirm)
|
||||||
|
WaitIqMessages[stanzaIDstr] = confirmation
|
||||||
|
comp.Out <- m
|
||||||
|
|
||||||
|
confirmation.TypeSend = TYPE_SEND_IQ
|
||||||
|
confirmation.IdMap = stanzaIDstr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (confirmation *Confirmation) askViaMessage(isAutoGeneratedTranctionID bool) {
|
||||||
|
m := xmpp.Message{From: jid.Domain, To: confirmation.JID, Type: xmpp.MessageTypeNormal}
|
||||||
|
|
||||||
|
m.Thread = xmpp.SessionID()
|
||||||
|
m.Body = confirmation.Domain + " (with method " + confirmation.Method + ") need to validate your identity, do you agree ?"
|
||||||
|
m.Body += "\nValidation code : " + confirmation.Transaction
|
||||||
|
if !isAutoGeneratedTranctionID {
|
||||||
|
// Send only if the transaction ID is not autogenerated
|
||||||
|
m.Body += "\nPlease check that this code is the same as on " + confirmation.Domain
|
||||||
|
}
|
||||||
|
m.Body += "\n\nIf your client doesn't support that functionnality, please send back the validation code to confirm the request."
|
||||||
|
m.Confir = &xmpp.Confirm{Id: confirmation.Transaction, Method: confirmation.Method, URL: confirmation.Domain}
|
||||||
|
|
||||||
|
log.Printf("%sSend message %v", LogInfo, m)
|
||||||
|
WaitMessageAnswers[confirmation.Transaction] = confirmation
|
||||||
|
comp.Out <- m
|
||||||
|
|
||||||
|
confirmation.TypeSend = TYPE_SEND_MESSAGE
|
||||||
|
confirmation.IdMap = confirmation.Transaction
|
||||||
|
}
|
||||||
|
|
||||||
|
func TransactionID() string {
|
||||||
|
var bytes = make([]byte, 8)
|
||||||
|
if _, err := rand.Read(bytes); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for k, v := range bytes {
|
||||||
|
bytes[k] = dictionary[v%byte(len(dictionary))]
|
||||||
|
}
|
||||||
|
return string(bytes)
|
||||||
|
}
|
||||||
44
xmpp/xmpp.go
44
xmpp/xmpp.go
|
|
@ -28,8 +28,8 @@ var (
|
||||||
|
|
||||||
ChanAction = make(chan string)
|
ChanAction = make(chan string)
|
||||||
|
|
||||||
WaitMessageAnswers = make(map[string]*Client)
|
WaitMessageAnswers = make(map[string]*Confirmation)
|
||||||
WaitIqMessages = make(map[string]*Client)
|
WaitIqMessages = make(map[string]*Confirmation)
|
||||||
|
|
||||||
Debug = true
|
Debug = true
|
||||||
)
|
)
|
||||||
|
|
@ -54,15 +54,15 @@ func mainXMPP() {
|
||||||
case *xmpp.Message:
|
case *xmpp.Message:
|
||||||
confirm := v.Confir
|
confirm := v.Confir
|
||||||
if confirm != nil {
|
if confirm != nil {
|
||||||
client := WaitMessageAnswers[confirm.Id]
|
confirmation := WaitMessageAnswers[confirm.Id]
|
||||||
processConfirm(v, client)
|
processConfirm(v, confirmation)
|
||||||
} else {
|
} else {
|
||||||
// If body is the confirmation id, it will be considerated as accepted.
|
// If body is the confirmation id, it will be considerated as accepted.
|
||||||
// In order to be compatible with all clients.
|
// In order to be compatible with all confirmations.
|
||||||
client := WaitMessageAnswers[v.Body]
|
confirmation := WaitMessageAnswers[v.Body]
|
||||||
jidFrom, _ := xmpp.ParseJID(v.From)
|
jidFrom, _ := xmpp.ParseJID(v.From)
|
||||||
if client != nil && client.JID == jidFrom.Bare() {
|
if confirmation != nil && confirmation.JID == jidFrom.Bare() {
|
||||||
processConfirm(v, client)
|
processConfirm(v, confirmation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,15 +85,15 @@ func mainXMPP() {
|
||||||
case xmpp.NSHTTPAuth:
|
case xmpp.NSHTTPAuth:
|
||||||
confirm := &xmpp.Confirm{}
|
confirm := &xmpp.Confirm{}
|
||||||
v.PayloadDecode(confirm)
|
v.PayloadDecode(confirm)
|
||||||
client := WaitIqMessages[v.Id]
|
confirmation := WaitIqMessages[v.Id]
|
||||||
processConfirm(v, client)
|
processConfirm(v, confirmation)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Handle reply iq that doesn't contain HTTP-Auth namespace
|
// Handle reply iq that doesn't contain HTTP-Auth namespace
|
||||||
client := WaitIqMessages[v.Id]
|
confirmation := WaitIqMessages[v.Id]
|
||||||
processConfirm(v, client)
|
processConfirm(v, confirmation)
|
||||||
|
|
||||||
if client == nil {
|
if confirmation == nil {
|
||||||
reply := v.Response(xmpp.IQTypeError)
|
reply := v.Response(xmpp.IQTypeError)
|
||||||
reply.PayloadEncode(xmpp.NewError("cancel", xmpp.FeatureNotImplemented, ""))
|
reply.PayloadEncode(xmpp.NewError("cancel", xmpp.FeatureNotImplemented, ""))
|
||||||
comp.Out <- reply
|
comp.Out <- reply
|
||||||
|
|
@ -106,19 +106,19 @@ func mainXMPP() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func processConfirm(x interface{}, client *Client) {
|
func processConfirm(x interface{}, confirmation *Confirmation) {
|
||||||
mes, mesOK := x.(*xmpp.Message)
|
mes, mesOK := x.(*xmpp.Message)
|
||||||
iq, iqOK := x.(*xmpp.Iq)
|
iq, iqOK := x.(*xmpp.Iq)
|
||||||
|
|
||||||
if client != nil {
|
if confirmation != nil {
|
||||||
if mesOK && mes.Error != nil {
|
if mesOK && mes.Error != nil {
|
||||||
// Message error
|
// Message error
|
||||||
errCondition := mes.Error.Condition()
|
errCondition := mes.Error.Condition()
|
||||||
if errCondition == xmpp.ServiceUnavailable {
|
if errCondition == xmpp.ServiceUnavailable {
|
||||||
// unreachable
|
// unreachable
|
||||||
client.ChanReply <- REPLY_UNREACHABLE
|
confirmation.ChanReply <- REPLY_UNREACHABLE
|
||||||
} else {
|
} else {
|
||||||
client.ChanReply <- REPLY_DENY
|
confirmation.ChanReply <- REPLY_DENY
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if iqOK && iq.Error != nil {
|
} else if iqOK && iq.Error != nil {
|
||||||
|
|
@ -126,18 +126,18 @@ func processConfirm(x interface{}, client *Client) {
|
||||||
errCondition := iq.Error.Condition()
|
errCondition := iq.Error.Condition()
|
||||||
if errCondition == xmpp.ServiceUnavailable || errCondition == xmpp.FeatureNotImplemented {
|
if errCondition == xmpp.ServiceUnavailable || errCondition == xmpp.FeatureNotImplemented {
|
||||||
// send by message if client doesn't implemente it
|
// send by message if client doesn't implemente it
|
||||||
client.JID = strings.SplitN(client.JID, "/", 2)[0]
|
confirmation.JID = strings.SplitN(confirmation.JID, "/", 2)[0]
|
||||||
go client.QueryClient()
|
go confirmation.SendConfirmation()
|
||||||
} else if errCondition == xmpp.RemoteServerNotFound {
|
} else if errCondition == xmpp.RemoteServerNotFound {
|
||||||
// unreachable
|
// unreachable
|
||||||
client.ChanReply <- REPLY_UNREACHABLE
|
confirmation.ChanReply <- REPLY_UNREACHABLE
|
||||||
} else {
|
} else {
|
||||||
client.ChanReply <- REPLY_DENY
|
confirmation.ChanReply <- REPLY_DENY
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// No error
|
// No error
|
||||||
client.ChanReply <- REPLY_OK
|
confirmation.ChanReply <- REPLY_OK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue