Пример #1
0
/**
 * Callback function for the resource bind request to process the response.
 */
static gboolean
resource_bind_cb(XmppStream *stream, xmlnode *root, gpointer user_data)
{
    gchar   *type;
    gchar   *jid;
    xmlnode *node;

    type = xmlnode_prop(root, "type");

    if (g_strcmp0(type, "result")) {
        hybrid_account_error_reason(stream->account->account,
                _("resource bind error."));
        return FALSE;
    }

    if (!(node = xmlnode_find(root, "jid"))) {
        hybrid_account_error_reason(stream->account->account,
                _("resource bind error: no jabber id returned."));
        return FALSE;
    }

    jid = xmlnode_content(node);
    xmpp_stream_set_jid(stream, jid);
    g_free(jid);

    /* request to start a session. */
    IqRequest *iq;

    iq = iq_request_create(stream, IQ_TYPE_SET);

    node = xmlnode_new_child(iq->node, "session");
    xmlnode_new_namespace(node, NULL, NS_XMPP_SESSION);

    iq_request_set_callback(iq, start_session_cb, NULL);

    if (iq_request_send(iq) != HYBRID_OK) {

        hybrid_account_error_reason(stream->account->account,
                _("start session error."));

        iq_request_destroy(iq);

        return TRUE;
    }

    iq_request_destroy(iq);

    return TRUE;
}
Пример #2
0
/**
 * Callback function to handle the cfg connect event.
 */
static gboolean
cfg_connect_cb(gint sk, gpointer user_data)
{
    gchar          *http;
    gchar          *body;
    fetion_account *ac = (fetion_account*)user_data;

    hybrid_account_set_connection_string(ac->account, _("Downloading configure file..."));

    body = generate_configuration_body(ac);
    http = g_strdup_printf("POST /nav/getsystemconfig.aspx HTTP/1.1\r\n"
                           "User-Agent: IIC2.0/PC "PROTO_VERSION"\r\n"
                           "Host: %s\r\n"
                           "Connection: Close\r\n"
                           "Content-Length: %lu\r\n\r\n%s",
                           NAV_SERVER, strlen(body), body);

    g_free(body);

    hybrid_debug_info("fetion", "send:\n%s", http);

    if (send(sk, http, strlen(http), 0) == -1) {
        hybrid_account_error_reason(ac->account, _("downloading cfg error"));
        g_free(http);

        return FALSE;
    }

    g_free(http);

    ac->source = hybrid_event_add(sk, HYBRID_EVENT_READ, cfg_read_cb, ac);

    return FALSE;
}
Пример #3
0
gboolean
imap_auth_cb(hybrid_imap *imap, const gchar *msg, gpointer user_data)
{
    hybrid_debug_info("imap", "recv:\n%s", msg);

    if (HYBRID_OK == check_resp_ok(msg)) {
        hybrid_account_set_connection_string(imap->account,
                                             _("IMAP OK."));
        hybrid_account_set_connection_status(imap->account,
                                             HYBRID_CONNECTION_CONNECTED);

        hybrid_account_set_state(imap->account, HYBRID_STATE_ONLINE);

        imap->mail_check_source = g_timeout_add_seconds(
                                        imap->mail_check_interval,
                                        check_mail, imap);
        return FALSE;
    }

    hybrid_account_error_reason(imap->account,
                                _("IMAP Authenticate Failed."
                                  " Check your username and password."));

    return FALSE;
}
Пример #4
0
/**
 * Process deregister message. When the same account logins
 * at somewhere else, this message will be received.
 */
static void
process_dereg_cb(fetion_account *ac, const gchar *sipmsg)
{
    hybrid_account_error_reason(ac->account,
                                _("Your account has logined elsewhere."
                                  "You are forced to quit."));
}
Пример #5
0
/**
 * Request the roster from the server.
 */
static void
xmpp_stream_get_roster(XmppStream *stream)
{
    xmlnode   *node;
    IqRequest *iq;

    g_return_if_fail(stream != NULL);

    xmpp_stream_iqid_increase(stream);

    iq = iq_request_create(stream, IQ_TYPE_GET);
    iq_request_set_callback(iq, request_roster_cb, NULL);

    node = xmlnode_new_child(iq->node, "query");
    xmlnode_new_namespace(node, NULL, NS_IQ_ROSTER);

#if 0
    xmlnode_new_namespace(node, "gr", NS_GOOGLE_ROSTER);
    xmlnode_new_prop(node, "gr:ext", "2");
#endif

    if (iq_request_send(iq) != HYBRID_OK) {

        hybrid_account_error_reason(
                stream->account->account,
                "request roster error.");
        iq_request_destroy(iq);

        return;
    }

    iq_request_destroy(iq);
}
Пример #6
0
/**
 * Client binds a resource.
 */
static void
xmpp_stream_bind(XmppStream *stream)
{
    xmlnode   *node;
    IqRequest *iq;

    g_return_if_fail(stream != NULL);

    iq = iq_request_create(stream, IQ_TYPE_SET);

    node = xmlnode_new_child(iq->node, "bind");
    xmlnode_new_namespace(node, NULL, NS_XMPP_BIND);

    node = xmlnode_new_child(node, "resource");
    xmlnode_set_content(node, "Hybrid.");

    iq_request_set_callback(iq, resource_bind_cb, NULL);

    if (iq_request_send(iq) != HYBRID_OK) {

        hybrid_account_error_reason(
                stream->account->account,
                "binds a resource error.");

        iq_request_destroy(iq);

        return;
    }
    
    iq_request_destroy(iq);
}
Пример #7
0
/**
 * Request the vcard from the server.
 */
static void
xmpp_stream_get_vcard(XmppStream *stream)
{
    xmlnode   *node;
    IqRequest *iq;

    g_return_if_fail(stream != NULL);

    xmpp_stream_iqid_increase(stream);

    iq = iq_request_create(stream, IQ_TYPE_GET);
    //iq_request_set_callback(iq, request_roster_cb, NULL);

    node = xmlnode_new_child(iq->node, "vCard");
    xmlnode_new_namespace(node, NULL, "vcard-temp");

    if (iq_request_send(iq) != HYBRID_OK) {

        hybrid_account_error_reason(
                stream->account->account,
                "request vcard error.");
        iq_request_destroy(iq);

        return;
    }

    iq_request_destroy(iq);
}
Пример #8
0
static gboolean
check_mail(gpointer user_data)
{
    hybrid_imap *imap;
    gchar       *cmd;

    imap = (hybrid_imap*)user_data;

    cmd = g_strdup_printf("A%d STATUS INBOX (UNSEEN)\r\n",
                          imap->current_tag);

    hybrid_debug_info("imap", "send:\n%s", cmd);

    imap_trans_create(imap, check_mail_cb, NULL);

    if (hybrid_ssl_write(imap->ssl, cmd, strlen(cmd)) <= 0) {
        hybrid_account_error_reason(imap->account,
                                    _("IMAP Connection Closed."));
    }

    g_free(cmd);

    if (imap->mail_check_source > 0) {
        g_source_remove(imap->mail_check_source);
        imap->mail_check_source = 0;
    }

    return FALSE;
}
Пример #9
0
/**
 * Ok, TLS handshake success, we will continue the authtication
 * through the established TLS channel.
 */
static gboolean
tls_conn_cb(HybridSslConnection *ssl, XmppStream *stream)
{
    gchar *msg;

    hybrid_account_set_connection_string(stream->account->account,
                                         "TLS connection established.");

    msg = create_initiate_stream(stream);

    /*
     * Reset the stream id, we will start a new stream through 
     * the TLS channel, whether stream id is NULL is the flag 
     * of a new stream.
     */
    xmpp_stream_set_id(stream, NULL);
    xmpp_stream_set_state(stream, XMPP_STATE_TLS_STREAM_STARTING);

    hybrid_debug_info("stream", "send start stream request:\n%s", msg);

    if (hybrid_ssl_write(ssl, msg, strlen(msg)) == -1) {

        hybrid_account_error_reason(stream->account->account,
                "send initial jabber request failed");
        g_free(msg);

        return FALSE;
    }

    g_free(msg);

    return FALSE;
}
Пример #10
0
/**
 * Parse the ssi authentication response string. then we can
 * get the following information: sipuri/mobileno/sid/ssic.
 */
static gint
parse_ssi_response(fetion_account *ac, const gchar *response)
{
    gchar   *prop;
    xmlnode *node;
    xmlnode *root = xmlnode_root(response, strlen(response));

    if (!root) {
        goto ssi_term;
    }

    prop = xmlnode_prop(root, "status-code");
    if (g_strcmp0(prop, "200") != 0) {
        g_free(prop);
        goto ssi_term;
    }

    g_free(prop);

    node = xmlnode_find(root, "user");

    prop = xmlnode_prop(node, "uri");
    fetion_account_set_sipuri(ac, prop);
    g_free(prop);

    if (!ac->sid || *(ac->sid) == '\0') {
        g_free(ac->sid);
        ac->sid = get_sid_from_sipuri(ac->sipuri);
        fetion_sip_set_from(ac->sip, ac->sid);
    }

    prop = xmlnode_prop(node, "mobile-no");
    fetion_account_set_mobileno(ac, prop);
    g_free(prop);

    prop = xmlnode_prop(node, "user-id");
    fetion_account_set_userid(ac, prop);
    g_free(prop);

#if 0
    node = xmlnode_find(root, "credential");
    prop = xmlnode_prop(node, "c");
    fetion_account_set_ssic(ac, prop);
    g_free(prop);
#endif

    return HYBRID_OK;
ssi_term:
    hybrid_account_error_reason(ac->account, _("ssi authencation"));
    xmlnode_free(root);
    return HYBRID_ERROR;
}
Пример #11
0
gboolean
xmpp_stream_init(gint sk, XmppStream *stream)
{
    gchar *msg;

    stream->sk = sk;

    /* send version. */
    msg = "<?xml version='1.0' ?>";

    if (send(sk, msg, strlen(msg), 0) == -1) {

        hybrid_account_error_reason(stream->account->account,
                                    "send initial jabber request failed");

        return FALSE;
    }

    /* send initiate stream request. */
    msg = create_initiate_stream(stream);

    hybrid_debug_info("xmpp", "send initite jabber stream:\n%s", msg);

    if (send(sk, msg, strlen(msg), 0) == -1) {

        hybrid_account_error_reason(stream->account->account,
                                    "send initial jabber request failed");
        g_free(msg);

        return FALSE;
    }

    g_free(msg);

    stream->source = hybrid_event_add(sk, HYBRID_EVENT_READ,
                                      (input_func)stream_recv_cb, stream);

    return FALSE;
}
Пример #12
0
static void
xmpp_stream_process_failure(XmppStream *stream, xmlnode *root)
{
    xmlnode       *node;
    HybridAccount *account;

    account = stream->account->account;
    
    if ((node = xmlnode_find(root, "not-authorized"))) {
        hybrid_account_error_reason(account,
                                    _("Account not authorized."
                                      " Check Username and Password."));
    }
}
Пример #13
0
/**
 * Callback function to handle the sipc reg response.
 */
static gboolean
sipc_reg_cb(gint sk, gpointer user_data)
{
    gchar  buf[BUF_LENGTH];
    gchar *digest;
    gchar *nonce, *key, *aeskey;
    gchar *response;
    gint   n;

    fetion_account *ac = (fetion_account*)user_data;

    if ((n = recv(sk, buf, sizeof(buf), 0)) == -1) {
        hybrid_account_error_reason(ac->account, _("sipc reg error."));
        return FALSE;
    }

    buf[n] = '\0';

    hybrid_debug_info("fetion", "recv:\n%s", buf);

    /* parse response, we need the key and nouce */
    digest = sip_header_get_attr(buf, "W");

    if (parse_sipc_reg_response(digest, &nonce, &key) != HYBRID_OK) {
        g_free(digest);
        return FALSE;
    }

    aeskey = generate_aes_key();

    response = generate_response(nonce, ac->userid, ac->password, key, aeskey);

    /* fill verify_data for pic confirm */
    strncpy(verify_data.response, response, sizeof(verify_data.response));

    /* now we start to handle the pushed messages */
    ac->source = hybrid_event_add(sk, HYBRID_EVENT_READ, hybrid_push_cb, ac);

    /* start sipc authencation action. */
    sipc_aut_action(sk, ac, response);

    g_free(digest);
    g_free(nonce);
    g_free(key);
    g_free(aeskey);
    g_free(response);

    return FALSE;
}
Пример #14
0
/**
 * Start the TLS handshake, if success, jump to the 
 * tls_conn_cb() callback function to send the 
 * stream start request through the TLS channel.
 */
static void
xmpp_stream_performtls(XmppStream *stream)
{

    g_return_if_fail(stream != NULL);

    hybrid_account_set_connection_string(stream->account->account,
                                         "Start performing tls");

    if (!(stream->ssl = hybrid_ssl_connect_with_fd(stream->sk,
                    (ssl_callback)tls_conn_cb, stream))) {

        hybrid_account_error_reason(stream->account->account, 
                _("TLS hand-shake failed."));

        return;
    }
}
Пример #15
0
/**
 * This function starts to register to the sipc server, since we have
 * got the ip address and port from the cfg string in the last step.
 */
static gboolean
sipc_reg_action(gint sk, gpointer user_data)
{
    gchar          *sipmsg;
    gchar          *cnouce = generate_cnouce();
    fetion_account *ac     = (fetion_account*)user_data;
    fetion_sip     *sip    = ac->sip;

    hybrid_debug_info("fetion", "sipc registeration action");

    hybrid_account_set_connection_string(ac->account,
            _("start registering to the sipc server."));

    /* Now we start to register to the sipc server. */
    fetion_sip_set_type(sip, SIP_REGISTER);

    sip_header *cheader = sip_header_create("CN", cnouce);
    sip_header *client  = sip_header_create("CL", "type=\"pc\""
                                            " ,version=\""PROTO_VERSION"\"");

    fetion_sip_add_header(sip, cheader);
    fetion_sip_add_header(sip, client);

    g_free(cnouce);

    sipmsg = fetion_sip_to_string(sip, NULL);

    hybrid_debug_info("fetion", "start registering to sip server(%s:%d)",
            ac->sipc_proxy_ip, ac->sipc_proxy_port);

    hybrid_debug_info("fetion", "send:\n%s", sipmsg);

    if (send(sk, sipmsg, strlen(sipmsg), 0) == -1) {
        hybrid_account_error_reason(ac->account, _("sipc reg error"));
        g_free(sipmsg);
        return FALSE;
    }

    hybrid_event_add(sk, HYBRID_EVENT_READ, sipc_reg_cb, ac);

    g_free(sipmsg);

    return FALSE;
}
Пример #16
0
gint
xmpp_stream_ping(XmppStream *stream)
{
    IqRequest *iq;
    xmlnode   *node;

    g_return_val_if_fail(stream != NULL, HYBRID_ERROR);

    iq = iq_request_create(stream, IQ_TYPE_GET);

    node = xmlnode_new_child(iq->node, "ping");
    xmlnode_new_namespace(node, NULL, NS_XMPP_PING);

    iq_request_set_callback(iq, ping_cb, NULL);
    
    if (stream->keepalive_source) {
        g_source_remove(stream->keepalive_source);
    }

    stream->keepalive_source = 
        g_timeout_add_seconds(60, (GSourceFunc)ping_timeout_cb, stream);

    if (iq_request_send(iq) != HYBRID_OK) {

        hybrid_debug_error("xmpp", "ping xmpp server failed.");

        iq_request_destroy(iq);

        hybrid_account_error_reason(stream->account->account,
                _("Connection Closed."));

        return HYBRID_ERROR;
    }

    iq_request_destroy(iq);

    return HYBRID_OK;
}
Пример #17
0
/**
 * Start a new stream on the sasl layer.
 */
static void
xmpp_stream_new_on_sasl(XmppStream *stream)
{
    gchar *msg;

    g_return_if_fail(stream != NULL);

    msg = create_initiate_stream(stream);

    xmpp_stream_set_id(stream, NULL);
    xmpp_stream_set_state(stream, XMPP_STATE_SASL_STREAM_STARTING);

    hybrid_debug_info("xmpp", "new stream on sasl,send:\n%s", msg);

    if (hybrid_ssl_write(stream->ssl, msg, strlen(msg)) == -1) {
        
        hybrid_account_error_reason(stream->account->account,
                "start new stream on sasl layer error.");
        return;
    }

    g_free(msg);
}
Пример #18
0
static gboolean
ping_cb(XmppStream *stream, xmlnode *node, gpointer user_data)
{
    gchar *value;

    if (xmlnode_has_prop(node, "type")) {
        value = xmlnode_prop(node, "type");

        if (g_strcmp0(value, "result") != 0) {

            hybrid_debug_error("xmpp", "ping xmpp server refused.");

            hybrid_account_error_reason(stream->account->account,
                    _("Connection Closed."));
        }
    }

    if (stream->keepalive_source) {
        g_source_remove(stream->keepalive_source);
        stream->keepalive_source = 0;
    }

    return FALSE;
}
Пример #19
0
/**
 * Callback function to handle the ssi read event. We get the response
 * string from the ssi server here.
 */
static gboolean
ssi_auth_cb(HybridSslConnection *ssl, gpointer user_data)
{
    gchar           buf[BUF_LENGTH];
    gchar          *pos;
    gchar          *pos1;
    gint            ret;
    gint            code;
    fetion_account *ac = (fetion_account*)user_data;

    ret = hybrid_ssl_read(ssl, buf, sizeof(buf));

    if (ret == -1 || ret == 0) {
        hybrid_debug_error("ssi", "ssi server response error");
        return FALSE;
    }

    buf[ret] = '\0';

    hybrid_ssl_connection_destory(ssl);

    hybrid_debug_info("fetion", "recv:\n%s", buf);

    code = hybrid_get_http_code(buf);

    if (421 == code || 420 == code) {            /* confirm code needed. */
        if (HYBRID_ERROR == parse_ssi_fail_resp(ac, buf)) {
            goto ssi_auth_err;
        }

        verify_data.ssl     = ssl;
        verify_data.type = VERIFY_TYPE_SSI;

        hybrid_proxy_connect(NAV_SERVER, 80, pic_download_cb, ac);

        return FALSE;
    }

    if (200 != code) {
        goto ssi_auth_err;
    }

    if (!(pos = strstr(buf, "ssic="))) {
        goto ssi_auth_err;
    }

    pos += 5;

    for (pos1 = pos; *pos1 && *pos1 != ';'; pos1 ++);

    ac->ssic = g_strndup(pos, pos1 - pos);

    if (!(pos = g_strrstr(buf, "\r\n\r\n"))) {
        goto ssi_auth_err;
    }

    pos += 4;

    if (strlen(pos) != hybrid_get_http_length(buf)) {
        goto ssi_auth_err;
    }

    if (parse_ssi_response(ac, pos) != HYBRID_OK) {
        goto ssi_auth_err;
    }

    /*
     * First of all, we load the account's version information from the disk,
     * so that we can use it for authenticating, if the server find the versions
     * are up-to-date, it would return a brief response message in stead of the
     * full version, so that we can use the information store locally. This method
     * makes account logining more faster.
     */
    fetion_config_load_account(ac);

    /* now we will download the configuration */
    hybrid_proxy_connect(NAV_SERVER, 80, cfg_connect_cb, ac);

    return FALSE;

ssi_auth_err:

    hybrid_account_error_reason(ac->account, _("ssi authentication failed"));

    return FALSE;
}
Пример #20
0
/**
 * Callback function to handle the pushed message.
 */
gboolean
hybrid_push_cb(gint sk, gpointer user_data)
{
    gchar           sipmsg[BUF_LENGTH];
    gchar          *pos;
    gchar          *h;
    gchar          *msg;
    fetion_account *ac = (fetion_account*)user_data;
    gint            n;
    guint           len, data_len;

    if ((n = recv(sk, sipmsg, sizeof(sipmsg), 0)) == -1) {
        hybrid_account_error_reason(ac->account, _("connection terminated"));
        return FALSE;
    } else if (0 == n) {
        hybrid_debug_info("fetion", "hybrid_push_cb in fetion received 0 bytes,"
                          "connection closed.");
        channel_list = g_slist_remove(channel_list, ac);
        fetion_account_destroy(ac);
        close(sk);
        return FALSE;
    }

    sipmsg[n] = '\0';

    data_len = ac->buffer ? strlen(ac->buffer) : 0;
    ac->buffer = (gchar*)realloc(ac->buffer, data_len + n + 1);
    memcpy(ac->buffer + data_len, sipmsg, n + 1);

recheck:
    data_len = ac->buffer ? strlen(ac->buffer) : 0;

    if ((pos = strstr(ac->buffer, "\r\n\r\n"))) {
        pos += 4;
        h = (gchar*)g_malloc0(data_len - strlen(pos) + 1);
        memcpy(h, ac->buffer, data_len - strlen(pos));
        h[data_len - strlen(pos)] = '\0';

        if (strstr(h, "L: ")) {
            len = fetion_sip_get_length(ac->buffer);

            if (len <= strlen(pos)) {
                msg = (gchar*)g_malloc0(strlen(h) + len + 1);
                memcpy(msg, ac->buffer, strlen(h) + len);
                msg[strlen(h) + len] = '\0';
                /* A message is complete, process it. */
                process_pushed(ac, msg);

                memmove(ac->buffer, ac->buffer + strlen(msg), data_len - strlen(msg));
                ac->buffer = (gchar*)realloc(ac->buffer, data_len - strlen(msg) + 1);
                ac->buffer[data_len - strlen(msg)] = '\0';

                g_free(msg);
                g_free(h);
                msg = NULL;
                h = NULL;

                goto recheck;
            }

        } else {
            /* A message is complete, process it. */
            process_pushed(ac, h);

            memmove(ac->buffer, ac->buffer + strlen(h), data_len - strlen(h));
            ac->buffer = (gchar*)realloc(ac->buffer, data_len - strlen(h) + 1);
            ac->buffer[data_len - strlen(h)] = '\0';

            g_free(h);
            h = NULL;
            goto recheck;
        }
        g_free(h);
    }

    return TRUE;
}
Пример #21
0
/**
 * Callback function to handle the read event after
 * rendered sipc authentication.
 */
static gint
sipc_auth_cb(fetion_account *ac, const gchar *sipmsg,
             fetion_transaction *trans)
{
    gint   code;
    gint   length;
    gchar *pos;

    code = fetion_sip_get_code(sipmsg);

    hybrid_debug_info("fetion", "sipc recv:\n%s", sipmsg);

    if (code == FETION_SIP_OK) { /**< ok, we got the contact list */

        /* update the portrait. */
        fetion_account_update_portrait(ac);

        length = fetion_sip_get_length(sipmsg);
        pos = strstr(ac->buffer, "\r\n\r\n") + 4;

        parse_sipc_resp(ac, pos, length);

        /* set the nickname of the hybrid account. */
        hybrid_account_set_nickname(ac->account, ac->nickname);

        /* set the mood phrase of the hybrid account. */
        hybrid_account_set_status_text(ac->account, ac->mood_phrase);

        hybrid_account_set_state(ac->account, HYBRID_STATE_INVISIBLE);

        /* set the connection status. */
        hybrid_account_set_connection_status(ac->account,
                HYBRID_CONNECTION_CONNECTED);

        /* init group list */
        fetion_groups_init(ac);

        /* init buddy list */
        fetion_buddies_init(ac);

        /* start scribe the pushed msg */
        fetion_buddy_scribe(ac);

    } else if (420 == code || 421 == code) {

        if (HYBRID_ERROR == parse_sipc_verification(ac, sipmsg)) {
            hybrid_account_error_reason(ac->account,
                                        _("Fetion Protocol ERROR."));
            return FALSE;
        }

        hybrid_debug_error("fetion", "sipc authentication need Verification.");

        verify_data.sipc_conn = ac->sk;
        verify_data.type      = VERIFY_TYPE_SIP;

        hybrid_proxy_connect(NAV_SERVER, 80, pic_download_cb, ac);

        g_free(ac->buffer);
        ac->buffer = NULL;

        return HYBRID_OK;
    } else {
        g_free(ac->buffer);
        ac->buffer = NULL;

        return HYBRID_ERROR;
    }

    return HYBRID_ERROR;
}
Пример #22
0
/**
 * Start sasl authentication.
 */
static void
xmpp_stream_startsasl(XmppStream *stream)
{
    guchar  *auth;
    gchar   *auth_encoded;
    gchar   *xml_string;
    gint     username_len;
    gint     password_len;
    xmlnode *node;

    g_return_if_fail(stream != NULL);

    hybrid_debug_info("xmpp", "start sasl authentication.");

    hybrid_account_set_connection_string(stream->account->account,
                                         "Start sasl authentication.");

    xmpp_stream_set_state(stream, XMPP_STATE_SASL_AUTHENTICATING);
    /*
     * construct the authentication string to be base64 encoded,
     * which is in form of '\0 + username + \0 + password '
     */
    username_len = strlen(stream->account->username);
    password_len = strlen(stream->account->password);

    auth = g_malloc0(username_len + password_len + 2);

    auth[0] = '\0';
    memcpy(auth + 1, stream->account->username, username_len);

    auth[username_len + 1] = '\0';
    memcpy(auth + 2 + username_len, stream->account->password,
            password_len);

    auth_encoded = hybrid_base64_encode(auth, username_len + password_len + 2);

    g_free(auth);

    /* construct the xml string, which is in form of:
     *
     * <auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" 
     * mechanism="PLAIN">encoded sasl string</auth> 
     */
    node = xmlnode_create("auth");

    xmlnode_new_namespace(node, NULL, NS_XMPP_SASL);
    xmlnode_new_namespace(node, "ga", "http://www.google.com/talk/protocol/auth");
    xmlnode_new_prop(node, "ga:client-uses-full-bind-result", "true");
    xmlnode_new_prop(node, "mechanism", "PLAIN");
    xmlnode_set_content(node, auth_encoded);

    g_free(auth_encoded);
    
    xml_string = xmlnode_to_string(node);
    xmlnode_free(node);

    hybrid_debug_info("xmpp", "sasl send:\n%s", xml_string);

    if (hybrid_ssl_write(stream->ssl, xml_string,
                strlen(xml_string)) == -1) {

        hybrid_account_error_reason(stream->account->account,
                "SASL authentication error.");

        return;
    }

    g_free(xml_string);

}
Пример #23
0
/**
 * Callback function to handle the cfg read event.
 */
static gboolean
cfg_read_cb(gint sk, gpointer user_data)
{
    gchar           buf[BUF_LENGTH];
    gint            n;
    gint            length = 0;
    gchar          *pos;
    fetion_account *ac     = (fetion_account*)user_data;

    if ((n = recv(sk, buf, sizeof(buf), 0)) == -1) {
        hybrid_account_error_reason(ac->account, _("read cfg failed"));
        return FALSE;
    }

    buf[n] = '\0';

    if (n != 0) {

        /* larger the recv buffer, and copy the new
         * received bytes to the buffer */
        length = ac->buffer ? strlen(ac->buffer) : 0;
        ac->buffer = g_realloc(ac->buffer, length + n + 1);
        memcpy(ac->buffer + length, buf, n + 1);

        return TRUE;

    } else { /* receive complete, start process */

        if (hybrid_get_http_code(ac->buffer) != 200) {
            goto error;
        }

        hybrid_debug_info("fetion", "cfg recv:\n%s", ac->buffer);

        if (!(pos = g_strrstr(ac->buffer, "\r\n\r\n"))) {
            goto error;
        }

        pos += 4;

        if (strlen(pos) != hybrid_get_http_length(ac->buffer)) {
            goto error;
        }

        if (parse_configuration(ac, pos) != HYBRID_OK) {
            g_free(ac->buffer);
            ac->buffer = NULL;
            goto error;
        }

        g_free(ac->buffer);
        ac->buffer = NULL;

        /* now we start sipc register */

        hybrid_proxy_connect(ac->sipc_proxy_ip, ac->sipc_proxy_port,
                sipc_reg_action, ac);
    }

    return FALSE;
error:
    hybrid_account_error_reason(ac->account, _("read cfg failed"));
    return FALSE;
}
Пример #24
0
static gboolean
pic_read_cb(gint sk, gpointer user_data)
{
    gint     n, len;
    gchar    sipmsg[BUF_LENGTH];
    gchar   *code, *pos;
    guchar  *pic;
    gint     piclen;
    xmlnode *root;
    xmlnode *node;

    fetion_account *ac = (fetion_account*)user_data;

    len    = ac->buffer ? strlen(ac->buffer) : 0;

    if((n = recv(sk, sipmsg, strlen(sipmsg), 0)) == -1) {
        return -1;
    }

    sipmsg[n] = 0;

    if(n == 0) {
           g_source_remove(ac->source);
        ac->source = 0;
        close(sk);

        if(! ac->buffer) {
            return 0;
        }

        hybrid_debug_info("fetion", "read message resp:\n%s", ac->buffer);

        if (200 != hybrid_get_http_code(ac->buffer)) {
            goto read_pic_err;
        }

        if(!(pos = strstr(ac->buffer, "\r\n\r\n"))) {
            goto read_pic_err;
        }

        pos += 4;

        if (!(root = xmlnode_root(pos, strlen(pos)))) {
            goto read_pic_err;
        }

        if (!(node = xmlnode_find(root, "pic-certificate"))) {
            xmlnode_free(root);
            goto read_pic_err;
        }

        if (!xmlnode_has_prop(node, "id") || !xmlnode_has_prop(node, "pic")) {
            xmlnode_free(root);
            goto read_pic_err;
        }

        ac->verification->guid = xmlnode_prop(node, "id");
        code                   = xmlnode_prop(node, "pic");

        pic = hybrid_base64_decode(code, &piclen);

        hybrid_confirm_window_create(ac->account, pic, piclen,
                                     pic_code_ok_cb, pic_code_cancel_cb, ac);

        g_free(code);
        g_free(pic);
        xmlnode_free(root);
        g_free(ac->buffer);
        ac->buffer = (gchar*)0;

        return FALSE;
    }

    ac->buffer = (gchar*)realloc(ac->buffer, len + n + 1);
    memcpy(ac->buffer + len, sipmsg, n + 1);

    return TRUE;

 read_pic_err:
    hybrid_debug_error("fetion", "read pic code error.");

    g_free(ac->buffer);
    ac->buffer = (gchar *)0;

    hybrid_account_error_reason(ac->account, _("read pic code error."));
    return FALSE;
}