Beispiel #1
0
/* Return a certificate ID.  These are the last 4 bytes of the SHA-1
   fingerprint.  If R_HIGH is not NULL the next 4 bytes are stored
   there. */
unsigned long
gpgsm_get_short_fingerprint (ksba_cert_t cert, unsigned long *r_high)
{
  unsigned char digest[20];

  gpgsm_get_fingerprint (cert, GCRY_MD_SHA1, digest, NULL);
  if (r_high)
    *r_high = buf32_to_ulong (digest+12);
  return buf32_to_ulong (digest + 16);
}
/****************
 * read the record with number recnum
 * returns: -1 on error, 0 on success
 */
int
tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
{
    byte readbuf[TRUST_RECORD_LEN];
    const byte *buf, *p;
    gpg_error_t err = 0;
    int n, i;

    if( db_fd == -1 )
	open_db();
    buf = get_record_from_cache( recnum );
    if( !buf ) {
	if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
            err = gpg_error_from_syserror ();
	    log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) );
	    return err;
	}
	n = read( db_fd, readbuf, TRUST_RECORD_LEN);
	if( !n ) {
	    return -1; /* eof */
	}
	else if( n != TRUST_RECORD_LEN ) {
            err = gpg_error_from_syserror ();
	    log_error(_("trustdb: read failed (n=%d): %s\n"), n,
							strerror(errno) );
	    return err;
	}
	buf = readbuf;
    }
    rec->recnum = recnum;
    rec->dirty = 0;
    p = buf;
    rec->rectype = *p++;
    if( expected && rec->rectype != expected ) {
	log_error("%lu: read expected rec type %d, got %d\n",
		    recnum, expected, rec->rectype );
	return gpg_error (GPG_ERR_TRUSTDB);
    }
    p++;    /* skip reserved byte */
    switch( rec->rectype ) {
      case 0:  /* unused (free) record */
	break;
      case RECTYPE_VER: /* version record */
	if( memcmp(buf+1, "gpg", 3 ) ) {
	    log_error( _("%s: not a trustdb file\n"), db_name );
	    err = gpg_error (GPG_ERR_TRUSTDB);
	}
	p += 2; /* skip "gpg" */
	rec->r.ver.version  = *p++;
	rec->r.ver.marginals = *p++;
	rec->r.ver.completes = *p++;
	rec->r.ver.cert_depth = *p++;
	rec->r.ver.trust_model = *p++;
	rec->r.ver.min_cert_level = *p++;
	p += 2;
	rec->r.ver.created  = buf32_to_ulong (p); p += 4;
	rec->r.ver.nextcheck = buf32_to_ulong (p); p += 4;
	p += 4;
	p += 4;
	rec->r.ver.firstfree =buf32_to_ulong (p); p += 4;
	p += 4;
	rec->r.ver.trusthashtbl =buf32_to_ulong (p); p += 4;
	if( recnum ) {
	    log_error( _("%s: version record with recnum %lu\n"), db_name,
							     (ulong)recnum );
	    err = gpg_error (GPG_ERR_TRUSTDB);
	}
	else if( rec->r.ver.version != 3 ) {
	    log_error( _("%s: invalid file version %d\n"), db_name,
							rec->r.ver.version );
	    err = gpg_error (GPG_ERR_TRUSTDB);
	}
	break;
      case RECTYPE_FREE:
	rec->r.free.next  = buf32_to_ulong (p); p += 4;
	break;
      case RECTYPE_HTBL:
	for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
	    rec->r.htbl.item[i] = buf32_to_ulong (p); p += 4;
	}
	break;
      case RECTYPE_HLST:
	rec->r.hlst.next = buf32_to_ulong (p); p += 4;
	for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
	    rec->r.hlst.rnum[i] = buf32_to_ulong (p); p += 4;
	}
	break;
      case RECTYPE_TRUST:
	memcpy( rec->r.trust.fingerprint, p, 20); p+=20;
        rec->r.trust.ownertrust = *p++;
        rec->r.trust.depth = *p++;
        rec->r.trust.min_ownertrust = *p++;
        p++;
	rec->r.trust.validlist = buf32_to_ulong (p); p += 4;
	break;
      case RECTYPE_VALID:
	memcpy( rec->r.valid.namehash, p, 20); p+=20;
        rec->r.valid.validity = *p++;
	rec->r.valid.next = buf32_to_ulong (p); p += 4;
	rec->r.valid.full_count = *p++;
	rec->r.valid.marginal_count = *p++;
	break;
      default:
	log_error( "%s: invalid record type %d at recnum %lu\n",
				   db_name, rec->rectype, (ulong)recnum );
	err = gpg_error (GPG_ERR_TRUSTDB);
	break;
    }

    return err;
}
Beispiel #3
0
/*
 * Migrate the trustdb as just up to gpg 1.0.6 (trustdb version 2)
 * to the 2.1 version as used with 1.0.6b - This is pretty trivial as needs
 * only to scan the tdb and insert new the new trust records.  The old ones are
 * obsolte from now on
 */
static void
migrate_from_v2 ()
{
  TRUSTREC rec;
  int i, n;
  struct {
    ulong keyrecno;
    byte  ot;
    byte okay;
    byte  fpr[20];
  } *ottable;
  int ottable_size, ottable_used;
  byte oldbuf[40];
  ulong recno;
  int rc, count;

  ottable_size = 5;
  ottable = xmalloc (ottable_size * sizeof *ottable);
  ottable_used = 0;

  /* We have some restrictions here.  We can't use the version record
   * and we can't use any of the old hashtables because we dropped the
   * code.  So we first collect all ownertrusts and then use a second
   * pass fo find the associated keys.  We have to do this all without using
   * the regular record read functions.
   */

  /* get all the ownertrusts */
  if (lseek (db_fd, 0, SEEK_SET ) == -1 )
      log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno));
  for (recno=0;;recno++)
    {
      do
        n = read (db_fd, oldbuf, 40);
      while (n==-1 && errno == EINTR);
      if (!n)
        break; /* eof */
      if (n != 40)
        log_fatal ("migrate_vfrom_v2: read error or short read\n");

      if (*oldbuf != 2)
        continue;

      /* v2 dir record */
      if (ottable_used == ottable_size)
        {
          ottable_size += 1000;
          ottable = xrealloc (ottable, ottable_size * sizeof *ottable);
        }
      ottable[ottable_used].keyrecno = buf32_to_ulong (oldbuf+6);
      ottable[ottable_used].ot = oldbuf[18];
      ottable[ottable_used].okay = 0;
      memset (ottable[ottable_used].fpr,0, 20);
      if (ottable[ottable_used].keyrecno && ottable[ottable_used].ot)
        ottable_used++;
    }
  log_info ("found %d ownertrust records\n", ottable_used);

  /* Read again and find the fingerprints */
  if (lseek (db_fd, 0, SEEK_SET ) == -1 )
      log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno));
  for (recno=0;;recno++)
    {
      do
        n = read (db_fd, oldbuf, 40);
      while (n==-1 && errno == EINTR);
      if (!n)
        break; /* eof */
      if (n != 40)
        log_fatal ("migrate_from_v2: read error or short read\n");

      if (*oldbuf != 3)
        continue;

      /* v2 key record */
      for (i=0; i < ottable_used; i++)
        {
          if (ottable[i].keyrecno == recno)
            {
              memcpy (ottable[i].fpr, oldbuf+20, 20);
              ottable[i].okay = 1;
              break;
            }
        }
    }

  /* got everything - create the v3 trustdb */
  if (ftruncate (db_fd, 0))
    log_fatal ("can't truncate `%s': %s\n", db_name, strerror (errno) );
  if (create_version_record ())
    log_fatal ("failed to recreate version record of `%s'\n", db_name);

  /* access the hash table, so it is store just after the version record,
   * this is not needed put a dump is more pretty */
  get_trusthashrec ();

  /* And insert the old ownertrust values */
  count = 0;
  for (i=0; i < ottable_used; i++)
    {
      if (!ottable[i].okay)
        continue;

      memset (&rec, 0, sizeof rec);
      rec.recnum = tdbio_new_recnum ();
      rec.rectype = RECTYPE_TRUST;
      memcpy(rec.r.trust.fingerprint, ottable[i].fpr, 20);
      rec.r.trust.ownertrust = ottable[i].ot;
      if (tdbio_write_record (&rec))
        log_fatal ("failed to write trust record of `%s'\n", db_name);
      count++;
    }

  revalidation_mark ();
  rc = tdbio_sync ();
  if (rc)
    log_fatal ("failed to sync `%s'\n", db_name);
  log_info ("migrated %d version 2 ownertrusts\n", count);
  xfree (ottable);
}
static ulong
get32 (const byte *buffer)
{
  return buf32_to_ulong (buffer);
}
Beispiel #5
0
/* Fetch the next certificate. Return 0 on success, GPG_ERR_EOF if no
   (more) certificates are available or any other error
   code. GPG_ERR_TRUNCATED may be returned to indicate that the result
   has been truncated. */
gpg_error_t
fetch_next_cert_ldap (cert_fetch_context_t context,
                      unsigned char **value, size_t *valuelen)
{
  gpg_error_t err;
  unsigned char hdr[5];
  char *p, *pend;
  unsigned long n;
  int okay = 0;
  /* int is_cms = 0; */

  *value = NULL;
  *valuelen = 0;

  err = 0;
  while (!err)
    {
      err = read_buffer (context->reader, hdr, 5);
      if (err)
        break;
      n = buf32_to_ulong (hdr+1);
      if (*hdr == 'V' && okay)
        {
#if 0  /* That code is not yet ready.  */

          if (is_cms)
            {
              /* The certificate needs to be parsed from CMS data. */
              ksba_cms_t cms;
              ksba_stop_reason_t stopreason;
              int i;

              err = ksba_cms_new (&cms);
              if (err)
                goto leave;
              err = ksba_cms_set_reader_writer (cms, context->reader, NULL);
              if (err)
                {
                  log_error ("ksba_cms_set_reader_writer failed: %s\n",
                             gpg_strerror (err));
                  goto leave;
                }

              do
                {
                  err = ksba_cms_parse (cms, &stopreason);
                  if (err)
                    {
                      log_error ("ksba_cms_parse failed: %s\n",
                                 gpg_strerror (err));
                      goto leave;
                    }

                  if (stopreason == KSBA_SR_BEGIN_DATA)
                    log_error ("userSMIMECertificate is not "
                               "a certs-only message\n");
                }
              while (stopreason != KSBA_SR_READY);

              for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
                {
                  check_and_store (ctrl, stats, cert, 0);
                  ksba_cert_release (cert);
                  cert = NULL;
                }
              if (!i)
                log_error ("no certificate found\n");
              else
                any = 1;
            }
          else
#endif
            {
              *value = xtrymalloc (n);
              if (!*value)
                return gpg_error_from_errno (errno);
              *valuelen = n;
              err = read_buffer (context->reader, *value, n);
              break; /* Ready or error.  */
            }
        }
      else if (!n && *hdr == 'A')
        okay = 0;
      else if (n)
        {
          if (n > context->tmpbufsize)
            {
              xfree (context->tmpbuf);
              context->tmpbufsize = 0;
              context->tmpbuf = xtrymalloc (n+1);
              if (!context->tmpbuf)
                return gpg_error_from_errno (errno);
              context->tmpbufsize = n;
            }
          err = read_buffer (context->reader, context->tmpbuf, n);
          if (err)
            break;
          if (*hdr == 'A')
            {
              p = context->tmpbuf;
              p[n] = 0; /*(we allocated one extra byte for this.)*/
              /* fixme: is_cms = 0; */
              if ( (pend = strchr (p, ';')) )
                *pend = 0; /* Strip off the extension. */
              if (!ascii_strcasecmp (p, USERCERTIFICATE))
                {
                  if (DBG_LOOKUP)
                    log_debug ("fetch_next_cert_ldap: got attribute '%s'\n",
                               USERCERTIFICATE);
                  okay = 1;
                }
              else if (!ascii_strcasecmp (p, CACERTIFICATE))
                {
                  if (DBG_LOOKUP)
                    log_debug ("fetch_next_cert_ldap: got attribute '%s'\n",
                               CACERTIFICATE);
                  okay = 1;
                }
              else if (!ascii_strcasecmp (p, X509CACERT))
                {
                  if (DBG_LOOKUP)
                    log_debug ("fetch_next_cert_ldap: got attribute '%s'\n",
                               CACERTIFICATE);
                  okay = 1;
                }
/*               else if (!ascii_strcasecmp (p, USERSMIMECERTIFICATE)) */
/*                 { */
/*                   if (DBG_LOOKUP) */
/*                     log_debug ("fetch_next_cert_ldap: got attribute '%s'\n", */
/*                                USERSMIMECERTIFICATE); */
/*                   okay = 1; */
/*                   is_cms = 1; */
/*                 } */
              else
                {
                  if (DBG_LOOKUP)
                    log_debug ("fetch_next_cert_ldap: got attribute '%s'"
                               " -  ignored\n", p);
                  okay = 0;
                }
            }
          else if (*hdr == 'E')
            {
              p = context->tmpbuf;
              p[n] = 0; /*(we allocated one extra byte for this.)*/
              if (!strcmp (p, "truncated"))
                {
                  context->truncated = 1;
                  log_info (_("ldap_search hit the size limit of"
                              " the server\n"));
                }
            }
        }
    }

  if (err)
    {
      xfree (*value);
      *value = NULL;
      *valuelen = 0;
      if (gpg_err_code (err) == GPG_ERR_EOF && context->truncated)
        {
          context->truncated = 0; /* So that the next call would return EOF. */
          err = gpg_error (GPG_ERR_TRUNCATED);
        }
    }

  return err;
}