Ejemplo n.º 1
0
static int _handle_legacy(xmpp_conn_t * const conn,
			  xmpp_stanza_t * const stanza,
			  void * const userdata)
{
    char *type, *name;

    /* delete missing handler */
    xmpp_timed_handler_delete(conn, _handle_missing_legacy);

    /* server responded to legacy auth request */
    type = xmpp_stanza_get_type(stanza);
    name = xmpp_stanza_get_name(stanza);
    if (!type || strcmp(name, "iq") != 0) {
	xmpp_error(conn->ctx, "xmpp", "Server sent us an unexpected response "\
		   "to legacy authentication request.");
	xmpp_disconnect(conn);
    } else if (strcmp(type, "error") == 0) {
	/* legacy client auth failed, no more fallbacks */
	xmpp_error(conn->ctx, "xmpp", "Legacy client authentication failed.");
	xmpp_disconnect(conn);
    } else if (strcmp(type, "result") == 0) {
	/* auth succeeded */
	xmpp_debug(conn->ctx, "xmpp", "Legacy auth succeeded.");

	conn->authenticated = 1;
	conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
    } else {
	xmpp_error(conn->ctx, "xmpp", "Server sent us a legacy authentication "\
		   "response with a bad type.");
	xmpp_disconnect(conn);
    }

    return 0;
}
Ejemplo n.º 2
0
/** Cleanly disconnect the connection.
 *  This function is only called by the stream parser when </stream:stream>
 *  is received, and it not intended to be called by code outside of Strophe.
 *
 *  @param conn a Strophe connection object
 */
void conn_disconnect_clean(xmpp_conn_t * const conn)
{
    /* remove the timed handler */
    xmpp_timed_handler_delete(conn, _disconnect_cleanup);

    conn_disconnect(conn);
}
Ejemplo n.º 3
0
/* Check if the received stanza is <handshake/> and set auth to true
 * and fire connection handler.
 */
int _handle_component_hs_response(xmpp_conn_t * const conn,
            xmpp_stanza_t * const stanza,
            void * const userdata)
{
    char *name;

    xmpp_timed_handler_delete(conn, _handle_missing_handshake);

    name = xmpp_stanza_get_name(stanza);
    if (strcmp(name, "handshake") != 0) {
        char *msg;
        size_t msg_size;
        xmpp_stanza_to_text(stanza, &msg, &msg_size);
        if (msg) {
            xmpp_debug(conn->ctx, "auth", "Handshake failed: %s", msg);
            xmpp_free(conn->ctx, msg);
        }
        xmpp_disconnect(conn);
        return XMPP_EINT;
    } else {
        conn->authenticated = 1;
        conn->conn_handler(conn, XMPP_CONN_CONNECT, 0, NULL, conn->userdata);
    }

    /* We don't need this handler anymore, return 0 so it can be deleted
     * from the list of handlers.
     */
    return 0;
}
Ejemplo n.º 4
0
static int _handle_session(xmpp_conn_t * const conn,
			   xmpp_stanza_t * const stanza,
			   void * const userdata)
{
    char *type;

    /* delete missing session handler */
    xmpp_timed_handler_delete(conn, _handle_missing_session);

    /* server has replied to the session request */
    type = xmpp_stanza_get_type(stanza);
    if (type && strcmp(type, "error") == 0) {
	xmpp_error(conn->ctx, "xmpp", "Session establishment failed.");
	xmpp_disconnect(conn);
    } else if (type && strcmp(type, "result") == 0) {
	xmpp_debug(conn->ctx, "xmpp", "Session establishment successful.");

	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 session reply.");
	xmpp_disconnect(conn);
    }

    return 0;
}
Ejemplo n.º 5
0
static int _handle_register(xmpp_conn_t * const conn,
			     xmpp_stanza_t * const stanza,
			     void * const userdata)
{
    char *type;

    /* delete missing handler */
    xmpp_timed_handler_delete(conn, _handle_missing_register);

    /* server responded to legacy auth request */
    type = xmpp_stanza_get_type(stanza);
    if (!type) {
	xmpp_error(conn->ctx, "xmpp", "Server sent us an unexpected response "\
		   "to register request.");
	xmpp_disconnect(conn);
    } else if (strcmp(type, "error") == 0) {
	/* legacy client auth failed, no more fallbacks */
	xmpp_error(conn->ctx, "xmpp", "Register clientfailed.");
	xmpp_disconnect(conn);
    } else if (strcmp(type, "result") == 0) {
	/* auth succeeded */
	xmpp_debug(conn->ctx, "xmpp", "Register succeeded.");

	_auth(conn);
    } else {
	xmpp_error(conn->ctx, "xmpp", "Server sent us a register"	\
		   "response with a bad type.");
	xmpp_disconnect(conn);
    }

    return 0;
}
Ejemplo n.º 6
0
static int
_pong_handler(xmpp_conn_t *const conn, xmpp_stanza_t * const stanza,
    void * const userdata)
{
    char *id = xmpp_stanza_get_id(stanza);
    char *type = xmpp_stanza_get_type(stanza);

    if (id != NULL && type != NULL) {
        // show warning if error
        if (strcmp(type, STANZA_TYPE_ERROR) == 0) {
            log_warning("Server ping (id=%s) responded with error", id);

            // turn off autoping if error type is 'cancel'
            xmpp_stanza_t *error = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);
            if (error != NULL) {
                char *errtype = xmpp_stanza_get_type(error);
                if (errtype != NULL) {
                    if (strcmp(errtype, "cancel") == 0) {
                        log_warning("Server ping (id=%s) error type 'cancel', disabling autoping.", id);
                        handle_autoping_cancel();
                        xmpp_timed_handler_delete(conn, _ping_timed_handler);
                    }
                }
            }
        }
    }

    // remove this handler
    return 0;
}
Ejemplo n.º 7
0
/** Fire off all timed handlers that are ready.
 *  This function is called internally by the event loop.
 *
 *  @param ctx a Strophe context object
 *
 *  @return the time in milliseconds until the next handler will be ready
 */
uint64_t handler_fire_timed(xmpp_ctx_t * const ctx)
{
    xmpp_connlist_t *connitem;
    xmpp_handlist_t *handitem, *temp;
    int ret, fired;
    uint64_t elapsed, min;

    min = (uint64_t)(-1);

    connitem = ctx->connlist;
    while (connitem) {
	if (connitem->conn->state != XMPP_STATE_CONNECTED) {
	    connitem = connitem->next;
	    continue;
	}
	
	/* enable all handlers that were added */
	for (handitem = connitem->conn->timed_handlers; handitem;
	     handitem = handitem->next)
	    handitem->enabled = 1;

	handitem = connitem->conn->timed_handlers;
	while (handitem) {
	    /* skip newly added handlers */
	    if (!handitem->enabled) {
		handitem = handitem->next;
		continue;
	    }

	    /* only fire user handlers after authentication */
	    if (handitem->user_handler && !connitem->conn->authenticated) {
		handitem = handitem->next;
		continue;
	    }

	    fired = 0;
	    elapsed = time_elapsed(handitem->last_stamp, time_stamp());
	    if (elapsed >= handitem->period) {
		/* fire! */
		fired = 1;
		handitem->last_stamp = time_stamp();
		ret = ((xmpp_timed_handler)handitem->handler)(connitem->conn, handitem->userdata);
	    } else if (min > (handitem->period - elapsed))
		min = handitem->period - elapsed;
		
	    temp = handitem;
	    handitem = handitem->next;

	    /* delete handler if it returned false */
	    if (fired && !ret)
		xmpp_timed_handler_delete(connitem->conn, temp->handler);
	}

	connitem = connitem->next;
    }

    return min;
}
Ejemplo n.º 8
0
static void
_iq_set_autoping(const int seconds)
{
    xmpp_conn_t * const conn = connection_get_conn();
    xmpp_ctx_t * const ctx = connection_get_ctx();

    if (jabber_get_connection_status() == JABBER_CONNECTED) {
        xmpp_timed_handler_delete(conn, _ping_timed_handler);

        if (seconds != 0) {
            int millis = seconds * 1000;
            xmpp_timed_handler_add(conn, _ping_timed_handler, millis,
                ctx);
        }
    }
}
Ejemplo n.º 9
0
static int _handle_features(xmpp_conn_t * const conn,
			    xmpp_stanza_t * const stanza,
			    void * const userdata)
{
    xmpp_stanza_t *child, *mech;
    char *text;

    /* remove the handler that detects missing stream:features */
    xmpp_timed_handler_delete(conn, _handle_missing_features);

    /* check for TLS */
    if (!conn->secured) {
        if (!conn->tls_disabled) {
            child = xmpp_stanza_get_child_by_name(stanza, "starttls");
            if (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_TLS) == 0))
                conn->tls_support = 1;
        } else {
            conn->tls_support = 0;
        }
    }

    /* check for SASL */
    child = xmpp_stanza_get_child_by_name(stanza, "mechanisms");
    if (child && (strcmp(xmpp_stanza_get_ns(child), XMPP_NS_SASL) == 0)) {
	for (mech = xmpp_stanza_get_children(child); mech;
	     mech = xmpp_stanza_get_next(mech)) {
	    if (xmpp_stanza_get_name(mech) && strcmp(xmpp_stanza_get_name(mech), "mechanism") == 0) {
		text = xmpp_stanza_get_text(mech);
		if (strcasecmp(text, "PLAIN") == 0)
		    conn->sasl_support |= SASL_MASK_PLAIN;
		else if (strcasecmp(text, "DIGEST-MD5") == 0)
		    conn->sasl_support |= SASL_MASK_DIGESTMD5;
                else if (strcasecmp(text, "SCRAM-SHA-1") == 0)
                    conn->sasl_support |= SASL_MASK_SCRAMSHA1;
		else if (strcasecmp(text, "ANONYMOUS") == 0)
		    conn->sasl_support |= SASL_MASK_ANONYMOUS;

		xmpp_free(conn->ctx, text);
	    }
	}
    }

    _auth(conn);

    return 0;
}
Ejemplo n.º 10
0
static int
_bookmark_handle_result(xmpp_conn_t * const conn,
    xmpp_stanza_t * const stanza, void * const userdata)
{
    xmpp_ctx_t *ctx = connection_get_ctx();
    char *id = (char *)userdata;
    xmpp_stanza_t *ptr;
    xmpp_stanza_t *nick;
    char *name;
    char *jid;
    char *autojoin;
    gboolean autojoin_val;
    Jid *my_jid;
    Bookmark *item;

    xmpp_timed_handler_delete(conn, _bookmark_handle_delete);
    g_free(id);

    name = xmpp_stanza_get_name(stanza);
    if (!name || strcmp(name, STANZA_NAME_IQ) != 0) {
        return 0;
    }

    ptr = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
    if (!ptr) {
        return 0;
    }
    ptr = xmpp_stanza_get_child_by_name(ptr, STANZA_NAME_STORAGE);
    if (!ptr) {
        return 0;
    }

    if (bookmark_ac == NULL) {
        bookmark_ac = autocomplete_new();
    }
    my_jid = jid_create(jabber_get_fulljid());

    ptr = xmpp_stanza_get_children(ptr);
    while (ptr) {
        name = xmpp_stanza_get_name(ptr);
        if (!name || strcmp(name, STANZA_NAME_CONFERENCE) != 0) {
            ptr = xmpp_stanza_get_next(ptr);
            continue;
        }
        jid = xmpp_stanza_get_attribute(ptr, STANZA_ATTR_JID);
        if (!jid) {
            ptr = xmpp_stanza_get_next(ptr);
            continue;
        }

        log_debug("Handle bookmark for %s", jid);

        name = NULL;
        nick = xmpp_stanza_get_child_by_name(ptr, "nick");
        if (nick) {
            char *tmp;
            tmp = xmpp_stanza_get_text(nick);
            if (tmp) {
                name = strdup(tmp);
                xmpp_free(ctx, tmp);
            }
        }

        autojoin = xmpp_stanza_get_attribute(ptr, "autojoin");
        if (autojoin && (strcmp(autojoin, "1") == 0 || strcmp(autojoin, "true") == 0)) {
            autojoin_val = TRUE;
        } else {
            autojoin_val = FALSE;
        }

        autocomplete_add(bookmark_ac, jid);
        item = malloc(sizeof(*item));
        item->jid = strdup(jid);
        item->nick = name;
        item->autojoin = autojoin_val;
        bookmark_list = g_list_append(bookmark_list, item);


        /* TODO: preference whether autojoin */
        if (autojoin_val) {
            if (autojoin_count < BOOKMARK_AUTOJOIN_MAX) {
                Jid *room_jid;

                ++autojoin_count;

                if (name == NULL) {
                    name = my_jid->localpart;
                }

                log_debug("Autojoin %s with nick=%s", jid, name);
                room_jid = jid_create_from_bare_and_resource(jid, name);
                if (!muc_room_is_active(room_jid)) {
                    presence_join_room(room_jid);
                    /* TODO: this should be removed after fixing #195 */
                    ui_room_join(room_jid);
                }
                jid_destroy(room_jid);
            } else {
                log_debug("Rejected autojoin %s (maximum has been reached)", jid);
            }
        }

        ptr = xmpp_stanza_get_next(ptr);
    }

    jid_destroy(my_jid);

    return 0;
}
Ejemplo n.º 11
0
static int
_bookmark_handle_result(xmpp_conn_t *const conn,
    xmpp_stanza_t *const stanza, void *const userdata)
{
    xmpp_ctx_t *ctx = connection_get_ctx();
    char *id = (char *)userdata;
    xmpp_stanza_t *ptr;
    xmpp_stanza_t *nick;
    xmpp_stanza_t *password_st;
    char *name;
    char *jid;
    char *autojoin;
    char *password;
    gboolean autojoin_val;
    Jid *my_jid;
    Bookmark *item;

    xmpp_timed_handler_delete(conn, _bookmark_handle_delete);
    g_free(id);

    name = xmpp_stanza_get_name(stanza);
    if (!name || strcmp(name, STANZA_NAME_IQ) != 0) {
        return 0;
    }

    ptr = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_QUERY);
    if (!ptr) {
        return 0;
    }
    ptr = xmpp_stanza_get_child_by_name(ptr, STANZA_NAME_STORAGE);
    if (!ptr) {
        return 0;
    }

    if (bookmark_ac == NULL) {
        bookmark_ac = autocomplete_new();
    }
    my_jid = jid_create(jabber_get_fulljid());

    ptr = xmpp_stanza_get_children(ptr);
    while (ptr) {
        name = xmpp_stanza_get_name(ptr);
        if (!name || strcmp(name, STANZA_NAME_CONFERENCE) != 0) {
            ptr = xmpp_stanza_get_next(ptr);
            continue;
        }
        jid = xmpp_stanza_get_attribute(ptr, STANZA_ATTR_JID);
        if (!jid) {
            ptr = xmpp_stanza_get_next(ptr);
            continue;
        }

        log_debug("Handle bookmark for %s", jid);

        name = NULL;
        nick = xmpp_stanza_get_child_by_name(ptr, "nick");
        if (nick) {
            char *tmp;
            tmp = xmpp_stanza_get_text(nick);
            if (tmp) {
                name = strdup(tmp);
                xmpp_free(ctx, tmp);
            }
        }

        password = NULL;
        password_st = xmpp_stanza_get_child_by_name(ptr, "password");
        if (password_st) {
            char *tmp;
            tmp = xmpp_stanza_get_text(password_st);
            if (tmp) {
                password = strdup(tmp);
                xmpp_free(ctx, tmp);
            }
        }

        autojoin = xmpp_stanza_get_attribute(ptr, "autojoin");
        if (autojoin && (strcmp(autojoin, "1") == 0 || strcmp(autojoin, "true") == 0)) {
            autojoin_val = TRUE;
        } else {
            autojoin_val = FALSE;
        }

        autocomplete_add(bookmark_ac, jid);
        item = malloc(sizeof(*item));
        item->jid = strdup(jid);
        item->nick = name;
        item->password = password;
        item->autojoin = autojoin_val;
        bookmark_list = g_list_append(bookmark_list, item);

        if (autojoin_val) {
            Jid *room_jid;

            char *account_name = jabber_get_account_name();
            ProfAccount *account = accounts_get_account(account_name);
            if (name == NULL) {
                name = account->muc_nick;
            }

            log_debug("Autojoin %s with nick=%s", jid, name);
            room_jid = jid_create_from_bare_and_resource(jid, name);
            if (!muc_active(room_jid->barejid)) {
                presence_join_room(jid, name, password);
                muc_join(jid, name, password, TRUE);
            }
            jid_destroy(room_jid);
            account_free(account);
        }

        ptr = xmpp_stanza_get_next(ptr);
    }

    jid_destroy(my_jid);

    return 0;
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
0
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;
}