* trustlist.c: New.
authorWerner Koch <wk@gnupg.org>
Tue, 15 Jan 2002 13:01:52 +0000 (13:01 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 15 Jan 2002 13:01:52 +0000 (13:01 +0000)
* command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted): New.

agent/ChangeLog
agent/Makefile.am
agent/agent.h
agent/command.c
agent/trustlist.c [new file with mode: 0644]

index 41ea89f..9c66e22 100644 (file)
@@ -1,3 +1,8 @@
+2002-01-15  Werner Koch  <wk@gnupg.org>
+
+       * trustlist.c: New.
+       * command.c (cmd_istrusted, cmd_listtrusted, cmd_marktrusted): New.
+
 2002-01-07  Werner Koch  <wk@gnupg.org>
 
        * genkey.c: Store the secret part and return the public part.
index 6b05183..68ee4c7 100644 (file)
@@ -31,7 +31,8 @@ gpg_agent_SOURCES = \
        findkey.c \
        pksign.c \
        pkdecrypt.c \
-       genkey.c 
+       genkey.c \
+       trustlist.c 
 
 gpg_agent_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a  \
                ../common/libcommon.a $(LIBGCRYPT_LIBS)
index b3e18c6..9f2b69c 100644 (file)
@@ -109,6 +109,10 @@ int agent_pkdecrypt (CTRL ctrl, const char *ciphertext, size_t ciphertextlen,
 int agent_genkey (CTRL ctrl,
                   const char *keyparam, size_t keyparmlen, FILE *outfp);
 
+/*-- trustlist.c --*/
+int agent_istrusted (const char *fpr);
+int agent_listtrusted (void *assuan_context);
+
 
 
 #endif /*AGENT_H*/
index b1357ce..9d9c7a0 100644 (file)
@@ -64,6 +64,62 @@ reset_notify (ASSUAN_CONTEXT ctx)
   ctrl->digest.valuelen = 0;
 }
 
+/* ISTRUSTED <hexstring_with_fingerprint>
+
+   Return OK when we have an entry with this fingerprint in our
+   trustlist */
+static int
+cmd_istrusted (ASSUAN_CONTEXT ctx, char *line)
+{
+  int rc, n, i;
+  char *p;
+  char fpr[41];
+
+  /* parse the fingerprint value */
+  for (p=line,n=0; hexdigitp (p); p++, n++)
+    ;
+  if (*p || !(n == 40 || n == 32))
+    return set_error (Parameter_Error, "invalid fingerprint");
+  i = 0;
+  if (n==32)
+    {
+      strcpy (fpr, "00000000");
+      i += 8;
+    }
+  for (p=line; i < 40; p++, i++)
+    fpr[i] = *p >= 'a'? (*p & 0xdf): *p;
+  fpr[i] = 0;
+  rc = agent_istrusted (fpr);
+  if (!rc)
+    return 0;
+  else if (rc == -1)
+    return ASSUAN_Not_Trusted;
+  else
+    return map_to_assuan_status (rc);
+}
+
+/* LISTTRUSTED 
+
+   List all entries from the trustlist */
+static int
+cmd_listtrusted (ASSUAN_CONTEXT ctx, char *line)
+{
+  return map_to_assuan_status (agent_listtrusted (ctx));
+}
+
+
+/* MARKTRUSTED <hexstring_with_fingerprint> <flag>
+
+   Store a new key in into the trustlist*/
+static int
+cmd_marktrusted (ASSUAN_CONTEXT ctx, char *line)
+{
+  return ASSUAN_Not_Implemented;
+}
+
+
+
+\f
 /* SIGKEY <hexstring_with_keygrip>
    SETKEY <hexstring_with_keygrip>
   
@@ -272,6 +328,7 @@ register_commands (ASSUAN_CONTEXT ctx)
     int cmd_id;
     int (*handler)(ASSUAN_CONTEXT, char *line);
   } table[] = {
+    { "ISTRUSTED",  0,  cmd_istrusted },
     { "SIGKEY",     0,  cmd_sigkey },
     { "SETKEY",     0,  cmd_sigkey },
     { "SETHASH",    0,  cmd_sethash },
@@ -280,6 +337,8 @@ register_commands (ASSUAN_CONTEXT ctx)
     { "GENKEY",     0,  cmd_genkey },
     { "GET_PASSPHRASE",0, cmd_get_passphrase },
     { "CLEAR_PASSPHRASE",0, cmd_clear_passphrase },
+    { "LISTTRUSTED",  0,  cmd_listtrusted },
+    { "MARKTRUSTED",  0,  cmd_marktrusted },
     { "",     ASSUAN_CMD_INPUT, NULL }, 
     { "",     ASSUAN_CMD_OUTPUT, NULL }, 
     { NULL }
diff --git a/agent/trustlist.c b/agent/trustlist.c
new file mode 100644 (file)
index 0000000..222d2dc
--- /dev/null
@@ -0,0 +1,227 @@
+/* trustlist.c - Maintain the list of trusted keys
+ *     Copyright (C) 2002 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "agent.h"
+#include "../assuan/assuan.h" /* fixme: nned a way to avoid assuna
+                                 calls here */
+
+static const char headerblurb[] =
+"# This is the list of trusted keys.  Comments like this one and empty\n"
+"# lines are allowed but keep in mind that the entire file is integrity\n"
+"# protected by the use of a MAC, so changing the file does not make\n"
+"# much sense without the knowledge of the MAC key.  Lines do have a\n"
+"# length limit but this is not serious limitation as the format of the\n"
+"# entries is fixed and checked by gpg-agent: A non-comment line starts\n"
+"# with optional white spaces, followed by exactly 40 hex character,\n"
+"# optioanlly followed by a flag charcter which my either be 'P', 'S'\n"
+"# or '*'. Additional data delimited with by a white space is ignored.\n"
+"\n";
+
+
+static FILE *trustfp;
+
+
+static int
+open_list (void)
+{
+  char *fname;
+
+  fname = make_filename (opt.homedir, "trustlist.txt", NULL);
+  trustfp = fopen (fname, "r");
+  if (!trustfp && errno == ENOENT)
+    {
+      trustfp = fopen (fname, "wx");
+      if (!trustfp)
+        {
+          log_error ("can't create `%s': %s\n", fname, strerror (errno));
+          xfree (fname);
+          return seterr (File_Create_Error);
+        }
+      fputs (headerblurb, trustfp);
+      fclose (trustfp);
+      trustfp = fopen (fname, "r");
+    }
+
+  if (!trustfp)
+    {
+      log_error ("can't open `%s': %s\n", fname, strerror (errno));
+      xfree (fname);
+      return seterr (File_Open_Error);
+    }
+
+  /*FIXME: check the MAC */
+
+  return 0;
+}
+
+
+
+/* Read the trustlist and return entry by entry.  KEY must point to a
+   buffer of at least 41 characters. KEYFLAG does return either 'P',
+   'S' or '*'.
+
+   Reading a valid entry return 0, EOF returns -1 any other error
+   returns the appropriate error code. */
+static int
+read_list (char *key, int *keyflag)
+{
+  int rc;
+  int c, i;
+  char *p, line[256];
+  
+  if (!trustfp)
+    {
+      rc = open_list ();
+      if (rc)
+        return rc;
+    }
+
+  do
+    {
+      if (!fgets (line, DIM(line)-1, trustfp) )
+        {
+          if (feof (trustfp))
+            return -1;
+          return GNUPG_Read_Error;
+        }
+      
+      if (!*line || line[strlen(line)-1] != '\n')
+        {
+          /* eat until end of line */
+          while ( (c=getc (trustfp)) != EOF && c != '\n')
+            ;
+          return *line? GNUPG_Line_Too_Long: GNUPG_Incomplete_Line;
+        }
+      
+      /* Allow for emty lines and spaces */
+      for (p=line; spacep (p); p++)
+        ;
+    }
+  while (!*p || *p == '\n' || *p == '#');
+  
+  for (i=0; hexdigitp (p+i) && i < 40; i++)
+    key[i] = p[i] >= 'a'? (p[i] & 0xdf): p[i];
+  key[i] = 0;
+  if (i!=40 || !(spacep (p+i) || p[i] == '\n'))
+    {
+      log_error ("invalid formatted fingerprint in trustlist\n");
+      return GNUPG_Bad_Data;
+    }
+  assert (p[i]);
+  if (p[i] == '\n')
+    *keyflag = '*';
+  else 
+    {
+      i++;
+      if ( p[i] == 'P' || p[i] == 'p')
+        *keyflag = 'P';
+      else if ( p[i] == 'S' || p[i] == 's')
+        *keyflag = 'S';
+      else if ( p[i] == '*')
+        *keyflag = '*';
+      else
+        {
+          log_error ("invalid keyflag in trustlist\n");
+          return GNUPG_Bad_Data;
+        }
+      i++;
+      if ( !(spacep (p+i) || p[i] == '\n'))
+        {
+          log_error ("invalid keyflag in trustlist\n");
+          return GNUPG_Bad_Data;
+        }
+    }
+
+  return 0;
+}
+
+/* check whether the given fr is in our trustdb.  We expect FPR to be
+   an all uppercase hexstring of 40 characters. */
+int 
+agent_istrusted (const char *fpr)
+{
+  int rc;
+  static char key[41];
+  int keyflag;
+
+  if (trustfp)
+    rewind (trustfp);
+  while (!(rc=read_list (key, &keyflag)))
+    {
+      if (!strcmp (key, fpr))
+        return 0;
+    }
+  if (rc != -1)
+    {
+      /* error in the trustdb - close it to give the user a chance for
+         correction */
+      fclose (trustfp);
+      trustfp = NULL;
+    }
+  return rc;
+}
+
+
+/* write all trust entries to FP */
+int 
+agent_listtrusted (void *assuan_context)
+{
+  int rc;
+  static char key[51];
+  int keyflag;
+
+  if (trustfp)
+    rewind (trustfp);
+  while (!(rc=read_list (key, &keyflag)))
+    {
+      key[40] = ' ';
+      key[41] = keyflag;
+      key[42] = '\n';
+      assuan_send_data (assuan_context, key, 43);
+      assuan_send_data (assuan_context, NULL, 0); /* flush */
+    } 
+  if (rc == -1)
+    rc = 0;
+  if (rc)
+    {
+      /* error in the trustdb - close it to give the user a chance for
+         correction */
+      fclose (trustfp);
+      trustfp = NULL;
+    }
+  return rc;
+}
+
+
+
+
+
+
+