GOST2012 TLS ClientCertificateType Identifiers support
[openssl.git] / apps / lib / apps_ui.c
1 /*
2  * Copyright 1995-2018 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
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_fallback_method = NULL;
17
18
19 static int ui_open(UI *ui)
20 {
21     int (*opener)(UI *ui) = UI_method_get_opener(ui_fallback_method);
22
23     if (opener)
24         return opener(ui);
25     return 1;
26 }
27
28 static int ui_read(UI *ui, UI_STRING *uis)
29 {
30     int (*reader)(UI *ui, UI_STRING *uis) = NULL;
31
32     if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
33         && UI_get0_user_data(ui)) {
34         switch (UI_get_string_type(uis)) {
35         case UIT_PROMPT:
36         case UIT_VERIFY:
37             {
38                 const char *password =
39                     ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
40                 if (password && password[0] != '\0') {
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_fallback_method);
55     if (reader)
56         return reader(ui, uis);
57     return 1;
58 }
59
60 static int ui_write(UI *ui, UI_STRING *uis)
61 {
62     int (*writer)(UI *ui, UI_STRING *uis) = NULL;
63
64     if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
65         && UI_get0_user_data(ui)) {
66         switch (UI_get_string_type(uis)) {
67         case UIT_PROMPT:
68         case UIT_VERIFY:
69             {
70                 const char *password =
71                     ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
72                 if (password && password[0] != '\0')
73                     return 1;
74             }
75             break;
76         case UIT_NONE:
77         case UIT_BOOLEAN:
78         case UIT_INFO:
79         case UIT_ERROR:
80             break;
81         }
82     }
83
84     writer = UI_method_get_writer(ui_fallback_method);
85     if (writer)
86         return writer(ui, uis);
87     return 1;
88 }
89
90 static int ui_close(UI *ui)
91 {
92     int (*closer)(UI *ui) = UI_method_get_closer(ui_fallback_method);
93
94     if (closer)
95         return closer(ui);
96     return 1;
97 }
98
99 int setup_ui_method(void)
100 {
101     ui_fallback_method = UI_null();
102 #ifndef OPENSSL_NO_UI_CONSOLE
103     ui_fallback_method = UI_OpenSSL();
104 #endif
105     ui_method = UI_create_method("OpenSSL application user interface");
106     UI_method_set_opener(ui_method, ui_open);
107     UI_method_set_reader(ui_method, ui_read);
108     UI_method_set_writer(ui_method, ui_write);
109     UI_method_set_closer(ui_method, ui_close);
110     return 0;
111 }
112
113 void destroy_ui_method(void)
114 {
115     if (ui_method) {
116         UI_destroy_method(ui_method);
117         ui_method = NULL;
118     }
119 }
120
121 const UI_METHOD *get_ui_method(void)
122 {
123     return ui_method;
124 }
125
126 static void *ui_malloc(int sz, const char *what)
127 {
128     void *vp = OPENSSL_malloc(sz);
129
130     if (vp == NULL) {
131         BIO_printf(bio_err, "Could not allocate %d bytes for %s\n", sz, what);
132         ERR_print_errors(bio_err);
133         exit(1);
134     }
135     return vp;
136 }
137
138 int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_data)
139 {
140     int res = 0;
141     UI *ui;
142     int ok = 0;
143     char *buff = NULL;
144     int ui_flags = 0;
145     const char *prompt_info = NULL;
146     char *prompt;
147
148     if ((ui = UI_new_method(ui_method)) == NULL)
149         return 0;
150
151     if (cb_data != NULL && cb_data->prompt_info != NULL)
152         prompt_info = cb_data->prompt_info;
153     prompt = UI_construct_prompt(ui, "pass phrase", prompt_info);
154     if (prompt == NULL) {
155         BIO_printf(bio_err, "Out of memory\n");
156         UI_free(ui);
157         return 0;
158     }
159
160     ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
161     UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
162
163     /* We know that there is no previous user data to return to us */
164     (void)UI_add_user_data(ui, cb_data);
165
166     ok = UI_add_input_string(ui, prompt, ui_flags, buf,
167                              PW_MIN_LENGTH, bufsiz - 1);
168
169     if (ok >= 0 && verify) {
170         buff = ui_malloc(bufsiz, "password buffer");
171         ok = UI_add_verify_string(ui, prompt, ui_flags, buff,
172                                   PW_MIN_LENGTH, bufsiz - 1, buf);
173     }
174     if (ok >= 0)
175         do {
176             ok = UI_process(ui);
177         } while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
178
179     OPENSSL_clear_free(buff, (unsigned int)bufsiz);
180
181     if (ok >= 0)
182         res = strlen(buf);
183     if (ok == -1) {
184         BIO_printf(bio_err, "User interface error\n");
185         ERR_print_errors(bio_err);
186         OPENSSL_cleanse(buf, (unsigned int)bufsiz);
187         res = 0;
188     }
189     if (ok == -2) {
190         BIO_printf(bio_err, "aborted!\n");
191         OPENSSL_cleanse(buf, (unsigned int)bufsiz);
192         res = 0;
193     }
194     UI_free(ui);
195     OPENSSL_free(prompt);
196     return res;
197 }