Add UI functions to set result with explicit length and to retrieve the length
authorRichard Levitte <levitte@openssl.org>
Sat, 1 Jul 2017 10:39:51 +0000 (12:39 +0200)
committerRichard Levitte <levitte@openssl.org>
Fri, 8 Sep 2017 18:06:06 +0000 (20:06 +0200)
This allows completely arbitrary passphrases to be entered, including
NUL bytes.

Reviewed-by: Ben Kaduk <kaduk@mit.edu>
(Merged from https://github.com/openssl/openssl/pull/3821)

crypto/err/openssl.txt
crypto/ui/ui_err.c
crypto/ui/ui_lib.c
crypto/ui/ui_locl.h
crypto/ui/ui_util.c
doc/man3/UI_STRING.pod
doc/man3/UI_new.pod
include/openssl/ui.h
include/openssl/uierr.h
util/libcrypto.num

index 4b3c55b..253e0ab 100644 (file)
@@ -1355,9 +1355,11 @@ UI_F_UI_DUP_INPUT_STRING:103:UI_dup_input_string
 UI_F_UI_DUP_USER_DATA:118:UI_dup_user_data
 UI_F_UI_DUP_VERIFY_STRING:106:UI_dup_verify_string
 UI_F_UI_GET0_RESULT:107:UI_get0_result
+UI_F_UI_GET_RESULT_LENGTH:119:UI_get_result_length
 UI_F_UI_NEW_METHOD:104:UI_new_method
 UI_F_UI_PROCESS:113:UI_process
 UI_F_UI_SET_RESULT:105:UI_set_result
+UI_F_UI_SET_RESULT_EX:120:UI_set_result_ex
 X509V3_F_A2I_GENERAL_NAME:164:a2i_GENERAL_NAME
 X509V3_F_ADDR_VALIDATE_PATH_INTERNAL:166:addr_validate_path_internal
 X509V3_F_ASIDENTIFIERCHOICE_CANONIZE:161:ASIdentifierChoice_canonize
index 6a44f7a..e69163c 100644 (file)
@@ -33,9 +33,12 @@ static const ERR_STRING_DATA UI_str_functs[] = {
     {ERR_PACK(ERR_LIB_UI, UI_F_UI_DUP_VERIFY_STRING, 0),
      "UI_dup_verify_string"},
     {ERR_PACK(ERR_LIB_UI, UI_F_UI_GET0_RESULT, 0), "UI_get0_result"},
+    {ERR_PACK(ERR_LIB_UI, UI_F_UI_GET_RESULT_LENGTH, 0),
+     "UI_get_result_length"},
     {ERR_PACK(ERR_LIB_UI, UI_F_UI_NEW_METHOD, 0), "UI_new_method"},
     {ERR_PACK(ERR_LIB_UI, UI_F_UI_PROCESS, 0), "UI_process"},
     {ERR_PACK(ERR_LIB_UI, UI_F_UI_SET_RESULT, 0), "UI_set_result"},
+    {ERR_PACK(ERR_LIB_UI, UI_F_UI_SET_RESULT_EX, 0), "UI_set_result_ex"},
     {0, NULL}
 };
 
index 5b3eaff..4727d56 100644 (file)
@@ -441,6 +441,19 @@ const char *UI_get0_result(UI *ui, int i)
     return UI_get0_result_string(sk_UI_STRING_value(ui->strings, i));
 }
 
+int UI_get_result_length(UI *ui, int i)
+{
+    if (i < 0) {
+        UIerr(UI_F_UI_GET_RESULT_LENGTH, UI_R_INDEX_TOO_SMALL);
+        return -1;
+    }
+    if (i >= sk_UI_STRING_num(ui->strings)) {
+        UIerr(UI_F_UI_GET_RESULT_LENGTH, UI_R_INDEX_TOO_LARGE);
+        return -1;
+    }
+    return UI_get_result_string_length(sk_UI_STRING_value(ui->strings, i));
+}
+
 static int print_error(const char *str, size_t len, UI *ui)
 {
     UI_STRING uis;
@@ -796,6 +809,21 @@ const char *UI_get0_result_string(UI_STRING *uis)
     return NULL;
 }
 
+int UI_get_result_string_length(UI_STRING *uis)
+{
+    switch (uis->type) {
+    case UIT_PROMPT:
+    case UIT_VERIFY:
+        return uis->result_len;
+    case UIT_NONE:
+    case UIT_BOOLEAN:
+    case UIT_INFO:
+    case UIT_ERROR:
+        break;
+    }
+    return -1;
+}
+
 const char *UI_get0_test_string(UI_STRING *uis)
 {
     switch (uis->type) {
@@ -843,8 +871,18 @@ int UI_get_result_maxsize(UI_STRING *uis)
 
 int UI_set_result(UI *ui, UI_STRING *uis, const char *result)
 {
-    int l = strlen(result);
+#if 0
+    /*
+     * This is placed here solely to preserve UI_F_UI_SET_RESULT
+     * To be removed for OpenSSL 1.2.0
+     */
+    UIerr(UI_F_UI_SET_RESULT, ERR_R_DISABLED);
+#endif
+    return UI_set_result_ex(ui, uis, result, strlen(result));
+}
 
+int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len)
+{
     ui->flags &= ~UI_FLAG_REDOABLE;
 
     switch (uis->type) {
@@ -859,16 +897,16 @@ int UI_set_result(UI *ui, UI_STRING *uis, const char *result)
             BIO_snprintf(number2, sizeof(number2), "%d",
                          uis->_.string_data.result_maxsize);
 
-            if (l < uis->_.string_data.result_minsize) {
+            if (len < uis->_.string_data.result_minsize) {
                 ui->flags |= UI_FLAG_REDOABLE;
-                UIerr(UI_F_UI_SET_RESULT, UI_R_RESULT_TOO_SMALL);
+                UIerr(UI_F_UI_SET_RESULT_EX, UI_R_RESULT_TOO_SMALL);
                 ERR_add_error_data(5, "You must type in ",
                                    number1, " to ", number2, " characters");
                 return -1;
             }
-            if (l > uis->_.string_data.result_maxsize) {
+            if (len > uis->_.string_data.result_maxsize) {
                 ui->flags |= UI_FLAG_REDOABLE;
-                UIerr(UI_F_UI_SET_RESULT, UI_R_RESULT_TOO_LARGE);
+                UIerr(UI_F_UI_SET_RESULT_EX, UI_R_RESULT_TOO_LARGE);
                 ERR_add_error_data(5, "You must type in ",
                                    number1, " to ", number2, " characters");
                 return -1;
@@ -876,19 +914,21 @@ int UI_set_result(UI *ui, UI_STRING *uis, const char *result)
         }
 
         if (uis->result_buf == NULL) {
-            UIerr(UI_F_UI_SET_RESULT, UI_R_NO_RESULT_BUFFER);
+            UIerr(UI_F_UI_SET_RESULT_EX, UI_R_NO_RESULT_BUFFER);
             return -1;
         }
 
-        OPENSSL_strlcpy(uis->result_buf, result,
-                    uis->_.string_data.result_maxsize + 1);
+        memcpy(uis->result_buf, result, len);
+        if (len <= uis->_.string_data.result_maxsize)
+            uis->result_buf[len] = '\0';
+        uis->result_len = len;
         break;
     case UIT_BOOLEAN:
         {
             const char *p;
 
             if (uis->result_buf == NULL) {
-                UIerr(UI_F_UI_SET_RESULT, UI_R_NO_RESULT_BUFFER);
+                UIerr(UI_F_UI_SET_RESULT_EX, UI_R_NO_RESULT_BUFFER);
                 return -1;
             }
 
index 1b0d596..19b33b8 100644 (file)
@@ -71,6 +71,7 @@ struct ui_string_st {
                                  * Otherwise, it may be allocated by the UI
                                  * routine, meaning result_minsize is going
                                  * to be overwritten. */
+    size_t result_len;
     union {
         struct {
             int result_minsize; /* Input: minimum required size of the
index dbfeecc..7249a07 100644 (file)
@@ -116,7 +116,7 @@ static int ui_read(UI *ui, UI_STRING *uis)
                 result[len] = '\0';
             if (len <= 0)
                 return len;
-            if (UI_set_result(ui, uis, result) >= 0)
+            if (UI_set_result_ex(ui, uis, result, len) >= 0)
                 return 1;
             return 0;
         }
index 340d9b2..5a464a3 100644 (file)
@@ -4,9 +4,9 @@
 
 UI_STRING, UI_string_types, UI_get_string_type,
 UI_get_input_flags, UI_get0_output_string,
-UI_get0_action_string, UI_get0_result_string,
+UI_get0_action_string, UI_get0_result_string, UI_get_result_string_length,
 UI_get0_test_string, UI_get_result_minsize,
-UI_get_result_maxsize, UI_set_result
+UI_get_result_maxsize, UI_set_result, UI_set_result_ex
 - User interface string parsing
 
 =head1 SYNOPSIS
@@ -29,10 +29,12 @@ UI_get_result_maxsize, UI_set_result
  const char *UI_get0_output_string(UI_STRING *uis);
  const char *UI_get0_action_string(UI_STRING *uis);
  const char *UI_get0_result_string(UI_STRING *uis);
+ int UI_get_result_string_length(UI_STRING *uis);
  const char *UI_get0_test_string(UI_STRING *uis);
  int UI_get_result_minsize(UI_STRING *uis);
  int UI_get_result_maxsize(UI_STRING *uis);
  int UI_set_result(UI *ui, UI_STRING *uis, const char *result);
+ int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len);
 
 =head1 DESCRIPTION
 
@@ -60,9 +62,11 @@ associated with a B<UIT_BOOLEAN> type B<UI_STRING>.
 For all other B<UI_STRING> types, NULL is returned.
 See L<UI_add_input_boolean(3)>.
 
-UI_get0_result_string() is used to retrieve the result of a prompt.
+UI_get0_result_string() and UI_get_result_string_length() are used to
+retrieve the result of a prompt and its length.
 This is only useful for B<UIT_PROMPT> and B<UIT_VERIFY> type strings.
-For all other B<UI_STRING> types, NULL is returned.
+For all other B<UI_STRING> types, UI_get0_result_string() returns NULL
+and UI_get_result_string_length() returns -1.
 
 UI_get0_test_string() is used to retrieve the string to compare the
 prompt result with.
@@ -74,7 +78,7 @@ retrieve the minimum and maximum required size of the result.
 This is only useful for B<UIT_PROMPT> and B<UIT_VERIFY> type strings.
 For all other B<UI_STRING> types, -1 is returned.
 
-UI_set_result() is used to set the result value of a prompt.
+UI_set_result_ex() is used to set the result value of a prompt and its length.
 For B<UIT_PROMPT> and B<UIT_VERIFY> type UI strings, this sets the
 result retrievable with UI_get0_result_string() by copying the
 contents of B<result> if its length fits the minimum and maximum size
@@ -88,6 +92,11 @@ set to the NUL char C<\0>.
 See L<UI_add_input_boolean(3)> for more information on B<ok_chars> and
 B<cancel_chars>.
 
+UI_set_result() does the same thing as UI_set_result_ex(), but calculates
+its length internally.
+It expects the string to be terminated with a NUL byte, and is therefore
+only useful with normal C strings.
+
 =head1 RETURN VALUES
 
 UI_get_string_type() returns the UI string type.
@@ -103,6 +112,10 @@ UI_get0_result_string() returns the UI string result buffer for
 B<UIT_PROMPT> and B<UIT_VERIFY> type UI strings, NULL for any other
 type.
 
+UI_get_result_string_length() returns the UI string result buffer's
+content length for B<UIT_PROMPT> and B<UIT_VERIFY> type UI strings,
+-1 for any other type.
+
 UI_get0_test_string() returns the UI string action description
 string for B<UIT_VERIFY> type UI strings, NULL for any other type.
 
index 469ea53..39b24da 100644 (file)
@@ -8,6 +8,7 @@ UI_add_verify_string, UI_dup_verify_string, UI_add_input_boolean,
 UI_dup_input_boolean, UI_add_info_string, UI_dup_info_string,
 UI_add_error_string, UI_dup_error_string, UI_construct_prompt,
 UI_add_user_data, UI_dup_user_data, UI_get0_user_data, UI_get0_result,
+UI_get_result_length,
 UI_process, UI_ctrl, UI_set_default_method, UI_get_default_method,
 UI_get_method, UI_set_method, UI_OpenSSL, UI_null - user interface
 
@@ -50,6 +51,7 @@ UI_get_method, UI_set_method, UI_OpenSSL, UI_null - user interface
  void *UI_get0_user_data(UI *ui);
 
  const char *UI_get0_result(UI *ui, int i);
+ int UI_get_result_length(UI *ui, int i);
 
  int UI_process(UI *ui);
 
@@ -82,12 +84,12 @@ user-defined random data can be passed down to the underlying method
 through calls to UI_add_user_data() or UI_dup_user_data().  The default
 UI method doesn't care about these data, but other methods might.  Finally,
 use UI_process() to actually perform the prompting and UI_get0_result()
-to find the result to the prompt.
+and UI_get_result_length() to find the result to the prompt and its length.
 
 A UI can contain more than one prompt, which are performed in the given
 sequence.  Each prompt gets an index number which is returned by the
 UI_add and UI_dup functions, and has to be used to get the corresponding
-result with UI_get0_result().
+result with UI_get0_result() and UI_get_result_length().
 
 UI_process() can be called more than once on the same UI, thereby allowing
 a UI to have a long lifetime, but can just as well have a short lifetime.
@@ -173,6 +175,9 @@ UI with UI_add_user_data() or UI_dup_user_data.
 UI_get0_result() returns a pointer to the result buffer associated with
 the information indexed by I<i>.
 
+UI_get_result_length() returns the length of the result buffer associated with
+the information indexed by I<i>.
+
 UI_process() goes through the information given so far, does all the printing
 and prompting and returns the final status, which is -2 on out-of-band events
 (Interrupt, Cancel, ...), -1 on error and 0 on success.
index 0f8c03f..a024674 100644 (file)
@@ -175,6 +175,7 @@ void *UI_get0_user_data(UI *ui);
 
 /* Return the result associated with a prompt given with the index i. */
 const char *UI_get0_result(UI *ui, int i);
+int UI_get_result_length(UI *ui, int i);
 
 /* When all strings have been added, process the whole thing. */
 int UI_process(UI *ui);
@@ -340,6 +341,7 @@ const char *UI_get0_output_string(UI_STRING *uis);
 const char *UI_get0_action_string(UI_STRING *uis);
 /* Return the result of a prompt */
 const char *UI_get0_result_string(UI_STRING *uis);
+int UI_get_result_string_length(UI_STRING *uis);
 /*
  * Return the string to test the result against.  Only useful with verifies.
  */
@@ -350,6 +352,7 @@ int UI_get_result_minsize(UI_STRING *uis);
 int UI_get_result_maxsize(UI_STRING *uis);
 /* Set the result of a UI_STRING. */
 int UI_set_result(UI *ui, UI_STRING *uis, const char *result);
+int UI_set_result_ex(UI *ui, UI_STRING *uis, const char *result, int len);
 
 /* A couple of popular utility functions */
 int UI_UTIL_read_pw_string(char *buf, int length, const char *prompt,
index 3550650..f7c77f2 100644 (file)
@@ -37,9 +37,11 @@ int ERR_load_UI_strings(void);
 # define UI_F_UI_DUP_USER_DATA                            118
 # define UI_F_UI_DUP_VERIFY_STRING                        106
 # define UI_F_UI_GET0_RESULT                              107
+# define UI_F_UI_GET_RESULT_LENGTH                        119
 # define UI_F_UI_NEW_METHOD                               104
 # define UI_F_UI_PROCESS                                  113
 # define UI_F_UI_SET_RESULT                               105
+# define UI_F_UI_SET_RESULT_EX                            120
 
 /*
  * UI reason codes.
index 8a276b9..30cea8c 100644 (file)
@@ -4390,3 +4390,6 @@ EVP_aria_128_gcm                        4333      1_1_1   EXIST::FUNCTION:ARIA
 EVP_aria_128_ccm                        4334   1_1_1   EXIST::FUNCTION:ARIA
 EVP_aria_192_gcm                        4335   1_1_1   EXIST::FUNCTION:ARIA
 CRYPTO_THREAD_glock_new                 4336   1_1_1   EXIST::FUNCTION:
+UI_get_result_length                    4337   1_1_1   EXIST::FUNCTION:
+UI_set_result_ex                        4338   1_1_1   EXIST::FUNCTION:
+UI_get_result_string_length             4339   1_1_1   EXIST::FUNCTION: