Esempio n. 1
0
static void _log_open_tag(xmpp_conn_t *conn, char **attrs)
{
    char buf[4096];
    size_t pos;
    int len;
    int i;
    
    if (!attrs) return;

    pos = 0;
    len = xmpp_snprintf(buf, 4096, "<stream:stream");
    if (len < 0) return;
    
    pos += len;
    
    for (i = 0; attrs[i]; i += 2) {
        len = xmpp_snprintf(&buf[pos], 4096 - pos, " %s='%s'",
                            attrs[i], attrs[i+1]);
        if (len < 0) return;
        pos += len;
    }

    len = xmpp_snprintf(&buf[pos], 4096 - pos, ">");
    if (len < 0) return;

    xmpp_debug(conn->ctx, "xmpp", "RECV: %s", buf);
}
Esempio n. 2
0
/* Will compute SHA1 and authenticate the component to the server */
int _handle_component_auth(xmpp_conn_t * const conn)
{
    uint8_t md_value[SHA1_DIGEST_SIZE];
    SHA1_CTX mdctx;
    char *digest;
    size_t i;

    if (conn->stream_id == NULL) {
        xmpp_error(conn->ctx, "auth", "Received no stream id from the server.");
        return XMPP_EINT;
    }

    /* Feed the session id and passphrase to the algorithm.
     * We need to compute SHA1(session_id + passphrase)
     */
    crypto_SHA1_Init(&mdctx);
    crypto_SHA1_Update(&mdctx, (uint8_t*)conn->stream_id,
                       strlen(conn->stream_id));
    crypto_SHA1_Update(&mdctx, (uint8_t*)conn->pass, strlen(conn->pass));
    crypto_SHA1_Final(&mdctx, md_value);

    digest = xmpp_alloc(conn->ctx, 2*sizeof(md_value)+1);
    if (digest) {
        /* convert the digest into string representation */
        for (i = 0; i < sizeof(md_value); i++)
            xmpp_snprintf(digest+i*2, 3, "%02x", md_value[i]);
        digest[2*sizeof(md_value)] = '\0';

        xmpp_debug(conn->ctx, "auth", "Digest: %s, len: %d",
                   digest, strlen(digest));

        /* Send the digest to the server */
        xmpp_send_raw_string(conn, "<handshake xmlns='%s'>%s</handshake>",
                             XMPP_NS_COMPONENT, digest);
        xmpp_debug(conn->ctx, "auth", "Sent component handshake to the server.");
        xmpp_free(conn->ctx, digest);
    } else {
        xmpp_debug(conn->ctx, "auth", "Couldn't allocate memory for component "\
                                      "handshake digest.");
        return XMPP_EMEM;
    }

    return 0;
}
Esempio n. 3
0
static char *_make_scram_sha1_init_msg(xmpp_conn_t * const conn)
{
    size_t message_len;
    char *node;
    char *message;
    char nonce[32];

    node = xmpp_jid_node(conn->ctx, conn->jid);
    if (!node) {
        return NULL;
    }
    xmpp_rand_nonce(conn->ctx, nonce, sizeof(nonce));
    message_len = strlen(node) + strlen(nonce) + 8 + 1;
    message = xmpp_alloc(conn->ctx, message_len);
    if (message) {
        xmpp_snprintf(message, message_len, "n,,n=%s,r=%s", node, nonce);
    }
    xmpp_free(conn->ctx, node);

    return message;
}
Esempio n. 4
0
/* always returns number of bytes written or that would have been
 * written if the buffer was large enough
 * return values < 0 indicate some error occurred,
 * and return values > buflen indicate buffer was not large enough
 */
static int _render_stanza_recursive(xmpp_stanza_t *stanza,
                             char * const buf, size_t const buflen)
{
    char *ptr = buf;
    size_t left = buflen;
    int ret, written;
    xmpp_stanza_t *child;
    hash_iterator_t *iter;
    const char *key;
    char *tmp;

    written = 0;

    if (stanza->type == XMPP_STANZA_UNKNOWN) return XMPP_EINVOP;

    if (stanza->type == XMPP_STANZA_TEXT) {
        if (!stanza->data) return XMPP_EINVOP;

        tmp = _escape_xml(stanza->ctx, stanza->data);
        if (tmp == NULL) return XMPP_EMEM;
        ret = xmpp_snprintf(ptr, left, "%s", tmp);
        xmpp_free(stanza->ctx, tmp);
        if (ret < 0) return XMPP_EMEM;
        _render_update(&written, buflen, ret, &left, &ptr);
    } else { /* stanza->type == XMPP_STANZA_TAG */
        if (!stanza->data) return XMPP_EINVOP;

        /* write beginning of tag and attributes */
        ret = xmpp_snprintf(ptr, left, "<%s", stanza->data);
        if (ret < 0) return XMPP_EMEM;
        _render_update(&written, buflen, ret, &left, &ptr);

        if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) {
            iter = hash_iter_new(stanza->attributes);
            while ((key = hash_iter_next(iter))) {
                if (!strcmp(key, "xmlns")) {
                    /* don't output namespace if parent stanza is the same */
                    if (stanza->parent &&
                        stanza->parent->attributes &&
                        hash_get(stanza->parent->attributes, key) &&
                        !strcmp((char*)hash_get(stanza->attributes, key),
                            (char*)hash_get(stanza->parent->attributes, key)))
                        continue;
                    /* or if this is the stream namespace */
                    if (!stanza->parent &&
                        !strcmp((char*)hash_get(stanza->attributes, key),
                            XMPP_NS_CLIENT))
                        continue;
                }
                tmp = _escape_xml(stanza->ctx,
                    (char *)hash_get(stanza->attributes, key));
                if (tmp == NULL) return XMPP_EMEM;
                ret = xmpp_snprintf(ptr, left, " %s=\"%s\"", key, tmp);
                xmpp_free(stanza->ctx, tmp);
                if (ret < 0) return XMPP_EMEM;
                _render_update(&written, buflen, ret, &left, &ptr);
            }
            hash_iter_release(iter);
        }

        if (!stanza->children) {
            /* write end if singleton tag */
            ret = xmpp_snprintf(ptr, left, "/>");
            if (ret < 0) return XMPP_EMEM;
            _render_update(&written, buflen, ret, &left, &ptr);
        } else {
            /* this stanza has child stanzas */

            /* write end of start tag */
            ret = xmpp_snprintf(ptr, left, ">");
            if (ret < 0) return XMPP_EMEM;
            _render_update(&written, buflen, ret, &left, &ptr);

            /* iterate and recurse over child stanzas */
            child = stanza->children;
            while (child) {
                ret = _render_stanza_recursive(child, ptr, left);
                if (ret < 0) return ret;

                _render_update(&written, buflen, ret, &left, &ptr);

                child = child->next;
            }

            /* write end tag */
            ret = xmpp_snprintf(ptr, left, "</%s>", stanza->data);
            if (ret < 0) return XMPP_EMEM;

            _render_update(&written, buflen, ret, &left, &ptr);
        }
    }

    return written;
}
Esempio n. 5
0
/* always returns number of bytes written or that would have been
 * written if the buffer was large enough
 * return values < 0 indicate some error occured,
 * and return values > buflen indicate buffer was not large enough
 */
static int _render_stanza_recursive(xmpp_stanza_t *stanza,
			     char * const buf, size_t const buflen)
{
    char *ptr = buf;
    size_t left = buflen;
    int ret, written;
    xmpp_stanza_t *child;
    hash_iterator_t *iter;
    const char *key;

    assert(stanza);

    written = 0;

    if (stanza->type == XMPP_STANZA_UNKNOWN) return XMPP_EINVOP;

    if (stanza->type == XMPP_STANZA_TEXT) {
	if (!stanza->data) return XMPP_EINVOP;

        assert(stanza->data);
	ret = xmpp_snprintf(ptr, left, "%s", stanza->data);
	if (ret < 0) return XMPP_EMEM;
	_render_update(&written, buflen, ret, &left, &ptr);
    } else { /* stanza->type == XMPP_STANZA_TAG */
	if (!stanza->data) return XMPP_EINVOP;

	/* write begining of tag and attributes */
        assert(stanza->data);
	ret = xmpp_snprintf(ptr, left, "<%s", stanza->data);
	if (ret < 0) return XMPP_EMEM;
	_render_update(&written, buflen, ret, &left, &ptr);

	if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) {
	    iter = hash_iter_new(stanza->attributes);
	    while ((key = hash_iter_next(iter))) {
                assert(hash_get(stanza->attributes, key));
		ret = xmpp_snprintf(ptr, left, " %s=\"%s\"", key,
			       (char *)hash_get(stanza->attributes, key));
		if (ret < 0) return XMPP_EMEM;
		_render_update(&written, buflen, ret, &left, &ptr);
	    }
	    hash_iter_release(iter);
	}

	if (!stanza->children) {
	    /* write end if singleton tag */
	    ret = xmpp_snprintf(ptr, left, "/>");
	    if (ret < 0) return XMPP_EMEM;
	    _render_update(&written, buflen, ret, &left, &ptr);
	} else {
	    /* this stanza has child stanzas */

	    /* write end of start tag */
	    ret = xmpp_snprintf(ptr, left, ">");
	    if (ret < 0) return XMPP_EMEM;
	    _render_update(&written, buflen, ret, &left, &ptr);

	    /* iterate and recurse over child stanzas */
	    child = stanza->children;
	    while (child) {
		ret = _render_stanza_recursive(child, ptr, left);
		if (ret < 0) return ret;

		_render_update(&written, buflen, ret, &left, &ptr);

		child = child->next;
	    }

	    /* write end tag */
            assert(stanza->data);
	    ret = xmpp_snprintf(ptr, left, "</%s>", stanza->data);
	    if (ret < 0) return XMPP_EMEM;

	    _render_update(&written, buflen, ret, &left, &ptr);
	}
    }

    return written;
}
Esempio n. 6
0
/** generate auth response string for the SASL SCRAM-SHA-1 mechanism */
char *sasl_scram_sha1(xmpp_ctx_t *ctx, const char *challenge,
                      const char *first_bare, const char *jid,
                      const char *password)
{
    uint8_t key[SHA1_DIGEST_SIZE];
    uint8_t sign[SHA1_DIGEST_SIZE];
    char *r = NULL;
    char *s = NULL;
    char *i = NULL;
    unsigned char *sval;
    size_t sval_len;
    long ival;
    char *tmp;
    char *ptr;
    char *saveptr = NULL;
    char *response;
    char *auth;
    char *response_b64;
    char *sign_b64;
    char *result = NULL;
    size_t response_len;
    size_t auth_len;
    int j;

    tmp = xmpp_strdup(ctx, challenge);
    if (!tmp) {
        return NULL;
    }

    ptr = strtok_r(tmp, ",", &saveptr);
    while (ptr) {
        if (strncmp(ptr, "r=", 2) == 0) {
            r = ptr;
        } else if (strncmp(ptr, "s=", 2) == 0) {
            s = ptr + 2;
        } else if (strncmp(ptr, "i=", 2) == 0) {
            i = ptr + 2;
        }
        ptr = strtok_r(NULL, ",", &saveptr);
    }

    if (!r || !s || !i) {
        goto out;
    }

    xmpp_base64_decode_bin(ctx, s, strlen(s), &sval, &sval_len);
    if (!sval) {
        goto out;
    }
    ival = strtol(i, &saveptr, 10);

    auth_len = 10 + strlen(r) + strlen(first_bare) + strlen(challenge);
    auth = xmpp_alloc(ctx, auth_len);
    if (!auth) {
        goto out_sval;
    }

    response_len = 39 + strlen(r);
    response = xmpp_alloc(ctx, response_len);
    if (!response) {
        goto out_auth;
    }

    xmpp_snprintf(response, response_len, "c=biws,%s", r);
    xmpp_snprintf(auth, auth_len, "%s,%s,%s", first_bare + 3, challenge,
                  response);

    SCRAM_SHA1_ClientKey((uint8_t *)password, strlen(password),
                         (uint8_t *)sval, sval_len, (uint32_t)ival, key);
    SCRAM_SHA1_ClientSignature(key, (uint8_t *)auth, strlen(auth), sign);
    for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
        sign[j] ^= key[j];
    }

    sign_b64 = xmpp_base64_encode(ctx, sign, sizeof(sign));
    if (!sign_b64) {
        goto out_response;
    }

    if (strlen(response) + strlen(sign_b64) + 3 + 1 > response_len) {
        xmpp_free(ctx, sign_b64);
        goto out_response;
    }
    strcat(response, ",p=");
    strcat(response, sign_b64);
    xmpp_free(ctx, sign_b64);

    response_b64 = xmpp_base64_encode(ctx, (unsigned char *)response,
                                      strlen(response));
    if (!response_b64) {
        goto out_response;
    }
    result = response_b64;

out_response:
    xmpp_free(ctx, response);
out_auth:
    xmpp_free(ctx, auth);
out_sval:
    xmpp_free(ctx, sval);
out:
    xmpp_free(ctx, tmp);
    return result;
}