mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
libekmfweb: Login to EKMF Web
To perform operations in EKMF Web, the user must log in with a EKMF Web user id and a time based one time passcode. The passcode can be obtained by the user from the EKMF Web user interface, after logging in into EKMF Web. That way a two factor authentication is performed. The client passes the passcode to EKMF Web retrieves a bearer token from EKMF Web which it then uses on subsequent requests to authenticate with EKMF Web. Such a bearer token is valid for several minutes, thus no re-login is required for zkey commands run during that time. Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
e44ae22989
commit
8c0f2491a3
@@ -136,6 +136,36 @@ int ekmf_print_certificates(const char *cert_pem, bool verbose);
|
||||
int ekmf_check_login_token(const struct ekmf_config *config, bool *valid,
|
||||
char **login_token, bool verbose);
|
||||
|
||||
/**
|
||||
* Performs a login of the specified user with a passcode. On success the
|
||||
* returned login token is stored in the file denoted by field login_token
|
||||
* of the config structure, so that it can be used by subsequent requests.
|
||||
*
|
||||
* To perform a single request, set curl_handle to NULL. This will cause the
|
||||
* function to initialize a new CURL handle, use it, and destroy it.
|
||||
* If you plan to perform multiple requests to the same host, supply the address
|
||||
* of a CURL pointer that is initially NULL. This function will then initialize
|
||||
* a new CURL handle on the first call. On subsequent calls, pass in the address
|
||||
* of the same CURL pointer so that the CURL handle is reused. After the last
|
||||
* request, the CURL handle must be destroyed by calling ekmf_curl_destroy).
|
||||
*
|
||||
* @param config the configuration structure
|
||||
* @param curl_handle address of a CURL handle used for reusing the same
|
||||
* CURL handle with multiple requests.
|
||||
* @param user_id the user-ID to log-in.
|
||||
* @param passcode the passcode to log-in the user.
|
||||
* @param error_msg on return: If not NULL, then a textual error message
|
||||
* is returned in case of a failing request. The caller
|
||||
* must free the error string when it is not NULL.
|
||||
* @param verbose if true, verbose messages are printed
|
||||
*
|
||||
* @returns zero for success, a negative errno in case of an error.
|
||||
* -EACCES is returned, if the passcode is no longer valid.
|
||||
*/
|
||||
int ekmf_login(const struct ekmf_config *config, CURL **curl_handle,
|
||||
const char *user_id, const char *passcode, char **error_msg,
|
||||
bool verbose);
|
||||
|
||||
enum ekmf_key_type {
|
||||
EKMF_KEY_TYPE_ECC = 1,
|
||||
EKMF_KEY_TYPE_RSA = 2,
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#define MAX_SYM_KEY_BLOB_SIZE CCA_MAX_SYM_KEY_TOKEN_SIZE
|
||||
|
||||
#define EKMF_URI_SYSTEM_PUBKEY "/api/v1/system/publicKey"
|
||||
#define EKMF_URI_SYSTEM_LOGIN "/api/v1/system/login"
|
||||
#define EKMF_URI_KEYS_GENERATE "/api/v1/keys"
|
||||
#define EKMF_URI_KEYS_EXPORT "/api/v1/keys/%s/export"
|
||||
#define EKMF_URI_KEYS_TAGS "/api/v1/keys/%s/tags"
|
||||
@@ -1243,6 +1244,142 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a login of the specified user with a passcode. On success the
|
||||
* returned login token is stored in the file denoted by field login_token
|
||||
* of the config structure, so that it can be used by subsequent requests.
|
||||
*
|
||||
* To perform a single request, set curl_handle to NULL. This will cause the
|
||||
* function to initialize a new CURL handle, use it, and destroy it.
|
||||
* If you plan to perform multiple requests to the same host, supply the address
|
||||
* of a CURL pointer that is initially NULL. This function will then initialize
|
||||
* a new CURL handle on the first call. On subsequent calls, pass in the address
|
||||
* of the same CURL pointer so that the CURL handle is reused. After the last
|
||||
* request, the CURL handle must be destroyed by calling ekmf_curl_destroy).
|
||||
*
|
||||
* @param config the configuration structure
|
||||
* @param curl_handle address of a CURL handle used for reusing the same
|
||||
* CURL handle with multiple requests.
|
||||
* @param user_id the user-ID to log-in.
|
||||
* @param passcode the passcode to log-in the user.
|
||||
* @param error_msg on return: If not NULL, then a textual error message
|
||||
* is returned in case of a failing request. The caller
|
||||
* must free the error string when it is not NULL.
|
||||
* @param verbose if true, verbose messages are printed
|
||||
*
|
||||
* @returns zero for success, a negative errno in case of an error.
|
||||
* -EACCES is returned, if the passcode is no longer valid.
|
||||
*/
|
||||
int ekmf_login(const struct ekmf_config *config, CURL **curl_handle,
|
||||
const char *user_id, const char *passcode, char **error_msg,
|
||||
bool verbose)
|
||||
{
|
||||
json_object *response_obj = NULL;
|
||||
json_object *request_obj = NULL;
|
||||
const char *login_token, *tok;
|
||||
CURL *curl = NULL;
|
||||
long status_code;
|
||||
FILE *fp = NULL;
|
||||
size_t count;
|
||||
int rc;
|
||||
|
||||
if (config == NULL || user_id == NULL || passcode == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
rc = _ekmf_get_curl_handle(curl_handle, &curl);
|
||||
if (rc != 0) {
|
||||
pr_verbose(verbose, "Failed to get CURL handle");
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
request_obj = json_object_new_object();
|
||||
JSON_CHECK_ERROR(request_obj == NULL, rc, -ENOMEM,
|
||||
"Failed to generate JSON object", verbose, out);
|
||||
|
||||
rc = json_object_object_add_ex(request_obj, "userId",
|
||||
json_object_new_string(user_id), 0);
|
||||
JSON_CHECK_ERROR(rc != 0, rc, -EIO, "Failed to add data to JSON object",
|
||||
verbose, out);
|
||||
|
||||
rc = json_object_object_add_ex(request_obj, "passcode",
|
||||
json_object_new_string(passcode), 0);
|
||||
JSON_CHECK_ERROR(rc != 0, rc, -EIO, "Failed to add data to JSON object",
|
||||
verbose, out);
|
||||
|
||||
rc = _ekmf_perform_request(config, EKMF_URI_SYSTEM_LOGIN, "POST",
|
||||
request_obj, NULL, NULL, &response_obj, NULL,
|
||||
&status_code, error_msg, curl, verbose);
|
||||
if (rc != 0) {
|
||||
pr_verbose(verbose, "Failed perform the REST call");
|
||||
if (rc > 0)
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (status_code) {
|
||||
case 200:
|
||||
break;
|
||||
case 410:
|
||||
pr_verbose(verbose, "The passcode is no longer valid");
|
||||
rc = -EACCES;
|
||||
goto out;
|
||||
default:
|
||||
pr_verbose(verbose, "REST Call failed with HTTP status code: "
|
||||
"%ld", status_code);
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
JSON_CHECK_OBJ(response_obj, json_type_object, rc, -EIO,
|
||||
"No or invalid response content", verbose, out);
|
||||
|
||||
login_token = json_get_string(response_obj, "authorizationToken");
|
||||
JSON_CHECK_ERROR(login_token == NULL, rc, -EBADMSG,
|
||||
"Invalid response content", verbose, out);
|
||||
|
||||
if (strncmp(login_token, "Bearer ", 7) != 0) {
|
||||
rc = -EBADMSG;
|
||||
pr_verbose(verbose, "Received token is not a Bearer token");
|
||||
goto out;
|
||||
}
|
||||
|
||||
tok = &login_token[7];
|
||||
while (*tok == ' ')
|
||||
tok++;
|
||||
|
||||
fp = fopen(config->login_token, "w");
|
||||
if (fp == NULL) {
|
||||
rc = -errno;
|
||||
pr_verbose(verbose, "Failed to open file %s: '%s'",
|
||||
config->login_token, strerror(-rc));
|
||||
goto out;
|
||||
}
|
||||
|
||||
count = fwrite(tok, 1, strlen(tok), fp);
|
||||
if (count != strlen(tok)) {
|
||||
pr_verbose(verbose, "Failed to write the token");
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pr_verbose(verbose, "Login token successfully updated in file '%s'",
|
||||
config->login_token);
|
||||
|
||||
out:
|
||||
_ekmf_release_curl_handle(curl_handle, curl);
|
||||
|
||||
if (request_obj != NULL)
|
||||
json_object_put(request_obj);
|
||||
if (response_obj != NULL)
|
||||
json_object_put(response_obj);
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the EKMFWeb server's public signing key and store it into PEM file
|
||||
* specified in field server_pubkey of the config structure.
|
||||
|
||||
@@ -3,6 +3,7 @@ LIBEKMFWEB_1.0 {
|
||||
ekmf_get_server_cert_chain;
|
||||
ekmf_print_certificates;
|
||||
ekmf_check_login_token;
|
||||
ekmf_login;
|
||||
ekmf_generate_identity_key;
|
||||
ekmf_reencipher_identity_key;
|
||||
ekmf_generate_csr;
|
||||
|
||||
Reference in New Issue
Block a user