A local copy of OpenSSL from GitHub
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

821 lines
22 KiB

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