Blame SOURCES/opencryptoki-3.16.0-fa94a16116d8382a987ddf9e8cdd88027dd1f647.patch

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