2009-10-22 Marcus Brinkmann <marcus@g10code.de>
* configure.ac: Add support for G13. src/ 2009-10-22 Marcus Brinkmann <marcus@g10code.de> * Makefile.am: Remove @NETLIBS@ from LIBADDs. (g13_components): New variable. (main_sources): Add $(g13_components). * g13.c, engine-g13.c: New files. * engine.c (engine_ops): Check for assuan for assuan engine, add g13 engine. * util.h (_gpgme_get_g13_path, _gpgme_encode_percent_string): New prototypes. * conversion.c (_gpgme_encode_percent_string): New function. * gpgme.h.in (gpgme_protocol_t): Add GPGME_PROTOCOL_G13. (struct _gpgme_op_g13_result, gpgme_g13_result_t): New types. (gpgme_op_g13_mount): New function. * gpgme.def, libgpgme.vers: Add gpgme_op_g13_mount. * gpgme.c (gpgme_set_protocol): Allow GPGME_PROTOCOL_G13. (gpgme_get_protocol_name): Add GPGME_PROTOCOL_G13. * posix-util.c (_gpgme_get_g13_path): New function. * w32-util.c (_gpgme_get_g13_path): New function. * engine-backend.h (_gpgme_engine_ops_g13): New declaration.
This commit is contained in:
parent
9e2397571d
commit
a6f3857128
@ -1,3 +1,7 @@
|
|||||||
|
2009-10-22 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* configure.ac: Add support for G13.
|
||||||
|
|
||||||
2009-10-20 Marcus Brinkmann <marcus@g10code.de>
|
2009-10-20 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* configure.ac (AC_CONFIG_FILES): Remove assuan/Makefile.
|
* configure.ac (AC_CONFIG_FILES): Remove assuan/Makefile.
|
||||||
|
13
NEWS
13
NEWS
@ -6,11 +6,16 @@ Noteworthy changes in version 1.2.1 (unreleased)
|
|||||||
application programmers on systems that can resolve inter-library
|
application programmers on systems that can resolve inter-library
|
||||||
dependencies at runtime, this is a transparent change.
|
dependencies at runtime, this is a transparent change.
|
||||||
|
|
||||||
|
* New engine GPGME_PROTOCOL_G13 to support the new g13 tool.
|
||||||
|
|
||||||
* Interface changes relative to the 1.2.0 release:
|
* Interface changes relative to the 1.2.0 release:
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
GPGME_STATUS_INV_SGNR NEW.
|
GPGME_STATUS_INV_SGNR NEW
|
||||||
GPGME_STATUS_NO_SGNR NEW.
|
GPGME_STATUS_NO_SGNR NEW
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
GPGME_PROTOCOL_G13 NEW
|
||||||
|
gpgme_op_g13_mount NEW
|
||||||
|
gpgme_g13_result_t NEW
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Noteworthy changes in version 1.2.0 (2009-06-18)
|
Noteworthy changes in version 1.2.0 (2009-06-18)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
125
configure.ac
125
configure.ac
@ -120,6 +120,7 @@ AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes")
|
|||||||
GPG_DEFAULT=no
|
GPG_DEFAULT=no
|
||||||
GPGSM_DEFAULT=no
|
GPGSM_DEFAULT=no
|
||||||
GPGCONF_DEFAULT=no
|
GPGCONF_DEFAULT=no
|
||||||
|
G13_DEFAULT=no
|
||||||
component_system=None
|
component_system=None
|
||||||
have_dosish_system=no
|
have_dosish_system=no
|
||||||
have_w32_system=no
|
have_w32_system=no
|
||||||
@ -133,6 +134,7 @@ case "${host}" in
|
|||||||
GPG_DEFAULT='c:\\gnupg\\gpg.exe'
|
GPG_DEFAULT='c:\\gnupg\\gpg.exe'
|
||||||
GPGSM_DEFAULT='c:\\gnupg\\gpgsm.exe'
|
GPGSM_DEFAULT='c:\\gnupg\\gpgsm.exe'
|
||||||
GPGCONF_DEFAULT='c:\\gnupg\\gpgconf.exe'
|
GPGCONF_DEFAULT='c:\\gnupg\\gpgconf.exe'
|
||||||
|
G13_DEFAULT='c:\\gnupg\\g13.exe'
|
||||||
#component_system='COM+'
|
#component_system='COM+'
|
||||||
|
|
||||||
AM_PATH_GLIB_2_0
|
AM_PATH_GLIB_2_0
|
||||||
@ -166,6 +168,7 @@ case "${host}" in
|
|||||||
# GPG_DEFAULT='/usr/bin/gpg'
|
# GPG_DEFAULT='/usr/bin/gpg'
|
||||||
# GPGSM_DEFAULT='/usr/bin/gpgsm'
|
# GPGSM_DEFAULT='/usr/bin/gpgsm'
|
||||||
# GPGCONF_DEFAULT='/usr/bin/gpgconf'
|
# GPGCONF_DEFAULT='/usr/bin/gpgconf'
|
||||||
|
# G13_DEFAULT='/usr/bin/g13'
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
@ -286,9 +289,11 @@ fi
|
|||||||
NEED_GPG_VERSION_DEFAULT=1.3.0
|
NEED_GPG_VERSION_DEFAULT=1.3.0
|
||||||
NEED_GPGSM_VERSION_DEFAULT=1.9.6
|
NEED_GPGSM_VERSION_DEFAULT=1.9.6
|
||||||
NEED_GPGCONF_VERSION_DEFAULT=2.0.4
|
NEED_GPGCONF_VERSION_DEFAULT=2.0.4
|
||||||
|
NEED_G13_VERSION_DEFAULT=2.1.0
|
||||||
NEED_GPG_VERSION="$NEED_GPG_VERSION_DEFAULT"
|
NEED_GPG_VERSION="$NEED_GPG_VERSION_DEFAULT"
|
||||||
NEED_GPGSM_VERSION="$NEED_GPGSM_VERSION_DEFAULT"
|
NEED_GPGSM_VERSION="$NEED_GPGSM_VERSION_DEFAULT"
|
||||||
NEED_GPGCONF_VERSION="$NEED_GPGCONF_VERSION_DEFAULT"
|
NEED_GPGCONF_VERSION="$NEED_GPGCONF_VERSION_DEFAULT"
|
||||||
|
NEED_G13_VERSION="$NEED_G13_VERSION_DEFAULT"
|
||||||
AC_ARG_WITH(gpg-version,
|
AC_ARG_WITH(gpg-version,
|
||||||
AC_HELP_STRING([--with-gpg-version=VER], [require GnuPG version VER]),
|
AC_HELP_STRING([--with-gpg-version=VER], [require GnuPG version VER]),
|
||||||
NEED_GPG_VERSION=$withval)
|
NEED_GPG_VERSION=$withval)
|
||||||
@ -316,6 +321,15 @@ fi
|
|||||||
if test "$NEED_GPGCONF_VERSION" = "no"; then
|
if test "$NEED_GPGCONF_VERSION" = "no"; then
|
||||||
NEED_GPGCONF_VERSION=0.0.0
|
NEED_GPGCONF_VERSION=0.0.0
|
||||||
fi
|
fi
|
||||||
|
AC_ARG_WITH(g13-version,
|
||||||
|
AC_HELP_STRING([--with-g13-version=VER], [require G13 version VER]),
|
||||||
|
NEED_G13_VERSION=$withval)
|
||||||
|
if test "$NEED_G13_VERSION" = "yes"; then
|
||||||
|
NEED_G13_VERSION="$NEED_G13_VERSION_DEFAULT"
|
||||||
|
fi
|
||||||
|
if test "$NEED_G13_VERSION" = "no"; then
|
||||||
|
NEED_G13_VERSION=0.0.0
|
||||||
|
fi
|
||||||
|
|
||||||
AC_DEFINE_UNQUOTED(NEED_GPG_VERSION, "$NEED_GPG_VERSION",
|
AC_DEFINE_UNQUOTED(NEED_GPG_VERSION, "$NEED_GPG_VERSION",
|
||||||
[Min. needed GnuPG version.])
|
[Min. needed GnuPG version.])
|
||||||
@ -323,6 +337,8 @@ AC_DEFINE_UNQUOTED(NEED_GPGSM_VERSION, "$NEED_GPGSM_VERSION",
|
|||||||
[Min. needed GPGSM version.])
|
[Min. needed GPGSM version.])
|
||||||
AC_DEFINE_UNQUOTED(NEED_GPGCONF_VERSION, "$NEED_GPGCONF_VERSION",
|
AC_DEFINE_UNQUOTED(NEED_GPGCONF_VERSION, "$NEED_GPGCONF_VERSION",
|
||||||
[Min. needed GPGCONF version.])
|
[Min. needed GPGCONF version.])
|
||||||
|
AC_DEFINE_UNQUOTED(NEED_G13_VERSION, "$NEED_G13_VERSION",
|
||||||
|
[Min. needed G13 version.])
|
||||||
|
|
||||||
|
|
||||||
NO_OVERRIDE=no
|
NO_OVERRIDE=no
|
||||||
@ -518,6 +534,9 @@ require_libassuan=no
|
|||||||
if test "$GPGSM" != "no"; then
|
if test "$GPGSM" != "no"; then
|
||||||
require_libassuan=yes
|
require_libassuan=yes
|
||||||
fi
|
fi
|
||||||
|
if test "$G13" != "no"; then
|
||||||
|
require_libassuan=yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
NO_OVERRIDE=no
|
NO_OVERRIDE=no
|
||||||
@ -623,6 +642,109 @@ if test "$GPGCONF" != "no"; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
NO_OVERRIDE=no
|
||||||
|
AC_ARG_WITH(g13,
|
||||||
|
AC_HELP_STRING([--with-g13=PATH],
|
||||||
|
[use g13 binary at PATH]),
|
||||||
|
G13=$withval, NO_OVERRIDE=yes)
|
||||||
|
if test "$NO_OVERRIDE" = "yes" || test "$G13" = "yes"; then
|
||||||
|
G13=
|
||||||
|
NO_OVERRIDE=yes
|
||||||
|
if test "$cross_compiling" != "yes"; then
|
||||||
|
AC_PATH_PROG(G13, g13)
|
||||||
|
fi
|
||||||
|
if test -z "$G13"; then
|
||||||
|
G13="$G13_DEFAULT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "$G13" = no; then
|
||||||
|
if test "$NO_OVERRIDE" = "yes"; then
|
||||||
|
if test "$cross_compiling" != "yes"; then
|
||||||
|
AC_MSG_WARN([
|
||||||
|
***
|
||||||
|
*** Could not find g13, install g13 or use --with-g13=PATH to enable it
|
||||||
|
***])
|
||||||
|
else
|
||||||
|
AC_MSG_ERROR([
|
||||||
|
***
|
||||||
|
*** Can not determine path to g13 when cross-compiling, use --with-g13=PATH
|
||||||
|
***])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
AC_DEFINE_UNQUOTED(G13_PATH, "$G13", [Path to the G13 binary.])
|
||||||
|
AC_DEFINE(ENABLE_G13,1,[Whether G13 support is enabled])
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(HAVE_G13, test "$G13" != "no")
|
||||||
|
|
||||||
|
dnl Check for G13 version requirement.
|
||||||
|
G13_VERSION=unknown
|
||||||
|
ok=maybe
|
||||||
|
if test -z "$G13" -o "x$G13" = "xno"; then
|
||||||
|
ok=no
|
||||||
|
else
|
||||||
|
if test "$cross_compiling" = "yes"; then
|
||||||
|
AC_MSG_WARN([G13 version can not be checked when cross compiling])
|
||||||
|
ok=no
|
||||||
|
else
|
||||||
|
if test ! -x "$G13"; then
|
||||||
|
AC_MSG_WARN([G13 not executable, version check disabled])
|
||||||
|
ok=no
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "$ok" = "maybe"; then
|
||||||
|
AC_MSG_CHECKING(for G13 >= $NEED_G13_VERSION)
|
||||||
|
req_major=`echo $NEED_G13_VERSION | \
|
||||||
|
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'`
|
||||||
|
req_minor=`echo $NEED_G13_VERSION | \
|
||||||
|
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'`
|
||||||
|
req_micro=`echo $NEED_G13_VERSION | \
|
||||||
|
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'`
|
||||||
|
G13_VERSION=`$G13 --version | sed -n '1 s/.*\ \([[0-9]].*\)/\1/p'`
|
||||||
|
major=`echo $G13_VERSION | \
|
||||||
|
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
|
||||||
|
minor=`echo $G13_VERSION | \
|
||||||
|
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
|
||||||
|
micro=`echo $G13_VERSION | \
|
||||||
|
sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'`
|
||||||
|
|
||||||
|
if test "$major" -gt "$req_major"; then
|
||||||
|
ok=yes
|
||||||
|
else
|
||||||
|
if test "$major" -eq "$req_major"; then
|
||||||
|
if test "$minor" -gt "$req_minor"; then
|
||||||
|
ok=yes
|
||||||
|
else
|
||||||
|
if test "$minor" -eq "$req_minor"; then
|
||||||
|
if test "$micro" -ge "$req_micro"; then
|
||||||
|
ok=yes
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "$ok" = "yes"; then
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
AC_MSG_WARN([G13 must be at least version $NEED_G13_VERSION])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
run_g13_test="$ok"
|
||||||
|
AC_ARG_ENABLE(g13-test,
|
||||||
|
AC_HELP_STRING([--disable-g13-test], [disable G13 run test]),
|
||||||
|
run_g13_test=$enableval)
|
||||||
|
AM_CONDITIONAL(RUN_G13_TESTS, test "$run_g13_test" = "yes")
|
||||||
|
|
||||||
|
# Only build if supported.
|
||||||
|
AM_CONDITIONAL(BUILD_G13, test "$G13" != "no")
|
||||||
|
if test "$G13" != "no"; then
|
||||||
|
AC_DEFINE(HAVE_G13, 1,
|
||||||
|
[Defined if we are building with g13 support.])
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Check for funopen
|
# Check for funopen
|
||||||
AC_CHECK_FUNCS(funopen)
|
AC_CHECK_FUNCS(funopen)
|
||||||
if test $ac_cv_func_funopen != yes; then
|
if test $ac_cv_func_funopen != yes; then
|
||||||
@ -777,6 +899,9 @@ echo "
|
|||||||
GpgConf path: $GPGCONF
|
GpgConf path: $GPGCONF
|
||||||
GpgConf version: $GPGCONF_VERSION, min. $NEED_GPGCONF_VERSION
|
GpgConf version: $GPGCONF_VERSION, min. $NEED_GPGCONF_VERSION
|
||||||
|
|
||||||
|
G13 path: $G13
|
||||||
|
G13 version: $G13_VERSION, min. $NEED_G13_VERSION
|
||||||
|
|
||||||
Assuan version: $LIBASSUAN_VERSION
|
Assuan version: $LIBASSUAN_VERSION
|
||||||
|
|
||||||
GPGME Pthread: $have_pthread
|
GPGME Pthread: $have_pthread
|
||||||
|
@ -1,3 +1,24 @@
|
|||||||
|
2009-10-22 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
|
* Makefile.am: Remove @NETLIBS@ from LIBADDs.
|
||||||
|
(g13_components): New variable.
|
||||||
|
(main_sources): Add $(g13_components).
|
||||||
|
* g13.c, engine-g13.c: New files.
|
||||||
|
* engine.c (engine_ops): Check for assuan for assuan engine, add
|
||||||
|
g13 engine.
|
||||||
|
* util.h (_gpgme_get_g13_path, _gpgme_encode_percent_string): New
|
||||||
|
prototypes.
|
||||||
|
* conversion.c (_gpgme_encode_percent_string): New function.
|
||||||
|
* gpgme.h.in (gpgme_protocol_t): Add GPGME_PROTOCOL_G13.
|
||||||
|
(struct _gpgme_op_g13_result, gpgme_g13_result_t): New types.
|
||||||
|
(gpgme_op_g13_mount): New function.
|
||||||
|
* gpgme.def, libgpgme.vers: Add gpgme_op_g13_mount.
|
||||||
|
* gpgme.c (gpgme_set_protocol): Allow GPGME_PROTOCOL_G13.
|
||||||
|
(gpgme_get_protocol_name): Add GPGME_PROTOCOL_G13.
|
||||||
|
* posix-util.c (_gpgme_get_g13_path): New function.
|
||||||
|
* w32-util.c (_gpgme_get_g13_path): New function.
|
||||||
|
* engine-backend.h (_gpgme_engine_ops_g13): New declaration.
|
||||||
|
|
||||||
2009-10-20 Marcus Brinkmann <marcus@g10code.de>
|
2009-10-20 Marcus Brinkmann <marcus@g10code.de>
|
||||||
|
|
||||||
* gpgme-config.in (netlibs): Remove.
|
* gpgme-config.in (netlibs): Remove.
|
||||||
|
@ -86,6 +86,12 @@ else
|
|||||||
gpgconf_components =
|
gpgconf_components =
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if HAVE_G13
|
||||||
|
g13_components = engine-g13.c
|
||||||
|
else
|
||||||
|
g13_components =
|
||||||
|
endif
|
||||||
|
|
||||||
# These are the source files common to all library versions. We used
|
# These are the source files common to all library versions. We used
|
||||||
# to build a non-installed library for that, but that does not work
|
# to build a non-installed library for that, but that does not work
|
||||||
# correctly on all platforms (in particular, one can not specify the
|
# correctly on all platforms (in particular, one can not specify the
|
||||||
@ -105,6 +111,7 @@ main_sources = \
|
|||||||
opassuan.c \
|
opassuan.c \
|
||||||
engine.h engine-backend.h engine.c engine-gpg.c status-table.h \
|
engine.h engine-backend.h engine.c engine-gpg.c status-table.h \
|
||||||
$(gpgsm_components) $(assuan_components) $(gpgconf_components) \
|
$(gpgsm_components) $(assuan_components) $(gpgconf_components) \
|
||||||
|
$(g13_components) g13.c \
|
||||||
gpgconf.c \
|
gpgconf.c \
|
||||||
sema.h priv-io.h $(system_components) dirinfo.c \
|
sema.h priv-io.h $(system_components) dirinfo.c \
|
||||||
debug.c debug.h gpgme.c version.c error.c
|
debug.c debug.h gpgme.c version.c error.c
|
||||||
@ -185,21 +192,20 @@ libgpgme_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) $(export_symbols) \
|
|||||||
$(libgpgme_version_script_cmd) -version-info \
|
$(libgpgme_version_script_cmd) -version-info \
|
||||||
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
||||||
libgpgme_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
|
libgpgme_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
|
||||||
libgpgme_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
libgpgme_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ @GPG_ERROR_LIBS@
|
||||||
@GPG_ERROR_LIBS@ @NETLIBS@
|
|
||||||
|
|
||||||
libgpgme_pthread_la_LDFLAGS = $(libgpgme_version_script_cmd) -version-info \
|
libgpgme_pthread_la_LDFLAGS = $(libgpgme_version_script_cmd) -version-info \
|
||||||
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
||||||
libgpgme_pthread_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers
|
libgpgme_pthread_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers
|
||||||
libgpgme_pthread_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
libgpgme_pthread_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
||||||
-lpthread @GPG_ERROR_LIBS@ @NETLIBS@
|
-lpthread @GPG_ERROR_LIBS@
|
||||||
|
|
||||||
libgpgme_pth_la_LDFLAGS = @PTH_LDFLAGS@ \
|
libgpgme_pth_la_LDFLAGS = @PTH_LDFLAGS@ \
|
||||||
$(libgpgme_version_script_cmd) -version-info \
|
$(libgpgme_version_script_cmd) -version-info \
|
||||||
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
||||||
libgpgme_pth_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers
|
libgpgme_pth_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers
|
||||||
libgpgme_pth_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
libgpgme_pth_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
||||||
@PTH_LIBS@ @GPG_ERROR_LIBS@ @NETLIBS@
|
@PTH_LIBS@ @GPG_ERROR_LIBS@
|
||||||
|
|
||||||
if BUILD_W32_GLIB
|
if BUILD_W32_GLIB
|
||||||
libgpgme_glib_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) \
|
libgpgme_glib_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) \
|
||||||
@ -208,7 +214,7 @@ libgpgme_glib_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) \
|
|||||||
libgpgme_glib_la_DEPENDENCIES = @LTLIBOBJS@ \
|
libgpgme_glib_la_DEPENDENCIES = @LTLIBOBJS@ \
|
||||||
$(srcdir)/libgpgme.vers $(gpgme_deps)
|
$(srcdir)/libgpgme.vers $(gpgme_deps)
|
||||||
libgpgme_glib_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
libgpgme_glib_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
||||||
@GPG_ERROR_LIBS@ @GLIB_LIBS@ @NETLIBS@
|
@GPG_ERROR_LIBS@ @GLIB_LIBS@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_W32_QT
|
if BUILD_W32_QT
|
||||||
@ -217,7 +223,7 @@ libgpgme_qt_la_LDFLAGS = $(gpgme_res_ldflag) $(no_undefined) \
|
|||||||
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
@LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
|
||||||
libgpgme_qt_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
|
libgpgme_qt_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
|
||||||
libgpgme_qt_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
libgpgme_qt_la_LIBADD = @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
|
||||||
@GPG_ERROR_LIBS@ @QT4_CORE_LIBS@ @NETLIBS@
|
@GPG_ERROR_LIBS@ @QT4_CORE_LIBS@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
status-table.h : gpgme.h
|
status-table.h : gpgme.h
|
||||||
|
@ -245,6 +245,75 @@ _gpgme_decode_percent_string (const char *src, char **destp, size_t len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Encode the string SRC with percent escaping and store the result in
|
||||||
|
the buffer *DESTP which is LEN bytes long. If LEN is zero, then a
|
||||||
|
large enough buffer is allocated with malloc and *DESTP is set to
|
||||||
|
the result. Currently, LEN is only used to specify if allocation
|
||||||
|
is desired or not, the caller is expected to make sure that *DESTP
|
||||||
|
is large enough if LEN is not zero. If BINARY is 1, then '\0'
|
||||||
|
characters are allowed in the output. */
|
||||||
|
gpgme_error_t
|
||||||
|
_gpgme_encode_percent_string (const char *src, char **destp, size_t len)
|
||||||
|
{
|
||||||
|
size_t destlen;
|
||||||
|
char *dest;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
destlen = 0;
|
||||||
|
str = src;
|
||||||
|
/* We percent-escape the + character because the user might need a
|
||||||
|
"percent plus" escaped string (special gpg format). But we
|
||||||
|
percent-escape the space character, which works with and without
|
||||||
|
the special plus format. */
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
if (*str == '+' || *str == '\"' || *str == '%'
|
||||||
|
|| *(const unsigned char *)str <= 0x20)
|
||||||
|
destlen += 3;
|
||||||
|
else
|
||||||
|
destlen++;
|
||||||
|
}
|
||||||
|
/* Terminating nul byte. */
|
||||||
|
destlen++;
|
||||||
|
|
||||||
|
/* Set up the destination buffer. */
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
if (len < destlen);
|
||||||
|
return gpg_error (GPG_ERR_INTERNAL);
|
||||||
|
|
||||||
|
dest = *destp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The converted string will never be larger than the original
|
||||||
|
string. */
|
||||||
|
dest = malloc (destlen);
|
||||||
|
if (!dest)
|
||||||
|
return gpg_error_from_errno (errno);
|
||||||
|
|
||||||
|
*destp = dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert the string. */
|
||||||
|
while (*src)
|
||||||
|
{
|
||||||
|
if (*src == '+' || *src == '\"' || *src == '%'
|
||||||
|
|| *(const unsigned char *)src <= 0x20)
|
||||||
|
{
|
||||||
|
snprintf (dest, 4, "%%%02X", *(unsigned char *)src);
|
||||||
|
dest += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*(dest++) = *src;
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
*(dest++) = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Parse the string TIMESTAMP into a time_t. The string may either be
|
/* Parse the string TIMESTAMP into a time_t. The string may either be
|
||||||
seconds since Epoch or in the ISO 8601 format like
|
seconds since Epoch or in the ISO 8601 format like
|
||||||
"20390815T143012". Returns 0 for an empty string or seconds since
|
"20390815T143012". Returns 0 for an empty string or seconds since
|
||||||
|
@ -554,6 +554,8 @@ llass_status_handler (void *opaque, int fd)
|
|||||||
TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
|
TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
|
||||||
"fd 0x%x: ERR line: %s",
|
"fd 0x%x: ERR line: %s",
|
||||||
fd, err ? gpg_strerror (err) : "ok");
|
fd, err ? gpg_strerror (err) : "ok");
|
||||||
|
/* Command execution errors are not fatal, as we use
|
||||||
|
a session based protocol. */
|
||||||
if (llass->result_cb)
|
if (llass->result_cb)
|
||||||
err = llass->result_cb (llass->result_cb_value, err);
|
err = llass->result_cb (llass->result_cb_value, err);
|
||||||
else
|
else
|
||||||
|
@ -22,11 +22,6 @@
|
|||||||
|
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
|
|
||||||
/* FIXME: Correct check? */
|
|
||||||
#ifdef GPGSM_PATH
|
|
||||||
#define ENABLE_GPGSM 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct engine_ops
|
struct engine_ops
|
||||||
{
|
{
|
||||||
/* Static functions. */
|
/* Static functions. */
|
||||||
@ -132,5 +127,8 @@ extern struct engine_ops _gpgme_engine_ops_gpgconf; /* gpg-conf. */
|
|||||||
#ifdef ENABLE_ASSUAN
|
#ifdef ENABLE_ASSUAN
|
||||||
extern struct engine_ops _gpgme_engine_ops_assuan; /* Low-level Assuan. */
|
extern struct engine_ops _gpgme_engine_ops_assuan; /* Low-level Assuan. */
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ENABLE_G13
|
||||||
|
extern struct engine_ops _gpgme_engine_ops_g13; /* Crypto VFS. */
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* ENGINE_BACKEND_H */
|
#endif /* ENGINE_BACKEND_H */
|
||||||
|
796
src/engine-g13.c
Normal file
796
src/engine-g13.c
Normal file
@ -0,0 +1,796 @@
|
|||||||
|
/* engine-g13.c - G13 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
|
||||||
|
02111-1307, USA. */
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <fcntl.h> /* FIXME */
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "gpgme.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "ops.h"
|
||||||
|
#include "wait.h"
|
||||||
|
#include "priv-io.h"
|
||||||
|
#include "sema.h"
|
||||||
|
|
||||||
|
#include "assuan.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include "engine-backend.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int fd; /* FD we talk about. */
|
||||||
|
int server_fd;/* Server FD for this connection. */
|
||||||
|
int dir; /* Inbound/Outbound, maybe given implicit? */
|
||||||
|
void *data; /* Handler-specific data. */
|
||||||
|
void *tag; /* ID from the user for gpgme_remove_io_callback. */
|
||||||
|
char server_fd_str[15]; /* Same as SERVER_FD but as a string. We
|
||||||
|
need this because _gpgme_io_fd2str can't
|
||||||
|
be used on a closed descriptor. */
|
||||||
|
} iocb_data_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct engine_g13
|
||||||
|
{
|
||||||
|
assuan_context_t assuan_ctx;
|
||||||
|
|
||||||
|
int lc_ctype_set;
|
||||||
|
int lc_messages_set;
|
||||||
|
|
||||||
|
iocb_data_t status_cb;
|
||||||
|
|
||||||
|
struct gpgme_io_cbs io_cbs;
|
||||||
|
|
||||||
|
/* Internal callbacks. */
|
||||||
|
engine_assuan_result_cb_t result_cb;
|
||||||
|
void *result_cb_value;
|
||||||
|
|
||||||
|
/* User provided callbacks. */
|
||||||
|
struct {
|
||||||
|
gpgme_assuan_data_cb_t data_cb;
|
||||||
|
void *data_cb_value;
|
||||||
|
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb;
|
||||||
|
void *inq_cb_value;
|
||||||
|
|
||||||
|
gpgme_assuan_status_cb_t status_cb;
|
||||||
|
void *status_cb_value;
|
||||||
|
} user;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct engine_g13 *engine_g13_t;
|
||||||
|
|
||||||
|
|
||||||
|
static void g13_io_event (void *engine,
|
||||||
|
gpgme_event_io_t type, void *type_data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static char *
|
||||||
|
g13_get_version (const char *file_name)
|
||||||
|
{
|
||||||
|
return _gpgme_get_program_version (file_name ? file_name
|
||||||
|
: _gpgme_get_g13_path ());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
g13_get_req_version (void)
|
||||||
|
{
|
||||||
|
return NEED_G13_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
close_notify_handler (int fd, void *opaque)
|
||||||
|
{
|
||||||
|
engine_g13_t g13 = opaque;
|
||||||
|
|
||||||
|
assert (fd != -1);
|
||||||
|
if (g13->status_cb.fd == fd)
|
||||||
|
{
|
||||||
|
if (g13->status_cb.tag)
|
||||||
|
(*g13->io_cbs.remove) (g13->status_cb.tag);
|
||||||
|
g13->status_cb.fd = -1;
|
||||||
|
g13->status_cb.tag = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This is the default inquiry callback. We use it to handle the
|
||||||
|
Pinentry notifications. */
|
||||||
|
static gpgme_error_t
|
||||||
|
default_inq_cb (engine_g13_t g13, const char *keyword, const char *args)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
|
||||||
|
if (!strcmp (keyword, "PINENTRY_LAUNCHED"))
|
||||||
|
{
|
||||||
|
_gpgme_allow_set_foreground_window ((pid_t)strtoul (args, NULL, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g13->user.inq_cb)
|
||||||
|
{
|
||||||
|
gpgme_data_t data = NULL;
|
||||||
|
|
||||||
|
err = g13->user.inq_cb (g13->user.inq_cb_value,
|
||||||
|
keyword, args, &data);
|
||||||
|
if (!err && data)
|
||||||
|
{
|
||||||
|
/* FIXME: Returning data is not yet implemented. However we
|
||||||
|
need to allow the caller to cleanup his data object.
|
||||||
|
Thus we run the callback in finish mode immediately. */
|
||||||
|
err = g13->user.inq_cb (g13->user.inq_cb_value,
|
||||||
|
NULL, NULL, &data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
g13_cancel (void *engine)
|
||||||
|
{
|
||||||
|
engine_g13_t g13 = engine;
|
||||||
|
|
||||||
|
if (!g13)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
if (g13->status_cb.fd != -1)
|
||||||
|
_gpgme_io_close (g13->status_cb.fd);
|
||||||
|
|
||||||
|
if (g13->assuan_ctx)
|
||||||
|
{
|
||||||
|
assuan_release (g13->assuan_ctx);
|
||||||
|
g13->assuan_ctx = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
g13_release (void *engine)
|
||||||
|
{
|
||||||
|
engine_g13_t g13 = engine;
|
||||||
|
|
||||||
|
if (!g13)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g13_cancel (engine);
|
||||||
|
|
||||||
|
free (g13);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
g13_new (void **engine, const char *file_name, const char *home_dir)
|
||||||
|
{
|
||||||
|
gpgme_error_t err = 0;
|
||||||
|
engine_g13_t g13;
|
||||||
|
int argc;
|
||||||
|
char *argv[5];
|
||||||
|
char *dft_display = NULL;
|
||||||
|
char dft_ttyname[64];
|
||||||
|
char *dft_ttytype = NULL;
|
||||||
|
char *optstr;
|
||||||
|
|
||||||
|
g13 = calloc (1, sizeof *g13);
|
||||||
|
if (!g13)
|
||||||
|
return gpg_error_from_errno (errno);
|
||||||
|
|
||||||
|
g13->status_cb.fd = -1;
|
||||||
|
g13->status_cb.dir = 1;
|
||||||
|
g13->status_cb.tag = 0;
|
||||||
|
g13->status_cb.data = g13;
|
||||||
|
|
||||||
|
err = assuan_new (&g13->assuan_ctx);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
argc = 0;
|
||||||
|
argv[argc++] = "g13";
|
||||||
|
if (home_dir)
|
||||||
|
{
|
||||||
|
argv[argc++] = "--homedir";
|
||||||
|
argv[argc++] = home_dir;
|
||||||
|
}
|
||||||
|
argv[argc++] = "--server";
|
||||||
|
argv[argc++] = NULL;
|
||||||
|
|
||||||
|
err = assuan_new_ext (&g13->assuan_ctx, GPG_ERR_SOURCE_GPGME,
|
||||||
|
&_gpgme_assuan_malloc_hooks, _gpgme_assuan_log_cb,
|
||||||
|
NULL);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
assuan_ctx_set_system_hooks (g13->assuan_ctx, &_gpgme_assuan_system_hooks);
|
||||||
|
|
||||||
|
#if USE_DESCRIPTOR_PASSING
|
||||||
|
err = assuan_pipe_connect_ext
|
||||||
|
(g13->assuan_ctx, file_name ? file_name : _gpgme_get_g13_path (),
|
||||||
|
argv, NULL, NULL, NULL, 1);
|
||||||
|
#else
|
||||||
|
err = assuan_pipe_connect
|
||||||
|
(g13->assuan_ctx, file_name ? file_name : _gpgme_get_g13_path (),
|
||||||
|
argv, NULL);
|
||||||
|
#endif
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
err = _gpgme_getenv ("DISPLAY", &dft_display);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
if (dft_display)
|
||||||
|
{
|
||||||
|
if (asprintf (&optstr, "OPTION display=%s", dft_display) < 0)
|
||||||
|
{
|
||||||
|
free (dft_display);
|
||||||
|
err = gpg_error_from_errno (errno);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
free (dft_display);
|
||||||
|
|
||||||
|
err = assuan_transact (g13->assuan_ctx, optstr, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
free (optstr);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isatty (1))
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_errno (rc);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_errno (errno);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
err = assuan_transact (g13->assuan_ctx, optstr, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
free (optstr);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
err = _gpgme_getenv ("TERM", &dft_ttytype);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
if (dft_ttytype)
|
||||||
|
{
|
||||||
|
if (asprintf (&optstr, "OPTION ttytype=%s", dft_ttytype) < 0)
|
||||||
|
{
|
||||||
|
free (dft_ttytype);
|
||||||
|
err = gpg_error_from_errno (errno);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
free (dft_ttytype);
|
||||||
|
|
||||||
|
err = assuan_transact (g13->assuan_ctx, optstr, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL);
|
||||||
|
free (optstr);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_W32_SYSTEM
|
||||||
|
/* Under Windows we need to use AllowSetForegroundWindow. Tell
|
||||||
|
g13 to tell us when it needs it. */
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
err = assuan_transact (g13->assuan_ctx, "OPTION allow-pinentry-notify",
|
||||||
|
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
|
if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
|
||||||
|
err = 0; /* This is a new feature of g13. */
|
||||||
|
}
|
||||||
|
#endif /*HAVE_W32_SYSTEM*/
|
||||||
|
|
||||||
|
leave:
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
g13_release (g13);
|
||||||
|
else
|
||||||
|
*engine = g13;
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
g13_set_locale (void *engine, int category, const char *value)
|
||||||
|
{
|
||||||
|
engine_g13_t g13 = engine;
|
||||||
|
gpgme_error_t err;
|
||||||
|
char *optstr;
|
||||||
|
char *catstr;
|
||||||
|
|
||||||
|
/* FIXME: If value is NULL, we need to reset the option to default.
|
||||||
|
But we can't do this. So we error out here. G13 needs support
|
||||||
|
for this. */
|
||||||
|
if (category == LC_CTYPE)
|
||||||
|
{
|
||||||
|
catstr = "lc-ctype";
|
||||||
|
if (!value && g13->lc_ctype_set)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
if (value)
|
||||||
|
g13->lc_ctype_set = 1;
|
||||||
|
}
|
||||||
|
#ifdef LC_MESSAGES
|
||||||
|
else if (category == LC_MESSAGES)
|
||||||
|
{
|
||||||
|
catstr = "lc-messages";
|
||||||
|
if (!value && g13->lc_messages_set)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
if (value)
|
||||||
|
g13->lc_messages_set = 1;
|
||||||
|
}
|
||||||
|
#endif /* LC_MESSAGES */
|
||||||
|
else
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
/* FIXME: Reset value to default. */
|
||||||
|
if (!value)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0)
|
||||||
|
err = gpg_error_from_errno (errno);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = assuan_transact (g13->assuan_ctx, optstr, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL);
|
||||||
|
free (optstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward declaration. */
|
||||||
|
static gpgme_status_code_t parse_status (const char *name);
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
g13_assuan_simple_command (assuan_context_t ctx, char *cmd,
|
||||||
|
engine_status_handler_t status_fnc,
|
||||||
|
void *status_fnc_value)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
char *line;
|
||||||
|
size_t linelen;
|
||||||
|
|
||||||
|
err = assuan_write_line (ctx, cmd);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
err = assuan_read_line (ctx, &line, &linelen);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (*line == '#' || !linelen)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (linelen >= 2
|
||||||
|
&& line[0] == 'O' && line[1] == 'K'
|
||||||
|
&& (line[2] == '\0' || line[2] == ' '))
|
||||||
|
return 0;
|
||||||
|
else if (linelen >= 4
|
||||||
|
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
|
||||||
|
&& line[3] == ' ')
|
||||||
|
err = atoi (&line[4]);
|
||||||
|
else if (linelen >= 2
|
||||||
|
&& line[0] == 'S' && line[1] == ' ')
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (r >= 0 && status_fnc)
|
||||||
|
err = status_fnc (status_fnc_value, r, rest);
|
||||||
|
else
|
||||||
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
|
}
|
||||||
|
while (!err);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
status_handler (void *opaque, int fd)
|
||||||
|
{
|
||||||
|
gpgme_error_t err = 0;
|
||||||
|
engine_g13_t g13 = opaque;
|
||||||
|
char *line;
|
||||||
|
size_t linelen;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
err = assuan_read_line (g13->assuan_ctx, &line, &linelen);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
/* Try our best to terminate the connection friendly. */
|
||||||
|
/* assuan_write_line (g13->assuan_ctx, "BYE"); */
|
||||||
|
TRACE2 (DEBUG_CTX, "gpgme:status_handler", g13,
|
||||||
|
"fd 0x%x: error reading assuan line: %s",
|
||||||
|
fd, gpg_strerror (err));
|
||||||
|
}
|
||||||
|
else if (linelen >= 3
|
||||||
|
&& line[0] == 'E' && line[1] == 'R' && line[2] == 'R'
|
||||||
|
&& (line[3] == '\0' || line[3] == ' '))
|
||||||
|
{
|
||||||
|
if (line[3] == ' ')
|
||||||
|
err = atoi (&line[4]);
|
||||||
|
if (! err)
|
||||||
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
|
TRACE2 (DEBUG_CTX, "gpgme:status_handler", g13,
|
||||||
|
"fd 0x%x: ERR line: %s",
|
||||||
|
fd, err ? gpg_strerror (err) : "ok");
|
||||||
|
|
||||||
|
/* In g13, command execution errors are not fatal, as we use
|
||||||
|
a session based protocol. */
|
||||||
|
if (g13->result_cb)
|
||||||
|
err = g13->result_cb (g13->result_cb_value, err);
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
_gpgme_io_close (g13->status_cb.fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (linelen >= 2
|
||||||
|
&& line[0] == 'O' && line[1] == 'K'
|
||||||
|
&& (line[2] == '\0' || line[2] == ' '))
|
||||||
|
{
|
||||||
|
TRACE1 (DEBUG_CTX, "gpgme:status_handler", g13,
|
||||||
|
"fd 0x%x: OK line", fd);
|
||||||
|
if (g13->result_cb)
|
||||||
|
err = g13->result_cb (g13->result_cb_value, 0);
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
_gpgme_io_close (g13->status_cb.fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (linelen > 2
|
||||||
|
&& line[0] == 'D' && line[1] == ' ')
|
||||||
|
{
|
||||||
|
/* We are using the colon handler even for plain inline data
|
||||||
|
- strange name for that function but for historic reasons
|
||||||
|
we keep it. */
|
||||||
|
/* FIXME We can't use this for binary data because we
|
||||||
|
assume this is a string. For the current usage of colon
|
||||||
|
output it is correct. */
|
||||||
|
char *src = line + 2;
|
||||||
|
char *end = line + linelen;
|
||||||
|
char *dst = src;
|
||||||
|
|
||||||
|
linelen = 0;
|
||||||
|
while (src < end)
|
||||||
|
{
|
||||||
|
if (*src == '%' && src + 2 < end)
|
||||||
|
{
|
||||||
|
/* Handle escaped characters. */
|
||||||
|
++src;
|
||||||
|
*dst++ = _gpgme_hextobyte (src);
|
||||||
|
src += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*dst++ = *src++;
|
||||||
|
|
||||||
|
linelen++;
|
||||||
|
}
|
||||||
|
|
||||||
|
src = line + 2;
|
||||||
|
if (linelen && g13->user.data_cb)
|
||||||
|
err = g13->user.data_cb (g13->user.data_cb_value,
|
||||||
|
src, linelen);
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
TRACE2 (DEBUG_CTX, "gpgme:g13_status_handler", g13,
|
||||||
|
"fd 0x%x: D inlinedata; status from cb: %s",
|
||||||
|
fd, (g13->user.data_cb ?
|
||||||
|
(err? gpg_strerror (err):"ok"):"no callback"));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (linelen > 2
|
||||||
|
&& line[0] == 'S' && line[1] == ' ')
|
||||||
|
{
|
||||||
|
char *src;
|
||||||
|
char *args;
|
||||||
|
|
||||||
|
src = line + 2;
|
||||||
|
while (*src == ' ')
|
||||||
|
src++;
|
||||||
|
|
||||||
|
args = strchr (line + 2, ' ');
|
||||||
|
if (!args)
|
||||||
|
args = line + linelen; /* set to an empty string */
|
||||||
|
else
|
||||||
|
*(args++) = 0;
|
||||||
|
|
||||||
|
while (*args == ' ')
|
||||||
|
args++;
|
||||||
|
|
||||||
|
if (g13->user.status_cb)
|
||||||
|
err = g13->user.status_cb (g13->user.status_cb_value,
|
||||||
|
src, args);
|
||||||
|
else
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
TRACE3 (DEBUG_CTX, "gpgme:g13_status_handler", g13,
|
||||||
|
"fd 0x%x: S line (%s) - status from cb: %s",
|
||||||
|
fd, line+2, (g13->user.status_cb ?
|
||||||
|
(err? gpg_strerror (err):"ok"):"no callback"));
|
||||||
|
}
|
||||||
|
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[7] == '\0' || line[7] == ' '))
|
||||||
|
{
|
||||||
|
char *src;
|
||||||
|
char *args;
|
||||||
|
|
||||||
|
for (src=line+7; *src == ' '; src++)
|
||||||
|
;
|
||||||
|
|
||||||
|
args = strchr (src, ' ');
|
||||||
|
if (!args)
|
||||||
|
args = line + linelen; /* Let it point to an empty string. */
|
||||||
|
else
|
||||||
|
*(args++) = 0;
|
||||||
|
|
||||||
|
while (*args == ' ')
|
||||||
|
args++;
|
||||||
|
|
||||||
|
err = default_inq_cb (g13, src, args);
|
||||||
|
if (!err)
|
||||||
|
{
|
||||||
|
/* Flush and send END. */
|
||||||
|
err = assuan_send_data (g13->assuan_ctx, NULL, 0);
|
||||||
|
}
|
||||||
|
else if (gpg_err_code (err) == GPG_ERR_ASS_CANCELED)
|
||||||
|
{
|
||||||
|
/* Flush and send CANcel. */
|
||||||
|
err = assuan_send_data (g13->assuan_ctx, NULL, 1);
|
||||||
|
}
|
||||||
|
assuan_write_line (g13->assuan_ctx, "END");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!err && assuan_pending_line (g13->assuan_ctx));
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
add_io_cb (engine_g13_t g13, iocb_data_t *iocbd, gpgme_io_cb_t handler)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
|
||||||
|
TRACE_BEG2 (DEBUG_ENGINE, "engine-g13:add_io_cb", g13,
|
||||||
|
"fd %d, dir %d", iocbd->fd, iocbd->dir);
|
||||||
|
err = (*g13->io_cbs.add) (g13->io_cbs.add_priv,
|
||||||
|
iocbd->fd, iocbd->dir,
|
||||||
|
handler, iocbd->data, &iocbd->tag);
|
||||||
|
if (err)
|
||||||
|
return TRACE_ERR (err);
|
||||||
|
if (!iocbd->dir)
|
||||||
|
/* FIXME Kludge around poll() problem. */
|
||||||
|
err = _gpgme_io_set_nonblocking (iocbd->fd);
|
||||||
|
return TRACE_ERR (err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
start (engine_g13_t g13, const char *command)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
int fdlist[5];
|
||||||
|
int nfds;
|
||||||
|
|
||||||
|
/* We need to know the fd used by assuan for reads. We do this by
|
||||||
|
using the assumption that the first returned fd from
|
||||||
|
assuan_get_active_fds() is always this one. */
|
||||||
|
nfds = assuan_get_active_fds (g13->assuan_ctx, 0 /* read fds */,
|
||||||
|
fdlist, DIM (fdlist));
|
||||||
|
if (nfds < 1)
|
||||||
|
return gpg_error (GPG_ERR_GENERAL); /* FIXME */
|
||||||
|
|
||||||
|
/* We "duplicate" the file descriptor, so we can close it here (we
|
||||||
|
can't close fdlist[0], as that is closed by libassuan, and
|
||||||
|
closing it here might cause libassuan to close some unrelated FD
|
||||||
|
later). Alternatively, we could special case status_fd and
|
||||||
|
register/unregister it manually as needed, but this increases
|
||||||
|
code duplication and is more complicated as we can not use the
|
||||||
|
close notifications etc. A third alternative would be to let
|
||||||
|
Assuan know that we closed the FD, but that complicates the
|
||||||
|
Assuan interface. */
|
||||||
|
|
||||||
|
g13->status_cb.fd = _gpgme_io_dup (fdlist[0]);
|
||||||
|
if (g13->status_cb.fd < 0)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
|
||||||
|
if (_gpgme_io_set_close_notify (g13->status_cb.fd,
|
||||||
|
close_notify_handler, g13))
|
||||||
|
{
|
||||||
|
_gpgme_io_close (g13->status_cb.fd);
|
||||||
|
g13->status_cb.fd = -1;
|
||||||
|
return gpg_error (GPG_ERR_GENERAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = add_io_cb (g13, &g13->status_cb, status_handler);
|
||||||
|
if (!err)
|
||||||
|
err = assuan_write_line (g13->assuan_ctx, command);
|
||||||
|
|
||||||
|
if (!err)
|
||||||
|
g13_io_event (g13, GPGME_EVENT_START, NULL);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if USE_DESCRIPTOR_PASSING
|
||||||
|
static gpgme_error_t
|
||||||
|
g13_reset (void *engine)
|
||||||
|
{
|
||||||
|
engine_g13_t g13 = engine;
|
||||||
|
|
||||||
|
/* We must send a reset because we need to reset the list of
|
||||||
|
signers. Note that RESET does not reset OPTION commands. */
|
||||||
|
return g13_assuan_simple_command (g13->assuan_ctx, "RESET", NULL, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
g13_transact (void *engine,
|
||||||
|
const char *command,
|
||||||
|
engine_assuan_result_cb_t result_cb,
|
||||||
|
void *result_cb_value,
|
||||||
|
gpgme_assuan_data_cb_t data_cb,
|
||||||
|
void *data_cb_value,
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb,
|
||||||
|
void *inq_cb_value,
|
||||||
|
gpgme_assuan_status_cb_t status_cb,
|
||||||
|
void *status_cb_value)
|
||||||
|
{
|
||||||
|
engine_g13_t g13 = engine;
|
||||||
|
gpgme_error_t err;
|
||||||
|
|
||||||
|
if (!g13 || !command || !*command)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
g13->result_cb = result_cb;
|
||||||
|
g13->result_cb_value = result_cb_value;
|
||||||
|
g13->user.data_cb = data_cb;
|
||||||
|
g13->user.data_cb_value = data_cb_value;
|
||||||
|
g13->user.inq_cb = inq_cb;
|
||||||
|
g13->user.inq_cb_value = inq_cb_value;
|
||||||
|
g13->user.status_cb = status_cb;
|
||||||
|
g13->user.status_cb_value = status_cb_value;
|
||||||
|
|
||||||
|
err = start (g13, command);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
g13_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
|
||||||
|
{
|
||||||
|
engine_g13_t g13 = engine;
|
||||||
|
g13->io_cbs = *io_cbs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
g13_io_event (void *engine, gpgme_event_io_t type, void *type_data)
|
||||||
|
{
|
||||||
|
engine_g13_t g13 = engine;
|
||||||
|
|
||||||
|
TRACE3 (DEBUG_ENGINE, "gpgme:g13_io_event", g13,
|
||||||
|
"event %p, type %d, type_data %p",
|
||||||
|
g13->io_cbs.event, type, type_data);
|
||||||
|
if (g13->io_cbs.event)
|
||||||
|
(*g13->io_cbs.event) (g13->io_cbs.event_priv, type, type_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct engine_ops _gpgme_engine_ops_g13 =
|
||||||
|
{
|
||||||
|
/* Static functions. */
|
||||||
|
_gpgme_get_g13_path,
|
||||||
|
NULL,
|
||||||
|
g13_get_version,
|
||||||
|
g13_get_req_version,
|
||||||
|
g13_new,
|
||||||
|
|
||||||
|
/* Member functions. */
|
||||||
|
g13_release,
|
||||||
|
#if USE_DESCRIPTOR_PASSING
|
||||||
|
g13_reset,
|
||||||
|
#else
|
||||||
|
NULL, /* reset */
|
||||||
|
#endif
|
||||||
|
NULL, /* set_status_handler */
|
||||||
|
NULL, /* set_command_handler */
|
||||||
|
NULL, /* set_colon_line_handler */
|
||||||
|
g13_set_locale,
|
||||||
|
NULL, /* decrypt */
|
||||||
|
NULL, /* delete */
|
||||||
|
NULL, /* edit */
|
||||||
|
NULL, /* encrypt */
|
||||||
|
NULL, /* encrypt_sign */
|
||||||
|
NULL, /* export */
|
||||||
|
NULL, /* export_ext */
|
||||||
|
NULL, /* genkey */
|
||||||
|
NULL, /* import */
|
||||||
|
NULL, /* keylist */
|
||||||
|
NULL, /* keylist_ext */
|
||||||
|
NULL, /* sign */
|
||||||
|
NULL, /* trustlist */
|
||||||
|
NULL, /* verify */
|
||||||
|
NULL, /* getauditlog */
|
||||||
|
g13_transact,
|
||||||
|
NULL, /* conf_load */
|
||||||
|
NULL, /* conf_save */
|
||||||
|
g13_set_io_cbs,
|
||||||
|
g13_io_event,
|
||||||
|
g13_cancel
|
||||||
|
};
|
12
src/engine.c
12
src/engine.c
@ -55,8 +55,13 @@ static struct engine_ops *engine_ops[] =
|
|||||||
#else
|
#else
|
||||||
NULL,
|
NULL,
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_GPGSM /* This indicates that we have assuan support. */
|
#ifdef ENABLE_ASSUAN
|
||||||
&_gpgme_engine_ops_assuan /* Low-Level Assuan. */
|
&_gpgme_engine_ops_assuan, /* Low-Level Assuan. */
|
||||||
|
#else
|
||||||
|
NULL
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_G13
|
||||||
|
&_gpgme_engine_ops_g13 /* Crypto VFS. */
|
||||||
#else
|
#else
|
||||||
NULL
|
NULL
|
||||||
#endif
|
#endif
|
||||||
@ -194,7 +199,8 @@ gpgme_get_engine_info (gpgme_engine_info_t *info)
|
|||||||
gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP,
|
gpgme_protocol_t proto_list[] = { GPGME_PROTOCOL_OpenPGP,
|
||||||
GPGME_PROTOCOL_CMS,
|
GPGME_PROTOCOL_CMS,
|
||||||
GPGME_PROTOCOL_GPGCONF,
|
GPGME_PROTOCOL_GPGCONF,
|
||||||
GPGME_PROTOCOL_ASSUAN };
|
GPGME_PROTOCOL_ASSUAN,
|
||||||
|
GPGME_PROTOCOL_G13 };
|
||||||
unsigned int proto;
|
unsigned int proto;
|
||||||
|
|
||||||
for (proto = 0; proto < DIM (proto_list); proto++)
|
for (proto = 0; proto < DIM (proto_list); proto++)
|
||||||
|
229
src/g13.c
Normal file
229
src/g13.c
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
/* g13.c - g13 support in GPGME
|
||||||
|
Copyright (C) 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
|
||||||
|
02111-1307, USA. */
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "gpgme.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "ops.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
struct _gpgme_op_g13_result result;
|
||||||
|
} *op_data_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* This callback is used to return the status of the assuan command
|
||||||
|
back rather than transmission errors. */
|
||||||
|
static gpgme_error_t
|
||||||
|
result_cb (void *priv, gpgme_error_t result)
|
||||||
|
{
|
||||||
|
gpgme_ctx_t ctx = (gpgme_ctx_t)priv;
|
||||||
|
gpgme_error_t err;
|
||||||
|
void *hook;
|
||||||
|
op_data_t opd;
|
||||||
|
|
||||||
|
err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL);
|
||||||
|
opd = hook;
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
if (!opd)
|
||||||
|
return gpg_error (GPG_ERR_INTERNAL);
|
||||||
|
|
||||||
|
opd->result.err = result;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gpgme_g13_result_t
|
||||||
|
gpgme_op_g13_result (gpgme_ctx_t ctx)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
void *hook;
|
||||||
|
op_data_t opd;
|
||||||
|
|
||||||
|
err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL);
|
||||||
|
opd = hook;
|
||||||
|
/* Check in case this function is used without having run a command
|
||||||
|
before. */
|
||||||
|
if (err || !opd)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &opd->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
opg13_start (gpgme_ctx_t ctx, int synchronous,
|
||||||
|
const char *command,
|
||||||
|
gpgme_assuan_data_cb_t data_cb,
|
||||||
|
void *data_cb_value,
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb,
|
||||||
|
void *inq_cb_value,
|
||||||
|
gpgme_assuan_status_cb_t status_cb,
|
||||||
|
void *status_cb_value)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
void *hook;
|
||||||
|
op_data_t opd;
|
||||||
|
|
||||||
|
if (!command || !*command)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
/* The flag value 256 is used to suppress an engine reset. This is
|
||||||
|
required to keep the connection running. */
|
||||||
|
err = _gpgme_op_reset (ctx, ((synchronous & 255) | 256));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, sizeof (*opd), NULL);
|
||||||
|
opd = hook;
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
opd->result.err = gpg_error (GPG_ERR_UNFINISHED);
|
||||||
|
|
||||||
|
return _gpgme_engine_op_assuan_transact (ctx->engine, command,
|
||||||
|
result_cb, ctx,
|
||||||
|
data_cb, data_cb_value,
|
||||||
|
inq_cb, inq_cb_value,
|
||||||
|
status_cb, status_cb_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* XXXX. This is the asynchronous variant. */
|
||||||
|
static gpgme_error_t
|
||||||
|
gpgme_op_g13_transact_start (gpgme_ctx_t ctx,
|
||||||
|
const char *command,
|
||||||
|
gpgme_assuan_data_cb_t data_cb,
|
||||||
|
void *data_cb_value,
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb,
|
||||||
|
void *inq_cb_value,
|
||||||
|
gpgme_assuan_status_cb_t status_cb,
|
||||||
|
void *status_cb_value)
|
||||||
|
{
|
||||||
|
return opg13_start (ctx, 0, command, data_cb, data_cb_value,
|
||||||
|
inq_cb, inq_cb_value, status_cb, status_cb_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* XXXX. This is the synchronous variant. */
|
||||||
|
static gpgme_error_t
|
||||||
|
gpgme_op_g13_transact (gpgme_ctx_t ctx,
|
||||||
|
const char *command,
|
||||||
|
gpgme_assuan_data_cb_t data_cb,
|
||||||
|
void *data_cb_value,
|
||||||
|
gpgme_assuan_inquire_cb_t inq_cb,
|
||||||
|
void *inq_cb_value,
|
||||||
|
gpgme_assuan_status_cb_t status_cb,
|
||||||
|
void *status_cb_value)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
|
||||||
|
err = opg13_start (ctx, 1, command, data_cb, data_cb_value,
|
||||||
|
inq_cb, inq_cb_value, status_cb, status_cb_value);
|
||||||
|
if (!err)
|
||||||
|
err = _gpgme_wait_one (ctx);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* The actual exported interface follows. */
|
||||||
|
|
||||||
|
static gpg_error_t
|
||||||
|
get_err (gpgme_ctx_t ctx)
|
||||||
|
{
|
||||||
|
gpgme_g13_result_t res;
|
||||||
|
|
||||||
|
res = gpgme_op_g13_result (ctx);
|
||||||
|
if (! res)
|
||||||
|
return gpg_error (GPG_ERR_GENERAL);
|
||||||
|
|
||||||
|
return res->err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* The container is automatically unmounted when the context is reset
|
||||||
|
or destroyed. This is a synchronous convenience interface, which
|
||||||
|
automatically returns an operation error if there is no
|
||||||
|
transmission error. */
|
||||||
|
gpgme_error_t
|
||||||
|
gpgme_op_g13_mount (gpgme_ctx_t ctx, const char *container_file,
|
||||||
|
const char *mount_dir, int flags)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
char *cmd;
|
||||||
|
char *container_file_esc = NULL;
|
||||||
|
|
||||||
|
err = _gpgme_encode_percent_string (container_file, &container_file_esc, 0);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (asprintf (&cmd, "OPEN -- %s", container_file_esc) < 0)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
free (container_file_esc);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
free (container_file_esc);
|
||||||
|
|
||||||
|
err = gpgme_op_g13_transact (ctx, cmd, NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL);
|
||||||
|
free (cmd);
|
||||||
|
err = err || get_err (ctx);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (mount_dir)
|
||||||
|
{
|
||||||
|
char *mount_dir_esc = NULL;
|
||||||
|
|
||||||
|
err = _gpgme_encode_percent_string (mount_dir, &mount_dir_esc, 0);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (asprintf (&cmd, "MOUNT -- %s", mount_dir_esc) < 0)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
free (mount_dir_esc);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
free (mount_dir_esc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (asprintf (&cmd, "MOUNT") < 0)
|
||||||
|
return gpg_error_from_syserror ();
|
||||||
|
}
|
||||||
|
|
||||||
|
err = gpgme_op_g13_transact (ctx, cmd, NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL);
|
||||||
|
free (cmd);
|
||||||
|
|
||||||
|
/* Note: in symmetry with the asynchronous variant, we don't return
|
||||||
|
the error in the result structure here, if any. */
|
||||||
|
return err;
|
||||||
|
}
|
@ -248,7 +248,8 @@ gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t protocol)
|
|||||||
|
|
||||||
if (protocol != GPGME_PROTOCOL_OpenPGP
|
if (protocol != GPGME_PROTOCOL_OpenPGP
|
||||||
&& protocol != GPGME_PROTOCOL_CMS
|
&& protocol != GPGME_PROTOCOL_CMS
|
||||||
&& protocol != GPGME_PROTOCOL_ASSUAN)
|
&& protocol != GPGME_PROTOCOL_ASSUAN
|
||||||
|
&& protocol != GPGME_PROTOCOL_G13)
|
||||||
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
|
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
|
||||||
|
|
||||||
if (ctx->protocol != protocol)
|
if (ctx->protocol != protocol)
|
||||||
@ -292,6 +293,9 @@ gpgme_get_protocol_name (gpgme_protocol_t protocol)
|
|||||||
case GPGME_PROTOCOL_ASSUAN:
|
case GPGME_PROTOCOL_ASSUAN:
|
||||||
return "Assuan";
|
return "Assuan";
|
||||||
|
|
||||||
|
case GPGME_PROTOCOL_G13:
|
||||||
|
return "G13";
|
||||||
|
|
||||||
case GPGME_PROTOCOL_UNKNOWN:
|
case GPGME_PROTOCOL_UNKNOWN:
|
||||||
return "unknown";
|
return "unknown";
|
||||||
|
|
||||||
|
@ -185,5 +185,7 @@ EXPORTS
|
|||||||
gpgme_op_export_keys @142
|
gpgme_op_export_keys @142
|
||||||
gpgme_op_export_keys_start @143
|
gpgme_op_export_keys_start @143
|
||||||
|
|
||||||
|
gpgme_op_g13_mount @144
|
||||||
|
|
||||||
; END
|
; END
|
||||||
|
|
||||||
|
@ -324,6 +324,7 @@ typedef enum
|
|||||||
GPGME_PROTOCOL_CMS = 1,
|
GPGME_PROTOCOL_CMS = 1,
|
||||||
GPGME_PROTOCOL_GPGCONF = 2, /* Special code for gpgconf. */
|
GPGME_PROTOCOL_GPGCONF = 2, /* Special code for gpgconf. */
|
||||||
GPGME_PROTOCOL_ASSUAN = 3, /* Low-level access to an Assuan server. */
|
GPGME_PROTOCOL_ASSUAN = 3, /* Low-level access to an Assuan server. */
|
||||||
|
GPGME_PROTOCOL_G13 = 4,
|
||||||
GPGME_PROTOCOL_UNKNOWN = 255
|
GPGME_PROTOCOL_UNKNOWN = 255
|
||||||
}
|
}
|
||||||
gpgme_protocol_t;
|
gpgme_protocol_t;
|
||||||
@ -1735,7 +1736,10 @@ typedef gpgme_error_t (*gpgme_assuan_status_cb_t)
|
|||||||
struct _gpgme_op_assuan_result
|
struct _gpgme_op_assuan_result
|
||||||
{
|
{
|
||||||
/* The result of the actual assuan command. An OK is indicated by a
|
/* The result of the actual assuan command. An OK is indicated by a
|
||||||
value of 0 and an ERR by the respective error error value. */
|
value of 0 and an ERR by the respective error error value. This
|
||||||
|
is required because assuan operations use a session-based
|
||||||
|
interface. The error code of the GPGME function calls just
|
||||||
|
reflects transmission errors. */
|
||||||
gpgme_error_t err;
|
gpgme_error_t err;
|
||||||
};
|
};
|
||||||
typedef struct _gpgme_op_assuan_result *gpgme_assuan_result_t;
|
typedef struct _gpgme_op_assuan_result *gpgme_assuan_result_t;
|
||||||
@ -1767,6 +1771,26 @@ gpgme_error_t gpgme_op_assuan_transact (gpgme_ctx_t ctx,
|
|||||||
void *stat_cb_value);
|
void *stat_cb_value);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Crypto container support. */
|
||||||
|
struct _gpgme_op_g13_result
|
||||||
|
{
|
||||||
|
/* The result of the actual assuan command. An OK is indicated by a
|
||||||
|
value of 0 and an ERR by the respective error error value. This
|
||||||
|
is required because assuan operations use a session-based
|
||||||
|
interface. The error code of the GPGME function calls just
|
||||||
|
reflects transmission errors. */
|
||||||
|
gpgme_error_t err;
|
||||||
|
};
|
||||||
|
typedef struct _gpgme_op_g13_result *gpgme_g13_result_t;
|
||||||
|
|
||||||
|
/* The container is automatically unmounted when the context is reset
|
||||||
|
or destroyed. This is a synchronous convenience interface, which
|
||||||
|
automatically returns an operation error if there is no
|
||||||
|
transmission error. */
|
||||||
|
gpgme_error_t gpgme_op_g13_mount (gpgme_ctx_t ctx, const char *container_file,
|
||||||
|
const char *mount_dir, int flags);
|
||||||
|
|
||||||
|
|
||||||
/* Interface to gpgconf(1). */
|
/* Interface to gpgconf(1). */
|
||||||
|
|
||||||
|
@ -64,6 +64,8 @@ GPGME_1.1 {
|
|||||||
gpgme_op_import_keys_start;
|
gpgme_op_import_keys_start;
|
||||||
gpgme_op_export_keys;
|
gpgme_op_export_keys;
|
||||||
gpgme_op_export_keys_start;
|
gpgme_op_export_keys_start;
|
||||||
|
|
||||||
|
gpgme_op_g13_mount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,6 +59,16 @@ _gpgme_get_gpgconf_path (void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
_gpgme_get_g13_path (void)
|
||||||
|
{
|
||||||
|
#ifdef G13_PATH
|
||||||
|
return G13_PATH;
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* See w32-util.c */
|
/* See w32-util.c */
|
||||||
int
|
int
|
||||||
_gpgme_get_conf_int (const char *key, int *value)
|
_gpgme_get_conf_int (const char *key, int *value)
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
const char *_gpgme_get_gpg_path (void);
|
const char *_gpgme_get_gpg_path (void);
|
||||||
const char *_gpgme_get_gpgsm_path (void);
|
const char *_gpgme_get_gpgsm_path (void);
|
||||||
const char *_gpgme_get_gpgconf_path (void);
|
const char *_gpgme_get_gpgconf_path (void);
|
||||||
|
const char *_gpgme_get_g13_path (void);
|
||||||
int _gpgme_get_conf_int (const char *key, int *value);
|
int _gpgme_get_conf_int (const char *key, int *value);
|
||||||
void _gpgme_allow_set_foreground_window (pid_t pid);
|
void _gpgme_allow_set_foreground_window (pid_t pid);
|
||||||
|
|
||||||
@ -93,6 +94,9 @@ gpgme_error_t _gpgme_decode_c_string (const char *src, char **destp,
|
|||||||
gpgme_error_t _gpgme_decode_percent_string (const char *src, char **destp,
|
gpgme_error_t _gpgme_decode_percent_string (const char *src, char **destp,
|
||||||
size_t len, int binary);
|
size_t len, int binary);
|
||||||
|
|
||||||
|
gpgme_error_t _gpgme_encode_percent_string (const char *src, char **destp,
|
||||||
|
size_t len);
|
||||||
|
|
||||||
|
|
||||||
/* Parse the string TIMESTAMP into a time_t. The string may either be
|
/* Parse the string TIMESTAMP into a time_t. The string may either be
|
||||||
seconds since Epoch or in the ISO 8601 format like
|
seconds since Epoch or in the ISO 8601 format like
|
||||||
|
@ -361,6 +361,25 @@ _gpgme_get_gpgconf_path (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *
|
||||||
|
_gpgme_get_g13_path (void)
|
||||||
|
{
|
||||||
|
static char *g13_program;
|
||||||
|
|
||||||
|
LOCK (get_path_lock);
|
||||||
|
#if 0
|
||||||
|
if (!g13_program)
|
||||||
|
g13_program = find_program_in_registry ("g13Program");
|
||||||
|
#endif
|
||||||
|
if (!g13_program)
|
||||||
|
g13_program = find_program_in_inst_dir ("g13.exe");
|
||||||
|
if (!g13_program)
|
||||||
|
g13_program = find_program_at_standard_place ("GNU\\GnuPG\\g13.exe");
|
||||||
|
UNLOCK (get_path_lock);
|
||||||
|
return g13_program;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
_gpgme_get_w32spawn_path (void)
|
_gpgme_get_w32spawn_path (void)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user