strange gpgme owner trust bug [long, sorry]

Albrecht Dreß albrecht.dress@arcor.de
Thu Jul 10 19:41:03 2003


--Yylu36WmvOXNoKYn
Content-Type: multipart/mixed; boundary="Dxnq1zWXvFF0Q93v"
Content-Disposition: inline


--Dxnq1zWXvFF0Q93v
Content-Type: text/plain; format=flowed; charset=ISO-8859-15
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hi all,

I have a strange problem retreiving the owner trust field from a key using=
=20
gpgme 0.3.15.

Usually, after checking a signed file using gpgme_op_verify(), the field=20
is returned correctly for the signer's key. When I sign something in the=20
same application using gpgme_op_sign(), and then check any signed file=20
again, the owner trust returned is *always* 0.

To illustrate this, I attach a minimal test case which I compiled using

gcc -Wall gpgme_test.c -o gpgme_test `gpgme-config --libs`

Now create a small text file (e.g. "TEST") and sign it with your private=20
key (which you should trust ultimately) using

gpg --clearsign -a TEST

The test program is run using the signed file, some other file, plus your=
=20
secret key id. It checks the file from arg #1 and dumps a few information=
=20
about the key, signs file arg #2 with key arg #3 (you must enter the pass=
=20
phrase), and then repeats the signature check of file #1:

linux > ./gpgme_test TEST.asc gpgme_test.c '<your-email@provider.xy>'
get_sig_info_from_ctx: key results
         name =3D removed
         email =3D removed
         validity =3D 5
         owner trust =3D 5
sign_file
ENTER
xxxxxxxxxxxxxxxx removed
xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xx x
<correct passphrase entered>
get_sig_info_from_ctx: key results
         name =3D removed
         email =3D removed
         validity =3D 5
         owner trust =3D 0

The owner trust changed, which is obviously wrong... I see this effect on=
=20
a Intel/SuSE 7.2 box running gpg 1.2.2 and on a Yellowdog (PowerPC) Linux=
=20
running gpg 1.2.3.

Is this a bug? Feature? Bad test program? Any other ideas?

Cheers, Albrecht.

--=20
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Albrecht Dre=DF  -  Johanna-Kirchner-Stra=DFe 13  -  D-53123 Bonn (German=
y)
        Phone (+49) 228 6199571  -  mailto:albrecht.dress@arcor.de
_________________________________________________________________________
--Dxnq1zWXvFF0Q93v
Content-Type: text/x-c; charset=us-ascii
Content-Disposition: attachment; filename="gpgme_test.c"

#include <gpgme.h>
#include <stdio.h>

static void check_file_sig(const char * filename);
static void get_sig_info_from_ctx(GpgmeCtx ctx);
void sign_file(const char *filename, const char * signer);
const char * get_pass(void * hook, const char * desc, void ** r_hd);

int
main(int argc, char **argv)
{
  if (argc < 4) {
    fprintf(stderr, "usage: %s <signed file> <file to sign> <signer>\n", argv[0]);
    return 1;
  }

  gpgme_check_version(NULL);

  check_file_sig(argv[1]);
  sign_file(argv[2], argv[3]);
  check_file_sig(argv[1]);

  return 0;
}


static void
check_file_sig(const char * filename)
{
  GpgmeError err;
  GpgmeCtx ctx;
  GpgmeData sig, out;
  GpgmeSigStat status;

  gpgme_new(&ctx);
    
  if ((err = gpgme_data_new_from_file(&sig, filename, 1)) != GPGME_No_Error) {
    fprintf(stderr, "gpgme could not get data from file: %s\n", gpgme_strerror(err));
    exit(1);
  }
  gpgme_data_new(&out);
    
  if ((err = gpgme_op_verify(ctx, sig, out, &status)) != GPGME_No_Error) {
    fprintf(stderr, "gpgme signature verification failed: %s\n", gpgme_strerror(err));
    exit(1);
  } else
    get_sig_info_from_ctx(ctx);

  gpgme_data_release(sig);
  gpgme_data_release(out);
  gpgme_release(ctx);
}


static void
get_sig_info_from_ctx(GpgmeCtx ctx)
{
  GpgmeKey key;
	
  gpgme_get_sig_key(ctx, 0, &key);
  printf("%s: key results\n\tname = %s\n\temail = %s\n\tvalidity = %lu\n"
	 "\towner trust = %lu\n",
	 __FUNCTION__,
	 gpgme_key_get_string_attr(key, GPGME_ATTR_NAME, NULL, 0),
	 gpgme_key_get_string_attr(key, GPGME_ATTR_EMAIL, NULL, 0),
	 gpgme_key_get_ulong_attr(key, GPGME_ATTR_VALIDITY, NULL, 0),
	 gpgme_key_get_ulong_attr(key, GPGME_ATTR_OTRUST, NULL, 0));
  gpgme_key_unref(key);
}


const char *
get_pass(void * hook, const char * desc, void ** r_hd)
{
  static char pb_buf[256];
  int len;

  if (!desc)
    return NULL;

  printf("%s\n", desc);
  fgets(pb_buf, 255, stdin);
  len = strlen(pb_buf);
  while (len && pb_buf[len - 1] < ' ') {
    len--;
    pb_buf[len] = '\0';
  }
  return pb_buf;
}


void
sign_file(const char *filename, const char * signer)
{
  GpgmeCtx ctx;
  GpgmeError err;
  GpgmeKey key;
  GpgmeData in, out;
  
  printf("%s\n", __FUNCTION__);

  gpgme_new(&ctx);
	    
  gpgme_op_keylist_start(ctx, signer, 1);
  if (gpgme_op_keylist_next(ctx, &key) == GPGME_EOF) {
    fprintf(stderr, "could not find secret key for %s\n", signer);
    exit(1);
  }
  gpgme_signers_add(ctx, key);
  gpgme_key_unref(key);
  gpgme_op_keylist_end(ctx);
  
  gpgme_set_armor(ctx, 1);
  gpgme_set_passphrase_cb(ctx, get_pass, NULL);
  if ((err = gpgme_data_new_from_file(&in, filename, 1)) != GPGME_No_Error) {
    fprintf(stderr, "gpgme could not get data from file: %s\n", gpgme_strerror(err));
    exit(1);
  }
  gpgme_data_new(&out);
  if ((err = gpgme_op_sign(ctx, in, out, GPGME_SIG_MODE_CLEAR)) != GPGME_No_Error) {
    fprintf(stderr, "signing failed: %s\n", gpgme_strerror(err));
    exit(1);
  }

  gpgme_data_release(in);
  gpgme_data_release(out);
  gpgme_release(ctx);
}

--Dxnq1zWXvFF0Q93v--

--Yylu36WmvOXNoKYn
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQA/DaWSn/9unNAn/9ERAoFNAKCkQVQ1tWklvA/3dXLUSPWjPVrH2wCgvBmx
HAl52CfREudOMRlkzPkVi4g=
=cO4q
-----END PGP SIGNATURE-----

--Yylu36WmvOXNoKYn--