Home | History | Annotate | Line # | Download | only in lib
      1      1.1  christos /*
      2      1.1  christos  * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
      3      1.1  christos  *
      4      1.1  christos  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5      1.1  christos  * this file except in compliance with the License.  You can obtain a copy
      6      1.1  christos  * in the file LICENSE in the source distribution or at
      7      1.1  christos  * https://www.openssl.org/source/license.html
      8      1.1  christos  */
      9      1.1  christos 
     10      1.1  christos #include <string.h>
     11      1.1  christos #include <openssl/err.h>
     12      1.1  christos #include <openssl/ui.h>
     13      1.1  christos #include "apps_ui.h"
     14      1.1  christos 
     15      1.1  christos static UI_METHOD *ui_method = NULL;
     16      1.1  christos static const UI_METHOD *ui_base_method = NULL;
     17      1.1  christos 
     18      1.1  christos static int ui_open(UI *ui)
     19      1.1  christos {
     20      1.1  christos     int (*opener)(UI *ui) = UI_method_get_opener(ui_base_method);
     21      1.1  christos 
     22      1.1  christos     if (opener != NULL)
     23      1.1  christos         return opener(ui);
     24      1.1  christos     return 1;
     25      1.1  christos }
     26      1.1  christos 
     27      1.1  christos static int ui_read(UI *ui, UI_STRING *uis)
     28      1.1  christos {
     29      1.1  christos     int (*reader)(UI *ui, UI_STRING *uis) = NULL;
     30      1.1  christos 
     31      1.1  christos     if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
     32      1.1  christos         && UI_get0_user_data(ui)) {
     33      1.1  christos         switch (UI_get_string_type(uis)) {
     34      1.1  christos         case UIT_PROMPT:
     35  1.1.1.2  christos         case UIT_VERIFY: {
     36  1.1.1.2  christos             const char *password = ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
     37  1.1.1.2  christos 
     38  1.1.1.2  christos             if (password != NULL) {
     39  1.1.1.2  christos                 UI_set_result(ui, uis, password);
     40  1.1.1.2  christos                 return 1;
     41      1.1  christos             }
     42  1.1.1.2  christos         } break;
     43      1.1  christos         case UIT_NONE:
     44      1.1  christos         case UIT_BOOLEAN:
     45      1.1  christos         case UIT_INFO:
     46      1.1  christos         case UIT_ERROR:
     47      1.1  christos             break;
     48      1.1  christos         }
     49      1.1  christos     }
     50      1.1  christos 
     51      1.1  christos     reader = UI_method_get_reader(ui_base_method);
     52      1.1  christos     if (reader != NULL)
     53      1.1  christos         return reader(ui, uis);
     54      1.1  christos     /* Default to the empty password if we've got nothing better */
     55      1.1  christos     UI_set_result(ui, uis, "");
     56      1.1  christos     return 1;
     57      1.1  christos }
     58      1.1  christos 
     59      1.1  christos static int ui_write(UI *ui, UI_STRING *uis)
     60      1.1  christos {
     61      1.1  christos     int (*writer)(UI *ui, UI_STRING *uis) = NULL;
     62      1.1  christos 
     63      1.1  christos     if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
     64      1.1  christos         && UI_get0_user_data(ui)) {
     65      1.1  christos         switch (UI_get_string_type(uis)) {
     66      1.1  christos         case UIT_PROMPT:
     67  1.1.1.2  christos         case UIT_VERIFY: {
     68  1.1.1.2  christos             const char *password = ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
     69      1.1  christos 
     70  1.1.1.2  christos             if (password != NULL)
     71  1.1.1.2  christos                 return 1;
     72  1.1.1.2  christos         } break;
     73      1.1  christos         case UIT_NONE:
     74      1.1  christos         case UIT_BOOLEAN:
     75      1.1  christos         case UIT_INFO:
     76      1.1  christos         case UIT_ERROR:
     77      1.1  christos             break;
     78      1.1  christos         }
     79      1.1  christos     }
     80      1.1  christos 
     81      1.1  christos     writer = UI_method_get_writer(ui_base_method);
     82      1.1  christos     if (writer != NULL)
     83      1.1  christos         return writer(ui, uis);
     84      1.1  christos     return 1;
     85      1.1  christos }
     86      1.1  christos 
     87      1.1  christos static int ui_close(UI *ui)
     88      1.1  christos {
     89      1.1  christos     int (*closer)(UI *ui) = UI_method_get_closer(ui_base_method);
     90      1.1  christos 
     91      1.1  christos     if (closer != NULL)
     92      1.1  christos         return closer(ui);
     93      1.1  christos     return 1;
     94      1.1  christos }
     95      1.1  christos 
     96      1.1  christos /* object_name defaults to prompt_info from ui user data if present */
     97      1.1  christos static char *ui_prompt_construct(UI *ui, const char *phrase_desc,
     98  1.1.1.2  christos     const char *object_name)
     99      1.1  christos {
    100      1.1  christos     PW_CB_DATA *cb_data = (PW_CB_DATA *)UI_get0_user_data(ui);
    101      1.1  christos 
    102      1.1  christos     if (phrase_desc == NULL)
    103      1.1  christos         phrase_desc = "pass phrase";
    104      1.1  christos     if (object_name == NULL && cb_data != NULL)
    105      1.1  christos         object_name = cb_data->prompt_info;
    106      1.1  christos     return UI_construct_prompt(NULL, phrase_desc, object_name);
    107      1.1  christos }
    108      1.1  christos 
    109      1.1  christos int set_base_ui_method(const UI_METHOD *ui_meth)
    110      1.1  christos {
    111      1.1  christos     if (ui_meth == NULL)
    112      1.1  christos         ui_meth = UI_null();
    113      1.1  christos     ui_base_method = ui_meth;
    114      1.1  christos     return 1;
    115      1.1  christos }
    116      1.1  christos 
    117      1.1  christos int setup_ui_method(void)
    118      1.1  christos {
    119      1.1  christos     ui_base_method = UI_null();
    120      1.1  christos #ifndef OPENSSL_NO_UI_CONSOLE
    121      1.1  christos     ui_base_method = UI_OpenSSL();
    122      1.1  christos #endif
    123      1.1  christos     ui_method = UI_create_method("OpenSSL application user interface");
    124      1.1  christos     return ui_method != NULL
    125      1.1  christos         && 0 == UI_method_set_opener(ui_method, ui_open)
    126      1.1  christos         && 0 == UI_method_set_reader(ui_method, ui_read)
    127      1.1  christos         && 0 == UI_method_set_writer(ui_method, ui_write)
    128      1.1  christos         && 0 == UI_method_set_closer(ui_method, ui_close)
    129  1.1.1.2  christos         && 0 == UI_method_set_prompt_constructor(ui_method, ui_prompt_construct);
    130      1.1  christos }
    131      1.1  christos 
    132      1.1  christos void destroy_ui_method(void)
    133      1.1  christos {
    134      1.1  christos     if (ui_method != NULL) {
    135      1.1  christos         UI_destroy_method(ui_method);
    136      1.1  christos         ui_method = NULL;
    137      1.1  christos     }
    138      1.1  christos }
    139      1.1  christos 
    140      1.1  christos const UI_METHOD *get_ui_method(void)
    141      1.1  christos {
    142      1.1  christos     return ui_method;
    143      1.1  christos }
    144      1.1  christos 
    145      1.1  christos static void *ui_malloc(int sz, const char *what)
    146      1.1  christos {
    147      1.1  christos     void *vp = OPENSSL_malloc(sz);
    148      1.1  christos 
    149      1.1  christos     if (vp == NULL) {
    150      1.1  christos         BIO_printf(bio_err, "Could not allocate %d bytes for %s\n", sz, what);
    151      1.1  christos         ERR_print_errors(bio_err);
    152      1.1  christos         exit(1);
    153      1.1  christos     }
    154      1.1  christos     return vp;
    155      1.1  christos }
    156      1.1  christos 
    157      1.1  christos int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data)
    158      1.1  christos {
    159      1.1  christos     int res = 0;
    160      1.1  christos     UI *ui;
    161      1.1  christos     int ok = 0;
    162      1.1  christos     char *buff = NULL;
    163      1.1  christos     int ui_flags = 0;
    164      1.1  christos     const char *prompt_info = NULL;
    165      1.1  christos     char *prompt;
    166      1.1  christos 
    167      1.1  christos     if ((ui = UI_new_method(ui_method)) == NULL)
    168      1.1  christos         return 0;
    169      1.1  christos 
    170      1.1  christos     if (cb_data != NULL && cb_data->prompt_info != NULL)
    171      1.1  christos         prompt_info = cb_data->prompt_info;
    172      1.1  christos     prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
    173      1.1  christos     if (prompt == NULL) {
    174      1.1  christos         BIO_printf(bio_err, "Out of memory\n");
    175      1.1  christos         UI_free(ui);
    176      1.1  christos         return 0;
    177      1.1  christos     }
    178      1.1  christos 
    179      1.1  christos     ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
    180      1.1  christos     UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
    181      1.1  christos 
    182      1.1  christos     /* We know that there is no previous user data to return to us */
    183      1.1  christos     (void)UI_add_user_data(ui, cb_data);
    184      1.1  christos 
    185      1.1  christos     ok = UI_add_input_string(ui, prompt, ui_flags, buf,
    186  1.1.1.2  christos         PW_MIN_LENGTH, bufsiz - 1);
    187      1.1  christos 
    188      1.1  christos     if (ok >= 0 && verify) {
    189      1.1  christos         buff = ui_malloc(bufsiz, "password buffer");
    190      1.1  christos         ok = UI_add_verify_string(ui, prompt, ui_flags, buff,
    191  1.1.1.2  christos             PW_MIN_LENGTH, bufsiz - 1, buf);
    192      1.1  christos     }
    193      1.1  christos     if (ok >= 0)
    194      1.1  christos         do {
    195      1.1  christos             ok = UI_process(ui);
    196      1.1  christos         } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
    197      1.1  christos 
    198      1.1  christos     OPENSSL_clear_free(buff, (unsigned int)bufsiz);
    199      1.1  christos 
    200      1.1  christos     if (ok >= 0)
    201      1.1  christos         res = strlen(buf);
    202      1.1  christos     if (ok == -1) {
    203      1.1  christos         BIO_printf(bio_err, "User interface error\n");
    204      1.1  christos         ERR_print_errors(bio_err);
    205      1.1  christos         OPENSSL_cleanse(buf, (unsigned int)bufsiz);
    206      1.1  christos         res = 0;
    207      1.1  christos     }
    208      1.1  christos     if (ok == -2) {
    209      1.1  christos         BIO_printf(bio_err, "aborted!\n");
    210      1.1  christos         OPENSSL_cleanse(buf, (unsigned int)bufsiz);
    211      1.1  christos         res = 0;
    212      1.1  christos     }
    213      1.1  christos     UI_free(ui);
    214      1.1  christos     OPENSSL_free(prompt);
    215      1.1  christos     return res;
    216      1.1  christos }
    217