1109998Smarkm/* crypto/ui/ui_lib.c -*- mode:C; c-file-style: "eay" -*- */ 2296341Sdelphij/* 3296341Sdelphij * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project 4296341Sdelphij * 2001. 5109998Smarkm */ 6109998Smarkm/* ==================================================================== 7109998Smarkm * Copyright (c) 2001 The OpenSSL Project. All rights reserved. 8109998Smarkm * 9109998Smarkm * Redistribution and use in source and binary forms, with or without 10109998Smarkm * modification, are permitted provided that the following conditions 11109998Smarkm * are met: 12109998Smarkm * 13109998Smarkm * 1. Redistributions of source code must retain the above copyright 14296341Sdelphij * notice, this list of conditions and the following disclaimer. 15109998Smarkm * 16109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 17109998Smarkm * notice, this list of conditions and the following disclaimer in 18109998Smarkm * the documentation and/or other materials provided with the 19109998Smarkm * distribution. 20109998Smarkm * 21109998Smarkm * 3. All advertising materials mentioning features or use of this 22109998Smarkm * software must display the following acknowledgment: 23109998Smarkm * "This product includes software developed by the OpenSSL Project 24109998Smarkm * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 25109998Smarkm * 26109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27109998Smarkm * endorse or promote products derived from this software without 28109998Smarkm * prior written permission. For written permission, please contact 29109998Smarkm * openssl-core@openssl.org. 30109998Smarkm * 31109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 32109998Smarkm * nor may "OpenSSL" appear in their names without prior written 33109998Smarkm * permission of the OpenSSL Project. 34109998Smarkm * 35109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 36109998Smarkm * acknowledgment: 37109998Smarkm * "This product includes software developed by the OpenSSL Project 38109998Smarkm * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 39109998Smarkm * 40109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 52109998Smarkm * ==================================================================== 53109998Smarkm * 54109998Smarkm * This product includes cryptographic software written by Eric Young 55109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 56109998Smarkm * Hudson (tjh@cryptsoft.com). 57109998Smarkm * 58109998Smarkm */ 59109998Smarkm 60109998Smarkm#include <string.h> 61160814Ssimon#include "cryptlib.h" 62109998Smarkm#include <openssl/e_os2.h> 63109998Smarkm#include <openssl/buffer.h> 64109998Smarkm#include <openssl/ui.h> 65109998Smarkm#include <openssl/err.h> 66109998Smarkm#include "ui_locl.h" 67109998Smarkm 68109998SmarkmIMPLEMENT_STACK_OF(UI_STRING_ST) 69109998Smarkm 70296341Sdelphijstatic const UI_METHOD *default_UI_meth = NULL; 71109998Smarkm 72109998SmarkmUI *UI_new(void) 73296341Sdelphij{ 74296341Sdelphij return (UI_new_method(NULL)); 75296341Sdelphij} 76109998Smarkm 77109998SmarkmUI *UI_new_method(const UI_METHOD *method) 78296341Sdelphij{ 79296341Sdelphij UI *ret; 80109998Smarkm 81296341Sdelphij ret = (UI *)OPENSSL_malloc(sizeof(UI)); 82296341Sdelphij if (ret == NULL) { 83296341Sdelphij UIerr(UI_F_UI_NEW_METHOD, ERR_R_MALLOC_FAILURE); 84296341Sdelphij return NULL; 85296341Sdelphij } 86296341Sdelphij if (method == NULL) 87296341Sdelphij ret->meth = UI_get_default_method(); 88296341Sdelphij else 89296341Sdelphij ret->meth = method; 90109998Smarkm 91296341Sdelphij ret->strings = NULL; 92296341Sdelphij ret->user_data = NULL; 93296341Sdelphij ret->flags = 0; 94296341Sdelphij CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data); 95296341Sdelphij return ret; 96296341Sdelphij} 97109998Smarkm 98109998Smarkmstatic void free_string(UI_STRING *uis) 99296341Sdelphij{ 100296341Sdelphij if (uis->flags & OUT_STRING_FREEABLE) { 101296341Sdelphij OPENSSL_free((char *)uis->out_string); 102296341Sdelphij switch (uis->type) { 103296341Sdelphij case UIT_BOOLEAN: 104296341Sdelphij OPENSSL_free((char *)uis->_.boolean_data.action_desc); 105296341Sdelphij OPENSSL_free((char *)uis->_.boolean_data.ok_chars); 106296341Sdelphij OPENSSL_free((char *)uis->_.boolean_data.cancel_chars); 107296341Sdelphij break; 108296341Sdelphij default: 109296341Sdelphij break; 110296341Sdelphij } 111296341Sdelphij } 112296341Sdelphij OPENSSL_free(uis); 113296341Sdelphij} 114109998Smarkm 115109998Smarkmvoid UI_free(UI *ui) 116296341Sdelphij{ 117296341Sdelphij if (ui == NULL) 118296341Sdelphij return; 119296341Sdelphij sk_UI_STRING_pop_free(ui->strings, free_string); 120296341Sdelphij CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data); 121296341Sdelphij OPENSSL_free(ui); 122296341Sdelphij} 123109998Smarkm 124109998Smarkmstatic int allocate_string_stack(UI *ui) 125296341Sdelphij{ 126296341Sdelphij if (ui->strings == NULL) { 127296341Sdelphij ui->strings = sk_UI_STRING_new_null(); 128296341Sdelphij if (ui->strings == NULL) { 129296341Sdelphij return -1; 130296341Sdelphij } 131296341Sdelphij } 132296341Sdelphij return 0; 133296341Sdelphij} 134109998Smarkm 135109998Smarkmstatic UI_STRING *general_allocate_prompt(UI *ui, const char *prompt, 136296341Sdelphij int prompt_freeable, 137296341Sdelphij enum UI_string_types type, 138296341Sdelphij int input_flags, char *result_buf) 139296341Sdelphij{ 140296341Sdelphij UI_STRING *ret = NULL; 141109998Smarkm 142296341Sdelphij if (prompt == NULL) { 143296341Sdelphij UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, ERR_R_PASSED_NULL_PARAMETER); 144296341Sdelphij } else if ((type == UIT_PROMPT || type == UIT_VERIFY 145296341Sdelphij || type == UIT_BOOLEAN) && result_buf == NULL) { 146296341Sdelphij UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, UI_R_NO_RESULT_BUFFER); 147296341Sdelphij } else if ((ret = (UI_STRING *)OPENSSL_malloc(sizeof(UI_STRING)))) { 148296341Sdelphij ret->out_string = prompt; 149296341Sdelphij ret->flags = prompt_freeable ? OUT_STRING_FREEABLE : 0; 150296341Sdelphij ret->input_flags = input_flags; 151296341Sdelphij ret->type = type; 152296341Sdelphij ret->result_buf = result_buf; 153296341Sdelphij } 154296341Sdelphij return ret; 155296341Sdelphij} 156109998Smarkm 157109998Smarkmstatic int general_allocate_string(UI *ui, const char *prompt, 158296341Sdelphij int prompt_freeable, 159296341Sdelphij enum UI_string_types type, int input_flags, 160296341Sdelphij char *result_buf, int minsize, int maxsize, 161296341Sdelphij const char *test_buf) 162296341Sdelphij{ 163296341Sdelphij int ret = -1; 164296341Sdelphij UI_STRING *s = general_allocate_prompt(ui, prompt, prompt_freeable, 165296341Sdelphij type, input_flags, result_buf); 166109998Smarkm 167296341Sdelphij if (s) { 168296341Sdelphij if (allocate_string_stack(ui) >= 0) { 169296341Sdelphij s->_.string_data.result_minsize = minsize; 170296341Sdelphij s->_.string_data.result_maxsize = maxsize; 171296341Sdelphij s->_.string_data.test_buf = test_buf; 172296341Sdelphij ret = sk_UI_STRING_push(ui->strings, s); 173296341Sdelphij /* sk_push() returns 0 on error. Let's addapt that */ 174296341Sdelphij if (ret <= 0) 175296341Sdelphij ret--; 176296341Sdelphij } else 177296341Sdelphij free_string(s); 178296341Sdelphij } 179296341Sdelphij return ret; 180296341Sdelphij} 181109998Smarkm 182109998Smarkmstatic int general_allocate_boolean(UI *ui, 183296341Sdelphij const char *prompt, 184296341Sdelphij const char *action_desc, 185296341Sdelphij const char *ok_chars, 186296341Sdelphij const char *cancel_chars, 187296341Sdelphij int prompt_freeable, 188296341Sdelphij enum UI_string_types type, 189296341Sdelphij int input_flags, char *result_buf) 190296341Sdelphij{ 191296341Sdelphij int ret = -1; 192296341Sdelphij UI_STRING *s; 193296341Sdelphij const char *p; 194109998Smarkm 195296341Sdelphij if (ok_chars == NULL) { 196296341Sdelphij UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, ERR_R_PASSED_NULL_PARAMETER); 197296341Sdelphij } else if (cancel_chars == NULL) { 198296341Sdelphij UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, ERR_R_PASSED_NULL_PARAMETER); 199296341Sdelphij } else { 200296341Sdelphij for (p = ok_chars; *p; p++) { 201296341Sdelphij if (strchr(cancel_chars, *p)) { 202296341Sdelphij UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, 203296341Sdelphij UI_R_COMMON_OK_AND_CANCEL_CHARACTERS); 204296341Sdelphij } 205296341Sdelphij } 206109998Smarkm 207296341Sdelphij s = general_allocate_prompt(ui, prompt, prompt_freeable, 208296341Sdelphij type, input_flags, result_buf); 209109998Smarkm 210296341Sdelphij if (s) { 211296341Sdelphij if (allocate_string_stack(ui) >= 0) { 212296341Sdelphij s->_.boolean_data.action_desc = action_desc; 213296341Sdelphij s->_.boolean_data.ok_chars = ok_chars; 214296341Sdelphij s->_.boolean_data.cancel_chars = cancel_chars; 215296341Sdelphij ret = sk_UI_STRING_push(ui->strings, s); 216296341Sdelphij /* 217296341Sdelphij * sk_push() returns 0 on error. Let's addapt that 218296341Sdelphij */ 219296341Sdelphij if (ret <= 0) 220296341Sdelphij ret--; 221296341Sdelphij } else 222296341Sdelphij free_string(s); 223296341Sdelphij } 224296341Sdelphij } 225296341Sdelphij return ret; 226296341Sdelphij} 227109998Smarkm 228296341Sdelphij/* 229296341Sdelphij * Returns the index to the place in the stack or -1 for error. Uses a 230296341Sdelphij * direct reference to the prompt. 231296341Sdelphij */ 232109998Smarkmint UI_add_input_string(UI *ui, const char *prompt, int flags, 233296341Sdelphij char *result_buf, int minsize, int maxsize) 234296341Sdelphij{ 235296341Sdelphij return general_allocate_string(ui, prompt, 0, 236296341Sdelphij UIT_PROMPT, flags, result_buf, minsize, 237296341Sdelphij maxsize, NULL); 238296341Sdelphij} 239109998Smarkm 240109998Smarkm/* Same as UI_add_input_string(), excepts it takes a copy of the prompt */ 241109998Smarkmint UI_dup_input_string(UI *ui, const char *prompt, int flags, 242296341Sdelphij char *result_buf, int minsize, int maxsize) 243296341Sdelphij{ 244296341Sdelphij char *prompt_copy = NULL; 245109998Smarkm 246296341Sdelphij if (prompt) { 247296341Sdelphij prompt_copy = BUF_strdup(prompt); 248296341Sdelphij if (prompt_copy == NULL) { 249296341Sdelphij UIerr(UI_F_UI_DUP_INPUT_STRING, ERR_R_MALLOC_FAILURE); 250296341Sdelphij return 0; 251296341Sdelphij } 252296341Sdelphij } 253109998Smarkm 254296341Sdelphij return general_allocate_string(ui, prompt_copy, 1, 255296341Sdelphij UIT_PROMPT, flags, result_buf, minsize, 256296341Sdelphij maxsize, NULL); 257296341Sdelphij} 258296341Sdelphij 259109998Smarkmint UI_add_verify_string(UI *ui, const char *prompt, int flags, 260296341Sdelphij char *result_buf, int minsize, int maxsize, 261296341Sdelphij const char *test_buf) 262296341Sdelphij{ 263296341Sdelphij return general_allocate_string(ui, prompt, 0, 264296341Sdelphij UIT_VERIFY, flags, result_buf, minsize, 265296341Sdelphij maxsize, test_buf); 266296341Sdelphij} 267109998Smarkm 268109998Smarkmint UI_dup_verify_string(UI *ui, const char *prompt, int flags, 269296341Sdelphij char *result_buf, int minsize, int maxsize, 270296341Sdelphij const char *test_buf) 271296341Sdelphij{ 272296341Sdelphij char *prompt_copy = NULL; 273109998Smarkm 274296341Sdelphij if (prompt) { 275296341Sdelphij prompt_copy = BUF_strdup(prompt); 276296341Sdelphij if (prompt_copy == NULL) { 277296341Sdelphij UIerr(UI_F_UI_DUP_VERIFY_STRING, ERR_R_MALLOC_FAILURE); 278296341Sdelphij return -1; 279296341Sdelphij } 280296341Sdelphij } 281109998Smarkm 282296341Sdelphij return general_allocate_string(ui, prompt_copy, 1, 283296341Sdelphij UIT_VERIFY, flags, result_buf, minsize, 284296341Sdelphij maxsize, test_buf); 285296341Sdelphij} 286296341Sdelphij 287109998Smarkmint UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc, 288296341Sdelphij const char *ok_chars, const char *cancel_chars, 289296341Sdelphij int flags, char *result_buf) 290296341Sdelphij{ 291296341Sdelphij return general_allocate_boolean(ui, prompt, action_desc, 292296341Sdelphij ok_chars, cancel_chars, 0, UIT_BOOLEAN, 293296341Sdelphij flags, result_buf); 294296341Sdelphij} 295109998Smarkm 296109998Smarkmint UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, 297296341Sdelphij const char *ok_chars, const char *cancel_chars, 298296341Sdelphij int flags, char *result_buf) 299296341Sdelphij{ 300296341Sdelphij char *prompt_copy = NULL; 301296341Sdelphij char *action_desc_copy = NULL; 302296341Sdelphij char *ok_chars_copy = NULL; 303296341Sdelphij char *cancel_chars_copy = NULL; 304109998Smarkm 305296341Sdelphij if (prompt) { 306296341Sdelphij prompt_copy = BUF_strdup(prompt); 307296341Sdelphij if (prompt_copy == NULL) { 308296341Sdelphij UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); 309296341Sdelphij goto err; 310296341Sdelphij } 311296341Sdelphij } 312296341Sdelphij 313296341Sdelphij if (action_desc) { 314296341Sdelphij action_desc_copy = BUF_strdup(action_desc); 315296341Sdelphij if (action_desc_copy == NULL) { 316296341Sdelphij UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); 317296341Sdelphij goto err; 318296341Sdelphij } 319296341Sdelphij } 320296341Sdelphij 321296341Sdelphij if (ok_chars) { 322296341Sdelphij ok_chars_copy = BUF_strdup(ok_chars); 323296341Sdelphij if (ok_chars_copy == NULL) { 324296341Sdelphij UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); 325296341Sdelphij goto err; 326296341Sdelphij } 327296341Sdelphij } 328296341Sdelphij 329296341Sdelphij if (cancel_chars) { 330296341Sdelphij cancel_chars_copy = BUF_strdup(cancel_chars); 331296341Sdelphij if (cancel_chars_copy == NULL) { 332296341Sdelphij UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); 333296341Sdelphij goto err; 334296341Sdelphij } 335296341Sdelphij } 336296341Sdelphij 337296341Sdelphij return general_allocate_boolean(ui, prompt_copy, action_desc_copy, 338296341Sdelphij ok_chars_copy, cancel_chars_copy, 1, 339296341Sdelphij UIT_BOOLEAN, flags, result_buf); 340109998Smarkm err: 341296341Sdelphij if (prompt_copy) 342296341Sdelphij OPENSSL_free(prompt_copy); 343296341Sdelphij if (action_desc_copy) 344296341Sdelphij OPENSSL_free(action_desc_copy); 345296341Sdelphij if (ok_chars_copy) 346296341Sdelphij OPENSSL_free(ok_chars_copy); 347296341Sdelphij if (cancel_chars_copy) 348296341Sdelphij OPENSSL_free(cancel_chars_copy); 349296341Sdelphij return -1; 350296341Sdelphij} 351109998Smarkm 352109998Smarkmint UI_add_info_string(UI *ui, const char *text) 353296341Sdelphij{ 354296341Sdelphij return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0, 355296341Sdelphij NULL); 356296341Sdelphij} 357109998Smarkm 358109998Smarkmint UI_dup_info_string(UI *ui, const char *text) 359296341Sdelphij{ 360296341Sdelphij char *text_copy = NULL; 361109998Smarkm 362296341Sdelphij if (text) { 363296341Sdelphij text_copy = BUF_strdup(text); 364296341Sdelphij if (text_copy == NULL) { 365296341Sdelphij UIerr(UI_F_UI_DUP_INFO_STRING, ERR_R_MALLOC_FAILURE); 366296341Sdelphij return -1; 367296341Sdelphij } 368296341Sdelphij } 369109998Smarkm 370296341Sdelphij return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL, 371296341Sdelphij 0, 0, NULL); 372296341Sdelphij} 373109998Smarkm 374109998Smarkmint UI_add_error_string(UI *ui, const char *text) 375296341Sdelphij{ 376296341Sdelphij return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0, 377296341Sdelphij NULL); 378296341Sdelphij} 379109998Smarkm 380109998Smarkmint UI_dup_error_string(UI *ui, const char *text) 381296341Sdelphij{ 382296341Sdelphij char *text_copy = NULL; 383109998Smarkm 384296341Sdelphij if (text) { 385296341Sdelphij text_copy = BUF_strdup(text); 386296341Sdelphij if (text_copy == NULL) { 387296341Sdelphij UIerr(UI_F_UI_DUP_ERROR_STRING, ERR_R_MALLOC_FAILURE); 388296341Sdelphij return -1; 389296341Sdelphij } 390296341Sdelphij } 391296341Sdelphij return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL, 392296341Sdelphij 0, 0, NULL); 393296341Sdelphij} 394109998Smarkm 395109998Smarkmchar *UI_construct_prompt(UI *ui, const char *object_desc, 396296341Sdelphij const char *object_name) 397296341Sdelphij{ 398296341Sdelphij char *prompt = NULL; 399109998Smarkm 400296341Sdelphij if (ui->meth->ui_construct_prompt) 401296341Sdelphij prompt = ui->meth->ui_construct_prompt(ui, object_desc, object_name); 402296341Sdelphij else { 403296341Sdelphij char prompt1[] = "Enter "; 404296341Sdelphij char prompt2[] = " for "; 405296341Sdelphij char prompt3[] = ":"; 406296341Sdelphij int len = 0; 407109998Smarkm 408296341Sdelphij if (object_desc == NULL) 409296341Sdelphij return NULL; 410296341Sdelphij len = sizeof(prompt1) - 1 + strlen(object_desc); 411296341Sdelphij if (object_name) 412296341Sdelphij len += sizeof(prompt2) - 1 + strlen(object_name); 413296341Sdelphij len += sizeof(prompt3) - 1; 414109998Smarkm 415296341Sdelphij prompt = (char *)OPENSSL_malloc(len + 1); 416296341Sdelphij BUF_strlcpy(prompt, prompt1, len + 1); 417296341Sdelphij BUF_strlcat(prompt, object_desc, len + 1); 418296341Sdelphij if (object_name) { 419296341Sdelphij BUF_strlcat(prompt, prompt2, len + 1); 420296341Sdelphij BUF_strlcat(prompt, object_name, len + 1); 421296341Sdelphij } 422296341Sdelphij BUF_strlcat(prompt, prompt3, len + 1); 423296341Sdelphij } 424296341Sdelphij return prompt; 425296341Sdelphij} 426109998Smarkm 427109998Smarkmvoid *UI_add_user_data(UI *ui, void *user_data) 428296341Sdelphij{ 429296341Sdelphij void *old_data = ui->user_data; 430296341Sdelphij ui->user_data = user_data; 431296341Sdelphij return old_data; 432296341Sdelphij} 433109998Smarkm 434109998Smarkmvoid *UI_get0_user_data(UI *ui) 435296341Sdelphij{ 436296341Sdelphij return ui->user_data; 437296341Sdelphij} 438109998Smarkm 439109998Smarkmconst char *UI_get0_result(UI *ui, int i) 440296341Sdelphij{ 441296341Sdelphij if (i < 0) { 442296341Sdelphij UIerr(UI_F_UI_GET0_RESULT, UI_R_INDEX_TOO_SMALL); 443296341Sdelphij return NULL; 444296341Sdelphij } 445296341Sdelphij if (i >= sk_UI_STRING_num(ui->strings)) { 446296341Sdelphij UIerr(UI_F_UI_GET0_RESULT, UI_R_INDEX_TOO_LARGE); 447296341Sdelphij return NULL; 448296341Sdelphij } 449296341Sdelphij return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i)); 450296341Sdelphij} 451109998Smarkm 452109998Smarkmstatic int print_error(const char *str, size_t len, UI *ui) 453296341Sdelphij{ 454296341Sdelphij UI_STRING uis; 455109998Smarkm 456296341Sdelphij memset(&uis, 0, sizeof(uis)); 457296341Sdelphij uis.type = UIT_ERROR; 458296341Sdelphij uis.out_string = str; 459109998Smarkm 460296341Sdelphij if (ui->meth->ui_write_string && !ui->meth->ui_write_string(ui, &uis)) 461296341Sdelphij return -1; 462296341Sdelphij return 0; 463296341Sdelphij} 464109998Smarkm 465109998Smarkmint UI_process(UI *ui) 466296341Sdelphij{ 467296341Sdelphij int i, ok = 0; 468109998Smarkm 469296341Sdelphij if (ui->meth->ui_open_session && !ui->meth->ui_open_session(ui)) 470296341Sdelphij return -1; 471109998Smarkm 472296341Sdelphij if (ui->flags & UI_FLAG_PRINT_ERRORS) 473296341Sdelphij ERR_print_errors_cb((int (*)(const char *, size_t, void *)) 474296341Sdelphij print_error, (void *)ui); 475109998Smarkm 476296341Sdelphij for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) { 477296341Sdelphij if (ui->meth->ui_write_string 478296341Sdelphij && !ui->meth->ui_write_string(ui, 479296341Sdelphij sk_UI_STRING_value(ui->strings, i))) 480296341Sdelphij { 481296341Sdelphij ok = -1; 482296341Sdelphij goto err; 483296341Sdelphij } 484296341Sdelphij } 485109998Smarkm 486296341Sdelphij if (ui->meth->ui_flush) 487296341Sdelphij switch (ui->meth->ui_flush(ui)) { 488296341Sdelphij case -1: /* Interrupt/Cancel/something... */ 489296341Sdelphij ok = -2; 490296341Sdelphij goto err; 491296341Sdelphij case 0: /* Errors */ 492296341Sdelphij ok = -1; 493296341Sdelphij goto err; 494296341Sdelphij default: /* Success */ 495296341Sdelphij ok = 0; 496296341Sdelphij break; 497296341Sdelphij } 498109998Smarkm 499296341Sdelphij for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) { 500296341Sdelphij if (ui->meth->ui_read_string) { 501296341Sdelphij switch (ui->meth->ui_read_string(ui, 502296341Sdelphij sk_UI_STRING_value(ui->strings, 503296341Sdelphij i))) { 504296341Sdelphij case -1: /* Interrupt/Cancel/something... */ 505296341Sdelphij ok = -2; 506296341Sdelphij goto err; 507296341Sdelphij case 0: /* Errors */ 508296341Sdelphij ok = -1; 509296341Sdelphij goto err; 510296341Sdelphij default: /* Success */ 511296341Sdelphij ok = 0; 512296341Sdelphij break; 513296341Sdelphij } 514296341Sdelphij } 515296341Sdelphij } 516109998Smarkm err: 517296341Sdelphij if (ui->meth->ui_close_session && !ui->meth->ui_close_session(ui)) 518296341Sdelphij return -1; 519296341Sdelphij return ok; 520296341Sdelphij} 521109998Smarkm 522296341Sdelphijint UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void)) 523296341Sdelphij{ 524296341Sdelphij if (ui == NULL) { 525296341Sdelphij UIerr(UI_F_UI_CTRL, ERR_R_PASSED_NULL_PARAMETER); 526296341Sdelphij return -1; 527296341Sdelphij } 528296341Sdelphij switch (cmd) { 529296341Sdelphij case UI_CTRL_PRINT_ERRORS: 530109998Smarkm { 531296341Sdelphij int save_flag = ! !(ui->flags & UI_FLAG_PRINT_ERRORS); 532296341Sdelphij if (i) 533296341Sdelphij ui->flags |= UI_FLAG_PRINT_ERRORS; 534296341Sdelphij else 535296341Sdelphij ui->flags &= ~UI_FLAG_PRINT_ERRORS; 536296341Sdelphij return save_flag; 537109998Smarkm } 538296341Sdelphij case UI_CTRL_IS_REDOABLE: 539296341Sdelphij return ! !(ui->flags & UI_FLAG_REDOABLE); 540296341Sdelphij default: 541296341Sdelphij break; 542296341Sdelphij } 543296341Sdelphij UIerr(UI_F_UI_CTRL, UI_R_UNKNOWN_CONTROL_COMMAND); 544296341Sdelphij return -1; 545296341Sdelphij} 546109998Smarkm 547296341Sdelphijint UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 548296341Sdelphij CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 549296341Sdelphij{ 550296341Sdelphij return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, argl, argp, 551296341Sdelphij new_func, dup_func, free_func); 552296341Sdelphij} 553296341Sdelphij 554109998Smarkmint UI_set_ex_data(UI *r, int idx, void *arg) 555296341Sdelphij{ 556296341Sdelphij return (CRYPTO_set_ex_data(&r->ex_data, idx, arg)); 557296341Sdelphij} 558109998Smarkm 559109998Smarkmvoid *UI_get_ex_data(UI *r, int idx) 560296341Sdelphij{ 561296341Sdelphij return (CRYPTO_get_ex_data(&r->ex_data, idx)); 562296341Sdelphij} 563109998Smarkm 564109998Smarkmvoid UI_set_default_method(const UI_METHOD *meth) 565296341Sdelphij{ 566296341Sdelphij default_UI_meth = meth; 567296341Sdelphij} 568109998Smarkm 569109998Smarkmconst UI_METHOD *UI_get_default_method(void) 570296341Sdelphij{ 571296341Sdelphij if (default_UI_meth == NULL) { 572296341Sdelphij default_UI_meth = UI_OpenSSL(); 573296341Sdelphij } 574296341Sdelphij return default_UI_meth; 575296341Sdelphij} 576109998Smarkm 577109998Smarkmconst UI_METHOD *UI_get_method(UI *ui) 578296341Sdelphij{ 579296341Sdelphij return ui->meth; 580296341Sdelphij} 581109998Smarkm 582109998Smarkmconst UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth) 583296341Sdelphij{ 584296341Sdelphij ui->meth = meth; 585296341Sdelphij return ui->meth; 586296341Sdelphij} 587109998Smarkm 588109998SmarkmUI_METHOD *UI_create_method(char *name) 589296341Sdelphij{ 590296341Sdelphij UI_METHOD *ui_method = (UI_METHOD *)OPENSSL_malloc(sizeof(UI_METHOD)); 591109998Smarkm 592296341Sdelphij if (ui_method) { 593296341Sdelphij memset(ui_method, 0, sizeof(*ui_method)); 594296341Sdelphij ui_method->name = BUF_strdup(name); 595296341Sdelphij } 596296341Sdelphij return ui_method; 597296341Sdelphij} 598109998Smarkm 599296341Sdelphij/* 600296341Sdelphij * BIG FSCKING WARNING!!!! If you use this on a statically allocated method 601296341Sdelphij * (that is, it hasn't been allocated using UI_create_method(), you deserve 602296341Sdelphij * anything Murphy can throw at you and more! You have been warned. 603296341Sdelphij */ 604109998Smarkmvoid UI_destroy_method(UI_METHOD *ui_method) 605296341Sdelphij{ 606296341Sdelphij OPENSSL_free(ui_method->name); 607296341Sdelphij ui_method->name = NULL; 608296341Sdelphij OPENSSL_free(ui_method); 609296341Sdelphij} 610109998Smarkm 611296341Sdelphijint UI_method_set_opener(UI_METHOD *method, int (*opener) (UI *ui)) 612296341Sdelphij{ 613296341Sdelphij if (method) { 614296341Sdelphij method->ui_open_session = opener; 615296341Sdelphij return 0; 616296341Sdelphij } else 617296341Sdelphij return -1; 618296341Sdelphij} 619109998Smarkm 620296341Sdelphijint UI_method_set_writer(UI_METHOD *method, 621296341Sdelphij int (*writer) (UI *ui, UI_STRING *uis)) 622296341Sdelphij{ 623296341Sdelphij if (method) { 624296341Sdelphij method->ui_write_string = writer; 625296341Sdelphij return 0; 626296341Sdelphij } else 627296341Sdelphij return -1; 628296341Sdelphij} 629109998Smarkm 630296341Sdelphijint UI_method_set_flusher(UI_METHOD *method, int (*flusher) (UI *ui)) 631296341Sdelphij{ 632296341Sdelphij if (method) { 633296341Sdelphij method->ui_flush = flusher; 634296341Sdelphij return 0; 635296341Sdelphij } else 636296341Sdelphij return -1; 637296341Sdelphij} 638109998Smarkm 639296341Sdelphijint UI_method_set_reader(UI_METHOD *method, 640296341Sdelphij int (*reader) (UI *ui, UI_STRING *uis)) 641296341Sdelphij{ 642296341Sdelphij if (method) { 643296341Sdelphij method->ui_read_string = reader; 644296341Sdelphij return 0; 645296341Sdelphij } else 646296341Sdelphij return -1; 647296341Sdelphij} 648109998Smarkm 649296341Sdelphijint UI_method_set_closer(UI_METHOD *method, int (*closer) (UI *ui)) 650296341Sdelphij{ 651296341Sdelphij if (method) { 652296341Sdelphij method->ui_close_session = closer; 653296341Sdelphij return 0; 654296341Sdelphij } else 655296341Sdelphij return -1; 656296341Sdelphij} 657109998Smarkm 658296341Sdelphijint UI_method_set_prompt_constructor(UI_METHOD *method, 659296341Sdelphij char *(*prompt_constructor) (UI *ui, 660296341Sdelphij const char 661296341Sdelphij *object_desc, 662296341Sdelphij const char 663296341Sdelphij *object_name)) 664296341Sdelphij{ 665296341Sdelphij if (method) { 666296341Sdelphij method->ui_construct_prompt = prompt_constructor; 667296341Sdelphij return 0; 668296341Sdelphij } else 669296341Sdelphij return -1; 670296341Sdelphij} 671238405Sjkim 672296341Sdelphijint (*UI_method_get_opener(UI_METHOD *method)) (UI *) { 673296341Sdelphij if (method) 674296341Sdelphij return method->ui_open_session; 675296341Sdelphij else 676296341Sdelphij return NULL; 677296341Sdelphij} 678109998Smarkm 679296341Sdelphijint (*UI_method_get_writer(UI_METHOD *method)) (UI *, UI_STRING *) { 680296341Sdelphij if (method) 681296341Sdelphij return method->ui_write_string; 682296341Sdelphij else 683296341Sdelphij return NULL; 684296341Sdelphij} 685109998Smarkm 686296341Sdelphijint (*UI_method_get_flusher(UI_METHOD *method)) (UI *) { 687296341Sdelphij if (method) 688296341Sdelphij return method->ui_flush; 689296341Sdelphij else 690296341Sdelphij return NULL; 691296341Sdelphij} 692109998Smarkm 693296341Sdelphijint (*UI_method_get_reader(UI_METHOD *method)) (UI *, UI_STRING *) { 694296341Sdelphij if (method) 695296341Sdelphij return method->ui_read_string; 696296341Sdelphij else 697296341Sdelphij return NULL; 698296341Sdelphij} 699109998Smarkm 700296341Sdelphijint (*UI_method_get_closer(UI_METHOD *method)) (UI *) { 701296341Sdelphij if (method) 702296341Sdelphij return method->ui_close_session; 703296341Sdelphij else 704296341Sdelphij return NULL; 705296341Sdelphij} 706109998Smarkm 707296341Sdelphijchar *(*UI_method_get_prompt_constructor(UI_METHOD *method)) (UI *, 708296341Sdelphij const char *, 709296341Sdelphij const char *) { 710296341Sdelphij if (method) 711296341Sdelphij return method->ui_construct_prompt; 712296341Sdelphij else 713296341Sdelphij return NULL; 714296341Sdelphij} 715238405Sjkim 716109998Smarkmenum UI_string_types UI_get_string_type(UI_STRING *uis) 717296341Sdelphij{ 718296341Sdelphij if (!uis) 719296341Sdelphij return UIT_NONE; 720296341Sdelphij return uis->type; 721296341Sdelphij} 722109998Smarkm 723109998Smarkmint UI_get_input_flags(UI_STRING *uis) 724296341Sdelphij{ 725296341Sdelphij if (!uis) 726296341Sdelphij return 0; 727296341Sdelphij return uis->input_flags; 728296341Sdelphij} 729109998Smarkm 730109998Smarkmconst char *UI_get0_output_string(UI_STRING *uis) 731296341Sdelphij{ 732296341Sdelphij if (!uis) 733296341Sdelphij return NULL; 734296341Sdelphij return uis->out_string; 735296341Sdelphij} 736109998Smarkm 737109998Smarkmconst char *UI_get0_action_string(UI_STRING *uis) 738296341Sdelphij{ 739296341Sdelphij if (!uis) 740296341Sdelphij return NULL; 741296341Sdelphij switch (uis->type) { 742296341Sdelphij case UIT_PROMPT: 743296341Sdelphij case UIT_BOOLEAN: 744296341Sdelphij return uis->_.boolean_data.action_desc; 745296341Sdelphij default: 746296341Sdelphij return NULL; 747296341Sdelphij } 748296341Sdelphij} 749109998Smarkm 750109998Smarkmconst char *UI_get0_result_string(UI_STRING *uis) 751296341Sdelphij{ 752296341Sdelphij if (!uis) 753296341Sdelphij return NULL; 754296341Sdelphij switch (uis->type) { 755296341Sdelphij case UIT_PROMPT: 756296341Sdelphij case UIT_VERIFY: 757296341Sdelphij return uis->result_buf; 758296341Sdelphij default: 759296341Sdelphij return NULL; 760296341Sdelphij } 761296341Sdelphij} 762109998Smarkm 763109998Smarkmconst char *UI_get0_test_string(UI_STRING *uis) 764296341Sdelphij{ 765296341Sdelphij if (!uis) 766296341Sdelphij return NULL; 767296341Sdelphij switch (uis->type) { 768296341Sdelphij case UIT_VERIFY: 769296341Sdelphij return uis->_.string_data.test_buf; 770296341Sdelphij default: 771296341Sdelphij return NULL; 772296341Sdelphij } 773296341Sdelphij} 774109998Smarkm 775109998Smarkmint UI_get_result_minsize(UI_STRING *uis) 776296341Sdelphij{ 777296341Sdelphij if (!uis) 778296341Sdelphij return -1; 779296341Sdelphij switch (uis->type) { 780296341Sdelphij case UIT_PROMPT: 781296341Sdelphij case UIT_VERIFY: 782296341Sdelphij return uis->_.string_data.result_minsize; 783296341Sdelphij default: 784296341Sdelphij return -1; 785296341Sdelphij } 786296341Sdelphij} 787109998Smarkm 788109998Smarkmint UI_get_result_maxsize(UI_STRING *uis) 789296341Sdelphij{ 790296341Sdelphij if (!uis) 791296341Sdelphij return -1; 792296341Sdelphij switch (uis->type) { 793296341Sdelphij case UIT_PROMPT: 794296341Sdelphij case UIT_VERIFY: 795296341Sdelphij return uis->_.string_data.result_maxsize; 796296341Sdelphij default: 797296341Sdelphij return -1; 798296341Sdelphij } 799296341Sdelphij} 800109998Smarkm 801109998Smarkmint UI_set_result(UI *ui, UI_STRING *uis, const char *result) 802296341Sdelphij{ 803296341Sdelphij int l = strlen(result); 804109998Smarkm 805296341Sdelphij ui->flags &= ~UI_FLAG_REDOABLE; 806109998Smarkm 807296341Sdelphij if (!uis) 808296341Sdelphij return -1; 809296341Sdelphij switch (uis->type) { 810296341Sdelphij case UIT_PROMPT: 811296341Sdelphij case UIT_VERIFY: 812296341Sdelphij { 813296341Sdelphij char number1[DECIMAL_SIZE(uis->_.string_data.result_minsize) + 1]; 814296341Sdelphij char number2[DECIMAL_SIZE(uis->_.string_data.result_maxsize) + 1]; 815109998Smarkm 816296341Sdelphij BIO_snprintf(number1, sizeof(number1), "%d", 817296341Sdelphij uis->_.string_data.result_minsize); 818296341Sdelphij BIO_snprintf(number2, sizeof(number2), "%d", 819296341Sdelphij uis->_.string_data.result_maxsize); 820109998Smarkm 821296341Sdelphij if (l < uis->_.string_data.result_minsize) { 822296341Sdelphij ui->flags |= UI_FLAG_REDOABLE; 823296341Sdelphij UIerr(UI_F_UI_SET_RESULT, UI_R_RESULT_TOO_SMALL); 824296341Sdelphij ERR_add_error_data(5, "You must type in ", 825296341Sdelphij number1, " to ", number2, " characters"); 826296341Sdelphij return -1; 827296341Sdelphij } 828296341Sdelphij if (l > uis->_.string_data.result_maxsize) { 829296341Sdelphij ui->flags |= UI_FLAG_REDOABLE; 830296341Sdelphij UIerr(UI_F_UI_SET_RESULT, UI_R_RESULT_TOO_LARGE); 831296341Sdelphij ERR_add_error_data(5, "You must type in ", 832296341Sdelphij number1, " to ", number2, " characters"); 833296341Sdelphij return -1; 834296341Sdelphij } 835296341Sdelphij } 836109998Smarkm 837296341Sdelphij if (!uis->result_buf) { 838296341Sdelphij UIerr(UI_F_UI_SET_RESULT, UI_R_NO_RESULT_BUFFER); 839296341Sdelphij return -1; 840296341Sdelphij } 841109998Smarkm 842296341Sdelphij BUF_strlcpy(uis->result_buf, result, 843296341Sdelphij uis->_.string_data.result_maxsize + 1); 844296341Sdelphij break; 845296341Sdelphij case UIT_BOOLEAN: 846296341Sdelphij { 847296341Sdelphij const char *p; 848109998Smarkm 849296341Sdelphij if (!uis->result_buf) { 850296341Sdelphij UIerr(UI_F_UI_SET_RESULT, UI_R_NO_RESULT_BUFFER); 851296341Sdelphij return -1; 852296341Sdelphij } 853109998Smarkm 854296341Sdelphij uis->result_buf[0] = '\0'; 855296341Sdelphij for (p = result; *p; p++) { 856296341Sdelphij if (strchr(uis->_.boolean_data.ok_chars, *p)) { 857296341Sdelphij uis->result_buf[0] = uis->_.boolean_data.ok_chars[0]; 858296341Sdelphij break; 859296341Sdelphij } 860296341Sdelphij if (strchr(uis->_.boolean_data.cancel_chars, *p)) { 861296341Sdelphij uis->result_buf[0] = uis->_.boolean_data.cancel_chars[0]; 862296341Sdelphij break; 863296341Sdelphij } 864296341Sdelphij } 865296341Sdelphij } 866296341Sdelphij default: 867296341Sdelphij break; 868296341Sdelphij } 869296341Sdelphij return 0; 870296341Sdelphij} 871