The documentation for Tigase promises a very functional server. Let's see if the product meets the hype. The website reports 105k downloads since 2008-08-02, though it's impossible to tell how many sites are actively using it today.
From the Tigase website I downloaded the software. The latest non-beta version (as of 2013-07-27) is 5.1.5 and 5.2.0-beta1 is also available. I downloaded the former. It's not clear whether you should download the exe, jar, tar.gz or zip file; I suspect but do not know that all have the same content. I downloaded tar.gz (13Mb). (Update: better to download the jar file, 12Mb.) It will unpack into ./tigase-server-5.1.5-b3164/ mode 644/755 root:root. A LSB style startup script is provided (for Red Hat). I'm putting it in /usr/local/share, since it is not architecture dependent, plus a symlink of tigase-server to the versioned dirname. 38Mb uncompressed.
Update: I'm trying Tigase again in 2014-06-14, and the current version is 5.2.1 dated 2014-04-07, 18MiB. I downloaded the dist-max.tar.gz variant; they no longer just give you a jar file. This time, I'm un-tarring into /m1 with a symlink from /usr/local/Tigase to the versioned directory. Oops, ./jars/java-server.jar is not the installer (maybe the server itself?) This isn't going to work.
So I'm backing up to 5.2.0 which does have a jar file https://projects.tigase.org/attachments/download/1342/tigase-server-5.2.0-b3447.jar dated 2014-02-13 (25.6Mb).
The next step is to run the GUI installer (or a command line installer
is also available). Make sure that the java
interpreter is available,
then run this command line: java -jar tigase-server-${VERSION}.jar. I'm going
to back out of the tar.gz installation and do it their way.
Here are notes on the installation process. Some uninteresting screens are not described.
Verify that you have both the Java Runtime Environment (JRE) and Java Development Toolkit (JDK) installed, at least version 1.6 (we have 1.7 from SuSE). The JDK path is usually autodetected; if it isn't, you may not have it installed. For OpenSuSE the package java-1_7_0-openjdk contains just the JRE (despite the name); the JDK is in java-1_7_0-openjdk-devel.
For a new installation it's recommended to both install and configure the server.
The default installation path for UNIX is /usr/local/Tigase-${VERSION}. I accepted this default. Later I moved it to a directory that fits my backup scheme better and made a symlink to it as /usr/local/Tigase.
What sub-packages do you want? By default, all but source code is turned on. I suppressed drivers for MySQL, PostgreSQL and Microsoft SQL Server, leaving Derby Database. Docs were kept (16.9Mb, oink). I hope I have the tools to read them. Eventual total size: 44Mb. In 5.2.0, total size is 33Mb.
Are we going to set up shortcuts? This probably means .desktop files in the desktop environment's list of applications. This is useless since root never runs a desktop environment. Suppressed.
The existing
server configuration defines --admins =
admin@jacinth, --virt-hosts = jacinth. I'm changing these as follows:
Advanced options (showing only the ones that were changed):
PubSub is like multicast for XMPP. Various publishers send messages to named channels, and subscribers designate channels whose messages they want to receive. By being creative about the channel namespace, the app developer can make this surprisingly flexible. Examples given were an RSS-like service where the names are search terms with source restrictions, and a social geolocation service where names represent people and places. This looks interesting but is not useful for my operation.
Plugins: by default everything is turned on except compression (experimental in Tigase), and I left it that way. The plugin list makes interesting reading:
resourceappended to the user's loginID)
Where should the Derby database store files? The default is ./tigasedb under the install directory. I changed to /var/lib/tigase. The program will create it for you. The user-db-uri ends up as jdbc:derby:/var/lib/tigase.
If you select Separate Authentication Database
it gives
you a screen for this. I picked Your Custom
as the (second)
database type, but in the next screen it showed --auth-db=Type Your Class
Here. So I went back and tried Tigase Custom
. Maybe it will work.
Final check of server configuration. It still has --admins = admin@jfcarter.net. Later I will give myself admin privileges and change the admin password.
Post install actions happen on the next screen. Give it some time; it probably has to compile all the bytecode before it can do anything. Despite my hacking it claims to have finished all steps.
Installation is finished. They have given you an uninstall script in ${INSTDIR}/Uninstaller. The main configuration file is in ${INSTDIR}/etc/tigase.conf and there are several other conf-type files in this directory. Apparently Tigase always refers to config files by a relative path from ${INSTDIR}, e.g. to start it they say to do (cd ${INSTDIR}; ./scripts/tigase.sh start etc/tigase.conf).
The last screen has a button to generate an automatic installation script. Presumably this is for cloning the configuration. I did not press it.
There is a LSB-type startup script for Red Hat in ${INSTDIR}/scripts/redhat/init.d/tigase . It will not be happy on the OpenSuSE system; I have made my own using this as a base, in /etc/init.d/tigase. It depends on these symbolic links:
Starting up the server for the first time: It starts. It runs for quite a long time but eventually it listens to port 5222. Here are all the ports it is listening to:
Further configuration: Edit ./etc/init.properties, remove ./etc/tigase.xml, stop and restart the server. Finding no tigase.xml it will rebuild it from init.properties. (tigase.xml appears to no longer be generated, don't have to remove it.)
Format of init.properties:
The log files are going into ${INSTDIR}/logs. This should be symlinked to /var/log/tigase and a /etc/logrotate.d file should be installed. Log files have an extension of .log or log.0 making rotation easier. A lock file and the PID file are also here. The default configuration turns on server debugging, which is prolix and should be turned off for production.
Update: Tigase itself rotates the log file when it reaches about 1Mb in size, which happens in less than a day with debug logging turned on. How many old files does it keep? Don't know yet.
Nightmare starting up Tigase -- it will start up and do a lot of service even though it can't open certain files. (What are they for?) Affected files:
Mon Jun 16 17:03:17 PDT 2014 Thread[main,5,main] java.io.FileNotFoundException: derby.log (Permission denied)
2014-06-16 17:03:51.031 [main] ConfigurationCache.store() WARNING: Cannot dump server configuration.
java.io.FileNotFoundException: etc/config-dump.properties (Permission denied)
I made symlinks from the indicated files to /var/log/tigase/(name), taking derby.log to mean it's in /usr/local/Tigase/.
To set up TLS, you need these items:
You need the tigase-extras package and the TLS plugin (we have).
A certificate chain file in PEM format containing the host cert, the private key, and the CA certs up to the root cert. The chain file for Apache wants the key first and the root cert is optional. This means you will need separate chain files for the two servers; but a change is promised so Tigase can work with an Apache chain file. Update: in version 5.2.0 the key may come first, then the host cert, then the intermediate cert(s) and the trust anchor. I did not experiment to find if the trust anchor really can be omitted, though the client will never believe in it. The 5.1.5 order is also acceptable, i.e. the host cert, then the key, and the intermediate cert(s) and trust anchor.
Copy this PEM file to ${INSTDIR}/certs/${HOST}.pem. (Will a symlink be satisfactory? Apparently so.) Stop the server, remove ./etc/tigase.xml, and restart the server. It will rebuild tigase.xml taking the cert(s) into account. (tigase.xml appears to no longer be generated, don't have to remove it.)
I made symlinks in ./certs to the chain files for jfcarter.net, jacinth.jfcarter.net and jacinth.cft.ca.us.
As with Openfire, there is a Java keystore in ./certs whose permissions are 644 and whose password is hardwired in the code and is widely known. Tigase has succesfully used the external (/etc/ssl) certs and has never written anything into this keystore. Good riddance.
I edited ./etc/init.properties making these changes:
Added some comments and re-ordered it more logically.
--virt-hosts = jfcarter.net (established during setup, but it's promised to be able to add (and configure?) vhosts at runtime)
--vhost-anonymous-enabled = false (no anonymous logins/sessions)
--vhost-tls-required = false (this is the default, but when debugging is finished I should turn this on)
--ssl-def-cert-domain = jfcarter.net (for SSL connections; with TLS it will tell the server which host cert it wants to see)
Somewhere it must be possible to configure SASL or LDAP auth.
Starting it up after making these changes. It did start and is listening
on 5222. It did not write on the Java keystore. The only error message was
SessionManager.addPlugin() WARNING: No implementation found for
plugin id: basic-filter
Testing TLS:
This is the test command line:
openssl s_client -connect jacinth.jfcarter.net:5222 -CApath /etc/ssl/certs -starttls xmpp
s_client hangs with high CPU usage. tigase.log.0 shows that it seems to accept the connection and shut it down when I kill s_client, with no error messages. Same behavior with jacinth.cft.ca.us.
Since it's listening to 5223, let's try that minus -starttls. Same behavior except no high CPU usage.
In a forum post someone says that s_client messes up the SSL/TLS negotiation (something to do with single versus double quotes) and fails to connect to some but not all XMPP servers. Evidently including Tigase.
Testing with Pidgin. On 5222 it did starttls, and tigase sent over a self-signed cert for jfcarter.net (which was generated at the time of this connection by Pidgin, confirmed in log). The server then closed the connection, probably because the user is not registered.
More Pidgin with admin@jacinth.jfcarter.net. Now it says host unknown. I think this is the server's error message to the client.
I changed the domain (--virt-hosts) to the hostname, jacinth.jfcarter.net. Now s_client can connect and attempt starttls, but the server did not send any certificate.
systemctl stop tigase
does not stop Tigase, what's going
on? systemctl start tigase
does start it.
It wants ./certs/jacinth.jfcarter.net.pem to be the name of the certificate chain file.
Even with the correct cert chain file, s_client on port 5222 receives no certificate after starttls, and on 5223 it hangs forever. No errors in the logs.
I changed the domain and all related hosts to jacinth.cft.ca.us, including the cert chain file. s_client is back to high CPU usage on port 5222, and hangs on 5223. No error messages in the logs.
Tidbit from a forum post dated 2012-06-25: if the client uses SSL (vs. TLS), you need to call the cert chain file default.pem (because there is no requested hostname). This is for 5.1.0beta7. I thought that's what the --ssl-def-cert-domain key is for (in 5.1.5).
Also you can set component properties as e.g. --c2s/5222/port_type=plain
I tried creating default.pem. No change in behavior.
Other people seem to be able to get this to work; it's not a generic problem with Tigase.
Testing with Pidgin. [This is with 5.1.5.] I told it to register admin@jacinth.cft.ca.us. It claimed that registration was successful. And I can connect. I also connected from another host. Confirmed with tcpdump that TLS was in use with the expected certs. The remote host connected using IPv6.
However, the
server attempts a S2S connection (to where?) and announces (to the
remote sender) Message delivery to admin/iris failed: S2S -
destination host not found (Code 404)
. The log file says it
checked routes to everywhere and could not find a route by which to
deliver the packet. It tried to open a connection to (maybe)
jacinth.cft.ca.us and could not find such a remote host.
It then sent a packet from admin/jacinth of type=error with the reported content. It found the session and wrote the packet to the session's socket.
In 5.2.0, the clients connect by IPv6 and can do normal activities.
I edited the client account records to use the IPv4 address explicitly as the connect server (5.1.5 only; 5.2.0 works with IPv6). A certificate override was required, after which both clients connected. (In 5.2.0 I installed the certificate right the first time so the override was not necessary.) And the chat session succeeds.
Issues for next time:
I moved the install directory to become /m1/Tigase-5.1.5-b3164 and made a symbolic link /usr/local/Tigase to that directory. INSTDIR was changed to use the link wherever occurring.
I hacked my LSB startup script to run Tigase as a non-root user xmpp:xmpp. Its home directory is /var/lib/xmpp. The /var/lib/tigase directory was renamed to become /var/lib/xmpp and was re-owned, mode 640 or 750.
Move the logs to /var/log/tigase . It needs a symlink from /usr/local/Tigase/logs to /var/log/tigase and the log dir and content needs to be owned by xmpp:xmpp. The PID file remains in the log directory. The derby database writes derby.log in the current directory (${INSTDIR}). I changed its ownership also and moved it to /var/log/tigase with a symlink.
Log rotation. Find out what we need to do to make Tigase use the new log file(s).
The debug output is rather extensive. But valuable for troubleshooting. When Tigase is working, turn this off.
Find out why systemctl failed to stop Tigase -- maybe because it was not used to start Tigase? Enable for auto startup.
Experiment, see if the order of the cert and key is relevant. Beware, the chain files in /etc/ssl/private do not include the root cert and the docs say it's wanted. For Apache it's optional.
Find out how to configure SASL auth, specifically GSSAPI, using saslauthd. Configure LDAP auth.
Get it to give admin privilege to the admin user.
My next goal was to revert my domain to jfcarter.net -- the step where I got locked out of the admin account on Openfire.
If the client is talking to domain jfcarter.net, it will ask the server for a cert for that domain, not the name by which it contacted the server. This seems bogus, but that's what Pidgin does (and probably everyone else). That bypasses the issue of multi-homed, DHCP and cluster hosts, by not referring to the server hostname at all. Let's try to come up with a cert for jfcarter.net.
Reviewing the procedure on Startcom:
(umask 077; openssl req -new -newkey rsa:2048 -out /etc/ssl/hostcerts/h-jfcarter-startcom-2014.csr -keyout /etc/ssl/private/h-jfcarter-startcom-2014.key -nodes)
I put the key and cert in /etc/ssl/{private,hostcerts} using a naming scheme so I can keep track of which is which, and I made symlinks jfcarter.{key,crt} to these objects. I also assembled the certificate chain file (mode 640 root:hostcert) with (in order) the cert, the key, Startcom's intermediate CA cert, and their root CA cert. And a symlink jfcarter.pem-ck to this as well. Note, the user executing Tigase must be in group hostcert to read the chain file, and you need to restart Tigase after adding the user to the group.
In ${INSTDIR}/certs I made a symbolic link:
ln -s /etc/ssl/private/jfcarter.pem-ck jfcarter.net.pem
Documentation says you can add (and remove?) certs while the server is running, but this didn't work and I had to restart Tigase, but it is likely that the problem was that the process was not in the hostcerts group and could not read the chain file.
This done, I could use a XMPP client (Pidgin) to connect without security warnings to the server, create the admin@jfcarter.net user account, log in on a different machine as admin@jfcarter.net (using a different resource), and have a chat session.
My ideal is to do single sign-on through Kerberos (GSSAPI), but there is no sign that Tigase can do Kerberos or interact with saslauthd. A less preferred but feasible option is LDAP authentication. See the admin guide page for the LDAP authentication connector. You just have to put in init.properties:
--auth-db = tigase.db.ldap.LdapAuthProvider
--auth-db-uri = ldap://localhost:389
basic-conf/auth-repo-params/user-dn-pattern = uid=%1$s,ou=people,dc=cft,dc=ca,dc=us
The first line turns on LDAP authentication. The second gives the URL of
the LDAP server. The docs don't mention multiple servers. TLS is not needed,
so it's OK to use localhost if you have a server on the same machine as Tigase.
The third line gives the Distinguished Name of the user record, where
%1$s
is replaced with the local part (minus domain) of the Jabber ID.
This works, and any user known to LDAP can authenticate and can use the XMPP service. Remember that XMPP has no permission (or programming) to write on LDAP so as to introduce a new user.
Per the Admin Guide, Server Configuration 5.x, add this line to init.properties:
c2s/clientCertCA=/path/to/cacert.pemSpecifying a Certificate Authority cert with which client certificates were signed. The client cert needs a SAN of type otherName containing an OID of "id-on-xmppAddr", whose content is a JabberID (user@domain). See XEP-0178 and RFC 6120 (sect. 13.7.1.4).
What this has to do with SASL is not clear.
Dealing with the problem where a client can authenticate but his session
is not authorized yet
so he cannot receive his roster, vCard, etc.,
i.e. he cannot see the presence of other people and cannot become a buddy.
I received a response from Artur Hefczyc, one of the Tigase developers. You need to append this to the --user-db-uri:
--user-db-uri = jdbc:derby:/var/lib/tigase;autoCreateUser=true
Then if a user gets authenticated which is not in the user database, it will be inserted. Now it works, and the new user can participate properly.
To set up your vCard, select Accounts, then hover over the account to be set up. In the sub-menu, pick Set User Info. The resulting form has all the defined text fields for a vCard (and I think you can upload a photo also). The vCard lives on the server and is individual per account. Not every protocol supports user info, but XMPP does.
A big fly in the ointment: Of two Android clients and six Intel boxes running OpenSuSE 12.3 (up to date on patches, same versions of everything), two of the SuSE clients (one each i586 and x86_64) cannot connect. This is with pidgin-2.10.7.
The affected machines send
starttls
and the server responds proceed
, the client sends a
big binary packet which the server acks, and everyone just sits there. The
big binary packet does not include the XMPP domain name, which the other
clients send at that point in a smaller packet. The failing (linux) clients
have the same version of Pidgin and all libraries. All clients are configured
identically, i.e. use the SRV record (and all get the correct server) on port
5222 with use TLS wnen available
(not old style SSL
).
I'm starting to suspect that the failing clients are trying to use SSL anyway.
Posted on the Ubuntu issue tracker, OP Mahendra (2011-09-28). He upgraded his OS getting OpenSSL 1.0.0e 6 Sep 2011. (We have openssl-1.0.1e.) wget and curl get aborts when they attempt tlsv1, which can be worked around by forcing tlsv3. A number of other client packages show similar behavior. If the server has openssl-0.9.8k the error is not seen.
In the above bug report, Paul Harvey gives a link about securing SSL in Apache Tomcat which made the problem go away for him. Basically you're suppressing certain ciphers, with the side effect of making TLSv1 impossible and forcing TLSv3. He retains SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA.
Pidgin's license is apparently not compatible with OpenSSL's license, so they use a substitute. TLS support is provided by a plugin found in /usr/lib64/purple-2/ (modify according to your distro and architecture). I have ssl.so ssl-gnutls.so ssl-nss.so. The running Pidgin maps all three of these. (This is on a failing client.) Key libraries for ssl-nss.so are libnss3.so and libssl3.so. For ssl-gnutls.so it is libgnutls.so.28. All these libraries are in /usr/lib64. How does it know which one to use, and how do you influence cipher selection?
libpurple/cipher.c is a generic API for encryption (of the stream? of the content?) and has nothing for choosing the cipher. Digging through the source code and learning how it works: Several of my other other projects are past their due dates due to instant message problems.
We all like Pidgin's user interface and we aren't happy about learning a new client, but if Pidgin doesn't work, I'm going to fire it and use a different client.
Client requirements:
Must be multi-protocol, doing XMPP and MSN. We don't use other protocols.
Must be able to connect to the Tigase XMPP server using TLS.
Must serve the core functions of presence and chat.
We aren't picky about fancy features and a glitzy UI.
Only free clients for Linux will be considered. Browser-based clients are not going to be considered (yet).
These clients are listed in xmpp.org's list of client software. It does not distinguish multi-protocol or non-free clients; these have been eliminated by checking the project websites.
Ayttm -- Last release is Ayttm-0.6.3 (2010-07-10), so not much developer attention. Protocols: Yahoo, MSN, Jabber, IRC, AIM, ICQ. Nonetheless looks good in a cursory examination.
Coccinella -- Main feature is a shared whiteboard. I think it doesn't serve our purpose, though it's interesting in other contexts.
emesene -- Supports MSN and XMPP, but as of 2013-03-19 MSN servers got reorganized and this functionality is now dead in Emesene.
Empathy -- The default chat client for Gnome. Uses the Telepathy library and the Gossip UI. Can do video chat. Uses GnuTLS (is this good or bad?) It's in the main SuSE distro. I installed it and its numerous dependencies.
If run from a SSH session (no Gnome infrastructure) it gets a segfault. If run from a XFCE session it has lots of warning messages (such as theme parsing error…) but it runs. It even can import your accounts from Pidgin. Attempting to connect from a formerly working client host to the XMPP server, it times out. This is not useful. Uninstalled.
Gajim -- XMPP protocol only. I've seen it mentioned in forum posts.
Galaxium -- Protocols: MSN, XMPP, IRC. You need version 0.8 or above for XMPP. This was released 2008-4Q, and no releases after that (not good). Screenshots look decent.
Gossip -- XMPP only, see Empathy for multi protocol extension.
Instantbird -- Multi-protocol. On a Mozilla chassis. GPL. What's their business model?
Kopete -- The official chat client for KDE. The problem is, it's going to drag in all the KDE infrastructure, which I otherwise don't use and have avoided installing on my net.
I have a very strong suspicion that the killer for Empathy was libgnutls28. Suppose I remove it, forcing Pidgin (libpurple) to use libnss3/libssl3? Not a good move; it would remove literally half the packages on the machine, 1024 packages that depend indirectly on libgnutls28. Forget that.
Suppose I remove or sabotage the GnuTLS plugin for libpurple? This is /usr/lib64/purple-2/ssl-gnutls.so . Changed mode to 000: Unbelievable, it worked! And no error messages. Pidgin on the formerly failing machine can connect to Tigase. I've filed an OpenSuSE bug report; here is a local copy of the bug report.
So this has brought the saga of the XMPP instant message server to a successful conclusion. Remaining cleanup items:
Turn on mandatory TLS in the server.
Turn off the server's debug output.
Make sure log rotation is working.
Famous last words. Two users log on to Tigase and negotiate buddy status. This works, and they receive presence updates from each other. One logs out. The other sees the gone user, not as offline but as unauthorized -- the buddy status is gone. I don't know what's going on here.