/*
* Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include "internal/cryptlib.h"
#include <openssl/e_os2.h>
#include <openssl/buffer.h>
#include <openssl/ui.h>
#include <openssl/err.h>
#include "ui_locl.h"
UI *UI_new(void)
{
return UI_new_method(NULL);
}
UI *UI_new_method(const UI_METHOD *method)
{
UI *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
UIerr(UI_F_UI_NEW_METHOD, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
UIerr(UI_F_UI_NEW_METHOD, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
if (method == NULL)
method = UI_get_default_method();
if (method == NULL)
method = UI_null();
ret->meth = method;
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data)) {
OPENSSL_free(ret);
return NULL;
}
return ret;
}
static void free_string(UI_STRING *uis)
{
if (uis->flags & OUT_STRING_FREEABLE) {
OPENSSL_free((char *)uis->out_string);
switch (uis->type) {
case UIT_BOOLEAN:
OPENSSL_free((char *)uis->_.boolean_data.action_desc);
OPENSSL_free((char *)uis->_.boolean_data.ok_chars);
OPENSSL_free((char *)uis->_.boolean_data.cancel_chars);
break;
case UIT_NONE:
case UIT_PROMPT:
case UIT_VERIFY:
case UIT_ERROR:
case UIT_INFO:
break;
}
}
OPENSSL_free(uis);
}
void UI_free(UI *ui)
{
if (ui == NULL)
return;
if ((ui->flags & UI_FLAG_DUPL_DATA) != 0) {
ui->meth->ui_destroy_data(ui, ui->user_data);
}
sk_UI_STRING_pop_free(ui->strings, free_string);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data);
CRYPTO_THREAD_lock_free(ui->lock);
OPENSSL_free(ui);
}
static int allocate_string_stack(UI *ui)
{
if (ui->strings == NULL) {
ui->strings = sk_UI_STRING_new_null();
if (ui->strings == NULL) {
return -1;
}
}
return 0;
}
static UI_STRING *general_allocate_prompt(UI *ui, const char *prompt,
int prompt_freeable,
enum UI_string_types type,
int input_flags, char *result_buf)
{
UI_STRING *ret = NULL;
if (prompt == NULL) {
UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, ERR_R_PASSED_NULL_PARAMETER);
} else if ((type == UIT_PROMPT || type == UIT_VERIFY
|| type == UIT_BOOLEAN) && result_buf == NULL) {
UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, UI_R_NO_RESULT_BUFFER);
} else if ((ret = OPENSSL_malloc(sizeof(*ret))) != NULL) {
ret->out_string = prompt;
ret->flags = prompt_freeable ? OUT_STRING_FREEABLE : 0;
ret->input_flags = input_flags;
ret->type = type;
ret->result_buf = result_buf;
}
return ret;
}
static int general_allocate_string(UI *ui, const char *prompt,
int prompt_freeable,
enum UI_string_types type, int input_flags,
char *result_buf, int minsize, int maxsize,
const char *test_buf)
{
int ret = -1;
UI_STRING *s = general_allocate_prompt(ui, prompt