First public contribution.
1 /* crypto/ui/ui_lib.c -*- mode:C; c-file-style: "eay" -*- */
2 /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
5 /* ====================================================================
6 * Copyright (c) 2001 The OpenSSL Project. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * openssl-core@openssl.org.
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
34 * 6. Redistributions of any form whatsoever must retain the following
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
59 © Portions copyright (c) 2006 Nokia Corporation. All rights reserved.
64 #include <openssl/e_os2.h>
65 #include <openssl/buffer.h>
66 #include <openssl/ui.h>
67 #include <openssl/err.h>
69 #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
70 #include "libcrypto_wsd_macros.h"
71 #include "libcrypto_wsd.h"
74 IMPLEMENT_STACK_OF(UI_STRING_ST)
77 static const UI_METHOD *default_UI_meth=NULL;
79 GET_STATIC_VAR_FROM_TLS(default_UI_meth,ui_lib,const UI_METHOD *)
80 #define default_UI_meth (*GET_WSD_VAR_NAME(default_UI_meth,ui_lib, s)())
83 EXPORT_C UI *UI_new(void)
85 return(UI_new_method(NULL));
88 EXPORT_C UI *UI_new_method(const UI_METHOD *method)
92 ret=(UI *)OPENSSL_malloc(sizeof(UI));
95 UIerr(UI_F_UI_NEW_METHOD,ERR_R_MALLOC_FAILURE);
99 ret->meth=UI_get_default_method();
105 CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data);
109 static void free_string(UI_STRING *uis)
111 if (uis->flags & OUT_STRING_FREEABLE)
113 OPENSSL_free((char *)uis->out_string);
117 OPENSSL_free((char *)uis->_.boolean_data.action_desc);
118 OPENSSL_free((char *)uis->_.boolean_data.ok_chars);
119 OPENSSL_free((char *)uis->_.boolean_data.cancel_chars);
128 EXPORT_C void UI_free(UI *ui)
132 sk_UI_STRING_pop_free(ui->strings,free_string);
133 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data);
137 static int allocate_string_stack(UI *ui)
139 if (ui->strings == NULL)
141 ui->strings=sk_UI_STRING_new_null();
142 if (ui->strings == NULL)
150 static UI_STRING *general_allocate_prompt(UI *ui, const char *prompt,
151 int prompt_freeable, enum UI_string_types type, int input_flags,
154 UI_STRING *ret = NULL;
158 UIerr(UI_F_GENERAL_ALLOCATE_PROMPT,ERR_R_PASSED_NULL_PARAMETER);
160 else if ((type == UIT_PROMPT || type == UIT_VERIFY
161 || type == UIT_BOOLEAN) && result_buf == NULL)
163 UIerr(UI_F_GENERAL_ALLOCATE_PROMPT,UI_R_NO_RESULT_BUFFER);
165 else if ((ret = (UI_STRING *)OPENSSL_malloc(sizeof(UI_STRING))))
167 ret->out_string=prompt;
168 ret->flags=prompt_freeable ? OUT_STRING_FREEABLE : 0;
169 ret->input_flags=input_flags;
171 ret->result_buf=result_buf;
176 static int general_allocate_string(UI *ui, const char *prompt,
177 int prompt_freeable, enum UI_string_types type, int input_flags,
178 char *result_buf, int minsize, int maxsize, const char *test_buf)
181 UI_STRING *s = general_allocate_prompt(ui, prompt, prompt_freeable,
182 type, input_flags, result_buf);
186 if (allocate_string_stack(ui) >= 0)
188 s->_.string_data.result_minsize=minsize;
189 s->_.string_data.result_maxsize=maxsize;
190 s->_.string_data.test_buf=test_buf;
191 ret=sk_UI_STRING_push(ui->strings, s);
192 /* sk_push() returns 0 on error. Let's addapt that */
201 static int general_allocate_boolean(UI *ui,
202 const char *prompt, const char *action_desc,
203 const char *ok_chars, const char *cancel_chars,
204 int prompt_freeable, enum UI_string_types type, int input_flags,
211 if (ok_chars == NULL)
213 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,ERR_R_PASSED_NULL_PARAMETER);
215 else if (cancel_chars == NULL)
217 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,ERR_R_PASSED_NULL_PARAMETER);
221 for(p = ok_chars; *p; p++)
223 if (strchr(cancel_chars, *p))
225 UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,
226 UI_R_COMMON_OK_AND_CANCEL_CHARACTERS);
230 s = general_allocate_prompt(ui, prompt, prompt_freeable,
231 type, input_flags, result_buf);
235 if (allocate_string_stack(ui) >= 0)
237 s->_.boolean_data.action_desc = action_desc;
238 s->_.boolean_data.ok_chars = ok_chars;
239 s->_.boolean_data.cancel_chars = cancel_chars;
240 ret=sk_UI_STRING_push(ui->strings, s);
241 /* sk_push() returns 0 on error.
252 /* Returns the index to the place in the stack or -1 for error. Uses a
253 direct reference to the prompt. */
254 EXPORT_C int UI_add_input_string(UI *ui, const char *prompt, int flags,
255 char *result_buf, int minsize, int maxsize)
257 return general_allocate_string(ui, prompt, 0,
258 UIT_PROMPT, flags, result_buf, minsize, maxsize, NULL);
261 /* Same as UI_add_input_string(), excepts it takes a copy of the prompt */
262 EXPORT_C int UI_dup_input_string(UI *ui, const char *prompt, int flags,
263 char *result_buf, int minsize, int maxsize)
265 char *prompt_copy=NULL;
269 prompt_copy=BUF_strdup(prompt);
270 if (prompt_copy == NULL)
272 UIerr(UI_F_UI_DUP_INPUT_STRING,ERR_R_MALLOC_FAILURE);
277 return general_allocate_string(ui, prompt_copy, 1,
278 UIT_PROMPT, flags, result_buf, minsize, maxsize, NULL);
281 EXPORT_C int UI_add_verify_string(UI *ui, const char *prompt, int flags,
282 char *result_buf, int minsize, int maxsize, const char *test_buf)
284 return general_allocate_string(ui, prompt, 0,
285 UIT_VERIFY, flags, result_buf, minsize, maxsize, test_buf);
288 EXPORT_C int UI_dup_verify_string(UI *ui, const char *prompt, int flags,
289 char *result_buf, int minsize, int maxsize, const char *test_buf)
291 char *prompt_copy=NULL;
295 prompt_copy=BUF_strdup(prompt);
296 if (prompt_copy == NULL)
298 UIerr(UI_F_UI_DUP_VERIFY_STRING,ERR_R_MALLOC_FAILURE);
303 return general_allocate_string(ui, prompt_copy, 1,
304 UIT_VERIFY, flags, result_buf, minsize, maxsize, test_buf);
307 EXPORT_C int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc,
308 const char *ok_chars, const char *cancel_chars,
309 int flags, char *result_buf)
311 return general_allocate_boolean(ui, prompt, action_desc,
312 ok_chars, cancel_chars, 0, UIT_BOOLEAN, flags, result_buf);
315 EXPORT_C int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc,
316 const char *ok_chars, const char *cancel_chars,
317 int flags, char *result_buf)
319 char *prompt_copy = NULL;
320 char *action_desc_copy = NULL;
321 char *ok_chars_copy = NULL;
322 char *cancel_chars_copy = NULL;
326 prompt_copy=BUF_strdup(prompt);
327 if (prompt_copy == NULL)
329 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE);
336 action_desc_copy=BUF_strdup(action_desc);
337 if (action_desc_copy == NULL)
339 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE);
346 ok_chars_copy=BUF_strdup(ok_chars);
347 if (ok_chars_copy == NULL)
349 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE);
356 cancel_chars_copy=BUF_strdup(cancel_chars);
357 if (cancel_chars_copy == NULL)
359 UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE);
364 return general_allocate_boolean(ui, prompt_copy, action_desc_copy,
365 ok_chars_copy, cancel_chars_copy, 1, UIT_BOOLEAN, flags,
368 if (prompt_copy) OPENSSL_free(prompt_copy);
369 if (action_desc_copy) OPENSSL_free(action_desc_copy);
370 if (ok_chars_copy) OPENSSL_free(ok_chars_copy);
371 if (cancel_chars_copy) OPENSSL_free(cancel_chars_copy);
375 EXPORT_C int UI_add_info_string(UI *ui, const char *text)
377 return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0,
381 EXPORT_C int UI_dup_info_string(UI *ui, const char *text)
383 char *text_copy=NULL;
387 text_copy=BUF_strdup(text);
388 if (text_copy == NULL)
390 UIerr(UI_F_UI_DUP_INFO_STRING,ERR_R_MALLOC_FAILURE);
395 return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL,
399 EXPORT_C int UI_add_error_string(UI *ui, const char *text)
401 return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0,
405 EXPORT_C int UI_dup_error_string(UI *ui, const char *text)
407 char *text_copy=NULL;
411 text_copy=BUF_strdup(text);
412 if (text_copy == NULL)
414 UIerr(UI_F_UI_DUP_ERROR_STRING,ERR_R_MALLOC_FAILURE);
418 return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL,
422 EXPORT_C char *UI_construct_prompt(UI *ui, const char *object_desc,
423 const char *object_name)
427 if (ui->meth->ui_construct_prompt)
428 prompt = ui->meth->ui_construct_prompt(ui,
429 object_desc, object_name);
432 char prompt1[] = "Enter ";
433 char prompt2[] = " for ";
434 char prompt3[] = ":";
437 if (object_desc == NULL)
439 len = sizeof(prompt1) - 1 + strlen(object_desc);
441 len += sizeof(prompt2) - 1 + strlen(object_name);
442 len += sizeof(prompt3) - 1;
444 prompt = (char *)OPENSSL_malloc(len + 1);
449 BUF_strlcpy(prompt, prompt1, len + 1);
450 BUF_strlcat(prompt, object_desc, len + 1);
453 BUF_strlcat(prompt, prompt2, len + 1);
454 BUF_strlcat(prompt, object_name, len + 1);
456 BUF_strlcat(prompt, prompt3, len + 1);
461 EXPORT_C void *UI_add_user_data(UI *ui, void *user_data)
463 void *old_data = ui->user_data;
464 ui->user_data = user_data;
468 EXPORT_C void *UI_get0_user_data(UI *ui)
470 return ui->user_data;
473 EXPORT_C const char *UI_get0_result(UI *ui, int i)
477 UIerr(UI_F_UI_GET0_RESULT,UI_R_INDEX_TOO_SMALL);
480 if (i >= sk_UI_STRING_num(ui->strings))
482 UIerr(UI_F_UI_GET0_RESULT,UI_R_INDEX_TOO_LARGE);
485 return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i));
488 static int print_error(const char *str, size_t len, UI *ui)
492 memset(&uis, 0, sizeof(uis));
493 uis.type = UIT_ERROR;
494 uis.out_string = str;
496 if (ui->meth->ui_write_string
497 && !ui->meth->ui_write_string(ui, &uis))
502 EXPORT_C int UI_process(UI *ui)
506 if (ui->meth->ui_open_session && !ui->meth->ui_open_session(ui))
509 if (ui->flags & UI_FLAG_PRINT_ERRORS)
511 (int (*)(const char *, size_t, void *))print_error,
514 for(i=0; i<sk_UI_STRING_num(ui->strings); i++)
516 if (ui->meth->ui_write_string
517 && !ui->meth->ui_write_string(ui,
518 sk_UI_STRING_value(ui->strings, i)))
525 if (ui->meth->ui_flush)
526 switch(ui->meth->ui_flush(ui))
528 case -1: /* Interrupt/Cancel/something... */
534 default: /* Success */
539 for(i=0; i<sk_UI_STRING_num(ui->strings); i++)
541 if (ui->meth->ui_read_string)
543 switch(ui->meth->ui_read_string(ui,
544 sk_UI_STRING_value(ui->strings, i)))
546 case -1: /* Interrupt/Cancel/something... */
552 default: /* Success */
559 if (ui->meth->ui_close_session && !ui->meth->ui_close_session(ui))
564 EXPORT_C int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f)(void))
568 UIerr(UI_F_UI_CTRL,ERR_R_PASSED_NULL_PARAMETER);
573 case UI_CTRL_PRINT_ERRORS:
575 int save_flag = !!(ui->flags & UI_FLAG_PRINT_ERRORS);
577 ui->flags |= UI_FLAG_PRINT_ERRORS;
579 ui->flags &= ~UI_FLAG_PRINT_ERRORS;
582 case UI_CTRL_IS_REDOABLE:
583 return !!(ui->flags & UI_FLAG_REDOABLE);
587 UIerr(UI_F_UI_CTRL,UI_R_UNKNOWN_CONTROL_COMMAND);
591 EXPORT_C int UI_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
592 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
594 return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, argl, argp,
595 new_func, dup_func, free_func);
598 EXPORT_C int UI_set_ex_data(UI *r, int idx, void *arg)
600 return(CRYPTO_set_ex_data(&r->ex_data,idx,arg));
603 EXPORT_C void *UI_get_ex_data(UI *r, int idx)
605 return(CRYPTO_get_ex_data(&r->ex_data,idx));
608 EXPORT_C void UI_set_default_method(const UI_METHOD *meth)
610 default_UI_meth=meth;
613 EXPORT_C const UI_METHOD *UI_get_default_method(void)
615 if (default_UI_meth == NULL)
617 default_UI_meth=UI_OpenSSL();
619 return default_UI_meth;
622 EXPORT_C const UI_METHOD *UI_get_method(UI *ui)
627 EXPORT_C const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth)
634 EXPORT_C UI_METHOD *UI_create_method(char *name)
636 UI_METHOD *ui_method = (UI_METHOD *)OPENSSL_malloc(sizeof(UI_METHOD));
640 memset(ui_method, 0, sizeof(*ui_method));
641 ui_method->name = BUF_strdup(name);
646 /* BIG FSCKING WARNING!!!! If you use this on a statically allocated method
647 (that is, it hasn't been allocated using UI_create_method(), you deserve
648 anything Murphy can throw at you and more! You have been warned. */
649 EXPORT_C void UI_destroy_method(UI_METHOD *ui_method)
651 OPENSSL_free(ui_method->name);
652 ui_method->name = NULL;
653 OPENSSL_free(ui_method);
656 EXPORT_C int UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui))
660 method->ui_open_session = opener;
667 EXPORT_C int UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis))
671 method->ui_write_string = writer;
678 EXPORT_C int UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui))
682 method->ui_flush = flusher;
689 EXPORT_C int UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis))
693 method->ui_read_string = reader;
700 EXPORT_C int UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui))
704 method->ui_close_session = closer;
711 EXPORT_C int (*UI_method_get_opener(UI_METHOD *method))(UI*)
714 return method->ui_open_session;
719 EXPORT_C int (*UI_method_get_writer(UI_METHOD *method))(UI*,UI_STRING*)
722 return method->ui_write_string;
727 EXPORT_C int (*UI_method_get_flusher(UI_METHOD *method))(UI*)
730 return method->ui_flush;
735 EXPORT_C int (*UI_method_get_reader(UI_METHOD *method))(UI*,UI_STRING*)
738 return method->ui_read_string;
743 EXPORT_C int (*UI_method_get_closer(UI_METHOD *method))(UI*)
746 return method->ui_close_session;
751 EXPORT_C enum UI_string_types UI_get_string_type(UI_STRING *uis)
758 EXPORT_C int UI_get_input_flags(UI_STRING *uis)
762 return uis->input_flags;
765 EXPORT_C const char *UI_get0_output_string(UI_STRING *uis)
769 return uis->out_string;
772 EXPORT_C const char *UI_get0_action_string(UI_STRING *uis)
780 return uis->_.boolean_data.action_desc;
786 EXPORT_C const char *UI_get0_result_string(UI_STRING *uis)
794 return uis->result_buf;
800 EXPORT_C const char *UI_get0_test_string(UI_STRING *uis)
807 return uis->_.string_data.test_buf;
813 EXPORT_C int UI_get_result_minsize(UI_STRING *uis)
821 return uis->_.string_data.result_minsize;
827 EXPORT_C int UI_get_result_maxsize(UI_STRING *uis)
835 return uis->_.string_data.result_maxsize;
841 EXPORT_C int UI_set_result(UI *ui, UI_STRING *uis, const char *result)
843 int l = strlen(result);
845 ui->flags &= ~UI_FLAG_REDOABLE;
854 char number1[DECIMAL_SIZE(uis->_.string_data.result_minsize)+1];
855 char number2[DECIMAL_SIZE(uis->_.string_data.result_maxsize)+1];
857 BIO_snprintf(number1, sizeof(number1), "%d",
858 uis->_.string_data.result_minsize);
859 BIO_snprintf(number2, sizeof(number2), "%d",
860 uis->_.string_data.result_maxsize);
862 if (l < uis->_.string_data.result_minsize)
864 ui->flags |= UI_FLAG_REDOABLE;
865 UIerr(UI_F_UI_SET_RESULT,UI_R_RESULT_TOO_SMALL);
866 ERR_add_error_data(5,"You must type in ",
867 number1," to ",number2," characters");
870 if (l > uis->_.string_data.result_maxsize)
872 ui->flags |= UI_FLAG_REDOABLE;
873 UIerr(UI_F_UI_SET_RESULT,UI_R_RESULT_TOO_LARGE);
874 ERR_add_error_data(5,"You must type in ",
875 number1," to ",number2," characters");
880 if (!uis->result_buf)
882 UIerr(UI_F_UI_SET_RESULT,UI_R_NO_RESULT_BUFFER);
886 BUF_strlcpy(uis->result_buf, result,
887 uis->_.string_data.result_maxsize + 1);
893 if (!uis->result_buf)
895 UIerr(UI_F_UI_SET_RESULT,UI_R_NO_RESULT_BUFFER);
899 uis->result_buf[0] = '\0';
900 for(p = result; *p; p++)
902 if (strchr(uis->_.boolean_data.ok_chars, *p))
905 uis->_.boolean_data.ok_chars[0];
908 if (strchr(uis->_.boolean_data.cancel_chars, *p))
911 uis->_.boolean_data.cancel_chars[0];