Having flamed out while setting up several XMPP servers, now I'm trying the ones based on Java. I don't know Java, I'm unhappy with their continuous security issues, and I've had bad experiences in the past with Java hogging resources. Nonetheless, my choice is now Java or nothing.
First will be Openfire. The current version is 3.8.2 dated about 2013-05-xx. The product hype on the website says:
Openfire is a real time collaboration (RTC) server licensed under the Open Source Apache License. It uses the only widely adopted open protocol for instant messaging, XMPP (also called Jabber). Openfire is incredibly easy to setup and administer, but offers rock-solid security and performance.
This version is available on the SuSE Build Service. I downloaded and installed openfire (12Mb compressed, oink) and openfire-doc (1.1Mb). Non-cryptic install dependencies are only Java and basic utilities like grep. Documentation starts at /usr/share/doc/packages/openfire-doc/index.html .
You will need some kind of database. Drivers are bundled for MySQL,
PostgreSQL, Microsoft SQL Server, and HSQLDB. The latter is the internal
database and it requires no configuration options. Separate database schemas
are provided for these four plus Oracle, Sybase and IBM DB2, implying that you
will need to hack if you use others. You are warned that HSQLDB does not
give high performance and a real
database is recommended for a heavily
used site. (SQLite…)
Files, from the SuSE package, end up in these places:
This is clearly not a LSB file layout. In particular, the log files are going to have to be moved to /var/log, the conf files have to be moved to /etc so they can be backed up, and the database has to go into /var/lib; I don't see where they're putting that. Logs from external commands can be redirected in /etc/sysconfig/openfire; I'm using /var/log/openfire (which I have to create by hand, owned by the Openfire user). The log files also have to be rotated; I copied one of my hacked scripts in /etc/logrotate.d .
Openfire runs as a non-root user. The docs mention a user jive
,
but the provided LSB script uses daemon
if it is not set in
/etc/sysconfig/openfire. I'm going to recycle ejabberd. No, I'm not.
The RPM sets ownership of the software to daemon:daemon and the main dir
/usr/share/openfire has mode 750. Temporarily I'm changing to daemon.
To configure Openfire, first make any needed changes in /etc/sysconfig/openfire. Then start it up and connect HTTP to port 9090. URL to connect to admin port 9090. Once TLS is configured it will listen on 9091 as well. It will not listen on 5222 until it has been configured.
When you connect it will run a setup wizard which will take care of the basic settings. These were my configuration choices:
Select language. Available translations are CZ DE EN ES FR NL PL pt_BR RU SK zh_CN.
Domain: The default is the hostname of your server. I hope this is not the Jabber domain that users will connect to, which is not my hostname. I changed it to the internal name of my server, which maps to an immutable IP address, versus the wild-side name which is aleatory (DHCP). You can also alter the admin ports here.
Hiss, boo! This is the XMPP domain, or at least the domain is set from this value.
More hiss, boo! Openfire seems to assume that only one domain will be served (no virtual hosts), and the server has the same name as the domain. Without this equality, SSL/TLS messes up.
Database: HSQLDB embedded database. Forget MySQL.
Profile: The choices are to store users and groups
in the
server database, or to use LDAP, or Clearspace
. The latter is
something proprietary that I've never heard of and am not going to
investigate. Knowing what an instant message server has to
do, I strongly suspect that storing users in the server database
includes storing their passwords. We demand host integration, i.e.
any user on this system is implicitly provisioned
to use the
instant message server and his/her identity, including the password,
is honored by all services including the instant messenger. That means
LDAP profile storage (readonly).
This is a disappointment: I had hoped for Kerberos (GSSAPI) authentication, but there is no sign of support for this.
LDAP Setup, Connnections: Type = OpenLDAP. Host = jacinth.cft.ca.us. Port = 389 (not encrypted). Base DN = ou=people,dc=cft,dc=ca,dc=us. Authentication: the admin DN and password are left blank and Openfire will rely on anonymous access to LDAP, which works. Advanced: I left all of them at the default, specifically to not use TLS.
The Test Settings
button produced no visible effect, which
probably means no error occurred. However, it trashed the Base DN
field. Fixed.
LDAP Setup, User Mapping: Username field = uid (default). I left the advanced settings alone. You can cause the user's vCard to be synthesized from the LDAP record. I turned on the feature to store an avatar (photo) in the database if the jpegPhoto attribute is empty. To match normal UNIX (OpenLDAP) usage I altered these settings:
Again, Test Settings
produced no visible effect.
For reference, this is the OpenLDAP command to search for a user. Fill in your own parameters: server name, base DN, and loginID to search for. Actually localhost should be fine, if the server is on localhost.
ldapsearch -x -H ldap://jacinth.cft.ca.us/ -b "ou=people,dc=cft,dc=ca,dc=us" '(uid=jimc)'
LDAP Setup, Group Mapping: We don't use groups for XMPP, but I took the opportunity to make the field names right. Group field = cn (correct). Member field = memberUid, changed from member. Description field: UNIX groups don't have descriptions. Advanced, POSIX mode = yes (value of memberUid is the user ID, vs. the complete Distinguished Name). No group filter.
Again, Test Settings
produced no visible effect.
Except, it put Member Field back to the default! Fixed.
Use the same ldapsearch command for the group, except ou=group, and in the filter the key is cn vs. uid.
Administrator account: I nominated myself to be an administrator.
The Test
button had no visible effect.
Login to the admin console: It wants your loginID and password for LDAP authentication. It let me on.
The next step is to clean up the server properties, from the admin console. You start out in the Server Manager tab. Most of these are informational only.
Server Information (and ports): This is just informational.
Server Properties: Best not to mess with any of these, but I may have to come back and change xmpp.domain, which ended up as the server's own hostname.
Database Properties: The connect URL is jdbc:hsqldb:/usr/share/openfire/embedded-db/openfire which is a filename in the installation directory, hiss, boo! It's the basename of a collection of files.
Logs: The log directory is /usr/share/openfire/logs , in the installation directory, hiss, boo! Logs are prolix in the Java style.
Email: The default is to do SMTP to localhost port 25, which is fine for me. No changes.
Security Audit Viewer: It filters the logs to show security related events.
Now in the Server Settings tab: The sections that I didn't change (most of them) are not shown.
Server to Server: I disabled this entirely.
HTTP Bindings: This looks like a real can of worms. I disabled it entirely.
Manage Updates: By default it will check for server and plugin updates and will notify administrator(s) by email when they appear. I left both of these turned on. If it gets too annoying I can suppress one or the other, later.
Registration Settings: By default it allows registration, password changing, and anonymous sessions. I turned off password changing (it's in LDAP, dummy) and anonymous sessions.
Conflict policy: XMPP user IDs include a resource
which
is kind of a sub-account. If the same user/resource logs in a second
time the default is to kick off the first session. I set a kick count
of 2, meaning that the login attempt will fail once (I hope with a
comprehensible error message), but the second time the other session
will be kicked off.
Security Settings: I changed to require TLS for both clients and server-to-server.
Server Certificates: Hiss, boo, horrid effusion of security abuse! It cannot use externally resident certificates, e.g. /etc/ssl/private/host.key; you have to import the cert into its internal storage managed by bouncycastle.jar, with unsalubrious permissions. /usr/share/openfire/resources/security/keystore has mode 644 daemon:daemon, hiss, boo! I changed it to 600 but daemon is not the user I want reading this file.
The procedure to compromise my security goes like this: On the Server Certificates page click the Import link (end of first paragraph). You get a form into which you cut and paste the text of the key and the cert, plus the key's password. I was hoping to just upload a PKCS#12 file.
You also need to use the keytool command to insert the root certificate chain in the likely case that there are no root certificates in the keystore.
For testing, I'm going to use the za-pai self signed cert that it generated, and tell the client to not be so picky.
On the Media Services tab, the default is to disable the media proxy service. This acts kind of like a H.323 application gateway. Possibly I might experiment with this in the future.
On the User/Group tab you can view your user roster, but this is kind of useless with LDAP. On the Sessions tab you can see the active sessions, including kicking off users. Under Group Chat you can create multi-user chat rooms.
On the Plugin tab you can view which plugins are installed and add new ones from Openfire's repository.
Search (XEP-0055) for searching for users by name(?) Installed by default.
The available plugins look like they would be useful for administration on a bigger server, but they are not useful for me.
The user experience: A user on localhost can connect and get a session
secured by TLS. The client complains about the unverifiable host cert; blow
off the error message. Any user on any other machine: it chatters back
and forth but never actually begins the session. (Thus it's not a firewall
issue, nor an issue of listening to the required port and/or interface.)
The client (Pidgin) says TLS handshake failed, timed out
.
Command line for testing this with s_client:
openssl s_client -connect jacinth.jfcarter.net:5222 -CApath /etc/ssl/certs -starttls xmpp
It does not do TLS at all! s_client reports that it can connect but no peer cert is available.
Isn't that cute? I restarted Openfire and tried to log in again to the admin console, and it won't let me on. I think what happened is, I changed the domain name to jfcarter.net, and the administrator was defined as jimc@jacinth.cft.ca.us. When jimc@jfcarter.net authenticates, it is not the administrator. And there is no way to go back, short of manually jiggering the database, for which I have no maintenance tools. I think that's the end of Openfire.
Conclusion on Openfire: I have these objections:
It can handle only one domain; no virtual hosts. I don't absolutely require multiple domains, but I use the feature for testing.
The server must have at least a CNAME, and certificates for it, for the domain's own name. This is not going to happen on my net.
The quality of custody of the secret key(s) is unacceptably low, and Openfire is unable to handle keys and certs stored in the usual location for UNIX.
I would very much like to get back GSSAPI authentication, which Openfire absolutely cannot do.
For PLAIN auth (loginID and password) I would very much prefer to use PAM so my standard authentication protocols will be followed. Openfire absolutely cannot do that either.
Since Openfire would be my only Java application, I lack the skill and maintenance tools to debug problems.
On the other hand, the setup and admin interface is nicely and professionally done, and so far the software, within its design limitations, seems to be stable. I'm sure that if I reinstalled it with a compromise domain name that both it and I can live with, it would work, which is a big advantage over the competitors.
However, I'm going to keep working on other XMPP servers, and only return to Openfire if all of them fail.