Blame SOURCES/opencryptoki-3.16.0-fa94a16116d8382a987ddf9e8cdd88027dd1f647.patch

9c2944
commit fa94a16116d8382a987ddf9e8cdd88027dd1f647
9c2944
Author: Ingo Franzki <ifranzki@linux.ibm.com>
9c2944
Date:   Tue Feb 16 17:13:34 2021 +0100
9c2944
9c2944
    Event support: Add event client
9c2944
    
9c2944
    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
9c2944
9c2944
diff --git a/usr/lib/common/common.mk b/usr/lib/common/common.mk
9c2944
index 2178ad45..882c84f4 100644
9c2944
--- a/usr/lib/common/common.mk
9c2944
+++ b/usr/lib/common/common.mk
9c2944
@@ -4,7 +4,7 @@ noinst_HEADERS +=							\
9c2944
 	usr/lib/common/shared_memory.h usr/lib/common/tok_spec_struct.h	\
9c2944
 	usr/lib/common/trace.h usr/lib/common/h_extern.h		\
9c2944
 	usr/lib/common/sw_crypt.h usr/lib/common/defs.h			\
9c2944
-	usr/lib/common/p11util.h					\
9c2944
+	usr/lib/common/p11util.h usr/lib/common/event_client.h		\
9c2944
 	usr/lib/common/list.h usr/lib/common/tok_specific.h
9c2944
 
9c2944
 usr/lib/common/lexer.c: usr/lib/common/parser.h
9c2944
diff --git a/usr/lib/common/event_client.c b/usr/lib/common/event_client.c
9c2944
new file mode 100644
9c2944
index 00000000..86117b84
9c2944
--- /dev/null
9c2944
+++ b/usr/lib/common/event_client.c
9c2944
@@ -0,0 +1,215 @@
9c2944
+/*
9c2944
+ * COPYRIGHT (c) International Business Machines Corp. 2021
9c2944
+ *
9c2944
+ * This program is provided under the terms of the Common Public License,
9c2944
+ * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
9c2944
+ * software constitutes recipient's acceptance of CPL-1.0 terms which can be
9c2944
+ * found in the file LICENSE file or at
9c2944
+ * https://opensource.org/licenses/cpl1.0.php
9c2944
+ */
9c2944
+
9c2944
+#include <stdlib.h>
9c2944
+#include <string.h>
9c2944
+#include <errno.h>
9c2944
+#include <sys/un.h>
9c2944
+#include <sys/socket.h>
9c2944
+#include <sys/stat.h>
9c2944
+#include <stdio.h>
9c2944
+#include <unistd.h>
9c2944
+#include <grp.h>
9c2944
+
9c2944
+#include "slotmgr.h"
9c2944
+#include "event_client.h"
9c2944
+
9c2944
+static int connect_socket(const char *file_path)
9c2944
+{
9c2944
+    int socketfd;
9c2944
+    struct sockaddr_un daemon_address;
9c2944
+    struct stat file_info;
9c2944
+    struct group *grp;
9c2944
+    int rc;
9c2944
+
9c2944
+    if (stat(file_path, &file_info))
9c2944
+        return -errno;
9c2944
+
9c2944
+    grp = getgrnam("pkcs11");
9c2944
+    if (!grp)
9c2944
+        return -errno;
9c2944
+
9c2944
+    if (file_info.st_uid != 0 || file_info.st_gid != grp->gr_gid)
9c2944
+        return -EPERM;
9c2944
+
9c2944
+    if ((socketfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
9c2944
+        return -errno;
9c2944
+
9c2944
+    memset(&daemon_address, 0, sizeof(struct sockaddr_un));
9c2944
+    daemon_address.sun_family = AF_UNIX;
9c2944
+    strcpy(daemon_address.sun_path, file_path);
9c2944
+
9c2944
+    if (connect(socketfd, (struct sockaddr *) &daemon_address,
9c2944
+                sizeof(struct sockaddr_un)) != 0) {
9c2944
+        rc = -errno;
9c2944
+        goto error;
9c2944
+    }
9c2944
+
9c2944
+    return socketfd;
9c2944
+
9c2944
+error:
9c2944
+    close(socketfd);
9c2944
+    return rc;
9c2944
+}
9c2944
+
9c2944
+static ssize_t read_all(int socketfd, char *buffer, size_t size)
9c2944
+{
9c2944
+    size_t bytes_received = 0;
9c2944
+    ssize_t n;
9c2944
+
9c2944
+    while (bytes_received < size) {
9c2944
+        n = read(socketfd, buffer + bytes_received, size - bytes_received);
9c2944
+        if (n < 0) {
9c2944
+            // read error
9c2944
+            if (errno == EINTR)
9c2944
+                continue;
9c2944
+            return -errno;
9c2944
+        }
9c2944
+        if (n == 0)
9c2944
+            break;
9c2944
+
9c2944
+        bytes_received += n;
9c2944
+    }
9c2944
+
9c2944
+    return bytes_received;
9c2944
+}
9c2944
+
9c2944
+static ssize_t send_all(int socketfd, char *buffer, size_t size)
9c2944
+{
9c2944
+    size_t bytes_sent = 0;
9c2944
+    ssize_t n;
9c2944
+
9c2944
+    while (bytes_sent < size) {
9c2944
+        n = send(socketfd, buffer + bytes_sent, size - bytes_sent, 0);
9c2944
+        if (n < 0) {
9c2944
+            // send error
9c2944
+            if (errno == EINTR)
9c2944
+                continue;
9c2944
+            return -errno;
9c2944
+        }
9c2944
+        if (n == 0)
9c2944
+            break;
9c2944
+
9c2944
+        bytes_sent += n;
9c2944
+    }
9c2944
+
9c2944
+    return bytes_sent;
9c2944
+}
9c2944
+
9c2944
+/*
9c2944
+ * Initialize an admin connection to the pkcsslotd.
9c2944
+ * Returns a file descriptor representing the connection, or a negative errno
9c2944
+ * in case of an error.
9c2944
+ */
9c2944
+int init_event_client()
9c2944
+{
9c2944
+    int fd;
9c2944
+
9c2944
+    fd = connect_socket(ADMIN_SOCKET_FILE_PATH);
9c2944
+
9c2944
+    return fd;
9c2944
+}
9c2944
+
9c2944
+/*
9c2944
+ * Send an event though the admin connection to the pkcsslotd, and thus to
9c2944
+ * all active token instances.
9c2944
+ * If parameter fd is < 0, then a connection to pkcsslotd is established
9c2944
+ * inside the function and closed before return. This is for a one shot event.
9c2944
+ * Otherwise, pass a file descriptor received from init_event_client(). This
9c2944
+ * is to send multiple events.
9c2944
+ * Event type is mandatory, flags can be zero.
9c2944
+ * The event payload is optional, if payload_len is non-zero, then payload must
9c2944
+ * point to a buffer containing the payload to send with the event.
9c2944
+ * The event destination can be used to selectively send the event to certain
9c2944
+ * token instances only. If destination is NULL, it is sent to all token
9c2944
+ * instances.
9c2944
+ * If flag EVENT_FLAGS_REPLY_REQ is on in the flags parameter, then it is waited
9c2944
+ * until all active token instances have replied. The combined result of the
9c2944
+ * replies from the token instances is returned in the reply structure.
9c2944
+ * Parameter reply must be non-NULL if flag EVENT_FLAGS_REPLY_REQ is set.
9c2944
+ * Returns zero for success, or a negative errno in case of an error. In most
9c2944
+ * error cases the connection to the pkcsslotd is out of sequence and can no
9c2944
+ * longer be used to send further events.
9c2944
+ */
9c2944
+int send_event(int fd, unsigned int type, unsigned int flags,
9c2944
+               unsigned int payload_len, const char *payload,
9c2944
+               const struct event_destination *destination,
9c2944
+               struct event_reply *reply)
9c2944
+{
9c2944
+    event_msg_t event_msg;
9c2944
+    event_reply_t event_reply;
9c2944
+    int rc, term = 0;
9c2944
+
9c2944
+    if (payload_len > 0 && payload == NULL)
9c2944
+        return -EINVAL;
9c2944
+    if ((flags & EVENT_FLAGS_REPLY_REQ) && reply == NULL)
9c2944
+        return -EINVAL;
9c2944
+    if (payload_len > EVENT_MAX_PAYLOAD_LENGTH)
9c2944
+        return -EMSGSIZE;
9c2944
+
9c2944
+    if (fd < 0) {
9c2944
+        fd = init_event_client();
9c2944
+        if (fd < 0)
9c2944
+            return fd;
9c2944
+        term = 1;
9c2944
+    }
9c2944
+
9c2944
+    memset(&event_msg, 0, sizeof(event_msg));
9c2944
+    event_msg.version = EVENT_VERSION_1;
9c2944
+    event_msg.type = type;
9c2944
+    event_msg.flags = flags;
9c2944
+    if (destination != NULL) {
9c2944
+        event_msg.token_type = destination->token_type;
9c2944
+        memcpy(event_msg.token_label, destination->token_label,
9c2944
+               sizeof(event_msg.token_label));
9c2944
+        event_msg.process_id = destination->process_id;
9c2944
+    } else {
9c2944
+        memset(event_msg.token_label, ' ', sizeof(event_msg.token_label));
9c2944
+    }
9c2944
+    event_msg.payload_len = payload_len;
9c2944
+
9c2944
+    rc = send_all(fd, (char *)&event_msg, sizeof(event_msg));
9c2944
+    if (rc < 0)
9c2944
+        goto out;
9c2944
+
9c2944
+    if (payload_len > 0) {
9c2944
+        rc = send_all(fd, (char *)payload, payload_len);
9c2944
+        if (rc < 0)
9c2944
+            goto out;
9c2944
+    }
9c2944
+
9c2944
+    if (flags & EVENT_FLAGS_REPLY_REQ) {
9c2944
+        rc = read_all(fd, (char *)&event_reply, sizeof(event_reply));
9c2944
+        if (rc < 0)
9c2944
+            goto out;
9c2944
+
9c2944
+        reply->positive_replies = event_reply.positive_replies;
9c2944
+        reply->negative_replies = event_reply.negative_replies;
9c2944
+        reply->nothandled_replies = event_reply.nothandled_replies;
9c2944
+    }
9c2944
+
9c2944
+    rc = 0;
9c2944
+
9c2944
+out:
9c2944
+    if (term)
9c2944
+        term_event_client(fd);
9c2944
+
9c2944
+    return rc;
9c2944
+}
9c2944
+
9c2944
+/*
9c2944
+ * Terminate the admin connection to the pkcsslotd.
9c2944
+ */
9c2944
+void term_event_client(int fd)
9c2944
+{
9c2944
+    if (fd >= 0)
9c2944
+        close(fd);
9c2944
+}
9c2944
+
9c2944
diff --git a/usr/lib/common/event_client.h b/usr/lib/common/event_client.h
9c2944
new file mode 100644
9c2944
index 00000000..2e4917b0
9c2944
--- /dev/null
9c2944
+++ b/usr/lib/common/event_client.h
9c2944
@@ -0,0 +1,39 @@
9c2944
+/*
9c2944
+ * COPYRIGHT (c) International Business Machines Corp. 2021
9c2944
+ *
9c2944
+ * This program is provided under the terms of the Common Public License,
9c2944
+ * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
9c2944
+ * software constitutes recipient's acceptance of CPL-1.0 terms which can be
9c2944
+ * found in the file LICENSE file or at
9c2944
+ * https://opensource.org/licenses/cpl1.0.php
9c2944
+ */
9c2944
+
9c2944
+
9c2944
+#ifndef _EVENT_CLIENT_H_
9c2944
+#define _EVENT_CLIENT_H_
9c2944
+
9c2944
+#include "events.h"
9c2944
+
9c2944
+struct event_destination {
9c2944
+    unsigned int token_type;    /* Destination token type: EVENT_TOK_TYPE_xxx */
9c2944
+    char token_label[member_size(event_msg_t, token_label)];
9c2944
+                                /* Label of destination token (or blanks) */
9c2944
+    pid_t process_id;           /* Process ID of destination process (or 0) */
9c2944
+};
9c2944
+
9c2944
+struct event_reply {
9c2944
+    unsigned long positive_replies;
9c2944
+    unsigned long negative_replies;
9c2944
+    unsigned long nothandled_replies;
9c2944
+};
9c2944
+
9c2944
+int init_event_client();
9c2944
+
9c2944
+int send_event(int fd, unsigned int type, unsigned int flags,
9c2944
+               unsigned int payload_len, const char *payload,
9c2944
+               const struct event_destination *destination,
9c2944
+               struct event_reply *reply);
9c2944
+
9c2944
+void term_event_client(int fd);
9c2944
+
9c2944
+#endif