예제 #1
0
const char *virNetSASLSessionGetIdentity(virNetSASLSessionPtr sasl)
{
    const void *val = NULL;
    int err;
    virMutexLock(&sasl->lock);

    err = sasl_getprop(sasl->conn, SASL_USERNAME, &val);
    if (err != SASL_OK) {
        virNetError(VIR_ERR_AUTH_FAILED,
                    _("cannot query SASL username on connection %d (%s)"),
                    err, sasl_errstring(err, NULL, NULL));
        val = NULL;
        goto cleanup;
    }
    if (val == NULL) {
        virNetError(VIR_ERR_AUTH_FAILED,
                    _("no client username was found"));
        goto cleanup;
    }
    VIR_DEBUG("SASL client username %s", (const char *)val);

cleanup:
    virMutexUnlock(&sasl->lock);
    return (const char*)val;
}
예제 #2
0
virNetSASLContextPtr virNetSASLContextNewClient(void)
{
    virNetSASLContextPtr ctxt;
    int err;

    err = sasl_client_init(NULL);
    if (err != SASL_OK) {
        virNetError(VIR_ERR_AUTH_FAILED,
                    _("failed to initialize SASL library: %d (%s)"),
                    err, sasl_errstring(err, NULL, NULL));
        return NULL;
    }

    if (VIR_ALLOC(ctxt) < 0) {
        virReportOOMError();
        return NULL;
    }

    if (virMutexInit(&ctxt->lock) < 0) {
        virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("Failed to initialized mutex"));
        VIR_FREE(ctxt);
        return NULL;
    }

    ctxt->refs = 1;

    return ctxt;
}
예제 #3
0
int virNetMessageEncodeNumFDs(virNetMessagePtr msg)
{
    XDR xdr;
    unsigned int numFDs = msg->nfds;
    int ret = -1;

    xdrmem_create(&xdr, msg->buffer + msg->bufferOffset,
                  msg->bufferLength - msg->bufferOffset, XDR_ENCODE);

    if (numFDs > VIR_NET_MESSAGE_NUM_FDS_MAX) {
        virNetError(VIR_ERR_RPC,
                    _("Too many FDs to send %d, expected %d maximum"),
                    numFDs, VIR_NET_MESSAGE_NUM_FDS_MAX);
        goto cleanup;
    }

    if (!xdr_u_int(&xdr, &numFDs)) {
        virNetError(VIR_ERR_RPC, "%s", _("Unable to encode number of FDs"));
        goto cleanup;
    }
    msg->bufferOffset += xdr_getpos(&xdr);

    VIR_DEBUG("Send %zu FDs to peer", msg->nfds);

    ret = 0;

cleanup:
    xdr_destroy(&xdr);
    return ret;
}
예제 #4
0
int virNetMessageEncodePayloadRaw(virNetMessagePtr msg,
                                  const char *data,
                                  size_t len)
{
    XDR xdr;
    unsigned int msglen;

    if ((msg->bufferLength - msg->bufferOffset) < len) {
        virNetError(VIR_ERR_RPC,
                    _("Stream data too long to send (%zu bytes needed, %zu bytes available)"),
                    len, (msg->bufferLength - msg->bufferOffset));
        return -1;
    }

    memcpy(msg->buffer + msg->bufferOffset, data, len);
    msg->bufferOffset += len;

    /* Re-encode the length word. */
    VIR_DEBUG("Encode length as %zu", msg->bufferOffset);
    xdrmem_create(&xdr, msg->buffer, VIR_NET_MESSAGE_HEADER_XDR_LEN, XDR_ENCODE);
    msglen = msg->bufferOffset;
    if (!xdr_u_int(&xdr, &msglen)) {
        virNetError(VIR_ERR_RPC, "%s", _("Unable to encode message length"));
        goto error;
    }
    xdr_destroy(&xdr);

    msg->bufferLength = msg->bufferOffset;
    msg->bufferOffset = 0;
    return 0;

error:
    xdr_destroy(&xdr);
    return -1;
}
예제 #5
0
virNetSASLContextPtr virNetSASLContextNewServer(const char *const*usernameWhitelist)
{
    virNetSASLContextPtr ctxt;
    int err;

    err = sasl_server_init(NULL, "libvirt");
    if (err != SASL_OK) {
        virNetError(VIR_ERR_AUTH_FAILED,
                    _("failed to initialize SASL library: %d (%s)"),
                    err, sasl_errstring(err, NULL, NULL));
        return NULL;
    }

    if (VIR_ALLOC(ctxt) < 0) {
        virReportOOMError();
        return NULL;
    }

    if (virMutexInit(&ctxt->lock) < 0) {
        virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("Failed to initialized mutex"));
        VIR_FREE(ctxt);
        return NULL;
    }

    ctxt->usernameWhitelist = usernameWhitelist;
    ctxt->refs = 1;

    return ctxt;
}
예제 #6
0
int virNetClientSend(virNetClientPtr client,
                     virNetMessagePtr msg,
                     bool expectReply)
{
    virNetClientCallPtr call;
    int ret = -1;

    PROBE(RPC_CLIENT_MSG_TX_QUEUE,
          "client=%p len=%zu prog=%u vers=%u proc=%u type=%u status=%u serial=%u",
          client, msg->bufferLength,
          msg->header.prog, msg->header.vers, msg->header.proc,
          msg->header.type, msg->header.status, msg->header.serial);

    if (expectReply &&
        (msg->bufferLength != 0) &&
        (msg->header.status == VIR_NET_CONTINUE)) {
        virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("Attempt to send an asynchronous message with a synchronous reply"));
        return -1;
    }

    if (VIR_ALLOC(call) < 0) {
        virReportOOMError();
        return -1;
    }

    virNetClientLock(client);

    if (virCondInit(&call->cond) < 0) {
        virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("cannot initialize condition variable"));
        goto cleanup;
    }

    msg->donefds = 0;
    if (msg->bufferLength)
        call->mode = VIR_NET_CLIENT_MODE_WAIT_TX;
    else
        call->mode = VIR_NET_CLIENT_MODE_WAIT_RX;
    call->msg = msg;
    call->expectReply = expectReply;

    ret = virNetClientIO(client, call);

cleanup:
    ignore_value(virCondDestroy(&call->cond));
    VIR_FREE(call);
    virNetClientUnlock(client);
    return ret;
}
예제 #7
0
/*
 * @msg: the outgoing message, whose header to encode
 *
 * Encodes the length word and header of the message, setting the
 * message offset ready to encode the payload. Leaves space
 * for the length field later. Upon return bufferLength will
 * refer to the total available space for message, while
 * bufferOffset will refer to current space used by header
 *
 * returns 0 if successfully encoded, -1 upon fatal error
 */
int virNetMessageEncodeHeader(virNetMessagePtr msg)
{
    XDR xdr;
    int ret = -1;
    unsigned int len = 0;

    msg->bufferLength = VIR_NET_MESSAGE_MAX + VIR_NET_MESSAGE_LEN_MAX;
    if (VIR_REALLOC_N(msg->buffer, msg->bufferLength) < 0) {
        virReportOOMError();
        goto cleanup;
    }
    msg->bufferOffset = 0;

    /* Format the header. */
    xdrmem_create(&xdr,
                  msg->buffer,
                  msg->bufferLength,
                  XDR_ENCODE);

    /* The real value is filled in shortly */
    if (!xdr_u_int(&xdr, &len)) {
        virNetError(VIR_ERR_RPC, "%s", _("Unable to encode message length"));
        goto cleanup;
    }

    if (!xdr_virNetMessageHeader(&xdr, &msg->header)) {
        virNetError(VIR_ERR_RPC, "%s", _("Unable to encode message header"));
        goto cleanup;
    }

    len = xdr_getpos(&xdr);
    xdr_setpos(&xdr, 0);

    /* Fill in current length - may be re-written later
     * if a payload is added
     */
    if (!xdr_u_int(&xdr, &len)) {
        virNetError(VIR_ERR_RPC, "%s", _("Unable to re-encode message length"));
        goto cleanup;
    }

    msg->bufferOffset += len;

    ret = 0;

cleanup:
    xdr_destroy(&xdr);
    return ret;
}
예제 #8
0
int virNetMessageDecodeLength(virNetMessagePtr msg)
{
    XDR xdr;
    unsigned int len;
    int ret = -1;

    xdrmem_create(&xdr, msg->buffer,
                  msg->bufferLength, XDR_DECODE);
    if (!xdr_u_int(&xdr, &len)) {
        virNetError(VIR_ERR_RPC, "%s", _("Unable to decode message length"));
        goto cleanup;
    }
    msg->bufferOffset = xdr_getpos(&xdr);

    if (len < VIR_NET_MESSAGE_LEN_MAX) {
        virNetError(VIR_ERR_RPC,
                    _("packet %d bytes received from server too small, want %d"),
                    len, VIR_NET_MESSAGE_LEN_MAX);
        goto cleanup;
    }

    /* Length includes length word - adjust to real length to read. */
    len -= VIR_NET_MESSAGE_LEN_MAX;

    if (len > VIR_NET_MESSAGE_MAX) {
        virNetError(VIR_ERR_RPC,
                    _("packet %d bytes received from server too large, want %d"),
                    len, VIR_NET_MESSAGE_MAX);
        goto cleanup;
    }

    /* Extend our declared buffer length and carry
       on reading the header + payload */
    msg->bufferLength += len;
    if (VIR_REALLOC_N(msg->buffer, msg->bufferLength) < 0) {
        virReportOOMError();
        goto cleanup;
    }

    VIR_DEBUG("Got length, now need %zu total (%u more)",
              msg->bufferLength, len);

    ret = 0;

cleanup:
    xdr_destroy(&xdr);
    return ret;
}
예제 #9
0
int virNetMessageDecodePayload(virNetMessagePtr msg,
                               xdrproc_t filter,
                               void *data)
{
    XDR xdr;

    /* Deserialise payload of the message. This assumes that
     * virNetMessageDecodeHeader has already been run, so
     * just start from after that data */
    xdrmem_create(&xdr, msg->buffer + msg->bufferOffset,
                  msg->bufferLength - msg->bufferOffset, XDR_DECODE);

    if (!(*filter)(&xdr, data)) {
        virNetError(VIR_ERR_RPC, "%s", _("Unable to decode message payload"));
        goto error;
    }

    /* Get the length stored in buffer. */
    msg->bufferLength += xdr_getpos(&xdr);
    xdr_destroy(&xdr);
    return 0;

error:
    xdr_destroy(&xdr);
    return -1;
}
예제 #10
0
/*
 * @msg: the complete incoming message, whose header to decode
 *
 * Decodes the header part of the message, but does not
 * validate the decoded fields in the header. It expects
 * bufferLength to refer to length of the data packet. Upon
 * return bufferOffset will refer to the amount of the packet
 * consumed by decoding of the header.
 *
 * returns 0 if successfully decoded, -1 upon fatal error
 */
int virNetMessageDecodeHeader(virNetMessagePtr msg)
{
    XDR xdr;
    int ret = -1;

    msg->bufferOffset = VIR_NET_MESSAGE_LEN_MAX;

    /* Parse the header. */
    xdrmem_create(&xdr,
                  msg->buffer + msg->bufferOffset,
                  msg->bufferLength - msg->bufferOffset,
                  XDR_DECODE);

    if (!xdr_virNetMessageHeader(&xdr, &msg->header)) {
        virNetError(VIR_ERR_RPC, "%s", _("Unable to decode message header"));
        goto cleanup;
    }

    msg->bufferOffset += xdr_getpos(&xdr);

    ret = 0;

cleanup:
    xdr_destroy(&xdr);
    return ret;
}
예제 #11
0
int virNetClientStreamEventRemoveCallback(virNetClientStreamPtr st)
{
    int ret = -1;

    virMutexUnlock(&st->lock);
    if (!st->cb) {
        virNetError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("no stream callback registered"));
        goto cleanup;
    }

    if (!st->cbDispatch &&
        st->cbFree)
        (st->cbFree)(st->cbOpaque);
    st->cb = NULL;
    st->cbOpaque = NULL;
    st->cbFree = NULL;
    st->cbEvents = 0;
    virEventRemoveTimeout(st->cbTimer);

    ret = 0;

cleanup:
    virMutexUnlock(&st->lock);
    return ret;
}
예제 #12
0
int virNetSASLSessionSecProps(virNetSASLSessionPtr sasl,
                              int minSSF,
                              int maxSSF,
                              bool allowAnonymous)
{
    sasl_security_properties_t secprops;
    int err;
    int ret = -1;

    VIR_DEBUG("minSSF=%d maxSSF=%d allowAnonymous=%d maxbufsize=%zu",
              minSSF, maxSSF, allowAnonymous, sasl->maxbufsize);

    virMutexLock(&sasl->lock);
    memset(&secprops, 0, sizeof secprops);

    secprops.min_ssf = minSSF;
    secprops.max_ssf = maxSSF;
    secprops.maxbufsize = sasl->maxbufsize;
    secprops.security_flags = allowAnonymous ? 0 :
        SASL_SEC_NOANONYMOUS | SASL_SEC_NOPLAINTEXT;

    err = sasl_setprop(sasl->conn, SASL_SEC_PROPS, &secprops);
    if (err != SASL_OK) {
        virNetError(VIR_ERR_INTERNAL_ERROR,
                    _("cannot set security props %d (%s)"),
                    err, sasl_errstring(err, NULL, NULL));
        goto cleanup;
    }

    ret = 0;

cleanup:
    virMutexUnlock(&sasl->lock);
    return ret;
}
예제 #13
0
virNetClientStreamPtr virNetClientStreamNew(virNetClientProgramPtr prog,
                                            int proc,
                                            unsigned serial)
{
    virNetClientStreamPtr st;

    if (VIR_ALLOC(st) < 0) {
        virReportOOMError();
        return NULL;
    }

    st->refs = 1;
    st->prog = prog;
    st->proc = proc;
    st->serial = serial;

    if (virMutexInit(&st->lock) < 0) {
        virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("cannot initialize mutex"));
        VIR_FREE(st);
        return NULL;
    }

    virNetClientProgramRef(prog);

    return st;
}
예제 #14
0
char *virNetSASLSessionListMechanisms(virNetSASLSessionPtr sasl)
{
    const char *mechlist;
    char *ret = NULL;
    int err;

    virMutexLock(&sasl->lock);
    err = sasl_listmech(sasl->conn,
                        NULL, /* Don't need to set user */
                        "", /* Prefix */
                        ",", /* Separator */
                        "", /* Suffix */
                        &mechlist,
                        NULL,
                        NULL);
    if (err != SASL_OK) {
        virNetError(VIR_ERR_INTERNAL_ERROR,
                    _("cannot list SASL mechanisms %d (%s)"),
                    err, sasl_errdetail(sasl->conn));
        goto cleanup;
    }
    if (!(ret = strdup(mechlist))) {
        virReportOOMError();
        goto cleanup;
    }

cleanup:
    virMutexUnlock(&sasl->lock);
    return ret;
}
예제 #15
0
static int
virNetClientCallDispatch(virNetClientPtr client)
{
    PROBE(RPC_CLIENT_MSG_RX,
          "client=%p len=%zu prog=%u vers=%u proc=%u type=%u status=%u serial=%u",
          client, client->msg.bufferLength,
          client->msg.header.prog, client->msg.header.vers, client->msg.header.proc,
          client->msg.header.type, client->msg.header.status, client->msg.header.serial);

    switch (client->msg.header.type) {
    case VIR_NET_REPLY: /* Normal RPC replies */
    case VIR_NET_REPLY_WITH_FDS: /* Normal RPC replies with FDs */
        return virNetClientCallDispatchReply(client);

    case VIR_NET_MESSAGE: /* Async notifications */
        return virNetClientCallDispatchMessage(client);

    case VIR_NET_STREAM: /* Stream protocol */
        return virNetClientCallDispatchStream(client);

    default:
        virNetError(VIR_ERR_RPC,
                    _("got unexpected RPC call prog %d vers %d proc %d type %d"),
                    client->msg.header.prog, client->msg.header.vers,
                    client->msg.header.proc, client->msg.header.type);
        return -1;
    }
}
예제 #16
0
static int
virNetClientCallDispatchReply(virNetClientPtr client)
{
    virNetClientCallPtr thecall;

    /* Ok, definitely got an RPC reply now find
       out who's been waiting for it */
    thecall = client->waitDispatch;
    while (thecall &&
           !(thecall->msg->header.prog == client->msg.header.prog &&
             thecall->msg->header.vers == client->msg.header.vers &&
             thecall->msg->header.serial == client->msg.header.serial))
        thecall = thecall->next;

    if (!thecall) {
        virNetError(VIR_ERR_RPC,
                    _("no call waiting for reply with prog %d vers %d serial %d"),
                    client->msg.header.prog, client->msg.header.vers, client->msg.header.serial);
        return -1;
    }

    memcpy(thecall->msg->buffer, client->msg.buffer, sizeof(client->msg.buffer));
    memcpy(&thecall->msg->header, &client->msg.header, sizeof(client->msg.header));
    thecall->msg->bufferLength = client->msg.bufferLength;
    thecall->msg->bufferOffset = client->msg.bufferOffset;

    thecall->mode = VIR_NET_CLIENT_MODE_COMPLETE;

    return 0;
}
예제 #17
0
int virNetMessageDupFD(virNetMessagePtr msg,
                       size_t slot)
{
    int fd;

    if (slot >= msg->nfds) {
        virNetError(VIR_ERR_INTERNAL_ERROR,
                    _("No FD available at slot %zu"), slot);
        return -1;
    }

    if ((fd = dup(msg->fds[slot])) < 0) {
        virReportSystemError(errno,
                             _("Unable to duplicate FD %d"),
                             msg->fds[slot]);
        return -1;
    }
    if (virSetInherit(fd, false) < 0) {
        VIR_FORCE_CLOSE(fd);
        virReportSystemError(errno,
                             _("Cannot set close-on-exec %d"),
                             fd);
        return -1;
    }
    return fd;
}
예제 #18
0
virNetSASLSessionPtr virNetSASLSessionNewClient(virNetSASLContextPtr ctxt ATTRIBUTE_UNUSED,
                                                const char *service,
                                                const char *hostname,
                                                const char *localAddr,
                                                const char *remoteAddr,
                                                const sasl_callback_t *cbs)
{
    virNetSASLSessionPtr sasl = NULL;
    int err;

    if (VIR_ALLOC(sasl) < 0) {
        virReportOOMError();
        goto cleanup;
    }

    if (virMutexInit(&sasl->lock) < 0) {
        virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
                    _("Failed to initialized mutex"));
        VIR_FREE(sasl);
        return NULL;
    }

    sasl->refs = 1;
    /* Arbitrary size for amount of data we can encode in a single block */
    sasl->maxbufsize = 1 << 16;

    err = sasl_client_new(service,
                          hostname,
                          localAddr,
                          remoteAddr,
                          cbs,
                          SASL_SUCCESS_DATA,
                          &sasl->conn);
    if (err != SASL_OK) {
        virNetError(VIR_ERR_AUTH_FAILED,
                    _("Failed to create SASL client context: %d (%s)"),
                    err, sasl_errstring(err, NULL, NULL));
        goto cleanup;
    }

    return sasl;

cleanup:
    virNetSASLSessionFree(sasl);
    return NULL;
}
예제 #19
0
int virNetSASLContextCheckIdentity(virNetSASLContextPtr ctxt,
                                   const char *identity)
{
    const char *const*wildcards;
    int ret = -1;

    virMutexLock(&ctxt->lock);

    /* If the list is not set, allow any DN. */
    wildcards = ctxt->usernameWhitelist;
    if (!wildcards) {
        ret = 1; /* No ACL, allow all */
        goto cleanup;
    }

    while (*wildcards) {
        int rv = fnmatch (*wildcards, identity, 0);
        if (rv == 0) {
            ret = 1;
            goto cleanup; /* Succesful match */
        }
        if (rv != FNM_NOMATCH) {
            virNetError(VIR_ERR_INTERNAL_ERROR,
                        _("Malformed TLS whitelist regular expression '%s'"),
                        *wildcards);
            goto cleanup;
        }

        wildcards++;
    }

    /* Denied */
    VIR_ERROR(_("SASL client %s not allowed in whitelist"), identity);

    /* This is the most common error: make it informative. */
    virNetError(VIR_ERR_SYSTEM_ERROR, "%s",
                _("Client's username is not on the list of allowed clients"));
    ret = 0;

cleanup:
    virMutexUnlock(&ctxt->lock);
    return ret;
}
예제 #20
0
int virNetMessageEncodePayload(virNetMessagePtr msg,
                               xdrproc_t filter,
                               void *data)
{
    XDR xdr;
    unsigned int msglen;

    /* Serialise payload of the message. This assumes that
     * virNetMessageEncodeHeader has already been run, so
     * just appends to that data */
    xdrmem_create(&xdr, msg->buffer + msg->bufferOffset,
                  msg->bufferLength - msg->bufferOffset, XDR_ENCODE);

    if (!(*filter)(&xdr, data)) {
        virNetError(VIR_ERR_RPC, "%s", _("Unable to encode message payload"));
        goto error;
    }

    /* Get the length stored in buffer. */
    msg->bufferOffset += xdr_getpos(&xdr);
    xdr_destroy(&xdr);

    /* Re-encode the length word. */
    VIR_DEBUG("Encode length as %zu", msg->bufferOffset);
    xdrmem_create(&xdr, msg->buffer, VIR_NET_MESSAGE_HEADER_XDR_LEN, XDR_ENCODE);
    msglen = msg->bufferOffset;
    if (!xdr_u_int(&xdr, &msglen)) {
        virNetError(VIR_ERR_RPC, "%s", _("Unable to encode message length"));
        goto error;
    }
    xdr_destroy(&xdr);

    msg->bufferLength = msg->bufferOffset;
    msg->bufferOffset = 0;
    return 0;

error:
    xdr_destroy(&xdr);
    return -1;
}
예제 #21
0
int virNetMessageDecodeNumFDs(virNetMessagePtr msg)
{
    XDR xdr;
    unsigned int numFDs;
    int ret = -1;
    size_t i;

    xdrmem_create(&xdr, msg->buffer + msg->bufferOffset,
                  msg->bufferLength - msg->bufferOffset, XDR_DECODE);
    if (!xdr_u_int(&xdr, &numFDs)) {
        virNetError(VIR_ERR_RPC, "%s", _("Unable to decode number of FDs"));
        goto cleanup;
    }
    msg->bufferOffset += xdr_getpos(&xdr);

    if (numFDs > VIR_NET_MESSAGE_NUM_FDS_MAX) {
        virNetError(VIR_ERR_RPC,
                    _("Received too many FDs %d, expected %d maximum"),
                    numFDs, VIR_NET_MESSAGE_NUM_FDS_MAX);
        goto cleanup;
    }

    msg->nfds = numFDs;
    if (VIR_ALLOC_N(msg->fds, msg->nfds) < 0) {
        virReportOOMError();
        goto cleanup;
    }
    for (i = 0 ; i < msg->nfds ; i++)
        msg->fds[i] = -1;

    VIR_DEBUG("Got %zu FDs from peer", msg->nfds);

    ret = 0;

cleanup:
    xdr_destroy(&xdr);
    return ret;
}
예제 #22
0
int virNetSASLSessionClientStep(virNetSASLSessionPtr sasl,
                                const char *serverin,
                                size_t serverinlen,
                                sasl_interact_t **prompt_need,
                                const char **clientout,
                                size_t *clientoutlen)
{
    unsigned inlen = serverinlen;
    unsigned outlen = 0;
    int err;
    int ret = -1;

    VIR_DEBUG("sasl=%p serverin=%s serverinlen=%zu prompt_need=%p clientout=%p clientoutlen=%p",
              sasl, serverin, serverinlen, prompt_need, clientout, clientoutlen);

    virMutexLock(&sasl->lock);
    err = sasl_client_step(sasl->conn,
                           serverin,
                           inlen,
                           prompt_need,
                           clientout,
                           &outlen);
    *clientoutlen = outlen;

    switch (err) {
    case SASL_OK:
        if (virNetSASLSessionUpdateBufSize(sasl) < 0)
            goto cleanup;
        ret = VIR_NET_SASL_COMPLETE;
        break;
    case SASL_CONTINUE:
        ret = VIR_NET_SASL_CONTINUE;
        break;
    case SASL_INTERACT:
        ret = VIR_NET_SASL_INTERACT;
        break;
    default:
        virNetError(VIR_ERR_AUTH_FAILED,
                    _("Failed to step SASL negotiation: %d (%s)"),
                    err, sasl_errdetail(sasl->conn));
        break;
    }

cleanup:
    virMutexUnlock(&sasl->lock);
    return ret;
}
예제 #23
0
int virNetSASLSessionServerStart(virNetSASLSessionPtr sasl,
                                 const char *mechname,
                                 const char *clientin,
                                 size_t clientinlen,
                                 const char **serverout,
                                 size_t *serveroutlen)
{
    unsigned inlen = clientinlen;
    unsigned outlen = 0;
    int err;
    int ret = -1;

    virMutexLock(&sasl->lock);
    err = sasl_server_start(sasl->conn,
                            mechname,
                            clientin,
                            inlen,
                            serverout,
                            &outlen);

    *serveroutlen = outlen;

    switch (err) {
    case SASL_OK:
        if (virNetSASLSessionUpdateBufSize(sasl) < 0)
            goto cleanup;
        ret = VIR_NET_SASL_COMPLETE;
        break;
    case SASL_CONTINUE:
        ret = VIR_NET_SASL_CONTINUE;
        break;
    case SASL_INTERACT:
        ret = VIR_NET_SASL_INTERACT;
        break;
    default:
        virNetError(VIR_ERR_AUTH_FAILED,
                    _("Failed to start SASL negotiation: %d (%s)"),
                    err, sasl_errdetail(sasl->conn));
        break;
    }

cleanup:
    virMutexUnlock(&sasl->lock);
    return ret;
}
예제 #24
0
int virNetServerProgramUnknownError(virNetServerClientPtr client,
                                    virNetMessagePtr msg,
                                    virNetMessageHeaderPtr req)
{
    virNetMessageError rerr;

    virNetError(VIR_ERR_RPC,
                _("Cannot find program %d version %d"), req->prog, req->vers);

    memset(&rerr, 0, sizeof(rerr));
    return virNetServerProgramSendError(req->prog,
                                        req->vers,
                                        client,
                                        msg,
                                        &rerr,
                                        req->proc,
                                        VIR_NET_REPLY,
                                        req->serial);
}
예제 #25
0
static int virNetServerDispatchNewClient(virNetServerServicePtr svc ATTRIBUTE_UNUSED,
                                         virNetServerClientPtr client,
                                         void *opaque)
{
    virNetServerPtr srv = opaque;

    virNetServerLock(srv);

    if (srv->nclients >= srv->nclients_max) {
        virNetError(VIR_ERR_RPC,
                    _("Too many active clients (%zu), dropping connection from %s"),
                    srv->nclients_max, virNetServerClientRemoteAddrString(client));
        goto error;
    }

    if (virNetServerClientInit(client) < 0)
        goto error;

    if (srv->clientInitHook &&
        srv->clientInitHook(srv, client) < 0)
        goto error;

    if (VIR_EXPAND_N(srv->clients, srv->nclients, 1) < 0) {
        virReportOOMError();
        goto error;
    }
    srv->clients[srv->nclients-1] = client;
    virNetServerClientRef(client);

    virNetServerClientSetDispatcher(client,
                                    virNetServerDispatchNewMessage,
                                    srv);

    virNetServerClientInitKeepAlive(client, srv->keepaliveInterval,
                                    srv->keepaliveCount);

    virNetServerUnlock(srv);
    return 0;

error:
    virNetServerUnlock(srv);
    return -1;
}
예제 #26
0
static int virNetSASLSessionUpdateBufSize(virNetSASLSessionPtr sasl)
{
    union {
        unsigned *maxbufsize;
        const void *ptr;
    } u;
    int err;

    err = sasl_getprop(sasl->conn, SASL_MAXOUTBUF, &u.ptr);
    if (err != SASL_OK) {
        virNetError(VIR_ERR_INTERNAL_ERROR,
                    _("cannot get security props %d (%s)"),
                    err, sasl_errstring(err, NULL, NULL));
        return -1;
    }

    VIR_DEBUG("Negotiated bufsize is %u vs requested size %zu",
              *u.maxbufsize, sasl->maxbufsize);
    sasl->maxbufsize = *u.maxbufsize;
    return 0;
}
예제 #27
0
int virNetSASLSessionGetKeySize(virNetSASLSessionPtr sasl)
{
    int err;
    int ssf;
    const void *val;

    virMutexLock(&sasl->lock);
    err = sasl_getprop(sasl->conn, SASL_SSF, &val);
    if (err != SASL_OK) {
        virNetError(VIR_ERR_AUTH_FAILED,
                    _("cannot query SASL ssf on connection %d (%s)"),
                    err, sasl_errstring(err, NULL, NULL));
        ssf = -1;
        goto cleanup;
    }
    ssf = *(const int *)val;

cleanup:
    virMutexUnlock(&sasl->lock);
    return ssf;
}
예제 #28
0
int virNetSASLSessionExtKeySize(virNetSASLSessionPtr sasl,
                                int ssf)
{
    int err;
    int ret = -1;
    virMutexLock(&sasl->lock);

    err = sasl_setprop(sasl->conn, SASL_SSF_EXTERNAL, &ssf);
    if (err != SASL_OK) {
        virNetError(VIR_ERR_INTERNAL_ERROR,
                    _("cannot set external SSF %d (%s)"),
                    err, sasl_errstring(err, NULL, NULL));
        goto cleanup;
    }

    ret = 0;

cleanup:
    virMutexUnlock(&sasl->lock);
    return ret;
}
예제 #29
0
int virNetClientStreamEventUpdateCallback(virNetClientStreamPtr st,
                                          int events)
{
    int ret = -1;

    virMutexLock(&st->lock);
    if (!st->cb) {
        virNetError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("no stream callback registered"));
        goto cleanup;
    }

    st->cbEvents = events;

    virNetClientStreamEventTimerUpdate(st);

    ret = 0;

cleanup:
    virMutexUnlock(&st->lock);
    return ret;
}
예제 #30
0
ssize_t virNetSASLSessionEncode(virNetSASLSessionPtr sasl,
                                const char *input,
                                size_t inputLen,
                                const char **output,
                                size_t *outputlen)
{
    unsigned inlen = inputLen;
    unsigned outlen = 0;
    int err;
    ssize_t ret = -1;

    virMutexLock(&sasl->lock);
    if (inputLen > sasl->maxbufsize) {
        virReportSystemError(EINVAL,
                             _("SASL data length %zu too long, max %zu"),
                             inputLen, sasl->maxbufsize);
        goto cleanup;
    }

    err = sasl_encode(sasl->conn,
                      input,
                      inlen,
                      output,
                      &outlen);
    *outputlen = outlen;

    if (err != SASL_OK) {
        virNetError(VIR_ERR_INTERNAL_ERROR,
                    _("failed to encode SASL data: %d (%s)"),
                    err, sasl_errstring(err, NULL, NULL));
        goto cleanup;
    }
    ret = 0;

cleanup:
    virMutexUnlock(&sasl->lock);
    return ret;
}