]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
aa6bb135 | 2 | * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. |
a63d5eaa | 3 | * |
aa6bb135 RS |
4 | * Licensed under the OpenSSL license (the "License"). You may not use |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
a63d5eaa RL |
8 | */ |
9 | ||
10 | #include <string.h> | |
b39fc560 | 11 | #include "internal/cryptlib.h" |
eb929eef RL |
12 | #include <openssl/e_os2.h> |
13 | #include <openssl/buffer.h> | |
a63d5eaa RL |
14 | #include <openssl/ui.h> |
15 | #include <openssl/err.h> | |
16 | #include "ui_locl.h" | |
17 | ||
0f113f3e | 18 | static const UI_METHOD *default_UI_meth = NULL; |
a63d5eaa RL |
19 | |
20 | UI *UI_new(void) | |
0f113f3e MC |
21 | { |
22 | return (UI_new_method(NULL)); | |
23 | } | |
a63d5eaa RL |
24 | |
25 | UI *UI_new_method(const UI_METHOD *method) | |
0f113f3e | 26 | { |
64b25758 | 27 | UI *ret = OPENSSL_zalloc(sizeof(*ret)); |
0f113f3e | 28 | |
0f113f3e MC |
29 | if (ret == NULL) { |
30 | UIerr(UI_F_UI_NEW_METHOD, ERR_R_MALLOC_FAILURE); | |
31 | return NULL; | |
32 | } | |
41cfbccc AG |
33 | |
34 | ret->lock = CRYPTO_THREAD_lock_new(); | |
35 | if (ret->lock == NULL) { | |
36 | UIerr(UI_F_UI_NEW_METHOD, ERR_R_MALLOC_FAILURE); | |
37 | OPENSSL_free(ret); | |
38 | return NULL; | |
39 | } | |
40 | ||
0f113f3e MC |
41 | if (method == NULL) |
42 | ret->meth = UI_get_default_method(); | |
43 | else | |
44 | ret->meth = method; | |
45 | ||
25a807bc F |
46 | if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_UI, ret, &ret->ex_data)) { |
47 | OPENSSL_free(ret); | |
48 | return NULL; | |
49 | } | |
0f113f3e MC |
50 | return ret; |
51 | } | |
a63d5eaa | 52 | |
d6f188be | 53 | static void free_string(UI_STRING *uis) |
0f113f3e MC |
54 | { |
55 | if (uis->flags & OUT_STRING_FREEABLE) { | |
56 | OPENSSL_free((char *)uis->out_string); | |
57 | switch (uis->type) { | |
58 | case UIT_BOOLEAN: | |
59 | OPENSSL_free((char *)uis->_.boolean_data.action_desc); | |
60 | OPENSSL_free((char *)uis->_.boolean_data.ok_chars); | |
61 | OPENSSL_free((char *)uis->_.boolean_data.cancel_chars); | |
62 | break; | |
63 | default: | |
64 | break; | |
65 | } | |
66 | } | |
67 | OPENSSL_free(uis); | |
68 | } | |
a63d5eaa RL |
69 | |
70 | void UI_free(UI *ui) | |
0f113f3e MC |
71 | { |
72 | if (ui == NULL) | |
73 | return; | |
74 | sk_UI_STRING_pop_free(ui->strings, free_string); | |
75 | CRYPTO_free_ex_data(CRYPTO_EX_INDEX_UI, ui, &ui->ex_data); | |
41cfbccc | 76 | CRYPTO_THREAD_lock_free(ui->lock); |
0f113f3e MC |
77 | OPENSSL_free(ui); |
78 | } | |
a63d5eaa RL |
79 | |
80 | static int allocate_string_stack(UI *ui) | |
0f113f3e MC |
81 | { |
82 | if (ui->strings == NULL) { | |
83 | ui->strings = sk_UI_STRING_new_null(); | |
84 | if (ui->strings == NULL) { | |
85 | return -1; | |
86 | } | |
87 | } | |
88 | return 0; | |
89 | } | |
a63d5eaa | 90 | |
2d2ed9df | 91 | static UI_STRING *general_allocate_prompt(UI *ui, const char *prompt, |
0f113f3e MC |
92 | int prompt_freeable, |
93 | enum UI_string_types type, | |
94 | int input_flags, char *result_buf) | |
95 | { | |
96 | UI_STRING *ret = NULL; | |
97 | ||
98 | if (prompt == NULL) { | |
99 | UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, ERR_R_PASSED_NULL_PARAMETER); | |
100 | } else if ((type == UIT_PROMPT || type == UIT_VERIFY | |
101 | || type == UIT_BOOLEAN) && result_buf == NULL) { | |
102 | UIerr(UI_F_GENERAL_ALLOCATE_PROMPT, UI_R_NO_RESULT_BUFFER); | |
90945fa3 | 103 | } else if ((ret = OPENSSL_malloc(sizeof(*ret))) != NULL) { |
0f113f3e MC |
104 | ret->out_string = prompt; |
105 | ret->flags = prompt_freeable ? OUT_STRING_FREEABLE : 0; | |
106 | ret->input_flags = input_flags; | |
107 | ret->type = type; | |
108 | ret->result_buf = result_buf; | |
109 | } | |
110 | return ret; | |
111 | } | |
2d2ed9df | 112 | |
a63d5eaa | 113 | static int general_allocate_string(UI *ui, const char *prompt, |
0f113f3e MC |
114 | int prompt_freeable, |
115 | enum UI_string_types type, int input_flags, | |
116 | char *result_buf, int minsize, int maxsize, | |
117 | const char *test_buf) | |
118 | { | |
119 | int ret = -1; | |
120 | UI_STRING *s = general_allocate_prompt(ui, prompt, prompt_freeable, | |
121 | type, input_flags, result_buf); | |
122 | ||
123 | if (s) { | |
124 | if (allocate_string_stack(ui) >= 0) { | |
125 | s->_.string_data.result_minsize = minsize; | |
126 | s->_.string_data.result_maxsize = maxsize; | |
127 | s->_.string_data.test_buf = test_buf; | |
128 | ret = sk_UI_STRING_push(ui->strings, s); | |
0d4fb843 | 129 | /* sk_push() returns 0 on error. Let's adapt that */ |
0f113f3e MC |
130 | if (ret <= 0) |
131 | ret--; | |
132 | } else | |
133 | free_string(s); | |
134 | } | |
135 | return ret; | |
136 | } | |
2d2ed9df RL |
137 | |
138 | static int general_allocate_boolean(UI *ui, | |
0f113f3e MC |
139 | const char *prompt, |
140 | const char *action_desc, | |
141 | const char *ok_chars, | |
142 | const char *cancel_chars, | |
143 | int prompt_freeable, | |
144 | enum UI_string_types type, | |
145 | int input_flags, char *result_buf) | |
146 | { | |
147 | int ret = -1; | |
148 | UI_STRING *s; | |
149 | const char *p; | |
150 | ||
151 | if (ok_chars == NULL) { | |
152 | UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, ERR_R_PASSED_NULL_PARAMETER); | |
153 | } else if (cancel_chars == NULL) { | |
154 | UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, ERR_R_PASSED_NULL_PARAMETER); | |
155 | } else { | |
156 | for (p = ok_chars; *p; p++) { | |
157 | if (strchr(cancel_chars, *p)) { | |
158 | UIerr(UI_F_GENERAL_ALLOCATE_BOOLEAN, | |
159 | UI_R_COMMON_OK_AND_CANCEL_CHARACTERS); | |
160 | } | |
161 | } | |
162 | ||
163 | s = general_allocate_prompt(ui, prompt, prompt_freeable, | |
164 | type, input_flags, result_buf); | |
165 | ||
166 | if (s) { | |
167 | if (allocate_string_stack(ui) >= 0) { | |
168 | s->_.boolean_data.action_desc = action_desc; | |
169 | s->_.boolean_data.ok_chars = ok_chars; | |
170 | s->_.boolean_data.cancel_chars = cancel_chars; | |
171 | ret = sk_UI_STRING_push(ui->strings, s); | |
172 | /* | |
0d4fb843 | 173 | * sk_push() returns 0 on error. Let's adapt that |
0f113f3e MC |
174 | */ |
175 | if (ret <= 0) | |
176 | ret--; | |
177 | } else | |
178 | free_string(s); | |
179 | } | |
180 | } | |
181 | return ret; | |
182 | } | |
183 | ||
184 | /* | |
185 | * Returns the index to the place in the stack or -1 for error. Uses a | |
186 | * direct reference to the prompt. | |
187 | */ | |
9ad0f681 | 188 | int UI_add_input_string(UI *ui, const char *prompt, int flags, |
0f113f3e MC |
189 | char *result_buf, int minsize, int maxsize) |
190 | { | |
191 | return general_allocate_string(ui, prompt, 0, | |
192 | UIT_PROMPT, flags, result_buf, minsize, | |
193 | maxsize, NULL); | |
194 | } | |
a63d5eaa RL |
195 | |
196 | /* Same as UI_add_input_string(), excepts it takes a copy of the prompt */ | |
9ad0f681 | 197 | int UI_dup_input_string(UI *ui, const char *prompt, int flags, |
0f113f3e MC |
198 | char *result_buf, int minsize, int maxsize) |
199 | { | |
200 | char *prompt_copy = NULL; | |
201 | ||
202 | if (prompt) { | |
7644a9ae | 203 | prompt_copy = OPENSSL_strdup(prompt); |
0f113f3e MC |
204 | if (prompt_copy == NULL) { |
205 | UIerr(UI_F_UI_DUP_INPUT_STRING, ERR_R_MALLOC_FAILURE); | |
206 | return 0; | |
207 | } | |
208 | } | |
209 | ||
210 | return general_allocate_string(ui, prompt_copy, 1, | |
211 | UIT_PROMPT, flags, result_buf, minsize, | |
212 | maxsize, NULL); | |
213 | } | |
a63d5eaa | 214 | |
9ad0f681 | 215 | int UI_add_verify_string(UI *ui, const char *prompt, int flags, |
0f113f3e MC |
216 | char *result_buf, int minsize, int maxsize, |
217 | const char *test_buf) | |
218 | { | |
219 | return general_allocate_string(ui, prompt, 0, | |
220 | UIT_VERIFY, flags, result_buf, minsize, | |
221 | maxsize, test_buf); | |
222 | } | |
a63d5eaa | 223 | |
9ad0f681 | 224 | int UI_dup_verify_string(UI *ui, const char *prompt, int flags, |
0f113f3e MC |
225 | char *result_buf, int minsize, int maxsize, |
226 | const char *test_buf) | |
227 | { | |
228 | char *prompt_copy = NULL; | |
229 | ||
230 | if (prompt) { | |
7644a9ae | 231 | prompt_copy = OPENSSL_strdup(prompt); |
0f113f3e MC |
232 | if (prompt_copy == NULL) { |
233 | UIerr(UI_F_UI_DUP_VERIFY_STRING, ERR_R_MALLOC_FAILURE); | |
234 | return -1; | |
235 | } | |
236 | } | |
237 | ||
238 | return general_allocate_string(ui, prompt_copy, 1, | |
239 | UIT_VERIFY, flags, result_buf, minsize, | |
240 | maxsize, test_buf); | |
241 | } | |
a63d5eaa | 242 | |
2d2ed9df | 243 | int UI_add_input_boolean(UI *ui, const char *prompt, const char *action_desc, |
0f113f3e MC |
244 | const char *ok_chars, const char *cancel_chars, |
245 | int flags, char *result_buf) | |
246 | { | |
247 | return general_allocate_boolean(ui, prompt, action_desc, | |
248 | ok_chars, cancel_chars, 0, UIT_BOOLEAN, | |
249 | flags, result_buf); | |
250 | } | |
2d2ed9df RL |
251 | |
252 | int UI_dup_input_boolean(UI *ui, const char *prompt, const char *action_desc, | |
0f113f3e MC |
253 | const char *ok_chars, const char *cancel_chars, |
254 | int flags, char *result_buf) | |
255 | { | |
256 | char *prompt_copy = NULL; | |
257 | char *action_desc_copy = NULL; | |
258 | char *ok_chars_copy = NULL; | |
259 | char *cancel_chars_copy = NULL; | |
260 | ||
261 | if (prompt) { | |
7644a9ae | 262 | prompt_copy = OPENSSL_strdup(prompt); |
0f113f3e MC |
263 | if (prompt_copy == NULL) { |
264 | UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); | |
265 | goto err; | |
266 | } | |
267 | } | |
268 | ||
269 | if (action_desc) { | |
7644a9ae | 270 | action_desc_copy = OPENSSL_strdup(action_desc); |
0f113f3e MC |
271 | if (action_desc_copy == NULL) { |
272 | UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); | |
273 | goto err; | |
274 | } | |
275 | } | |
276 | ||
277 | if (ok_chars) { | |
7644a9ae | 278 | ok_chars_copy = OPENSSL_strdup(ok_chars); |
0f113f3e MC |
279 | if (ok_chars_copy == NULL) { |
280 | UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); | |
281 | goto err; | |
282 | } | |
283 | } | |
284 | ||
285 | if (cancel_chars) { | |
7644a9ae | 286 | cancel_chars_copy = OPENSSL_strdup(cancel_chars); |
0f113f3e MC |
287 | if (cancel_chars_copy == NULL) { |
288 | UIerr(UI_F_UI_DUP_INPUT_BOOLEAN, ERR_R_MALLOC_FAILURE); | |
289 | goto err; | |
290 | } | |
291 | } | |
292 | ||
293 | return general_allocate_boolean(ui, prompt_copy, action_desc_copy, | |
294 | ok_chars_copy, cancel_chars_copy, 1, | |
295 | UIT_BOOLEAN, flags, result_buf); | |
2d2ed9df | 296 | err: |
b548a1f1 RS |
297 | OPENSSL_free(prompt_copy); |
298 | OPENSSL_free(action_desc_copy); | |
299 | OPENSSL_free(ok_chars_copy); | |
300 | OPENSSL_free(cancel_chars_copy); | |
0f113f3e MC |
301 | return -1; |
302 | } | |
2d2ed9df | 303 | |
a63d5eaa | 304 | int UI_add_info_string(UI *ui, const char *text) |
0f113f3e MC |
305 | { |
306 | return general_allocate_string(ui, text, 0, UIT_INFO, 0, NULL, 0, 0, | |
307 | NULL); | |
308 | } | |
a63d5eaa RL |
309 | |
310 | int UI_dup_info_string(UI *ui, const char *text) | |
0f113f3e MC |
311 | { |
312 | char *text_copy = NULL; | |
313 | ||
314 | if (text) { | |
7644a9ae | 315 | text_copy = OPENSSL_strdup(text); |
0f113f3e MC |
316 | if (text_copy == NULL) { |
317 | UIerr(UI_F_UI_DUP_INFO_STRING, ERR_R_MALLOC_FAILURE); | |
318 | return -1; | |
319 | } | |
320 | } | |
321 | ||
322 | return general_allocate_string(ui, text_copy, 1, UIT_INFO, 0, NULL, | |
323 | 0, 0, NULL); | |
324 | } | |
a63d5eaa RL |
325 | |
326 | int UI_add_error_string(UI *ui, const char *text) | |
0f113f3e MC |
327 | { |
328 | return general_allocate_string(ui, text, 0, UIT_ERROR, 0, NULL, 0, 0, | |
329 | NULL); | |
330 | } | |
a63d5eaa RL |
331 | |
332 | int UI_dup_error_string(UI *ui, const char *text) | |
0f113f3e MC |
333 | { |
334 | char *text_copy = NULL; | |
335 | ||
336 | if (text) { | |
7644a9ae | 337 | text_copy = OPENSSL_strdup(text); |
0f113f3e MC |
338 | if (text_copy == NULL) { |
339 | UIerr(UI_F_UI_DUP_ERROR_STRING, ERR_R_MALLOC_FAILURE); | |
340 | return -1; | |
341 | } | |
342 | } | |
343 | return general_allocate_string(ui, text_copy, 1, UIT_ERROR, 0, NULL, | |
344 | 0, 0, NULL); | |
345 | } | |
9ad0f681 RL |
346 | |
347 | char *UI_construct_prompt(UI *ui, const char *object_desc, | |
0f113f3e MC |
348 | const char *object_name) |
349 | { | |
350 | char *prompt = NULL; | |
351 | ||
352 | if (ui->meth->ui_construct_prompt) | |
353 | prompt = ui->meth->ui_construct_prompt(ui, object_desc, object_name); | |
354 | else { | |
355 | char prompt1[] = "Enter "; | |
356 | char prompt2[] = " for "; | |
357 | char prompt3[] = ":"; | |
358 | int len = 0; | |
359 | ||
360 | if (object_desc == NULL) | |
361 | return NULL; | |
362 | len = sizeof(prompt1) - 1 + strlen(object_desc); | |
363 | if (object_name) | |
364 | len += sizeof(prompt2) - 1 + strlen(object_name); | |
365 | len += sizeof(prompt3) - 1; | |
366 | ||
b196e7d9 | 367 | prompt = OPENSSL_malloc(len + 1); |
0f113f3e MC |
368 | if (prompt == NULL) |
369 | return NULL; | |
7644a9ae RS |
370 | OPENSSL_strlcpy(prompt, prompt1, len + 1); |
371 | OPENSSL_strlcat(prompt, object_desc, len + 1); | |
0f113f3e | 372 | if (object_name) { |
7644a9ae RS |
373 | OPENSSL_strlcat(prompt, prompt2, len + 1); |
374 | OPENSSL_strlcat(prompt, object_name, len + 1); | |
0f113f3e | 375 | } |
7644a9ae | 376 | OPENSSL_strlcat(prompt, prompt3, len + 1); |
0f113f3e MC |
377 | } |
378 | return prompt; | |
379 | } | |
a63d5eaa | 380 | |
1e7e62f8 | 381 | void *UI_add_user_data(UI *ui, void *user_data) |
0f113f3e MC |
382 | { |
383 | void *old_data = ui->user_data; | |
384 | ui->user_data = user_data; | |
385 | return old_data; | |
386 | } | |
1e7e62f8 RL |
387 | |
388 | void *UI_get0_user_data(UI *ui) | |
0f113f3e MC |
389 | { |
390 | return ui->user_data; | |
391 | } | |
1e7e62f8 | 392 | |
a63d5eaa | 393 | const char *UI_get0_result(UI *ui, int i) |
0f113f3e MC |
394 | { |
395 | if (i < 0) { | |
396 | UIerr(UI_F_UI_GET0_RESULT, UI_R_INDEX_TOO_SMALL); | |
397 | return NULL; | |
398 | } | |
399 | if (i >= sk_UI_STRING_num(ui->strings)) { | |
400 | UIerr(UI_F_UI_GET0_RESULT, UI_R_INDEX_TOO_LARGE); | |
401 | return NULL; | |
402 | } | |
403 | return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i)); | |
404 | } | |
a63d5eaa | 405 | |
2d2ed9df | 406 | static int print_error(const char *str, size_t len, UI *ui) |
0f113f3e MC |
407 | { |
408 | UI_STRING uis; | |
2d2ed9df | 409 | |
0f113f3e MC |
410 | memset(&uis, 0, sizeof(uis)); |
411 | uis.type = UIT_ERROR; | |
412 | uis.out_string = str; | |
2d2ed9df | 413 | |
0f113f3e MC |
414 | if (ui->meth->ui_write_string && !ui->meth->ui_write_string(ui, &uis)) |
415 | return -1; | |
416 | return 0; | |
417 | } | |
2d2ed9df | 418 | |
a63d5eaa | 419 | int UI_process(UI *ui) |
0f113f3e MC |
420 | { |
421 | int i, ok = 0; | |
2d2ed9df | 422 | |
0f113f3e MC |
423 | if (ui->meth->ui_open_session && !ui->meth->ui_open_session(ui)) |
424 | return -1; | |
425 | ||
426 | if (ui->flags & UI_FLAG_PRINT_ERRORS) | |
427 | ERR_print_errors_cb((int (*)(const char *, size_t, void *)) | |
428 | print_error, (void *)ui); | |
429 | ||
430 | for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) { | |
431 | if (ui->meth->ui_write_string | |
432 | && !ui->meth->ui_write_string(ui, | |
433 | sk_UI_STRING_value(ui->strings, i))) | |
434 | { | |
435 | ok = -1; | |
436 | goto err; | |
437 | } | |
438 | } | |
439 | ||
440 | if (ui->meth->ui_flush) | |
441 | switch (ui->meth->ui_flush(ui)) { | |
442 | case -1: /* Interrupt/Cancel/something... */ | |
443 | ok = -2; | |
444 | goto err; | |
445 | case 0: /* Errors */ | |
446 | ok = -1; | |
447 | goto err; | |
448 | default: /* Success */ | |
449 | ok = 0; | |
450 | break; | |
451 | } | |
452 | ||
453 | for (i = 0; i < sk_UI_STRING_num(ui->strings); i++) { | |
454 | if (ui->meth->ui_read_string) { | |
455 | switch (ui->meth->ui_read_string(ui, | |
456 | sk_UI_STRING_value(ui->strings, | |
457 | i))) { | |
458 | case -1: /* Interrupt/Cancel/something... */ | |
459 | ok = -2; | |
460 | goto err; | |
461 | case 0: /* Errors */ | |
462 | ok = -1; | |
463 | goto err; | |
464 | default: /* Success */ | |
465 | ok = 0; | |
466 | break; | |
467 | } | |
468 | } | |
469 | } | |
470 | err: | |
471 | if (ui->meth->ui_close_session && !ui->meth->ui_close_session(ui)) | |
472 | return -1; | |
473 | return ok; | |
474 | } | |
475 | ||
476 | int UI_ctrl(UI *ui, int cmd, long i, void *p, void (*f) (void)) | |
477 | { | |
478 | if (ui == NULL) { | |
479 | UIerr(UI_F_UI_CTRL, ERR_R_PASSED_NULL_PARAMETER); | |
480 | return -1; | |
481 | } | |
482 | switch (cmd) { | |
483 | case UI_CTRL_PRINT_ERRORS: | |
a63d5eaa | 484 | { |
0f113f3e MC |
485 | int save_flag = ! !(ui->flags & UI_FLAG_PRINT_ERRORS); |
486 | if (i) | |
487 | ui->flags |= UI_FLAG_PRINT_ERRORS; | |
488 | else | |
489 | ui->flags &= ~UI_FLAG_PRINT_ERRORS; | |
490 | return save_flag; | |
a63d5eaa | 491 | } |
0f113f3e MC |
492 | case UI_CTRL_IS_REDOABLE: |
493 | return ! !(ui->flags & UI_FLAG_REDOABLE); | |
494 | default: | |
495 | break; | |
496 | } | |
497 | UIerr(UI_F_UI_CTRL, UI_R_UNKNOWN_CONTROL_COMMAND); | |
498 | return -1; | |
499 | } | |
500 | ||
a63d5eaa | 501 | int UI_set_ex_data(UI *r, int idx, void *arg) |
0f113f3e MC |
502 | { |
503 | return (CRYPTO_set_ex_data(&r->ex_data, idx, arg)); | |
504 | } | |
a63d5eaa RL |
505 | |
506 | void *UI_get_ex_data(UI *r, int idx) | |
0f113f3e MC |
507 | { |
508 | return (CRYPTO_get_ex_data(&r->ex_data, idx)); | |
509 | } | |
a63d5eaa RL |
510 | |
511 | void UI_set_default_method(const UI_METHOD *meth) | |
0f113f3e MC |
512 | { |
513 | default_UI_meth = meth; | |
514 | } | |
a63d5eaa RL |
515 | |
516 | const UI_METHOD *UI_get_default_method(void) | |
0f113f3e MC |
517 | { |
518 | if (default_UI_meth == NULL) { | |
519 | default_UI_meth = UI_OpenSSL(); | |
520 | } | |
521 | return default_UI_meth; | |
522 | } | |
a63d5eaa RL |
523 | |
524 | const UI_METHOD *UI_get_method(UI *ui) | |
0f113f3e MC |
525 | { |
526 | return ui->meth; | |
527 | } | |
a63d5eaa RL |
528 | |
529 | const UI_METHOD *UI_set_method(UI *ui, const UI_METHOD *meth) | |
0f113f3e MC |
530 | { |
531 | ui->meth = meth; | |
532 | return ui->meth; | |
533 | } | |
a63d5eaa | 534 | |
9ad0f681 | 535 | UI_METHOD *UI_create_method(char *name) |
0f113f3e | 536 | { |
b51bce94 | 537 | UI_METHOD *ui_method = OPENSSL_zalloc(sizeof(*ui_method)); |
0f113f3e | 538 | |
90945fa3 | 539 | if (ui_method != NULL) |
7644a9ae | 540 | ui_method->name = OPENSSL_strdup(name); |
0f113f3e MC |
541 | return ui_method; |
542 | } | |
543 | ||
544 | /* | |
545 | * BIG FSCKING WARNING!!!! If you use this on a statically allocated method | |
546 | * (that is, it hasn't been allocated using UI_create_method(), you deserve | |
547 | * anything Murphy can throw at you and more! You have been warned. | |
548 | */ | |
eb929eef | 549 | void UI_destroy_method(UI_METHOD *ui_method) |
0f113f3e MC |
550 | { |
551 | OPENSSL_free(ui_method->name); | |
552 | ui_method->name = NULL; | |
553 | OPENSSL_free(ui_method); | |
554 | } | |
555 | ||
556 | int UI_method_set_opener(UI_METHOD *method, int (*opener) (UI *ui)) | |
557 | { | |
558 | if (method) { | |
559 | method->ui_open_session = opener; | |
560 | return 0; | |
561 | } else | |
562 | return -1; | |
563 | } | |
564 | ||
565 | int UI_method_set_writer(UI_METHOD *method, | |
566 | int (*writer) (UI *ui, UI_STRING *uis)) | |
567 | { | |
568 | if (method) { | |
569 | method->ui_write_string = writer; | |
570 | return 0; | |
571 | } else | |
572 | return -1; | |
573 | } | |
574 | ||
575 | int UI_method_set_flusher(UI_METHOD *method, int (*flusher) (UI *ui)) | |
576 | { | |
577 | if (method) { | |
578 | method->ui_flush = flusher; | |
579 | return 0; | |
580 | } else | |
581 | return -1; | |
582 | } | |
583 | ||
584 | int UI_method_set_reader(UI_METHOD *method, | |
585 | int (*reader) (UI *ui, UI_STRING *uis)) | |
586 | { | |
587 | if (method) { | |
588 | method->ui_read_string = reader; | |
589 | return 0; | |
590 | } else | |
591 | return -1; | |
592 | } | |
593 | ||
594 | int UI_method_set_closer(UI_METHOD *method, int (*closer) (UI *ui)) | |
595 | { | |
596 | if (method) { | |
597 | method->ui_close_session = closer; | |
598 | return 0; | |
599 | } else | |
600 | return -1; | |
601 | } | |
602 | ||
603 | int UI_method_set_prompt_constructor(UI_METHOD *method, | |
604 | char *(*prompt_constructor) (UI *ui, | |
605 | const char | |
606 | *object_desc, | |
607 | const char | |
608 | *object_name)) | |
609 | { | |
610 | if (method) { | |
611 | method->ui_construct_prompt = prompt_constructor; | |
612 | return 0; | |
613 | } else | |
614 | return -1; | |
615 | } | |
616 | ||
617 | int (*UI_method_get_opener(UI_METHOD *method)) (UI *) { | |
618 | if (method) | |
619 | return method->ui_open_session; | |
620 | else | |
621 | return NULL; | |
622 | } | |
623 | ||
624 | int (*UI_method_get_writer(UI_METHOD *method)) (UI *, UI_STRING *) { | |
625 | if (method) | |
626 | return method->ui_write_string; | |
627 | else | |
628 | return NULL; | |
629 | } | |
630 | ||
631 | int (*UI_method_get_flusher(UI_METHOD *method)) (UI *) { | |
632 | if (method) | |
633 | return method->ui_flush; | |
634 | else | |
635 | return NULL; | |
636 | } | |
637 | ||
638 | int (*UI_method_get_reader(UI_METHOD *method)) (UI *, UI_STRING *) { | |
639 | if (method) | |
640 | return method->ui_read_string; | |
641 | else | |
642 | return NULL; | |
643 | } | |
644 | ||
645 | int (*UI_method_get_closer(UI_METHOD *method)) (UI *) { | |
646 | if (method) | |
647 | return method->ui_close_session; | |
648 | else | |
649 | return NULL; | |
650 | } | |
651 | ||
652 | char *(*UI_method_get_prompt_constructor(UI_METHOD *method)) (UI *, | |
653 | const char *, | |
654 | const char *) { | |
655 | if (method) | |
656 | return method->ui_construct_prompt; | |
657 | else | |
658 | return NULL; | |
659 | } | |
a63d5eaa RL |
660 | |
661 | enum UI_string_types UI_get_string_type(UI_STRING *uis) | |
0f113f3e MC |
662 | { |
663 | if (!uis) | |
664 | return UIT_NONE; | |
665 | return uis->type; | |
666 | } | |
a63d5eaa | 667 | |
9ad0f681 | 668 | int UI_get_input_flags(UI_STRING *uis) |
0f113f3e MC |
669 | { |
670 | if (!uis) | |
671 | return 0; | |
672 | return uis->input_flags; | |
673 | } | |
9ad0f681 | 674 | |
a63d5eaa | 675 | const char *UI_get0_output_string(UI_STRING *uis) |
0f113f3e MC |
676 | { |
677 | if (!uis) | |
678 | return NULL; | |
679 | return uis->out_string; | |
680 | } | |
a63d5eaa | 681 | |
2d2ed9df | 682 | const char *UI_get0_action_string(UI_STRING *uis) |
0f113f3e MC |
683 | { |
684 | if (!uis) | |
685 | return NULL; | |
686 | switch (uis->type) { | |
687 | case UIT_PROMPT: | |
688 | case UIT_BOOLEAN: | |
689 | return uis->_.boolean_data.action_desc; | |
690 | default: | |
691 | return NULL; | |
692 | } | |
693 | } | |
2d2ed9df | 694 | |
a63d5eaa | 695 | const char *UI_get0_result_string(UI_STRING *uis) |
0f113f3e MC |
696 | { |
697 | if (!uis) | |
698 | return NULL; | |
699 | switch (uis->type) { | |
700 | case UIT_PROMPT: | |
701 | case UIT_VERIFY: | |
702 | return uis->result_buf; | |
703 | default: | |
704 | return NULL; | |
705 | } | |
706 | } | |
a63d5eaa RL |
707 | |
708 | const char *UI_get0_test_string(UI_STRING *uis) | |
0f113f3e MC |
709 | { |
710 | if (!uis) | |
711 | return NULL; | |
712 | switch (uis->type) { | |
713 | case UIT_VERIFY: | |
714 | return uis->_.string_data.test_buf; | |
715 | default: | |
716 | return NULL; | |
717 | } | |
718 | } | |
a63d5eaa RL |
719 | |
720 | int UI_get_result_minsize(UI_STRING *uis) | |
0f113f3e MC |
721 | { |
722 | if (!uis) | |
723 | return -1; | |
724 | switch (uis->type) { | |
725 | case UIT_PROMPT: | |
726 | case UIT_VERIFY: | |
727 | return uis->_.string_data.result_minsize; | |
728 | default: | |
729 | return -1; | |
730 | } | |
731 | } | |
a63d5eaa RL |
732 | |
733 | int UI_get_result_maxsize(UI_STRING *uis) | |
0f113f3e MC |
734 | { |
735 | if (!uis) | |
736 | return -1; | |
737 | switch (uis->type) { | |
738 | case UIT_PROMPT: | |
739 | case UIT_VERIFY: | |
740 | return uis->_.string_data.result_maxsize; | |
741 | default: | |
742 | return -1; | |
743 | } | |
744 | } | |
a63d5eaa | 745 | |
2d2ed9df | 746 | int UI_set_result(UI *ui, UI_STRING *uis, const char *result) |
0f113f3e MC |
747 | { |
748 | int l = strlen(result); | |
749 | ||
750 | ui->flags &= ~UI_FLAG_REDOABLE; | |
751 | ||
752 | if (!uis) | |
753 | return -1; | |
754 | switch (uis->type) { | |
755 | case UIT_PROMPT: | |
756 | case UIT_VERIFY: | |
757 | { | |
758 | char number1[DECIMAL_SIZE(uis->_.string_data.result_minsize) + 1]; | |
759 | char number2[DECIMAL_SIZE(uis->_.string_data.result_maxsize) + 1]; | |
760 | ||
761 | BIO_snprintf(number1, sizeof(number1), "%d", | |
762 | uis->_.string_data.result_minsize); | |
763 | BIO_snprintf(number2, sizeof(number2), "%d", | |
764 | uis->_.string_data.result_maxsize); | |
765 | ||
766 | if (l < uis->_.string_data.result_minsize) { | |
767 | ui->flags |= UI_FLAG_REDOABLE; | |
768 | UIerr(UI_F_UI_SET_RESULT, UI_R_RESULT_TOO_SMALL); | |
769 | ERR_add_error_data(5, "You must type in ", | |
770 | number1, " to ", number2, " characters"); | |
771 | return -1; | |
772 | } | |
773 | if (l > uis->_.string_data.result_maxsize) { | |
774 | ui->flags |= UI_FLAG_REDOABLE; | |
775 | UIerr(UI_F_UI_SET_RESULT, UI_R_RESULT_TOO_LARGE); | |
776 | ERR_add_error_data(5, "You must type in ", | |
777 | number1, " to ", number2, " characters"); | |
778 | return -1; | |
779 | } | |
780 | } | |
781 | ||
782 | if (!uis->result_buf) { | |
783 | UIerr(UI_F_UI_SET_RESULT, UI_R_NO_RESULT_BUFFER); | |
784 | return -1; | |
785 | } | |
786 | ||
7644a9ae | 787 | OPENSSL_strlcpy(uis->result_buf, result, |
0f113f3e MC |
788 | uis->_.string_data.result_maxsize + 1); |
789 | break; | |
790 | case UIT_BOOLEAN: | |
791 | { | |
792 | const char *p; | |
793 | ||
794 | if (!uis->result_buf) { | |
795 | UIerr(UI_F_UI_SET_RESULT, UI_R_NO_RESULT_BUFFER); | |
796 | return -1; | |
797 | } | |
798 | ||
799 | uis->result_buf[0] = '\0'; | |
800 | for (p = result; *p; p++) { | |
801 | if (strchr(uis->_.boolean_data.ok_chars, *p)) { | |
802 | uis->result_buf[0] = uis->_.boolean_data.ok_chars[0]; | |
803 | break; | |
804 | } | |
805 | if (strchr(uis->_.boolean_data.cancel_chars, *p)) { | |
806 | uis->result_buf[0] = uis->_.boolean_data.cancel_chars[0]; | |
807 | break; | |
808 | } | |
809 | } | |
810 | } | |
811 | default: | |
812 | break; | |
813 | } | |
814 | return 0; | |
815 | } |