pinentry: Implementation Details

 
 4 Implementation Details
 ************************
 
 The pinentry source code can be divided into three categories.  There is
 a backend module, which lives in 'pinentry/', there are utility
 functions, e.g., in 'secmem/', and there are various frontends.
 
    All of the low-level logic lives in the backend.  This frees the
 frontends from having to implement, e.g., the Assuan protocol.  When the
 backend receives an option, it updates the state in a 'pinentry_t'
 struct.  The frontend is called when the client either calls 'GETPIN',
 'CONFIRM' or 'MESSAGE'.  In these cases, the backend invokes the
 'pinentry_cmd_handler', which is passed the 'pinentry_t' struct.
 
    When the callback is invoked, the frontend should create a window
 based on the state in the 'pinentry_t' struct.  For instance, the title
 to use for the dialog's window (if any) is stored in the 'title' field.
 If the is 'NULL', the frontend should choose a reasonable default value.
 (Default is not always provided, because different tool kits and
 environments have different reasonable defaults.)
 
    The widget needs to support a number of different interactions with
 the user.  Each of them is described below.
 
 'Passphrase Confirmation'
 
      When creating a new key, the passphrase should be entered twice.
      The client (typically GPG Agent) indicates this to the PINENTRY by
      invoking 'SETREPEAT'.  In this case, the backend sets the
      'repeat_passphrase' field to a copy of the passed string.  The
      value of this field should be used to label a second text input.
 
      It is the frontend's responsibility to check that the passwords
      match.  If they don't match, the frontend should display an error
      message and continue to prompt the user.
 
      If the passwords do match, then, when the user presses the okay
      button, the 'repeat_okay' field should be set to '1' (this causes
      the backend to emit the 'S PIN_REPEATED' status message).
 
 'Message Box'
 
      Sometimes GPG Agent needs to display a message.  In this case, the
      'pin' variable is 'NULL'.
 
      At the Assuan level, this mode is selected by using either the
      'MESSAGE' or the 'CONFIRM' command instead of the 'GETPIN' command.
      The 'MESSAGE' command never shows the cancel or an other button.
      The same holds for 'CONFIRM' if it was passed the "-one-button"
      argument.  If 'CONFIRM' was not passed this argument, the dialog
      for 'CONFIRM' should show both the 'ok' and the 'cancel' buttons
      and optionally the 'notok' button.  The frontend can determine
      whether the dialog is a one-button dialog by inspecting the
      'one_button' variable.
 
 'Passphrase Entry'
 
      If neither of the above cases holds, then GPG Agent is simply
      requesting the passphrase.  In this case, the 'ok' and 'cancel'
      buttons should be displayed.
 
    The layout of the three variants is quite similar.  Here are the
 relevant elements that describe the layout:
 
 'title'
      The window's title.
 
 'description'
      The reason for the dialog.  When requesting a passphrase, this
      describes the key.  When showing a message box, this is the message
      to show.
 
 'error'
      If GPG Agent determines that the passphrase was incorrect, it will
      call 'GETPIN' again (up to a configurable number of times) to again
      prompt the user.  In this case, this variable contains a
      description of the error message.  This text should typically be
      highlighted in someway.
 
 'prompt, default-prompt'
      The string to associate with the passphrase entry box.
 
      There is a subtle difference between 'prompt' and 'default-prompt'.
      'default-prompt' means that a stylized prompt (e.g., an icon
      suggesting a prompt) may be used.  'prompt' means that the entry's
      meaning is not consistent with such a style and, as such, no icon
      should be used.
 
      If both variables are set, the 'prompt' variant takes precedence.
 
 'repeat_passphrase'
      The string to associate with the second passphrase entry box.  The
      second passphrase entry box should only be shown if this is not
      'NULL'.
 
 'ok, default-ok'
      The string to show in the 'ok' button.
 
      If there are any '_' characters, the following character should be
      used as an accelerator.  (A double underscore means a plain
      underscore should be shown.)  If the frontend does not support
      accelerators, then the underscores should be removed manually.
 
      There is a subtle difference between 'ok' and 'default-ok'.
      'default-ok' means that a stylized OK button should be used.  For
      instance, it could include a check mark.  'ok' means that the
      button's meaning is not consistent with such an icon and, as such,
      no icon should be used.  Thus, if the 'ok' button should have the
      text "No password required" then 'ok' should be used because a
      check mark icon doesn't make sense.
 
      If this variable is 'NULL', the frontend should choose a reasonable
      default.
 
      If both variables are set, the 'ok' variant takes precedence.
 
 'cancel, default-cancel'
      Like the 'ok' and 'default-ok' buttons except these strings are
      used for the cancel button.
 
      This button should not be shown if 'one_button' is set.
 
      'default-notok' Like the 'default-ok' button except this string is
      used for the other button.
 
      This button should only be displayed when showing a message box.
      If these variables are 'NULL' or 'one_button' is set, this button
      should not be displayed.
 
 'quality_bar'
      If this is set, a widget should be used to show the password's
      quality.  The value of this field is a label for the widget.
 
      Note: to update the password quality, whenever the password
      changes, call the 'pinentry_inq_quality' function and then update
      the password quality widget correspondingly.
 
 'quality_bar_tt'
      A tooltip for the quality bar.
 
 'default_pwmngr'
      If 'may_cache_password' and 'keyinfo' are set and the user
      consents, then the PINENTRY may cache the password with an external
      manager.  Note: getting the user's consent is essential, because
      password managers often provide a different level of security.  If
      the above condition is true and 'tried_password_cache' is false,
      then a check box with the specified string should be displayed.
      The check box must default to off.
 
 'default-cf-visi'
      The string to show with a question if you want to confirm that the
      user wants to change the visibility of the password.
 
 'default-tt-visi'
      Tooltip for an action that would reveal the entered password.
 
 'default-tt-hide'
      Tooltip for an action that would hide the password revealed by the
      action labeld with 'default-tt-visi'
 
    When the handler is done, it should store the passphrase in 'pin', if
 appropriate.  This variable is allocated in secure memory.  Use
 'pinentry_setbufferlen' to size the buffer.
 
    The actual return code is dependent on whether the dialog is in
 message mode or in passphrase mode.
 
    If the dialog is in message mode and the user pressed ok, return 1.
 Otherwise, return 0.  If an error occurred, indicate this by setting it
 in 'specific_err' or setting 'locale_err' to '1' (for locale specific
 errors).  If the dialog was canceled, then the handler should set the
 'canceled' variable to '1'.  If the not ok button was pressed, don't do
 anything else.
 
    If the dialog is in passphrase mode return '1' if the user entered a
 password and pressed ok.  If an error occurred, return '-1' and set
 'specific_err' or 'locale_err', as above.  If the user canceled the
 dialog box, return '-1'.
 
    If the window was closed, then the handler should set the
 'close_button' variable and otherwise act as if the cancel button was
 pressed.