1da347917Sbeck /* crypto/ui/ui_lib.c -*- mode:C; c-file-style: "eay" -*- */ 2da347917Sbeck /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL 3da347917Sbeck * project 2001. 4da347917Sbeck */ 5da347917Sbeck /* ==================================================================== 6da347917Sbeck * Copyright (c) 2001 The OpenSSL Project. All rights reserved. 7da347917Sbeck * 8da347917Sbeck * Redistribution and use in source and binary forms, with or without 9da347917Sbeck * modification, are permitted provided that the following conditions 10da347917Sbeck * are met: 11da347917Sbeck * 12da347917Sbeck * 1. Redistributions of source code must retain the above copyright 13da347917Sbeck * notice, this list of conditions and the following disclaimer. 14da347917Sbeck * 15da347917Sbeck * 2. Redistributions in binary form must reproduce the above copyright 16da347917Sbeck * notice, this list of conditions and the following disclaimer in 17da347917Sbeck * the documentation and/or other materials provided with the 18da347917Sbeck * distribution. 19da347917Sbeck * 20da347917Sbeck * 3. All advertising materials mentioning features or use of this 21da347917Sbeck * software must display the following acknowledgment: 22da347917Sbeck * "This product includes software developed by the OpenSSL Project 23da347917Sbeck * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 24da347917Sbeck * 25da347917Sbeck * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26da347917Sbeck * endorse or promote products derived from this software without 27da347917Sbeck * prior written permission. For written permission, please contact 28da347917Sbeck * openssl-core@openssl.org. 29da347917Sbeck * 30da347917Sbeck * 5. Products derived from this software may not be called "OpenSSL" 31da347917Sbeck * nor may "OpenSSL" appear in their names without prior written 32da347917Sbeck * permission of the OpenSSL Project. 33da347917Sbeck * 34da347917Sbeck * 6. Redistributions of any form whatsoever must retain the following 35da347917Sbeck * acknowledgment: 36da347917Sbeck * "This product includes software developed by the OpenSSL Project 37da347917Sbeck * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 38da347917Sbeck * 39da347917Sbeck * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40da347917Sbeck * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41da347917Sbeck * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42da347917Sbeck * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43da347917Sbeck * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44da347917Sbeck * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45da347917Sbeck * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46da347917Sbeck * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47da347917Sbeck * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48da347917Sbeck * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49da347917Sbeck * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50da347917Sbeck * OF THE POSSIBILITY OF SUCH DAMAGE. 51da347917Sbeck * ==================================================================== 52da347917Sbeck * 53da347917Sbeck * This product includes cryptographic software written by Eric Young 54da347917Sbeck * (eay@cryptsoft.com). This product includes software written by Tim 55da347917Sbeck * Hudson (tjh@cryptsoft.com). 56da347917Sbeck * 57da347917Sbeck */ 58da347917Sbeck 59da347917Sbeck #include <string.h> 60*20175b85Sjsing 61*20175b85Sjsing #include <openssl/opensslconf.h> 62*20175b85Sjsing 634fcf65c5Sdjm #include "cryptlib.h" 64*20175b85Sjsing 65da347917Sbeck #include <openssl/buffer.h> 66da347917Sbeck #include <openssl/ui.h> 67da347917Sbeck #include <openssl/err.h> 68da347917Sbeck #include "ui_locl.h" 69da347917Sbeck 70c3bf3550Sjsing IMPLEMENT_STACK_OF(UI_STRING_ST) static const UI_METHOD *default_UI_meth = NULL; 71da347917Sbeck 72c3bf3550Sjsing UI * 73c3bf3550Sjsing UI_new(void) 74da347917Sbeck { 75da347917Sbeck return (UI_new_method(NULL)); 76da347917Sbeck } 77da347917Sbeck 78764af611Stedu UI * 79764af611Stedu UI_new_method(const UI_METHOD *method) 80da347917Sbeck { 81da347917Sbeck UI *ret; 82da347917Sbeck 836f3a6cb1Sbeck ret = (UI *) malloc(sizeof(UI)); 84764af611Stedu if (ret == NULL) { 85da347917Sbeck UIerr(UI_F_UI_NEW_METHOD, ERR_R_MALLOC_FAILURE); 86da347917Sbeck return NULL; 87da347917Sbeck } 88da347917Sbeck if (method == NULL) 89da347917Sbeck ret->meth = UI_get_default_method(); 90da347917Sbeck else 91da347917Sbeck ret->meth = method; 92da347917Sbeck 93da347917Sbeck ret->strings = NULL; 94da347917Sbeck ret->user_data = NULL; 9550c17820Sdjm ret->flags = 0; 96da347917Sbeck CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data); 97da347917Sbeck return ret; 98da347917Sbeck } 99da347917Sbeck 100764af611Stedu static void 101764af611Stedu free_string(UI_STRING *uis) 102da347917Sbeck { 103764af611Stedu if (uis->flags & OUT_STRING_FREEABLE) { 1046f3a6cb1Sbeck free((char *) uis->out_string); 105764af611Stedu switch (uis->type) { 106da347917Sbeck case UIT_BOOLEAN: 1076f3a6cb1Sbeck free((char *)uis->_.boolean_data.action_desc); 1086f3a6cb1Sbeck free((char *)uis->_.boolean_data.ok_chars); 1096f3a6cb1Sbeck free((char *)uis->_.boolean_data.cancel_chars); 110da347917Sbeck break; 111da347917Sbeck default: 112da347917Sbeck break; 113da347917Sbeck } 114da347917Sbeck } 1156f3a6cb1Sbeck free(uis); 116da347917Sbeck } 117da347917Sbeck 118764af611Stedu void 119764af611Stedu UI_free(UI *ui) 120da347917Sbeck { 121da347917Sbeck if (ui == NULL) 122da347917Sbeck return; 123da347917Sbeck sk_UI_STRING_pop_free(ui->strings, free_string); 124da347917Sbeck CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data); 1256f3a6cb1Sbeck free(ui); 126da347917Sbeck } 127da347917Sbeck 128764af611Stedu static int 129764af611Stedu allocate_string_stack(UI *ui) 130da347917Sbeck { 131764af611Stedu if (ui->strings == NULL) { 132da347917Sbeck ui->strings = sk_UI_STRING_new_null(); 133764af611Stedu if (ui->strings == NULL) { 134da347917Sbeck return -1; 135da347917Sbeck } 136da347917Sbeck } 137da347917Sbeck return 0; 138da347917Sbeck } 139da347917Sbeck 140764af611Stedu static UI_STRING * 141ba586daeSjsing general_allocate_prompt(UI *ui, const char *prompt, int prompt_freeable, 142ba586daeSjsing enum UI_string_types type, int input_flags, char *result_buf) 143da347917Sbeck { 144da347917Sbeck UI_STRING *ret = NULL; 145da347917Sbeck 146764af611Stedu if (prompt == NULL) { 147ba586daeSjsing UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, 148ba586daeSjsing ERR_R_PASSED_NULL_PARAMETER); 149c3bf3550Sjsing } else if ((type == UIT_PROMPT || type == UIT_VERIFY || 150c3bf3550Sjsing type == UIT_BOOLEAN) && result_buf == NULL) { 151da347917Sbeck UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, UI_R_NO_RESULT_BUFFER); 152764af611Stedu } else if ((ret = (UI_STRING *) malloc(sizeof(UI_STRING)))) { 153da347917Sbeck ret->out_string = prompt; 154da347917Sbeck ret->flags = prompt_freeable ? OUT_STRING_FREEABLE : 0; 155da347917Sbeck ret->input_flags = input_flags; 156da347917Sbeck ret->type = type; 157da347917Sbeck ret->result_buf = result_buf; 158da347917Sbeck } 159da347917Sbeck return ret; 160da347917Sbeck } 161da347917Sbeck 162764af611Stedu static int 163ba586daeSjsing general_allocate_string(UI *ui, const char *prompt, int prompt_freeable, 164ba586daeSjsing enum UI_string_types type, int input_flags, char *result_buf, int minsize, 165ba586daeSjsing int maxsize, const char *test_buf) 166da347917Sbeck { 167da347917Sbeck int ret = -1; 168da347917Sbeck UI_STRING *s = general_allocate_prompt(ui, prompt, prompt_freeable, 169da347917Sbeck type, input_flags, result_buf); 170da347917Sbeck 171764af611Stedu if (s) { 172764af611Stedu if (allocate_string_stack(ui) >= 0) { 173da347917Sbeck s->_.string_data.result_minsize = minsize; 174da347917Sbeck s->_.string_data.result_maxsize = maxsize; 175da347917Sbeck s->_.string_data.test_buf = test_buf; 176da347917Sbeck ret = sk_UI_STRING_push(ui->strings, s); 177da347917Sbeck /* sk_push() returns 0 on error. Let's addapt that */ 178764af611Stedu if (ret <= 0) 179764af611Stedu ret--; 180764af611Stedu } else 181da347917Sbeck free_string(s); 182da347917Sbeck } 183da347917Sbeck return ret; 184da347917Sbeck } 185da347917Sbeck 186764af611Stedu static int 187ba586daeSjsing general_allocate_boolean(UI *ui, const char *prompt, const char *action_desc, 188ba586daeSjsing const char *ok_chars, const char *cancel_chars, int prompt_freeable, 189ba586daeSjsing enum UI_string_types type, int input_flags, char *result_buf) 190da347917Sbeck { 191da347917Sbeck int ret = -1; 192da347917Sbeck UI_STRING *s; 193da347917Sbeck const char *p; 194da347917Sbeck 195764af611Stedu if (ok_chars == NULL) { 196ba586daeSjsing UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, 197ba586daeSjsing ERR_R_PASSED_NULL_PARAMETER); 198764af611Stedu } else if (cancel_chars == NULL) { 199ba586daeSjsing UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, 200ba586daeSjsing ERR_R_PASSED_NULL_PARAMETER); 201764af611Stedu } else { 202764af611Stedu for (p = ok_chars; *p; p++) { 203764af611Stedu if (strchr(cancel_chars, *p)) { 204da347917Sbeck UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, 205da347917Sbeck UI_R_COMMON_OK_AND_CANCEL_CHARACTERS); 206da347917Sbeck } 207da347917Sbeck } 208da347917Sbeck 209da347917Sbeck s = general_allocate_prompt(ui, prompt, prompt_freeable, 210da347917Sbeck type, input_flags, result_buf); 211da347917Sbeck 212764af611Stedu if (s) { 213764af611Stedu if (allocate_string_stack(ui) >= 0) { 214da347917Sbeck s->_.boolean_data.action_desc = action_desc; 215da347917Sbeck s->_.boolean_data.ok_chars = ok_chars; 216da347917Sbeck s->_.boolean_data.cancel_chars = cancel_chars; 217da347917Sbeck ret = sk_UI_STRING_push(ui->strings, s); 218764af611Stedu /* 219764af611Stedu * sk_push() returns 0 on error. Let's addapt 220764af611Stedu * that 221764af611Stedu */ 222764af611Stedu if (ret <= 0) 223764af611Stedu ret--; 224764af611Stedu } else 225da347917Sbeck free_string(s); 226da347917Sbeck } 227da347917Sbeck } 228da347917Sbeck return ret; 229da347917Sbeck } 230da347917Sbeck 231767fe2ffSmarkus /* Returns the index to the place in the stack or -1 for error. Uses a 232da347917Sbeck direct reference to the prompt. */ 233764af611Stedu int 234ba586daeSjsing UI_add_input_string(UI *ui, const char *prompt, int flags, char *result_buf, 235ba586daeSjsing int minsize, int maxsize) 236da347917Sbeck { 237ba586daeSjsing return general_allocate_string(ui, prompt, 0, UIT_PROMPT, flags, 238ba586daeSjsing result_buf, minsize, maxsize, NULL); 239da347917Sbeck } 240da347917Sbeck 241da347917Sbeck /* Same as UI_add_input_string(), excepts it takes a copy of the prompt */ 242764af611Stedu int 243ba586daeSjsing UI_dup_input_string(UI *ui, const char *prompt, int flags, char *result_buf, 244ba586daeSjsing int minsize, int maxsize) 245da347917Sbeck { 246da347917Sbeck char *prompt_copy = NULL; 247da347917Sbeck 248764af611Stedu if (prompt) { 249da347917Sbeck prompt_copy = BUF_strdup(prompt); 250764af611Stedu if (prompt_copy == NULL) { 251da347917Sbeck UIerr(UI_F_UI_DUP_INPUT_STRING, ERR_R_MALLOC_FAILURE); 252da347917Sbeck return 0; 253da347917Sbeck } 254da347917Sbeck } 255ba586daeSjsing return general_allocate_string(ui, prompt_copy, 1, UIT_PROMPT, flags, 256ba586daeSjsing result_buf, minsize, maxsize, NULL); 257da347917Sbeck } 258da347917Sbeck 259764af611Stedu int 260ba586daeSjsing UI_add_verify_string(UI *ui, const char *prompt, int flags, char *result_buf, 261ba586daeSjsing int minsize, int maxsize, const char *test_buf) 262da347917Sbeck { 263ba586daeSjsing return general_allocate_string(ui, prompt, 0, UIT_VERIFY, flags, 264ba586daeSjsing result_buf, minsize, maxsize, test_buf); 265da347917Sbeck } 266da347917Sbeck 267764af611Stedu int 268764af611Stedu UI_dup_verify_string(UI *ui, const char *prompt, int flags, 269da347917Sbeck char *result_buf, int minsize, int maxsize, const char *test_buf) 270da347917Sbeck { 271da347917Sbeck char *prompt_copy = NULL; 272da347917Sbeck 273764af611Stedu if (prompt) { 274da347917Sbeck prompt_copy = BUF_strdup(prompt); 275764af611Stedu if (prompt_copy == NULL) { 276da347917Sbeck UIerr(UI_F_UI_DUP_VERIFY_STRING, ERR_R_MALLOC_FAILURE); 277da347917Sbeck return -1; 278da347917Sbeck } 279da347917Sbeck } 280ba586daeSjsing return general_allocate_string(ui, prompt_copy, 1, UIT_VERIFY, flags, 281ba586daeSjsing result_buf, minsize, maxsize, test_buf); 282da347917Sbeck } 283da347917Sbeck 284764af611Stedu int 285764af611Stedu UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc, 286ba586daeSjsing const char *ok_chars, const char *cancel_chars, int flags, char *result_buf) 287da347917Sbeck { 288ba586daeSjsing return general_allocate_boolean(ui, prompt, action_desc, ok_chars, 289ba586daeSjsing cancel_chars, 0, UIT_BOOLEAN, flags, result_buf); 290da347917Sbeck } 291da347917Sbeck 292764af611Stedu int 293764af611Stedu UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, 294ba586daeSjsing const char *ok_chars, const char *cancel_chars, int flags, char *result_buf) 295da347917Sbeck { 296da347917Sbeck char *prompt_copy = NULL; 297da347917Sbeck char *action_desc_copy = NULL; 298da347917Sbeck char *ok_chars_copy = NULL; 299da347917Sbeck char *cancel_chars_copy = NULL; 300da347917Sbeck 301764af611Stedu if (prompt) { 302da347917Sbeck prompt_copy = BUF_strdup(prompt); 303764af611Stedu if (prompt_copy == NULL) { 304da347917Sbeck UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); 305da347917Sbeck goto err; 306da347917Sbeck } 307da347917Sbeck } 308764af611Stedu if (action_desc) { 309da347917Sbeck action_desc_copy = BUF_strdup(action_desc); 310764af611Stedu if (action_desc_copy == NULL) { 311da347917Sbeck UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); 312da347917Sbeck goto err; 313da347917Sbeck } 314da347917Sbeck } 315764af611Stedu if (ok_chars) { 316da347917Sbeck ok_chars_copy = BUF_strdup(ok_chars); 317764af611Stedu if (ok_chars_copy == NULL) { 318da347917Sbeck UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); 319da347917Sbeck goto err; 320da347917Sbeck } 321da347917Sbeck } 322764af611Stedu if (cancel_chars) { 323da347917Sbeck cancel_chars_copy = BUF_strdup(cancel_chars); 324764af611Stedu if (cancel_chars_copy == NULL) { 325da347917Sbeck UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); 326da347917Sbeck goto err; 327da347917Sbeck } 328da347917Sbeck } 329da347917Sbeck return general_allocate_boolean(ui, prompt_copy, action_desc_copy, 330da347917Sbeck ok_chars_copy, cancel_chars_copy, 1, UIT_BOOLEAN, flags, 331da347917Sbeck result_buf); 332c3bf3550Sjsing 333da347917Sbeck err: 334764af611Stedu free(prompt_copy); 335764af611Stedu free(action_desc_copy); 336764af611Stedu free(ok_chars_copy); 337764af611Stedu free(cancel_chars_copy); 338da347917Sbeck return -1; 339da347917Sbeck } 340da347917Sbeck 341764af611Stedu int 342764af611Stedu UI_add_info_string(UI *ui, const char *text) 343da347917Sbeck { 344da347917Sbeck return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0, 345da347917Sbeck NULL); 346da347917Sbeck } 347da347917Sbeck 348764af611Stedu int 349764af611Stedu UI_dup_info_string(UI *ui, const char *text) 350da347917Sbeck { 351da347917Sbeck char *text_copy = NULL; 352da347917Sbeck 353764af611Stedu if (text) { 354da347917Sbeck text_copy = BUF_strdup(text); 355764af611Stedu if (text_copy == NULL) { 356da347917Sbeck UIerr(UI_F_UI_DUP_INFO_STRING, ERR_R_MALLOC_FAILURE); 357da347917Sbeck return -1; 358da347917Sbeck } 359da347917Sbeck } 360da347917Sbeck return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL, 361da347917Sbeck 0, 0, NULL); 362da347917Sbeck } 363da347917Sbeck 364764af611Stedu int 365764af611Stedu UI_add_error_string(UI *ui, const char *text) 366da347917Sbeck { 367da347917Sbeck return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0, 368da347917Sbeck NULL); 369da347917Sbeck } 370da347917Sbeck 371764af611Stedu int 372764af611Stedu UI_dup_error_string(UI *ui, const char *text) 373da347917Sbeck { 374da347917Sbeck char *text_copy = NULL; 375da347917Sbeck 376764af611Stedu if (text) { 377da347917Sbeck text_copy = BUF_strdup(text); 378764af611Stedu if (text_copy == NULL) { 379da347917Sbeck UIerr(UI_F_UI_DUP_ERROR_STRING, ERR_R_MALLOC_FAILURE); 380da347917Sbeck return -1; 381da347917Sbeck } 382da347917Sbeck } 383da347917Sbeck return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL, 384da347917Sbeck 0, 0, NULL); 385da347917Sbeck } 386da347917Sbeck 387764af611Stedu char * 388c3bf3550Sjsing UI_construct_prompt(UI *ui, const char *object_desc, const char *object_name) 389da347917Sbeck { 390005a942cSjsing const char *format = "Enter %s for %s:"; 39164a2fea0Sjsing char *prompt; 392da347917Sbeck 393da347917Sbeck if (ui->meth->ui_construct_prompt) 39464a2fea0Sjsing return ui->meth->ui_construct_prompt(ui, object_desc, 39564a2fea0Sjsing object_name); 396da347917Sbeck 397da347917Sbeck if (object_desc == NULL) 398da347917Sbeck return NULL; 39964a2fea0Sjsing if (object_name == NULL) 40064a2fea0Sjsing format = "Enter %s:"; 40164a2fea0Sjsing if (asprintf(&prompt, format, object_desc, object_name) == -1) 40264a2fea0Sjsing return NULL; 403da347917Sbeck 404da347917Sbeck return prompt; 405da347917Sbeck } 406da347917Sbeck 407764af611Stedu void * 408764af611Stedu UI_add_user_data(UI *ui, void *user_data) 409da347917Sbeck { 410da347917Sbeck void *old_data = ui->user_data; 411ba586daeSjsing 412da347917Sbeck ui->user_data = user_data; 413da347917Sbeck return old_data; 414da347917Sbeck } 415da347917Sbeck 416764af611Stedu void * 417764af611Stedu UI_get0_user_data(UI *ui) 418da347917Sbeck { 419da347917Sbeck return ui->user_data; 420da347917Sbeck } 421da347917Sbeck 422764af611Stedu const char * 423764af611Stedu UI_get0_result(UI *ui, int i) 424da347917Sbeck { 425764af611Stedu if (i < 0) { 426da347917Sbeck UIerr(UI_F_UI_GET0_RESULT, UI_R_INDEX_TOO_SMALL); 427da347917Sbeck return NULL; 428da347917Sbeck } 429764af611Stedu if (i >= sk_UI_STRING_num(ui->strings)) { 430da347917Sbeck UIerr(UI_F_UI_GET0_RESULT, UI_R_INDEX_TOO_LARGE); 431da347917Sbeck return NULL; 432da347917Sbeck } 433da347917Sbeck return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i)); 434da347917Sbeck } 435da347917Sbeck 436764af611Stedu static int 437764af611Stedu print_error(const char *str, size_t len, UI *ui) 438da347917Sbeck { 439da347917Sbeck UI_STRING uis; 440da347917Sbeck 441da347917Sbeck memset(&uis, 0, sizeof(uis)); 442da347917Sbeck uis.type = UIT_ERROR; 443da347917Sbeck uis.out_string = str; 444da347917Sbeck 445c3bf3550Sjsing if (ui->meth->ui_write_string && 446c3bf3550Sjsing !ui->meth->ui_write_string(ui, &uis)) 447da347917Sbeck return -1; 448da347917Sbeck return 0; 449da347917Sbeck } 450da347917Sbeck 451764af611Stedu int 452764af611Stedu UI_process(UI *ui) 453da347917Sbeck { 454da347917Sbeck int i, ok = 0; 455da347917Sbeck 456da347917Sbeck if (ui->meth->ui_open_session && !ui->meth->ui_open_session(ui)) 457da347917Sbeck return -1; 458da347917Sbeck 459da347917Sbeck if (ui->flags & UI_FLAG_PRINT_ERRORS) 460da347917Sbeck ERR_print_errors_cb( 461da347917Sbeck (int (*)(const char *, size_t, void *)) print_error, 462da347917Sbeck (void *)ui); 463da347917Sbeck 464764af611Stedu for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) { 465c3bf3550Sjsing if (ui->meth->ui_write_string && 466c3bf3550Sjsing !ui->meth->ui_write_string(ui, 467764af611Stedu sk_UI_STRING_value(ui->strings, i))) { 468da347917Sbeck ok = -1; 469da347917Sbeck goto err; 470da347917Sbeck } 471da347917Sbeck } 472da347917Sbeck 473da347917Sbeck if (ui->meth->ui_flush) 474764af611Stedu switch (ui->meth->ui_flush(ui)) { 475da347917Sbeck case -1: /* Interrupt/Cancel/something... */ 476da347917Sbeck ok = -2; 477da347917Sbeck goto err; 478da347917Sbeck case 0: /* Errors */ 479da347917Sbeck ok = -1; 480da347917Sbeck goto err; 481da347917Sbeck default: /* Success */ 482da347917Sbeck ok = 0; 483da347917Sbeck break; 484da347917Sbeck } 485da347917Sbeck 486764af611Stedu for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) { 487764af611Stedu if (ui->meth->ui_read_string) { 488da347917Sbeck switch (ui->meth->ui_read_string(ui, 489764af611Stedu sk_UI_STRING_value(ui->strings, i))) { 490da347917Sbeck case -1: /* Interrupt/Cancel/something... */ 491da347917Sbeck ok = -2; 492da347917Sbeck goto err; 493da347917Sbeck case 0: /* Errors */ 494da347917Sbeck ok = -1; 495da347917Sbeck goto err; 496da347917Sbeck default: /* Success */ 497da347917Sbeck ok = 0; 498da347917Sbeck break; 499da347917Sbeck } 500da347917Sbeck } 501da347917Sbeck } 502ba586daeSjsing 503da347917Sbeck err: 504da347917Sbeck if (ui->meth->ui_close_session && !ui->meth->ui_close_session(ui)) 505da347917Sbeck return -1; 506da347917Sbeck return ok; 507da347917Sbeck } 508da347917Sbeck 509764af611Stedu int 510764af611Stedu UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void)) 511da347917Sbeck { 512764af611Stedu if (ui == NULL) { 513da347917Sbeck UIerr(UI_F_UI_CTRL, ERR_R_PASSED_NULL_PARAMETER); 514da347917Sbeck return -1; 515da347917Sbeck } 516764af611Stedu switch (cmd) { 517da347917Sbeck case UI_CTRL_PRINT_ERRORS: 518da347917Sbeck { 519da347917Sbeck int save_flag = !!(ui->flags & UI_FLAG_PRINT_ERRORS); 520da347917Sbeck if (i) 521da347917Sbeck ui->flags |= UI_FLAG_PRINT_ERRORS; 522da347917Sbeck else 523da347917Sbeck ui->flags &= ~UI_FLAG_PRINT_ERRORS; 524da347917Sbeck return save_flag; 525da347917Sbeck } 526da347917Sbeck case UI_CTRL_IS_REDOABLE: 527da347917Sbeck return !!(ui->flags & UI_FLAG_REDOABLE); 528da347917Sbeck default: 529da347917Sbeck break; 530da347917Sbeck } 531da347917Sbeck UIerr(UI_F_UI_CTRL, UI_R_UNKNOWN_CONTROL_COMMAND); 532da347917Sbeck return -1; 533da347917Sbeck } 534da347917Sbeck 535764af611Stedu int 536764af611Stedu UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 537da347917Sbeck CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 538da347917Sbeck { 539da347917Sbeck return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, argl, argp, 540da347917Sbeck new_func, dup_func, free_func); 541da347917Sbeck } 542da347917Sbeck 543764af611Stedu int 544764af611Stedu UI_set_ex_data(UI *r, int idx, void *arg) 545da347917Sbeck { 546da347917Sbeck return (CRYPTO_set_ex_data(&r->ex_data, idx, arg)); 547da347917Sbeck } 548da347917Sbeck 549764af611Stedu void * 550764af611Stedu UI_get_ex_data(UI *r, int idx) 551da347917Sbeck { 552da347917Sbeck return (CRYPTO_get_ex_data(&r->ex_data, idx)); 553da347917Sbeck } 554da347917Sbeck 555764af611Stedu void 556764af611Stedu UI_set_default_method(const UI_METHOD *meth) 557da347917Sbeck { 558da347917Sbeck default_UI_meth = meth; 559da347917Sbeck } 560da347917Sbeck 561764af611Stedu const UI_METHOD * 562764af611Stedu UI_get_default_method(void) 563da347917Sbeck { 564764af611Stedu if (default_UI_meth == NULL) { 565da347917Sbeck default_UI_meth = UI_OpenSSL(); 566da347917Sbeck } 567da347917Sbeck return default_UI_meth; 568da347917Sbeck } 569da347917Sbeck 570764af611Stedu const UI_METHOD * 571764af611Stedu UI_get_method(UI *ui) 572da347917Sbeck { 573da347917Sbeck return ui->meth; 574da347917Sbeck } 575da347917Sbeck 576764af611Stedu const UI_METHOD * 577764af611Stedu UI_set_method(UI *ui, const UI_METHOD *meth) 578da347917Sbeck { 579da347917Sbeck ui->meth = meth; 580da347917Sbeck return ui->meth; 581da347917Sbeck } 582da347917Sbeck 583da347917Sbeck 584764af611Stedu UI_METHOD * 585764af611Stedu UI_create_method(char *name) 586da347917Sbeck { 5876f3a6cb1Sbeck UI_METHOD *ui_method = (UI_METHOD *)malloc(sizeof(UI_METHOD)); 588da347917Sbeck 589764af611Stedu if (ui_method) { 590da347917Sbeck memset(ui_method, 0, sizeof(*ui_method)); 591da347917Sbeck ui_method->name = BUF_strdup(name); 5924fcf65c5Sdjm } 593da347917Sbeck return ui_method; 594da347917Sbeck } 595da347917Sbeck 596da347917Sbeck /* BIG FSCKING WARNING!!!! If you use this on a statically allocated method 597da347917Sbeck (that is, it hasn't been allocated using UI_create_method(), you deserve 598da347917Sbeck anything Murphy can throw at you and more! You have been warned. */ 599764af611Stedu void 600764af611Stedu UI_destroy_method(UI_METHOD *ui_method) 601da347917Sbeck { 6026f3a6cb1Sbeck free(ui_method->name); 603da347917Sbeck ui_method->name = NULL; 6046f3a6cb1Sbeck free(ui_method); 605da347917Sbeck } 606da347917Sbeck 607764af611Stedu int 608764af611Stedu UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui)) 609da347917Sbeck { 610764af611Stedu if (method) { 611da347917Sbeck method->ui_open_session = opener; 612da347917Sbeck return 0; 613764af611Stedu } else 614da347917Sbeck return -1; 615da347917Sbeck } 616da347917Sbeck 617764af611Stedu int 618764af611Stedu UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis)) 619da347917Sbeck { 620764af611Stedu if (method) { 621da347917Sbeck method->ui_write_string = writer; 622da347917Sbeck return 0; 623764af611Stedu } else 624da347917Sbeck return -1; 625da347917Sbeck } 626da347917Sbeck 627764af611Stedu int 628764af611Stedu UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui)) 629da347917Sbeck { 630764af611Stedu if (method) { 631da347917Sbeck method->ui_flush = flusher; 632da347917Sbeck return 0; 633764af611Stedu } else 634da347917Sbeck return -1; 635da347917Sbeck } 636da347917Sbeck 637764af611Stedu int 638764af611Stedu UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis)) 639da347917Sbeck { 640764af611Stedu if (method) { 641da347917Sbeck method->ui_read_string = reader; 642da347917Sbeck return 0; 643764af611Stedu } else 644da347917Sbeck return -1; 645da347917Sbeck } 646da347917Sbeck 647764af611Stedu int 648764af611Stedu UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui)) 649da347917Sbeck { 650764af611Stedu if (method) { 651da347917Sbeck method->ui_close_session = closer; 652da347917Sbeck return 0; 653764af611Stedu } else 654da347917Sbeck return -1; 655da347917Sbeck } 656da347917Sbeck 657764af611Stedu int 658c3bf3550Sjsing UI_method_set_prompt_constructor(UI_METHOD *method, 659c3bf3550Sjsing char *(*prompt_constructor)(UI *ui, const char *object_desc, 660c3bf3550Sjsing const char *object_name)) 6610a5d6edeSdjm { 662764af611Stedu if (method) { 6630a5d6edeSdjm method->ui_construct_prompt = prompt_constructor; 6640a5d6edeSdjm return 0; 665764af611Stedu } else 6660a5d6edeSdjm return -1; 6670a5d6edeSdjm } 6680a5d6edeSdjm 669c3bf3550Sjsing int 670c3bf3550Sjsing (*UI_method_get_opener(UI_METHOD * method))(UI *) 671da347917Sbeck { 672da347917Sbeck if (method) 673da347917Sbeck return method->ui_open_session; 674da347917Sbeck else 675da347917Sbeck return NULL; 676da347917Sbeck } 677da347917Sbeck 678c3bf3550Sjsing int 679c3bf3550Sjsing (*UI_method_get_writer(UI_METHOD *method))(UI *, UI_STRING *) 680da347917Sbeck { 681da347917Sbeck if (method) 682da347917Sbeck return method->ui_write_string; 683da347917Sbeck else 684da347917Sbeck return NULL; 685da347917Sbeck } 686da347917Sbeck 687c3bf3550Sjsing int 688c3bf3550Sjsing (*UI_method_get_flusher(UI_METHOD *method)) (UI *) 689da347917Sbeck { 690da347917Sbeck if (method) 691da347917Sbeck return method->ui_flush; 692da347917Sbeck else 693da347917Sbeck return NULL; 694da347917Sbeck } 695da347917Sbeck 696c3bf3550Sjsing int 697c3bf3550Sjsing (*UI_method_get_reader(UI_METHOD *method))(UI *, UI_STRING *) 698da347917Sbeck { 699da347917Sbeck if (method) 700da347917Sbeck return method->ui_read_string; 701da347917Sbeck else 702da347917Sbeck return NULL; 703da347917Sbeck } 704da347917Sbeck 705c3bf3550Sjsing int 706c3bf3550Sjsing (*UI_method_get_closer(UI_METHOD *method))(UI *) 707da347917Sbeck { 708da347917Sbeck if (method) 709da347917Sbeck return method->ui_close_session; 710da347917Sbeck else 711da347917Sbeck return NULL; 712da347917Sbeck } 713da347917Sbeck 714c3bf3550Sjsing char * 715c3bf3550Sjsing (*UI_method_get_prompt_constructor(UI_METHOD *method))(UI *, const char *, 716c3bf3550Sjsing const char *) 7170a5d6edeSdjm { 7180a5d6edeSdjm if (method) 7190a5d6edeSdjm return method->ui_construct_prompt; 7200a5d6edeSdjm else 7210a5d6edeSdjm return NULL; 7220a5d6edeSdjm } 7230a5d6edeSdjm 724764af611Stedu enum UI_string_types 725764af611Stedu UI_get_string_type(UI_STRING *uis) 726da347917Sbeck { 727da347917Sbeck if (!uis) 728da347917Sbeck return UIT_NONE; 729da347917Sbeck return uis->type; 730da347917Sbeck } 731da347917Sbeck 732764af611Stedu int 733764af611Stedu UI_get_input_flags(UI_STRING *uis) 734da347917Sbeck { 735da347917Sbeck if (!uis) 736da347917Sbeck return 0; 737da347917Sbeck return uis->input_flags; 738da347917Sbeck } 739da347917Sbeck 740764af611Stedu const char * 741764af611Stedu UI_get0_output_string(UI_STRING *uis) 742da347917Sbeck { 743da347917Sbeck if (!uis) 744da347917Sbeck return NULL; 745da347917Sbeck return uis->out_string; 746da347917Sbeck } 747da347917Sbeck 748764af611Stedu const char * 749764af611Stedu UI_get0_action_string(UI_STRING *uis) 750da347917Sbeck { 751da347917Sbeck if (!uis) 752da347917Sbeck return NULL; 753764af611Stedu switch (uis->type) { 754da347917Sbeck case UIT_PROMPT: 755da347917Sbeck case UIT_BOOLEAN: 756da347917Sbeck return uis->_.boolean_data.action_desc; 757da347917Sbeck default: 758da347917Sbeck return NULL; 759da347917Sbeck } 760da347917Sbeck } 761da347917Sbeck 762764af611Stedu const char * 763764af611Stedu UI_get0_result_string(UI_STRING *uis) 764da347917Sbeck { 765da347917Sbeck if (!uis) 766da347917Sbeck return NULL; 767764af611Stedu switch (uis->type) { 768da347917Sbeck case UIT_PROMPT: 769da347917Sbeck case UIT_VERIFY: 770da347917Sbeck return uis->result_buf; 771da347917Sbeck default: 772da347917Sbeck return NULL; 773da347917Sbeck } 774da347917Sbeck } 775da347917Sbeck 776764af611Stedu const char * 777764af611Stedu UI_get0_test_string(UI_STRING *uis) 778da347917Sbeck { 779da347917Sbeck if (!uis) 780da347917Sbeck return NULL; 781764af611Stedu switch (uis->type) { 782da347917Sbeck case UIT_VERIFY: 783da347917Sbeck return uis->_.string_data.test_buf; 784da347917Sbeck default: 785da347917Sbeck return NULL; 786da347917Sbeck } 787da347917Sbeck } 788da347917Sbeck 789764af611Stedu int 790764af611Stedu UI_get_result_minsize(UI_STRING *uis) 791da347917Sbeck { 792da347917Sbeck if (!uis) 793da347917Sbeck return -1; 794764af611Stedu switch (uis->type) { 795da347917Sbeck case UIT_PROMPT: 796da347917Sbeck case UIT_VERIFY: 797da347917Sbeck return uis->_.string_data.result_minsize; 798da347917Sbeck default: 799da347917Sbeck return -1; 800da347917Sbeck } 801da347917Sbeck } 802da347917Sbeck 803764af611Stedu int 804764af611Stedu UI_get_result_maxsize(UI_STRING *uis) 805da347917Sbeck { 806da347917Sbeck if (!uis) 807da347917Sbeck return -1; 808764af611Stedu switch (uis->type) { 809da347917Sbeck case UIT_PROMPT: 810da347917Sbeck case UIT_VERIFY: 811da347917Sbeck return uis->_.string_data.result_maxsize; 812da347917Sbeck default: 813da347917Sbeck return -1; 814da347917Sbeck } 815da347917Sbeck } 816da347917Sbeck 817764af611Stedu int 818764af611Stedu UI_set_result(UI *ui, UI_STRING *uis, const char *result) 819da347917Sbeck { 820da347917Sbeck int l = strlen(result); 821da347917Sbeck 822da347917Sbeck ui->flags &= ~UI_FLAG_REDOABLE; 823da347917Sbeck 824da347917Sbeck if (!uis) 825da347917Sbeck return -1; 826764af611Stedu switch (uis->type) { 827da347917Sbeck case UIT_PROMPT: 828da347917Sbeck case UIT_VERIFY: 829764af611Stedu if (l < uis->_.string_data.result_minsize) { 830da347917Sbeck ui->flags |= UI_FLAG_REDOABLE; 8310f637b92Sbeck UIerr(UI_F_UI_SET_RESULT, 8320f637b92Sbeck UI_R_RESULT_TOO_SMALL); 8330f637b92Sbeck ERR_asprintf_error_data 8340f637b92Sbeck ("You must type in %d to %d characters", 8350f637b92Sbeck uis->_.string_data.result_minsize, 8360f637b92Sbeck uis->_.string_data.result_maxsize); 837da347917Sbeck return -1; 838da347917Sbeck } 839764af611Stedu if (l > uis->_.string_data.result_maxsize) { 840da347917Sbeck ui->flags |= UI_FLAG_REDOABLE; 8410f637b92Sbeck UIerr(UI_F_UI_SET_RESULT, 8420f637b92Sbeck UI_R_RESULT_TOO_LARGE); 8430f637b92Sbeck ERR_asprintf_error_data 8440f637b92Sbeck ("You must type in %d to %d characters", 8450f637b92Sbeck uis->_.string_data.result_minsize, 8460f637b92Sbeck uis->_.string_data.result_maxsize); 847da347917Sbeck return -1; 848da347917Sbeck } 849764af611Stedu if (!uis->result_buf) { 850da347917Sbeck UIerr(UI_F_UI_SET_RESULT, UI_R_NO_RESULT_BUFFER); 851da347917Sbeck return -1; 852da347917Sbeck } 853143cedbbSbeck strlcpy(uis->result_buf, result, 854c52d3e9eSho uis->_.string_data.result_maxsize + 1); 855da347917Sbeck break; 856da347917Sbeck case UIT_BOOLEAN: 857da347917Sbeck { 858da347917Sbeck const char *p; 859da347917Sbeck 860764af611Stedu if (!uis->result_buf) { 861da347917Sbeck UIerr(UI_F_UI_SET_RESULT, UI_R_NO_RESULT_BUFFER); 862da347917Sbeck return -1; 863da347917Sbeck } 864da347917Sbeck uis->result_buf[0] = '\0'; 865764af611Stedu for (p = result; *p; p++) { 866764af611Stedu if (strchr(uis->_.boolean_data.ok_chars, *p)) { 867da347917Sbeck uis->result_buf[0] = 868da347917Sbeck uis->_.boolean_data.ok_chars[0]; 869da347917Sbeck break; 870da347917Sbeck } 871764af611Stedu if (strchr(uis->_.boolean_data.cancel_chars, *p)) { 872da347917Sbeck uis->result_buf[0] = 873da347917Sbeck uis->_.boolean_data.cancel_chars[0]; 874da347917Sbeck break; 875da347917Sbeck } 876da347917Sbeck } 877da347917Sbeck default: 878da347917Sbeck break; 879da347917Sbeck } 880da347917Sbeck } 881da347917Sbeck return 0; 882da347917Sbeck } 883