void auth_handle_component_open(xmpp_conn_t * const conn) { /* reset all timed handlers */ handler_reset_timed(conn, 0); handler_add(conn, _handle_error, XMPP_NS_STREAMS, "error", NULL, NULL); handler_add(conn, _handle_component_hs_response, NULL, "handshake", NULL, NULL); handler_add_timed(conn, _handle_missing_handshake, HANDSHAKE_TIMEOUT, NULL); _handle_component_auth(conn); }
/** Set up handlers at stream start. * This function is called internally to Strophe for handling the opening * of an XMPP stream. It's called by the parser when a stream is opened * or reset, and adds the initial handlers for <stream:error/> and * <stream:features/>. This function is not intended for use outside * of Strophe. * * @param conn a Strophe connection object */ void auth_handle_open(xmpp_conn_t * const conn) { /* reset all timed handlers */ handler_reset_timed(conn, 0); /* setup handler for stream:error */ handler_add(conn, _handle_error, XMPP_NS_STREAMS, "error", NULL, NULL); /* setup handlers for incoming <stream:features> */ handler_add(conn, _handle_features, XMPP_NS_STREAMS, "features", NULL, NULL); handler_add_timed(conn, _handle_missing_features, FEATURES_TIMEOUT, NULL); }
static void test_handler_remove(void) { handler_add("http", "e"); g_assert_true(handler_remove("http")); g_assert_false(handler_remove("http")); }
void auth_handle_component_open(xmpp_conn_t * const conn) { int rc; /* reset all timed handlers */ handler_reset_timed(conn, 0); handler_add(conn, _handle_error, XMPP_NS_STREAMS, "error", NULL, NULL); handler_add(conn, _handle_component_hs_response, NULL, "handshake", NULL, NULL); handler_add_timed(conn, _handle_missing_handshake, HANDSHAKE_TIMEOUT, NULL); rc = _handle_component_auth(conn); if (rc != 0) { xmpp_error(conn->ctx, "auth", "Component authentication failed."); xmpp_disconnect(conn); } }
/* called when stream:stream tag received after SASL auth */ static void _handle_open_sasl(xmpp_conn_t * const conn) { xmpp_debug(conn->ctx, "xmpp", "Reopened stream successfully."); /* setup stream:features handlers */ handler_add(conn, _handle_features_sasl, XMPP_NS_STREAMS, "features", NULL, NULL); handler_add_timed(conn, _handle_missing_features_sasl, FEATURES_TIMEOUT, NULL); }
/* handle the challenge phase of digest auth */ static int _handle_digestmd5_challenge(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, void * const userdata) { char *text; char *response; xmpp_stanza_t *auth, *authdata; char *name; name = xmpp_stanza_get_name(stanza); xmpp_debug(conn->ctx, "xmpp",\ "handle digest-md5 (challenge) called for %s", name); if (strcmp(name, "challenge") == 0) { text = xmpp_stanza_get_text(stanza); response = sasl_digest_md5(conn->ctx, text, conn->jid, conn->pass); if (!response) { disconnect_mem_error(conn); return 0; } xmpp_free(conn->ctx, text); auth = xmpp_stanza_new(conn->ctx); if (!auth) { disconnect_mem_error(conn); return 0; } xmpp_stanza_set_name(auth, "response"); xmpp_stanza_set_ns(auth, XMPP_NS_SASL); authdata = xmpp_stanza_new(conn->ctx); if (!authdata) { disconnect_mem_error(conn); return 0; } xmpp_stanza_set_text(authdata, response); xmpp_free(conn->ctx, response); xmpp_stanza_add_child(auth, authdata); xmpp_stanza_release(authdata); handler_add(conn, _handle_digestmd5_rspauth, XMPP_NS_SASL, NULL, NULL, NULL); xmpp_send(conn, auth); xmpp_stanza_release(auth); } else { return _handle_sasl_result(conn, stanza, "DIGEST-MD5"); } /* remove ourselves */ return 0; }
static void test_handler_run_failed(void) { if (g_test_subprocess()) { handler_add("http", "unknown-program %s"); handle_uri(TEST_URI); return; } g_test_trap_subprocess(NULL, 0, 0); g_test_trap_assert_failed(); g_test_trap_assert_stderr("*Can't run *unknown-program*"); }
static void test_handler_run_success(void) { if (g_test_subprocess()) { handler_add("http", "echo -n 'handled uri %s'"); handle_uri(TEST_URI); return; } g_test_trap_subprocess(NULL, 0, 0); g_test_trap_assert_passed(); g_test_trap_assert_stdout("handled uri " TEST_URI); }
int main(int argc, char *argv[]) { void *ctx, *socket, *pub; handler_t *handler; int rc; char header[TOPS_MAX_HEADER_SIZE]; ctx = zmq_init (1); // TODO: cmd line options for socket ports socket = zmq_socket (ctx, ZMQ_REP); rc = zmq_bind (socket, "tcp://*:9292"); pub = zmq_socket (ctx, ZMQ_PUB); rc = zmq_bind (pub, "tcp://*:9293"); handler = handler_init (); while (1) { memset (header, 0, TOPS_MAX_HEADER_SIZE); zmq_recv (socket, header, TOPS_MAX_HEADER_SIZE, 0); //printf("DEBUG: %s\n", header); if (strcmp (header, TOPS_ADD) == 0) { rc = handler_add (handler, socket, pub); } else if (strcmp (header, TOPS_REM) == 0) { rc = handler_rem (handler, socket); } else if (strcmp (header, TOPS_GET) == 0) { rc = handler_get (handler, socket); } else { rc = handler_unknown (handler, socket); } if (rc != 0) { // TODO: asplode! } } handler_close (handler); zmq_close (socket); zmq_term (ctx); return 0; }
/* authenticate the connection * this may get called multiple times. if any auth method fails, * this will get called again until one auth method succeeds or every * method fails */ static void _auth(xmpp_conn_t * const conn) { xmpp_stanza_t *auth, *authdata, *query, *child, *iq; char *str, *authid; char *scram_init; int anonjid; /* if there is no node in conn->jid, we assume anonymous connect */ str = xmpp_jid_node(conn->ctx, conn->jid); if (str == NULL) { anonjid = 1; } else { xmpp_free(conn->ctx, str); anonjid = 0; } if (conn->tls_support) { tls_t *tls = tls_new(conn->ctx, conn->sock); /* If we couldn't init tls, it isn't there, so go on */ if (!tls) { conn->tls_support = 0; _auth(conn); return; } else { tls_free(tls); } auth = _make_starttls(conn); if (!auth) { disconnect_mem_error(conn); return; } handler_add(conn, _handle_proceedtls_default, XMPP_NS_TLS, NULL, NULL, NULL); xmpp_send(conn, auth); xmpp_stanza_release(auth); /* TLS was tried, unset flag */ conn->tls_support = 0; } else if (anonjid && conn->sasl_support & SASL_MASK_ANONYMOUS) { /* some crap here */ auth = _make_sasl_auth(conn, "ANONYMOUS"); if (!auth) { disconnect_mem_error(conn); return; } handler_add(conn, _handle_sasl_result, XMPP_NS_SASL, NULL, NULL, "ANONYMOUS"); xmpp_send(conn, auth); xmpp_stanza_release(auth); /* SASL ANONYMOUS was tried, unset flag */ conn->sasl_support &= ~SASL_MASK_ANONYMOUS; } else if (anonjid) { xmpp_error(conn->ctx, "auth", "No node in JID, and SASL ANONYMOUS unsupported."); xmpp_disconnect(conn); } else if (conn->sasl_support & SASL_MASK_SCRAMSHA1) { auth = _make_sasl_auth(conn, "SCRAM-SHA-1"); if (!auth) { disconnect_mem_error(conn); return; } /* don't free scram_init on success */ scram_init = _make_scram_sha1_init_msg(conn); if (!scram_init) { xmpp_stanza_release(auth); disconnect_mem_error(conn); return; } str = (char *)base64_encode(conn->ctx, (unsigned char *)scram_init, strlen(scram_init)); if (!str) { xmpp_free(conn->ctx, scram_init); xmpp_stanza_release(auth); disconnect_mem_error(conn); return; } authdata = xmpp_stanza_new(conn->ctx); if (!authdata) { xmpp_free(conn->ctx, str); xmpp_free(conn->ctx, scram_init); xmpp_stanza_release(auth); disconnect_mem_error(conn); return; } xmpp_stanza_set_text(authdata, str); xmpp_free(conn->ctx, str); xmpp_stanza_add_child(auth, authdata); xmpp_stanza_release(authdata); handler_add(conn, _handle_scram_sha1_challenge, XMPP_NS_SASL, NULL, NULL, (void *)scram_init); xmpp_send(conn, auth); xmpp_stanza_release(auth); /* SASL SCRAM-SHA-1 was tried, unset flag */ conn->sasl_support &= ~SASL_MASK_SCRAMSHA1; } else if (conn->sasl_support & SASL_MASK_DIGESTMD5) { auth = _make_sasl_auth(conn, "DIGEST-MD5"); if (!auth) { disconnect_mem_error(conn); return; } handler_add(conn, _handle_digestmd5_challenge, XMPP_NS_SASL, NULL, NULL, NULL); xmpp_send(conn, auth); xmpp_stanza_release(auth); /* SASL DIGEST-MD5 was tried, unset flag */ conn->sasl_support &= ~SASL_MASK_DIGESTMD5; } else if (conn->sasl_support & SASL_MASK_PLAIN) { auth = _make_sasl_auth(conn, "PLAIN"); if (!auth) { disconnect_mem_error(conn); return; } authdata = xmpp_stanza_new(conn->ctx); if (!authdata) { disconnect_mem_error(conn); return; } authid = _get_authid(conn); if (!authid) { disconnect_mem_error(conn); return; } str = sasl_plain(conn->ctx, authid, conn->pass); if (!str) { disconnect_mem_error(conn); return; } xmpp_stanza_set_text(authdata, str); xmpp_free(conn->ctx, str); xmpp_free(conn->ctx, authid); xmpp_stanza_add_child(auth, authdata); xmpp_stanza_release(authdata); handler_add(conn, _handle_sasl_result, XMPP_NS_SASL, NULL, NULL, "PLAIN"); xmpp_send(conn, auth); xmpp_stanza_release(auth); /* SASL PLAIN was tried */ conn->sasl_support &= ~SASL_MASK_PLAIN; } else if (conn->type == XMPP_CLIENT) { /* legacy client authentication */ iq = xmpp_stanza_new(conn->ctx); if (!iq) { disconnect_mem_error(conn); return; } xmpp_stanza_set_name(iq, "iq"); xmpp_stanza_set_type(iq, "set"); xmpp_stanza_set_id(iq, "_xmpp_auth1"); query = xmpp_stanza_new(conn->ctx); if (!query) { xmpp_stanza_release(iq); disconnect_mem_error(conn); return; } xmpp_stanza_set_name(query, "query"); xmpp_stanza_set_ns(query, XMPP_NS_AUTH); xmpp_stanza_add_child(iq, query); xmpp_stanza_release(query); child = xmpp_stanza_new(conn->ctx); if (!child) { xmpp_stanza_release(iq); disconnect_mem_error(conn); return; } xmpp_stanza_set_name(child, "username"); xmpp_stanza_add_child(query, child); xmpp_stanza_release(child); authdata = xmpp_stanza_new(conn->ctx); if (!authdata) { xmpp_stanza_release(iq); disconnect_mem_error(conn); return; } str = xmpp_jid_node(conn->ctx, conn->jid); xmpp_stanza_set_text(authdata, str); xmpp_free(conn->ctx, str); xmpp_stanza_add_child(child, authdata); xmpp_stanza_release(authdata); child = xmpp_stanza_new(conn->ctx); if (!child) { xmpp_stanza_release(iq); disconnect_mem_error(conn); return; } xmpp_stanza_set_name(child, "password"); xmpp_stanza_add_child(query, child); xmpp_stanza_release(child); authdata = xmpp_stanza_new(conn->ctx); if (!authdata) { xmpp_stanza_release(iq); disconnect_mem_error(conn); return; } xmpp_stanza_set_text(authdata, conn->pass); xmpp_stanza_add_child(child, authdata); xmpp_stanza_release(authdata); child = xmpp_stanza_new(conn->ctx); if (!child) { xmpp_stanza_release(iq); disconnect_mem_error(conn); return; } xmpp_stanza_set_name(child, "resource"); xmpp_stanza_add_child(query, child); xmpp_stanza_release(child); authdata = xmpp_stanza_new(conn->ctx); if (!authdata) { xmpp_stanza_release(iq); disconnect_mem_error(conn); return; } str = xmpp_jid_resource(conn->ctx, conn->jid); if (str) { xmpp_stanza_set_text(authdata, str); xmpp_free(conn->ctx, str); } else { xmpp_stanza_release(authdata); xmpp_stanza_release(iq); xmpp_error(conn->ctx, "auth", "Cannot authenticate without resource"); xmpp_disconnect(conn); return; } xmpp_stanza_add_child(child, authdata); xmpp_stanza_release(authdata); handler_add_id(conn, _handle_legacy, "_xmpp_auth1", NULL); handler_add_timed(conn, _handle_missing_legacy, LEGACY_TIMEOUT, NULL); xmpp_send(conn, iq); xmpp_stanza_release(iq); } }
static void test_handler_add(void) { /* check none handled http first */ g_assert_true(handler_add("http", "echo -n 'handled uri %s'")); }