@@ -617,23 +617,109 @@
COMMAND -- pkcs11-id-count (OpenVPN 2.1 or higher)
---------------------------------------------------
-Retrieve available number of certificates.
+Retrieve available number of PKCS#11 certificates.
+
+For management client versions <7:
+
+ pkcs11-id-count
+
+The reply is ">PKCS11ID-COUNT:<count>".
Example:
pkcs11-id-count
>PKCS11ID-COUNT:5
+For management client versions >= 7:
+
+ pkcs11-id-count
+
+The reply is a decimal count followed by "END" on a separate line.
+
+Example:
+
+ pkcs11-id-count
+ 5
+ END
+
COMMAND -- pkcs11-id-get (OpenVPN 2.1 or higher)
-------------------------------------------------
+Retrieve PKCS#11 certificates.
+
+For management client versions < 7:
+
+ pkcs11-id-get <index>
+
Retrieve certificate by index, the ID string should be provided
as PKCS#11 identity, the blob is a base 64 encoded certificate.
Example:
pkcs11-id-get 1
- PKCS11ID-ENTRY:'1', ID:'<snip>', BLOB:'<snip>'
+ >PKCS11ID-ENTRY:'1', ID:'<id>', BLOB:'<blob>'
+
+For management client versions >= 7:
+
+ pkcs11-id-get <index>
+ pkcs11-id-get <start> <end>
+ pkcs11-id-get all
+
+Retrieve a single PKCS#11 certificate at index <index> or multiple
+PKCS#11 certificates from index <start> to <end>-1. Alternatively
+<start> = "all" retrieves all PKCS#11 certificates. A comma separated
+list including index, PKCS#11 id and the base 64 encoded certificate
+will be returned. If any id retrieval results in a failure, the returned
+list will be partial and terminated by "ERROR: .." instead of "END".
+The "ERROR" message will include the index of failure.
+
+Example 1:
+
+ Management interface client sends:
+
+ pkcs11-id-get 1
+
+ OpenVPN daemon responds with:
+
+ 1,<id>,<blob>
+ END
+
+Example 2:
+
+ Management interface client sends:
+
+ pkcs11-id-get 1 3
+
+ OpenVPN daemon responds with:
+
+ 1,<id_a>,<blob_a>
+ 2,<id_b>,<blob_b>
+ END
+
+Example 3:
+
+ Management interface client sends:
+
+ pkcs11-id-get all
+
+ OpenVPN daemon with 3 PKCS#11 certificates responds with:
+
+ 0,<id_a>,<blob_a>
+ 1,<id_b>,<blob_b>
+ 2,<id_c>,<blob_c>
+ END
+
+Example 4:
+
+ Management interface client sends:
+
+ pkcs11-id-get all
+
+ OpenVPN daemon with 3 PKCS#11 certificates fails to retrieve index 1
+
+ 0,<id_a>,<blob_a>
+ ERROR: Failed to load PKCS#11 id at index: 1
+
COMMAND -- client-auth (OpenVPN 2.1 or higher)
-----------------------------------------------
@@ -1240,7 +1326,7 @@
"ERROR: [text]".
(2) For commands which print multiple lines of output,
- the last line will be "END".
+ the last line will be "END" or "ERROR: [text]".
(3) Real-time messages will be in the form ">[source]:[text]",
where source is "CLIENT", "ECHO", "FATAL", "HOLD", "INFO", "LOG",
@@ -74,6 +74,7 @@
MCV_USERNAME_ONLY = 4,
MCV_MULTILINE_PASSWORD = 5,
MCV_PREFERRED_USERNAME = 6,
+ MCV_MULTILINE_PKCS11_RESPONSE = 7,
};
struct management *management; /* GLOBAL */
@@ -120,7 +121,8 @@
msg(M_CLIENT, "pid : Show process ID of the current OpenVPN process.");
#ifdef ENABLE_PKCS11
msg(M_CLIENT, "pkcs11-id-count : Get number of available PKCS#11 identities.");
- msg(M_CLIENT, "pkcs11-id-get index : Get PKCS#11 identity at index.");
+ msg(M_CLIENT, "pkcs11-id-get i|all [j] : Get PKCS#11 identity at index = i.");
+ msg(M_CLIENT, " For version >= 7 also i to j-1 or all.");
#endif
msg(M_CLIENT, "client-auth CID KID : Authenticate client-id/key-id CID/KID (MULTILINE)");
msg(M_CLIENT, "client-auth-nt CID KID : Authenticate client-id/key-id CID/KID");
@@ -894,26 +896,81 @@
static void
man_pkcs11_id_count(const struct management *man)
{
- msg(M_CLIENT, ">PKCS11ID-COUNT:%d", pkcs11_management_id_count());
-}
-
-static void
-man_pkcs11_id_get(struct management *man, const int index)
-{
- char *id = NULL;
- char *base64 = NULL;
-
- if (pkcs11_management_id_get(index, &id, &base64))
+ if (man->connection.client_version >= MCV_MULTILINE_PKCS11_RESPONSE)
{
- msg(M_CLIENT, ">PKCS11ID-ENTRY:'%d', ID:'%s', BLOB:'%s'", index, id, base64);
+ msg(M_CLIENT, "%d", pkcs11_management_id_count());
+ msg(M_CLIENT, "END");
}
else
{
- msg(M_CLIENT, ">PKCS11ID-ENTRY:'%d'", index);
+ msg(M_CLIENT, ">PKCS11ID-COUNT:%d", pkcs11_management_id_count());
+ }
+}
+
+static void
+man_pkcs11_id_get(struct management *man, const char *p1, const char *p2)
+{
+ ASSERT(p1);
+
+ if ((streq(p1, "all") || p2 != NULL) && man->connection.client_version < MCV_MULTILINE_PKCS11_RESPONSE)
+ {
+ msg(M_CLIENT, "ERROR: Listing multiple ids is only supported for version >= %d", MCV_MULTILINE_PKCS11_RESPONSE);
+ return;
}
- free(id);
- free(base64);
+ if (man->connection.client_version >= MCV_MULTILINE_PKCS11_RESPONSE)
+ {
+ unsigned int count = pkcs11_management_id_count();
+ unsigned int from = (unsigned int)atoi(p1);
+ unsigned int to = p2 ? (unsigned int)atoi(p2) : from + 1;
+
+ if (streq(p1, "all"))
+ {
+ from = 0;
+ to = count;
+ }
+
+ bool error = false;
+ for (unsigned int i = from; i < min_uint(to, count) && !error; i++)
+ {
+ char *id = NULL;
+ char *base64 = NULL;
+
+ if (pkcs11_management_id_get(i, &id, &base64))
+ {
+ msg(M_CLIENT, "%u,%s,%s", i, id, base64);
+ }
+ else
+ {
+ error = true;
+ msg(M_CLIENT, "ERROR: Failed to load PKCS#11 id at index: %u", i);
+ }
+ free(id);
+ free(base64);
+ }
+ if (!error)
+ {
+ msg(M_CLIENT, "END");
+ }
+ }
+ else
+ {
+ int index = atoi(p1);
+
+ char *id = NULL;
+ char *base64 = NULL;
+
+ if (pkcs11_management_id_get(index, &id, &base64))
+ {
+ msg(M_CLIENT, ">PKCS11ID-ENTRY:'%d', ID:'%s', BLOB:'%s'", index, id, base64);
+ }
+ else
+ {
+ msg(M_CLIENT, ">PKCS11ID-ENTRY:'%d'", index);
+ }
+ free(id);
+ free(base64);
+ }
}
#endif /* ifdef ENABLE_PKCS11 */
@@ -1838,9 +1895,9 @@
}
else if (streq(p[0], "pkcs11-id-get"))
{
- if (man_need(p, 1, 0))
+ if (man_need(p, 1, MN_AT_LEAST))
{
- man_pkcs11_id_get(man, atoi(p[1]));
+ man_pkcs11_id_get(man, p[1], p[2]);
}
}
#endif
@@ -50,7 +50,7 @@
#include "socket_util.h"
#include "mroute.h"
-#define MANAGEMENT_VERSION 6
+#define MANAGEMENT_VERSION 7
#define MANAGEMENT_N_PASSWORD_RETRIES 3
#define MANAGEMENT_LOG_HISTORY_INITIAL_SIZE 100
#define MANAGEMENT_ECHO_BUFFER_SIZE 100