LCOV - code coverage report
Current view: top level - g10 - server.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 9 225 4.0 %
Date: 2016-11-29 15:00:56 Functions: 1 24 4.2 %

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

Generated by: LCOV version 1.11