1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

Implemented the STATUSFD mechanism.

2007-08-16  Moritz Schulte  <moritz@g10code.com>

	* command.c: Include "statusfd.h".
	(cmd_statusfd): New function.
	(register_commands): New entry for STATUSFD command.
	(update_reader_status_file): Call statusfd_event_card_inserted and
	statusfd_event_card_removed on events.
	(scd_command_handler): Pass flags=3 to
	assuan_init_socket_server_ext (enabling fd passing).
	* statusfd.c, statusfd.h: New files.
	* Makefile.am (scdaemon_SOURCES): Added statusfd.c, statusfd.h.
	* NOTES-STATUSFD: New file.
This commit is contained in:
Moritz Schulte 2007-08-16 12:44:17 +00:00
parent fe750f0c7c
commit 62039d815e
6 changed files with 257 additions and 1 deletions

View File

@ -1,3 +1,16 @@
2007-08-16 Moritz Schulte <moritz@g10code.com>
* command.c: Include "statusfd.h".
(cmd_statusfd): New function.
(register_commands): New entry for STATUSFD command.
(update_reader_status_file): Call statusfd_event_card_inserted and
statusfd_event_card_removed on events.
(scd_command_handler): Pass flags=3 to
assuan_init_socket_server_ext (enabling fd passing).
* statusfd.c, statusfd.h: New files.
* Makefile.am (scdaemon_SOURCES): Added statusfd.c, statusfd.h.
* NOTES-STATUSFD: New file.
2007-08-07 Werner Koch <wk@g10code.com> 2007-08-07 Werner Koch <wk@g10code.com>
* tlv.c, tlv.h: Move to ../common/. * tlv.c, tlv.h: Move to ../common/.

View File

@ -38,6 +38,7 @@ scdaemon_SOURCES = \
apdu.c apdu.h \ apdu.c apdu.h \
ccid-driver.c ccid-driver.h \ ccid-driver.c ccid-driver.h \
iso7816.c iso7816.h \ iso7816.c iso7816.h \
statusfd.c statusfd.h \
app.c app-common.h app-help.c $(card_apps) app.c app-common.h app-help.c $(card_apps)

36
scd/NOTES-STATUSFD Normal file
View File

@ -0,0 +1,36 @@
Description of the statusfd mechanism:
Applications can now ask scdaemon to be notified about certain events
(card inserted/removed) on a specified file descriptor.
This is how it works:
Run gpg-agent in daemon mode.
Figure out scdaemons socket:
moritz@pink:~/g10/hacks/gnupg-mo/build/scd$ gpg-connect-agent
SCD GETINFO socket_name
D /tmp/gpg-QZRVNr/S.scdaemon
OK
Connect to scdaemon and register a status file descriptor:
moritz@pink:~/g10/hacks/gnupg-mo/build/scd$ gpg-connect-agent -S /tmp/gpg-QZRVNr/S.scdaemon
/sendfd /tmp/scd-events w
STATUSFD
OK
moritz@pink:~/g10/hacks/gnupg-mo/build/scd$
Watch the log file as you remove/insert the smartcard:
moritz@pink:~/g10/hacks/gnupg-mo/build/scd$ tail -f /tmp/scd-events
CARD REMOVED
CARD INSERTED
CARD REMOVED
CARD INSERTED
^C
moritz@pink:~/g10/hacks/gnupg-mo/build/scd$
That's it for now.

View File

@ -40,6 +40,7 @@
#ifdef HAVE_LIBUSB #ifdef HAVE_LIBUSB
#include "ccid-driver.h" #include "ccid-driver.h"
#endif #endif
#include "statusfd.h"
/* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */ /* Maximum length allowed as a PIN; used for INQUIRE NEEDPIN */
#define MAXLEN_PIN 100 #define MAXLEN_PIN 100
@ -1649,6 +1650,34 @@ cmd_apdu (assuan_context_t ctx, char *line)
return rc; return rc;
} }
/* STATUSFD
*/
static int
cmd_statusfd (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
int rc;
int fd;
/* FIXME, moritz, locking? */
if ( IS_LOCKED (ctrl) )
return gpg_error (GPG_ERR_LOCKED);
rc = assuan_receivefd (ctx, &fd);
if (rc)
/* FIXME, moritz, proper error message for client? */
goto leave;
rc = statusfd_register (fd);
leave:
if (rc)
close (fd);
return rc;
}
@ -1683,6 +1712,7 @@ register_commands (assuan_context_t ctx)
{ "GETINFO", cmd_getinfo }, { "GETINFO", cmd_getinfo },
{ "RESTART", cmd_restart }, { "RESTART", cmd_restart },
{ "APDU", cmd_apdu }, { "APDU", cmd_apdu },
{ "STATUSFD", cmd_statusfd },
{ NULL } { NULL }
}; };
int i, rc; int i, rc;
@ -1719,7 +1749,7 @@ scd_command_handler (ctrl_t ctrl, int fd)
} }
else else
{ {
rc = assuan_init_socket_server_ext (&ctx, fd, 2); rc = assuan_init_socket_server_ext (&ctx, fd, 3);
} }
if (rc) if (rc)
{ {
@ -1880,6 +1910,15 @@ update_reader_status_file (void)
log_info ("updating status of slot %d to 0x%04X\n", log_info ("updating status of slot %d to 0x%04X\n",
ss->slot, status); ss->slot, status);
{
/* Broadcast on statusfds. */
if ((! (ss->status & 2)) && (status & 2))
statusfd_event_card_inserted (0);
if ((ss->status & 2) && (! (status & 2)))
statusfd_event_card_removed (0);
}
/* FIXME: Should this be IDX instead of ss->slot? This /* FIXME: Should this be IDX instead of ss->slot? This
depends on how client sessions will associate the reader depends on how client sessions will associate the reader
status with their session. */ status with their session. */

139
scd/statusfd.c Normal file
View File

@ -0,0 +1,139 @@
/* statusfd.c - SCdaemon status fd handling
* Copyright (C) 2007 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 3 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, see <http://www.gnu.org/licenses/>.
*/
/* AUTHOR: Moritz Schulte <moritz@g10code.com>. */
#include <config.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pth.h>
#include "scdaemon.h"
#include "statusfd.h"
struct statusfd_s
{
FILE *stream;
struct statusfd_s *next, **prevp;
};
typedef struct statusfd_s *statusfd_t;
static statusfd_t statusfd_list;
static int
statusfd_add (FILE *stream)
{
statusfd_t statusfd_obj;
int rc;
statusfd_obj = xtrymalloc (sizeof (*statusfd_obj));
if (statusfd_obj)
{
statusfd_obj->stream = stream;
statusfd_obj->next = statusfd_list;
statusfd_obj->prevp = &statusfd_list;
if (statusfd_list)
statusfd_list->prevp = &statusfd_obj->next;
statusfd_list = statusfd_obj;
rc = 0;
}
else
rc = gpg_error_from_syserror ();
return rc;
}
static void
statusfd_remove (statusfd_t statusfd)
{
*statusfd->prevp = statusfd->next;
if (statusfd->next)
statusfd->next->prevp = statusfd->prevp;
xfree (statusfd);
}
static void
statusfd_broadcast (const char *fmt, ...)
{
statusfd_t statusfd = statusfd_list;
statusfd_t statusfd_next;
int ret;
va_list ap;
va_start (ap, fmt);
while (statusfd)
{
ret = vfprintf (statusfd->stream, fmt, ap);
if (ret >= 0)
ret = fflush (statusfd->stream);
if (ret < 0)
{
/* Error on this statusfd stream, remove it. */
/* FIXME: only remove on certain errros? -moritz */
statusfd_next = statusfd->next;
statusfd_remove (statusfd);
statusfd = statusfd_next;
continue;
}
statusfd = statusfd->next;
}
va_end (ap);
}
int
statusfd_register (int fd)
{
FILE *stream;
int rc;
stream = fdopen (fd, "a");
if (! stream)
rc = gpg_error_from_syserror ();
else
rc = statusfd_add (stream);
if (rc && stream)
fclose (stream);
return rc;
}
void
statusfd_event_card_inserted (int slot)
{
statusfd_broadcast ("CARD INSERTED\n");
}
void
statusfd_event_card_removed (int slot)
{
statusfd_broadcast ("CARD REMOVED\n");
}

28
scd/statusfd.h Normal file
View File

@ -0,0 +1,28 @@
/* statusfd.h - SCdaemon status fd handling
* Copyright (C) 2007 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef GNUPG_SCD_STATUSFD_H
#define GNUPG_SCD_STATUSFD_H
int statusfd_register (int fd);
void statusfd_event_card_inserted (int slot);
void statusfd_event_card_removed (int slot);
#endif