From: Marvin Wunderlich <[email protected]> Responses to the management interface commands pkcs11-id-[get|count] did not follow the standard syntax, but instead looked like notifications.
Introduce a new management interface version so that clients announcing versions >= 7 will receive responses in the new format while keeping compatibility for older client versions. If a client announces a management version >= 7 the responses conform to the common multiline + END syntax. At the same time, it is now possible to query all PKCS#11 ids using "all" or a range from "start" to "end" - 1. Failures to retrieve an id will return a partial response terminated by an "ERROR" message including the erroneous index. The response format for pkcs11-id-get was changed to return a comma separated list (index,id,cert_blob) which is easier to parse. Change-Id: I09e55085cde6dbc0040e111a42128527d59832b8 Signed-off-by: Marvin Wunderlich <[email protected]> Acked-by: Selva Nair <[email protected]> Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/2148 --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/2148 This mail reflects revision 5 of this Change. Acked-by according to Gerrit (reflected above): Selva Nair <[email protected]> diff --git a/doc/management-notes.txt b/doc/management-notes.txt index 6c798c0..42ea644 100644 --- a/doc/management-notes.txt +++ b/doc/management-notes.txt @@ -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", diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c index 58f63e6..f00eb30 100644 --- a/src/openvpn/manage.c +++ b/src/openvpn/manage.c @@ -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 diff --git a/src/openvpn/manage.h b/src/openvpn/manage.h index 82c0caa..1d2aff1 100644 --- a/src/openvpn/manage.h +++ b/src/openvpn/manage.h @@ -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 _______________________________________________ Openvpn-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openvpn-devel
