Blame usr/sbin/pkcsslotd/socket_server.c

Packit Service 0210bb
/*
Packit Service 0210bb
 * This program is provided under the terms of the Common Public License,
Packit Service 0210bb
 * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
Packit Service 0210bb
 * software constitutes recipient's acceptance of CPL-1.0 terms which can be
Packit Service 0210bb
 * found in the file LICENSE file or at
Packit Service 0210bb
 * https://opensource.org/licenses/cpl1.0.php
Packit Service 0210bb
 */
Packit Service 0210bb
Packit Service 0210bb
/* (C) COPYRIGHT Google Inc. 2013 */
Packit Service 0210bb
Packit Service 0210bb
#include <errno.h>
Packit Service 0210bb
#include <stdio.h>
Packit Service 0210bb
#include <unistd.h>
Packit Service 0210bb
#include <string.h>
Packit Service 0210bb
Packit Service 0210bb
#include <sys/time.h>
Packit Service 0210bb
#include <sys/socket.h>
Packit Service 0210bb
#include <sys/un.h>
Packit Service 0210bb
#include <sys/select.h>
Packit Service 0210bb
#include <sys/stat.h>
Packit Service 0210bb
#include <grp.h>
Packit Service 0210bb
Packit Service 0210bb
#include "log.h"
Packit Service 0210bb
#include "slotmgr.h"
Packit Service 0210bb
#include "pkcsslotd.h"
Packit Service 0210bb
#include "apictl.h"
Packit Service 0210bb
Packit Service 0210bb
// Creates the daemon's listener socket, to which clients will connect and
Packit Service 0210bb
// retrieve slot information through.  Returns the file descriptor of the
Packit Service 0210bb
// created socket.
Packit Service 0210bb
int CreateListenerSocket(void)
Packit Service 0210bb
{
Packit Service 0210bb
    struct sockaddr_un address;
Packit Service 0210bb
    struct group *grp;
Packit Service 0210bb
    int socketfd;
Packit Service 0210bb
Packit Service 0210bb
    socketfd = socket(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
Packit Service 0210bb
    if (socketfd < 0) {
Packit Service 0210bb
        ErrLog("Failed to create listener socket, errno 0x%X.", errno);
Packit Service 0210bb
        return -1;
Packit Service 0210bb
    }
Packit Service 0210bb
    if (unlink(SOCKET_FILE_PATH) && errno != ENOENT) {
Packit Service 0210bb
        ErrLog("Failed to unlink socket file, errno 0x%X.", errno);
Packit Service 0210bb
        close(socketfd);
Packit Service 0210bb
        return -1;
Packit Service 0210bb
    }
Packit Service 0210bb
Packit Service 0210bb
    memset(&address, 0, sizeof(struct sockaddr_un));
Packit Service 0210bb
    address.sun_family = AF_UNIX;
Packit Service 0210bb
    strcpy(address.sun_path, SOCKET_FILE_PATH);
Packit Service 0210bb
Packit Service 0210bb
    if (bind(socketfd,
Packit Service 0210bb
             (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0) {
Packit Service 0210bb
        ErrLog("Failed to bind to socket, errno 0x%X.", errno);
Packit Service 0210bb
        close(socketfd);
Packit Service 0210bb
        return -1;
Packit Service 0210bb
    }
Packit Service 0210bb
    // make socket file part of the pkcs11 group, and write accessable
Packit Service 0210bb
    // for that group
Packit Service 0210bb
    grp = getgrnam("pkcs11");
Packit Service 0210bb
    if (!grp) {
Packit Service 0210bb
        ErrLog("Group PKCS#11 does not exist");
Packit Service 0210bb
        DetachSocketListener(socketfd);
Packit Service 0210bb
        return -1;
Packit Service 0210bb
    }
Packit Service 0210bb
    if (chown(SOCKET_FILE_PATH, 0, grp->gr_gid)) {
Packit Service 0210bb
        ErrLog("Could not change file group on socket, errno 0x%X.", errno);
Packit Service 0210bb
        DetachSocketListener(socketfd);
Packit Service 0210bb
        return -1;
Packit Service 0210bb
    }
Packit Service 0210bb
    if (chmod(SOCKET_FILE_PATH,
Packit Service 0210bb
              S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP | S_IXUSR | S_IXGRP)) {
Packit Service 0210bb
        ErrLog("Could not change file permissions on socket, errno 0x%X.",
Packit Service 0210bb
               errno);
Packit Service 0210bb
        DetachSocketListener(socketfd);
Packit Service 0210bb
        return -1;
Packit Service 0210bb
    }
Packit Service 0210bb
Packit Service 0210bb
    if (listen(socketfd, 20) != 0) {
Packit Service 0210bb
        ErrLog("Failed to listen to socket, errno 0x%X.", errno);
Packit Service 0210bb
        DetachSocketListener(socketfd);
Packit Service 0210bb
        return -1;
Packit Service 0210bb
    }
Packit Service 0210bb
Packit Service 0210bb
    return socketfd;
Packit Service 0210bb
}
Packit Service 0210bb
Packit Service 0210bb
int InitSocketData(Slot_Mgr_Socket_t *socketData)
Packit Service 0210bb
{
Packit Service 0210bb
    unsigned int processed = 0;
Packit Service 0210bb
Packit Service 0210bb
    PopulateCKInfo(&(socketData->ck_info));
Packit Service 0210bb
    socketData->num_slots = NumberSlotsInDB;
Packit Service 0210bb
    PopulateSlotInfo(socketData->slot_info, &processed);
Packit Service 0210bb
Packit Service 0210bb
    /* check that we read in correct amount of slots */
Packit Service 0210bb
    if (processed != NumberSlotsInDB) {
Packit Service 0210bb
        ErrLog("Failed to populate slot info.\n");
Packit Service 0210bb
        return FALSE;
Packit Service 0210bb
    }
Packit Service 0210bb
Packit Service 0210bb
    return TRUE;
Packit Service 0210bb
}
Packit Service 0210bb
Packit Service 0210bb
int SocketConnectionHandler(int socketfd, int timeout_secs)
Packit Service 0210bb
{
Packit Service 0210bb
    int returnVal;
Packit Service 0210bb
    fd_set set;
Packit Service 0210bb
    struct timeval timeout;
Packit Service 0210bb
Packit Service 0210bb
    FD_ZERO(&set);
Packit Service 0210bb
    FD_SET(socketfd, &set);
Packit Service 0210bb
Packit Service 0210bb
    timeout.tv_sec = timeout_secs;
Packit Service 0210bb
    timeout.tv_usec = 0;
Packit Service 0210bb
Packit Service 0210bb
    returnVal = select(socketfd + 1, &set, NULL, NULL, &timeout);
Packit Service 0210bb
    if (returnVal == -1) {
Packit Service 0210bb
        ErrLog("select failed on socket connection, errno 0x%X.", errno);
Packit Service 0210bb
        return FALSE;
Packit Service 0210bb
    } else if (returnVal == 0) {
Packit Service 0210bb
        // select call timed out, return
Packit Service 0210bb
        return FALSE;
Packit Service 0210bb
    } else {
Packit Service 0210bb
        struct sockaddr_un address;
Packit Service 0210bb
        socklen_t address_length = sizeof(address);
Packit Service 0210bb
Packit Service 0210bb
        int connectionfd = accept(socketfd,
Packit Service 0210bb
                                  (struct sockaddr *) &address,
Packit Service 0210bb
                                  &address_length);
Packit Service 0210bb
        if (connectionfd < 0) {
Packit Service 0210bb
            if (errno != EAGAIN && errno != EWOULDBLOCK) {
Packit Service 0210bb
                /* These errors are allowed since
Packit Service 0210bb
                 * socket is non-blocking
Packit Service 0210bb
                 */
Packit Service 0210bb
                ErrLog("Failed to accept socket connection, errno 0x%X.",
Packit Service 0210bb
                       errno);
Packit Service 0210bb
            }
Packit Service 0210bb
            return FALSE;
Packit Service 0210bb
        }
Packit Service 0210bb
        if (write(connectionfd, &socketData, sizeof(socketData)) !=
Packit Service 0210bb
            sizeof(socketData)) {
Packit Service 0210bb
            ErrLog("Failed to write socket data, errno 0x%X.", errno);
Packit Service 0210bb
            close(connectionfd);
Packit Service 0210bb
            return FALSE;
Packit Service 0210bb
        }
Packit Service 0210bb
        close(connectionfd);
Packit Service 0210bb
        return TRUE;
Packit Service 0210bb
    }
Packit Service 0210bb
}
Packit Service 0210bb
Packit Service 0210bb
void DetachSocketListener(int socketfd)
Packit Service 0210bb
{
Packit Service 0210bb
    close(socketfd);
Packit Service 0210bb
    unlink(SOCKET_FILE_PATH);
Packit Service 0210bb
}