示例#1
0
文件: broker.c 项目: ghalwasi/c-mlib
static
void handle_conn(Broker *broker, HttpRequest *req, Socket *sock) {
    json_error_t err;

    json_t *body;
    {
        const char *start = strchr(req->body, '{');
        const char *end = strrchr(req->body, '}');
        if (!(start && end)) {
            goto exit;
        }
        body = json_loadb(start, end - start + 1, 0, &err);
        if (!body) {
            broker_send_internal_error(sock);
            goto exit;
        }
    }

    const char *dsId = broker_http_param_get(&req->uri, "dsId");
    if (!dsId) {
        goto exit;
    }
    log_info("%s connecting \n", dsId);
    const char *token = broker_http_param_get(&req->uri, "token");
    json_t *resp = broker_handshake_handle_conn(broker, dsId, token, body);
    json_decref(body);
    if (!resp) {
        broker_send_internal_error(sock);
        goto exit;
    }

    char *data = json_dumps(resp, JSON_INDENT(2));
    json_decref(resp);
    if (!data) {
        broker_send_internal_error(sock);
        goto exit;
    }

    char buf[1024];
    int len = snprintf(buf, sizeof(buf) - 1,
                       CONN_RESP, (int) strlen(data), data);
    buf[len] = '\0';
    dslink_free(data);
    dslink_socket_write(sock, buf, (size_t) len);

exit:
    return;
}
示例#2
0
static
ssize_t want_write_cb(wslay_event_context_ptr ctx,
                      const uint8_t *data, size_t len,
                      int flags, void *user_data) {
    (void) flags;

    DSLink *link = user_data;
    int written = dslink_socket_write(link->_socket, (char *) data, len);
    if (written < 0) {
        if (errno == MBEDTLS_ERR_SSL_WANT_WRITE) {
            wslay_event_set_error(ctx, WSLAY_ERR_WANT_WRITE);
        } else {
            wslay_event_set_error(ctx, WSLAY_ERR_CALLBACK_FAILURE);
        }
        return -1;
    }

    return written;
}
示例#3
0
int dslink_handshake_connect_ws(Url *url,
                                mbedtls_ecdh_context *key,
                                const char *uri,
                                const char *tempKey,
                                const char *salt,
                                const char *dsId,
                                Socket **sock) {
    *sock = NULL;
    int ret = 0;
    unsigned char auth[90];
    if ((ret = gen_auth_key(key, tempKey, salt,
                            auth, sizeof(auth))) != 0) {
        goto exit;
    }

    char req[512];
    size_t reqLen;
    {
        char builtUri[256];
        snprintf(builtUri, sizeof(builtUri) - 1, "%s?auth=%s&dsId=%s",
                 uri, auth, dsId);

        char wsKey[32];
        if ((ret = gen_ws_key(wsKey, sizeof(wsKey))) != 0) {
            goto exit;
        }

        reqLen = snprintf(req, sizeof(req), DSLINK_WS_REQ,
                          builtUri, url->host, url->port, wsKey);
    }

    if ((ret = dslink_socket_connect(sock, url->host,
                                     url->port, url->secure)) != 0) {
        *sock = NULL;
        goto exit;
    }

    dslink_socket_write(*sock, req, reqLen);

    char buf[1024];
    size_t len = 0;
    memset(buf, 0, sizeof(buf));
    while (len < (sizeof(buf) - 1)) {
        // Read 1 byte at a time to ensure that we don't accidentally
        // read web socket data
        int read = dslink_socket_read(*sock, buf + len, 1);
        if (read <= 0) {
            goto exit;
        }
        if (buf[len++] == '\n' && strstr(buf, "\r\n\r\n")) {
            if (!strstr(buf, "101 Switching Protocols")) {
                ret = DSLINK_HANDSHAKE_INVALID_RESPONSE;
            } if (strstr(buf, "401 Unauthorized")) {
                ret = DSLINK_HANDSHAKE_UNAUTHORIZED;
            }
            goto exit;
        }
    }

    // Failed to find the end of the HTTP response
    ret = DSLINK_HANDSHAKE_INVALID_RESPONSE;
exit:
    if (ret != 0 && *sock) {
        dslink_socket_close(*sock);
        *sock = NULL;
    }
    return ret;
}
示例#4
0
int dslink_handshake_generate(Url *url,
                              mbedtls_ecdh_context *key,
                              const char *name,
                              uint8_t isRequester,
                              uint8_t isResponder,
                              json_t **handshake,
                              char **dsId) {
    *handshake = NULL;
    Socket *sock = NULL;
    char *resp = NULL;
    char *body = NULL;
    int ret = 0;

    unsigned char pubKeyBin[65];
    size_t pubKeyBinLen = 0;

    unsigned char pubKey[90];
    size_t pubKeyLen = 0;

    if ((errno = mbedtls_ecp_point_write_binary(&key->grp,
                                                &key->Q,
                                                MBEDTLS_ECP_PF_UNCOMPRESSED,
                                                &pubKeyBinLen, pubKeyBin,
                                                sizeof(pubKeyBin))) != 0) {
        ret = DSLINK_CRYPT_KEY_ENCODE_ERR;
        goto exit;
    }

    if ((errno = dslink_base64_url_encode(pubKey,
                                          sizeof(pubKey),
                                          &pubKeyLen,
                                          pubKeyBin,
                                          pubKeyBinLen)) != 0) {
        ret = DSLINK_CRYPT_BASE64_URL_ENCODE_ERR;
        goto exit;
    }

    { // Generate dsId
        unsigned char sha[32];
        mbedtls_sha256(pubKeyBin, pubKeyBinLen, sha, 0);

        unsigned char tmp[45];
        size_t tmpLen = 0;
        if ((errno = dslink_base64_url_encode((unsigned char *) tmp,
                                              sizeof(tmp),
                                              &tmpLen,
                                              sha,
                                              sizeof(sha))) != 0) {
            ret = DSLINK_CRYPT_BASE64_URL_ENCODE_ERR;
            goto exit;
        }

        size_t nameLen = strlen(name);
        *dsId = malloc(nameLen + tmpLen + 2);
        if (!(*dsId)) {
            ret = DSLINK_ALLOC_ERR;
            goto exit;
        }
        memcpy(*dsId, name, nameLen);
        *(*dsId + nameLen) = '-';
        memcpy((*dsId + nameLen + 1), (char *) tmp, tmpLen);
        *(*dsId + nameLen + tmpLen + 1) = '\0';
    }

    { // Create the request body
        json_t *obj = json_object();
        if (!obj) {
            ret = DSLINK_ALLOC_ERR;
            goto exit;
        }

        json_object_set_new(obj, "publicKey", json_string((char *) pubKey));
        json_object_set_new(obj, "isRequester", json_boolean(isRequester));
        json_object_set_new(obj, "isResponder", json_boolean(isResponder));
        json_object_set_new(obj, "version", json_string("1.1.2"));
        body = json_dumps(obj, JSON_INDENT(2));
        json_delete(obj);
        if (!body) {
            ret = DSLINK_ALLOC_ERR;
            goto exit;
        }
    }

    char req[512];
    size_t reqLen;
    {
        char uri[128];
        snprintf(uri, sizeof(uri), "%s?dsId=%s", url->uri, *dsId);
        reqLen = snprintf(req, sizeof(req), DSLINK_POST_REQ, uri, url->host,
                          url->port, (int) strlen(body), body);
    }

    if ((ret = dslink_socket_connect(&sock, url->host,
                                     url->port, url->secure)) != 0) {
        goto exit;
    }

    dslink_socket_write(sock, req, reqLen);

    int respLen = 0;
    while (1) {
        char buf[1024];
        int read = dslink_socket_read(sock, buf, sizeof(buf) - 1);
        if (read <= 0) {
            break;
        }
        if (resp == NULL) {
            resp = malloc((size_t) read + 1);
            if (!resp) {
                ret = DSLINK_ALLOC_ERR;
                goto exit;
            }
            respLen = read;
            memcpy(resp, buf, read);
            *(resp + respLen) = '\0';
        } else {
            char *tmp = realloc(resp, (size_t) respLen + read + 1);
            if (!tmp) {
                free(resp);
                ret = DSLINK_ALLOC_ERR;
                goto exit;
            }
            resp = tmp;
            memcpy(resp + respLen, buf, read);
            respLen += read;
            *(resp + respLen) = '\0';
        }
    }

    if (!resp) {
        ret = DSLINK_HANDSHAKE_NO_RESPONSE;
        goto exit;
    }

    char *index = strstr(resp, "401 Unauthorized");
    if (index) {
        ret = DSLINK_HANDSHAKE_UNAUTHORIZED;
        goto exit;
    }

    index = strchr(resp, '{');
    if (!index) {
        ret = DSLINK_HANDSHAKE_INVALID_RESPONSE;
        goto exit;
    }

    char *json = index;
    index = strrchr(json, '}');
    if (!index) {
        ret = DSLINK_HANDSHAKE_INVALID_RESPONSE;
        goto exit;
    }
    *(index + 1) = '\0';

    json_error_t jsonErr;
    *handshake = json_loads(json, 0, &jsonErr);
    if (!(*handshake)) {
        ret = DSLINK_ALLOC_ERR;
        goto exit;
    }
    const char *id = json_string_value(json_object_get(*handshake, "id"));
    if (id) {
        free(*dsId);
        size_t size = strlen(id) + 1;
        *dsId = malloc(size);
        if (!(*dsId)) {
            ret = DSLINK_ALLOC_ERR;
            json_delete(*handshake);
            *handshake = NULL;
            goto exit;
        }
        memcpy(*dsId, id, size);
    }

exit:
    DSLINK_CHECKED_EXEC(free, body);
    DSLINK_CHECKED_EXEC(free, resp);
    DSLINK_CHECKED_EXEC(dslink_socket_close, sock);
    return ret;
}