Fix possible realloc overflow for gpgsm and uiserver engines.
[gpgme.git] / src / engine-uiserver.c
index 92f7536..a7184b7 100644 (file)
@@ -1,19 +1,19 @@
 /* engine-uiserver.c - Uiserver engine.
    Copyright (C) 2000 Werner Koch (dd9jn)
    Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009 g10 Code GmbH
+
    This file is part of GPGME.
 
    GPGME is free software; you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as
    published by the Free Software Foundation; either version 2.1 of
    the License, or (at your option) any later version.
-   
+
    GPGME is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.
-   
+
    You should have received a copy of the GNU Lesser General Public
    License along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -49,7 +49,6 @@
 #include "data.h"
 
 #include "assuan.h"
-#include "status-table.h"
 #include "debug.h"
 
 #include "engine-backend.h"
@@ -104,7 +103,7 @@ struct engine_uiserver
       int linelen;
     } attic;
     int any; /* any data line seen */
-  } colon; 
+  } colon;
 
   gpgme_data_t inline_data;  /* Used to collect D lines.  */
 
@@ -114,7 +113,7 @@ struct engine_uiserver
 typedef struct engine_uiserver *engine_uiserver_t;
 
 
-static void uiserver_io_event (void *engine, 
+static void uiserver_io_event (void *engine,
                             gpgme_event_io_t type, void *type_data);
 
 
@@ -297,7 +296,7 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir)
 
   err = assuan_socket_connect (uiserver->assuan_ctx,
                               file_name ?
-                              file_name : _gpgme_get_uiserver_socket_path (),
+                              file_name : _gpgme_get_default_uisrv_socket (),
                               0, ASSUAN_SOCKET_SERVER_FDPASSING);
   if (err)
     goto leave;
@@ -309,8 +308,8 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir)
     {
       if (asprintf (&optstr, "OPTION display=%s", dft_display) < 0)
         {
+         err = gpg_error_from_syserror ();
          free (dft_display);
-         err = gpg_error_from_errno (errno);
          goto leave;
        }
       free (dft_display);
@@ -336,7 +335,7 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir)
        {
          if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0)
            {
-             err = gpg_error_from_errno (errno);
+             err = gpg_error_from_syserror ();
              goto leave;
            }
          err = assuan_transact (uiserver->assuan_ctx, optstr, NULL, NULL, NULL,
@@ -352,8 +351,8 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir)
            {
              if (asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype) < 0)
                {
+                 err = gpg_error_from_syserror ();
                  free (dft_ttytype);
-                 err = gpg_error_from_errno (errno);
                  goto leave;
                }
              free (dft_ttytype);
@@ -422,11 +421,11 @@ uiserver_set_locale (void *engine, int category, const char *value)
     return gpg_error (GPG_ERR_INV_VALUE);
 
   /* FIXME: Reset value to default.  */
-  if (!value) 
+  if (!value)
     return 0;
 
   if (asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0)
-    err = gpg_error_from_errno (errno);
+    err = gpg_error_from_syserror ();
   else
     {
       err = assuan_transact (uiserver->assuan_ctx, optstr, NULL, NULL,
@@ -453,9 +452,6 @@ uiserver_set_protocol (void *engine, gpgme_protocol_t protocol)
 }
 
 
-/* Forward declaration.  */
-static gpgme_status_code_t parse_status (const char *name);
-
 static gpgme_error_t
 uiserver_assuan_simple_command (assuan_context_t ctx, char *cmd,
                             engine_status_handler_t status_fnc,
@@ -498,7 +494,7 @@ uiserver_assuan_simple_command (assuan_context_t ctx, char *cmd,
          else
            *(rest++) = 0;
 
-         r = parse_status (line + 2);
+         r = _gpgme_parse_status (line + 2);
 
          if (r >= 0 && status_fnc)
            err = status_fnc (status_fnc_value, r, rest);
@@ -557,7 +553,7 @@ uiserver_set_fd (engine_uiserver_t uiserver, fd_type_t fd_type, const char *opt)
       int fds[2];
 
       if (_gpgme_io_pipe (fds, 0) < 0)
-       return gpg_error_from_errno (errno);
+       return gpg_error_from_syserror ();
 
       iocb_data->fd = dir ? fds[0] : fds[1];
       iocb_data->server_fd = dir ? fds[1] : fds[0];
@@ -620,27 +616,6 @@ map_data_enc (gpgme_data_t d)
 }
 
 
-static int
-status_cmp (const void *ap, const void *bp)
-{
-  const struct status_table_s *a = ap;
-  const struct status_table_s *b = bp;
-
-  return strcmp (a->name, b->name);
-}
-
-
-static gpgme_status_code_t
-parse_status (const char *name)
-{
-  struct status_table_s t, *r;
-  t.name = name;
-  r = bsearch (&t, status_table, DIM(status_table) - 1,
-              sizeof t, status_cmp);
-  return r ? r->code : -1;
-}
-
-
 static gpgme_error_t
 status_handler (void *opaque, int fd)
 {
@@ -682,7 +657,7 @@ status_handler (void *opaque, int fd)
          if (uiserver->status.fnc)
            err = uiserver->status.fnc (uiserver->status.fnc_value,
                                     GPGME_STATUS_EOF, "");
-         
+
          if (!err && uiserver->colon.fnc && uiserver->colon.any)
             {
               /* We must tell a colon function about the EOF. We do
@@ -719,11 +694,11 @@ status_handler (void *opaque, int fd)
            {
              char *newline = realloc (*aline, *alinelen + linelen + 1);
              if (!newline)
-               err = gpg_error_from_errno (errno);
+               err = gpg_error_from_syserror ();
              else
                {
                  *aline = newline;
-                 uiserver->colon.attic.linesize += linelen + 1;
+                 uiserver->colon.attic.linesize = *alinelen + linelen + 1;
                }
            }
          if (!err)
@@ -745,12 +720,12 @@ status_handler (void *opaque, int fd)
                      *dst = *src++;
                      (*alinelen)++;
                    }
-                 
+
                  if (*dst == '\n')
                    {
                      /* Terminate the pending line, pass it to the colon
                         handler and reset it.  */
-                     
+
                      uiserver->colon.any = 1;
                      if (*alinelen > 1 && *(dst - 1) == '\r')
                        dst--;
@@ -779,7 +754,7 @@ status_handler (void *opaque, int fd)
           char *src = line + 2;
          char *end = line + linelen;
          char *dst = src;
-          ssize_t nwritten;
+          gpgme_ssize_t nwritten;
 
           linelen = 0;
           while (src < end)
@@ -793,10 +768,10 @@ status_handler (void *opaque, int fd)
                 }
               else
                 *dst++ = *src++;
-              
+
               linelen++;
             }
-          
+
           src = line + 2;
           while (linelen > 0)
             {
@@ -804,7 +779,7 @@ status_handler (void *opaque, int fd)
               if (!nwritten || (nwritten < 0 && errno != EINTR)
                   || nwritten > linelen)
                 {
-                  err = gpg_error_from_errno (errno);
+                  err = gpg_error_from_syserror ();
                   break;
                 }
               src += nwritten;
@@ -820,14 +795,14 @@ status_handler (void *opaque, int fd)
        {
          char *rest;
          gpgme_status_code_t r;
-         
+
          rest = strchr (line + 2, ' ');
          if (!rest)
            rest = line + linelen; /* set to an empty string */
          else
            *(rest++) = 0;
 
-         r = parse_status (line + 2);
+         r = _gpgme_parse_status (line + 2);
 
          if (r >= 0)
            {
@@ -843,7 +818,7 @@ status_handler (void *opaque, int fd)
       else if (linelen >= 7
                && line[0] == 'I' && line[1] == 'N' && line[2] == 'Q'
                && line[3] == 'U' && line[4] == 'I' && line[5] == 'R'
-               && line[6] == 'E' 
+               && line[6] == 'E'
                && (line[7] == '\0' || line[7] == ' '))
         {
           char *keyword = line+7;
@@ -856,7 +831,7 @@ status_handler (void *opaque, int fd)
 
     }
   while (!err && assuan_pending_line (uiserver->assuan_ctx));
-         
+
   return err;
 }
 
@@ -968,7 +943,7 @@ _uiserver_decrypt (void *engine, int verify,
 
   if (asprintf (&cmd, "DECRYPT%s%s", protocol,
                verify ? "" : " --no-verify") < 0)
-    return gpg_error_from_errno (errno);
+    return gpg_error_from_syserror ();
 
   uiserver->input_cb.data = ciph;
   err = uiserver_set_fd (uiserver, INPUT_FD,
@@ -1020,7 +995,7 @@ set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[])
   linelen = 10 + 40 + 1;       /* "RECIPIENT " + guess + '\0'.  */
   line = malloc (10 + 40 + 1);
   if (!line)
-    return gpg_error_from_errno (errno);
+    return gpg_error_from_syserror ();
   strcpy (line, "RECIPIENT ");
   for (i=0; !err && recp[i]; i++)
     {
@@ -1040,9 +1015,9 @@ set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[])
          char *newline = realloc (line, newlen);
          if (! newline)
            {
-             int saved_errno = errno;
+             int saved_err = gpg_error_from_syserror ();
              free (line);
-             return gpg_error_from_errno (saved_errno);
+             return saved_err;
            }
          line = newline;
          linelen = newlen;
@@ -1095,7 +1070,7 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
       if (asprintf (&cmd, "PREP_ENCRYPT%s%s", protocol,
                    (flags & GPGME_ENCRYPT_EXPECT_SIGN)
                    ? " --expect-sign" : "") < 0)
-       return gpg_error_from_errno (errno);
+       return gpg_error_from_syserror ();
     }
   else
     {
@@ -1103,7 +1078,7 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
        return gpg_error (GPG_ERR_INV_VALUE);
 
       if (asprintf (&cmd, "ENCRYPT%s", protocol) < 0)
-       return gpg_error_from_errno (errno);
+       return gpg_error_from_syserror ();
     }
 
   if (plain)
@@ -1117,7 +1092,7 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
          return err;
        }
     }
-    
+
   if (ciph)
     {
       uiserver->output_cb.data = ciph;
@@ -1172,20 +1147,20 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
 
   if (asprintf (&cmd, "SIGN%s%s", protocol,
                (mode == GPGME_SIG_MODE_DETACH) ? " --detached" : "") < 0)
-    return gpg_error_from_errno (errno);
+    return gpg_error_from_syserror ();
 
   key = gpgme_signers_enum (ctx, 0);
   if (key)
     {
       const char *s = NULL;
-      
+
       if (key && key->uids)
         s = key->uids->email;
-      
+
       if (s && strlen (s) < 80)
         {
           char buf[100];
-          
+
           strcpy (stpcpy (buf, "SENDER --info "), s);
           err = uiserver_assuan_simple_command (uiserver->assuan_ctx, buf,
                                                 uiserver->status.fnc,
@@ -1194,7 +1169,7 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
       else
         err = gpg_error (GPG_ERR_INV_VALUE);
       gpgme_key_unref (key);
-      if (err) 
+      if (err)
       {
        free (cmd);
        return err;
@@ -1247,7 +1222,7 @@ uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
     return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
 
   if (asprintf (&cmd, "VERIFY%s", protocol) < 0)
-    return gpg_error_from_errno (errno);
+    return gpg_error_from_syserror ();
 
   uiserver->input_cb.data = sig;
   err = uiserver_set_fd (uiserver, INPUT_FD,
@@ -1281,7 +1256,7 @@ uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
 
 static void
 uiserver_set_status_handler (void *engine, engine_status_handler_t fnc,
-                         void *fnc_value) 
+                         void *fnc_value)
 {
   engine_uiserver_t uiserver = engine;
 
@@ -1292,7 +1267,7 @@ uiserver_set_status_handler (void *engine, engine_status_handler_t fnc,
 
 static gpgme_error_t
 uiserver_set_colon_line_handler (void *engine, engine_colon_line_handler_t fnc,
-                             void *fnc_value) 
+                             void *fnc_value)
 {
   engine_uiserver_t uiserver = engine;
 
@@ -1327,7 +1302,7 @@ uiserver_io_event (void *engine, gpgme_event_io_t type, void *type_data)
 struct engine_ops _gpgme_engine_ops_uiserver =
   {
     /* Static functions.  */
-    _gpgme_get_uiserver_socket_path,
+    _gpgme_get_default_uisrv_socket,
     NULL,
     uiserver_get_version,
     uiserver_get_req_version,
@@ -1363,5 +1338,8 @@ struct engine_ops _gpgme_engine_ops_uiserver =
     uiserver_set_io_cbs,
     uiserver_io_event,
     uiserver_cancel,
-    NULL               /* cancel_op */
+    NULL,              /* cancel_op */
+    NULL,               /* passwd */
+    NULL,                /* set_pinentry_mode */
+    NULL                /* opspawn */
   };