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