void xmpp_stream_start(void *data, const char *supplied_el, const char **attr)
{
-
- lprintf(CTDL_DEBUG, "New stream detected.\n");
+ lprintf(CTDL_DEBUG, "New XMPP stream.\n");
while (*attr) {
if (!strcasecmp(attr[0], "to")) {
/* The features of this stream are... */
cprintf("<stream:features>");
+#ifdef HAVE_OPENSSL_XXXX_COMMENTED_OUT
+ /* TLS encryption (but only if it isn't already active) */
+ if (!CC->redirect_ssl) {
+ cprintf("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'></starttls>");
+ }
+#endif
+
if (!CC->logged_in) {
/* If we're not logged in yet, offer SASL as our feature set */
xmpp_output_auth_mechs();
- }
- else {
- /* If we've logged in, now offer binding and sessions as our feature set */
- cprintf("<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>");
- cprintf("<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>");
+
+ /* Also offer non-SASL authentication */
+ cprintf("<auth xmlns=\"http://jabber.org/features/iq-auth\"/>");
}
+ /* Offer binding and sessions as part of our feature set */
+ cprintf("<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>");
+ cprintf("<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>");
+
cprintf("</stream:features>");
CC->is_async = 1; /* XMPP sessions are inherently async-capable */
safestrncpy(XMPP->iq_query_xmlns, supplied_el, sizeof XMPP->iq_query_xmlns);
}
+ else if (!strcasecmp(el, "bind")) {
+ XMPP->bind_requested = 1;
+ }
+
else if (!strcasecmp(el, "iq")) {
for (i=0; attr[i] != NULL; i+=2) {
if (!strcasecmp(attr[i], "type")) {
}
}
}
+
+ else if (!strcasecmp(el, "message")) {
+ for (i=0; attr[i] != NULL; i+=2) {
+ if (!strcasecmp(attr[i], "to")) {
+ safestrncpy(XMPP->message_to, attr[i+1], sizeof XMPP->message_to);
+ }
+ }
+ }
+
+ else if (!strcasecmp(el, "html")) {
+ ++XMPP->html_tag_level;
+ }
}
if (XMPP->chardata_len > 0) {
safestrncpy(XMPP->iq_client_resource, XMPP->chardata,
sizeof XMPP->iq_client_resource);
+ striplt(XMPP->iq_client_resource);
+ }
+ }
+
+ if (!strcasecmp(el, "username")) { /* NON SASL ONLY */
+ if (XMPP->chardata_len > 0) {
+ safestrncpy(XMPP->iq_client_username, XMPP->chardata,
+ sizeof XMPP->iq_client_username);
+ striplt(XMPP->iq_client_username);
+ }
+ }
+
+ if (!strcasecmp(el, "password")) { /* NON SASL ONLY */
+ if (XMPP->chardata_len > 0) {
+ safestrncpy(XMPP->iq_client_password, XMPP->chardata,
+ sizeof XMPP->iq_client_password);
+ striplt(XMPP->iq_client_password);
}
}
}
}
+ /*
+ * Non SASL authentication
+ */
+ else if (
+ (!strcasecmp(XMPP->iq_type, "set"))
+ && (!strcasecmp(XMPP->iq_query_xmlns, "jabber:iq:auth:query"))
+ ) {
+
+ jabber_non_sasl_authenticate(
+ XMPP->iq_id,
+ XMPP->iq_client_username,
+ XMPP->iq_client_password,
+ XMPP->iq_client_resource
+ );
+ }
+
/*
* If this <iq> stanza was a "bind" attempt, process it ...
*/
- else if ( (!IsEmptyStr(XMPP->iq_id)) && (!IsEmptyStr(XMPP->iq_client_resource)) ) {
+ else if (
+ (XMPP->bind_requested)
+ && (!IsEmptyStr(XMPP->iq_id))
+ && (!IsEmptyStr(XMPP->iq_client_resource))
+ && (CC->logged_in)
+ ) {
/* Generate the "full JID" of the client resource */
- // snprintf(XMPP->client_jid, sizeof XMPP->client_jid,
- // "%d@%s/%s",
- // CC->cs_pid,
- // config.c_fqdn,
- // XMPP->iq_client_resource
- //);
-
snprintf(XMPP->client_jid, sizeof XMPP->client_jid,
"%s/%s",
CC->cs_inet_email,
XMPP->iq_client_resource[0] = 0;
XMPP->iq_session = 0;
XMPP->iq_query_xmlns[0] = 0;
+ XMPP->bind_requested = 0;
}
else if (!strcasecmp(el, "auth")) {
jabber_wholist_presence_dump();
}
+ else if ( (!strcasecmp(el, "body")) && (XMPP->html_tag_level == 0) ) {
+ if (XMPP->message_body != NULL) {
+ free(XMPP->message_body);
+ XMPP->message_body = NULL;
+ }
+ if (XMPP->chardata_len > 0) {
+ XMPP->message_body = strdup(XMPP->chardata);
+ }
+ }
+
+ else if (!strcasecmp(el, "message")) {
+ jabber_send_message(XMPP->message_to, XMPP->message_body);
+ XMPP->html_tag_level = 0;
+ }
+
+ else if (!strcasecmp(el, "html")) {
+ --XMPP->html_tag_level;
+ }
+
+ else if (!strcasecmp(el, "starttls")) {
+#ifdef HAVE_OPENSSL
+ cprintf("<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
+ CtdlModuleStartCryptoMsgs(NULL, NULL, NULL);
+ if (!CC->redirect_ssl) CC->kill_me = 1;
+#else
+ cprintf("<failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
+ CC->kill_me = 1;
+#endif
+ }
+
XMPP->chardata_len = 0;
if (XMPP->chardata_alloc > 0) {
XMPP->chardata[0] = 0;
XMPP->chardata = NULL;
XMPP->chardata_len = 0;
XMPP->chardata_alloc = 0;
+ if (XMPP->message_body != NULL) {
+ free(XMPP->message_body);
+ }
}
XML_ParserFree(XMPP->xp);
free(XMPP);
strcpy(CC->cs_clientname, "Jabber session");
CC->session_specific_data = malloc(sizeof(struct citxmpp));
memset(XMPP, 0, sizeof(struct citxmpp));
+ XMPP->last_event_processed = queue_event_seq;
/* XMPP does not use a greeting, but we still have to initialize some things. */
CTDL_MODULE_INIT(jabber)
{
-#ifdef HAVE_EXPAT
if (!threading) {
- CtdlRegisterServiceHook(5222, /* FIXME change to config.c_xmpp_port */
+#ifdef HAVE_EXPAT
+ CtdlRegisterServiceHook(config.c_xmpp_c2s_port,
NULL,
xmpp_greeting,
xmpp_command_loop,
CtdlRegisterSessionHook(xmpp_cleanup_function, EVT_STOP);
CtdlRegisterSessionHook(xmpp_login_hook, EVT_LOGIN);
CtdlRegisterSessionHook(xmpp_logout_hook, EVT_LOGOUT);
-
+ CtdlRegisterSessionHook(xmpp_login_hook, EVT_UNSTEALTH);
+ CtdlRegisterSessionHook(xmpp_logout_hook, EVT_STEALTH);
#else
lprintf(CTDL_INFO, "This server is missing the Expat XML parser. Jabber service will be disabled.\n");
#endif