ssl/libcrypto/src/crypto/ui/ui_lib.c
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     1 /* crypto/ui/ui_lib.c -*- mode:C; c-file-style: "eay" -*- */
       
     2 /* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
       
     3  * project 2001.
       
     4  */
       
     5 /* ====================================================================
       
     6  * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
       
     7  *
       
     8  * Redistribution and use in source and binary forms, with or without
       
     9  * modification, are permitted provided that the following conditions
       
    10  * are met:
       
    11  *
       
    12  * 1. Redistributions of source code must retain the above copyright
       
    13  *    notice, this list of conditions and the following disclaimer. 
       
    14  *
       
    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
       
    18  *    distribution.
       
    19  *
       
    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/)"
       
    24  *
       
    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.
       
    29  *
       
    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.
       
    33  *
       
    34  * 6. Redistributions of any form whatsoever must retain the following
       
    35  *    acknowledgment:
       
    36  *    "This product includes software developed by the OpenSSL Project
       
    37  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
       
    38  *
       
    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  * ====================================================================
       
    52  *
       
    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).
       
    56  *
       
    57  */
       
    58  /*
       
    59  © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
    60  */
       
    61 
       
    62 #include <string.h>
       
    63 #include "cryptlib.h"
       
    64 #include <openssl/e_os2.h>
       
    65 #include <openssl/buffer.h>
       
    66 #include <openssl/ui.h>
       
    67 #include <openssl/err.h>
       
    68 #include "ui_locl.h"
       
    69 #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
       
    70 #include "libcrypto_wsd_macros.h"
       
    71 #include "libcrypto_wsd.h"
       
    72 #endif
       
    73 
       
    74 IMPLEMENT_STACK_OF(UI_STRING_ST)
       
    75 
       
    76 #ifndef EMULATOR
       
    77 static const UI_METHOD *default_UI_meth=NULL;
       
    78 #else
       
    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)())
       
    81 #endif
       
    82 
       
    83 EXPORT_C UI *UI_new(void)
       
    84 	{
       
    85 	return(UI_new_method(NULL));
       
    86 	}
       
    87 
       
    88 EXPORT_C UI *UI_new_method(const UI_METHOD *method)
       
    89 	{
       
    90 	UI *ret;
       
    91 
       
    92 	ret=(UI *)OPENSSL_malloc(sizeof(UI));
       
    93 	if (ret == NULL)
       
    94 		{
       
    95 		UIerr(UI_F_UI_NEW_METHOD,ERR_R_MALLOC_FAILURE);
       
    96 		return NULL;
       
    97 		}
       
    98 	if (method == NULL)
       
    99 		ret->meth=UI_get_default_method();
       
   100 	else
       
   101 		ret->meth=method;
       
   102 
       
   103 	ret->strings=NULL;
       
   104 	ret->user_data=NULL;
       
   105 	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data);
       
   106 	return ret;
       
   107 	}
       
   108 
       
   109 static void free_string(UI_STRING *uis)
       
   110 	{
       
   111 	if (uis->flags & OUT_STRING_FREEABLE)
       
   112 		{
       
   113 		OPENSSL_free((char *)uis->out_string);
       
   114 		switch(uis->type)
       
   115 			{
       
   116 		case UIT_BOOLEAN:
       
   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);
       
   120 			break;
       
   121 		default:
       
   122 			break;
       
   123 			}
       
   124 		}
       
   125 	OPENSSL_free(uis);
       
   126 	}
       
   127 
       
   128 EXPORT_C void UI_free(UI *ui)
       
   129 	{
       
   130 	if (ui == NULL)
       
   131 		return;
       
   132 	sk_UI_STRING_pop_free(ui->strings,free_string);
       
   133 	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data);
       
   134 	OPENSSL_free(ui);
       
   135 	}
       
   136 
       
   137 static int allocate_string_stack(UI *ui)
       
   138 	{
       
   139 	if (ui->strings == NULL)
       
   140 		{
       
   141 		ui->strings=sk_UI_STRING_new_null();
       
   142 		if (ui->strings == NULL)
       
   143 			{
       
   144 			return -1;
       
   145 			}
       
   146 		}
       
   147 	return 0;
       
   148 	}
       
   149 
       
   150 static UI_STRING *general_allocate_prompt(UI *ui, const char *prompt,
       
   151 	int prompt_freeable, enum UI_string_types type, int input_flags,
       
   152 	char *result_buf)
       
   153 	{
       
   154 	UI_STRING *ret = NULL;
       
   155 
       
   156 	if (prompt == NULL)
       
   157 		{
       
   158 		UIerr(UI_F_GENERAL_ALLOCATE_PROMPT,ERR_R_PASSED_NULL_PARAMETER);
       
   159 		}
       
   160 	else if ((type == UIT_PROMPT || type == UIT_VERIFY
       
   161 			 || type == UIT_BOOLEAN) && result_buf == NULL)
       
   162 		{
       
   163 		UIerr(UI_F_GENERAL_ALLOCATE_PROMPT,UI_R_NO_RESULT_BUFFER);
       
   164 		}
       
   165 	else if ((ret = (UI_STRING *)OPENSSL_malloc(sizeof(UI_STRING))))
       
   166 		{
       
   167 		ret->out_string=prompt;
       
   168 		ret->flags=prompt_freeable ? OUT_STRING_FREEABLE : 0;
       
   169 		ret->input_flags=input_flags;
       
   170 		ret->type=type;
       
   171 		ret->result_buf=result_buf;
       
   172 		}
       
   173 	return ret;
       
   174 	}
       
   175 
       
   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)
       
   179 	{
       
   180 	int ret = -1;
       
   181 	UI_STRING *s = general_allocate_prompt(ui, prompt, prompt_freeable,
       
   182 		type, input_flags, result_buf);
       
   183 
       
   184 	if (s)
       
   185 		{
       
   186 		if (allocate_string_stack(ui) >= 0)
       
   187 			{
       
   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 */
       
   193 			if (ret <= 0) ret--;
       
   194 			}
       
   195 		else
       
   196 			free_string(s);
       
   197 		}
       
   198 	return ret;
       
   199 	}
       
   200 
       
   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,
       
   205 	char *result_buf)
       
   206 	{
       
   207 	int ret = -1;
       
   208 	UI_STRING *s;
       
   209 	const char *p;
       
   210 
       
   211 	if (ok_chars == NULL)
       
   212 		{
       
   213 		UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,ERR_R_PASSED_NULL_PARAMETER);
       
   214 		}
       
   215 	else if (cancel_chars == NULL)
       
   216 		{
       
   217 		UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,ERR_R_PASSED_NULL_PARAMETER);
       
   218 		}
       
   219 	else
       
   220 		{
       
   221 		for(p = ok_chars; *p; p++)
       
   222 			{
       
   223 			if (strchr(cancel_chars, *p))
       
   224 				{
       
   225 				UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN,
       
   226 					UI_R_COMMON_OK_AND_CANCEL_CHARACTERS);
       
   227 				}
       
   228 			}
       
   229 
       
   230 		s = general_allocate_prompt(ui, prompt, prompt_freeable,
       
   231 			type, input_flags, result_buf);
       
   232 
       
   233 		if (s)
       
   234 			{
       
   235 			if (allocate_string_stack(ui) >= 0)
       
   236 				{
       
   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.
       
   242 				   Let's addapt that */
       
   243 				if (ret <= 0) ret--;
       
   244 				}
       
   245 			else
       
   246 				free_string(s);
       
   247 			}
       
   248 		}
       
   249 	return ret;
       
   250 	}
       
   251 
       
   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)
       
   256 	{
       
   257 	return general_allocate_string(ui, prompt, 0,
       
   258 		UIT_PROMPT, flags, result_buf, minsize, maxsize, NULL);
       
   259 	}
       
   260 
       
   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)
       
   264 	{
       
   265 	char *prompt_copy=NULL;
       
   266 
       
   267 	if (prompt)
       
   268 		{
       
   269 		prompt_copy=BUF_strdup(prompt);
       
   270 		if (prompt_copy == NULL)
       
   271 			{
       
   272 			UIerr(UI_F_UI_DUP_INPUT_STRING,ERR_R_MALLOC_FAILURE);
       
   273 			return 0;
       
   274 			}
       
   275 		}
       
   276 	
       
   277 	return general_allocate_string(ui, prompt_copy, 1,
       
   278 		UIT_PROMPT, flags, result_buf, minsize, maxsize, NULL);
       
   279 	}
       
   280 
       
   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)
       
   283 	{
       
   284 	return general_allocate_string(ui, prompt, 0,
       
   285 		UIT_VERIFY, flags, result_buf, minsize, maxsize, test_buf);
       
   286 	}
       
   287 
       
   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)
       
   290 	{
       
   291 	char *prompt_copy=NULL;
       
   292 
       
   293 	if (prompt)
       
   294 		{
       
   295 		prompt_copy=BUF_strdup(prompt);
       
   296 		if (prompt_copy == NULL)
       
   297 			{
       
   298 			UIerr(UI_F_UI_DUP_VERIFY_STRING,ERR_R_MALLOC_FAILURE);
       
   299 			return -1;
       
   300 			}
       
   301 		}
       
   302 	
       
   303 	return general_allocate_string(ui, prompt_copy, 1,
       
   304 		UIT_VERIFY, flags, result_buf, minsize, maxsize, test_buf);
       
   305 	}
       
   306 
       
   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)
       
   310 	{
       
   311 	return general_allocate_boolean(ui, prompt, action_desc,
       
   312 		ok_chars, cancel_chars, 0, UIT_BOOLEAN, flags, result_buf);
       
   313 	}
       
   314 
       
   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)
       
   318 	{
       
   319 	char *prompt_copy = NULL;
       
   320 	char *action_desc_copy = NULL;
       
   321 	char *ok_chars_copy = NULL;
       
   322 	char *cancel_chars_copy = NULL;
       
   323 
       
   324 	if (prompt)
       
   325 		{
       
   326 		prompt_copy=BUF_strdup(prompt);
       
   327 		if (prompt_copy == NULL)
       
   328 			{
       
   329 			UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE);
       
   330 			goto err;
       
   331 			}
       
   332 		}
       
   333 	
       
   334 	if (action_desc)
       
   335 		{
       
   336 		action_desc_copy=BUF_strdup(action_desc);
       
   337 		if (action_desc_copy == NULL)
       
   338 			{
       
   339 			UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE);
       
   340 			goto err;
       
   341 			}
       
   342 		}
       
   343 	
       
   344 	if (ok_chars)
       
   345 		{
       
   346 		ok_chars_copy=BUF_strdup(ok_chars);
       
   347 		if (ok_chars_copy == NULL)
       
   348 			{
       
   349 			UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE);
       
   350 			goto err;
       
   351 			}
       
   352 		}
       
   353 	
       
   354 	if (cancel_chars)
       
   355 		{
       
   356 		cancel_chars_copy=BUF_strdup(cancel_chars);
       
   357 		if (cancel_chars_copy == NULL)
       
   358 			{
       
   359 			UIerr(UI_F_UI_DUP_INPUT_BOOLEAN,ERR_R_MALLOC_FAILURE);
       
   360 			goto err;
       
   361 			}
       
   362 		}
       
   363 	
       
   364 	return general_allocate_boolean(ui, prompt_copy, action_desc_copy,
       
   365 		ok_chars_copy, cancel_chars_copy, 1, UIT_BOOLEAN, flags,
       
   366 		result_buf);
       
   367  err:
       
   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);
       
   372 	return -1;
       
   373 	}
       
   374 
       
   375 EXPORT_C int UI_add_info_string(UI *ui, const char *text)
       
   376 	{
       
   377 	return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0,
       
   378 		NULL);
       
   379 	}
       
   380 
       
   381 EXPORT_C int UI_dup_info_string(UI *ui, const char *text)
       
   382 	{
       
   383 	char *text_copy=NULL;
       
   384 
       
   385 	if (text)
       
   386 		{
       
   387 		text_copy=BUF_strdup(text);
       
   388 		if (text_copy == NULL)
       
   389 			{
       
   390 			UIerr(UI_F_UI_DUP_INFO_STRING,ERR_R_MALLOC_FAILURE);
       
   391 			return -1;
       
   392 			}
       
   393 		}
       
   394 
       
   395 	return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL,
       
   396 		0, 0, NULL);
       
   397 	}
       
   398 
       
   399 EXPORT_C int UI_add_error_string(UI *ui, const char *text)
       
   400 	{
       
   401 	return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0,
       
   402 		NULL);
       
   403 	}
       
   404 
       
   405 EXPORT_C int UI_dup_error_string(UI *ui, const char *text)
       
   406 	{
       
   407 	char *text_copy=NULL;
       
   408 
       
   409 	if (text)
       
   410 		{
       
   411 		text_copy=BUF_strdup(text);
       
   412 		if (text_copy == NULL)
       
   413 			{
       
   414 			UIerr(UI_F_UI_DUP_ERROR_STRING,ERR_R_MALLOC_FAILURE);
       
   415 			return -1;
       
   416 			}
       
   417 		}
       
   418 	return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL,
       
   419 		0, 0, NULL);
       
   420 	}
       
   421 
       
   422 EXPORT_C char *UI_construct_prompt(UI *ui, const char *object_desc,
       
   423 	const char *object_name)
       
   424 	{
       
   425 	char *prompt = NULL;
       
   426 
       
   427 	if (ui->meth->ui_construct_prompt)
       
   428 		prompt = ui->meth->ui_construct_prompt(ui,
       
   429 			object_desc, object_name);
       
   430 	else
       
   431 		{
       
   432 		char prompt1[] = "Enter ";
       
   433 		char prompt2[] = " for ";
       
   434 		char prompt3[] = ":";
       
   435 		int len = 0;
       
   436 
       
   437 		if (object_desc == NULL)
       
   438 			return NULL;
       
   439 		len = sizeof(prompt1) - 1 + strlen(object_desc);
       
   440 		if (object_name)
       
   441 			len += sizeof(prompt2) - 1 + strlen(object_name);
       
   442 		len += sizeof(prompt3) - 1;
       
   443 
       
   444 		prompt = (char *)OPENSSL_malloc(len + 1);
       
   445 #ifdef SYMBIAN		
       
   446 		if(prompt==NULL)
       
   447 		return NULL;
       
   448 #endif		
       
   449 		BUF_strlcpy(prompt, prompt1, len + 1);
       
   450 		BUF_strlcat(prompt, object_desc, len + 1);
       
   451 		if (object_name)
       
   452 			{
       
   453 			BUF_strlcat(prompt, prompt2, len + 1);
       
   454 			BUF_strlcat(prompt, object_name, len + 1);
       
   455 			}
       
   456 		BUF_strlcat(prompt, prompt3, len + 1);
       
   457 		}
       
   458 	return prompt;
       
   459 	}
       
   460 
       
   461 EXPORT_C void *UI_add_user_data(UI *ui, void *user_data)
       
   462 	{
       
   463 	void *old_data = ui->user_data;
       
   464 	ui->user_data = user_data;
       
   465 	return old_data;
       
   466 	}
       
   467 
       
   468 EXPORT_C void *UI_get0_user_data(UI *ui)
       
   469 	{
       
   470 	return ui->user_data;
       
   471 	}
       
   472 
       
   473 EXPORT_C const char *UI_get0_result(UI *ui, int i)
       
   474 	{
       
   475 	if (i < 0)
       
   476 		{
       
   477 		UIerr(UI_F_UI_GET0_RESULT,UI_R_INDEX_TOO_SMALL);
       
   478 		return NULL;
       
   479 		}
       
   480 	if (i >= sk_UI_STRING_num(ui->strings))
       
   481 		{
       
   482 		UIerr(UI_F_UI_GET0_RESULT,UI_R_INDEX_TOO_LARGE);
       
   483 		return NULL;
       
   484 		}
       
   485 	return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i));
       
   486 	}
       
   487 
       
   488 static int print_error(const char *str, size_t len, UI *ui)
       
   489 	{
       
   490 	UI_STRING uis;
       
   491 
       
   492 	memset(&uis, 0, sizeof(uis));
       
   493 	uis.type = UIT_ERROR;
       
   494 	uis.out_string = str;
       
   495 
       
   496 	if (ui->meth->ui_write_string
       
   497 		&& !ui->meth->ui_write_string(ui, &uis))
       
   498 		return -1;
       
   499 	return 0;
       
   500 	}
       
   501 
       
   502 EXPORT_C int UI_process(UI *ui)
       
   503 	{
       
   504 	int i, ok=0;
       
   505 
       
   506 	if (ui->meth->ui_open_session && !ui->meth->ui_open_session(ui))
       
   507 		return -1;
       
   508 
       
   509 	if (ui->flags & UI_FLAG_PRINT_ERRORS)
       
   510 		ERR_print_errors_cb(
       
   511 			(int (*)(const char *, size_t, void *))print_error,
       
   512 			(void *)ui);
       
   513 
       
   514 	for(i=0; i<sk_UI_STRING_num(ui->strings); i++)
       
   515 		{
       
   516 		if (ui->meth->ui_write_string
       
   517 			&& !ui->meth->ui_write_string(ui,
       
   518 				sk_UI_STRING_value(ui->strings, i)))
       
   519 			{
       
   520 			ok=-1;
       
   521 			goto err;
       
   522 			}
       
   523 		}
       
   524 
       
   525 	if (ui->meth->ui_flush)
       
   526 		switch(ui->meth->ui_flush(ui))
       
   527 			{
       
   528 		case -1: /* Interrupt/Cancel/something... */
       
   529 			ok = -2;
       
   530 			goto err;
       
   531 		case 0: /* Errors */
       
   532 			ok = -1;
       
   533 			goto err;
       
   534 		default: /* Success */
       
   535 			ok = 0;
       
   536 			break;
       
   537 			}
       
   538 
       
   539 	for(i=0; i<sk_UI_STRING_num(ui->strings); i++)
       
   540 		{
       
   541 		if (ui->meth->ui_read_string)
       
   542 			{
       
   543 			switch(ui->meth->ui_read_string(ui,
       
   544 				sk_UI_STRING_value(ui->strings, i)))
       
   545 				{
       
   546 			case -1: /* Interrupt/Cancel/something... */
       
   547 				ok = -2;
       
   548 				goto err;
       
   549 			case 0: /* Errors */
       
   550 				ok = -1;
       
   551 				goto err;
       
   552 			default: /* Success */
       
   553 				ok = 0;
       
   554 				break;
       
   555 				}
       
   556 			}
       
   557 		}
       
   558  err:
       
   559 	if (ui->meth->ui_close_session && !ui->meth->ui_close_session(ui))
       
   560 		return -1;
       
   561 	return ok;
       
   562 	}
       
   563 
       
   564 EXPORT_C int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f)(void))
       
   565 	{
       
   566 	if (ui == NULL)
       
   567 		{
       
   568 		UIerr(UI_F_UI_CTRL,ERR_R_PASSED_NULL_PARAMETER);
       
   569 		return -1;
       
   570 		}
       
   571 	switch(cmd)
       
   572 		{
       
   573 	case UI_CTRL_PRINT_ERRORS:
       
   574 		{
       
   575 		int save_flag = !!(ui->flags & UI_FLAG_PRINT_ERRORS);
       
   576 		if (i)
       
   577 			ui->flags |= UI_FLAG_PRINT_ERRORS;
       
   578 		else
       
   579 			ui->flags &= ~UI_FLAG_PRINT_ERRORS;
       
   580 		return save_flag;
       
   581 		}
       
   582 	case UI_CTRL_IS_REDOABLE:
       
   583 		return !!(ui->flags & UI_FLAG_REDOABLE);
       
   584 	default:
       
   585 		break;
       
   586 		}
       
   587 	UIerr(UI_F_UI_CTRL,UI_R_UNKNOWN_CONTROL_COMMAND);
       
   588 	return -1;
       
   589 	}
       
   590 
       
   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)
       
   593         {
       
   594 	return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_UI, argl, argp,
       
   595 				new_func, dup_func, free_func);
       
   596         }
       
   597 
       
   598 EXPORT_C int UI_set_ex_data(UI *r, int idx, void *arg)
       
   599 	{
       
   600 	return(CRYPTO_set_ex_data(&r->ex_data,idx,arg));
       
   601 	}
       
   602 
       
   603 EXPORT_C void *UI_get_ex_data(UI *r, int idx)
       
   604 	{
       
   605 	return(CRYPTO_get_ex_data(&r->ex_data,idx));
       
   606 	}
       
   607 
       
   608 EXPORT_C void UI_set_default_method(const UI_METHOD *meth)
       
   609 	{
       
   610 	default_UI_meth=meth;
       
   611 	}
       
   612 
       
   613 EXPORT_C const UI_METHOD *UI_get_default_method(void)
       
   614 	{
       
   615 	if (default_UI_meth == NULL)
       
   616 		{
       
   617 		default_UI_meth=UI_OpenSSL();
       
   618 		}
       
   619 	return default_UI_meth;
       
   620 	}
       
   621 
       
   622 EXPORT_C const UI_METHOD *UI_get_method(UI *ui)
       
   623 	{
       
   624 	return ui->meth;
       
   625 	}
       
   626 
       
   627 EXPORT_C const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth)
       
   628 	{
       
   629 	ui->meth=meth;
       
   630 	return ui->meth;
       
   631 	}
       
   632 
       
   633 
       
   634 EXPORT_C UI_METHOD *UI_create_method(char *name)
       
   635 	{
       
   636 	UI_METHOD *ui_method = (UI_METHOD *)OPENSSL_malloc(sizeof(UI_METHOD));
       
   637 
       
   638 	if (ui_method)
       
   639 		{
       
   640 		memset(ui_method, 0, sizeof(*ui_method));
       
   641 		ui_method->name = BUF_strdup(name);
       
   642 		}
       
   643 	return ui_method;
       
   644 	}
       
   645 
       
   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)
       
   650 	{
       
   651 	OPENSSL_free(ui_method->name);
       
   652 	ui_method->name = NULL;
       
   653 	OPENSSL_free(ui_method);
       
   654 	}
       
   655 
       
   656 EXPORT_C int UI_method_set_opener(UI_METHOD *method, int (*opener)(UI *ui))
       
   657 	{
       
   658 	if (method)
       
   659 		{
       
   660 		method->ui_open_session = opener;
       
   661 		return 0;
       
   662 		}
       
   663 	else
       
   664 		return -1;
       
   665 	}
       
   666 
       
   667 EXPORT_C int UI_method_set_writer(UI_METHOD *method, int (*writer)(UI *ui, UI_STRING *uis))
       
   668 	{
       
   669 	if (method)
       
   670 		{
       
   671 		method->ui_write_string = writer;
       
   672 		return 0;
       
   673 		}
       
   674 	else
       
   675 		return -1;
       
   676 	}
       
   677 
       
   678 EXPORT_C int UI_method_set_flusher(UI_METHOD *method, int (*flusher)(UI *ui))
       
   679 	{
       
   680 	if (method)
       
   681 		{
       
   682 		method->ui_flush = flusher;
       
   683 		return 0;
       
   684 		}
       
   685 	else
       
   686 		return -1;
       
   687 	}
       
   688 
       
   689 EXPORT_C int UI_method_set_reader(UI_METHOD *method, int (*reader)(UI *ui, UI_STRING *uis))
       
   690 	{
       
   691 	if (method)
       
   692 		{
       
   693 		method->ui_read_string = reader;
       
   694 		return 0;
       
   695 		}
       
   696 	else
       
   697 		return -1;
       
   698 	}
       
   699 
       
   700 EXPORT_C int UI_method_set_closer(UI_METHOD *method, int (*closer)(UI *ui))
       
   701 	{
       
   702 	if (method)
       
   703 		{
       
   704 		method->ui_close_session = closer;
       
   705 		return 0;
       
   706 		}
       
   707 	else
       
   708 		return -1;
       
   709 	}
       
   710 
       
   711 EXPORT_C int (*UI_method_get_opener(UI_METHOD *method))(UI*)
       
   712 	{
       
   713 	if (method)
       
   714 		return method->ui_open_session;
       
   715 	else
       
   716 		return NULL;
       
   717 	}
       
   718 
       
   719 EXPORT_C int (*UI_method_get_writer(UI_METHOD *method))(UI*,UI_STRING*)
       
   720 	{
       
   721 	if (method)
       
   722 		return method->ui_write_string;
       
   723 	else
       
   724 		return NULL;
       
   725 	}
       
   726 
       
   727 EXPORT_C int (*UI_method_get_flusher(UI_METHOD *method))(UI*)
       
   728 	{
       
   729 	if (method)
       
   730 		return method->ui_flush;
       
   731 	else
       
   732 		return NULL;
       
   733 	}
       
   734 
       
   735 EXPORT_C int (*UI_method_get_reader(UI_METHOD *method))(UI*,UI_STRING*)
       
   736 	{
       
   737 	if (method)
       
   738 		return method->ui_read_string;
       
   739 	else
       
   740 		return NULL;
       
   741 	}
       
   742 
       
   743 EXPORT_C int (*UI_method_get_closer(UI_METHOD *method))(UI*)
       
   744 	{
       
   745 	if (method)
       
   746 		return method->ui_close_session;
       
   747 	else
       
   748 		return NULL;
       
   749 	}
       
   750 
       
   751 EXPORT_C enum UI_string_types UI_get_string_type(UI_STRING *uis)
       
   752 	{
       
   753 	if (!uis)
       
   754 		return UIT_NONE;
       
   755 	return uis->type;
       
   756 	}
       
   757 
       
   758 EXPORT_C int UI_get_input_flags(UI_STRING *uis)
       
   759 	{
       
   760 	if (!uis)
       
   761 		return 0;
       
   762 	return uis->input_flags;
       
   763 	}
       
   764 
       
   765 EXPORT_C const char *UI_get0_output_string(UI_STRING *uis)
       
   766 	{
       
   767 	if (!uis)
       
   768 		return NULL;
       
   769 	return uis->out_string;
       
   770 	}
       
   771 
       
   772 EXPORT_C const char *UI_get0_action_string(UI_STRING *uis)
       
   773 	{
       
   774 	if (!uis)
       
   775 		return NULL;
       
   776 	switch(uis->type)
       
   777 		{
       
   778 	case UIT_PROMPT:
       
   779 	case UIT_BOOLEAN:
       
   780 		return uis->_.boolean_data.action_desc;
       
   781 	default:
       
   782 		return NULL;
       
   783 		}
       
   784 	}
       
   785 
       
   786 EXPORT_C const char *UI_get0_result_string(UI_STRING *uis)
       
   787 	{
       
   788 	if (!uis)
       
   789 		return NULL;
       
   790 	switch(uis->type)
       
   791 		{
       
   792 	case UIT_PROMPT:
       
   793 	case UIT_VERIFY:
       
   794 		return uis->result_buf;
       
   795 	default:
       
   796 		return NULL;
       
   797 		}
       
   798 	}
       
   799 
       
   800 EXPORT_C const char *UI_get0_test_string(UI_STRING *uis)
       
   801 	{
       
   802 	if (!uis)
       
   803 		return NULL;
       
   804 	switch(uis->type)
       
   805 		{
       
   806 	case UIT_VERIFY:
       
   807 		return uis->_.string_data.test_buf;
       
   808 	default:
       
   809 		return NULL;
       
   810 		}
       
   811 	}
       
   812 
       
   813 EXPORT_C int UI_get_result_minsize(UI_STRING *uis)
       
   814 	{
       
   815 	if (!uis)
       
   816 		return -1;
       
   817 	switch(uis->type)
       
   818 		{
       
   819 	case UIT_PROMPT:
       
   820 	case UIT_VERIFY:
       
   821 		return uis->_.string_data.result_minsize;
       
   822 	default:
       
   823 		return -1;
       
   824 		}
       
   825 	}
       
   826 
       
   827 EXPORT_C int UI_get_result_maxsize(UI_STRING *uis)
       
   828 	{
       
   829 	if (!uis)
       
   830 		return -1;
       
   831 	switch(uis->type)
       
   832 		{
       
   833 	case UIT_PROMPT:
       
   834 	case UIT_VERIFY:
       
   835 		return uis->_.string_data.result_maxsize;
       
   836 	default:
       
   837 		return -1;
       
   838 		}
       
   839 	}
       
   840 
       
   841 EXPORT_C int UI_set_result(UI *ui, UI_STRING *uis, const char *result)
       
   842 	{
       
   843 	int l = strlen(result);
       
   844 
       
   845 	ui->flags &= ~UI_FLAG_REDOABLE;
       
   846 
       
   847 	if (!uis)
       
   848 		return -1;
       
   849 	switch (uis->type)
       
   850 		{
       
   851 	case UIT_PROMPT:
       
   852 	case UIT_VERIFY:
       
   853 		{
       
   854 		char number1[DECIMAL_SIZE(uis->_.string_data.result_minsize)+1];
       
   855 		char number2[DECIMAL_SIZE(uis->_.string_data.result_maxsize)+1];
       
   856 
       
   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);
       
   861 
       
   862 		if (l < uis->_.string_data.result_minsize)
       
   863 			{
       
   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");
       
   868 			return -1;
       
   869 			}
       
   870 		if (l > uis->_.string_data.result_maxsize)
       
   871 			{
       
   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");
       
   876 			return -1;
       
   877 			}
       
   878 		}
       
   879 
       
   880 		if (!uis->result_buf)
       
   881 			{
       
   882 			UIerr(UI_F_UI_SET_RESULT,UI_R_NO_RESULT_BUFFER);
       
   883 			return -1;
       
   884 			}
       
   885 
       
   886 		BUF_strlcpy(uis->result_buf, result,
       
   887 			    uis->_.string_data.result_maxsize + 1);
       
   888 		break;
       
   889 	case UIT_BOOLEAN:
       
   890 		{
       
   891 		const char *p;
       
   892 
       
   893 		if (!uis->result_buf)
       
   894 			{
       
   895 			UIerr(UI_F_UI_SET_RESULT,UI_R_NO_RESULT_BUFFER);
       
   896 			return -1;
       
   897 			}
       
   898 
       
   899 		uis->result_buf[0] = '\0';
       
   900 		for(p = result; *p; p++)
       
   901 			{
       
   902 			if (strchr(uis->_.boolean_data.ok_chars, *p))
       
   903 				{
       
   904 				uis->result_buf[0] =
       
   905 					uis->_.boolean_data.ok_chars[0];
       
   906 				break;
       
   907 				}
       
   908 			if (strchr(uis->_.boolean_data.cancel_chars, *p))
       
   909 				{
       
   910 				uis->result_buf[0] =
       
   911 					uis->_.boolean_data.cancel_chars[0];
       
   912 				break;
       
   913 				}
       
   914 			}
       
   915 	default:
       
   916 		break;
       
   917 		}
       
   918 		}
       
   919 	return 0;
       
   920 	}