Пример #1
0
/**
 * Called to retrive the mechlist from the packet.
 * @return 0 to continue authentication, 1 if no authentication needed, or
 * -1 on error.
 */
static int
set_chosen_mech(mc_pSESSREQ sreq, lcb_string *mechlist, const char **data,
                unsigned int *ndata)
{
    cbsasl_error_t saslerr;
    const char *chosenmech;
    mc_pSESSINFO ctx = sreq->inner;

    lcb_assert(sreq->inner);
    if (ctx->settings->sasl_mech_force) {
        char *forcemech = ctx->settings->sasl_mech_force;
        if (!strstr(mechlist->base, forcemech)) {
            /** Requested mechanism not found */
            set_error_ex(sreq, LCB_SASLMECH_UNAVAILABLE, mechlist->base);
            return -1;
        }

        lcb_string_clear(mechlist);
        if (lcb_string_appendz(mechlist, forcemech)) {
            set_error_ex(sreq, LCB_CLIENT_ENOMEM, NULL);
            return -1;
        }
    }

    saslerr = cbsasl_client_start(ctx->sasl, mechlist->base,
                                  NULL, data, ndata, &chosenmech);
    switch (saslerr) {
    case SASL_OK:
        ctx->nmech = strlen(chosenmech);
        if (! (ctx->mech = strdup(chosenmech)) ) {
            set_error_ex(sreq, LCB_CLIENT_ENOMEM, NULL);
            return -1;
        }
        return 0;
    case SASL_NOMECH:
        lcb_log(LOGARGS(sreq, INFO), SESSREQ_LOGFMT "Server does not support SASL (no mechanisms supported)", SESSREQ_LOGID(sreq));
        return 1;
        break;
    default:
        lcb_log(LOGARGS(sreq, INFO), SESSREQ_LOGFMT "cbsasl_client_start returned %d", SESSREQ_LOGID(sreq), saslerr);
        set_error_ex(sreq, LCB_EINTERNAL, "Couldn't start SASL client");
        return -1;
    }
}
Пример #2
0
static void sasl_list_mech_response_handler(lcb_server_t *server,
                                            struct lcb_command_data_st *command_data,
                                            protocol_binary_response_header *res)
{
    const char *chosenmech;
    char *mechlist;
    const char *data;
    unsigned int ndata;
    protocol_binary_request_no_extras req;
    lcb_size_t bodysize;
    lcb_uint16_t ret = ntohs(res->response.status);
    lcb_connection_t conn = &server->connection;

    if (ret != PROTOCOL_BINARY_RESPONSE_SUCCESS) {
        lcb_error_handler(server->instance, LCB_AUTH_ERROR,
                          "SASL authentication failed: "
                          "bad SASL_LIST_MECH status code");
        return;
    }

    bodysize = ntohl(res->response.bodylen);
    mechlist = calloc(bodysize + 1, sizeof(char));
    if (mechlist == NULL) {
        lcb_error_handler(server->instance, LCB_CLIENT_ENOMEM, NULL);
        return;
    }
    memcpy(mechlist, (const char *)(res + 1), bodysize);

    if (server->instance->sasl_mech_force) {
        if (!strstr(mechlist, server->instance->sasl_mech_force)) {
            lcb_error_handler(server->instance, LCB_SASLMECH_UNAVAILABLE,
                              mechlist);
            free(mechlist);
            return;
        }

        /** strstr already ensures we have enough space */
        strcpy(mechlist, server->instance->sasl_mech_force);
    }

    if (cbsasl_client_start(server->sasl_conn, mechlist,
                          NULL, &data, &ndata, &chosenmech) != SASL_OK) {
        free(mechlist);
        lcb_error_handler(server->instance, LCB_AUTH_ERROR,
                          "Unable to start sasl client");
        return;
    }
    free(mechlist);

    server->sasl_nmech = strlen(chosenmech);
    server->sasl_mech = strdup(chosenmech);
    if (server->sasl_mech == NULL) {
        lcb_error_handler(server->instance, LCB_CLIENT_ENOMEM, NULL);
        return;
    }

    memset(&req, 0, sizeof(req));
    req.message.header.request.magic = PROTOCOL_BINARY_REQ;
    req.message.header.request.opcode = PROTOCOL_BINARY_CMD_SASL_AUTH;
    req.message.header.request.keylen = ntohs((lcb_uint16_t)server->sasl_nmech);
    req.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
    req.message.header.request.bodylen = ntohl((lcb_uint32_t)(server->sasl_nmech + ndata));

    lcb_server_buffer_start_packet(server, command_data->cookie, conn->output,
                                   &server->output_cookies,
                                   req.bytes, sizeof(req.bytes));
    lcb_server_buffer_write_packet(server, conn->output,
                                   server->sasl_mech, server->sasl_nmech);
    lcb_server_buffer_write_packet(server, conn->output, data, ndata);
    lcb_server_buffer_end_packet(server, conn->output);
    lcb_sockrw_set_want(conn, LCB_WRITE_EVENT, 0);
}