Compare commits
34 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
ea4f78e23b | |
|
|
8384410023 | |
|
|
5fa7fe5235 | |
|
|
a330e7df29 | |
|
|
a00eb69071 | |
|
|
6337ad74af | |
|
|
ce6a3a26af | |
|
|
a85f476600 | |
|
|
2f301ffc80 | |
|
|
c146c8dae2 | |
|
|
bed3e755f7 | |
|
|
90269e40e5 | |
|
|
88f7537bbd | |
|
|
dfa6cd1b32 | |
|
|
39d865b082 | |
|
|
a6f6ef86ac | |
|
|
a070b03c0f | |
|
|
a06062e714 | |
|
|
b61490b75c | |
|
|
89efb0137b | |
|
|
c788a29d46 | |
|
|
0b0611fc45 | |
|
|
a1cd475788 | |
|
|
178a9b4796 | |
|
|
7da25057cf | |
|
|
8847f220fd | |
|
|
4a5ff9f227 | |
|
|
2b101c1c1d | |
|
|
b63a944cb2 | |
|
|
e2fbb6c8e3 | |
|
|
7e9fd69879 | |
|
|
78c8aecb8e | |
|
|
c88ec7a32d | |
|
|
20dc1ee9e8 |
44
README.md
44
README.md
|
|
@ -1,52 +1,70 @@
|
|||
# HTTPAuthentificationOverXMPP
|
||||
# HTTPAuthenticationOverXMPP
|
||||
|
||||
Provide an HTTP anthentification over XMPP. Implementation of [XEP-0070](https://xmpp.org/extensions/xep-0070.html).
|
||||
Provide an HTTP authentication over XMPP. Implementation of [XEP-0070](https://xmpp.org/extensions/xep-0070.html).
|
||||
|
||||
Can be run as a XMPP client or XMPP component.
|
||||
|
||||
|
||||
## Compilation
|
||||
### Dependencies
|
||||
|
||||
* [go-xmpp](https://git.kingpenguin.tk/chteufleur/go-xmpp) for the XMPP part.
|
||||
* [cfg](https://github.com/jimlawless/cfg) for the configuration file.
|
||||
|
||||
### Build and run
|
||||
|
||||
You must first [install go environment](https://golang.org/doc/install) on your system.
|
||||
Then, go into your $GOPATH directory and go get the source code.
|
||||
```sh
|
||||
go get git.kingpenguin.tk/chteufleur/HTTPAuthentificationOverXMPP.git
|
||||
```
|
||||
|
||||
First, you need to go into directory ``$GOPATH/src/chteufleur/HTTPAuthentificationOverXMPP.git``.
|
||||
Then, you can run the project directly by using command ``go run main.go``.
|
||||
Or, in order to build the project you can run the command ``go build main.go``.
|
||||
It will generate a binary that you can run as any binary file.
|
||||
|
||||
### Configure
|
||||
Configure the gateway by editing the ``httpAuth.cfg`` file in order to give all XMPP component and HTTP server informations.
|
||||
An example of the config file can be found in [the repos](https://git.kingpenguin.tk/chteufleur/HTTPAuthentificationOverXMPP/src/master/httpAuth.cfg).
|
||||
Configure the gateway by editing the ``httpAuth.conf`` file in order to give all XMPP and HTTP server informations. This configuration file has to be placed following the [XDG specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) (example ``/etc/xdg/http-auth/httpAuth.conf``).
|
||||
An example of the config file can be found in [the repos](https://git.kingpenguin.tk/chteufleur/HTTPAuthentificationOverXMPP/src/master/httpAuth.conf).
|
||||
|
||||
XMPP
|
||||
* xmpp_server_address : Component server address connection (default: 127.0.0.1)
|
||||
* xmpp_server_port : Component server port connection (default: 5347)
|
||||
* xmpp_hostname : Component hostname
|
||||
* xmpp_secret : Component password
|
||||
* __xmpp_jid__ : Account JID
|
||||
* __xmpp_secret__ : Account password
|
||||
* xmpp_debug : Enable debug log at true (default: false)
|
||||
* xmpp_verify_cert_validity : Enable certificate verification (default: true)
|
||||
* xmpp_default_lang : Message default languages
|
||||
|
||||
HTTP
|
||||
* http_port : HTTP port to bind (default: 9090, desactive: -1)
|
||||
* https_port : HTTPS port to bind (default: 9093, desactive: -1)
|
||||
* http_port : HTTP port to bind (default: -1, desactive: -1)
|
||||
* https_port : HTTPS port to bind (default: -1, desactive: -1)
|
||||
* https_cert_path : Path to the certificate file (default: ./cert.pem)
|
||||
* https_key_path : Path to the key file (default: ./key.pem)
|
||||
* http_timeoute_sec : Define a timeout if user did not give an answer to the request (default: 60)
|
||||
* http_timeout_sec : Define a timeout if user did not give an answer to the request (default: 60)
|
||||
* http_bind_address_ipv4 : Bind address on IPv4 (default: 127.0.0.1)
|
||||
* http_bind_address_ipv6 : Bind address on IPv6 (default: [::1])
|
||||
|
||||
__Bold config__ are mandatory.
|
||||
|
||||
### Utilization
|
||||
If ``http_bind_address_ipv4`` is set to ``0.0.0.0``, it will bind all address on IPv4 __AND__ IPv6.
|
||||
|
||||
The lang messages file must be placed into the same directory than the configuration file.
|
||||
An example of this file can be found in [the repos](https://git.kingpenguin.tk/chteufleur/HTTPAuthentificationOverXMPP/src/master/messages.lang)
|
||||
|
||||
### 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
|
||||
* __method__ : Method you access the domain
|
||||
* transaction_id : Transaction identifier (auto generated if not provide)
|
||||
* __transaction_id__ : Transaction identifier (auto generated if not provide)
|
||||
* timeout : Timeout of the request in second (default : 60, max : 300)
|
||||
|
||||
__Bold parameters__ are mandatory.
|
||||
|
||||
Example:
|
||||
```
|
||||
GET /auth?jid=user%40host%2fresource&domain=example.org&method=POST&transaction_id=WhatEverYouWant&timeout=120 HTTP/1.1
|
||||
GET /auth?jid=user%40host%2fresource;domain=example.org;method=POST;transaction_id=WhatEverYouWant;timeout=120 HTTP/1.1
|
||||
```
|
||||
|
||||
This will send a request to the given JID, then return HTTP code depending on what appended.
|
||||
|
|
|
|||
22
cert.pem
22
cert.pem
|
|
@ -1,22 +0,0 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDmjCCAoICCQDTJ1wt8ibb0DANBgkqhkiG9w0BAQsFADCBjjELMAkGA1UEBhMC
|
||||
RlIxEzARBgNVBAgMClNvbWUtU3RhdGUxEDAOBgNVBAcMB1ZhbGVuY2UxITAfBgNV
|
||||
BAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEUMBIGA1UEAwwLZXhhbXBsZS5v
|
||||
cmcxHzAdBgkqhkiG9w0BCQEWEHRvdG9AZXhhbXBsZS5vcmcwHhcNMTYwNzE0MDgx
|
||||
MDA3WhcNMTcwNzE0MDgxMDA3WjCBjjELMAkGA1UEBhMCRlIxEzARBgNVBAgMClNv
|
||||
bWUtU3RhdGUxEDAOBgNVBAcMB1ZhbGVuY2UxITAfBgNVBAoMGEludGVybmV0IFdp
|
||||
ZGdpdHMgUHR5IEx0ZDEUMBIGA1UEAwwLZXhhbXBsZS5vcmcxHzAdBgkqhkiG9w0B
|
||||
CQEWEHRvdG9AZXhhbXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQCjNtyD6vXdVSj+Vmin/1t4JApafQ4475oJsvsNfd2cMgQ9856RZPyZFCCe
|
||||
9veffUSV9ffYcgtPF8ZfRkOLZvSzYNYrrgI+Qsp2Y/Mw1hAupn2IadjdB0ZAFpZi
|
||||
fnH5tuXSIiPbrl1sQZxSdIhgRPdj6scnBFwjbbm+DfyQYvjtm5LTOYbNOc/Sali+
|
||||
lSdC22Z69nL7rscg3LFeBb8Oqx6MU8cvQ/nNsfxP+Ynimon3E28mP8VftyL81J6z
|
||||
g8H6ly9R3kkapPrUg3CWP1z5rya+MdujcxkhEfO9oybSokaU/VkpMfrM4iBjs9m5
|
||||
+hU3kWfVqB38OYUVEz2GagWrvDdJAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAD3/
|
||||
fkCOvAhy38R10IgYEVH8MlrG3Rpy7CCYhUPgBrdFRgFAhwegDSc5my4rgiGmETkX
|
||||
SlEppuHyoMNe8Sv70ibflqrCcwMPz/BWRlTDSWdwUqNjr4RfOT6LrO/9bZQT4tV8
|
||||
Av4smslUaXiKuFyJLY1uFXbw2BqZTQQgaDQGdaqRNkCPRT00+VUbzR/qOEQ0Kv0U
|
||||
QAX1tN1kmrJo5ccGB9WVvijp1ZlimMjtvh5v7Uxa6Wl4l7D9B1+5glEhPKunOlcK
|
||||
MAHrHIuBRuuQUmtdk9zj3HYZtniChflPUO3+QWr3nfA6IhVEvz1wa4BQFzfwm4NY
|
||||
eFcBWz6pr3zuawKjUlk=
|
||||
-----END CERTIFICATE-----
|
||||
73
http/http.go
73
http/http.go
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"fmt"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -28,23 +29,31 @@ const (
|
|||
RETURN_VALUE_OK = "OK"
|
||||
RETURN_VALUE_NOK = "NOK"
|
||||
|
||||
MAX_PORT_VAL = 65535
|
||||
|
||||
StatusUnknownError = 520
|
||||
StatusUnreachable = 523
|
||||
)
|
||||
|
||||
var (
|
||||
HttpPortBind = 9090
|
||||
HttpsPortBind = 9093
|
||||
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) {
|
||||
// TODO
|
||||
fmt.Fprintf(w, "Welcome to HTTP authentification over XMPP")
|
||||
}
|
||||
|
||||
|
|
@ -53,15 +62,15 @@ func authHandler(w http.ResponseWriter, r *http.Request) {
|
|||
jid := strings.Join(r.Form[PARAM_JID], "")
|
||||
method := strings.Join(r.Form[METHOD_ACCESS], "")
|
||||
domain := strings.Join(r.Form[DOMAIN_ACCESS], "")
|
||||
transaction := strings.Join(r.Form[TRANSACTION_ID], "")
|
||||
|
||||
if jid == "" || method == "" || domain == "" {
|
||||
if jid == "" || method == "" || domain == "" || transaction == "" {
|
||||
// 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)
|
||||
|
|
@ -74,13 +83,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 +110,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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -119,26 +128,44 @@ func Run() {
|
|||
http.HandleFunc(ROUTE_AUTH, authHandler)
|
||||
|
||||
if HttpPortBind > 0 {
|
||||
go runHttp()
|
||||
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()
|
||||
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() {
|
||||
func runHttp(bindAddress string) {
|
||||
port := strconv.Itoa(HttpPortBind)
|
||||
log.Printf("%sHTTP listenning on port %s", LogInfo, port)
|
||||
err := http.ListenAndServe(":"+port, nil)
|
||||
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() {
|
||||
func runHttps(bindAddress string) {
|
||||
port := strconv.Itoa(HttpsPortBind)
|
||||
log.Printf("%sHTTPS listenning on port %s", LogInfo, port)
|
||||
err := http.ListenAndServeTLS(":"+port, CertPath, KeyPath, nil)
|
||||
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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
# XMPP informations
|
||||
# XMPP informations (component)
|
||||
xmpp_server_address=192.168.1.2
|
||||
xmpp_server_port=5347
|
||||
xmpp_hostname=xmppsteam.kingpenguin.tk
|
||||
xmpp_jid=xmppsteam.kingpenguin.tk
|
||||
xmpp_secret=xmpp4steam_password
|
||||
xmpp_debug=true
|
||||
xmpp_verify_cert_validity=true
|
||||
|
||||
# HTTP informations
|
||||
http_bind_address_ipv4=127.0.0.1
|
||||
http_bind_address_ipv6=[::1]
|
||||
http_port=9090
|
||||
https_port=9093
|
||||
https_cert_path=./cert.pem
|
||||
https_key_path=./key.pem
|
||||
http_timeoute_sec=60
|
||||
http_timeout_sec=60
|
||||
27
key.pem
27
key.pem
|
|
@ -1,27 +0,0 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAozbcg+r13VUo/lZop/9beCQKWn0OOO+aCbL7DX3dnDIEPfOe
|
||||
kWT8mRQgnvb3n31ElfX32HILTxfGX0ZDi2b0s2DWK64CPkLKdmPzMNYQLqZ9iGnY
|
||||
3QdGQBaWYn5x+bbl0iIj265dbEGcUnSIYET3Y+rHJwRcI225vg38kGL47ZuS0zmG
|
||||
zTnP0mpYvpUnQttmevZy+67HINyxXgW/DqsejFPHL0P5zbH8T/mJ4pqJ9xNvJj/F
|
||||
X7ci/NSes4PB+pcvUd5JGqT61INwlj9c+a8mvjHbo3MZIRHzvaMm0qJGlP1ZKTH6
|
||||
zOIgY7PZufoVN5Fn1agd/DmFFRM9hmoFq7w3SQIDAQABAoIBAQCAI6lbVJP1Uk/d
|
||||
5v9BrkUk/L64LmiFIPAB32glPoVHhSk5blQ2+F8s29WEmIbuy42WYsdUQq1ISnUv
|
||||
Bd4vywQg9M0Q/Au8z/lem7gpxlZsGcCC4f8mAPkRhepJp9ZZ5FNo9+7JIYstXBGb
|
||||
1uvfESZdZs02f8DK+/GRGjAJN/sRqAo4MvwZzrX9DIMnTt5MiujCAWOMX4rXT316
|
||||
epSyUAxMnNzC3On32TmGqrHXTF7KMGPjbSupAHDS4F8iL9ntFF2QPcW5um8jEneZ
|
||||
ln/oJo2+2LYFJPcj0BbvCAcRaIumvHNQgfC0ispStCR37IlEZKyQXUtX/z/BPQO/
|
||||
d8KzylqRAoGBANl1tMVz4d20kkQzyXOCmQ7C/y98AHWDiFH2Iq/QMV21TFomit66
|
||||
SR8RVwWH3G6C8cQRHFa504iDP3Lo/jq+rf4SMwEJq+X5aVkThCq5DDZech/qslyF
|
||||
FTA4IIkcqxF5/UOQg3UxGKU2I7mKLLgnhaPvPqcd7t/PzXAgJqV45ElFAoGBAMAk
|
||||
AHPZFpb5IMPbVSen/jZ6cbNtRsOyUv2Vlz+Pkjbfl0SsxOInPZxwwEcEgLC2micN
|
||||
CH1rTZXpMLKOr/VBdkbp4uMMR8X2kro02b9zlmBmAXleyuAPbQAbRn4epnnfzqxb
|
||||
TcJNHQJT4uQRhtshTQ2GqnHXei/ZMBrI35VCN5w1AoGBAM9c3LqE3Fbrv6Zls64A
|
||||
VS+sZmbDWjS07qMpkL4SS2DOZzZ4Fmh5PwzvHgpaGasQFrcekeVpYfuFHFXZM8SU
|
||||
25mxhQ1ySYcNJJYadCfBOZIG0dD5nod3KFNI0k2tFrudlhJ9lb2EybmRPNPKnQYm
|
||||
OduvYhE+C/FEWOSY5AFanGX5AoGARxWKrVFlUBl/C7a7fF5kaFdIdW86PPBeT77m
|
||||
I/fDylVSK3AXruuBmb0FBcEes0H7KfNibrQiEhIhmA29/2hmj7m73PAQJachhY5D
|
||||
+NaUjblvVi3BtL9APkfY/pPsVy570bw9umK5FsFeMa5iS/O4BAcMS+3CIK2jZGVo
|
||||
glnrJPkCgYEAiI0nFwbd5oP4bP41zDKU7lrnwrmbCKZr5ZYScw1NtSqKo7aJnhEi
|
||||
fBYMT8aXHVt4ALcI/VzR8LnoTQcJ6Pibn0pZ91sE8FRk99qfnF0rK4LLKF6R+UJH
|
||||
X+dmoMOcHQ9MEyPhNvdgsTo72KMPzJn8q58VTq/6I4we+VCOlZNwlCA=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
84
main.go
84
main.go
|
|
@ -10,16 +10,17 @@ import (
|
|||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
Version = "v0.3.1"
|
||||
configurationFilePath = "httpAuth.cfg"
|
||||
|
||||
default_xmpp_server_address = "127.0.0.1"
|
||||
default_xmpp_server_port = "5347"
|
||||
Version = "v0.5-dev"
|
||||
configurationFilePath = "http-auth/httpAuth.conf"
|
||||
langFilePath = "http-auth/messages.lang"
|
||||
PathConfEnvVariable = "XDG_CONFIG_DIRS"
|
||||
DefaultXdgConfigDirs = "/etc/xdg"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -29,13 +30,13 @@ var (
|
|||
func init() {
|
||||
log.Printf("Running HTTP-Auth %v", Version)
|
||||
|
||||
err := cfg.Load(configurationFilePath, mapConfig)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to load configuration file.", err)
|
||||
if !loadConfigFile() {
|
||||
log.Fatal("Failed to load configuration file.")
|
||||
}
|
||||
loadLangFile()
|
||||
|
||||
// HTTP config
|
||||
httpTimeout, err := strconv.Atoi(mapConfig["http_timeoute_sec"])
|
||||
httpTimeout, err := strconv.Atoi(mapConfig["http_timeout_sec"])
|
||||
if err == nil && httpTimeout > 0 && httpTimeout < http.MaxTimeout {
|
||||
log.Println("Define HTTP timeout to " + strconv.Itoa(httpTimeout) + " second")
|
||||
http.TimeoutSec = httpTimeout
|
||||
|
|
@ -52,28 +53,71 @@ func init() {
|
|||
http.CertPath = mapConfig["https_cert_path"]
|
||||
http.KeyPath = mapConfig["https_key_path"]
|
||||
}
|
||||
bindAddressIPv4 := mapConfig["http_bind_address_ipv4"]
|
||||
if bindAddressIPv4 != "" {
|
||||
http.BindAddressIPv4 = bindAddressIPv4
|
||||
}
|
||||
bindAddressIPv6 := mapConfig["http_bind_address_ipv6"]
|
||||
if bindAddressIPv6 != "" {
|
||||
http.BindAddressIPv6 = bindAddressIPv6
|
||||
}
|
||||
|
||||
// XMPP config
|
||||
xmpp_server_address := mapConfig["xmpp_server_address"]
|
||||
if xmpp_server_address == "" {
|
||||
xmpp_server_address = default_xmpp_server_address
|
||||
if xmpp_server_address != "" {
|
||||
xmpp.Addr = xmpp_server_address
|
||||
}
|
||||
xmpp_server_port := mapConfig["xmpp_server_port"]
|
||||
if xmpp_server_port == "" {
|
||||
xmpp_server_port = default_xmpp_server_port
|
||||
if xmpp_server_port != "" {
|
||||
xmpp.Port = xmpp_server_port
|
||||
}
|
||||
|
||||
xmpp.Addr = xmpp_server_address + ":" + xmpp_server_port
|
||||
xmpp.JidStr = mapConfig["xmpp_hostname"]
|
||||
xmpp.JidStr = mapConfig["xmpp_jid"]
|
||||
xmpp.Secret = mapConfig["xmpp_secret"]
|
||||
xmpp.Debug = mapConfig["xmpp_debug"] == "true"
|
||||
xmpp.VerifyCertValidity = mapConfig["xmpp_verify_cert_validity"] != "false" // Default TRUE
|
||||
}
|
||||
|
||||
func getChanString(c chan interface{}) string {
|
||||
ret := ""
|
||||
i := <-c
|
||||
if v, ok := i.(string); ok {
|
||||
ret = v
|
||||
func loadConfigFile() bool {
|
||||
ret := false
|
||||
envVariable := os.Getenv(PathConfEnvVariable)
|
||||
if envVariable == "" {
|
||||
envVariable = DefaultXdgConfigDirs
|
||||
}
|
||||
for _, path := range strings.Split(envVariable, ":") {
|
||||
log.Println("Try to find configuration file into " + path)
|
||||
configFile := path + "/" + configurationFilePath
|
||||
if _, err := os.Stat(configFile); err == nil {
|
||||
// The config file exist
|
||||
if cfg.Load(configFile, mapConfig) == nil {
|
||||
// And has been loaded succesfully
|
||||
log.Println("Find configuration file at " + configFile)
|
||||
ret = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func loadLangFile() bool {
|
||||
ret := false
|
||||
envVariable := os.Getenv(PathConfEnvVariable)
|
||||
if envVariable == "" {
|
||||
envVariable = DefaultXdgConfigDirs
|
||||
}
|
||||
for _, path := range strings.Split(envVariable, ":") {
|
||||
log.Println("Try to find messages lang file into " + path)
|
||||
langFile := path + "/" + langFilePath
|
||||
if _, err := os.Stat(langFile); err == nil {
|
||||
// The config file exist
|
||||
if cfg.Load(langFile, xmpp.MapLangs) == nil {
|
||||
// And has been loaded succesfully
|
||||
log.Println("Find messages lang file at " + langFile)
|
||||
ret = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
en=_DOMAIN_ (with method _METHOD_) need to validate your identity, do you agree?\nValidation code: _VALIDE_CODE_\nPlease check that this code is the same as on _DOMAIN_.\n\nIf your client doesn't support that functionality, please send back the validation code to confirm the request.
|
||||
fr=_DOMAIN_ (avec la methode _METHOD_) a besoin de valider votre identitée, acceptez-vous ?\nCode de validation : _VALIDE_CODE_\nVeuillez vérifier que ce code est le même que sur _DOMAIN_.\n\nSi votre client ne support pas cette fonctionnalitée, veuilez renvoyer le code de validation pour confirmer la requête.
|
||||
ca=_DOMAIN_ (via _METHOD_) validarà la teva identitat, hi estàs d'acord?\nCodi de validació: _VALIDE_CODE_ \nComprova que aquest codi sigui el mateix que a _DOMAIN_.\n\nSi la teva aplicació no contempla aquesta funcionalitat, respon a aquest missatge amb el codi per a confirmar la petició.
|
||||
es=_DOMAIN_ (via _METHOD_) validará tu identitad, estás de acuerdo?\nCódigo de validación: _VALIDE_CODE_ \nComprueba que el código sea el mismo que en _DOMAIN_.\n\nSi tu aplicación no contempla esta funcionalidad, responde a este mensaje con el código para confirmar la petición.
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
# Packaging
|
||||
|
||||
## Build libraries as shared
|
||||
|
||||
In order to packaged the project, you will need to follow those different steps.
|
||||
We will build libraries as shared libraries.
|
||||
|
||||
The first step is to buid the GO standard library as shared.
|
||||
```
|
||||
$ cd $GOPATH
|
||||
$ go install -buildmode=shared std
|
||||
```
|
||||
|
||||
Next, we will build the 2 libraries to make them shared…
|
||||
```
|
||||
$ cd $GOPATH
|
||||
$ go install -buildmode=shared -linkshared github.com/jimlawless/cfg
|
||||
$ go install -buildmode=shared -linkshared git.kingpenguin.tk/chteufleur/go-xmpp.git/src/xmpp
|
||||
```
|
||||
|
||||
Then finally, build the project with the option that tell to use libraries as shared and not static.
|
||||
```
|
||||
$ cd $GOPATH
|
||||
$ go install -linkshared git.kingpenguin.tk/chteufleur/HTTPAuthentificationOverXMPP.git
|
||||
```
|
||||
|
||||
You will find shared libraries over here :
|
||||
* ``$GOROOT/pkg/linux_amd64_dynlink/libstd.so``
|
||||
* ``$GOPATH/pkg/linux_amd64_dynlink/libgithub.com-jimlawless-cfg.so``
|
||||
* ``$GOPATH/pkg/linux_amd64_dynlink/libgit.kingpenguin.tk-chteufleur-go-xmpp.git-src-xmpp.so``
|
||||
|
||||
And the binary file here :
|
||||
* ``$GOPATH/bin/HTTPAuthentificationOverXMPP.git``
|
||||
|
||||
An example can be found [here](https://github.com/jbuberel/buildmodeshared/tree/master/gofromgo).
|
||||
|
||||
## Configuration
|
||||
|
||||
At the installation, the folder ``$XDG_CONFIG_DIRS/http-auth/`` need to be created (example ``/etc/xdg/http-auth``) where to place the configuration file named ``httpAuth.conf`` and the file lang configuration named ``messages.lang``.
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
[Unit]
|
||||
Description=Provide an HTTP authentication over XMPP (https://xmpp.org/extensions/xep-0070.html)
|
||||
|
||||
[Service]
|
||||
ExecStart=/etc/init.d/http-auth.sh start
|
||||
ExecStop=/etc/init.d/http-auth.sh stop
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#!/bin/sh
|
||||
|
||||
#######################
|
||||
name="httpAuth"
|
||||
dirPath="/usr/local/sbin"
|
||||
#######################
|
||||
sh="/bin/bash"
|
||||
pidPath="/var/run/http-auth/http-auth.pid"
|
||||
#######################
|
||||
|
||||
do_start() {
|
||||
nohup $dirPath/$name &
|
||||
/bin/echo $! > $pidPath
|
||||
}
|
||||
|
||||
do_stop() {
|
||||
if [ -e $pidPath ]
|
||||
then
|
||||
pid=$(/bin/cat $pidPath)
|
||||
kill $pid
|
||||
rm $pidPath
|
||||
fi
|
||||
}
|
||||
|
||||
get_status() {
|
||||
if [ -e $pidPath ] ; then
|
||||
pid=$(/bin/cat $pidPath) ;
|
||||
/bin/echo "$name is running with PID $pid" ;
|
||||
else
|
||||
/bin/echo "$name is stopped" ;
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
case $1 in
|
||||
start)
|
||||
do_start
|
||||
;;
|
||||
stop)
|
||||
do_stop
|
||||
;;
|
||||
restart)
|
||||
do_stop
|
||||
do_start
|
||||
;;
|
||||
status)
|
||||
get_status
|
||||
;;
|
||||
*)
|
||||
/bin/echo "Usage: $0 {start|stop|restart|status}"
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
|
@ -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,97 @@
|
|||
package xmpp
|
||||
|
||||
import (
|
||||
"git.kingpenguin.tk/chteufleur/go-xmpp.git/src/xmpp"
|
||||
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
REPLY_UNREACHABLE = "reply_unreachable"
|
||||
REPLY_DENY = "reply_deny"
|
||||
REPLY_OK = "reply_ok"
|
||||
|
||||
TYPE_SEND_MESSAGE = "type_send_message"
|
||||
TYPE_SEND_IQ = "type_send_iq"
|
||||
|
||||
TEMPLATE_DOMAIN = "_DOMAIN_"
|
||||
TEMPLATE_METHOD = "_METHOD_"
|
||||
TEMPLATE_VALIDATION_CODE = "_VALIDE_CODE_"
|
||||
DEFAULT_MESSAGE = "_DOMAIN_ (with method _METHOD_) need to validate your identity, do you agree ?\nValidation code : _VALIDE_CODE_\nPlease check that this code is the same as on _DOMAIN_.\n\nIf your client doesn't support that functionnality, please send back the validation code to confirm the request."
|
||||
)
|
||||
|
||||
var (
|
||||
MapLangs = make(map[string]string)
|
||||
)
|
||||
|
||||
type Confirmation struct {
|
||||
JID string
|
||||
Method string
|
||||
Domain string
|
||||
Transaction string
|
||||
|
||||
TypeSend string
|
||||
IdMap string
|
||||
|
||||
ChanReply chan string
|
||||
}
|
||||
|
||||
func (confirmation *Confirmation) SendConfirmation() {
|
||||
log.Printf("%sQuery JID %s", LogInfo, confirmation.JID)
|
||||
clientJID, _ := xmpp.ParseJID(confirmation.JID)
|
||||
if clientJID.Resource == "" {
|
||||
confirmation.askViaMessage()
|
||||
} else {
|
||||
confirmation.askViaIQ()
|
||||
}
|
||||
}
|
||||
|
||||
func (confirmation *Confirmation) askViaIQ() {
|
||||
stanzaID++
|
||||
stanzaIDstr := strconv.Itoa(stanzaID)
|
||||
m := xmpp.IQ{Type: xmpp.IQTypeGet, To: confirmation.JID, From: jid.Full(), 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() {
|
||||
m := xmpp.Message{From: jid.Full(), To: confirmation.JID, Type: xmpp.MessageTypeNormal}
|
||||
m.Thread = xmpp.SessionID()
|
||||
confirmation.setBodies(&m)
|
||||
m.Confirm = &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 (confirmation *Confirmation) setBodies(message *xmpp.Message) {
|
||||
msg := DEFAULT_MESSAGE
|
||||
if len(MapLangs) == 0 {
|
||||
msg = strings.Replace(msg, TEMPLATE_DOMAIN, confirmation.Domain, -1)
|
||||
msg = strings.Replace(msg, TEMPLATE_METHOD, confirmation.Method, -1)
|
||||
msg = strings.Replace(msg, TEMPLATE_VALIDATION_CODE, confirmation.Transaction, -1)
|
||||
message.Body = append(message.Body, xmpp.MessageBody{Lang: "en", Value: msg})
|
||||
} else {
|
||||
for key, val := range MapLangs {
|
||||
msg = val
|
||||
msg = strings.Replace(msg, TEMPLATE_DOMAIN, confirmation.Domain, -1)
|
||||
msg = strings.Replace(msg, TEMPLATE_METHOD, confirmation.Method, -1)
|
||||
msg = strings.Replace(msg, TEMPLATE_VALIDATION_CODE, confirmation.Transaction, -1)
|
||||
msg = strings.Replace(msg, "\\n", "\n", -1)
|
||||
msg = strings.Replace(msg, "\\r", "\r", -1)
|
||||
msg = strings.Replace(msg, "\\t", "\t", -1)
|
||||
message.Body = append(message.Body, xmpp.MessageBody{Lang: key, Value: msg})
|
||||
}
|
||||
}
|
||||
}
|
||||
157
xmpp/xmpp.go
157
xmpp/xmpp.go
|
|
@ -8,13 +8,17 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
LogInfo = "\t[XMPP COMPONENT INFO]\t"
|
||||
LogError = "\t[XMPP COMPONENT ERROR]\t"
|
||||
LogDebug = "\t[XMPP COMPONENT DEBUG]\t"
|
||||
LogInfo = "\t[XMPP INFO]\t"
|
||||
LogError = "\t[XMPP ERROR]\t"
|
||||
LogDebug = "\t[XMPP DEBUG]\t"
|
||||
|
||||
DEFAULT_SERVER_ADDRESS = "127.0.0.1"
|
||||
DEFAULT_SERVER_PORT = "5347"
|
||||
)
|
||||
|
||||
var (
|
||||
Addr = "127.0.0.1:5347"
|
||||
Addr = ""
|
||||
Port = ""
|
||||
JidStr = ""
|
||||
Secret = ""
|
||||
|
||||
|
|
@ -28,18 +32,55 @@ 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
|
||||
Debug = true
|
||||
VerifyCertValidity = true
|
||||
|
||||
identity = &xmpp.DiscoIdentity{Category: "client", Type: "bot", Name: "HTTP authentication over XMPP"}
|
||||
)
|
||||
|
||||
func Run() {
|
||||
var addr string
|
||||
var isComponent bool
|
||||
|
||||
log.Printf("%sRunning", LogInfo)
|
||||
// Create stream and configure it as a component connection.
|
||||
jid = must(xmpp.ParseJID(JidStr)).(xmpp.JID)
|
||||
stream = must(xmpp.NewStream(Addr, &xmpp.StreamConfig{LogStanzas: Debug})).(*xmpp.Stream)
|
||||
comp = must(xmpp.NewComponentXMPP(stream, jid, Secret)).(*xmpp.XMPP)
|
||||
isComponent = jid.Node == ""
|
||||
|
||||
if isComponent {
|
||||
// component
|
||||
if Addr == "" {
|
||||
Addr = DEFAULT_SERVER_ADDRESS
|
||||
}
|
||||
if Port == "" {
|
||||
Port = DEFAULT_SERVER_PORT
|
||||
}
|
||||
addr = Addr + ":" + Port
|
||||
} else {
|
||||
// client
|
||||
if Addr == "" {
|
||||
addrs := must(xmpp.HomeServerAddrs(jid)).([]string)
|
||||
addr = addrs[0]
|
||||
} else {
|
||||
if Port == "" {
|
||||
Port = DEFAULT_SERVER_PORT
|
||||
}
|
||||
addr = Addr + ":" + Port
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("%sConnecting to %s", LogInfo, addr)
|
||||
stream = must(xmpp.NewStream(addr, &xmpp.StreamConfig{LogStanzas: Debug, ConnectionDomain: jid.Domain})).(*xmpp.Stream)
|
||||
|
||||
if isComponent {
|
||||
comp = must(xmpp.NewComponentXMPP(stream, jid, Secret)).(*xmpp.XMPP)
|
||||
} else {
|
||||
comp = must(xmpp.NewClientXMPP(stream, jid, Secret, &xmpp.ClientConfig{InsecureSkipVerify: !VerifyCertValidity})).(*xmpp.XMPP)
|
||||
comp.Out <- xmpp.Presence{}
|
||||
}
|
||||
|
||||
mainXMPP()
|
||||
log.Printf("%sReach main method's end", LogInfo)
|
||||
|
|
@ -52,24 +93,29 @@ func mainXMPP() {
|
|||
case *xmpp.Presence:
|
||||
|
||||
case *xmpp.Message:
|
||||
confirm := v.Confir
|
||||
confirm := v.Confirm
|
||||
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]
|
||||
jidFrom, _ := xmpp.ParseJID(v.From)
|
||||
if client != nil && client.JID == jidFrom.Bare() {
|
||||
processConfirm(v, client)
|
||||
// In order to be compatible with all confirmations.
|
||||
if len(v.Body) > 0 {
|
||||
confirmation := WaitMessageAnswers[v.Body[0].Value]
|
||||
jidFrom, _ := xmpp.ParseJID(v.From)
|
||||
if confirmation != nil && confirmation.JID == jidFrom.Bare() {
|
||||
processConfirm(v, confirmation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case *xmpp.Iq:
|
||||
case *xmpp.IQ:
|
||||
switch v.PayloadName().Space {
|
||||
case xmpp.NSDiscoInfo:
|
||||
execDisco(v)
|
||||
|
||||
case xmpp.NSDiscoItems:
|
||||
execDiscoCommand(v)
|
||||
execDisco(v)
|
||||
|
||||
case xmpp.NSVCardTemp:
|
||||
reply := v.Response(xmpp.IQTypeResult)
|
||||
|
|
@ -85,17 +131,17 @@ 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, ""))
|
||||
reply.PayloadEncode(xmpp.NewError("cancel", xmpp.ErrorFeatureNotImplemented, ""))
|
||||
comp.Out <- reply
|
||||
}
|
||||
}
|
||||
|
|
@ -106,38 +152,38 @@ func mainXMPP() {
|
|||
}
|
||||
}
|
||||
|
||||
func processConfirm(x interface{}, client *Client) {
|
||||
func processConfirm(x interface{}, confirmation *Confirmation) {
|
||||
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 {
|
||||
// Message error
|
||||
errCondition := mes.Error.Condition()
|
||||
if errCondition == xmpp.ServiceUnavailable {
|
||||
if errCondition == xmpp.ErrorServiceUnavailable {
|
||||
// unreachable
|
||||
client.ChanReply <- REPLY_UNREACHABLE
|
||||
confirmation.ChanReply <- REPLY_UNREACHABLE
|
||||
} else {
|
||||
client.ChanReply <- REPLY_DENY
|
||||
confirmation.ChanReply <- REPLY_DENY
|
||||
}
|
||||
|
||||
} else if iqOK && iq.Error != nil {
|
||||
// IQ error
|
||||
errCondition := iq.Error.Condition()
|
||||
if errCondition == xmpp.ServiceUnavailable || errCondition == xmpp.FeatureNotImplemented {
|
||||
if errCondition == xmpp.ErrorServiceUnavailable || errCondition == xmpp.ErrorFeatureNotImplemented {
|
||||
// send by message if client doesn't implemente it
|
||||
client.JID = strings.SplitN(client.JID, "/", 2)[0]
|
||||
go client.QueryClient()
|
||||
} else if errCondition == xmpp.RemoteServerNotFound {
|
||||
confirmation.JID = strings.SplitN(confirmation.JID, "/", 2)[0]
|
||||
go confirmation.SendConfirmation()
|
||||
} else if errCondition == xmpp.ErrorRemoteServerNotFound {
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -149,8 +195,39 @@ func must(v interface{}, err error) interface{} {
|
|||
return v
|
||||
}
|
||||
|
||||
func execDiscoCommand(iq *xmpp.Iq) {
|
||||
log.Printf("%sDiscovery item iq received", LogInfo)
|
||||
func execDisco(iq *xmpp.IQ) {
|
||||
log.Printf("%sDisco Feature", LogInfo)
|
||||
|
||||
discoInfoReceived := &xmpp.DiscoItems{}
|
||||
iq.PayloadDecode(discoInfoReceived)
|
||||
|
||||
switch iq.PayloadName().Space {
|
||||
case xmpp.NSDiscoInfo:
|
||||
reply := iq.Response(xmpp.IQTypeResult)
|
||||
|
||||
discoInfo := &xmpp.DiscoInfo{}
|
||||
discoInfo.Identity = append(discoInfo.Identity, *identity)
|
||||
discoInfo.Feature = append(discoInfo.Feature, xmpp.DiscoFeature{Var: xmpp.NSDiscoInfo})
|
||||
discoInfo.Feature = append(discoInfo.Feature, xmpp.DiscoFeature{Var: xmpp.NSDiscoItems})
|
||||
discoInfo.Feature = append(discoInfo.Feature, xmpp.DiscoFeature{Var: xmpp.NSJabberClient})
|
||||
|
||||
reply.PayloadEncode(discoInfo)
|
||||
comp.Out <- reply
|
||||
|
||||
case xmpp.NSDiscoItems:
|
||||
if discoInfoReceived.Node == xmpp.NodeAdHocCommand {
|
||||
execDiscoCommand(iq)
|
||||
} else {
|
||||
reply := iq.Response(xmpp.IQTypeResult)
|
||||
discoItems := &xmpp.DiscoItems{}
|
||||
reply.PayloadEncode(discoItems)
|
||||
comp.Out <- reply
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func execDiscoCommand(iq *xmpp.IQ) {
|
||||
log.Printf("%sAd-Hoc Command", LogInfo)
|
||||
reply := iq.Response(xmpp.IQTypeResult)
|
||||
discoItem := &xmpp.DiscoItems{Node: xmpp.NodeAdHocCommand}
|
||||
reply.PayloadEncode(discoItem)
|
||||
|
|
|
|||
Loading…
Reference in New Issue