diff --git a/README.md b/README.md index 378a3c1..73f87f6 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ HTTP * 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: * __jid__ : JID of the user (user@host/resource or user@host) * __domain__ : Domain you want to access diff --git a/http/http.go b/http/http.go index ce72299..7a5da46 100644 --- a/http/http.go +++ b/http/http.go @@ -74,13 +74,13 @@ func authHandler(w http.ResponseWriter, r *http.Request) { chanAnswer := make(chan string) - client := new(xmpp.Client) - client.JID = jid - client.Method = method - client.Domain = domain - client.Transaction = transaction - client.ChanReply = chanAnswer - client.QueryClient() + 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: @@ -101,14 +101,14 @@ func authHandler(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusUnauthorized) } - switch client.TypeSend { + switch confirmation.TypeSend { case xmpp.TYPE_SEND_IQ: log.Printf("%sDelete IQ", LogDebug) - delete(xmpp.WaitIqMessages, client.IdMap) + delete(xmpp.WaitIqMessages, confirmation.IdMap) case xmpp.TYPE_SEND_MESSAGE: log.Printf("%sDelete Message", LogDebug) - delete(xmpp.WaitMessageAnswers, client.IdMap) + delete(xmpp.WaitMessageAnswers, confirmation.IdMap) } } diff --git a/xmpp/client.go b/xmpp/client.go deleted file mode 100644 index b3ba366..0000000 --- a/xmpp/client.go +++ /dev/null @@ -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) -} diff --git a/xmpp/confirmation.go b/xmpp/confirmation.go new file mode 100644 index 0000000..2885147 --- /dev/null +++ b/xmpp/confirmation.go @@ -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) +} diff --git a/xmpp/xmpp.go b/xmpp/xmpp.go index e3df8d3..06208e1 100644 --- a/xmpp/xmpp.go +++ b/xmpp/xmpp.go @@ -28,8 +28,8 @@ var ( ChanAction = make(chan string) - WaitMessageAnswers = make(map[string]*Client) - WaitIqMessages = make(map[string]*Client) + WaitMessageAnswers = make(map[string]*Confirmation) + WaitIqMessages = make(map[string]*Confirmation) Debug = true ) @@ -54,15 +54,15 @@ func mainXMPP() { case *xmpp.Message: confirm := v.Confir if confirm != nil { - client := WaitMessageAnswers[confirm.Id] - processConfirm(v, client) + confirmation := WaitMessageAnswers[confirm.Id] + processConfirm(v, confirmation) } else { // If body is the confirmation id, it will be considerated as accepted. - // In order to be compatible with all clients. - client := WaitMessageAnswers[v.Body] + // In order to be compatible with all confirmations. + confirmation := WaitMessageAnswers[v.Body] jidFrom, _ := xmpp.ParseJID(v.From) - if client != nil && client.JID == jidFrom.Bare() { - processConfirm(v, client) + if confirmation != nil && confirmation.JID == jidFrom.Bare() { + processConfirm(v, confirmation) } } @@ -85,15 +85,15 @@ func mainXMPP() { case xmpp.NSHTTPAuth: confirm := &xmpp.Confirm{} v.PayloadDecode(confirm) - client := WaitIqMessages[v.Id] - processConfirm(v, client) + confirmation := WaitIqMessages[v.Id] + processConfirm(v, confirmation) default: // Handle reply iq that doesn't contain HTTP-Auth namespace - client := WaitIqMessages[v.Id] - processConfirm(v, client) + confirmation := WaitIqMessages[v.Id] + processConfirm(v, confirmation) - if client == nil { + if confirmation == nil { reply := v.Response(xmpp.IQTypeError) reply.PayloadEncode(xmpp.NewError("cancel", xmpp.FeatureNotImplemented, "")) 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) iq, iqOK := x.(*xmpp.Iq) - if client != nil { + if confirmation != nil { if mesOK && mes.Error != nil { // Message error errCondition := mes.Error.Condition() if errCondition == xmpp.ServiceUnavailable { // unreachable - client.ChanReply <- REPLY_UNREACHABLE + confirmation.ChanReply <- REPLY_UNREACHABLE } else { - client.ChanReply <- REPLY_DENY + confirmation.ChanReply <- REPLY_DENY } } else if iqOK && iq.Error != nil { @@ -126,18 +126,18 @@ func processConfirm(x interface{}, client *Client) { errCondition := iq.Error.Condition() if errCondition == xmpp.ServiceUnavailable || errCondition == xmpp.FeatureNotImplemented { // send by message if client doesn't implemente it - client.JID = strings.SplitN(client.JID, "/", 2)[0] - go client.QueryClient() + confirmation.JID = strings.SplitN(confirmation.JID, "/", 2)[0] + go confirmation.SendConfirmation() } else if errCondition == xmpp.RemoteServerNotFound { // unreachable - client.ChanReply <- REPLY_UNREACHABLE + confirmation.ChanReply <- REPLY_UNREACHABLE } else { - client.ChanReply <- REPLY_DENY + confirmation.ChanReply <- REPLY_DENY } } else { // No error - client.ChanReply <- REPLY_OK + confirmation.ChanReply <- REPLY_OK } } }