From 5eb5e9e0afb996a74bb3a5f2c5fb8b66573aec3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 1 Feb 2017 18:16:27 +0100 Subject: ci: add a packaging:debian job, based on the debian branch --- .gitlab-ci.yml | 58 ++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d03a47f..33f699d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,3 +1,8 @@ +stages: + - build + - test + - packaging + before_script: - uname -a - locale @@ -64,24 +69,6 @@ build:6: UDNS: "-DWITHOUT_UDNS=1" <<: *basic_build -build:rpm: - stage: build - only: - - master@louiz/biboumi - tags: - - docker - image: docker.louiz.org/biboumi-test-fedora:latest - script: - - cmake .. -DCMAKE_CXX_COMPILER=${COMPILER} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} ${BOTAN} ${UDNS} ${SYSTEMD} ${LIBIDN} ${LITESQL} - - make rpm -j$(nproc || echo 1) - artifacts: - paths: - - build/rpmbuild/RPMS - - build/rpmbuild/SRPMS - when: always - name: $CI_PROJECT_NAME-rpm-$CI_BUILD_ID - - .template:basic_test: &basic_test stage: test tags: @@ -153,3 +140,38 @@ test:sonar-qube: - ~/sonar-scanner/bin/build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir ./bw-outputs make biboumi test_suite - cd .. - ~/sonar-scanner/bin/sonar-scanner -Dsonar.host.url=https://sonarqube.com -Dsonar.login=$SONAR_LOGIN -Dsonar.language=cpp -Dsonar.cfamily.build-wrapper-output=build/bw-outputs -Dsonar.sourceEncoding=UTF-8 -Dsonar.sources=src/,louloulibs/,tests/ -Dsonar.projectKey=biboumi -Dsonar.projectName=Biboumi -Dsonar.projectVersion=3.0 + +packaging:rpm: + stage: packaging + only: + - master@louiz/biboumi + tags: + - docker + image: docker.louiz.org/biboumi-test-fedora:latest + script: + - cmake .. -DCMAKE_CXX_COMPILER=${COMPILER} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} ${BOTAN} ${UDNS} ${SYSTEMD} ${LIBIDN} ${LITESQL} + - make rpm -j$(nproc || echo 1) + artifacts: + paths: + - build/rpmbuild/RPMS + - build/rpmbuild/SRPMS + when: always + name: $CI_PROJECT_NAME-rpm-$CI_BUILD_ID + +packaging:deb: + stage: packaging + only: + - master@louiz/biboumi + tags: + - docker + image: docker.louiz.org/packaging-debian:latest + script: + - git checkout debian + - git merge --no-commit --no-ff master + - mk-build-deps + - apt install -y ./biboumi-build-deps*.deb + - debuild -b -us -uc + artifacts: + untracked: true + when: always + name: $CI_PROJECT_NAME-deb-$CI_BUILD_ID -- cgit v1.2.3 From 479b7189935baa4ca9c9d2a5525bdb1fbd8b9fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 1 Feb 2017 18:37:51 +0100 Subject: Only use the C.UTF-8 LANG value --- CMakeLists.txt | 4 ++-- louloulibs/utils/time.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d934ef..1766e58 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -331,8 +331,8 @@ if(NOT DEFINED SERVICE_GROUP) endif() configure_file(unit/biboumi.service.cmake biboumi.service) -# The date MUST be in english format -set(ENV{LANG} "en_US.utf-8") +# Force the format of the date output +set(ENV{LANG} "C.UTF-8") execute_process(COMMAND "date" "+%a %b %d %Y" OUTPUT_VARIABLE RPM_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) unset(ENV{LANG}) diff --git a/louloulibs/utils/time.cpp b/louloulibs/utils/time.cpp index e3c49ed..d9c4381 100644 --- a/louloulibs/utils/time.cpp +++ b/louloulibs/utils/time.cpp @@ -24,7 +24,7 @@ std::time_t parse_datetime(const std::string& stamp) std::tm t = {}; #ifdef HAS_GET_TIME std::istringstream ss(stamp); - ss.imbue(std::locale("en_US.UTF-8")); + ss.imbue(std::locale("C.UTF-8")); std::string timezone; ss >> std::get_time(&t, format) >> timezone; -- cgit v1.2.3 From 835c650ef5a7297cc8bd0d6e0799186e6a5d2126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 1 Feb 2017 20:33:16 +0100 Subject: Actually, just use the C locale for the date formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don’t need any UTF-8 support here, and it’s more portable --- CMakeLists.txt | 2 +- louloulibs/utils/time.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1766e58..da9cf37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -332,7 +332,7 @@ endif() configure_file(unit/biboumi.service.cmake biboumi.service) # Force the format of the date output -set(ENV{LANG} "C.UTF-8") +set(ENV{LANG} "C") execute_process(COMMAND "date" "+%a %b %d %Y" OUTPUT_VARIABLE RPM_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) unset(ENV{LANG}) diff --git a/louloulibs/utils/time.cpp b/louloulibs/utils/time.cpp index d9c4381..e9f3943 100644 --- a/louloulibs/utils/time.cpp +++ b/louloulibs/utils/time.cpp @@ -24,7 +24,7 @@ std::time_t parse_datetime(const std::string& stamp) std::tm t = {}; #ifdef HAS_GET_TIME std::istringstream ss(stamp); - ss.imbue(std::locale("C.UTF-8")); + ss.imbue(std::locale("C")); std::string timezone; ss >> std::get_time(&t, format) >> timezone; -- cgit v1.2.3 From e2da6fcddde7603510a266488980160d4cd462cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 1 Feb 2017 20:52:50 +0100 Subject: Properly destroy the dns_handler socket when first start fails To correctly exit the process --- src/main.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index bc8e779..76ab5d9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -196,7 +196,12 @@ int main(int ac, char** av) } } else - identd.shutdown(); + { +#ifdef UDNS_FOUND + dns_handler.destroy(); +#endif + identd.shutdown(); + } } // If the only existing connection is the one to the XMPP component: // close the XMPP stream. -- cgit v1.2.3 From f197e30398bcd99766f61e457111550b02703d3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 1 Feb 2017 20:53:27 +0100 Subject: ci: in packaging:deb, override the before_script --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 33f699d..5e48cbc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -165,6 +165,7 @@ packaging:deb: tags: - docker image: docker.louiz.org/packaging-debian:latest + before_script: [] script: - git checkout debian - git merge --no-commit --no-ff master -- cgit v1.2.3 From 9ce29fa76c7db94f54497af896e5c9f9aee672d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 1 Feb 2017 21:16:40 +0100 Subject: ci: packaging:deb, build for debian branch, include built .deb file --- .gitlab-ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5e48cbc..1fe1c77 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -162,6 +162,7 @@ packaging:deb: stage: packaging only: - master@louiz/biboumi + - debian@louiz/biboumi tags: - docker image: docker.louiz.org/packaging-debian:latest @@ -173,6 +174,6 @@ packaging:deb: - apt install -y ./biboumi-build-deps*.deb - debuild -b -us -uc artifacts: - untracked: true - when: always + paths: + - ../*.deb name: $CI_PROJECT_NAME-deb-$CI_BUILD_ID -- cgit v1.2.3 From 4ec2e1f794d3edf985b31d0e6ef3f7dba51780a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 1 Feb 2017 21:27:29 +0100 Subject: ci: packaging:deb try move the build artifacts into the build directory --- .gitlab-ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1fe1c77..1b5c113 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -173,7 +173,9 @@ packaging:deb: - mk-build-deps - apt install -y ./biboumi-build-deps*.deb - debuild -b -us -uc + - mv ../*.deb . + - mv ../*.build . + - mv ../*.buildinfo . artifacts: - paths: - - ../*.deb + untracked: true name: $CI_PROJECT_NAME-deb-$CI_BUILD_ID -- cgit v1.2.3 From 7d41577bc46d6ba300da2b0f13d2e318b087b118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sun, 12 Feb 2017 15:11:13 +0100 Subject: The form fields in the Configure ad-hoc commands are not required --- src/xmpp/biboumi_adhoc_commands.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/xmpp/biboumi_adhoc_commands.cpp b/src/xmpp/biboumi_adhoc_commands.cpp index ccb3517..a83af80 100644 --- a/src/xmpp/biboumi_adhoc_commands.cpp +++ b/src/xmpp/biboumi_adhoc_commands.cpp @@ -206,8 +206,6 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com XmlSubNode instructions(x, "instructions"); instructions.set_inner("Edit the form, to configure the settings of the IRC server "s + server_domain); - XmlNode required("required"); - XmlSubNode ports(x, "field"); ports["var"] = "ports"; ports["type"] = "text-multi"; @@ -219,7 +217,6 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com XmlSubNode ports_value(ports, "value"); ports_value.set_inner(val); } - ports.add_child(required); #ifdef BOTAN_FOUND XmlSubNode tls_ports(x, "field"); @@ -233,7 +230,6 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com XmlSubNode tls_ports_value(tls_ports, "value"); tls_ports_value.set_inner(val); } - tls_ports.add_child(required); XmlSubNode verify_cert(x, "field"); verify_cert["var"] = "verify_cert"; @@ -255,7 +251,6 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com XmlSubNode fingerprint_value(fingerprint, "value"); fingerprint_value.set_inner(options.trustedFingerprint.value()); } - fingerprint.add_child(required); #endif XmlSubNode pass(x, "field"); @@ -267,7 +262,6 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com XmlSubNode pass_value(pass, "value"); pass_value.set_inner(options.pass.value()); } - pass.add_child(required); XmlSubNode after_cnt_cmd(x, "field"); after_cnt_cmd["var"] = "after_connect_command"; @@ -279,7 +273,6 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com XmlSubNode after_cnt_cmd_value(after_cnt_cmd, "value"); after_cnt_cmd_value.set_inner(options.afterConnectionCommand.value()); } - after_cnt_cmd.add_child(required); if (Config::get("realname_customization", "true") == "true") { @@ -292,7 +285,6 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com XmlSubNode username_value(username, "value"); username_value.set_inner(options.username.value()); } - username.add_child(required); XmlSubNode realname(x, "field"); realname["var"] = "realname"; @@ -303,7 +295,6 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com XmlSubNode realname_value(realname, "value"); realname_value.set_inner(options.realname.value()); } - realname.add_child(required); } XmlSubNode encoding_out(x, "field"); @@ -316,7 +307,6 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com XmlSubNode encoding_out_value(encoding_out, "value"); encoding_out_value.set_inner(options.encodingOut.value()); } - encoding_out.add_child(required); XmlSubNode encoding_in(x, "field"); encoding_in["var"] = "encoding_in"; @@ -328,7 +318,6 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com XmlSubNode encoding_in_value(encoding_in, "value"); encoding_in_value.set_inner(options.encodingIn.value()); } - encoding_in.add_child(required); XmlSubNode linger_time(x, "field"); linger_time["var"] = "linger_time"; @@ -339,7 +328,6 @@ void ConfigureIrcServerStep1(XmppComponent&, AdhocSession& session, XmlNode& com XmlSubNode linger_time_value(linger_time, "value"); linger_time_value.set_inner(std::to_string(options.lingerTime.value())); } - encoding_in.add_child(required); } void ConfigureIrcServerStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node) @@ -454,8 +442,6 @@ void ConfigureIrcChannelStep1(XmppComponent&, AdhocSession& session, XmlNode& co XmlSubNode instructions(x, "instructions"); instructions.set_inner("Edit the form, to configure the settings of the IRC channel "s + iid.get_local()); - XmlNode required("required"); - XmlSubNode encoding_out(x, "field"); encoding_out["var"] = "encoding_out"; encoding_out["type"] = "text-single"; @@ -466,7 +452,6 @@ void ConfigureIrcChannelStep1(XmppComponent&, AdhocSession& session, XmlNode& co XmlSubNode encoding_out_value(encoding_out, "value"); encoding_out_value.set_inner(options.encodingOut.value()); } - encoding_out.add_child(required); XmlSubNode encoding_in(x, "field"); encoding_in["var"] = "encoding_in"; @@ -478,7 +463,6 @@ void ConfigureIrcChannelStep1(XmppComponent&, AdhocSession& session, XmlNode& co XmlSubNode encoding_in_value(encoding_in, "value"); encoding_in_value.set_inner(options.encodingIn.value()); } - encoding_in.add_child(required); } void ConfigureIrcChannelStep2(XmppComponent&, AdhocSession& session, XmlNode& command_node) -- cgit v1.2.3 From 70014a7f6611360d4862835586dbaa30df20a2d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sun, 12 Feb 2017 15:23:41 +0100 Subject: ci: run apt update before apt install in packaging:deb --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1b5c113..ac6f2bf 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -171,6 +171,7 @@ packaging:deb: - git checkout debian - git merge --no-commit --no-ff master - mk-build-deps + - apt update -y - apt install -y ./biboumi-build-deps*.deb - debuild -b -us -uc - mv ../*.deb . -- cgit v1.2.3 From 5ae33d6b9ed47bf43626066c5bdc4d91a7b75db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sun, 12 Feb 2017 16:50:47 +0100 Subject: e2e: add tests for the linger time option --- tests/end_to_end/__main__.py | 54 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/tests/end_to_end/__main__.py b/tests/end_to_end/__main__.py index 20730a7..92a903c 100644 --- a/tests/end_to_end/__main__.py +++ b/tests/end_to_end/__main__.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import collections +import datetime import slixmpp import asyncio import logging @@ -95,7 +96,11 @@ class XMPPComponent(slixmpp.BaseXMPP): def run_scenario(self): if self.scenario.steps: step = self.scenario.steps.pop(0) - step(self, self.biboumi) + try: + step(self, self.biboumi) + except Exception as e: + self.error(e) + self.run_scenario() else: if self.biboumi: self.biboumi.stop() @@ -261,6 +266,16 @@ def expect_stanza(xpaths, xmpp, biboumi, optional=False, after=None): else: print("Warning, from argument type passed to expect_stanza: %s" % (type(xpaths))) +def save_datetime(xmpp, biboumi): + xmpp.saved_values["saved_datetime"] = datetime.datetime.now() + asyncio.get_event_loop().call_soon(xmpp.run_scenario) + +def expect_now_is_after(timedelta, xmpp, biboumi): + time_passed = datetime.datetime.now() - xmpp.saved_values["saved_datetime"] + if time_passed < timedelta: + raise StanzaError("Not enough time has passed: %s instead of %s" % (time_passed, timedelta)) + asyncio.get_event_loop().call_soon(xmpp.run_scenario) + # list_of_xpaths: [(xpath, xpath), (xpath, xpath), (xpath)] def expect_unordered(list_of_xpaths, xmpp, biboumi): formatted_list_of_xpaths = [] @@ -473,7 +488,6 @@ def extract_attribute(xpath, name, stanza): def save_value(name, func, stanza, xmpp): xmpp.saved_values[name] = func(stanza) - if __name__ == '__main__': atexit.register(asyncio.get_event_loop().close) @@ -1947,6 +1961,42 @@ if __name__ == '__main__': partial(send_stanza, ""), partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='canceled']"), ]), + Scenario("irc_server_linger_time", + [ + handshake_sequence(), + # Set a custom value for the linger_time option, using the ad-hoc command + partial(send_stanza, ""), + partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='configure'][@sessionid][@status='executing']", + "/iq/commands:command/dataform:x[@type='form']/dataform:title[text()='Configure the IRC server irc.localhost']", + "/iq/commands:command/commands:actions/commands:next", + ), + after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid")) + ), + partial(send_stanza, "" + "" + "" + "3" + ""), + partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='completed']/commands:note[@type='info'][text()='Configuration successfully applied.']"), + + partial(send_stanza, + ""), + connection_sequence("irc.localhost", '{jid_one}/{resource_one}'), + partial(expect_stanza, + "/message/body[text()='Mode #foo [+nt] by {irc_host_one}']"), + partial(expect_stanza, + ("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']", + "/presence/muc_user:x/muc_user:status[@code='110']") + ), + partial(expect_stanza, "/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"), + + partial(save_datetime), + partial(send_stanza, ""), + partial(expect_stanza, "/presence[@type='unavailable'][@from='#foo%{irc_server_one}/{nick_one}']"), + partial(expect_stanza, "/message[@from='{irc_server_one}']/body[text()='ERROR: Closing Link: localhost (Client Quit)']"), + partial(expect_stanza, "/message[@from='{irc_server_one}']/body[text()='ERROR: Connection closed.']"), + partial(expect_now_is_after, datetime.timedelta(seconds=3)), + ]), Scenario("irc_tls_connection", [ handshake_sequence(), -- cgit v1.2.3 From 8b2f748b1d8de6513ca69e643b50477b0e5a2130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 13 Feb 2017 09:58:54 +0100 Subject: Do not send a not-connected error, on "unavailable" presences fix #3231 --- src/xmpp/biboumi_component.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index bd6975e..52bf2b7 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -179,10 +179,11 @@ void BiboumiComponent::handle_presence(const Stanza& stanza) } catch (const IRCNotConnected& ex) { - this->send_stanza_error("presence", from_str, to_str, id, - "cancel", "remote-server-not-found", - "Not connected to IRC server "s + ex.hostname, - true); + if (type == "unavailable") + this->send_stanza_error("presence", from_str, to_str, id, + "cancel", "remote-server-not-found", + "Not connected to IRC server "s + ex.hostname, + true); } stanza_error.disable(); } -- cgit v1.2.3 From 3a288340df860f6aeaf0f9a59734c1d39d091495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 13 Feb 2017 10:21:25 +0100 Subject: Fix the previous commit fix #3231 --- src/xmpp/biboumi_component.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 52bf2b7..663e92e 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -179,7 +179,7 @@ void BiboumiComponent::handle_presence(const Stanza& stanza) } catch (const IRCNotConnected& ex) { - if (type == "unavailable") + if (type != "unavailable") this->send_stanza_error("presence", from_str, to_str, id, "cancel", "remote-server-not-found", "Not connected to IRC server "s + ex.hostname, -- cgit v1.2.3 From fa6635e5487c3efe536c36a27be0ee10b918a346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 13 Feb 2017 10:24:16 +0100 Subject: Add a e2e test for the previous 2 commits ref #3231 --- tests/end_to_end/__main__.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/end_to_end/__main__.py b/tests/end_to_end/__main__.py index 92a903c..945bf6f 100644 --- a/tests/end_to_end/__main__.py +++ b/tests/end_to_end/__main__.py @@ -551,6 +551,22 @@ if __name__ == '__main__': partial(expect_stanza, "/message[@from='{irc_server_one}']/body[text()='ERROR: Closing Link: localhost (Client Quit)']"), partial(expect_stanza, "/message[@from='{irc_server_one}']/body[text()='ERROR: Connection closed.']"), ]), + Scenario("not_connected_error", + [ + handshake_sequence(), + partial(send_stanza, + ""), + partial(send_stanza, + ""), + connection_sequence("irc.localhost", '{jid_one}/{resource_one}'), + partial(expect_stanza, + "/message/body[text()='Mode #foo [+nt] by {irc_host_one}']"), + partial(expect_stanza, + ("/presence[@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']/muc_user:x/muc_user:item[@affiliation='admin'][@role='moderator']", + "/presence/muc_user:x/muc_user:status[@code='110']") + ), + partial(expect_stanza, "/message[@from='#foo%{irc_server_one}'][@type='groupchat']/subject[not(text())]"), + ]), Scenario("irc_server_disconnection", [ handshake_sequence(), -- cgit v1.2.3 From 7f08cf83aa5db58bfac004dddae565e6536eeb2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 15 Feb 2017 01:02:27 +0100 Subject: Little scopeguard cleanup, and add a test --- louloulibs/utils/encoding.cpp | 4 ++-- louloulibs/utils/scopeguard.hpp | 6 ++++-- tests/utils.cpp | 11 +++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/louloulibs/utils/encoding.cpp b/louloulibs/utils/encoding.cpp index 087095f..aa91dac 100644 --- a/louloulibs/utils/encoding.cpp +++ b/louloulibs/utils/encoding.cpp @@ -152,7 +152,7 @@ namespace utils throw std::runtime_error("Cannot convert into UTF-8"); // Make sure cd is always closed when we leave this function - const auto sg = utils::make_scope_guard([&cd](auto&&){ iconv_close(cd); }); + const auto sg = utils::make_scope_guard([&cd](){ iconv_close(cd); }); size_t inbytesleft = str.size(); @@ -169,7 +169,7 @@ namespace utils char* outbuf_ptr = outbuf; // Make sure outbuf is always deleted when we leave this function - const auto sg2 = utils::make_scope_guard([outbuf](auto&&){ delete[] outbuf; }); + const auto sg2 = utils::make_scope_guard([outbuf](){ delete[] outbuf; }); bool done = false; while (done == false) diff --git a/louloulibs/utils/scopeguard.hpp b/louloulibs/utils/scopeguard.hpp index cd0e89e..e697fc3 100644 --- a/louloulibs/utils/scopeguard.hpp +++ b/louloulibs/utils/scopeguard.hpp @@ -87,9 +87,11 @@ private: }; template -auto make_scope_guard(F&& f) +auto make_scope_guard(F f) { - return std::unique_ptr>{(void*)1, std::forward(f)}; + static struct Empty {} empty; + auto deleter = [f = std::move(f)](Empty*) { f(); }; + return std::unique_ptr{&empty, std::move(deleter)}; } } diff --git a/tests/utils.cpp b/tests/utils.cpp index 48951da..d1f0edf 100644 --- a/tests/utils.cpp +++ b/tests/utils.cpp @@ -8,6 +8,7 @@ #include #include #include +#include using namespace std::string_literals; @@ -140,3 +141,13 @@ TEST_CASE("parse_datetime") CHECK(utils::parse_datetime("1970-01-02T00:00:12*00:00") == -1); CHECK(utils::parse_datetime("1970-01-02T00:00:12+0000") == -1); } + +TEST_CASE("scope_guard") +{ + bool res = false; + { + auto guard = utils::make_scope_guard([&res](){ res = true; }); + CHECK(!res); + } + CHECK(res); +} -- cgit v1.2.3 From fef585ad6699042e594f407afe78df1e40344efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 15 Feb 2017 01:05:42 +0100 Subject: Surround ipv6 with [], and properly cleanup otherwise invalid domains fix #2694 (yeah, it was closed, but it was badly fixed) --- louloulibs/xmpp/jid.cpp | 74 +++++++++++++++++++++++++++++++++++++++++-------- tests/jid.cpp | 20 +++++++++---- 2 files changed, 77 insertions(+), 17 deletions(-) diff --git a/louloulibs/xmpp/jid.cpp b/louloulibs/xmpp/jid.cpp index 7b62f3e..d17d4e9 100644 --- a/louloulibs/xmpp/jid.cpp +++ b/louloulibs/xmpp/jid.cpp @@ -6,6 +6,9 @@ #include #ifdef LIBIDN_FOUND #include + #include + #include + #include #endif #include @@ -58,19 +61,68 @@ std::string jidprep(const std::string& original) char domain[max_jid_part_len] = {}; memcpy(domain, jid.domain.data(), std::min(max_jid_part_len, jid.domain.size())); - rc = static_cast(::stringprep(domain, max_jid_part_len, - static_cast(0), stringprep_nameprep)); - if (rc != STRINGPREP_OK) + { - log_error(error_msg + stringprep_strerror(rc)); - return ""; + // Using getaddrinfo, check if the domain part is a valid IPv4 (then use + // it as is), or IPv6 (surround it with []), or a domain name (run + // nameprep) + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_NUMERICHOST; + hints.ai_family = AF_UNSPEC; + + struct addrinfo* res = nullptr; + auto addrinfo_deleter = utils::make_scope_guard([res]() { if (res) freeaddrinfo(res); }); + if (::getaddrinfo(domain, nullptr, &hints, &res) || !res || + (res->ai_family != AF_INET && res->ai_family != AF_INET6)) + { // Not an IP, run nameprep on it + rc = static_cast(::stringprep(domain, max_jid_part_len, + static_cast(0), stringprep_nameprep)); + if (rc != STRINGPREP_OK) + { + log_error(error_msg + stringprep_strerror(rc)); + return ""; + } + + // Make sure it contains only allowed characters + using std::begin; + using std::end; + char* domain_end = domain + ::strlen(domain); + std::replace_if(std::begin(domain), domain + ::strlen(domain), + [](const char c) -> bool + { + return !((c >= 'a' && c <= 'z') || c == '-' || + (c >= '0' && c <= '9') || c == '.'); + }, '-'); + // Make sure there are no doubled - or . + std::set special_chars{'-', '.'}; + domain_end = std::unique(begin(domain), domain + ::strlen(domain), [&special_chars](const char& a, const char& b) -> bool + { + return special_chars.count(a) && special_chars.count(b); + }); + // remove leading and trailing -. if any + if (domain_end != domain && special_chars.count(*(domain_end - 1))) + --domain_end; + if (domain_end != domain && special_chars.count(domain[0])) + { + std::memmove(domain, domain + 1, domain_end - domain + 1); + --domain_end; + } + // And if the final result is an empty string, return a dummy hostname + if (domain_end == domain) + ::strcpy(domain, "empty"); + else + *domain_end = '\0'; + } + else if (res->ai_family == AF_INET6) + { // IPv6, surround it with []. The length is always enough: + // the longest possible IPv6 is way shorter than max_jid_part_len + ::memmove(domain + 1, domain, jid.domain.size()); + domain[0] = '['; + domain[jid.domain.size() + 1] = ']'; + } } - std::replace_if(std::begin(domain), domain + ::strlen(domain), - [](const char c) -> bool - { - return !((c >= 'a' && c <= 'z') || c == '-' || - (c >= '0' && c <= '9') || c == '.'); - }, '-'); + // If there is no resource, stop here if (jid.resource.empty()) diff --git a/tests/jid.cpp b/tests/jid.cpp index 9015afd..089f797 100644 --- a/tests/jid.cpp +++ b/tests/jid.cpp @@ -15,7 +15,10 @@ TEST_CASE("Jid") CHECK(jid2.local == ""); CHECK(jid2.domain == "ツ.coucou"); CHECK(jid2.resource == "coucou@coucou/coucou"); +} +TEST_CASE("jidprep") +{ // Jidprep const std::string badjid("~zigougou™@EpiK-7D9D1FDE.poez.io/Boujour/coucou/slt™"); const std::string correctjid = jidprep(badjid); @@ -26,13 +29,18 @@ TEST_CASE("Jid") CHECK(jidprep(badjid) == "~zigougoutm@epik-7d9d1fde.poez.io/Boujour/coucou/sltTM"); CHECK(jidprep(badjid) == "~zigougoutm@epik-7d9d1fde.poez.io/Boujour/coucou/sltTM"); - const std::string badjid2("Zigougou@poez.io"); - const std::string correctjid2 = jidprep(badjid2); - CHECK(correctjid2 == "zigougou@poez.io"); + CHECK(jidprep("Zigougou@poez.io") == "zigougou@poez.io"); + + CHECK(jidprep("~Bisous@88.123.43.45") == "~bisous@88.123.43.45"); + + CHECK(jidprep("~Bisous@::ffff:42.156.139.46") == "~bisous@[::ffff:42.156.139.46]"); + + CHECK(jidprep("louiz!6bf74289@2001:bc8:38e7::") == "louiz!6bf74289@[2001:bc8:38e7::]"); - const std::string crappy("~Bisous@7ea8beb1:c5fd2849:da9a048e:ip"); - const std::string fixed_crappy = jidprep(crappy); - CHECK(fixed_crappy == "~bisous@7ea8beb1-c5fd2849-da9a048e-ip"); + CHECK(jidprep("louiz@+:::::----coucou.com78--.") == "louiz@coucou.com78"); + CHECK(jidprep("louiz@coucou.com78--.") == "louiz@coucou.com78"); + CHECK(jidprep("louiz@+:::::----coucou.com78") == "louiz@coucou.com78"); + CHECK(jidprep("louiz@:::::") == "louiz@empty"); #else // Without libidn, jidprep always returns an empty string CHECK(jidprep(badjid) == ""); #endif -- cgit v1.2.3 From 561bbe9c145a80befc5b98c9865881e7f5d57648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 15 Feb 2017 01:19:36 +0100 Subject: Fix a leak on getaddrinfo, thank you LeakSanitizer! --- louloulibs/xmpp/jid.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/louloulibs/xmpp/jid.cpp b/louloulibs/xmpp/jid.cpp index d17d4e9..493ddc1 100644 --- a/louloulibs/xmpp/jid.cpp +++ b/louloulibs/xmpp/jid.cpp @@ -71,10 +71,10 @@ std::string jidprep(const std::string& original) hints.ai_flags = AI_NUMERICHOST; hints.ai_family = AF_UNSPEC; - struct addrinfo* res = nullptr; - auto addrinfo_deleter = utils::make_scope_guard([res]() { if (res) freeaddrinfo(res); }); - if (::getaddrinfo(domain, nullptr, &hints, &res) || !res || - (res->ai_family != AF_INET && res->ai_family != AF_INET6)) + struct addrinfo* addr_res = nullptr; + const auto ret = ::getaddrinfo(domain, nullptr, &hints, &addr_res); + auto addrinfo_deleter = utils::make_scope_guard([addr_res] { freeaddrinfo(addr_res); }); + if (ret || !addr_res || (addr_res->ai_family != AF_INET && addr_res->ai_family != AF_INET6)) { // Not an IP, run nameprep on it rc = static_cast(::stringprep(domain, max_jid_part_len, static_cast(0), stringprep_nameprep)); @@ -114,7 +114,7 @@ std::string jidprep(const std::string& original) else *domain_end = '\0'; } - else if (res->ai_family == AF_INET6) + else if (addr_res->ai_family == AF_INET6) { // IPv6, surround it with []. The length is always enough: // the longest possible IPv6 is way shorter than max_jid_part_len ::memmove(domain + 1, domain, jid.domain.size()); -- cgit v1.2.3 From efb8a11c5763632eee0fffea190a90712c6373f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 15 Feb 2017 01:27:45 +0100 Subject: Add missing include --- louloulibs/xmpp/jid.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/louloulibs/xmpp/jid.cpp b/louloulibs/xmpp/jid.cpp index 493ddc1..5862599 100644 --- a/louloulibs/xmpp/jid.cpp +++ b/louloulibs/xmpp/jid.cpp @@ -6,6 +6,8 @@ #include #ifdef LIBIDN_FOUND #include + #include + #include #include #include #include -- cgit v1.2.3 From 679bf94192695f2d6e7fe7e991bf490f95f63d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 15 Feb 2017 01:46:29 +0100 Subject: Only call freeaddrinfo if an actual addrinfo struct has been allocated --- louloulibs/xmpp/jid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/louloulibs/xmpp/jid.cpp b/louloulibs/xmpp/jid.cpp index 5862599..46e01ea 100644 --- a/louloulibs/xmpp/jid.cpp +++ b/louloulibs/xmpp/jid.cpp @@ -75,7 +75,7 @@ std::string jidprep(const std::string& original) struct addrinfo* addr_res = nullptr; const auto ret = ::getaddrinfo(domain, nullptr, &hints, &addr_res); - auto addrinfo_deleter = utils::make_scope_guard([addr_res] { freeaddrinfo(addr_res); }); + auto addrinfo_deleter = utils::make_scope_guard([addr_res] { if (addr_res) freeaddrinfo(addr_res); }); if (ret || !addr_res || (addr_res->ai_family != AF_INET && addr_res->ai_family != AF_INET6)) { // Not an IP, run nameprep on it rc = static_cast(::stringprep(domain, max_jid_part_len, -- cgit v1.2.3 From 6c35f49dd8c0a8f8add13c177660e65c64e649eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 17 Feb 2017 18:25:49 +0100 Subject: Add a biboumi Dockerfile --- docker/biboumi/Dockerfile | 45 ++++++++++++++++++++++++++++++++++++++ docker/biboumi/README.rst | 51 ++++++++++++++++++++++++++++++++++++++++++++ docker/biboumi/biboumi.cfg | 6 ++++++ docker/biboumi/entrypoint.sh | 10 +++++++++ 4 files changed, 112 insertions(+) create mode 100644 docker/biboumi/Dockerfile create mode 100644 docker/biboumi/README.rst create mode 100644 docker/biboumi/biboumi.cfg create mode 100644 docker/biboumi/entrypoint.sh diff --git a/docker/biboumi/Dockerfile b/docker/biboumi/Dockerfile new file mode 100644 index 0000000..95bd150 --- /dev/null +++ b/docker/biboumi/Dockerfile @@ -0,0 +1,45 @@ +# This Dockerfile creates a docker image running biboumi + +FROM docker.io/fedora:latest + +RUN dnf --refresh install -y\ + gcc-c++\ + cmake\ + make\ + udns-devel\ + sqlite-devel\ + libuuid-devel\ + expat-devel\ + libidn-devel\ + systemd-devel\ + git\ + python\ + && dnf clean all + +# Install botan +RUN git clone https://github.com/randombit/botan.git && cd botan && ./configure.py --prefix=/usr && make -j8 && make install && ldconfig && rm -rf /botan + +# Install litesql +RUN git clone git://git.louiz.org/litesql && mkdir /litesql/build && cd /litesql/build && cmake .. -DCMAKE_INSTALL_PREFIX=/usr && make -j8 && cd /litesql/build && make install && ldconfig && rm -rf /litesql + +# Install biboumi +RUN git clone git://git.louiz.org/biboumi && mkdir ./biboumi/build && cd ./biboumi/build &&\ + cmake .. -DCMAKE_INSTALL_PREFIX=/usr\ + -DCMAKE_BUILD_TYPE=Release\ + -DWITH_BOTAN=1\ + -DWITH_LITESQL=1\ + -DWITH_LIBIDN=1\ + -DWITH_SYSTEMD=1\ + && make -j8 && make install && rm -rf /biboumi + +RUN useradd biboumi + +COPY ./biboumi.cfg /etc/biboumi/biboumi.cfg +RUN chown -R biboumi:biboumi /etc/biboumi + +COPY ./entrypoint.sh /entrypoint.sh +RUN chmod 755 /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] + +USER biboumi diff --git a/docker/biboumi/README.rst b/docker/biboumi/README.rst new file mode 100644 index 0000000..b9c63ea --- /dev/null +++ b/docker/biboumi/README.rst @@ -0,0 +1,51 @@ +Biboumi Docker Image +==================== + +Running +------- + +This image does not embed any XMPP server. You need to have a running XMPP +server (as an other docker container for example) first. + +Assuming you have a running `prosody +`_ container already running and +`properly configured +`_ you can +use the following command to start your biboumi container. + +``` +docker run --link prosody:xmpp \ + -e BIBOUMI_PASSWORD=P4SSW0RD \ + -e BIBOUMI_HOSTNAME=irc.example.com \ + -e BIBOUMI_ADMIN=blabla \ + biboumi +``` + +Variables +--------- + +The configuration file inside the image is a template that is completed when +the container is started, using the following environment variables: + +* BIBOUMI_HOSTNAME: Sets the value of the *hostname* option. +* BIBOUMI_SECRET: Sets the value of the *password* option. +* BIBOUMI_ADMIN: Sets the value of the *admin* option. + +All these variables are optional, but biboumi will probably fail to start if +the hostname and secret are missing. + +You can also directly provide your own configuration file by mounting it +inside the container using the -v option: + +``` +docker run --link prosody:xmpp \ + -v $PWD/biboumi.cfg:/etc/biboumi/biboumi.cfg \ + biboumi +``` + +Linking with the XMPP server +---------------------------- + +You can use the --link option to connect to any server, but it needs to be +called *xmpp*. For example, if you are using a container named ejabberd, you +would use the option *--link ejabberd:xmpp*. diff --git a/docker/biboumi/biboumi.cfg b/docker/biboumi/biboumi.cfg new file mode 100644 index 0000000..fff6563 --- /dev/null +++ b/docker/biboumi/biboumi.cfg @@ -0,0 +1,6 @@ +xmpp_server_ip=xmpp +port=5347 +db_name=/var/lib/biboumi/biboumi.sqlite +hostname=BIBOUMI_HOSTNAME +password=BIBOUMI_PASSWORD +admin=BIBOUMI_ADMIN diff --git a/docker/biboumi/entrypoint.sh b/docker/biboumi/entrypoint.sh new file mode 100644 index 0000000..a0c0508 --- /dev/null +++ b/docker/biboumi/entrypoint.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +sed -i s/BIBOUMI_HOSTNAME/${BIBOUMI_HOSTNAME:-biboumi.localhost}/ /etc/biboumi/biboumi.cfg +sed -i s/BIBOUMI_ADMIN/${BIBOUMI_ADMIN:-}/ /etc/biboumi/biboumi.cfg +sed -i s/BIBOUMI_SECRET/${BIBOUMI_SECRET:-missing_secret}/ /etc/biboumi/biboumi.cfg + +echo "Running biboumi with the following conf: " +cat /etc/biboumi/biboumi.cfg + +/usr/bin/biboumi /etc/biboumi/biboumi.cfg -- cgit v1.2.3 From 724b7bf8e912f241770c3a9a6e9a3941b0922a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 17 Feb 2017 18:32:55 +0100 Subject: ci: Add a packaging:docker job that builds and push to the image docker.io --- .gitlab-ci.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ac6f2bf..fb172ce 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -180,3 +180,14 @@ packaging:deb: artifacts: untracked: true name: $CI_PROJECT_NAME-deb-$CI_BUILD_ID + +packaging:docker: + stage: packaging + only: + - master@louiz/biboumi + tags: + - docker-in-docker + script: + - docker login -p $DOCKER_PASSWORD -u louiz -e none@none docker.io + - docker build -t docker.io/louiz/biboumi docker/biboumi + - docker push docker.io/louiz/biboumi -- cgit v1.2.3 From 384f3591e7ac9858ee7683ef5d5ad43451fc1c0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 17 Feb 2017 10:51:44 +0100 Subject: ci: Empty the before_script for the packaging:docker job --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fb172ce..ff5e8ee 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -187,6 +187,7 @@ packaging:docker: - master@louiz/biboumi tags: - docker-in-docker + before_script: [] script: - docker login -p $DOCKER_PASSWORD -u louiz -e none@none docker.io - docker build -t docker.io/louiz/biboumi docker/biboumi -- cgit v1.2.3 From a03fd18d0a4412ae05b08f5923c346a8fbbbfa69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 17 Feb 2017 20:27:26 +0100 Subject: ci: remove all mention of docker.io in packaging:docker --- .gitlab-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ff5e8ee..facda29 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -189,6 +189,6 @@ packaging:docker: - docker-in-docker before_script: [] script: - - docker login -p $DOCKER_PASSWORD -u louiz -e none@none docker.io - - docker build -t docker.io/louiz/biboumi docker/biboumi - - docker push docker.io/louiz/biboumi + - docker login -p $DOCKER_PASSWORD -u louiz + - docker build -t louiz/biboumi docker/biboumi + - docker push louiz/biboumi -- cgit v1.2.3 From f90969e1a18c148d93c82ab09ae48e4f634efbb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 17 Feb 2017 22:57:30 +0100 Subject: docker: Properly handle and document the /var/lib/biboumi directory --- docker/biboumi/Dockerfile | 3 +++ docker/biboumi/README.rst | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/docker/biboumi/Dockerfile b/docker/biboumi/Dockerfile index 95bd150..721d106 100644 --- a/docker/biboumi/Dockerfile +++ b/docker/biboumi/Dockerfile @@ -34,6 +34,9 @@ RUN git clone git://git.louiz.org/biboumi && mkdir ./biboumi/build && cd ./bibou RUN useradd biboumi +RUN mkdir /var/lib/biboumi +RUN chown -R biboumi:biboumi /var/lib/biboumi + COPY ./biboumi.cfg /etc/biboumi/biboumi.cfg RUN chown -R biboumi:biboumi /etc/biboumi diff --git a/docker/biboumi/README.rst b/docker/biboumi/README.rst index b9c63ea..fb4b212 100644 --- a/docker/biboumi/README.rst +++ b/docker/biboumi/README.rst @@ -15,6 +15,7 @@ use the following command to start your biboumi container. ``` docker run --link prosody:xmpp \ + -v $PWD/database:/var/lib/biboumi \ -e BIBOUMI_PASSWORD=P4SSW0RD \ -e BIBOUMI_HOSTNAME=irc.example.com \ -e BIBOUMI_ADMIN=blabla \ @@ -49,3 +50,10 @@ Linking with the XMPP server You can use the --link option to connect to any server, but it needs to be called *xmpp*. For example, if you are using a container named ejabberd, you would use the option *--link ejabberd:xmpp*. +Volumes +------- + +The database is stored in the /var/lib/biboumi/ directory. If you don’t bind +a local directory to it, the database will be lost when the container is +stopped. If you want to keep your database between each run, bind it with +the -v option, like this: **-v /srv/biboumi/:/var/lib/biboumi**. -- cgit v1.2.3 From 27d847711c5e663d2fa3b2295f5f50c898783eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 17 Feb 2017 14:58:23 +0100 Subject: docker: Add the XMPP_SERVER_IP option, and document the --network=host usage --- docker/biboumi/README.rst | 27 +++++++++++++++++++++++---- docker/biboumi/biboumi.cfg | 2 +- docker/biboumi/entrypoint.sh | 1 + 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/docker/biboumi/README.rst b/docker/biboumi/README.rst index fb4b212..f6d529d 100644 --- a/docker/biboumi/README.rst +++ b/docker/biboumi/README.rst @@ -5,7 +5,7 @@ Running ------- This image does not embed any XMPP server. You need to have a running XMPP -server (as an other docker container for example) first. +server first: as an other docker image, or running on the host machine. Assuming you have a running `prosody `_ container already running and @@ -22,6 +22,19 @@ docker run --link prosody:xmpp \ biboumi ``` +If instead you already have an XMPP server running on the host machine, you +can start the biboumi container like this: + +``` +docker run --network=host \ + -v $PWD/database:/var/lib/biboumi \ + -e BIBOUMI_PASSWORD=P4SSW0RD \ + -e BIBOUMI_HOSTNAME=irc.example.com \ + -e BIBOUMI_ADMIN=blabla \ + -e BIBOUMI_XMPP_SERVER_IP=127.0.0.1 \ + biboumi +``` + Variables --------- @@ -31,6 +44,7 @@ the container is started, using the following environment variables: * BIBOUMI_HOSTNAME: Sets the value of the *hostname* option. * BIBOUMI_SECRET: Sets the value of the *password* option. * BIBOUMI_ADMIN: Sets the value of the *admin* option. +* BIBOUMI_XMPP_SERVER_IP: Sets the value of the *xmpp_server_ip* option. The default is **xmpp**. All these variables are optional, but biboumi will probably fail to start if the hostname and secret are missing. @@ -47,9 +61,14 @@ docker run --link prosody:xmpp \ Linking with the XMPP server ---------------------------- -You can use the --link option to connect to any server, but it needs to be -called *xmpp*. For example, if you are using a container named ejabberd, you -would use the option *--link ejabberd:xmpp*. +You can use the --link option to connect to any server running in a docker +container, but it needs to be called *xmpp*, or the custom value set for the +**BIBOUMI_XMPP_SERVER_IP** option. For example, if you are using a container +named ejabberd, you would use the option *--link ejabberd:xmpp*. + +If you want to connect to the XMPP server running on the host machine, use +the **--network=host** option. + Volumes ------- diff --git a/docker/biboumi/biboumi.cfg b/docker/biboumi/biboumi.cfg index fff6563..cc5df61 100644 --- a/docker/biboumi/biboumi.cfg +++ b/docker/biboumi/biboumi.cfg @@ -1,4 +1,4 @@ -xmpp_server_ip=xmpp +xmpp_server_ip=BIBOUMI_XMPP_SERVER_IP port=5347 db_name=/var/lib/biboumi/biboumi.sqlite hostname=BIBOUMI_HOSTNAME diff --git a/docker/biboumi/entrypoint.sh b/docker/biboumi/entrypoint.sh index a0c0508..4d00164 100644 --- a/docker/biboumi/entrypoint.sh +++ b/docker/biboumi/entrypoint.sh @@ -1,5 +1,6 @@ #!/bin/bash +sed -i s/BIBOUMI_XMPP_SERVER_IP/${BIBOUMI_XMPP_SERVER_IP:-xmpp}/ /etc/biboumi/biboumi.cfg sed -i s/BIBOUMI_HOSTNAME/${BIBOUMI_HOSTNAME:-biboumi.localhost}/ /etc/biboumi/biboumi.cfg sed -i s/BIBOUMI_ADMIN/${BIBOUMI_ADMIN:-}/ /etc/biboumi/biboumi.cfg sed -i s/BIBOUMI_SECRET/${BIBOUMI_SECRET:-missing_secret}/ /etc/biboumi/biboumi.cfg -- cgit v1.2.3 From 9f978cda943619c95a41e5da9047c3cc0dd31555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Fri, 17 Feb 2017 22:59:16 +0100 Subject: docker: fix the SECRET->PASSWORD in entrypoint.sh --- docker/biboumi/entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/biboumi/entrypoint.sh b/docker/biboumi/entrypoint.sh index 4d00164..eda53a4 100644 --- a/docker/biboumi/entrypoint.sh +++ b/docker/biboumi/entrypoint.sh @@ -3,7 +3,7 @@ sed -i s/BIBOUMI_XMPP_SERVER_IP/${BIBOUMI_XMPP_SERVER_IP:-xmpp}/ /etc/biboumi/biboumi.cfg sed -i s/BIBOUMI_HOSTNAME/${BIBOUMI_HOSTNAME:-biboumi.localhost}/ /etc/biboumi/biboumi.cfg sed -i s/BIBOUMI_ADMIN/${BIBOUMI_ADMIN:-}/ /etc/biboumi/biboumi.cfg -sed -i s/BIBOUMI_SECRET/${BIBOUMI_SECRET:-missing_secret}/ /etc/biboumi/biboumi.cfg +sed -i s/BIBOUMI_PASSWORD/${BIBOUMI_PASSWORD:-missing_password}/ /etc/biboumi/biboumi.cfg echo "Running biboumi with the following conf: " cat /etc/biboumi/biboumi.cfg -- cgit v1.2.3 From d81cbc4a33ee2c28628ccb632af9ae1b27e84d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 27 Feb 2017 18:01:20 +0100 Subject: Use uname() instead of CMAKE_SYSTEM fix #3235 --- louloulibs/louloulibs.h.cmake | 1 - louloulibs/utils/system.cpp | 21 +++++++++++++++++++++ louloulibs/utils/system.hpp | 8 ++++++++ louloulibs/xmpp/xmpp_component.cpp | 3 ++- tests/utils.cpp | 7 +++++++ 5 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 louloulibs/utils/system.cpp create mode 100644 louloulibs/utils/system.hpp diff --git a/louloulibs/louloulibs.h.cmake b/louloulibs/louloulibs.h.cmake index ebb9b9a..e2b2e25 100644 --- a/louloulibs/louloulibs.h.cmake +++ b/louloulibs/louloulibs.h.cmake @@ -1,4 +1,3 @@ -#define SYSTEM_NAME "${CMAKE_SYSTEM}" #cmakedefine ICONV_SECOND_ARGUMENT_IS_CONST #cmakedefine LIBIDN_FOUND #cmakedefine SYSTEMD_FOUND diff --git a/louloulibs/utils/system.cpp b/louloulibs/utils/system.cpp new file mode 100644 index 0000000..c0bee11 --- /dev/null +++ b/louloulibs/utils/system.cpp @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +using namespace std::string_literals; + +namespace utils +{ +std::string get_system_name() +{ + struct utsname uts; + const int res = ::uname(&uts); + if (res == -1) + { + log_error("uname failed: ", std::strerror(errno)); + return "Unknown"; + } + return uts.sysname + " "s + uts.release; +} +} \ No newline at end of file diff --git a/louloulibs/utils/system.hpp b/louloulibs/utils/system.hpp new file mode 100644 index 0000000..7ea1677 --- /dev/null +++ b/louloulibs/utils/system.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include + +namespace utils +{ +std::string get_system_name(); +} \ No newline at end of file diff --git a/louloulibs/xmpp/xmpp_component.cpp b/louloulibs/xmpp/xmpp_component.cpp index e1b6131..e40b1e4 100644 --- a/louloulibs/xmpp/xmpp_component.cpp +++ b/louloulibs/xmpp/xmpp_component.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -585,7 +586,7 @@ void XmppComponent::send_version(const std::string& id, const std::string& jid_t } { XmlSubNode os(query, "os"); - os.set_inner(SYSTEM_NAME); + os.set_inner(utils::get_system_name()); } } else diff --git a/tests/utils.cpp b/tests/utils.cpp index d1f0edf..b8a3e75 100644 --- a/tests/utils.cpp +++ b/tests/utils.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include using namespace std::string_literals; @@ -151,3 +152,9 @@ TEST_CASE("scope_guard") } CHECK(res); } + +TEST_CASE("system_name") +{ + CHECK(utils::get_system_name() != "Unknown"); + CHECK(!utils::get_system_name().empty()); +} \ No newline at end of file -- cgit v1.2.3 From dcb48c5a20be1440ad87f1996b3373cb51f0fe07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 28 Feb 2017 18:24:51 +0100 Subject: Add a irc channel ad-hoc configure test --- tests/end_to_end/__main__.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/end_to_end/__main__.py b/tests/end_to_end/__main__.py index 945bf6f..e26b5db 100644 --- a/tests/end_to_end/__main__.py +++ b/tests/end_to_end/__main__.py @@ -1977,6 +1977,37 @@ if __name__ == '__main__': partial(send_stanza, ""), partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='canceled']"), ]), + Scenario("irc_channel_configure", + [ + handshake_sequence(), + partial(send_stanza, ""), + partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='configure'][@sessionid][@status='executing']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_in']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_out']", + ), + after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid")) + ), + partial(send_stanza, "" + "" + "" + "" + "UTF-8" + "latin-1" + ""), + partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='completed']/commands:note[@type='info'][text()='Configuration successfully applied.']"), + + partial(send_stanza, ""), + partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='configure'][@sessionid][@status='executing']", + "/iq/commands:command/dataform:x[@type='form']/dataform:title[text()='Configure the IRC channel #foo on server irc.localhost']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_in']/dataform:value[text()='latin-1']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_out']/dataform:value[text()='UTF-8']", + "/iq/commands:command/commands:actions/commands:next", + ), + after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid")) + ), + partial(send_stanza, ""), + partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='canceled']"), + ]), Scenario("irc_server_linger_time", [ handshake_sequence(), -- cgit v1.2.3 From 26eb28dc2368d14e171201a0c6b76b76b19e1ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 28 Feb 2017 19:39:09 +0100 Subject: Split the biboumi dockerfile into two, to be able to disable the cache --- .gitlab-ci.yml | 2 +- docker/biboumi/Dockerfile | 30 +++++------------------------- docker/biboumi/Dockerfile.base | 23 +++++++++++++++++++++++ docker/biboumi/README.rst | 20 ++++++++++++++++++++ docker/biboumi/build-docker.sh | 14 ++++++++++++++ 5 files changed, 63 insertions(+), 26 deletions(-) create mode 100644 docker/biboumi/Dockerfile.base create mode 100755 docker/biboumi/build-docker.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index facda29..70c1fe8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -190,5 +190,5 @@ packaging:docker: before_script: [] script: - docker login -p $DOCKER_PASSWORD -u louiz - - docker build -t louiz/biboumi docker/biboumi + - ./docker/biboumi/build-docker.sh louiz/biboumi - docker push louiz/biboumi diff --git a/docker/biboumi/Dockerfile b/docker/biboumi/Dockerfile index 721d106..7e73c9a 100644 --- a/docker/biboumi/Dockerfile +++ b/docker/biboumi/Dockerfile @@ -1,28 +1,8 @@ -# This Dockerfile creates a docker image running biboumi - -FROM docker.io/fedora:latest - -RUN dnf --refresh install -y\ - gcc-c++\ - cmake\ - make\ - udns-devel\ - sqlite-devel\ - libuuid-devel\ - expat-devel\ - libidn-devel\ - systemd-devel\ - git\ - python\ - && dnf clean all - -# Install botan -RUN git clone https://github.com/randombit/botan.git && cd botan && ./configure.py --prefix=/usr && make -j8 && make install && ldconfig && rm -rf /botan - -# Install litesql -RUN git clone git://git.louiz.org/litesql && mkdir /litesql/build && cd /litesql/build && cmake .. -DCMAKE_INSTALL_PREFIX=/usr && make -j8 && cd /litesql/build && make install && ldconfig && rm -rf /litesql - -# Install biboumi +# This dockerfile uses the image built using Dockerfile.base, and installs +# biboumi in it + +FROM biboumi-base + RUN git clone git://git.louiz.org/biboumi && mkdir ./biboumi/build && cd ./biboumi/build &&\ cmake .. -DCMAKE_INSTALL_PREFIX=/usr\ -DCMAKE_BUILD_TYPE=Release\ diff --git a/docker/biboumi/Dockerfile.base b/docker/biboumi/Dockerfile.base new file mode 100644 index 0000000..bbc32c2 --- /dev/null +++ b/docker/biboumi/Dockerfile.base @@ -0,0 +1,23 @@ +# This dockerfile install all the dependencies needing to compile biboumi + +FROM docker.io/fedora:latest + +RUN dnf --refresh install -y\ + gcc-c++\ + cmake\ + make\ + udns-devel\ + sqlite-devel\ + libuuid-devel\ + expat-devel\ + libidn-devel\ + systemd-devel\ + git\ + python\ + && dnf clean all + +# Install botan +RUN git clone https://github.com/randombit/botan.git && cd botan && ./configure.py --prefix=/usr && make -j8 && make install && ldconfig && rm -rf /botan + +# Install litesql +RUN git clone git://git.louiz.org/litesql && mkdir /litesql/build && cd /litesql/build && cmake .. -DCMAKE_INSTALL_PREFIX=/usr && make -j8 && cd /litesql/build && make install && ldconfig && rm -rf /litesql diff --git a/docker/biboumi/README.rst b/docker/biboumi/README.rst index f6d529d..d2e2a7e 100644 --- a/docker/biboumi/README.rst +++ b/docker/biboumi/README.rst @@ -76,3 +76,23 @@ The database is stored in the /var/lib/biboumi/ directory. If you don’t bind a local directory to it, the database will be lost when the container is stopped. If you want to keep your database between each run, bind it with the -v option, like this: **-v /srv/biboumi/:/var/lib/biboumi**. + +Building +-------- + +This image is built from 2 Dockerfiles: +- Dockerfile.base: builds and installs all the dependencies needed to build and run biboumi +- Dockerfile: builds and installs biboumi itself + +The goal is to be able to force the rebuild of biboumi itself (by using +the --no-cache option) without having to rebuild and install all its +dependencies. + +The build does not require any file in the build context, everything is +fetched during the build using git or dnf. + +To build a biboumi image named “foo/biboumi”, you can run the script: + +``` +./build-docker.sh foo/biboumi +``` diff --git a/docker/biboumi/build-docker.sh b/docker/biboumi/build-docker.sh new file mode 100755 index 0000000..d206b89 --- /dev/null +++ b/docker/biboumi/build-docker.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +if [[ -z "$1" ]]; then + echo "Usage: ./build-docker.sh " + echo "Example: ./build-docker.sh docker.io/coucou/biboumi" + exit 1 +fi + +directory=$(dirname $0) +image_name=$1 + +echo $directory +docker build -t biboumi-base $directory -f $directory/Dockerfile.base +docker build -t $image_name $directory -f $directory/Dockerfile --no-cache -- cgit v1.2.3 From 9a4b5d96cec0795a3cfdb5af887c273b5538452e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 28 Feb 2017 22:04:20 +0100 Subject: Also test the channel config on a fixed_irc_server instance --- tests/end_to_end/__main__.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/end_to_end/__main__.py b/tests/end_to_end/__main__.py index e26b5db..b84c9b1 100644 --- a/tests/end_to_end/__main__.py +++ b/tests/end_to_end/__main__.py @@ -2008,6 +2008,37 @@ if __name__ == '__main__': partial(send_stanza, ""), partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='canceled']"), ]), + Scenario("irc_channel_configure_fixed", + [ + handshake_sequence(), + partial(send_stanza, ""), + partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='configure'][@sessionid][@status='executing']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_in']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_out']", + ), + after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid")) + ), + partial(send_stanza, "" + "" + "" + "" + "UTF-8" + "latin-1" + ""), + partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='completed']/commands:note[@type='info'][text()='Configuration successfully applied.']"), + + partial(send_stanza, ""), + partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='configure'][@sessionid][@status='executing']", + "/iq/commands:command/dataform:x[@type='form']/dataform:title[text()='Configure the IRC channel #foo on server irc.localhost']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_in']/dataform:value[text()='latin-1']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@type='text-single'][@var='encoding_out']/dataform:value[text()='UTF-8']", + "/iq/commands:command/commands:actions/commands:next", + ), + after = partial(save_value, "sessionid", partial(extract_attribute, "/iq[@type='result']/commands:command[@node='configure']", "sessionid")) + ), + partial(send_stanza, ""), + partial(expect_stanza, "/iq[@type='result']/commands:command[@node='configure'][@status='canceled']"), + ], conf='fixed_server'), Scenario("irc_server_linger_time", [ handshake_sequence(), -- cgit v1.2.3 From c7163791106a01c4dce747096a6c99c3f6ed0cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 28 Feb 2017 23:09:10 +0100 Subject: Add a test for the ad-hoc command disconnect-from-irc-server --- tests/end_to_end/__main__.py | 97 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 13 deletions(-) diff --git a/tests/end_to_end/__main__.py b/tests/end_to_end/__main__.py index b84c9b1..f176d8b 100644 --- a/tests/end_to_end/__main__.py +++ b/tests/end_to_end/__main__.py @@ -371,7 +371,9 @@ identd_port=1113 common_replacements = { 'irc_server_one': 'irc.localhost@biboumi.localhost', + 'irc_server_two': 'localhost@biboumi.localhost', 'irc_host_one': 'irc.localhost', + 'irc_host_two': 'localhost', 'biboumi_host': 'biboumi.localhost', 'resource_one': 'resource1', 'resource_two': 'resource2', @@ -393,8 +395,8 @@ def handshake_sequence(): def connection_begin_sequence(irc_host, jid): jid = jid.format_map(common_replacements) - xpath = "/message[@to='" + jid + "'][@from='irc.localhost@biboumi.localhost']/body[text()='%s']" - xpath_re = "/message[@to='" + jid + "'][@from='irc.localhost@biboumi.localhost']/body[re:test(text(), '%s')]" + xpath = "/message[@to='" + jid + "'][@from='" + irc_host + "@biboumi.localhost']/body[text()='%s']" + xpath_re = "/message[@to='" + jid + "'][@from='" + irc_host + "@biboumi.localhost']/body[re:test(text(), '%s')]" return ( partial(expect_stanza, xpath % ('Connecting to %s:6697 (encrypted)' % irc_host)), @@ -410,21 +412,22 @@ def connection_begin_sequence(irc_host, jid): xpath % 'Connected to IRC server.'), # These five messages can be receive in any order partial(expect_stanza, - xpath_re % (r'^%s: (\*\*\* Checking Ident|\*\*\* Looking up your hostname\.\.\.|\*\*\* Found your hostname: .*|ACK multi-prefix|\*\*\* Got Ident response)$' % irc_host)), + xpath_re % (r'^%s: (\*\*\* Checking Ident|\*\*\* Looking up your hostname\.\.\.|\*\*\* Found your hostname: .*|ACK multi-prefix|\*\*\* Got Ident response)$' % 'irc.localhost')), partial(expect_stanza, - xpath_re % (r'^%s: (\*\*\* Checking Ident|\*\*\* Looking up your hostname\.\.\.|\*\*\* Found your hostname: .*|ACK multi-prefix|\*\*\* Got Ident response)$' % irc_host)), + xpath_re % (r'^%s: (\*\*\* Checking Ident|\*\*\* Looking up your hostname\.\.\.|\*\*\* Found your hostname: .*|ACK multi-prefix|\*\*\* Got Ident response)$' % 'irc.localhost')), partial(expect_stanza, - xpath_re % (r'^%s: (\*\*\* Checking Ident|\*\*\* Looking up your hostname\.\.\.|\*\*\* Found your hostname: .*|ACK multi-prefix|\*\*\* Got Ident response)$' % irc_host)), + xpath_re % (r'^%s: (\*\*\* Checking Ident|\*\*\* Looking up your hostname\.\.\.|\*\*\* Found your hostname: .*|ACK multi-prefix|\*\*\* Got Ident response)$' % 'irc.localhost')), partial(expect_stanza, - xpath_re % (r'^%s: (\*\*\* Checking Ident|\*\*\* Looking up your hostname\.\.\.|\*\*\* Found your hostname: .*|ACK multi-prefix|\*\*\* Got Ident response)$' % irc_host)), + xpath_re % (r'^%s: (\*\*\* Checking Ident|\*\*\* Looking up your hostname\.\.\.|\*\*\* Found your hostname: .*|ACK multi-prefix|\*\*\* Got Ident response)$' % 'irc.localhost')), partial(expect_stanza, - xpath_re % (r'^%s: (\*\*\* Checking Ident|\*\*\* Looking up your hostname\.\.\.|\*\*\* Found your hostname: .*|ACK multi-prefix|\*\*\* Got Ident response)$' % irc_host)), + xpath_re % (r'^%s: (\*\*\* Checking Ident|\*\*\* Looking up your hostname\.\.\.|\*\*\* Found your hostname: .*|ACK multi-prefix|\*\*\* Got Ident response)$' % 'irc.localhost')), ) def connection_tls_begin_sequence(irc_host, jid): jid = jid.format_map(common_replacements) - xpath = "/message[@to='" + jid + "'][@from='irc.localhost@biboumi.localhost']/body[text()='%s']" - xpath_re = "/message[@to='" + jid + "'][@from='irc.localhost@biboumi.localhost']/body[re:test(text(), '%s')]" + xpath = "/message[@to='" + jid + "'][@from='" + irc_host + "@biboumi.localhost']/body[text()='%s']" + xpath_re = "/message[@to='" + jid + "'][@from='" + irc_host + "@biboumi.localhost']/body[re:test(text(), '%s')]" + irc_host = 'irc.localhost' return ( partial(expect_stanza, xpath % ('Connecting to %s:7778 (encrypted)' % irc_host)), @@ -445,8 +448,9 @@ def connection_tls_begin_sequence(irc_host, jid): def connection_end_sequence(irc_host, jid): jid = jid.format_map(common_replacements) - xpath = "/message[@to='" + jid + "'][@from='irc.localhost@biboumi.localhost']/body[text()='%s']" - xpath_re = "/message[@to='" + jid + "'][@from='irc.localhost@biboumi.localhost']/body[re:test(text(), '%s')]" + xpath = "/message[@to='" + jid + "'][@from='" + irc_host + "@biboumi.localhost']/body[text()='%s']" + xpath_re = "/message[@to='" + jid + "'][@from='" + irc_host + "@biboumi.localhost']/body[re:test(text(), '%s')]" + irc_host = 'irc.localhost' return ( partial(expect_stanza, xpath_re % (r'^%s: Your host is .*$' % irc_host)), @@ -744,8 +748,6 @@ if __name__ == '__main__': partial(expect_stanza, ("/iq[@type='result']/disco_items:query[@node='http://jabber.org/protocol/commands']", "/iq/disco_items:query/disco_items:item[5]")), ], conf='fixed_server'), - - Scenario("list_adhoc_irc", [ handshake_sequence(), @@ -812,6 +814,75 @@ if __name__ == '__main__': # Note, charybdis ignores our QUIT message, so we can't test it partial(expect_stanza, "/presence[@type='unavailable'][@to='{jid_admin}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_one}']"), ]), + Scenario("execute_admin_disconnect_from_server_adhoc_command", + [ + handshake_sequence(), + + # Admin connects to first server + partial(send_stanza, ""), + connection_sequence("irc.localhost", '{jid_admin}/{resource_one}'), + partial(expect_stanza, "/message/body[text()='Mode #bar [+nt] by {irc_host_one}']"), + partial(expect_stanza, "/presence"), + partial(expect_stanza, "/message"), + + # Non-Admin connects to first server + partial(send_stanza, ""), + connection_sequence("irc.localhost", '{jid_one}/{resource_one}'), + partial(expect_stanza, "/message/body[text()='Mode #foo [+nt] by {irc_host_one}']"), + partial(expect_stanza, "/presence"), + partial(expect_stanza, "/message"), + + # Non-admin connects to second server + partial(send_stanza, ""), + connection_sequence("localhost", '{jid_one}/{resource_one}'), + partial(expect_stanza, "/message/body[text()='Mode #bon [+nt] by {irc_host_one}']"), + partial(expect_stanza, "/presence"), + partial(expect_stanza, "/message"), + + # Execute as admin + partial(send_stanza, ""), + partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='disconnect-from-irc-server'][@sessionid][@status='executing']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='jid'][@type='list-single']/dataform:option[@label='{jid_one}']/dataform:value[text()='{jid_one}']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='jid'][@type='list-single']/dataform:option[@label='{jid_admin}']/dataform:value[text()='{jid_admin}']", + "/iq/commands:command/commands:actions/commands:next", + ), + after = partial(save_value, "sessionid", partial(extract_attribute, "/iq/commands:command[@node='disconnect-from-irc-server']", "sessionid")) + ), + partial(send_stanza, "{jid_one}e2e test one"), + + partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='disconnect-from-irc-server'][@sessionid][@status='executing']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='quit-message'][@type='text-single']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='irc-servers'][@type='list-multi']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='irc-servers']/dataform:option[@label='localhost']/dataform:value[text()='localhost']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='irc-servers']/dataform:option[@label='irc.localhost']/dataform:value[text()='irc.localhost']", + "/iq/commands:command/commands:actions/commands:next", + ), + after = partial(save_value, "sessionid", partial(extract_attribute, "/iq/commands:command[@node='disconnect-from-irc-server']", "sessionid")) + ), + partial(send_stanza, "localhostDisconnected by e2e"), + partial(expect_unordered, [("/presence[@type='unavailable'][@to='{jid_one}/{resource_one}'][@from='#bon%{irc_server_two}/{nick_three}']",), + ("/iq[@type='result']/commands:command[@node='disconnect-from-irc-server'][@status='completed']/commands:note[@type='info'][text()='{jid_one} was disconnected from 1 IRC server.']",), + ("/message[@to='{jid_one}/{resource_one}']/body[text()='ERROR: Disconnected by e2e']",), + ]), + + + # Execute as non-admin (this skips the first step) + partial(send_stanza, ""), + + partial(expect_stanza, ("/iq[@type='result']/commands:command[@node='disconnect-from-irc-server'][@sessionid][@status='executing']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='quit-message'][@type='text-single']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='irc-servers'][@type='list-multi']", + "/iq/commands:command/dataform:x[@type='form']/dataform:field[@var='irc-servers']/dataform:option[@label='irc.localhost']/dataform:value[text()='irc.localhost']", + "/iq/commands:command/commands:actions/commands:next", + ), + after = partial(save_value, "sessionid", partial(extract_attribute, "/iq/commands:command[@node='disconnect-from-irc-server']", "sessionid")) + ), + partial(send_stanza, "irc.localhostDisconnected by e2e"), + partial(expect_unordered, [("/presence[@type='unavailable'][@to='{jid_one}/{resource_one}'][@from='#foo%{irc_server_one}/{nick_two}']",), + ("/iq[@type='result']/commands:command[@node='disconnect-from-irc-server'][@status='completed']/commands:note[@type='info'][text()='{jid_one}/{resource_one} was disconnected from 1 IRC server.']",), + ("/message[@to='{jid_one}/{resource_one}']/body[text()='ERROR: Disconnected by e2e']",), + ]), + ]), Scenario("multisessionnick", [ handshake_sequence(), -- cgit v1.2.3 From 73915e889db80ae2950d9845e4158514f1e95dd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 28 Feb 2017 23:48:38 +0100 Subject: Remove the sonar-qube build [ci skip] --- .gitlab-ci.yml | 14 -------------- README.rst | 3 --- 2 files changed, 17 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 70c1fe8..a243be2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -127,20 +127,6 @@ test:coverity: - tar czvf biboumi_coverity.tgz cov-int - curl --form token=$COVERITY_TOKEN --form email=louiz@louiz.org --form file=@biboumi_coverity.tgz --form version="$(git rev-parse --short HEAD)" --form description="Automatic submission by gitlab-ci" https://scan.coverity.com/builds?project=louiz%2Fbiboumi -test:sonar-qube: - stage: test - only: - - master@louiz/biboumi - tags: - - docker - image: docker.louiz.org/biboumi-test-fedora:latest - allow_failure: true - script: - - cmake .. - - ~/sonar-scanner/bin/build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir ./bw-outputs make biboumi test_suite - - cd .. - - ~/sonar-scanner/bin/sonar-scanner -Dsonar.host.url=https://sonarqube.com -Dsonar.login=$SONAR_LOGIN -Dsonar.language=cpp -Dsonar.cfamily.build-wrapper-output=build/bw-outputs -Dsonar.sourceEncoding=UTF-8 -Dsonar.sources=src/,louloulibs/,tests/ -Dsonar.projectKey=biboumi -Dsonar.projectName=Biboumi -Dsonar.projectVersion=3.0 - packaging:rpm: stage: packaging only: diff --git a/README.rst b/README.rst index 636c717..02cfa3d 100644 --- a/README.rst +++ b/README.rst @@ -7,9 +7,6 @@ Biboumi .. image:: https://codecov.io/gh/louiz/biboumi/branch/master/graph/badge.svg :target: https://codecov.io/gh/louiz/biboumi -.. image:: https://sonarqube.com/api/badges/gate?key=biboumi - :target: https://sonarqube.com/component_issues/index?id=biboumi - .. image:: https://scan.coverity.com/projects/3726/badge.svg :target: https://scan.coverity.com/projects/louiz-biboumi -- cgit v1.2.3 From fa3d44e7aaf43487f8fed62c9398ade6fa797acb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 28 Feb 2017 23:34:11 +0100 Subject: Use AI_NUMERICHOST when using getaddrinfo to bind() our client sockets --- louloulibs/network/tcp_client_socket_handler.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/louloulibs/network/tcp_client_socket_handler.cpp b/louloulibs/network/tcp_client_socket_handler.cpp index 4e6445c..530c3d9 100644 --- a/louloulibs/network/tcp_client_socket_handler.cpp +++ b/louloulibs/network/tcp_client_socket_handler.cpp @@ -35,7 +35,11 @@ void TCPClientSocketHandler::init_socket(const struct addrinfo* rp) // Convert the address from string format to a sockaddr that can be // used in bind() struct addrinfo* result; - int err = ::getaddrinfo(this->bind_addr.data(), nullptr, nullptr, &result); + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_NUMERICHOST; + hints.ai_family = AF_UNSPEC; + int err = ::getaddrinfo(this->bind_addr.data(), nullptr, &hints, &result); if (err != 0 || !result) log_error("Failed to bind socket to ", this->bind_addr, ": ", gai_strerror(err)); -- cgit v1.2.3 From 58b3345f85e4fff5b133ecfb63456cba9b09604c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 28 Feb 2017 23:35:23 +0100 Subject: e2e: Add an outgoing_bind= conf option --- tests/end_to_end/__main__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/end_to_end/__main__.py b/tests/end_to_end/__main__.py index f176d8b..f93025e 100644 --- a/tests/end_to_end/__main__.py +++ b/tests/end_to_end/__main__.py @@ -357,7 +357,8 @@ password=coucou db_name=e2e_test.sqlite port=8811 admin=admin@example.com -identd_port=1113""", +identd_port=1113 +outgoing_bind=127.0.0.1""", 'fixed_server': """hostname=biboumi.localhost -- cgit v1.2.3 From 90b3c07b6c43215076f2f1eacbfb1335aa714366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 28 Feb 2017 23:46:55 +0100 Subject: Revert "Split the biboumi dockerfile into two, to be able to disable the cache" This reverts commit 26eb28dc2368d14e171201a0c6b76b76b19e1ddc. --- .gitlab-ci.yml | 2 +- docker/biboumi/Dockerfile | 30 +++++++++++++++++++++++++----- docker/biboumi/Dockerfile.base | 23 ----------------------- docker/biboumi/README.rst | 20 -------------------- docker/biboumi/build-docker.sh | 14 -------------- 5 files changed, 26 insertions(+), 63 deletions(-) delete mode 100644 docker/biboumi/Dockerfile.base delete mode 100755 docker/biboumi/build-docker.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a243be2..9427fce 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -176,5 +176,5 @@ packaging:docker: before_script: [] script: - docker login -p $DOCKER_PASSWORD -u louiz - - ./docker/biboumi/build-docker.sh louiz/biboumi + - docker build -t louiz/biboumi docker/biboumi - docker push louiz/biboumi diff --git a/docker/biboumi/Dockerfile b/docker/biboumi/Dockerfile index 7e73c9a..721d106 100644 --- a/docker/biboumi/Dockerfile +++ b/docker/biboumi/Dockerfile @@ -1,8 +1,28 @@ -# This dockerfile uses the image built using Dockerfile.base, and installs -# biboumi in it - -FROM biboumi-base - +# This Dockerfile creates a docker image running biboumi + +FROM docker.io/fedora:latest + +RUN dnf --refresh install -y\ + gcc-c++\ + cmake\ + make\ + udns-devel\ + sqlite-devel\ + libuuid-devel\ + expat-devel\ + libidn-devel\ + systemd-devel\ + git\ + python\ + && dnf clean all + +# Install botan +RUN git clone https://github.com/randombit/botan.git && cd botan && ./configure.py --prefix=/usr && make -j8 && make install && ldconfig && rm -rf /botan + +# Install litesql +RUN git clone git://git.louiz.org/litesql && mkdir /litesql/build && cd /litesql/build && cmake .. -DCMAKE_INSTALL_PREFIX=/usr && make -j8 && cd /litesql/build && make install && ldconfig && rm -rf /litesql + +# Install biboumi RUN git clone git://git.louiz.org/biboumi && mkdir ./biboumi/build && cd ./biboumi/build &&\ cmake .. -DCMAKE_INSTALL_PREFIX=/usr\ -DCMAKE_BUILD_TYPE=Release\ diff --git a/docker/biboumi/Dockerfile.base b/docker/biboumi/Dockerfile.base deleted file mode 100644 index bbc32c2..0000000 --- a/docker/biboumi/Dockerfile.base +++ /dev/null @@ -1,23 +0,0 @@ -# This dockerfile install all the dependencies needing to compile biboumi - -FROM docker.io/fedora:latest - -RUN dnf --refresh install -y\ - gcc-c++\ - cmake\ - make\ - udns-devel\ - sqlite-devel\ - libuuid-devel\ - expat-devel\ - libidn-devel\ - systemd-devel\ - git\ - python\ - && dnf clean all - -# Install botan -RUN git clone https://github.com/randombit/botan.git && cd botan && ./configure.py --prefix=/usr && make -j8 && make install && ldconfig && rm -rf /botan - -# Install litesql -RUN git clone git://git.louiz.org/litesql && mkdir /litesql/build && cd /litesql/build && cmake .. -DCMAKE_INSTALL_PREFIX=/usr && make -j8 && cd /litesql/build && make install && ldconfig && rm -rf /litesql diff --git a/docker/biboumi/README.rst b/docker/biboumi/README.rst index d2e2a7e..f6d529d 100644 --- a/docker/biboumi/README.rst +++ b/docker/biboumi/README.rst @@ -76,23 +76,3 @@ The database is stored in the /var/lib/biboumi/ directory. If you don’t bind a local directory to it, the database will be lost when the container is stopped. If you want to keep your database between each run, bind it with the -v option, like this: **-v /srv/biboumi/:/var/lib/biboumi**. - -Building --------- - -This image is built from 2 Dockerfiles: -- Dockerfile.base: builds and installs all the dependencies needed to build and run biboumi -- Dockerfile: builds and installs biboumi itself - -The goal is to be able to force the rebuild of biboumi itself (by using -the --no-cache option) without having to rebuild and install all its -dependencies. - -The build does not require any file in the build context, everything is -fetched during the build using git or dnf. - -To build a biboumi image named “foo/biboumi”, you can run the script: - -``` -./build-docker.sh foo/biboumi -``` diff --git a/docker/biboumi/build-docker.sh b/docker/biboumi/build-docker.sh deleted file mode 100755 index d206b89..0000000 --- a/docker/biboumi/build-docker.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -if [[ -z "$1" ]]; then - echo "Usage: ./build-docker.sh " - echo "Example: ./build-docker.sh docker.io/coucou/biboumi" - exit 1 -fi - -directory=$(dirname $0) -image_name=$1 - -echo $directory -docker build -t biboumi-base $directory -f $directory/Dockerfile.base -docker build -t $image_name $directory -f $directory/Dockerfile --no-cache -- cgit v1.2.3 From ea0151165a8719e596cbd35165db28fe90a376b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 28 Feb 2017 23:54:02 +0100 Subject: Use markdown for the docker readme --- docker/biboumi/README.md | 77 ++++++++++++++++++++++++++++++++++++++++++++++ docker/biboumi/README.rst | 78 ----------------------------------------------- 2 files changed, 77 insertions(+), 78 deletions(-) create mode 100644 docker/biboumi/README.md delete mode 100644 docker/biboumi/README.rst diff --git a/docker/biboumi/README.md b/docker/biboumi/README.md new file mode 100644 index 0000000..094bb78 --- /dev/null +++ b/docker/biboumi/README.md @@ -0,0 +1,77 @@ +Biboumi Docker Image +==================== + +Running +------- + +This image does not embed any XMPP server. You need to have a running XMPP +server first: as an other docker image, or running on the host machine. + +Assuming you have a running [prosody](https://hub.docker.com/r/prosody/prosody/) +container already running and +[properly configured](https://prosody.im/doc/components#adding_an_external_component) +you can use the following command to start your biboumi container. + +``` +docker run --link prosody:xmpp \ + -v $PWD/database:/var/lib/biboumi \ + -e BIBOUMI_PASSWORD=P4SSW0RD \ + -e BIBOUMI_HOSTNAME=irc.example.com \ + -e BIBOUMI_ADMIN=blabla \ + biboumi +``` + +If instead you already have an XMPP server running on the host machine, you +can start the biboumi container like this: + +``` +docker run --network=host \ + -v $PWD/database:/var/lib/biboumi \ + -e BIBOUMI_PASSWORD=P4SSW0RD \ + -e BIBOUMI_HOSTNAME=irc.example.com \ + -e BIBOUMI_ADMIN=blabla \ + -e BIBOUMI_XMPP_SERVER_IP=127.0.0.1 \ + biboumi +``` + +Variables +--------- + +The configuration file inside the image is a template that is completed when +the container is started, using the following environment variables: + +* BIBOUMI_HOSTNAME: Sets the value of the *hostname* option. +* BIBOUMI_SECRET: Sets the value of the *password* option. +* BIBOUMI_ADMIN: Sets the value of the *admin* option. +* BIBOUMI_XMPP_SERVER_IP: Sets the value of the *xmpp_server_ip* option. The default is **xmpp**. + +All these variables are optional, but biboumi will probably fail to start if +the hostname and secret are missing. + +You can also directly provide your own configuration file by mounting it +inside the container using the -v option: + +``` +docker run --link prosody:xmpp \ + -v $PWD/biboumi.cfg:/etc/biboumi/biboumi.cfg \ + biboumi +``` + +Linking with the XMPP server +---------------------------- + +You can use the --link option to connect to any server running in a docker +container, but it needs to be called *xmpp*, or the custom value set for the +**BIBOUMI_XMPP_SERVER_IP** option. For example, if you are using a container +named ejabberd, you would use the option *--link ejabberd:xmpp*. + +If you want to connect to the XMPP server running on the host machine, use +the **--network=host** option. + +Volumes +------- + +The database is stored in the /var/lib/biboumi/ directory. If you don’t bind +a local directory to it, the database will be lost when the container is +stopped. If you want to keep your database between each run, bind it with +the -v option, like this: **-v /srv/biboumi/:/var/lib/biboumi**. diff --git a/docker/biboumi/README.rst b/docker/biboumi/README.rst deleted file mode 100644 index f6d529d..0000000 --- a/docker/biboumi/README.rst +++ /dev/null @@ -1,78 +0,0 @@ -Biboumi Docker Image -==================== - -Running -------- - -This image does not embed any XMPP server. You need to have a running XMPP -server first: as an other docker image, or running on the host machine. - -Assuming you have a running `prosody -`_ container already running and -`properly configured -`_ you can -use the following command to start your biboumi container. - -``` -docker run --link prosody:xmpp \ - -v $PWD/database:/var/lib/biboumi \ - -e BIBOUMI_PASSWORD=P4SSW0RD \ - -e BIBOUMI_HOSTNAME=irc.example.com \ - -e BIBOUMI_ADMIN=blabla \ - biboumi -``` - -If instead you already have an XMPP server running on the host machine, you -can start the biboumi container like this: - -``` -docker run --network=host \ - -v $PWD/database:/var/lib/biboumi \ - -e BIBOUMI_PASSWORD=P4SSW0RD \ - -e BIBOUMI_HOSTNAME=irc.example.com \ - -e BIBOUMI_ADMIN=blabla \ - -e BIBOUMI_XMPP_SERVER_IP=127.0.0.1 \ - biboumi -``` - -Variables ---------- - -The configuration file inside the image is a template that is completed when -the container is started, using the following environment variables: - -* BIBOUMI_HOSTNAME: Sets the value of the *hostname* option. -* BIBOUMI_SECRET: Sets the value of the *password* option. -* BIBOUMI_ADMIN: Sets the value of the *admin* option. -* BIBOUMI_XMPP_SERVER_IP: Sets the value of the *xmpp_server_ip* option. The default is **xmpp**. - -All these variables are optional, but biboumi will probably fail to start if -the hostname and secret are missing. - -You can also directly provide your own configuration file by mounting it -inside the container using the -v option: - -``` -docker run --link prosody:xmpp \ - -v $PWD/biboumi.cfg:/etc/biboumi/biboumi.cfg \ - biboumi -``` - -Linking with the XMPP server ----------------------------- - -You can use the --link option to connect to any server running in a docker -container, but it needs to be called *xmpp*, or the custom value set for the -**BIBOUMI_XMPP_SERVER_IP** option. For example, if you are using a container -named ejabberd, you would use the option *--link ejabberd:xmpp*. - -If you want to connect to the XMPP server running on the host machine, use -the **--network=host** option. - -Volumes -------- - -The database is stored in the /var/lib/biboumi/ directory. If you don’t bind -a local directory to it, the database will be lost when the container is -stopped. If you want to keep your database between each run, bind it with -the -v option, like this: **-v /srv/biboumi/:/var/lib/biboumi**. -- cgit v1.2.3 From ecdf18dfc6e6761e22f47679c05174d768cfe891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Tue, 28 Feb 2017 23:57:13 +0100 Subject: ci: remove packaging:docker --- .gitlab-ci.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9427fce..c616f89 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -166,15 +166,3 @@ packaging:deb: artifacts: untracked: true name: $CI_PROJECT_NAME-deb-$CI_BUILD_ID - -packaging:docker: - stage: packaging - only: - - master@louiz/biboumi - tags: - - docker-in-docker - before_script: [] - script: - - docker login -p $DOCKER_PASSWORD -u louiz - - docker build -t louiz/biboumi docker/biboumi - - docker push louiz/biboumi -- cgit v1.2.3 From e6e37a6f209ae2e9416b0da03ff21469cb4645b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Wed, 1 Mar 2017 14:14:39 +0100 Subject: =?UTF-8?q?Don=E2=80=99t=20wrap=20the=20lines=20in=20docker/README?= =?UTF-8?q?.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/biboumi/README.md | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/docker/biboumi/README.md b/docker/biboumi/README.md index 094bb78..e69c1b0 100644 --- a/docker/biboumi/README.md +++ b/docker/biboumi/README.md @@ -4,13 +4,9 @@ Biboumi Docker Image Running ------- -This image does not embed any XMPP server. You need to have a running XMPP -server first: as an other docker image, or running on the host machine. +This image does not embed any XMPP server. You need to have a running XMPP server first: as an other docker image, or running on the host machine. -Assuming you have a running [prosody](https://hub.docker.com/r/prosody/prosody/) -container already running and -[properly configured](https://prosody.im/doc/components#adding_an_external_component) -you can use the following command to start your biboumi container. +Assuming you have a running [prosody](https://hub.docker.com/r/prosody/prosody/) container already running and [properly configured](https://prosody.im/doc/components#adding_an_external_component) you can use the following command to start your biboumi container. ``` docker run --link prosody:xmpp \ @@ -21,8 +17,7 @@ docker run --link prosody:xmpp \ biboumi ``` -If instead you already have an XMPP server running on the host machine, you -can start the biboumi container like this: +If instead you already have an XMPP server running on the host machine, you can start the biboumi container like this: ``` docker run --network=host \ @@ -37,19 +32,16 @@ docker run --network=host \ Variables --------- -The configuration file inside the image is a template that is completed when -the container is started, using the following environment variables: +The configuration file inside the image is a template that is completed when the container is started, using the following environment variables: * BIBOUMI_HOSTNAME: Sets the value of the *hostname* option. * BIBOUMI_SECRET: Sets the value of the *password* option. * BIBOUMI_ADMIN: Sets the value of the *admin* option. * BIBOUMI_XMPP_SERVER_IP: Sets the value of the *xmpp_server_ip* option. The default is **xmpp**. -All these variables are optional, but biboumi will probably fail to start if -the hostname and secret are missing. +All these variables are optional, but biboumi will probably fail to start if the hostname and secret are missing. -You can also directly provide your own configuration file by mounting it -inside the container using the -v option: +You can also directly provide your own configuration file by mounting it inside the container using the -v option: ``` docker run --link prosody:xmpp \ @@ -60,18 +52,11 @@ docker run --link prosody:xmpp \ Linking with the XMPP server ---------------------------- -You can use the --link option to connect to any server running in a docker -container, but it needs to be called *xmpp*, or the custom value set for the -**BIBOUMI_XMPP_SERVER_IP** option. For example, if you are using a container -named ejabberd, you would use the option *--link ejabberd:xmpp*. +You can use the --link option to connect to any server running in a docker container, but it needs to be called *xmpp*, or the custom value set for the **BIBOUMI_XMPP_SERVER_IP** option. For example, if you are using a container named ejabberd, you would use the option *--link ejabberd:xmpp*. -If you want to connect to the XMPP server running on the host machine, use -the **--network=host** option. +If you want to connect to the XMPP server running on the host machine, use the **--network=host** option. Volumes ------- -The database is stored in the /var/lib/biboumi/ directory. If you don’t bind -a local directory to it, the database will be lost when the container is -stopped. If you want to keep your database between each run, bind it with -the -v option, like this: **-v /srv/biboumi/:/var/lib/biboumi**. +The database is stored in the /var/lib/biboumi/ directory. If you don’t bind a local directory to it, the database will be lost when the container is stopped. If you want to keep your database between each run, bind it with the -v option, like this: **-v /srv/biboumi/:/var/lib/biboumi**. -- cgit v1.2.3 From d81c3ad5ac2c12130d90044b7597bf962a7cfe9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Sat, 4 Mar 2017 14:00:53 +0100 Subject: Fix the order of from and to address in muc traffic info reply And add a test for it. fix #3238 --- src/xmpp/biboumi_component.cpp | 2 +- src/xmpp/biboumi_component.hpp | 2 +- tests/end_to_end/__main__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/xmpp/biboumi_component.cpp b/src/xmpp/biboumi_component.cpp index 663e92e..2783b93 100644 --- a/src/xmpp/biboumi_component.cpp +++ b/src/xmpp/biboumi_component.cpp @@ -738,7 +738,7 @@ void BiboumiComponent::send_irc_server_disco_info(const std::string& id, const s this->send_stanza(iq); } -void BiboumiComponent::send_irc_channel_muc_traffic_info(const std::string id, const std::string& jid_from, const std::string& jid_to) +void BiboumiComponent::send_irc_channel_muc_traffic_info(const std::string id, const std::string& jid_to, const std::string& jid_from) { Stanza iq("iq"); { diff --git a/src/xmpp/biboumi_component.hpp b/src/xmpp/biboumi_component.hpp index 7cafdec..aa0c3db 100644 --- a/src/xmpp/biboumi_component.hpp +++ b/src/xmpp/biboumi_component.hpp @@ -69,7 +69,7 @@ public: * Sends the allowed namespaces in MUC message, according to * http://xmpp.org/extensions/xep-0045.html#impl-service-traffic */ - void send_irc_channel_muc_traffic_info(const std::string id, const std::string& jid_from, const std::string& jid_to); + void send_irc_channel_muc_traffic_info(const std::string id, const std::string& jid_to, const std::string& jid_from); /** * Send a ping request */ diff --git a/tests/end_to_end/__main__.py b/tests/end_to_end/__main__.py index f93025e..c298793 100644 --- a/tests/end_to_end/__main__.py +++ b/tests/end_to_end/__main__.py @@ -1864,7 +1864,7 @@ if __name__ == '__main__': partial(send_stanza, ""), - partial(expect_stanza, "/iq[@type='result']/disco_info:query[@node='http://jabber.org/protocol/muc#traffic']"), + partial(expect_stanza, "/iq[@from='#foo%{irc_server_one}'][@to='{jid_one}/{resource_one}'][@type='result']/disco_info:query[@node='http://jabber.org/protocol/muc#traffic']"), ]), Scenario("raw_message", [ -- cgit v1.2.3 From 99a4ddedaf903d27b781341108433ae2d9533ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 6 Mar 2017 00:51:43 +0100 Subject: Remove the embedded sha1 code, and use one of botan or gcrypt This adds a hard dependency on one of Botan or gcrypt. Botan is already a recommended dependency, and gcrypt is probably packaged almost everywhere, so this should not be a big deal. ref #3241 --- INSTALL.rst | 4 + louloulibs/CMakeLists.txt | 11 +++ louloulibs/cmake/Modules/FindGCRYPT.cmake | 35 +++++++ louloulibs/louloulibs.h.cmake | 1 + louloulibs/utils/sha1.cpp | 151 ++++++------------------------ louloulibs/utils/sha1.hpp | 34 +------ louloulibs/xmpp/auth.cpp | 15 +-- src/identd/identd_socket.cpp | 9 +- 8 files changed, 87 insertions(+), 173 deletions(-) create mode 100644 louloulibs/cmake/Modules/FindGCRYPT.cmake diff --git a/INSTALL.rst b/INSTALL.rst index fa88ffb..9815af9 100644 --- a/INSTALL.rst +++ b/INSTALL.rst @@ -45,6 +45,9 @@ libbotan_ 1.11 or 2.0 (optional) Provides TLS support. Without it, IRC connections are all made in plain-text mode. +gcrypt_ (mandatory only if botan is absent) + Provides the SHA-1 hash function, for the case where Botan is absent. + litesql_ (optional) Provides a way to store various options in a (sqlite3) database. Each user of the gateway can store their own values (for example their prefered port, @@ -158,3 +161,4 @@ to use biboumi. .. _litesql: http://git.louiz.org/litesql .. _systemd: https://www.freedesktop.org/wiki/Software/systemd/ .. _biboumi.1.rst: doc/biboumi.1.rst +.. _gcrypt: https://www.gnu.org/software/libgcrypt/ diff --git a/louloulibs/CMakeLists.txt b/louloulibs/CMakeLists.txt index f672833..2268571 100644 --- a/louloulibs/CMakeLists.txt +++ b/louloulibs/CMakeLists.txt @@ -33,6 +33,10 @@ elseif(NOT WITHOUT_BOTAN) find_package(BOTAN) endif() +if(NOT BOTAN_FOUND) + find_package(GCRYPT REQUIRED) +endif() + if(WITH_UDNS) find_package(UDNS REQUIRED) elseif(NOT WITHOUT_UDNS) @@ -67,6 +71,11 @@ if(BOTAN_FOUND) set(BOTAN_FOUND ${BOTAN_FOUND} PARENT_SCOPE) set(BOTAN_INCLUDE_DIRS ${BOTAN_INCLUDE_DIRS} PARENT_SCOPE) endif() +if(GCRYPT_FOUND) + include_directories(SYSTEM ${GCRYPT_INCLUDE_DIRS}) + set(GCRYPT_FOUND ${GCRYPT_FOUND} PARENT_SCOPE) + set(GCRYPT_INCLUDE_DIRS ${GCRYPT_INCLUDE_DIRS} PARENT_SCOPE) +endif() if(UDNS_FOUND) include_directories(${UDNS_INCLUDE_DIRS}) @@ -117,6 +126,8 @@ add_library(network STATIC ${source_network}) target_link_libraries(network logger) if(BOTAN_FOUND) target_link_libraries(network ${BOTAN_LIBRARIES}) +elseif(GCRYPT_FOUND) + target_link_libraries(network ${GCRYPT_LIBRARIES}) endif() if(UDNS_FOUND) target_link_libraries(network ${UDNS_LIBRARIES}) diff --git a/louloulibs/cmake/Modules/FindGCRYPT.cmake b/louloulibs/cmake/Modules/FindGCRYPT.cmake new file mode 100644 index 0000000..bb1bc67 --- /dev/null +++ b/louloulibs/cmake/Modules/FindGCRYPT.cmake @@ -0,0 +1,35 @@ +# - Find gcrypt +# Find the gcrypt cryptographic library +# +# This module defines the following variables: +# GCRYPT_FOUND - True if library and include directory are found +# If set to TRUE, the following are also defined: +# GCRYPT_INCLUDE_DIRS - The directory where to find the header file +# GCRYPT_LIBRARIES - Where to find the library file +# +# For conveniance, these variables are also set. They have the same values +# than the variables above. The user can thus choose his/her prefered way +# to write them. +# GCRYPT_LIBRARY +# GCRYPT_INCLUDE_DIR +# +# This file is in the public domain + +find_path(GCRYPT_INCLUDE_DIRS NAMES gcrypt.h + PATH_SUFFIXES gcrypt + DOC "The gcrypt include directory") + +find_library(GCRYPT_LIBRARIES NAMES gcrypt + DOC "The gcrypt library") + +# Use some standard module to handle the QUIETLY and REQUIRED arguments, and +# set GCRYPT_FOUND to TRUE if these two variables are set. +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GCRYPT REQUIRED_VARS GCRYPT_LIBRARIES GCRYPT_INCLUDE_DIRS) + +if(GCRYPT_FOUND) + set(GCRYPT_LIBRARY ${GCRYPT_LIBRARIES}) + set(GCRYPT_INCLUDE_DIR ${GCRYPT_INCLUDE_DIRS}) +endif() + +mark_as_advanced(GCRYPT_INCLUDE_DIRS GCRYPT_LIBRARIES) diff --git a/louloulibs/louloulibs.h.cmake b/louloulibs/louloulibs.h.cmake index e2b2e25..5777d92 100644 --- a/louloulibs/louloulibs.h.cmake +++ b/louloulibs/louloulibs.h.cmake @@ -3,6 +3,7 @@ #cmakedefine SYSTEMD_FOUND #cmakedefine POLLER ${POLLER} #cmakedefine BOTAN_FOUND +#cmakedefine GCRYPT_FOUND #cmakedefine UDNS_FOUND #cmakedefine SOFTWARE_VERSION "${SOFTWARE_VERSION}" #cmakedefine PROJECT_NAME "${PROJECT_NAME}" diff --git a/louloulibs/utils/sha1.cpp b/louloulibs/utils/sha1.cpp index f75bc2a..71ad18d 100644 --- a/louloulibs/utils/sha1.cpp +++ b/louloulibs/utils/sha1.cpp @@ -1,121 +1,32 @@ -/* This code is public-domain - it is based on libcrypt - * placed in the public domain by Wei Dai and other contributors. - */ - -#include "sha1.hpp" - -#define SHA1_K0 0x5a827999 -#define SHA1_K20 0x6ed9eba1 -#define SHA1_K40 0x8f1bbcdc -#define SHA1_K60 0xca62c1d6 - -const uint8_t sha1InitState[] = { - 0x01,0x23,0x45,0x67, // H0 - 0x89,0xab,0xcd,0xef, // H1 - 0xfe,0xdc,0xba,0x98, // H2 - 0x76,0x54,0x32,0x10, // H3 - 0xf0,0xe1,0xd2,0xc3 // H4 -}; - -void sha1_init(sha1nfo *s) { - memcpy(s->state.b,sha1InitState,HASH_LENGTH); - s->byteCount = 0; - s->bufferOffset = 0; -} - -uint32_t sha1_rol32(uint32_t number, uint8_t bits) { - return ((number << bits) | (number >> (32-bits))); -} - -void sha1_hashBlock(sha1nfo *s) { - uint8_t i; - uint32_t a,b,c,d,e,t; - - a=s->state.w[0]; - b=s->state.w[1]; - c=s->state.w[2]; - d=s->state.w[3]; - e=s->state.w[4]; - for (i=0; i<80; i++) { - if (i>=16) { - t = s->buffer.w[(i+13)&15] ^ s->buffer.w[(i+8)&15] ^ s->buffer.w[(i+2)&15] ^ s->buffer.w[i&15]; - s->buffer.w[i&15] = sha1_rol32(t,1); - } - if (i<20) { - t = (d ^ (b & (c ^ d))) + SHA1_K0; - } else if (i<40) { - t = (b ^ c ^ d) + SHA1_K20; - } else if (i<60) { - t = ((b & c) | (d & (b | c))) + SHA1_K40; - } else { - t = (b ^ c ^ d) + SHA1_K60; - } - t+=sha1_rol32(a,5) + e + s->buffer.w[i&15]; - e=d; - d=c; - c=sha1_rol32(b,30); - b=a; - a=t; - } - s->state.w[0] += a; - s->state.w[1] += b; - s->state.w[2] += c; - s->state.w[3] += d; - s->state.w[4] += e; -} - -void sha1_addUncounted(sha1nfo *s, uint8_t data) { - s->buffer.b[s->bufferOffset ^ 3] = data; - s->bufferOffset++; - if (s->bufferOffset == BLOCK_LENGTH) { - sha1_hashBlock(s); - s->bufferOffset = 0; - } -} - -void sha1_writebyte(sha1nfo *s, uint8_t data) { - ++s->byteCount; - sha1_addUncounted(s, data); -} - -void sha1_write(sha1nfo *s, const char *data, size_t len) { - for (;len--;) sha1_writebyte(s, (uint8_t) *data++); -} - -void sha1_pad(sha1nfo *s) { - // Implement SHA-1 padding (fips180-2 §5.1.1) - - // Pad with 0x80 followed by 0x00 until the end of the block - sha1_addUncounted(s, 0x80); - while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); - - // Append length in the last 8 bytes - sha1_addUncounted(s, 0); // We're only using 32 bit lengths - sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths - sha1_addUncounted(s, 0); // So zero pad the top bits - sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 - sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as - sha1_addUncounted(s, s->byteCount >> 13); // byte. - sha1_addUncounted(s, s->byteCount >> 5); - sha1_addUncounted(s, s->byteCount << 3); -} - -uint8_t* sha1_result(sha1nfo *s) { - int i; - // Pad to complete the last block - sha1_pad(s); - - // Swap byte order back - for (i=0; i<5; i++) { - uint32_t a,b; - a=s->state.w[i]; - b=a<<24; - b|=(a<<8) & 0x00ff0000; - b|=(a>>8) & 0x0000ff00; - b|=a>>24; - s->state.w[i]=b; - } - - // Return pointer to hash (20 characters) - return s->state.b; +#include + +#include + +#ifdef BOTAN_FOUND +# include +# include +#endif +#ifdef GCRYPT_FOUND +# include +# include +# include +# include +#endif + +std::string sha1(const std::string& input) +{ +#ifdef BOTAN_FOUND + auto sha1 = Botan::HashFunction::create_or_throw("SHA-1"); + sha1->update(input); + return Botan::hex_encode(sha1->final(), false); +#endif +#ifdef GCRYPT_FOUND + const auto hash_length = gcry_md_get_algo_dlen(GCRY_MD_SHA1); + std::vector output(hash_length, {}); + gcry_md_hash_buffer(GCRY_MD_SHA1, output.data(), input.data(), input.size()); + std::ostringstream digest; + for (std::size_t i = 0; i < hash_length; i++) + digest << std::hex << std::setfill('0') << std::setw(2) << static_cast(output[i]); + return digest.str(); +#endif } diff --git a/louloulibs/utils/sha1.hpp b/louloulibs/utils/sha1.hpp index d436782..6c551ac 100644 --- a/louloulibs/utils/sha1.hpp +++ b/louloulibs/utils/sha1.hpp @@ -1,33 +1,5 @@ -/* This code is public-domain - it is based on libcrypt - * placed in the public domain by Wei Dai and other contributors. - */ +#pragma once -#include -#include +#include -#define HASH_LENGTH 20 -#define BLOCK_LENGTH 64 - -union _buffer { - uint8_t b[BLOCK_LENGTH]; - uint32_t w[BLOCK_LENGTH/4]; -}; - -union _state { - uint8_t b[HASH_LENGTH]; - uint32_t w[HASH_LENGTH/4]; -}; - -typedef struct sha1nfo { - union _buffer buffer; - uint8_t bufferOffset; - union _state state; - uint32_t byteCount; - uint8_t keyBuffer[BLOCK_LENGTH]; - uint8_t innerHash[HASH_LENGTH]; -} sha1nfo; - -void sha1_init(sha1nfo *s); -void sha1_writebyte(sha1nfo *s, uint8_t data); -void sha1_write(sha1nfo *s, const char *data, size_t len); -uint8_t* sha1_result(sha1nfo *s); +std::string sha1(const std::string& input); diff --git a/louloulibs/xmpp/auth.cpp b/louloulibs/xmpp/auth.cpp index c20f95d..8a34a4e 100644 --- a/louloulibs/xmpp/auth.cpp +++ b/louloulibs/xmpp/auth.cpp @@ -2,20 +2,7 @@ #include -#include -#include - std::string get_handshake_digest(const std::string& stream_id, const std::string& secret) { - sha1nfo sha1; - sha1_init(&sha1); - sha1_write(&sha1, stream_id.data(), stream_id.size()); - sha1_write(&sha1, secret.data(), secret.size()); - const uint8_t* result = sha1_result(&sha1); - - std::ostringstream digest; - for (int i = 0; i < HASH_LENGTH; i++) - digest << std::hex << std::setfill('0') << std::setw(2) << static_cast(result[i]); - - return digest.str(); + return sha1(stream_id + secret); } diff --git a/src/identd/identd_socket.cpp b/src/identd/identd_socket.cpp index 46553ca..a94f172 100644 --- a/src/identd/identd_socket.cpp +++ b/src/identd/identd_socket.cpp @@ -38,14 +38,7 @@ void IdentdSocket::parse_in_buffer(const std::size_t) static std::string hash_jid(const std::string& jid) { - sha1nfo sha1; - sha1_init(&sha1); - sha1_write(&sha1, jid.data(), jid.size()); - const uint8_t* res = sha1_result(&sha1); - std::ostringstream result; - for (int i = 0; i < HASH_LENGTH; i++) - result << std::hex << std::setfill('0') << std::setw(2) << static_cast(res[i]); - return result.str(); + return sha1(jid); } std::string IdentdSocket::generate_answer(const BiboumiComponent& biboumi, uint16_t local, uint16_t remote) -- cgit v1.2.3 From 11c63ebceb07d9b65ed16182139477ea79739c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?louiz=E2=80=99?= Date: Mon, 6 Mar 2017 01:22:51 +0100 Subject: Add the gcrypt dependency to the biboumi-test docker images --- docker/biboumi-test/debian/Dockerfile.base | 1 + docker/biboumi-test/fedora/Dockerfile.base | 1 + 2 files changed, 2 insertions(+) diff --git a/docker/biboumi-test/debian/Dockerfile.base b/docker/biboumi-test/debian/Dockerfile.base index 125c048..e609feb 100644 --- a/docker/biboumi-test/debian/Dockerfile.base +++ b/docker/biboumi-test/debian/Dockerfile.base @@ -14,6 +14,7 @@ RUN apt install -y g++\ libudns-dev\ libsqlite3-dev\ libuuid1\ + libgcrypt20-dev\ cmake\ make\ libexpat1-dev\ diff --git a/docker/biboumi-test/fedora/Dockerfile.base b/docker/biboumi-test/fedora/Dockerfile.base index 0fd3095..dd536e5 100644 --- a/docker/biboumi-test/fedora/Dockerfile.base +++ b/docker/biboumi-test/fedora/Dockerfile.base @@ -12,6 +12,7 @@ RUN dnf --refresh install -y\ udns-devel\ sqlite-devel\ libuuid-devel\ + libgcrypt-devel\ cmake\ make\ expat-devel\ -- cgit v1.2.3