assuan interface for gpgme

Werner Koch wk at gnupg.org
Wed Feb 18 17:00:23 CET 2009


On Wed, 18 Feb 2009 12:02, marcus.brinkmann at ruhr-uni-bochum.de said:

>>     err = sendfnc (sendfnc_value, my_data, my_datalen);
>
> I think we should use a gpgme_assuan_send function that does the dispatch to
> the sendfnc.  We use user provided function pointers in the interface, but

I considered that but it has the drawback that we need, more or less, to
expose the assuan interface.  Another option I considered was to either
pass the gpgme context to the callback or some opaque data to be passed
to an gpgme_assuan_send_data_from_inq function.

> well, and I don't think that's necessary.  One reason is that this way we can
> catch all calls into GPGME with a regex breakpoint on gpgme_*.

Good point.  Given that there may only be one inquire going on per gpgme
context, what about changing the calllback to:

  typedef gpgme_error_t (*gpgme_assuan_inquire_cb_t)
       (void *opaque, const char *name, const char *args,
        gpgme_ctx_t ctx); 

and a 

  gpgme_op_assuan_send_inq_data (...)

which takes the context and may check that it has been called from an
inq callback.

> Instead, the user could indicate if there is more data to be returned by
> setting a flag in a return value slot, and GPGME can keep calling the inquire
> callback when sending data is possible until the user is satisfied.

That would complicate the data flow and make an inquire callback pretty
unreadable.  We need to allow calling a send function as often as
needed.

> If we also provide a buffer for the user to fill, then no send callback is
> necessary.

That makes it hard to use.  You don't know beforehand how much data to
send back.  For example a requested certificate my be just a few hundred
bytes of 100kb in the case of PGP.

>>     err = gpgme_op_assuan_result (ctx);
>> 
>> which returns 0 for the 'OK' line and an gpg-error code for the 'ERR
>> <n>' line.
>
> For consistency and extensibility, we should return a struct, just as with all

I don't see a reason for extensibility because the protocol defines that
there is just a retrun value of OK or ERR which can all be represented
by an integer (famous last 640k-are-enough words)

  if (!err)
    {
      s = gpgme_op_assuan_result (ctx);
      err = s? s->err : gpg_error (GPG_ERR_BUG);
    }

is a lot of unneeded code.  The question is more whether we need a
separate error code at all for syncronous operations: Folding it into
the error code returned by gpgmg_op_assuan_transact would make things
even easier.  If there is need to check whetehr it is an application
error or a gpgme error, a test with gpg_err_source (err) ==
GPG_ERR_SORUC$E_GPGME would do the trick.  In fact the code I wrote
until now always did:

      err = gpgme_op_assuan_transact ();
      if (!err)
        err = gpgme_op_assuan_result ();

and thus not distinguish between the errors.  Usuallay you expect
success or a few well defined error codes, everyhing else is a severe
error and most likely you will close or reset the context in response.

Thus my proposal would be to keep the result function as it is now and
change the syncronous version of gpgme_op_assuan_transact to return the
application error directly.


> We should add a gpgme_op_assuan_end function, as we have for keylistings.  No
> need to trash a perfectly reasonably context to disconnect.

A new gpgme_reset could be used to reuse a context.  Pretty easy to
implement, given that we already have a _gpgme_op_reset.


> need to have this mechanism: Options can be passed as assuan commands using
> transact the normal way, that's the whole purpose of the protocol.  Using

I was think not thinking about application option but those required to
operate a certain socket.

> convenience behavior as well.  My preference however would be to just require
> home_dir to be NULL at all times, and to not have any default commands, and
> instead provide a convenience function
>
> gpgme_error_t gpgme_op_assuan_init_gpg_agent (ctx);

That is very special for the gpg-agent.  Right the option I suggested is
also special for the gpg-agent (due to PINENTRY_LAUNCHED) but it is not
codified in the API and on the same semantic level as the name of the
socket.

> way there is no inconsistency and no difficulty in understanding and extending
> the interface.  This also avoids sending commands at connection time, which is
> good for reliability in the asynchronous variant (in case the server blocks
> errornously).

We have quite a couple of hacks in gpgme to cope with special
requirements of GnuPG.  I don't see the gpgme_op_assuan family as a
replacement for libassuan. it is merely a convenience API which allows
us to re-use code we already have in gpgme in case an application
requires services from GnuPG which are not implemented by gpgme proper.

We are expecting well behaving servers and frankly a buggy server my
block at any time not just right after a completed command transaction.
In fact that is even more likely due to the size of the OS buffers.



Salam-Shalom,

   Werner

-- 
Die Gedanken sind frei.  Auschnahme regelt ein Bundeschgesetz.




More information about the Gnupg-devel mailing list