LCOV - code coverage report
Current view: top level - g10 - server.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 234 0.0 %
Date: 2015-11-05 17:10:59 Functions: 0 26 0.0 %

          Line data    Source code
       1             : /* server.c - server mode for gpg
       2             :  * Copyright (C) 2006, 2008  Free Software Foundation, Inc.
       3             :  *
       4             :  * This file is part of GnuPG.
       5             :  *
       6             :  * GnuPG is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * GnuPG is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : #include <errno.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <stdarg.h>
      26             : #include <ctype.h>
      27             : #include <unistd.h>
      28             : 
      29             : 
      30             : #include "gpg.h"
      31             : #include <assuan.h>
      32             : #include "util.h"
      33             : #include "i18n.h"
      34             : #include "options.h"
      35             : #include "../common/sysutils.h"
      36             : #include "status.h"
      37             : 
      38             : 
      39             : #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
      40             : 
      41             : 
      42             : /* Data used to associate an Assuan context with local server data.  */
      43             : struct server_local_s
      44             : {
      45             :   /* Our current Assuan context. */
      46             :   assuan_context_t assuan_ctx;
      47             :   /* File descriptor as set by the MESSAGE command. */
      48             :   gnupg_fd_t message_fd;
      49             : 
      50             :   /* List of prepared recipients.  */
      51             :   pk_list_t recplist;
      52             : 
      53             :   /* Set if pinentry notifications should be passed back to the
      54             :      client. */
      55             :   int allow_pinentry_notify;
      56             : };
      57             : 
      58             : 
      59             : 
      60             : /* Helper to close the message fd if it is open. */
      61             : static void
      62           0 : close_message_fd (ctrl_t ctrl)
      63             : {
      64           0 :   if (ctrl->server_local->message_fd != GNUPG_INVALID_FD)
      65             :     {
      66           0 :       assuan_sock_close (ctrl->server_local->message_fd);
      67           0 :       ctrl->server_local->message_fd = GNUPG_INVALID_FD;
      68             :     }
      69           0 : }
      70             : 
      71             : 
      72             : /* Skip over options.  Blanks after the options are also removed.  */
      73             : static char *
      74           0 : skip_options (const char *line)
      75             : {
      76           0 :   while (spacep (line))
      77           0 :     line++;
      78           0 :   while ( *line == '-' && line[1] == '-' )
      79             :     {
      80           0 :       while (*line && !spacep (line))
      81           0 :         line++;
      82           0 :       while (spacep (line))
      83           0 :         line++;
      84             :     }
      85           0 :   return (char*)line;
      86             : }
      87             : 
      88             : 
      89             : /* Check whether the option NAME appears in LINE.  */
      90             : static int
      91           0 : has_option (const char *line, const char *name)
      92             : {
      93             :   const char *s;
      94           0 :   int n = strlen (name);
      95             : 
      96           0 :   s = strstr (line, name);
      97           0 :   if (s && s >= skip_options (line))
      98           0 :     return 0;
      99           0 :   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
     100             : }
     101             : 
     102             : 
     103             : 
     104             : 
     105             : 
     106             : /* Called by libassuan for Assuan options.  See the Assuan manual for
     107             :    details. */
     108             : static gpg_error_t
     109           0 : option_handler (assuan_context_t ctx, const char *key, const char *value)
     110             : {
     111           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
     112             : 
     113             :   (void)value;
     114             : 
     115             :   /* Fixme: Implement the tty and locale args. */
     116           0 :   if (!strcmp (key, "display"))
     117             :     {
     118             :     }
     119           0 :   else if (!strcmp (key, "ttyname"))
     120             :     {
     121             :     }
     122           0 :   else if (!strcmp (key, "ttytype"))
     123             :     {
     124             :     }
     125           0 :   else if (!strcmp (key, "lc-ctype"))
     126             :     {
     127             :     }
     128           0 :   else if (!strcmp (key, "lc-messages"))
     129             :     {
     130             :     }
     131           0 :   else if (!strcmp (key, "xauthority"))
     132             :     {
     133             :     }
     134           0 :   else if (!strcmp (key, "pinentry_user_data"))
     135             :     {
     136             :     }
     137           0 :   else if (!strcmp (key, "list-mode"))
     138             :     {
     139             :       /* This is for now a dummy option. */
     140             :     }
     141           0 :   else if (!strcmp (key, "allow-pinentry-notify"))
     142             :     {
     143           0 :       ctrl->server_local->allow_pinentry_notify = 1;
     144             :     }
     145             :   else
     146           0 :     return gpg_error (GPG_ERR_UNKNOWN_OPTION);
     147             : 
     148           0 :   return 0;
     149             : }
     150             : 
     151             : 
     152             : /* Called by libassuan for RESET commands. */
     153             : static gpg_error_t
     154           0 : reset_notify (assuan_context_t ctx, char *line)
     155             : {
     156           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
     157             : 
     158             :   (void)line;
     159             : 
     160           0 :   release_pk_list (ctrl->server_local->recplist);
     161           0 :   ctrl->server_local->recplist = NULL;
     162             : 
     163           0 :   close_message_fd (ctrl);
     164           0 :   assuan_close_input_fd (ctx);
     165           0 :   assuan_close_output_fd (ctx);
     166           0 :   return 0;
     167             : }
     168             : 
     169             : 
     170             : /* Called by libassuan for INPUT commands. */
     171             : static gpg_error_t
     172           0 : input_notify (assuan_context_t ctx, char *line)
     173             : {
     174             : /*   ctrl_t ctrl = assuan_get_pointer (ctx); */
     175             : 
     176             :   (void)ctx;
     177             : 
     178           0 :   if (strstr (line, "--armor"))
     179             :     ; /* FIXME */
     180           0 :   else if (strstr (line, "--base64"))
     181             :     ; /* FIXME */
     182           0 :   else if (strstr (line, "--binary"))
     183             :     ;
     184             :   else
     185             :     {
     186             :       /* FIXME (autodetect encoding) */
     187             :     }
     188           0 :   return 0;
     189             : }
     190             : 
     191             : 
     192             : /* Called by libassuan for OUTPUT commands. */
     193             : static gpg_error_t
     194           0 : output_notify (assuan_context_t ctx, char *line)
     195             : {
     196             : /*   ctrl_t ctrl = assuan_get_pointer (ctx); */
     197             : 
     198             :   (void)ctx;
     199             : 
     200           0 :   if (strstr (line, "--armor"))
     201             :     ; /* FIXME */
     202           0 :   else if (strstr (line, "--base64"))
     203             :     {
     204             :       /* FIXME */
     205             :     }
     206           0 :   return 0;
     207             : }
     208             : 
     209             : 
     210             : 
     211             : 
     212             : /*  RECIPIENT [--hidden] <userID>
     213             : 
     214             :    Set the recipient for the encryption.  <userID> should be the
     215             :    internal representation of the key; the server may accept any other
     216             :    way of specification.  If this is a valid and trusted recipient the
     217             :    server does respond with OK, otherwise the return is an ERR with
     218             :    the reason why the recipient can't be used, the encryption will
     219             :    then not be done for this recipient.  If the policy is not to
     220             :    encrypt at all if not all recipients are valid, the client has to
     221             :    take care of this.  All RECIPIENT commands are cumulative until a
     222             :    RESET or an successful ENCRYPT command.  */
     223             : static gpg_error_t
     224           0 : cmd_recipient (assuan_context_t ctx, char *line)
     225             : {
     226           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
     227             :   gpg_error_t err;
     228             :   int hidden;
     229             : 
     230           0 :   hidden = has_option (line,"--hidden");
     231           0 :   line = skip_options (line);
     232             : 
     233             :   /* FIXME: Expand groups
     234             :   if (opt.grouplist)
     235             :     remusr = expand_group (rcpts);
     236             :   else
     237             :     remusr = rcpts;
     238             :   */
     239             : 
     240           0 :   err = find_and_check_key (ctrl, line, PUBKEY_USAGE_ENC, hidden,
     241           0 :                             &ctrl->server_local->recplist);
     242             : 
     243           0 :   if (err)
     244           0 :     log_error ("command '%s' failed: %s\n", "RECIPIENT", gpg_strerror (err));
     245           0 :   return err;
     246             : }
     247             : 
     248             : 
     249             : 
     250             : /*  SIGNER <userID>
     251             : 
     252             :    Set the signer's keys for the signature creation.  <userID> should
     253             :    be the internal representation of the key; the server may accept
     254             :    any other way of specification.  If this is a valid and usable
     255             :    signing key the server does respond with OK, otherwise it returns
     256             :    an ERR with the reason why the key can't be used, the signing will
     257             :    then not be done for this key.  If the policy is not to sign at all
     258             :    if not all signer keys are valid, the client has to take care of
     259             :    this.  All SIGNER commands are cumulative until a RESET but they
     260             :    are *not* reset by an SIGN command becuase it can be expected that
     261             :    set of signers are used for more than one sign operation.
     262             : 
     263             :    Note that this command returns an INV_RECP status which is a bit
     264             :    strange, but they are very similar.  */
     265             : static gpg_error_t
     266           0 : cmd_signer (assuan_context_t ctx, char *line)
     267             : {
     268             :   (void)ctx;
     269             :   (void)line;
     270           0 :   return gpg_error (GPG_ERR_NOT_SUPPORTED);
     271             : }
     272             : 
     273             : 
     274             : 
     275             : /*  ENCRYPT
     276             : 
     277             :    Do the actual encryption process.  Takes the plaintext from the
     278             :    INPUT command, writes the ciphertext to the file descriptor set
     279             :    with the OUTPUT command, take the recipients from all the
     280             :    recipients set so far with RECIPIENTS.
     281             : 
     282             :    If this command fails the clients should try to delete all output
     283             :    currently done or otherwise mark it as invalid.  GPG does ensure
     284             :    that there won't be any security problem with leftover data on the
     285             :    output in this case.
     286             : 
     287             :    In most cases this command won't fail because most necessary checks
     288             :    have been done while setting the recipients.  However some checks
     289             :    can only be done right here and thus error may occur anyway (for
     290             :    example, no recipients at all).
     291             : 
     292             :    The input, output and message pipes are closed after this
     293             :    command.  */
     294             : static gpg_error_t
     295           0 : cmd_encrypt (assuan_context_t ctx, char *line)
     296             : {
     297           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
     298             :   gpg_error_t err;
     299             :   int inp_fd, out_fd;
     300             : 
     301             :   (void)line; /* LINE is not used.  */
     302             : 
     303           0 :   if ( !ctrl->server_local->recplist )
     304             :     {
     305           0 :       write_status_text (STATUS_NO_RECP, "0");
     306           0 :       err = gpg_error (GPG_ERR_NO_USER_ID);
     307           0 :       goto leave;
     308             :     }
     309             : 
     310           0 :   inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
     311           0 :   if (inp_fd == -1)
     312             :     {
     313           0 :       err = set_error (GPG_ERR_ASS_NO_INPUT, NULL);
     314           0 :       goto leave;
     315             :     }
     316           0 :   out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
     317           0 :   if (out_fd == -1)
     318             :     {
     319           0 :       err = set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
     320           0 :       goto leave;
     321             :     }
     322             : 
     323             : 
     324             :   /* FIXME: GPGSM does this here: Add all encrypt-to marked recipients
     325             :      from the default list. */
     326             : 
     327             :   /* fixme: err = ctrl->audit? 0 : start_audit_session (ctrl);*/
     328             : 
     329           0 :   err = encrypt_crypt (ctrl, inp_fd, NULL, NULL, 0,
     330           0 :                        ctrl->server_local->recplist,
     331             :                        out_fd);
     332             : 
     333             :  leave:
     334             :   /* Release the recipient list on success.  */
     335           0 :   if (!err)
     336             :     {
     337           0 :       release_pk_list (ctrl->server_local->recplist);
     338           0 :       ctrl->server_local->recplist = NULL;
     339             :     }
     340             : 
     341             :   /* Close and reset the fds. */
     342           0 :   close_message_fd (ctrl);
     343           0 :   assuan_close_input_fd (ctx);
     344           0 :   assuan_close_output_fd (ctx);
     345             : 
     346           0 :   if (err)
     347           0 :     log_error ("command '%s' failed: %s\n", "ENCRYPT", gpg_strerror (err));
     348           0 :   return err;
     349             : }
     350             : 
     351             : 
     352             : 
     353             : /*  DECRYPT
     354             : 
     355             :     This performs the decrypt operation.  */
     356             : static gpg_error_t
     357           0 : cmd_decrypt (assuan_context_t ctx, char *line)
     358             : {
     359           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
     360             :   gpg_error_t err;
     361             :   int inp_fd, out_fd;
     362             : 
     363             :   (void)line; /* LINE is not used.  */
     364             : 
     365           0 :   inp_fd = translate_sys2libc_fd (assuan_get_input_fd (ctx), 0);
     366           0 :   if (inp_fd == -1)
     367           0 :     return set_error (GPG_ERR_ASS_NO_INPUT, NULL);
     368           0 :   out_fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
     369           0 :   if (out_fd == -1)
     370           0 :     return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
     371             : 
     372           0 :   glo_ctrl.lasterr = 0;
     373           0 :   err = decrypt_message_fd (ctrl, inp_fd, out_fd);
     374           0 :   if (!err)
     375           0 :     err = glo_ctrl.lasterr;
     376             : 
     377             :   /* Close and reset the fds. */
     378           0 :   close_message_fd (ctrl);
     379           0 :   assuan_close_input_fd (ctx);
     380           0 :   assuan_close_output_fd (ctx);
     381             : 
     382           0 :   if (err)
     383           0 :     log_error ("command '%s' failed: %s\n", "DECRYPT", gpg_strerror (err));
     384           0 :   return err;
     385             : }
     386             : 
     387             : 
     388             : 
     389             : /*  VERIFY
     390             : 
     391             :    This does a verify operation on the message send to the input-FD.
     392             :    The result is written out using status lines.  If an output FD was
     393             :    given, the signed text will be written to that.
     394             : 
     395             :    If the signature is a detached one, the server will inquire about
     396             :    the signed material and the client must provide it.
     397             :  */
     398             : static gpg_error_t
     399           0 : cmd_verify (assuan_context_t ctx, char *line)
     400             : {
     401             :   int rc;
     402             : #ifdef HAVE_W32_SYSTEM
     403             :   (void)ctx;
     404             :   (void)line;
     405             :   rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
     406             : #else
     407           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
     408           0 :   gnupg_fd_t fd = assuan_get_input_fd (ctx);
     409           0 :   gnupg_fd_t out_fd = assuan_get_output_fd (ctx);
     410           0 :   estream_t out_fp = NULL;
     411             : 
     412             :   /* FIXME: Revamp this code it is nearly to 3 years old and was only
     413             :      intended as a quick test.  */
     414             : 
     415             :   (void)line;
     416             : 
     417           0 :   if (fd == GNUPG_INVALID_FD)
     418           0 :     return gpg_error (GPG_ERR_ASS_NO_INPUT);
     419             : 
     420           0 :   if (out_fd != GNUPG_INVALID_FD)
     421             :     {
     422             :       es_syshd_t syshd;
     423             : 
     424             : #ifdef HAVE_W32_SYSTEM
     425             :       syshd.type = ES_SYSHD_HANDLE;
     426             :       syshd.u.handle = out_fd;
     427             : #else
     428           0 :       syshd.type = ES_SYSHD_FD;
     429           0 :       syshd.u.fd = out_fd;
     430             : #endif
     431           0 :       out_fp = es_sysopen_nc (&syshd, "w");
     432           0 :       if (!out_fp)
     433           0 :         return set_error (gpg_err_code_from_syserror (), "fdopen() failed");
     434             :     }
     435             : 
     436           0 :   log_debug ("WARNING: The server mode is WORK "
     437             :              "IN PROGRESS and not ready for use\n");
     438             : 
     439           0 :   rc = gpg_verify (ctrl, fd, ctrl->server_local->message_fd, out_fp);
     440             : 
     441           0 :   es_fclose (out_fp);
     442           0 :   close_message_fd (ctrl);
     443           0 :   assuan_close_input_fd (ctx);
     444           0 :   assuan_close_output_fd (ctx);
     445             : #endif
     446             : 
     447           0 :   if (rc)
     448           0 :     log_error ("command '%s' failed: %s\n", "VERIFY", gpg_strerror (rc));
     449           0 :   return rc;
     450             : }
     451             : 
     452             : 
     453             : 
     454             : /*  SIGN [--detached]
     455             : 
     456             :    Sign the data set with the INPUT command and write it to the sink
     457             :    set by OUTPUT.  With "--detached" specified, a detached signature
     458             :    is created.  */
     459             : static gpg_error_t
     460           0 : cmd_sign (assuan_context_t ctx, char *line)
     461             : {
     462             :   (void)ctx;
     463             :   (void)line;
     464           0 :   return gpg_error (GPG_ERR_NOT_SUPPORTED);
     465             : }
     466             : 
     467             : 
     468             : 
     469             : /*  IMPORT
     470             : 
     471             :   Import keys as read from the input-fd, return status message for
     472             :   each imported one.  The import checks the validity of the key.  */
     473             : static gpg_error_t
     474           0 : cmd_import (assuan_context_t ctx, char *line)
     475             : {
     476             :   (void)ctx;
     477             :   (void)line;
     478           0 :   return gpg_error (GPG_ERR_NOT_SUPPORTED);
     479             : }
     480             : 
     481             : 
     482             : 
     483             : /*  EXPORT [--data [--armor|--base64]] [--] pattern
     484             : 
     485             :    Similar to the --export command line command, this command exports
     486             :    public keys matching PATTERN.  The output is send to the output fd
     487             :    unless the --data option has been used in which case the output
     488             :    gets send inline using regular data lines.  The options "--armor"
     489             :    and "--base" ospecify an output format if "--data" has been used.
     490             :    Recall that in general the output format is set with the OUTPUT
     491             :    command.
     492             :  */
     493             : static gpg_error_t
     494           0 : cmd_export (assuan_context_t ctx, char *line)
     495             : {
     496             :   (void)ctx;
     497             :   (void)line;
     498           0 :   return gpg_error (GPG_ERR_NOT_SUPPORTED);
     499             : }
     500             : 
     501             : 
     502             : 
     503             : /*  DELKEYS
     504             : 
     505             :     Fixme
     506             : */
     507             : static gpg_error_t
     508           0 : cmd_delkeys (assuan_context_t ctx, char *line)
     509             : {
     510             :   (void)ctx;
     511             :   (void)line;
     512           0 :   return gpg_error (GPG_ERR_NOT_SUPPORTED);
     513             : }
     514             : 
     515             : 
     516             : 
     517             : /*  MESSAGE FD[=<n>]
     518             : 
     519             :    Set the file descriptor to read a message which is used with
     520             :    detached signatures.  */
     521             : static gpg_error_t
     522           0 : cmd_message (assuan_context_t ctx, char *line)
     523             : {
     524             :   int rc;
     525             :   gnupg_fd_t fd;
     526           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
     527             : 
     528           0 :   rc = assuan_command_parse_fd (ctx, line, &fd);
     529           0 :   if (rc)
     530           0 :     return rc;
     531           0 :   if (fd == GNUPG_INVALID_FD)
     532           0 :     return gpg_error (GPG_ERR_ASS_NO_INPUT);
     533           0 :   ctrl->server_local->message_fd = fd;
     534           0 :   return 0;
     535             : }
     536             : 
     537             : 
     538             : 
     539             : /* LISTKEYS [<patterns>]
     540             :    LISTSECRETKEYS [<patterns>]
     541             : 
     542             :    fixme
     543             : */
     544             : static gpg_error_t
     545           0 : do_listkeys (assuan_context_t ctx, char *line, int mode)
     546             : {
     547             :   (void)ctx;
     548             :   (void)line;
     549             :   (void)mode;
     550             : 
     551           0 :   return gpg_error (GPG_ERR_NOT_SUPPORTED);
     552             : }
     553             : 
     554             : 
     555             : static gpg_error_t
     556           0 : cmd_listkeys (assuan_context_t ctx, char *line)
     557             : {
     558           0 :   return do_listkeys (ctx, line, 3);
     559             : }
     560             : 
     561             : 
     562             : static gpg_error_t
     563           0 : cmd_listsecretkeys (assuan_context_t ctx, char *line)
     564             : {
     565           0 :   return do_listkeys (ctx, line, 2);
     566             : }
     567             : 
     568             : 
     569             : 
     570             : /* GENKEY
     571             : 
     572             :    Read the parameters in native format from the input fd and create a
     573             :    new OpenPGP key.
     574             :  */
     575             : static gpg_error_t
     576           0 : cmd_genkey (assuan_context_t ctx, char *line)
     577             : {
     578             :   (void)ctx;
     579             :   (void)line;
     580           0 :   return gpg_error (GPG_ERR_NOT_SUPPORTED);
     581             : }
     582             : 
     583             : 
     584             : /* GETINFO <what>
     585             : 
     586             :    Multipurpose function to return a variety of information.
     587             :    Supported values for WHAT are:
     588             : 
     589             :      version     - Return the version of the program.
     590             :      pid         - Return the process id of the server.
     591             : 
     592             :  */
     593             : static gpg_error_t
     594           0 : cmd_getinfo (assuan_context_t ctx, char *line)
     595             : {
     596             :   int rc;
     597             : 
     598           0 :   if (!strcmp (line, "version"))
     599             :     {
     600           0 :       const char *s = VERSION;
     601           0 :       rc = assuan_send_data (ctx, s, strlen (s));
     602             :     }
     603           0 :   else if (!strcmp (line, "pid"))
     604             :     {
     605             :       char numbuf[50];
     606             : 
     607           0 :       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
     608           0 :       rc = assuan_send_data (ctx, numbuf, strlen (numbuf));
     609             :     }
     610             :   else
     611           0 :     rc = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
     612           0 :   return rc;
     613             : }
     614             : 
     615             : static const char hlp_passwd[] =
     616             :   "PASSWD <userID>\n"
     617             :   "\n"
     618             :   "Change the passphrase of the secret key for USERID.";
     619             : static gpg_error_t
     620           0 : cmd_passwd (assuan_context_t ctx, char *line)
     621             : {
     622             :   /* ctrl_t ctrl = assuan_get_pointer (ctx); */
     623             :   gpg_error_t err;
     624             : 
     625             :   (void)ctx;
     626           0 :   line = skip_options (line);
     627             : 
     628           0 :   err = gpg_error (GPG_ERR_NOT_SUPPORTED);
     629             : 
     630           0 :   return err;
     631             : }
     632             : 
     633             : 
     634             : 
     635             : 
     636             : /* Helper to register our commands with libassuan. */
     637             : static int
     638           0 : register_commands (assuan_context_t ctx)
     639             : {
     640             :   static struct
     641             :   {
     642             :     const char *name;
     643             :     assuan_handler_t handler;
     644             :     const char * const help;
     645             :   } table[] = {
     646             :     { "RECIPIENT",     cmd_recipient },
     647             :     { "SIGNER",        cmd_signer    },
     648             :     { "ENCRYPT",       cmd_encrypt   },
     649             :     { "DECRYPT",       cmd_decrypt   },
     650             :     { "VERIFY",        cmd_verify    },
     651             :     { "SIGN",          cmd_sign      },
     652             :     { "IMPORT",        cmd_import    },
     653             :     { "EXPORT",        cmd_export    },
     654             :     { "INPUT",         NULL          },
     655             :     { "OUTPUT",        NULL          },
     656             :     { "MESSAGE",       cmd_message   },
     657             :     { "LISTKEYS",      cmd_listkeys  },
     658             :     { "LISTSECRETKEYS",cmd_listsecretkeys },
     659             :     { "GENKEY",        cmd_genkey    },
     660             :     { "DELKEYS",       cmd_delkeys   },
     661             :     { "GETINFO",       cmd_getinfo   },
     662             :     { "PASSWD",        cmd_passwd,  hlp_passwd},
     663             :     { NULL }
     664             :   };
     665             :   int i, rc;
     666             : 
     667           0 :   for (i=0; table[i].name; i++)
     668             :     {
     669           0 :       rc = assuan_register_command (ctx, table[i].name,
     670             :                                     table[i].handler, table[i].help);
     671           0 :       if (rc)
     672           0 :         return rc;
     673             :     }
     674           0 :   return 0;
     675             : }
     676             : 
     677             : 
     678             : 
     679             : 
     680             : /* Startup the server.  CTRL must have been allocated by the caller
     681             :    and set to the default values. */
     682             : int
     683           0 : gpg_server (ctrl_t ctrl)
     684             : {
     685             :   int rc;
     686             : #ifndef HAVE_W32_SYSTEM
     687             :   int filedes[2];
     688             : #endif
     689           0 :   assuan_context_t ctx = NULL;
     690             :   static const char hello[] = ("GNU Privacy Guard's OpenPGP server "
     691             :                                VERSION " ready");
     692             : 
     693             :   /* We use a pipe based server so that we can work from scripts.
     694             :      assuan_init_pipe_server will automagically detect when we are
     695             :      called with a socketpair and ignore FILEDES in this case.  */
     696             : #ifndef HAVE_W32_SYSTEM
     697           0 :   filedes[0] = assuan_fdopen (0);
     698           0 :   filedes[1] = assuan_fdopen (1);
     699             : #endif
     700           0 :   rc = assuan_new (&ctx);
     701           0 :   if (rc)
     702             :     {
     703           0 :       log_error ("failed to allocate the assuan context: %s\n",
     704             :                  gpg_strerror (rc));
     705           0 :       goto leave;
     706             :     }
     707             : 
     708             : #ifdef HAVE_W32_SYSTEM
     709             :   rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
     710             : #else
     711           0 :   rc = assuan_init_pipe_server (ctx, filedes);
     712             : #endif
     713           0 :   if (rc)
     714             :     {
     715           0 :       log_error ("failed to initialize the server: %s\n", gpg_strerror (rc));
     716           0 :       goto leave;
     717             :     }
     718             : 
     719           0 :   rc = register_commands (ctx);
     720           0 :   if (rc)
     721             :     {
     722           0 :       log_error ("failed to the register commands with Assuan: %s\n",
     723             :                  gpg_strerror(rc));
     724           0 :       goto leave;
     725             :     }
     726             : 
     727           0 :   assuan_set_pointer (ctx, ctrl);
     728           0 :   if (opt.verbose || opt.debug)
     729           0 :     {
     730           0 :       char *tmp = NULL;
     731             : 
     732           0 :       tmp = xtryasprintf ("Home: %s\n"
     733             :                           "Config: %s\n"
     734             :                           "%s",
     735             :                           opt.homedir,
     736             :                           "fixme: need config filename",
     737             :                           hello);
     738           0 :       if (tmp)
     739             :         {
     740           0 :           assuan_set_hello_line (ctx, tmp);
     741           0 :           xfree (tmp);
     742             :         }
     743             :     }
     744             :   else
     745           0 :     assuan_set_hello_line (ctx, hello);
     746           0 :   assuan_register_reset_notify (ctx, reset_notify);
     747           0 :   assuan_register_input_notify (ctx, input_notify);
     748           0 :   assuan_register_output_notify (ctx, output_notify);
     749           0 :   assuan_register_option_handler (ctx, option_handler);
     750             : 
     751           0 :   ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
     752           0 :   if (!ctrl->server_local)
     753             :     {
     754           0 :       rc = gpg_error_from_syserror ();
     755           0 :       goto leave;
     756             :     }
     757           0 :   ctrl->server_local->assuan_ctx = ctx;
     758           0 :   ctrl->server_local->message_fd = GNUPG_INVALID_FD;
     759             : 
     760             :   for (;;)
     761             :     {
     762           0 :       rc = assuan_accept (ctx);
     763           0 :       if (rc == -1)
     764             :         {
     765           0 :           rc = 0;
     766           0 :           break;
     767             :         }
     768           0 :       else if (rc)
     769             :         {
     770           0 :           log_info ("Assuan accept problem: %s\n", gpg_strerror (rc));
     771           0 :           break;
     772             :         }
     773             : 
     774           0 :       rc = assuan_process (ctx);
     775           0 :       if (rc)
     776             :         {
     777           0 :           log_info ("Assuan processing failed: %s\n", gpg_strerror (rc));
     778           0 :           continue;
     779             :         }
     780           0 :     }
     781             : 
     782             :  leave:
     783           0 :   if (ctrl->server_local)
     784             :     {
     785           0 :       release_pk_list (ctrl->server_local->recplist);
     786             : 
     787           0 :       xfree (ctrl->server_local);
     788           0 :       ctrl->server_local = NULL;
     789             :     }
     790           0 :   assuan_release (ctx);
     791           0 :   return rc;
     792             : }
     793             : 
     794             : 
     795             : /* Helper to notify the client about Pinentry events.  Because that
     796             :    might disturb some older clients, this is only done when enabled
     797             :    via an option.  If it is not enabled we tell Windows to allow
     798             :    setting the foreground window right here.  Returns an gpg error
     799             :    code. */
     800             : gpg_error_t
     801           0 : gpg_proxy_pinentry_notify (ctrl_t ctrl, const unsigned char *line)
     802             : {
     803           0 :   if (!ctrl || !ctrl->server_local
     804           0 :       || !ctrl->server_local->allow_pinentry_notify)
     805             :     {
     806           0 :       gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
     807             :       /* Client might be interested in that event - send as status line.  */
     808           0 :       if (!strncmp (line, "PINENTRY_LAUNCHED", 17)
     809           0 :           && (line[17]==' '||!line[17]))
     810             :         {
     811           0 :           for (line += 17; *line && spacep (line); line++)
     812             :             ;
     813           0 :           write_status_text (STATUS_PINENTRY_LAUNCHED, line);
     814             :         }
     815           0 :       return 0;
     816             :     }
     817           0 :   return assuan_inquire (ctrl->server_local->assuan_ctx, line, NULL, NULL, 0);
     818             : }

Generated by: LCOV version 1.11