b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek/*
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek SSSD
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek KCM Server - the KCM server request and reply parsing and dispatching
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek Copyright (C) Red Hat, 2016
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek This program is free software; you can redistribute it and/or modify
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek it under the terms of the GNU General Public License as published by
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek the Free Software Foundation; either version 3 of the License, or
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek (at your option) any later version.
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek This program is distributed in the hope that it will be useful,
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek but WITHOUT ANY WARRANTY; without even the implied warranty of
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek GNU General Public License for more details.
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek You should have received a copy of the GNU General Public License
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek along with this program. If not, see <http://www.gnu.org/licenses/>.
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek*/
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
2186f88e0449f2303dc84e98c88379ccf8e55714Lukas Slebodnik#include <sys/uio.h>
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek#include <krb5/krb5.h>
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek#include "config.h"
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek#include "util/util.h"
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek#include "responder/common/responder.h"
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek#include "responder/kcm/kcmsrv_pvt.h"
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek#include "responder/kcm/kcm.h"
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek#include "responder/kcm/kcmsrv_ops.h"
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek/* The first four bytes of a message is always the size */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek#define KCM_MSG_LEN_SIZE 4
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek/* The return code is 32bits */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek#define KCM_RETCODE_SIZE 4
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek/* The maximum length of a request or reply as defined by the RPC
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * protocol. This is the same constant size as MIT KRB5 uses
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek */
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio#define KCM_PACKET_MAX_SIZE 10*1024*1024
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek/* KCM operation, its raw input and raw output and result */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstruct kcm_op_io {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_op *op;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_data request;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct sss_iobuf *reply;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek};
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek/**
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * KCM IO-vector operations
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstruct kcm_iovec {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* We don't use iovec b/c void pointers don't allow for
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * pointer arithmetics and it's convenient to keep track
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * of processed bytes
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek uint8_t *kiov_base;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek size_t kiov_len;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek size_t nprocessed;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek};
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic errno_t kcm_iovec_op(int fd, struct kcm_iovec *kiov, bool do_read)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ssize_t len;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct iovec iov[1];
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek iov[0].iov_base = kiov->kiov_base + kiov->nprocessed;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek iov[0].iov_len = kiov->kiov_len - kiov->nprocessed;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (iov[0].iov_len == 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* This iovec is full (read) or depleted (write), proceed to the next one */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return EOK;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (do_read) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek len = readv(fd, iov, 1);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek } else {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek len = writev(fd, iov, 1);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (len == -1) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return EAGAIN;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek } else {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return errno;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (len == 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* Read event on fd that doesn't yield data? error */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return ENODATA;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* Decrease the amount of available free space in the iovec */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek kiov->nprocessed += len;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return EOK;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic errno_t kcm_read_iovec(int fd, struct kcm_iovec *kiov)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return kcm_iovec_op(fd, kiov, true);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic errno_t kcm_write_iovec(int fd, struct kcm_iovec *kiov)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return kcm_iovec_op(fd, kiov, false);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek/**
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * Parsing KCM input
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek *
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * The request is received as two IO vectors:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek *
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * first iovec:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * length 32-bit big-endian integer
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek *
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * second iovec:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * major protocol number 8-bit big-endian integer
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * minor protocol number 8-bit big-endian integer
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * opcode 16-bit big-endian integer
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * message payload buffer
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstruct kcm_reqbuf {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek uint8_t lenbuf[KCM_MSG_LEN_SIZE];
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_iovec v_len;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* Includes the major, minor versions etc */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_iovec v_msg;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek};
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidênciostatic uint32_t kcm_input_get_payload_len(struct kcm_iovec *v)
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio{
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio size_t lc = 0;
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio uint32_t len_be = 0;
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio /* The first 4 bytes before the payload is message length */
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio SAFEALIGN_COPY_UINT32_CHECK(&len_be, v->kiov_base, v->kiov_len, &lc);
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio return be32toh(len_be);
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio}
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic errno_t kcm_input_parse(struct kcm_reqbuf *reqbuf,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_op_io *op_io)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek size_t mc = 0;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek uint16_t opcode_be = 0;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek uint32_t msglen;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek uint8_t proto_maj = 0;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek uint8_t proto_min = 0;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
2f11cf256a10ca6f6ace35a05cc2edb46689567fFabiano Fidêncio msglen = kcm_input_get_payload_len(&reqbuf->v_len);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek DEBUG(SSSDBG_TRACE_LIBS,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek "Received message with length %"PRIu32"\n", msglen);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (msglen == 0) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Illegal zero-length message\n");
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return EBADMSG;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (msglen != reqbuf->v_msg.nprocessed) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek "Sender claims the message is %"PRIu32" bytes, "
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek "but received %zu\n",
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek msglen, reqbuf->v_msg.nprocessed);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return EBADMSG;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek /* First 16 bits are 8 bit major and 8bit minor protocol version */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek SAFEALIGN_COPY_UINT8_CHECK(&proto_maj,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek reqbuf->v_msg.kiov_base + mc,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek reqbuf->v_msg.kiov_len,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek &mc);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek SAFEALIGN_COPY_UINT8_CHECK(&proto_min,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek reqbuf->v_msg.kiov_base + mc,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek reqbuf->v_msg.kiov_len,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek &mc);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (proto_maj != KCM_PROTOCOL_VERSION_MAJOR) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek "Expected major version %d, got %"PRIu16"\n",
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek KCM_PROTOCOL_VERSION_MAJOR, (uint16_t) proto_maj);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return ERR_KCM_MALFORMED_IN_PKT;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (proto_min != KCM_PROTOCOL_VERSION_MINOR) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek "Expected minor version %d, got %"PRIu16"\n",
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek KCM_PROTOCOL_VERSION_MINOR, (uint16_t) proto_maj);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return ERR_KCM_MALFORMED_IN_PKT;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek SAFEALIGN_COPY_UINT16_CHECK(&opcode_be,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek reqbuf->v_msg.kiov_base + mc,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek reqbuf->v_msg.kiov_len,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek &mc);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek op_io->op = kcm_get_opt(be16toh(opcode_be));
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek if (op_io->op == NULL) {
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek "Did not find a KCM operation handler for the requested opcode\n");
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek return ERR_KCM_MALFORMED_IN_PKT;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek }
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek /* The operation only receives the payload, not the opcode or the protocol info */
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek op_io->request.data = reqbuf->v_msg.kiov_base + mc;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek op_io->request.length = reqbuf->v_msg.nprocessed - mc;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return EOK;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek/**
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * Constructing a reply for failure and success
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek *
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * The reply consists of three IO vectors:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * 1) length iovec:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * length: 32-bit big-endian
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek *
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * 2) return code iovec:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * retcode: 32-bit big-endian. Non-zero on failure in the KCM server,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * zero if the KCM operation ran (even if the operation itself
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * failed)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek *
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * 3) reply iovec
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * message: buffer, first 32-bits of the buffer is the return code of
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * the KCM operation, the rest depends on the operation itself.
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * The buffer's length is specified by the first integer in the
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * reply (very intuitive, right?)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek *
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * The client always reads the length and return code iovectors. However, the
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * client reads the reply iovec only if retcode is 0 in the return code iovector
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * (see kcmio_unix_socket_read() in the MIT tree)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstruct kcm_repbuf {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek uint8_t lenbuf[KCM_MSG_LEN_SIZE];
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_iovec v_len;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek uint8_t rcbuf[KCM_RETCODE_SIZE];
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_iovec v_rc;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_iovec v_msg;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek};
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic errno_t kcm_failbuf_construct(errno_t ret,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_repbuf *repbuf)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek size_t c;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek c = 0;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek SAFEALIGN_SETMEM_UINT32(repbuf->lenbuf, 0, &c);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek c = 0;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek SAFEALIGN_SETMEM_UINT32(repbuf->rcbuf, htobe32(ret), &c);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek DEBUG(SSSDBG_TRACE_LIBS, "Sent reply with error %d\n", ret);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek return EOK;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek}
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek/* retcode is 0 if the operation at least ran, non-zero if there
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek * was some kind of internal KCM error, like input couldn't be parsed
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek */
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidênciostatic errno_t kcm_output_construct(TALLOC_CTX *mem_ctx,
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio struct kcm_op_io *op_io,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek struct kcm_repbuf *repbuf)
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek{
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio uint8_t *rep;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek size_t replen;
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio size_t c;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek replen = sss_iobuf_get_len(op_io->reply);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek if (replen > KCM_PACKET_MAX_SIZE) {
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek "Reply exceeds the KCM protocol limit, aborting\n");
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek return E2BIG;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek }
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek DEBUG(SSSDBG_TRACE_LIBS,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek "Sending a reply with %zu bytes of payload\n", replen);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek c = 0;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek SAFEALIGN_SETMEM_UINT32(repbuf->lenbuf, htobe32(replen), &c);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek c = 0;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek SAFEALIGN_SETMEM_UINT32(repbuf->rcbuf, 0, &c);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek if (replen > 0) {
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio rep = talloc_zero_array(mem_ctx, uint8_t, replen);
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio if (rep == NULL) {
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio DEBUG(SSSDBG_CRIT_FAILURE,
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio "Failed to allocate memory for the message\n");
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio return ENOMEM;
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio }
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek c = 0;
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio SAFEALIGN_MEMCPY_CHECK(rep,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek sss_iobuf_get_data(op_io->reply),
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek replen,
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio replen,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek &c);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio /* Set the buffer and its length to send to KCM client */
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio repbuf->v_msg.kiov_base = rep;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek repbuf->v_msg.kiov_len = replen;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek }
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return EOK;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek/**
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * Construct a reply buffer and send it to the KCM client
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic void kcm_reply_error(struct cli_ctx *cctx,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek errno_t retcode,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_repbuf *repbuf)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek errno_t ret;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek krb5_error_code kerr;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek "KCM operation returs failure [%d]: %s\n",
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek retcode, sss_strerror(retcode));
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek kerr = sss2krb5_error(retcode);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ret = kcm_failbuf_construct(kerr, repbuf);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (ret != EOK) {
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek "Cannot construct the reply buffer, terminating client\n");
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek talloc_free(cctx);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek TEVENT_FD_WRITEABLE(cctx->cfde);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek/**
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek * Request-reply dispatcher
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstruct kcm_req_ctx {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* client context owns per-client buffers including this one */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct cli_ctx *cctx;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* raw IO buffers */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_reqbuf reqbuf;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_repbuf repbuf;
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* long-lived responder structures */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_ctx *kctx;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_op_io op_io;
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek};
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidênciostatic void kcm_send_reply(struct kcm_req_ctx *req_ctx)
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio{
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio struct cli_ctx *cctx;
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio errno_t ret;
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio DEBUG(SSSDBG_TRACE_INTERNAL, "Sending a reply\n");
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio cctx = req_ctx->cctx;
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio ret = kcm_output_construct(cctx, &req_ctx->op_io, &req_ctx->repbuf);
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio if (ret != EOK) {
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio DEBUG(SSSDBG_CRIT_FAILURE,
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio "Cannot construct the reply buffer, terminating client\n");
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio kcm_reply_error(cctx, ret, &req_ctx->repbuf);
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio return;
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio }
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio TEVENT_FD_WRITEABLE(cctx->cfde);
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio}
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozekstatic void kcm_cmd_request_done(struct tevent_req *req);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
2b5518eeaacc6245cfa77ee4a7086f16208060fcJakub Hrozekstatic errno_t kcm_cmd_dispatch(struct kcm_ctx *kctx,
2b5518eeaacc6245cfa77ee4a7086f16208060fcJakub Hrozek struct kcm_req_ctx *req_ctx)
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek{
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek struct tevent_req *req;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek struct cli_ctx *cctx;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek cctx = req_ctx->cctx;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
2b5518eeaacc6245cfa77ee4a7086f16208060fcJakub Hrozek req = kcm_cmd_send(req_ctx,
2b5518eeaacc6245cfa77ee4a7086f16208060fcJakub Hrozek cctx->ev,
2b5518eeaacc6245cfa77ee4a7086f16208060fcJakub Hrozek kctx->qctx,
2b5518eeaacc6245cfa77ee4a7086f16208060fcJakub Hrozek req_ctx->kctx->kcm_data,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek req_ctx->cctx->creds,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek &req_ctx->op_io.request,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek req_ctx->op_io.op);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek if (req == NULL) {
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, "Failed to schedule KCM operation.\n");
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek return ENOMEM;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek }
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek tevent_req_set_callback(req, kcm_cmd_request_done, req_ctx);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek return EOK;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek}
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozekstatic void kcm_cmd_request_done(struct tevent_req *req)
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek{
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek struct kcm_req_ctx *req_ctx;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek errno_t ret;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek req_ctx = tevent_req_callback_data(req, struct kcm_req_ctx);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek ret = kcm_cmd_recv(req_ctx, req,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek &req_ctx->op_io.reply);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek talloc_free(req);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek if (ret != EOK) {
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek DEBUG(SSSDBG_OP_FAILURE,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek "KCM operation failed [%d]: %s\n", ret, sss_strerror(ret));
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio kcm_reply_error(req_ctx->cctx, ret, &req_ctx->repbuf);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek return;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek }
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio kcm_send_reply(req_ctx);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek}
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidênciostatic errno_t kcm_recv_data(TALLOC_CTX *mem_ctx,
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio int fd,
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio struct kcm_reqbuf *reqbuf)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio uint8_t *msg;
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio uint32_t msglen;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek errno_t ret;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ret = kcm_read_iovec(fd, &reqbuf->v_len);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (ret != EOK) {
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek /* Not all errors are fatal, hence we don't print DEBUG messages
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek * here, but in the caller
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return ret;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio msglen = kcm_input_get_payload_len(&reqbuf->v_len);
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio if (msglen > KCM_PACKET_MAX_SIZE) {
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio DEBUG(SSSDBG_CRIT_FAILURE,
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio "Request exceeds the KCM protocol limit, aborting\n");
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio return E2BIG;
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio }
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio msg = talloc_zero_array(mem_ctx, uint8_t, msglen);
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio if (msg == NULL) {
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio DEBUG(SSSDBG_CRIT_FAILURE,
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio "Failed to allocate memory for the message\n");
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio return ENOMEM;
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio }
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio /* Set the buffer and its expected len to receive the data */
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio reqbuf->v_msg.kiov_base = msg;
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio reqbuf->v_msg.kiov_len = msglen;
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ret = kcm_read_iovec(fd, &reqbuf->v_msg);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (ret != EOK) {
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek /* Not all errors are fatal, hence we don't print DEBUG messages
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek * here, but in the caller
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return ret;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return EOK;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
bfc6d9d611bfbc54b3f738084d86fb887c8769b5Fabiano Fidêncio/* Mind that kcm_new_req() does not take a mem_ctx argument on purpose as we
bfc6d9d611bfbc54b3f738084d86fb887c8769b5Fabiano Fidêncio * really want the cctx to be the memory context here so that if the client
bfc6d9d611bfbc54b3f738084d86fb887c8769b5Fabiano Fidêncio * disconnects, the request goes away. */
bfc6d9d611bfbc54b3f738084d86fb887c8769b5Fabiano Fidênciostatic struct kcm_req_ctx *kcm_new_req(struct cli_ctx *cctx,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_ctx *kctx)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_req_ctx *req;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek req = talloc_zero(cctx, struct kcm_req_ctx);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (req == NULL) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return NULL;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek req->reqbuf.v_len.kiov_base = req->reqbuf.lenbuf;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek req->reqbuf.v_len.kiov_len = KCM_MSG_LEN_SIZE;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek req->repbuf.v_len.kiov_base = req->repbuf.lenbuf;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek req->repbuf.v_len.kiov_len = KCM_MSG_LEN_SIZE;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek req->repbuf.v_rc.kiov_base = req->repbuf.rcbuf;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek req->repbuf.v_rc.kiov_len = KCM_RETCODE_SIZE;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek req->cctx = cctx;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek req->kctx = kctx;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return req;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic void kcm_recv(struct cli_ctx *cctx)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_req_ctx *req;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_ctx *kctx;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek int ret;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek kctx = talloc_get_type(cctx->rctx->pvt_ctx, struct kcm_ctx);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek req = talloc_get_type(cctx->state_ctx, struct kcm_req_ctx);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (req == NULL) {
bfc6d9d611bfbc54b3f738084d86fb887c8769b5Fabiano Fidêncio /* A new request comes in, setup data structures. */
bfc6d9d611bfbc54b3f738084d86fb887c8769b5Fabiano Fidêncio req = kcm_new_req(cctx, kctx);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (req == NULL) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek "Cannot set up client connection\n");
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek talloc_free(cctx);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek cctx->state_ctx = req;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
786c40023e1348e7613805446ae821af7030b5d3Fabiano Fidêncio ret = kcm_recv_data(req, cctx->cfd, &req->reqbuf);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek switch (ret) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek case ENODATA:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek DEBUG(SSSDBG_TRACE_ALL, "Client closed connection.\n");
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek talloc_free(cctx);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek case EAGAIN:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek DEBUG(SSSDBG_TRACE_ALL, "Retry later\n");
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek case EOK:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* all fine */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek break;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek default:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek "Failed to receive data (%d, %s), aborting client\n",
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ret, sss_strerror(ret));
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek talloc_free(cctx);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ret = kcm_input_parse(&req->reqbuf, &req->op_io);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (ret != EOK) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE,
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek "Failed to parse data (%d, %s), aborting client\n",
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ret, sss_strerror(ret));
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek goto fail;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* do not read anymore, client is done sending */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek TEVENT_FD_NOT_READABLE(cctx->cfde);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
2b5518eeaacc6245cfa77ee4a7086f16208060fcJakub Hrozek ret = kcm_cmd_dispatch(kctx, req);
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek if (ret != EOK) {
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek "Failed to dispatch KCM operation [%d]: %s\n",
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek ret, sss_strerror(ret));
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek goto fail;
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek }
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek /* Dispatched request resumes in kcm_cmd_request_done */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekfail:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek /* Fail with reply */
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek kcm_reply_error(cctx, ret, &req->repbuf);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic int kcm_send_data(struct cli_ctx *cctx)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek struct kcm_req_ctx *req;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek errno_t ret;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek req = talloc_get_type(cctx->state_ctx, struct kcm_req_ctx);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ret = kcm_write_iovec(cctx->cfd, &req->repbuf.v_len);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (ret != EOK) {
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek "Failed to write the length iovec [%d]: %s\n",
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek ret, sss_strerror(ret));
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return ret;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ret = kcm_write_iovec(cctx->cfd, &req->repbuf.v_rc);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (ret != EOK) {
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek "Failed to write the retcode iovec [%d]: %s\n",
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek ret, sss_strerror(ret));
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return ret;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ret = kcm_write_iovec(cctx->cfd, &req->repbuf.v_msg);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (ret != EOK) {
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE,
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek "Failed to write the msg iovec [%d]: %s\n",
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek ret, sss_strerror(ret));
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return ret;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return EOK;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekstatic void kcm_send(struct cli_ctx *cctx)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek errno_t ret;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek ret = kcm_send_data(cctx);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek if (ret == EAGAIN) {
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek DEBUG(SSSDBG_TRACE_ALL, "Sending data again..\n");
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek } else if (ret != EOK) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek DEBUG(SSSDBG_FATAL_FAILURE, "Failed to send data, aborting client!\n");
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek talloc_free(cctx);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek }
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
1ec4198f38d34a1f82a2db55d8c9782a434fb55fJakub Hrozek DEBUG(SSSDBG_TRACE_INTERNAL, "All data sent!\n");
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek TEVENT_FD_NOT_WRITEABLE(cctx->cfde);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek TEVENT_FD_READABLE(cctx->cfde);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek talloc_zfree(cctx->state_ctx);
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozekstatic void kcm_fd_handler(struct tevent_context *ev,
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek struct tevent_fd *fde,
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek uint16_t flags, void *ptr)
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek{
01ef93a43e1629006416f33111f6077b3e92b175Fabiano Fidêncio sss_client_fd_handler(ptr, kcm_recv, kcm_send, flags);
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek}
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozekint kcm_connection_setup(struct cli_ctx *cctx)
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek cctx->cfd_handler = kcm_fd_handler;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return EOK;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek}
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozekkrb5_error_code sss2krb5_error(errno_t err)
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek{
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek switch (err) {
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek case EOK:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return 0;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek case ENOMEM:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return KRB5_CC_NOMEM;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek case EACCES:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return KRB5_FCC_PERM;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek case ERR_KCM_OP_NOT_IMPLEMENTED:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return KRB5_CC_NOSUPP;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek case ERR_WRONG_NAME_FORMAT:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return KRB5_CC_BADNAME;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek case ERR_NO_MATCHING_CREDS:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return KRB5_FCC_NOFILE;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek case ERR_NO_CREDS:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return KRB5_CC_NOTFOUND;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek case ERR_KCM_CC_END:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return KRB5_CC_END;
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek case ERR_KCM_MALFORMED_IN_PKT:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek case EINVAL:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek case EIO:
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return KRB5_CC_IO;
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek }
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
9dcdbf596e138df3eec202487549a67cd3b0091bJakub Hrozek return KRB5_FCC_INTERNAL;
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek}
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek/* Dummy, not used here but required to link to other responder files */
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozekstruct cli_protocol_version *register_cli_protocol_version(void)
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek{
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek return NULL;
b9c563c29243291f40489bb0dcbf3946fca72d58Jakub Hrozek}