From adf2c13a8cf5778efa5299cc6f19044e427ff458 Mon Sep 17 00:00:00 2001 From: Theo McGinley Date: Sat, 9 Feb 2019 14:35:31 +0000 Subject: [PATCH 01/10] Fixed infinite retries for failed TCP dial --- client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client.go b/client.go index d167341..7a17f45 100644 --- a/client.go +++ b/client.go @@ -119,7 +119,7 @@ func (c *Client) Connect() (*Session, error) { var try = 0 var success bool c.Metrics = initMetrics() - for try <= c.config.Retry || !success { + for try <= c.config.Retry && !success { if tcpconn, err = net.DialTimeout("tcp", c.config.Address, time.Duration(c.config.ConnectTimeout)*time.Second); err == nil { c.Metrics.setConnectTime() success = true From ffcde39ba658fde01030bb0dad38a65cea14c9e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20R=C3=A9mond?= Date: Sun, 10 Feb 2019 17:53:18 +0100 Subject: [PATCH 02/10] Add test (and refactor them) for PR#15 (#18) * Add test (and refactor them) for #15 * Update Dockerfile to support Go modules on Codeship --- Dockerfile | 4 ++-- iq_test.go | 52 +++++++++++++++--------------------------------- message_test.go | 7 ++++--- presence_test.go | 43 ++++++++++++++++++++++++++++++++++++--- test.sh | 1 + xmpp_test.go | 29 +++++++++++++++++++++++++++ 6 files changed, 92 insertions(+), 44 deletions(-) create mode 100644 xmpp_test.go diff --git a/Dockerfile b/Dockerfile index 973432e..8fa1feb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM golang:1.11 -WORKDIR /go/src/gosrc.io/xmpp +WORKDIR /xmpp RUN curl -o codecov.sh -s https://codecov.io/bash && chmod +x codecov.sh COPY . ./ -RUN go get -t ./... +# RUN go get -t ./... diff --git a/iq_test.go b/iq_test.go index 959a602..f78456b 100644 --- a/iq_test.go +++ b/iq_test.go @@ -1,4 +1,4 @@ -package xmpp // import "gosrc.io/xmpp" +package xmpp_test // import "gosrc.io/xmpp" import ( "encoding/xml" @@ -6,20 +6,22 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "gosrc.io/xmpp" ) func TestUnmarshalIqs(t *testing.T) { //var cs1 = new(iot.ControlSet) var tests = []struct { iqString string - parsedIQ IQ + parsedIQ xmpp.IQ }{ - {"", IQ{XMLName: xml.Name{Space: "", Local: "iq"}, PacketAttrs: PacketAttrs{To: "test@localhost", Type: "set", Id: "1"}}}, + {"", + xmpp.IQ{XMLName: xml.Name{Space: "", Local: "iq"}, PacketAttrs: xmpp.PacketAttrs{To: "test@localhost", Type: "set", Id: "1"}}}, //{"", IQ{XMLName: xml.Name{Space: "jabber:client", Local: "iq"}, PacketAttrs: PacketAttrs{To: "test@localhost", From: "server", Type: "set", Id: "2"}, Payload: cs1}}, } for _, test := range tests { - parsedIQ := IQ{} + parsedIQ := xmpp.IQ{} err := xml.Unmarshal([]byte(test.iqString), &parsedIQ) if err != nil { t.Errorf("Unmarshal(%s) returned error", test.iqString) @@ -33,14 +35,14 @@ func TestUnmarshalIqs(t *testing.T) { } func TestGenerateIq(t *testing.T) { - iq := NewIQ("result", "admin@localhost", "test@localhost", "1", "en") - payload := DiscoInfo{ - Identity: Identity{ + iq := xmpp.NewIQ("result", "admin@localhost", "test@localhost", "1", "en") + payload := xmpp.DiscoInfo{ + Identity: xmpp.Identity{ Name: "Test Gateway", Category: "gateway", Type: "mqtt", }, - Features: []Feature{ + Features: []xmpp.Feature{ {Var: "http://jabber.org/protocol/disco#info"}, {Var: "http://jabber.org/protocol/disco#item"}, }, @@ -56,7 +58,7 @@ func TestGenerateIq(t *testing.T) { t.Error("empty error should not be serialized") } - parsedIQ := IQ{} + parsedIQ := xmpp.IQ{} if err = xml.Unmarshal(data, &parsedIQ); err != nil { t.Errorf("Unmarshal(%s) returned error", data) } @@ -67,7 +69,7 @@ func TestGenerateIq(t *testing.T) { } func TestErrorTag(t *testing.T) { - xError := Err{ + xError := xmpp.Err{ XMLName: xml.Name{Local: "error"}, Code: 503, Type: "cancel", @@ -80,7 +82,7 @@ func TestErrorTag(t *testing.T) { t.Errorf("cannot marshal xml structure: %s", err) } - parsedError := Err{} + parsedError := xmpp.Err{} if err = xml.Unmarshal(data, &parsedError); err != nil { t.Errorf("Unmarshal(%s) returned error", data) } @@ -91,8 +93,8 @@ func TestErrorTag(t *testing.T) { } func TestDiscoItems(t *testing.T) { - iq := NewIQ("get", "romeo@montague.net/orchard", "catalog.shakespeare.lit", "items3", "en") - payload := DiscoItems{ + iq := xmpp.NewIQ("get", "romeo@montague.net/orchard", "catalog.shakespeare.lit", "items3", "en") + payload := xmpp.DiscoItems{ Node: "music", } iq.AddPayload(&payload) @@ -102,7 +104,7 @@ func TestDiscoItems(t *testing.T) { t.Errorf("cannot marshal xml structure") } - parsedIQ := IQ{} + parsedIQ := xmpp.IQ{} if err = xml.Unmarshal(data, &parsedIQ); err != nil { t.Errorf("Unmarshal(%s) returned error", data) } @@ -111,25 +113,3 @@ func TestDiscoItems(t *testing.T) { t.Errorf("non matching items\n%s", cmp.Diff(parsedIQ.Payload, iq.Payload)) } } - -// Compare iq structure but ignore empty namespace as they are set properly on -// marshal / unmarshal. There is no need to manage them on the manually -// crafted structure. -func xmlEqual(x, y interface{}) bool { - alwaysEqual := cmp.Comparer(func(_, _ interface{}) bool { return true }) - opts := cmp.Options{ - cmp.FilterValues(func(x, y interface{}) bool { - xx, xok := x.(xml.Name) - yy, yok := y.(xml.Name) - if xok && yok { - zero := xml.Name{} - if xx == zero || yy == zero { - return true - } - } - return false - }, alwaysEqual), - } - - return cmp.Equal(x, y, opts) -} diff --git a/message_test.go b/message_test.go index 888205c..76b8e65 100644 --- a/message_test.go +++ b/message_test.go @@ -1,14 +1,15 @@ -package xmpp // import "gosrc.io/xmpp" +package xmpp_test // import "gosrc.io/xmpp_test" import ( "encoding/xml" "testing" "github.com/google/go-cmp/cmp" + "gosrc.io/xmpp" ) func TestGenerateMessage(t *testing.T) { - message := NewMessage("chat", "admin@localhost", "test@localhost", "1", "en") + message := xmpp.NewMessage("chat", "admin@localhost", "test@localhost", "1", "en") message.Body = "Hi" message.Subject = "Msg Subject" @@ -17,7 +18,7 @@ func TestGenerateMessage(t *testing.T) { t.Errorf("cannot marshal xml structure") } - parsedMessage := Message{} + parsedMessage := xmpp.Message{} if err = xml.Unmarshal(data, &parsedMessage); err != nil { t.Errorf("Unmarshal(%s) returned error", data) } diff --git a/presence_test.go b/presence_test.go index 388ab6a..0e66a73 100644 --- a/presence_test.go +++ b/presence_test.go @@ -1,14 +1,16 @@ -package xmpp // import "gosrc.io/xmpp" +package xmpp_test // import "gosrc.io/xmpp_test" import ( "encoding/xml" "testing" + "gosrc.io/xmpp" + "github.com/google/go-cmp/cmp" ) func TestGeneratePresence(t *testing.T) { - presence := NewPresence("admin@localhost", "test@localhost", "1", "en") + presence := xmpp.NewPresence("admin@localhost", "test@localhost", "1", "en") presence.Show = "chat" data, err := xml.Marshal(presence) @@ -16,7 +18,7 @@ func TestGeneratePresence(t *testing.T) { t.Errorf("cannot marshal xml structure") } - parsedPresence := Presence{} + var parsedPresence xmpp.Presence if err = xml.Unmarshal(data, &parsedPresence); err != nil { t.Errorf("Unmarshal(%s) returned error", data) } @@ -25,3 +27,38 @@ func TestGeneratePresence(t *testing.T) { t.Errorf("non matching items\n%s", cmp.Diff(parsedPresence, presence)) } } + +func TestPresenceSubElt(t *testing.T) { + // Test structure to ensure that show, status and priority are correctly defined as presence + // package sub-elements + type pres struct { + Show string `xml:"show"` + Status string `xml:"status"` + Priority string `xml:"priority"` + } + + presence := xmpp.NewPresence("admin@localhost", "test@localhost", "1", "en") + presence.Show = "xa" + presence.Status = "Coding" + presence.Priority = "10" + + data, err := xml.Marshal(presence) + if err != nil { + t.Errorf("cannot marshal xml structure") + } + + var parsedPresence pres + if err = xml.Unmarshal(data, &parsedPresence); err != nil { + t.Errorf("Unmarshal(%s) returned error", data) + } + + if parsedPresence.Show != presence.Show { + t.Errorf("cannot read 'show' as presence subelement (%s)", parsedPresence.Show) + } + if parsedPresence.Status != presence.Status { + t.Errorf("cannot read 'status' as presence subelement (%s)", parsedPresence.Status) + } + if parsedPresence.Priority != presence.Priority { + t.Errorf("cannot read 'priority' as presence subelement (%s)", parsedPresence.Priority) + } +} diff --git a/test.sh b/test.sh index 341553c..9730026 100755 --- a/test.sh +++ b/test.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash set -e +export GO111MODULE=on echo "" > coverage.txt for d in $(go list ./... | grep -v vendor); do diff --git a/xmpp_test.go b/xmpp_test.go new file mode 100644 index 0000000..b52d0d3 --- /dev/null +++ b/xmpp_test.go @@ -0,0 +1,29 @@ +package xmpp_test // import "gosrc.io/xmpp_test" + +import ( + "encoding/xml" + + "github.com/google/go-cmp/cmp" +) + +// Compare iq structure but ignore empty namespace as they are set properly on +// marshal / unmarshal. There is no need to manage them on the manually +// crafted structure. +func xmlEqual(x, y interface{}) bool { + alwaysEqual := cmp.Comparer(func(_, _ interface{}) bool { return true }) + opts := cmp.Options{ + cmp.FilterValues(func(x, y interface{}) bool { + xx, xok := x.(xml.Name) + yy, yok := y.(xml.Name) + if xok && yok { + zero := xml.Name{} + if xx == zero || yy == zero { + return true + } + } + return false + }, alwaysEqual), + } + + return cmp.Equal(x, y, opts) +} From c642ad79fc0a873d3e23dd8ae18a9022f2166cdc Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Thu, 16 May 2019 16:13:19 +0200 Subject: [PATCH 03/10] More file to ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2b2d575..04fa968 100755 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ _testmain.go *.test *.prof coverage.out +coverage.txt .idea/ *.iml From f45829916c5f4487080bd9f8316a7ebe6ab6f6ac Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Thu, 16 May 2019 17:46:36 +0200 Subject: [PATCH 04/10] Add tool to check XMPP certificate on starttls Minor refactoring --- auth.go | 2 +- check_cert.go | 146 +++++++++++++++++++++++++++++++++++ cmd/xmpp-check/TODO.md | 3 + cmd/xmpp-check/xmpp-check.go | 43 +++++++++++ parser.go | 2 + session.go | 6 +- socket_proxy.go | 18 ++--- stream.go | 16 +++- 8 files changed, 222 insertions(+), 14 deletions(-) create mode 100644 check_cert.go create mode 100644 cmd/xmpp-check/TODO.md create mode 100644 cmd/xmpp-check/xmpp-check.go diff --git a/auth.go b/auth.go index 66ac983..de38cac 100644 --- a/auth.go +++ b/auth.go @@ -8,7 +8,7 @@ import ( "io" ) -func authSASL(socket io.ReadWriter, decoder *xml.Decoder, f streamFeatures, user string, password string) (err error) { +func authSASL(socket io.ReadWriter, decoder *xml.Decoder, f StreamFeatures, user string, password string) (err error) { // TODO: Implement other type of SASL Authentication havePlain := false for _, m := range f.Mechanisms.Mechanism { diff --git a/check_cert.go b/check_cert.go new file mode 100644 index 0000000..b23b6bb --- /dev/null +++ b/check_cert.go @@ -0,0 +1,146 @@ +package xmpp + +import ( + "crypto/tls" + "encoding/xml" + "errors" + "fmt" + "net" + "strings" + "time" +) + +// TODO: Should I move this as an extension of the client? +// I should probably make the code more modular, but keep concern separated to keep it simple. +type ServerCheck struct { + address string + domain string +} + +func NewChecker(address, domain string) (*ServerCheck, error) { + client := ServerCheck{} + + var err error + var host string + if client.address, host, err = extractParams(address); err != nil { + return &client, err + } + + if domain != "" { + client.domain = domain + } else { + client.domain = host + } + + return &client, nil +} + +// Check triggers actual TCP connection, based on previously defined parameters. +func (c *ServerCheck) Check() error { + var tcpconn net.Conn + var err error + + timeout := 15 * time.Second + tcpconn, err = net.DialTimeout("tcp", c.address, timeout) + if err != nil { + return err + } + + decoder := xml.NewDecoder(tcpconn) + + // Send stream open tag + if _, err = fmt.Fprintf(tcpconn, xmppStreamOpen, c.domain, NSClient, NSStream); err != nil { + return err + } + + // Set xml decoder and extract streamID from reply (not used for now) + _, err = initDecoder(decoder) + if err != nil { + return err + } + + // extract stream features + var f StreamFeatures + packet, err := next(decoder) + if err != nil { + err = fmt.Errorf("stream open decode features: %s", err) + return err + } + + switch p := packet.(type) { + case StreamFeatures: + f = p + case StreamError: + return errors.New("open stream error: " + p.Error.Local) + default: + return errors.New("expected packet received while expecting features, got " + p.Name()) + } + + startTLSFeature := f.StartTLS.XMLName.Space + " " + f.StartTLS.XMLName.Local + if startTLSFeature == nsTLS+" starttls" { + fmt.Fprintf(tcpconn, "") + + var k tlsProceed + if err = decoder.DecodeElement(&k, nil); err != nil { + return fmt.Errorf("expecting starttls proceed: %s", err) + } + + DefaultTlsConfig.ServerName = c.domain + tlsConn := tls.Client(tcpconn, &DefaultTlsConfig) + // We convert existing connection to TLS + if err = tlsConn.Handshake(); err != nil { + return err + } + + // We check that cert matches hostname + if err = tlsConn.VerifyHostname(c.domain); err != nil { + return err + } + + if err = checkExpiration(tlsConn); err != nil { + return err + } + return nil + } + return errors.New("TLS not supported on server") +} + +// Check expiration date for the whole certificate chain and returns an error +// if the expiration date is in less than 48 hours. +func checkExpiration(tlsConn *tls.Conn) error { + checkedCerts := make(map[string]struct{}) + for _, chain := range tlsConn.ConnectionState().VerifiedChains { + for _, cert := range chain { + if _, checked := checkedCerts[string(cert.Signature)]; checked { + continue + } + checkedCerts[string(cert.Signature)] = struct{}{} + + // Check the expiration. + timeNow := time.Now() + expiresInHours := int64(cert.NotAfter.Sub(timeNow).Hours()) + // fmt.Printf("Cert '%s' expires in %d days\n", cert.Subject.CommonName, expiresInHours/24) + if expiresInHours <= 48 { + return fmt.Errorf("certificate '%s' will expire on %s", cert.Subject.CommonName, cert.NotAfter) + } + } + } + return nil +} + +func extractParams(addr string) (string, string, error) { + var err error + hostport := strings.Split(addr, ":") + if len(hostport) > 2 { + err = errors.New("too many colons in xmpp server address") + return addr, hostport[0], err + } + + // Address is composed of two parts, we are good + if len(hostport) == 2 && hostport[1] != "" { + return addr, hostport[0], err + } + + // Port was not passed, we append XMPP default port: + return strings.Join([]string{hostport[0], "5222"}, ":"), hostport[0], err +} diff --git a/cmd/xmpp-check/TODO.md b/cmd/xmpp-check/TODO.md new file mode 100644 index 0000000..682b4cb --- /dev/null +++ b/cmd/xmpp-check/TODO.md @@ -0,0 +1,3 @@ +# TODO + +- Use a config file to define the checks to perform as client on an XMPP server. \ No newline at end of file diff --git a/cmd/xmpp-check/xmpp-check.go b/cmd/xmpp-check/xmpp-check.go new file mode 100644 index 0000000..6e7ceab --- /dev/null +++ b/cmd/xmpp-check/xmpp-check.go @@ -0,0 +1,43 @@ +package main + +import ( + "log" + "os" + + "gosrc.io/xmpp" +) + +func main() { + args := os.Args[1:] + + if len(args) == 0 { + log.Fatal("usage: xmpp-check host[:port] [domain]") + } + + var address string + var domain string + if len(args) >= 1 { + address = args[0] + } + + if len(args) >= 2 { + domain = args[1] + } + + runCheck(address, domain) +} + +func runCheck(address, domain string) { + client, err := xmpp.NewChecker(address, domain) + // client, err := xmpp.NewChecker("mickael.m.in-app.io:5222", "mickael.m.in-app.io") + + if err != nil { + log.Fatal("Error: ", err) + } + + if err = client.Check(); err != nil { + log.Fatal("Failed connection check: ", err) + } + + log.Println("All checks passed") +} diff --git a/parser.go b/parser.go index 898d408..0ad24fc 100644 --- a/parser.go +++ b/parser.go @@ -90,6 +90,8 @@ func decodeStream(p *xml.Decoder, se xml.StartElement) (Packet, error) { switch se.Name.Local { case "error": return streamError.decode(p, se) + case "features": + return streamFeatures.decode(p, se) default: return nil, errors.New("unexpected XMPP packet " + se.Name.Space + " <" + se.Name.Local + "/>") diff --git a/session.go b/session.go index 8259b9a..a15fdb3 100644 --- a/session.go +++ b/session.go @@ -15,7 +15,7 @@ type Session struct { // Session info BindJid string // Jabber ID as provided by XMPP server StreamId string - Features streamFeatures + Features StreamFeatures TlsEnabled bool lastPacketId int @@ -85,7 +85,7 @@ func (s *Session) setProxy(conn net.Conn, newConn net.Conn, o Config) { s.decoder.CharsetReader = o.CharsetReader } -func (s *Session) open(domain string) (f streamFeatures) { +func (s *Session) open(domain string) (f StreamFeatures) { // Send stream open tag if _, s.err = fmt.Fprintf(s.socketProxy, xmppStreamOpen, domain, NSClient, NSStream); s.err != nil { return @@ -121,7 +121,7 @@ func (s *Session) startTlsIfSupported(conn net.Conn, domain string) net.Conn { // TODO: add option to accept all TLS certificates: insecureSkipTlsVerify (DefaultTlsConfig.InsecureSkipVerify) DefaultTlsConfig.ServerName = domain - var tlsConn *tls.Conn = tls.Client(conn, &DefaultTlsConfig) + tlsConn := tls.Client(conn, &DefaultTlsConfig) // We convert existing connection to TLS if s.err = tlsConn.Handshake(); s.err != nil { return tlsConn diff --git a/socket_proxy.go b/socket_proxy.go index 49f2f8e..6068124 100644 --- a/socket_proxy.go +++ b/socket_proxy.go @@ -20,21 +20,21 @@ func newSocketProxy(conn io.ReadWriter, logFile *os.File) io.ReadWriter { } } -func (pl *socketProxy) Read(p []byte) (n int, err error) { - n, err = pl.socket.Read(p) +func (sp *socketProxy) Read(p []byte) (n int, err error) { + n, err = sp.socket.Read(p) if n > 0 { - pl.logFile.Write([]byte("RECV:\n")) // Prefix - if n, err := pl.logFile.Write(p[:n]); err != nil { + sp.logFile.Write([]byte("RECV:\n")) // Prefix + if n, err := sp.logFile.Write(p[:n]); err != nil { return n, err } - pl.logFile.Write([]byte("\n\n")) // Separator + sp.logFile.Write([]byte("\n\n")) // Separator } return } -func (pl *socketProxy) Write(p []byte) (n int, err error) { - pl.logFile.Write([]byte("SEND:\n")) // Prefix - for _, w := range []io.Writer{pl.socket, pl.logFile} { +func (sp *socketProxy) Write(p []byte) (n int, err error) { + sp.logFile.Write([]byte("SEND:\n")) // Prefix + for _, w := range []io.Writer{sp.socket, sp.logFile} { n, err = w.Write(p) if err != nil { return @@ -44,6 +44,6 @@ func (pl *socketProxy) Write(p []byte) (n int, err error) { return } } - pl.logFile.Write([]byte("\n\n")) // Separator + sp.logFile.Write([]byte("\n\n")) // Separator return len(p), nil } diff --git a/stream.go b/stream.go index 3b48db0..1e0df97 100644 --- a/stream.go +++ b/stream.go @@ -7,7 +7,7 @@ import ( // ============================================================================ // StreamFeatures Packet -type streamFeatures struct { +type StreamFeatures struct { XMLName xml.Name `xml:"http://etherx.jabber.org/streams features"` StartTLS tlsStartTLS Caps Caps @@ -17,6 +17,20 @@ type streamFeatures struct { Any []xml.Name `xml:",any"` } +func (StreamFeatures) Name() string { + return "stream:features" +} + +type streamFeatureDecoder struct{} + +var streamFeatures streamFeatureDecoder + +func (streamFeatureDecoder) decode(p *xml.Decoder, se xml.StartElement) (StreamFeatures, error) { + var packet StreamFeatures + err := p.DecodeElement(&packet, &se) + return packet, err +} + // ============================================================================ // StreamError Packet From 1a6e4f266b251e8ff9663861333bd209813da65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20R=C3=A9mond?= Date: Thu, 16 May 2019 18:01:47 +0200 Subject: [PATCH 05/10] Fix import path --- check_cert.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/check_cert.go b/check_cert.go index b23b6bb..6190d96 100644 --- a/check_cert.go +++ b/check_cert.go @@ -1,4 +1,4 @@ -package xmpp +package xmpp // import "gosrc.io/xmpp" import ( "crypto/tls" From 23a710b36f9af30dcc69ce386d8cdc7b296f4485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20R=C3=A9mond?= Date: Thu, 16 May 2019 18:03:12 +0200 Subject: [PATCH 06/10] Update message_test.go --- message_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/message_test.go b/message_test.go index 76b8e65..21ee882 100644 --- a/message_test.go +++ b/message_test.go @@ -1,4 +1,4 @@ -package xmpp_test // import "gosrc.io/xmpp_test" +package xmpp_test import ( "encoding/xml" From 5d6329f0b44e9ba8163d9769c2745e01ad864e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20R=C3=A9mond?= Date: Thu, 16 May 2019 18:03:44 +0200 Subject: [PATCH 07/10] Update presence_test.go --- presence_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/presence_test.go b/presence_test.go index 0e66a73..f9d9f54 100644 --- a/presence_test.go +++ b/presence_test.go @@ -1,4 +1,4 @@ -package xmpp_test // import "gosrc.io/xmpp_test" +package xmpp_test import ( "encoding/xml" From 53916900d4402ea460c4c702db9c3f6034a61bed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20R=C3=A9mond?= Date: Thu, 16 May 2019 18:04:09 +0200 Subject: [PATCH 08/10] Update xmpp_test.go --- xmpp_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmpp_test.go b/xmpp_test.go index b52d0d3..7f7e6de 100644 --- a/xmpp_test.go +++ b/xmpp_test.go @@ -1,4 +1,4 @@ -package xmpp_test // import "gosrc.io/xmpp_test" +package xmpp_test import ( "encoding/xml" From da0a8b9c298b3d1d1e44ff3812d09c730156e17e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20R=C3=A9mond?= Date: Thu, 16 May 2019 18:09:39 +0200 Subject: [PATCH 09/10] Add readme for XMPP check domain --- cmd/xmpp-check/README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 cmd/xmpp-check/README.md diff --git a/cmd/xmpp-check/README.md b/cmd/xmpp-check/README.md new file mode 100644 index 0000000..43a8df8 --- /dev/null +++ b/cmd/xmpp-check/README.md @@ -0,0 +1,28 @@ +# XMPP Check + +XMPP check is a tool to check TLS certificate on a remote server. + +## Installation + +``` +$ go get -u gosrc.io/xmpp/cmd/xmpp-check +``` + +## Usage + +If you server is on standard port and XMPP domains matches the hostname you can simply use: + +``` +$ xmpp-check myhost.net:5222 xmppdomain.net +2019/05/16 16:04:36 All checks passed +``` + +You can also pass the port and the XMPP domain if different from the server hostname: + +``` +$ xmpp-check myhost.net:5222 xmppdomain.net +2019/05/16 16:04:36 All checks passed +``` + +Error code will be non-zero in case of error. You can thus use it directly with your usual +monitoring scripts. From 95dded61a1543dbf308b288d4ac2f8a4971206ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20R=C3=A9mond?= Date: Thu, 16 May 2019 18:10:06 +0200 Subject: [PATCH 10/10] Update README.md --- cmd/xmpp-check/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/xmpp-check/README.md b/cmd/xmpp-check/README.md index 43a8df8..e2d5b3e 100644 --- a/cmd/xmpp-check/README.md +++ b/cmd/xmpp-check/README.md @@ -13,7 +13,7 @@ $ go get -u gosrc.io/xmpp/cmd/xmpp-check If you server is on standard port and XMPP domains matches the hostname you can simply use: ``` -$ xmpp-check myhost.net:5222 xmppdomain.net +$ xmpp-check myhost.net 2019/05/16 16:04:36 All checks passed ``` @@ -21,7 +21,7 @@ You can also pass the port and the XMPP domain if different from the server host ``` $ xmpp-check myhost.net:5222 xmppdomain.net -2019/05/16 16:04:36 All checks passed +2019/05/16 16:05:21 All checks passed ``` Error code will be non-zero in case of error. You can thus use it directly with your usual