X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fui%2Fui_lib.c;h=85bf8c1f80b615be7f4b0baae58f58f8a19e7fed;hp=132236fe65095edaa3fce4e18328ee1ac54f4268;hb=HEAD;hpb=a63d5eaab28a20463818b43a76ce8acd19d58812 diff --git a/crypto/ui/ui_lib.c b/crypto/ui/ui_lib.c index 132236fe65..a8756af1cd 100644 --- a/crypto/ui/ui_lib.c +++ b/crypto/ui/ui_lib.c @@ -1,506 +1,927 @@ -/* crypto/ui/ui_lib.c -*- mode:C; c-file-style: "eay" -*- */ -/* Written by Richard Levitte (levitte@stacken.kth.se) for the OpenSSL - * project 2000. - */ -/* ==================================================================== - * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). +/* + * Copyright 2001-2023 The OpenSSL Project Authors. All Rights Reserved. * + * Licensed under the Apache License 2.0 (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 - +#include "internal/cryptlib.h" +#include +#include #include #include -#include "ui_locl.h" - -IMPLEMENT_STACK_OF(UI_STRING_ST) - -static const UI_METHOD *default_UI_meth=NULL; -static int ui_meth_num=0; -static STACK_OF(CRYPTO_EX_DATA_FUNCS) *ui_meth=NULL; +#include "ui_local.h" UI *UI_new(void) - { - return(UI_new_method(NULL)); - } +{ + return UI_new_method(NULL); +} UI *UI_new_method(const UI_METHOD *method) - { - UI *ret; - - ret=(UI *)OPENSSL_malloc(sizeof(UI)); - if (ret == NULL) - { - UIerr(UI_F_UI_NEW_METHOD,ERR_R_MALLOC_FAILURE); - return NULL; - } - if (method == NULL) - ret->meth=UI_get_default_method(); - else - ret->meth=method; - - ret->strings=NULL; - return ret; - } - -static void free_string(void *data) - { - UI_STRING *uis = (UI_STRING *)data; - if (uis->flags & OUT_STRING_FREEABLE) - OPENSSL_free((char *)uis->out_string); - OPENSSL_free(uis); - } +{ + UI *ret = OPENSSL_zalloc(sizeof(*ret)); + + if (ret == NULL) + return NULL; + + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + ERR_raise(ERR_LIB_UI, ERR_R_CRYPTO_LIB); + 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)) { + UI_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) - { - sk_UI_STRING_pop_free(ui->strings,free_string); - OPENSSL_free(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; - } +{ + 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) { + ERR_raise(ERR_LIB_UI, ERR_R_PASSED_NULL_PARAMETER); + } else if ((type == UIT_PROMPT || type == UIT_VERIFY + || type == UIT_BOOLEAN) && result_buf == NULL) { + ERR_raise(ERR_LIB_UI, UI_R_NO_RESULT_BUFFER); + } else if ((ret = OPENSSL_zalloc(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, - char *result_buf, int minsize, int maxsize, const char *test_buf) - { - int ret=-1; - - if (prompt == NULL) - { - UIerr(UI_F_GENERAL_ALLOCATE_STRING,ERR_R_PASSED_NULL_PARAMETER); - } - else if (allocate_string_stack(ui) >= 0) - { - UI_STRING *s=(UI_STRING *)OPENSSL_malloc(sizeof(UI_STRING)); - s->out_string=prompt; - s->flags=prompt_freeable ? OUT_STRING_FREEABLE : 0; - s->type=type; - s->result_buf=result_buf; - s->result_minsize=minsize; - s->result_maxsize=maxsize; - s->test_buf=test_buf; - ret=sk_UI_STRING_push(ui->strings, s); - } - return ret; - } - -/* Returns the index to the place in the stack or 0 for error. Uses a - direct reference to the prompt. */ -int UI_add_input_string(UI *ui, const char *prompt, int echo_p, - char *result_buf, int minsize, int maxsize) - { - return general_allocate_string(ui, prompt, 0, - echo_p?UI_STRING_ECHO:UI_STRING_NOECHO, - result_buf, minsize, maxsize, NULL); - } + 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, prompt_freeable, + type, input_flags, result_buf); + + if (s != NULL) { + if (allocate_string_stack(ui) >= 0) { + s->_.string_data.result_minsize = minsize; + s->_.string_data.result_maxsize = maxsize; + s->_.string_data.test_buf = test_buf; + ret = sk_UI_STRING_push(ui->strings, s); + /* sk_push() returns 0 on error. Let's adapt that */ + if (ret <= 0) { + ret--; + free_string(s); + } + } else + free_string(s); + } + return ret; +} + +static int general_allocate_boolean(UI *ui, + const char *prompt, + const char *action_desc, + const char *ok_chars, + const char *cancel_chars, + int prompt_freeable, + enum UI_string_types type, + int input_flags, char *result_buf) +{ + int ret = -1; + UI_STRING *s; + const char *p; + + if (ok_chars == NULL) { + ERR_raise(ERR_LIB_UI, ERR_R_PASSED_NULL_PARAMETER); + } else if (cancel_chars == NULL) { + ERR_raise(ERR_LIB_UI, ERR_R_PASSED_NULL_PARAMETER); + } else { + for (p = ok_chars; *p != '\0'; p++) { + if (strchr(cancel_chars, *p) != NULL) { + ERR_raise(ERR_LIB_UI, UI_R_COMMON_OK_AND_CANCEL_CHARACTERS); + } + } + + s = general_allocate_prompt(ui, prompt, prompt_freeable, + type, input_flags, result_buf); + + if (s != NULL) { + if (allocate_string_stack(ui) >= 0) { + s->_.boolean_data.action_desc = action_desc; + s->_.boolean_data.ok_chars = ok_chars; + s->_.boolean_data.cancel_chars = cancel_chars; + ret = sk_UI_STRING_push(ui->strings, s); + /* + * sk_push() returns 0 on error. Let's adapt that + */ + if (ret <= 0) { + ret--; + free_string(s); + } + } else + free_string(s); + } + } + return ret; +} + +/* + * Returns the index to the place in the stack or -1 for error. Uses a + * direct reference to the prompt. + */ +int UI_add_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize) +{ + return general_allocate_string(ui, prompt, 0, + UIT_PROMPT, flags, result_buf, minsize, + maxsize, NULL); +} /* Same as UI_add_input_string(), excepts it takes a copy of the prompt */ -int UI_dup_input_string(UI *ui, const char *prompt, int echo_p, - char *result_buf, int minsize, int maxsize) - { - char *prompt_copy=NULL; - - if (prompt) - { - prompt_copy=strdup(prompt); - if (prompt_copy == NULL) - { - UIerr(UI_F_UI_DUP_INPUT_STRING,ERR_R_MALLOC_FAILURE); - return 0; - } - } - - return general_allocate_string(ui, prompt, 1, - echo_p?UI_STRING_ECHO:UI_STRING_NOECHO, - result_buf, minsize, maxsize, NULL); - } - -int UI_add_verify_string(UI *ui, const char *prompt, int echo_p, - char *result_buf, int minsize, int maxsize, const char *test_buf) - { - return general_allocate_string(ui, prompt, 0, - echo_p?UI_VERIFY_ECHO:UI_VERIFY_NOECHO, - result_buf, minsize, maxsize, test_buf); - } - -int UI_dup_verify_string(UI *ui, const char *prompt, int echo_p, - char *result_buf, int minsize, int maxsize, const char *test_buf) - { - char *prompt_copy=NULL; - - if (prompt) - { - prompt_copy=strdup(prompt); - if (prompt_copy == NULL) - { - UIerr(UI_F_UI_DUP_VERIFY_STRING,ERR_R_MALLOC_FAILURE); - return -1; - } - } - - return general_allocate_string(ui, prompt, 1, - echo_p?UI_VERIFY_ECHO:UI_VERIFY_NOECHO, - result_buf, minsize, maxsize, test_buf); - } +int UI_dup_input_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize) +{ + char *prompt_copy = NULL; + + if (prompt != NULL) { + prompt_copy = OPENSSL_strdup(prompt); + if (prompt_copy == NULL) + return 0; + } + + return general_allocate_string(ui, prompt_copy, 1, + UIT_PROMPT, flags, result_buf, minsize, + maxsize, NULL); +} + +int UI_add_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, + const char *test_buf) +{ + return general_allocate_string(ui, prompt, 0, + UIT_VERIFY, flags, result_buf, minsize, + maxsize, test_buf); +} + +int UI_dup_verify_string(UI *ui, const char *prompt, int flags, + char *result_buf, int minsize, int maxsize, + const char *test_buf) +{ + char *prompt_copy = NULL; + + if (prompt != NULL) { + prompt_copy = OPENSSL_strdup(prompt); + if (prompt_copy == NULL) + return -1; + } + + return general_allocate_string(ui, prompt_copy, 1, + UIT_VERIFY, flags, result_buf, minsize, + maxsize, test_buf); +} + +int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf) +{ + return general_allocate_boolean(ui, prompt, action_desc, + ok_chars, cancel_chars, 0, UIT_BOOLEAN, + flags, result_buf); +} + +int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, + const char *ok_chars, const char *cancel_chars, + int flags, char *result_buf) +{ + char *prompt_copy = NULL; + char *action_desc_copy = NULL; + char *ok_chars_copy = NULL; + char *cancel_chars_copy = NULL; + + if (prompt != NULL) { + prompt_copy = OPENSSL_strdup(prompt); + if (prompt_copy == NULL) + goto err; + } + + if (action_desc != NULL) { + action_desc_copy = OPENSSL_strdup(action_desc); + if (action_desc_copy == NULL) + goto err; + } + + if (ok_chars != NULL) { + ok_chars_copy = OPENSSL_strdup(ok_chars); + if (ok_chars_copy == NULL) + goto err; + } + + if (cancel_chars != NULL) { + cancel_chars_copy = OPENSSL_strdup(cancel_chars); + if (cancel_chars_copy == NULL) + goto err; + } + + return general_allocate_boolean(ui, prompt_copy, action_desc_copy, + ok_chars_copy, cancel_chars_copy, 1, + UIT_BOOLEAN, flags, result_buf); + err: + OPENSSL_free(prompt_copy); + OPENSSL_free(action_desc_copy); + OPENSSL_free(ok_chars_copy); + OPENSSL_free(cancel_chars_copy); + return -1; +} int UI_add_info_string(UI *ui, const char *text) - { - return general_allocate_string(ui, text, 0, UI_INFO, NULL, 0, 0, NULL); - } +{ + return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0, + NULL); +} int UI_dup_info_string(UI *ui, const char *text) - { - char *text_copy=NULL; - - if (text) - { - text_copy=strdup(text); - if (text_copy == NULL) - { - UIerr(UI_F_UI_DUP_INFO_STRING,ERR_R_MALLOC_FAILURE); - return -1; - } - } - - return general_allocate_string(ui, text, 1, UI_INFO, NULL, 0, 0, NULL); - } +{ + char *text_copy = NULL; + + if (text != NULL) { + text_copy = OPENSSL_strdup(text); + if (text_copy == NULL) + return -1; + } + + return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL, + 0, 0, NULL); +} int UI_add_error_string(UI *ui, const char *text) - { - return general_allocate_string(ui, text, 0, UI_ERROR, NULL, 0, 0, - NULL); - } +{ + return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0, + NULL); +} int UI_dup_error_string(UI *ui, const char *text) - { - char *text_copy=NULL; - - if (text) - { - text_copy=strdup(text); - if (text_copy == NULL) - { - UIerr(UI_F_UI_DUP_ERROR_STRING,ERR_R_MALLOC_FAILURE); - return -1; - } - } - return general_allocate_string(ui, text_copy, 1, UI_ERROR, NULL, 0, 0, - NULL); - } +{ + char *text_copy = NULL; + + if (text != NULL) { + text_copy = OPENSSL_strdup(text); + if (text_copy == NULL) + return -1; + } + return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL, + 0, 0, NULL); +} + +char *UI_construct_prompt(UI *ui, const char *phrase_desc, + const char *object_name) +{ + char *prompt = NULL; + + if (ui != NULL && ui->meth != NULL && ui->meth->ui_construct_prompt != NULL) + prompt = ui->meth->ui_construct_prompt(ui, phrase_desc, object_name); + else { + char prompt1[] = "Enter "; + char prompt2[] = " for "; + char prompt3[] = ":"; + int len = 0; + + if (phrase_desc == NULL) + return NULL; + len = sizeof(prompt1) - 1 + strlen(phrase_desc); + if (object_name != NULL) + len += sizeof(prompt2) - 1 + strlen(object_name); + len += sizeof(prompt3) - 1; + + if ((prompt = OPENSSL_malloc(len + 1)) == NULL) + return NULL; + OPENSSL_strlcpy(prompt, prompt1, len + 1); + OPENSSL_strlcat(prompt, phrase_desc, len + 1); + if (object_name != NULL) { + OPENSSL_strlcat(prompt, prompt2, len + 1); + OPENSSL_strlcat(prompt, object_name, len + 1); + } + OPENSSL_strlcat(prompt, prompt3, len + 1); + } + return prompt; +} + +void *UI_add_user_data(UI *ui, void *user_data) +{ + void *old_data = ui->user_data; + + if ((ui->flags & UI_FLAG_DUPL_DATA) != 0) { + ui->meth->ui_destroy_data(ui, old_data); + old_data = NULL; + } + ui->user_data = user_data; + ui->flags &= ~UI_FLAG_DUPL_DATA; + return old_data; +} + +int UI_dup_user_data(UI *ui, void *user_data) +{ + void *duplicate = NULL; + + if (ui->meth->ui_duplicate_data == NULL + || ui->meth->ui_destroy_data == NULL) { + ERR_raise(ERR_LIB_UI, UI_R_USER_DATA_DUPLICATION_UNSUPPORTED); + return -1; + } + + duplicate = ui->meth->ui_duplicate_data(ui, user_data); + if (duplicate == NULL) { + ERR_raise(ERR_LIB_UI, ERR_R_UI_LIB); + return -1; + } + + (void)UI_add_user_data(ui, duplicate); + ui->flags |= UI_FLAG_DUPL_DATA; + + return 0; +} + +void *UI_get0_user_data(UI *ui) +{ + return ui->user_data; +} const char *UI_get0_result(UI *ui, int i) - { - if (i < 0) - { - UIerr(UI_F_UI_GET0_RESULT,UI_R_INDEX_TOO_SMALL); - return NULL; - } - if (i >= sk_UI_STRING_num(ui->strings)) - { - UIerr(UI_F_UI_GET0_RESULT,UI_R_INDEX_TOO_LARGE); - return NULL; - } - return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i)); - } +{ + if (i < 0) { + ERR_raise(ERR_LIB_UI, UI_R_INDEX_TOO_SMALL); + return NULL; + } + if (i >= sk_UI_STRING_num(ui->strings)) { + ERR_raise(ERR_LIB_UI, UI_R_INDEX_TOO_LARGE); + return NULL; + } + return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i)); +} + +int UI_get_result_length(UI *ui, int i) +{ + if (i < 0) { + ERR_raise(ERR_LIB_UI, UI_R_INDEX_TOO_SMALL); + return -1; + } + if (i >= sk_UI_STRING_num(ui->strings)) { + ERR_raise(ERR_LIB_UI, UI_R_INDEX_TOO_LARGE); + return -1; + } + return UI_get_result_string_length(sk_UI_STRING_value(ui->strings, i)); +} + +static int print_error(const char *str, size_t len, UI *ui) +{ + UI_STRING uis; + + memset(&uis, 0, sizeof(uis)); + uis.type = UIT_ERROR; + uis.out_string = str; + + if (ui->meth->ui_write_string != NULL + && ui->meth->ui_write_string(ui, &uis) <= 0) + return -1; + return 0; +} int UI_process(UI *ui) - { - int i, ok=0; - - if (ui->meth->ui_open_session && !ui->meth->ui_open_session(ui)) - return -1; - - for(i=0; istrings); i++) - { - if (ui->meth->ui_write_string - && !ui->meth->ui_write_string(ui, - sk_UI_STRING_value(ui->strings, i))) - { - ok=-1; - goto err; - } - } - - for(i=0; istrings); i++) - { - if (ui->meth->ui_read_string - && !ui->meth->ui_read_string(ui, - sk_UI_STRING_value(ui->strings, i))) - { - ok=-1; - goto err; - } - } - err: - if (ui->meth->ui_close_session && !ui->meth->ui_close_session(ui)) - return -1; - return ok; - } +{ + int i, ok = 0; + const char *state = "processing"; + + if (ui->meth->ui_open_session != NULL + && ui->meth->ui_open_session(ui) <= 0) { + state = "opening session"; + ok = -1; + goto err; + } + + if (ui->flags & UI_FLAG_PRINT_ERRORS) + ERR_print_errors_cb((int (*)(const char *, size_t, void *)) + print_error, (void *)ui); + + for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) { + if (ui->meth->ui_write_string != NULL + && (ui->meth->ui_write_string(ui, + sk_UI_STRING_value(ui->strings, i)) + <= 0)) + { + state = "writing strings"; + ok = -1; + goto err; + } + } + + if (ui->meth->ui_flush != NULL) + switch (ui->meth->ui_flush(ui)) { + case -1: /* Interrupt/Cancel/something... */ + ui->flags &= ~UI_FLAG_REDOABLE; + ok = -2; + goto err; + case 0: /* Errors */ + state = "flushing"; + ok = -1; + goto err; + default: /* Success */ + ok = 0; + break; + } + + for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) { + if (ui->meth->ui_read_string != NULL) { + switch (ui->meth->ui_read_string(ui, + sk_UI_STRING_value(ui->strings, + i))) { + case -1: /* Interrupt/Cancel/something... */ + ui->flags &= ~UI_FLAG_REDOABLE; + ok = -2; + goto err; + case 0: /* Errors */ + state = "reading strings"; + ok = -1; + goto err; + default: /* Success */ + ok = 0; + break; + } + } else { + ui->flags &= ~UI_FLAG_REDOABLE; + ok = -2; + goto err; + } + } -int UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, - CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) + state = NULL; + err: + if (ui->meth->ui_close_session != NULL + && ui->meth->ui_close_session(ui) <= 0) { + if (state == NULL) + state = "closing session"; + ok = -1; + } + + if (ok == -1) + ERR_raise_data(ERR_LIB_UI, UI_R_PROCESSING_ERROR, "while %s", state); + return ok; +} + +int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void)) +{ + if (ui == NULL) { + ERR_raise(ERR_LIB_UI, ERR_R_PASSED_NULL_PARAMETER); + return -1; + } + switch (cmd) { + case UI_CTRL_PRINT_ERRORS: { - ui_meth_num++; - return(CRYPTO_get_ex_new_index(ui_meth_num-1, - &ui_meth,argl,argp,new_func,dup_func,free_func)); + int save_flag = ! !(ui->flags & UI_FLAG_PRINT_ERRORS); + if (i) + ui->flags |= UI_FLAG_PRINT_ERRORS; + else + ui->flags &= ~UI_FLAG_PRINT_ERRORS; + return save_flag; } + case UI_CTRL_IS_REDOABLE: + return ! !(ui->flags & UI_FLAG_REDOABLE); + default: + break; + } + ERR_raise(ERR_LIB_UI, UI_R_UNKNOWN_CONTROL_COMMAND); + return -1; +} int UI_set_ex_data(UI *r, int idx, void *arg) - { - return(CRYPTO_set_ex_data(&r->ex_data,idx,arg)); - } - -void *UI_get_ex_data(UI *r, int idx) - { - return(CRYPTO_get_ex_data(&r->ex_data,idx)); - } - -void UI_set_default_method(const UI_METHOD *meth) - { - default_UI_meth=meth; - } - -const UI_METHOD *UI_get_default_method(void) - { - if (default_UI_meth == NULL) - { - default_UI_meth=UI_OpenSSL(); - } - return default_UI_meth; - } +{ + return CRYPTO_set_ex_data(&r->ex_data, idx, arg); +} + +void *UI_get_ex_data(const UI *r, int idx) +{ + return CRYPTO_get_ex_data(&r->ex_data, idx); +} const UI_METHOD *UI_get_method(UI *ui) - { - return ui->meth; - } +{ + return ui->meth; +} const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth) - { - ui->meth=meth; - return ui->meth; - } - - -UI_METHOD *UI_create_method(void) - { - return (UI_METHOD *)OPENSSL_malloc(sizeof(UI_METHOD)); - } - -int UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui)) - { - if (method) - { - method->ui_open_session = opener; - return 0; - } - else - return -1; - } - -int UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis)) - { - if (method) - { - method->ui_write_string = writer; - return 0; - } - else - return -1; - } - -int UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis)) - { - if (method) - { - method->ui_read_string = reader; - return 0; - } - else - return -1; - } - -int UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui)) - { - if (method) - { - method->ui_close_session = closer; - return 0; - } - else - return -1; - } - -int (*UI_method_get_opener(UI_METHOD *method))(UI*) - { - if (method) - return method->ui_open_session; - else - return NULL; - } - -int (*UI_method_get_writer(UI_METHOD *method))(UI*,UI_STRING*) - { - if (method) - return method->ui_write_string; - else - return NULL; - } - -int (*UI_method_get_reader(UI_METHOD *method))(UI*,UI_STRING*) - { - if (method) - return method->ui_read_string; - else - return NULL; - } - -int (*UI_method_get_closer(UI_METHOD *method))(UI*) - { - if (method) - return method->ui_close_session; - else - return NULL; - } +{ + ui->meth = meth; + return ui->meth; +} + +UI_METHOD *UI_create_method(const char *name) +{ + UI_METHOD *ui_method = NULL; + + if ((ui_method = OPENSSL_zalloc(sizeof(*ui_method))) == NULL + || (ui_method->name = OPENSSL_strdup(name)) == NULL + || !CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI_METHOD, ui_method, + &ui_method->ex_data)) { + + if (ui_method != NULL) { + if (ui_method->name != NULL) + /* + * These conditions indicate that the CRYPTO_new_ex_data() + * call failed. + */ + ERR_raise(ERR_LIB_UI, ERR_R_CRYPTO_LIB); + OPENSSL_free(ui_method->name); + } + OPENSSL_free(ui_method); + return NULL; + } + return ui_method; +} + +/* + * BIG FSCKING WARNING!!!! If you use this on a statically allocated method + * (that is, it hasn't been allocated using UI_create_method(), you deserve + * anything Murphy can throw at you and more! You have been warned. + */ +void UI_destroy_method(UI_METHOD *ui_method) +{ + if (ui_method == NULL) + return; + CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI_METHOD, ui_method, + &ui_method->ex_data); + OPENSSL_free(ui_method->name); + ui_method->name = NULL; + OPENSSL_free(ui_method); +} + +int UI_method_set_opener(UI_METHOD *method, int (*opener) (UI *ui)) +{ + if (method != NULL) { + method->ui_open_session = opener; + return 0; + } + return -1; +} + +int UI_method_set_writer(UI_METHOD *method, + int (*writer) (UI *ui, UI_STRING *uis)) +{ + if (method != NULL) { + method->ui_write_string = writer; + return 0; + } + return -1; +} + +int UI_method_set_flusher(UI_METHOD *method, int (*flusher) (UI *ui)) +{ + if (method != NULL) { + method->ui_flush = flusher; + return 0; + } + return -1; +} + +int UI_method_set_reader(UI_METHOD *method, + int (*reader) (UI *ui, UI_STRING *uis)) +{ + if (method != NULL) { + method->ui_read_string = reader; + return 0; + } + return -1; +} + +int UI_method_set_closer(UI_METHOD *method, int (*closer) (UI *ui)) +{ + if (method != NULL) { + method->ui_close_session = closer; + return 0; + } + return -1; +} + +int UI_method_set_data_duplicator(UI_METHOD *method, + void *(*duplicator) (UI *ui, void *ui_data), + void (*destructor)(UI *ui, void *ui_data)) +{ + if (method != NULL) { + method->ui_duplicate_data = duplicator; + method->ui_destroy_data = destructor; + return 0; + } + return -1; +} + +int UI_method_set_prompt_constructor(UI_METHOD *method, + char *(*prompt_constructor) (UI *ui, + const char *, + const char *)) +{ + if (method != NULL) { + method->ui_construct_prompt = prompt_constructor; + return 0; + } + return -1; +} + +int UI_method_set_ex_data(UI_METHOD *method, int idx, void *data) +{ + return CRYPTO_set_ex_data(&method->ex_data, idx, data); +} + +int (*UI_method_get_opener(const UI_METHOD *method)) (UI *) +{ + if (method != NULL) + return method->ui_open_session; + return NULL; +} + +int (*UI_method_get_writer(const UI_METHOD *method)) (UI *, UI_STRING *) +{ + if (method != NULL) + return method->ui_write_string; + return NULL; +} + +int (*UI_method_get_flusher(const UI_METHOD *method)) (UI *) +{ + if (method != NULL) + return method->ui_flush; + return NULL; +} + +int (*UI_method_get_reader(const UI_METHOD *method)) (UI *, UI_STRING *) +{ + if (method != NULL) + return method->ui_read_string; + return NULL; +} + +int (*UI_method_get_closer(const UI_METHOD *method)) (UI *) +{ + if (method != NULL) + return method->ui_close_session; + return NULL; +} + +char *(*UI_method_get_prompt_constructor(const UI_METHOD *method)) + (UI *, const char *, const char *) +{ + if (method != NULL) + return method->ui_construct_prompt; + return NULL; +} + +void *(*UI_method_get_data_duplicator(const UI_METHOD *method)) (UI *, void *) +{ + if (method != NULL) + return method->ui_duplicate_data; + return NULL; +} + +void (*UI_method_get_data_destructor(const UI_METHOD *method)) (UI *, void *) +{ + if (method != NULL) + return method->ui_destroy_data; + return NULL; +} + +const void *UI_method_get_ex_data(const UI_METHOD *method, int idx) +{ + return CRYPTO_get_ex_data(&method->ex_data, idx); +} enum UI_string_types UI_get_string_type(UI_STRING *uis) - { - if (!uis) - return UI_NONE; - return uis->type; - } +{ + return uis->type; +} + +int UI_get_input_flags(UI_STRING *uis) +{ + return uis->input_flags; +} const char *UI_get0_output_string(UI_STRING *uis) - { - if (!uis) - return NULL; - return uis->out_string; - } +{ + return uis->out_string; +} + +const char *UI_get0_action_string(UI_STRING *uis) +{ + switch (uis->type) { + case UIT_BOOLEAN: + return uis->_.boolean_data.action_desc; + case UIT_PROMPT: + case UIT_NONE: + case UIT_VERIFY: + case UIT_INFO: + case UIT_ERROR: + break; + } + return NULL; +} const char *UI_get0_result_string(UI_STRING *uis) - { - if (!uis) - return NULL; - switch(uis->type) - { - case UI_STRING_ECHO: - case UI_STRING_NOECHO: - case UI_VERIFY_ECHO: - case UI_VERIFY_NOECHO: - return uis->result_buf; - default: - return NULL; - } - } +{ + switch (uis->type) { + case UIT_PROMPT: + case UIT_VERIFY: + return uis->result_buf; + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: + break; + } + return NULL; +} + +int UI_get_result_string_length(UI_STRING *uis) +{ + switch (uis->type) { + case UIT_PROMPT: + case UIT_VERIFY: + return uis->result_len; + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: + break; + } + return -1; +} const char *UI_get0_test_string(UI_STRING *uis) - { - if (!uis) - return NULL; - return uis->test_buf; - } +{ + switch (uis->type) { + case UIT_VERIFY: + return uis->_.string_data.test_buf; + case UIT_NONE: + case UIT_BOOLEAN: + case UIT_INFO: + case UIT_ERROR: + case UIT_PROMPT: + break; + } + return NULL; +} int UI_get_result_minsize(UI_STRING *uis) - { - if (!uis) - return -1; - return uis->result_minsize; - } +{ + switch (uis->type) { + case UIT_PROMPT: + case UIT_VERIFY: + return uis->_.string_data.result_minsize; + case UIT_NONE: + case UIT_INFO: + case UIT_ERROR: + case UIT_BOOLEAN: + break; + } + return -1; +} int UI_get_result_maxsize(UI_STRING *uis) - { - if (!uis) - return -1; - return uis->result_maxsize; - } - -int UI_set_result(UI_STRING *uis, char *result) - { - int l = strlen(result); - - if (!uis) - return -1; - if (l < uis->result_minsize) - { - UIerr(UI_F_UI_SET_RESULT,UI_R_RESULT_TOO_SMALL); - return -1; - } - if (l > uis->result_maxsize) - { - UIerr(UI_F_UI_SET_RESULT,UI_R_RESULT_TOO_LARGE); - return -1; - } - - if (!uis->result_buf) - { - uis->result_buf = OPENSSL_malloc(uis->result_maxsize+1); - } - - if (!uis->result_buf) - { - UIerr(UI_F_UI_NEW_METHOD,ERR_R_MALLOC_FAILURE); - return -1; - } - - strcpy(uis->result_buf, result); - return 0; - } +{ + switch (uis->type) { + case UIT_PROMPT: + case UIT_VERIFY: + return uis->_.string_data.result_maxsize; + case UIT_NONE: + case UIT_INFO: + case UIT_ERROR: + case UIT_BOOLEAN: + break; + } + return -1; +} + +int UI_set_result(UI *ui, UI_STRING *uis, const char *result) +{ + return UI_set_result_ex(ui, uis, result, strlen(result)); +} + +int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len) +{ + ui->flags &= ~UI_FLAG_REDOABLE; + + switch (uis->type) { + case UIT_PROMPT: + case UIT_VERIFY: + if (len < uis->_.string_data.result_minsize) { + ui->flags |= UI_FLAG_REDOABLE; + ERR_raise_data(ERR_LIB_UI, UI_R_RESULT_TOO_SMALL, + "You must type in %d to %d characters", + uis->_.string_data.result_minsize, + uis->_.string_data.result_maxsize); + return -1; + } + if (len > uis->_.string_data.result_maxsize) { + ui->flags |= UI_FLAG_REDOABLE; + ERR_raise_data(ERR_LIB_UI, UI_R_RESULT_TOO_LARGE, + "You must type in %d to %d characters", + uis->_.string_data.result_minsize, + uis->_.string_data.result_maxsize); + return -1; + } + + if (uis->result_buf == NULL) { + ERR_raise(ERR_LIB_UI, UI_R_NO_RESULT_BUFFER); + return -1; + } + + memcpy(uis->result_buf, result, len); + if (len <= uis->_.string_data.result_maxsize) + uis->result_buf[len] = '\0'; + uis->result_len = len; + break; + case UIT_BOOLEAN: + { + const char *p; + + if (uis->result_buf == NULL) { + ERR_raise(ERR_LIB_UI, UI_R_NO_RESULT_BUFFER); + return -1; + } + + uis->result_buf[0] = '\0'; + for (p = result; *p; p++) { + if (strchr(uis->_.boolean_data.ok_chars, *p)) { + uis->result_buf[0] = uis->_.boolean_data.ok_chars[0]; + break; + } + if (strchr(uis->_.boolean_data.cancel_chars, *p)) { + uis->result_buf[0] = uis->_.boolean_data.cancel_chars[0]; + break; + } + } + } + case UIT_NONE: + case UIT_INFO: + case UIT_ERROR: + break; + } + return 0; +}