コード例 #1
0
ファイル: auth.c プロジェクト: mcanthony/libstrophe
/* 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);
}
コード例 #2
0
ファイル: auth.c プロジェクト: mcanthony/libstrophe
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);
}
コード例 #3
0
ファイル: conn.c プロジェクト: CAOJINGYOU/libstrophe
/** Initiate termination of the connection to the XMPP server.
 *  This function starts the disconnection sequence by sending
 *  </stream:stream> to the XMPP server.  This function will do nothing
 *  if the connection state is CONNECTING or CONNECTED.
 *
 *  @param conn a Strophe connection object
 *
 *  @ingroup Connections
 */
void xmpp_disconnect(xmpp_conn_t * const conn)
{
    if (conn->state != XMPP_STATE_CONNECTING &&
	conn->state != XMPP_STATE_CONNECTED)
	return;

    /* close the stream */
    xmpp_send_raw_string(conn, "</stream:stream>");

    /* setup timed handler in case disconnect takes too long */
    handler_add_timed(conn, _disconnect_cleanup,
		      DISCONNECT_TIMEOUT, NULL);
}
コード例 #4
0
ファイル: auth.c プロジェクト: mcanthony/libstrophe
/** 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);
}
コード例 #5
0
ファイル: auth.c プロジェクト: boothj5/libmesode
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);
    }
}
コード例 #6
0
ファイル: auth.c プロジェクト: mcanthony/libstrophe
static int _handle_bind(xmpp_conn_t * const conn,
			xmpp_stanza_t * const stanza,
			void * const userdata)
{
    char *type;
    xmpp_stanza_t *iq, *session;

    /* delete missing bind handler */
    xmpp_timed_handler_delete(conn, _handle_missing_bind);

    /* server has replied to bind request */
    type = xmpp_stanza_get_type(stanza);
    if (type && strcmp(type, "error") == 0) {
	xmpp_error(conn->ctx, "xmpp", "Binding failed.");
	xmpp_disconnect(conn);
    } else if (type && strcmp(type, "result") == 0) {
        xmpp_stanza_t *binding = xmpp_stanza_get_child_by_name(stanza, "bind");
	xmpp_debug(conn->ctx, "xmpp", "Bind successful.");

        if (binding) {
            xmpp_stanza_t *jid_stanza = xmpp_stanza_get_child_by_name(binding,
                                                                      "jid");
            if (jid_stanza) {
                conn->bound_jid = xmpp_stanza_get_text(jid_stanza);
            }
        }

	/* establish a session if required */
	if (conn->session_required) {
	    /* setup response handlers */
	    handler_add_id(conn, _handle_session, "_xmpp_session1", NULL);
	    handler_add_timed(conn, _handle_missing_session,
			      SESSION_TIMEOUT, NULL);

	    /* send session request */
	    iq = xmpp_stanza_new(conn->ctx);
	    if (!iq) {
		disconnect_mem_error(conn);
		return 0;
	    }

	    xmpp_stanza_set_name(iq, "iq");
	    xmpp_stanza_set_type(iq, "set");
	    xmpp_stanza_set_id(iq, "_xmpp_session1");

	    session = xmpp_stanza_new(conn->ctx);
	    if (!session) {
		xmpp_stanza_release(iq);
		disconnect_mem_error(conn);
	    }

	    xmpp_stanza_set_name(session, "session");
	    xmpp_stanza_set_ns(session, XMPP_NS_SESSION);

	    xmpp_stanza_add_child(iq, session);
	    xmpp_stanza_release(session);

	    /* send session establishment request */
	    xmpp_send(conn, iq);
	    xmpp_stanza_release(iq);
	} else {
	    conn->authenticated = 1;

	    /* call connection handler */
	    conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL,
			       conn->userdata);
	}
    } else {
	xmpp_error(conn->ctx, "xmpp", "Server sent malformed bind reply.");
	xmpp_disconnect(conn);
    }

    return 0;
}
コード例 #7
0
ファイル: auth.c プロジェクト: mcanthony/libstrophe
static int _handle_features_sasl(xmpp_conn_t * const conn,
				 xmpp_stanza_t * const stanza,
				 void * const userdata)
{
    xmpp_stanza_t *bind, *session, *iq, *res, *text;
    char *resource;

    /* remove missing features handler */
    xmpp_timed_handler_delete(conn, _handle_missing_features_sasl);

    /* we are expecting <bind/> and <session/> since this is a
       XMPP style connection */

    bind = xmpp_stanza_get_child_by_name(stanza, "bind");
    if (bind && strcmp(xmpp_stanza_get_ns(bind), XMPP_NS_BIND) == 0) {
	/* resource binding is required */
	conn->bind_required = 1;
    }

    session = xmpp_stanza_get_child_by_name(stanza, "session");
    if (session && strcmp(xmpp_stanza_get_ns(session), XMPP_NS_SESSION) == 0) {
	/* session establishment required */
	conn->session_required = 1;
    }

    /* if bind is required, go ahead and start it */
    if (conn->bind_required) {
	/* bind resource */

	/* setup response handlers */
	handler_add_id(conn, _handle_bind, "_xmpp_bind1", NULL);
	handler_add_timed(conn, _handle_missing_bind,
			  BIND_TIMEOUT, NULL);

	/* send bind request */
	iq = xmpp_stanza_new(conn->ctx);
	if (!iq) {
	    disconnect_mem_error(conn);
	    return 0;
	}

	xmpp_stanza_set_name(iq, "iq");
	xmpp_stanza_set_type(iq, "set");
	xmpp_stanza_set_id(iq, "_xmpp_bind1");

	bind = xmpp_stanza_copy(bind);
	if (!bind) {
	    xmpp_stanza_release(iq);
	    disconnect_mem_error(conn);
	    return 0;
	}

	/* request a specific resource if we have one */
        resource = xmpp_jid_resource(conn->ctx, conn->jid);
	if ((resource != NULL) && (strlen(resource) == 0)) {
	    /* jabberd2 doesn't handle an empty resource */
	    xmpp_free(conn->ctx, resource);
	    resource = NULL;
	}

	/* if we have a resource to request, do it. otherwise the
	   server will assign us one */
	if (resource) {
	    res = xmpp_stanza_new(conn->ctx);
	    if (!res) {
		xmpp_stanza_release(bind);
		xmpp_stanza_release(iq);
		disconnect_mem_error(conn);
		return 0;
	    }
	    xmpp_stanza_set_name(res, "resource");
	    text = xmpp_stanza_new(conn->ctx);
	    if (!text) {
		xmpp_stanza_release(res);
		xmpp_stanza_release(bind);
		xmpp_stanza_release(iq);
		disconnect_mem_error(conn);
		return 0;
	    }
	    xmpp_stanza_set_text(text, resource);
	    xmpp_stanza_add_child(res, text);
            xmpp_stanza_release(text);
	    xmpp_stanza_add_child(bind, res);
            xmpp_stanza_release(res);
	    xmpp_free(conn->ctx, resource);
	}

	xmpp_stanza_add_child(iq, bind);
	xmpp_stanza_release(bind);

	/* send bind request */
	xmpp_send(conn, iq);
	xmpp_stanza_release(iq);
    } else {
	/* can't bind, disconnect */
	xmpp_error(conn->ctx, "xmpp", "Stream features does not allow "\
		   "resource bind.");
	xmpp_disconnect(conn);
    }

    return 0;
}
コード例 #8
0
ファイル: auth.c プロジェクト: mcanthony/libstrophe
/* 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);
    }
}
コード例 #9
0
ファイル: auth.c プロジェクト: catap/libstrophe
/** registration at connections
 *
 *  @param conn a Strophe connection object
 */
static void _register(xmpp_conn_t * const conn)
{
    char *str;

    xmpp_stanza_t *iq, *q, *child, *regdata;

    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_reg1");

    q = xmpp_stanza_new(conn->ctx);
    if (!q) {
	xmpp_stanza_release(iq);
	disconnect_mem_error(conn);
	return;
    }
    xmpp_stanza_set_name(q, "query");
    xmpp_stanza_set_ns(q, XMPP_NS_REGISTER);
    xmpp_stanza_add_child(iq, q);
    xmpp_stanza_release(q);

    child = xmpp_stanza_new(conn->ctx);
    if (!child) {
	xmpp_stanza_release(iq);
	disconnect_mem_error(conn);
	return;
    }
    xmpp_stanza_set_name(child, "registered");
    xmpp_stanza_add_child(q, child);
    xmpp_stanza_release(child);

    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(q, child);
    xmpp_stanza_release(child);

    regdata = xmpp_stanza_new(conn->ctx);
    if (!regdata) {
	xmpp_stanza_release(iq);
	disconnect_mem_error(conn);
	return;
    }
    str = xmpp_jid_node(conn->ctx, conn->jid);
    xmpp_stanza_set_text(regdata, str);
    xmpp_free(conn->ctx, str);
    xmpp_stanza_add_child(child, regdata);
    xmpp_stanza_release(regdata);

    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(q, child);
    xmpp_stanza_release(child);

    regdata = xmpp_stanza_new(conn->ctx);
    if (!regdata) {
	xmpp_stanza_release(iq);
	disconnect_mem_error(conn);
	return;
    }
    xmpp_stanza_set_text(regdata, conn->pass);
    xmpp_stanza_add_child(child, regdata);
    xmpp_stanza_release(regdata);

    child = xmpp_stanza_new(conn->ctx);
    if (!child) {
	xmpp_stanza_release(iq);
	disconnect_mem_error(conn);
	return;
    }
    xmpp_stanza_set_name(child, "email");
    xmpp_stanza_add_child(q, child);
    xmpp_stanza_release(child);

    regdata = xmpp_stanza_new(conn->ctx);
    if (!regdata) {
	xmpp_stanza_release(iq);
	disconnect_mem_error(conn);
	return;
    }
    str = xmpp_jid_node(conn->ctx, conn->jid);
    xmpp_stanza_set_text(regdata, str);
    xmpp_free(conn->ctx, str);
    xmpp_stanza_add_child(child, regdata);
    xmpp_stanza_release(regdata);

    handler_add_id(conn, _handle_register, "_xmpp_reg1", NULL);
    handler_add_timed(conn, _handle_missing_register, 
		      LAZY_REGISTRATION_TIMEOUT, NULL);

    xmpp_send(conn, iq);
    xmpp_stanza_release(iq);
}