From 92b1342d2f6c235a142451036365b7ac75cef461 Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Fri, 19 Dec 2014 18:18:27 -0500 Subject: [PATCH] Add KILL command and GETINFO --verbose CLIENTS. The KILL command can be used to terminate another client (obtained via GETINFO) when the current client is the invoking user. --- doc/pwmd.html | 152 +++++++++++++++++++++++++++++++---------------------- src/commands.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++--------- src/common.h | 1 + src/pwmd.c | 1 + 4 files changed, 227 insertions(+), 88 deletions(-) diff --git a/doc/pwmd.html b/doc/pwmd.html index f72e4162..b08389bb 100644 --- a/doc/pwmd.html +++ b/doc/pwmd.html @@ -726,6 +726,8 @@ Next: , P • KEYGRIP:   +• KILL:   + • LIST:   • LOCK:   @@ -989,12 +991,15 @@ Next: , Previous:

Syntax:

-
GETINFO [--data] CACHE | CLIENTS | PID | USER | LAST_ERROR | VERSION
+
GETINFO [--data] [--verbose] CACHE | CLIENTS | PID | USER | LAST_ERROR | VERSION
 
-

Get server and other information: cache returns the number of cached -documents via a status message. clients returns the number of -connected clients via a status message. pid returns the process ID +

Get server and other information: CACHE returns the number of cached +documents via a status message. CLIENTS returns the number of +connected clients via a status message or a list of connected clients when +the --verbose parameter is used. The list contains space delimited +fields specifying the thread ID, client name and opened file and is always +returned with a data response. PID returns the process ID number of the server via a data response. VERSION returns the server version number and compile-time features with a data response with each being space delimited. LAST_ERROR returns a detailed description of @@ -1077,7 +1082,7 @@ command.

-Next: , Previous: , Up: Commands   [Contents]

+Next: , Previous: , Up: Commands   [Contents]

21 KEYGRIP command

@@ -1098,13 +1103,32 @@ GPG_ERR_NOT_SUPPORTED.


+ +
+

+Next: , Previous: , Up: Commands   [Contents]

+
+ +

22 KILL command

+ +

Syntax: +

+
KILL <thread_id>
+
+ +

Terminates the client identified by thread_id and releases any file +lock or other resources it has held. See GETINFO for details about listing +connected clients. +

+ +

-Next: , Previous: , Up: Commands   [Contents]

+Next: , Previous: , Up: Commands   [Contents]

-

22 LIST command

+

23 LIST command

Syntax:

@@ -1154,7 +1178,7 @@ arguments are retrieved via a server INQUIRE. Next: , Previous: , Up: Commands   [Contents]

-

23 LOCK command

+

24 LOCK command

Syntax:

@@ -1174,7 +1198,7 @@ command. See UNLOCK. Next: , Previous: , Up: Commands   [Contents]

-

24 LS command

+

25 LS command

Syntax:

@@ -1192,7 +1216,7 @@ Next: , Previous: , Previous: , Up: Commands   [Contents]

-

25 MOVE command

+

26 MOVE command

Syntax:

@@ -1216,7 +1240,7 @@ arguments are retrieved via a server INQUIRE. Next: , Previous: , Up: Commands   [Contents]

-

26 NOP command

+

27 NOP command

Syntax:

@@ -1233,7 +1257,7 @@ Next: , Previous: , Previous: , Up: Commands   [Contents]

-

27 OPEN command

+

28 OPEN command

Syntax:

@@ -1260,7 +1284,7 @@ file has been opened. Next: , Previous: , Up: Commands   [Contents]

-

28 OPTION command

+

29 OPTION command

Syntax:

@@ -1339,7 +1363,7 @@ an error. When -1, then an error will be returned immediately. Next: , Previous: , Up: Commands   [Contents]

-

29 PASSWD command

+

30 PASSWD command

Syntax:

@@ -1372,7 +1396,7 @@ the data file, although a passphrase may be required when changing it. Next: , Previous: , Up: Commands   [Contents]

-

30 REALPATH command

+

31 REALPATH command

Syntax:

@@ -1393,7 +1417,7 @@ arguments are retrieved via a server INQUIRE. Next: , Previous: , Up: Commands   [Contents]

-

31 RENAME command

+

32 RENAME command

Syntax:

@@ -1414,7 +1438,7 @@ arguments are retrieved via a server INQUIRE. Next: , Previous: , Up: Commands   [Contents]

-

32 RESET command

+

33 RESET command

Syntax:

@@ -1431,7 +1455,7 @@ Next: , Previous: , Previous: , Up: Commands   [Contents]

-

33 SAVE command

+

34 SAVE command

Syntax:

@@ -1496,7 +1520,7 @@ has no effect with symmetrically encrypted data files. Next: , Previous: , Up: Commands   [Contents]

-

34 STORE command

+

35 STORE command

Syntax:

@@ -1527,7 +1551,7 @@ to prevent XML parsing and pwmd syntax errors. Next: , Previous: , Up: Commands   [Contents]

-

35 UNLOCK command

+

36 UNLOCK command

Syntax:

@@ -1546,7 +1570,7 @@ see ISCACHED). Next: , Previous: , Up: Commands   [Contents]

-

36 XPATH command

+

37 XPATH command

Syntax:

@@ -1581,7 +1605,7 @@ expression syntax. Previous: , Up: Commands   [Contents]

-

37 XPATHATTR command

+

38 XPATHATTR command

Syntax:

@@ -1615,7 +1639,7 @@ expression syntax. Next: , Previous: , Up: Top   [Contents]

-

38 Status messages and their meanings

+

39 Status messages and their meanings

Some commands send status messages to inform the client about certain operations or as a progress indicator. Status messages begin with a KEYWORD followed by a status description for status messages that @@ -1668,7 +1692,7 @@ and the other being the total bytes to be transferred. Next: , Previous: , Up: Top   [Contents]

-

39 The target attribute

+

40 The target attribute

A case sensitive attribute named target is treated specially when found in each element of an element path. This attribute, like other @@ -1726,7 +1750,7 @@ path after resolving all target attributes. Next: , Previous: , Up: Top   [Contents]

-

40 Recognized signals

+

41 Recognized signals

Sending the SIGHUP signal to a pwmd process will reload the configuration file and sending SIGUSR1 will clear the entire file @@ -1770,25 +1794,26 @@ Previous: , Up: 19 IMPORT command

  • 20 ISCACHED command
  • 21 KEYGRIP command
  • -
  • 22 LIST command
  • -
  • 23 LOCK command
  • -
  • 24 LS command
  • -
  • 25 MOVE command
  • -
  • 26 NOP command
  • -
  • 27 OPEN command
  • -
  • 28 OPTION command
  • -
  • 29 PASSWD command
  • -
  • 30 REALPATH command
  • -
  • 31 RENAME command
  • -
  • 32 RESET command
  • -
  • 33 SAVE command
  • -
  • 34 STORE command
  • -
  • 35 UNLOCK command
  • -
  • 36 XPATH command
  • -
  • 37 XPATHATTR command
  • -
  • 38 Status messages and their meanings
  • -
  • 39 The target attribute
  • -
  • 40 Recognized signals
  • +
  • 22 KILL command
  • +
  • 23 LIST command
  • +
  • 24 LOCK command
  • +
  • 25 LS command
  • +
  • 26 MOVE command
  • +
  • 27 NOP command
  • +
  • 28 OPEN command
  • +
  • 29 OPTION command
  • +
  • 30 PASSWD command
  • +
  • 31 REALPATH command
  • +
  • 32 RENAME command
  • +
  • 33 RESET command
  • +
  • 34 SAVE command
  • +
  • 35 STORE command
  • +
  • 36 UNLOCK command
  • +
  • 37 XPATH command
  • +
  • 38 XPATHATTR command
  • +
  • 39 Status messages and their meanings
  • +
  • 40 The target attribute
  • +
  • 41 Recognized signals
  • Concept Index
  • @@ -1820,25 +1845,26 @@ Previous: , Up: 19 IMPORT command
  • 20 ISCACHED command
  • 21 KEYGRIP command
  • -
  • 22 LIST command
  • -
  • 23 LOCK command
  • -
  • 24 LS command
  • -
  • 25 MOVE command
  • -
  • 26 NOP command
  • -
  • 27 OPEN command
  • -
  • 28 OPTION command
  • -
  • 29 PASSWD command
  • -
  • 30 REALPATH command
  • -
  • 31 RENAME command
  • -
  • 32 RESET command
  • -
  • 33 SAVE command
  • -
  • 34 STORE command
  • -
  • 35 UNLOCK command
  • -
  • 36 XPATH command
  • -
  • 37 XPATHATTR command
  • -
  • 38 Status messages and their meanings
  • -
  • 39 The target attribute
  • -
  • 40 Recognized signals
  • +
  • 22 KILL command
  • +
  • 23 LIST command
  • +
  • 24 LOCK command
  • +
  • 25 LS command
  • +
  • 26 MOVE command
  • +
  • 27 NOP command
  • +
  • 28 OPEN command
  • +
  • 29 OPTION command
  • +
  • 30 PASSWD command
  • +
  • 31 REALPATH command
  • +
  • 32 RENAME command
  • +
  • 33 RESET command
  • +
  • 34 SAVE command
  • +
  • 35 STORE command
  • +
  • 36 UNLOCK command
  • +
  • 37 XPATH command
  • +
  • 38 XPATHATTR command
  • +
  • 39 Status messages and their meanings
  • +
  • 40 The target attribute
  • +
  • 41 Recognized signals
  • Concept Index
  • diff --git a/src/commands.c b/src/commands.c index 13d8c732..582986c9 100644 --- a/src/commands.c +++ b/src/commands.c @@ -61,7 +61,7 @@ #define OPT_NO_PASSPHRASE 0x0002 #define OPT_RESET 0x0004 #define OPT_LIST_RECURSE 0x0008 -#define OPT_LIST_VERBOSE 0x0010 +#define OPT_VERBOSE 0x0010 #define OPT_LOCK 0x0020 #define OPT_LOCK_ON_OPEN 0x0040 #define OPT_SIGN 0x0080 @@ -1573,11 +1573,11 @@ parse_list_opt_norecurse (void *data, void *value) } static gpg_error_t -parse_list_opt_verbose (void *data, void *value) +parse_opt_verbose (void *data, void *value) { struct client_s *client = data; - client->opts |= OPT_LIST_VERBOSE; + client->opts |= OPT_VERBOSE; return 0; } @@ -1679,7 +1679,7 @@ do_list (assuan_context_t ctx, char *line) elements->recurse = client->opts & OPT_LIST_RECURSE; elements->verbose = - (client->opts & OPT_LIST_VERBOSE) | (client->opts & OPT_LIST_WITH_TARGET); + (client->opts & OPT_VERBOSE) | (client->opts & OPT_LIST_WITH_TARGET); elements->with_target = client->opts & OPT_LIST_WITH_TARGET; if (!line || !*line) @@ -1723,7 +1723,7 @@ do_list (assuan_context_t ctx, char *line) elements->recurse = client->opts & OPT_LIST_RECURSE; elements->verbose = - (client->opts & OPT_LIST_VERBOSE) | (client->opts & + (client->opts & OPT_VERBOSE) | (client->opts & OPT_LIST_WITH_TARGET); elements->with_target = client->opts & OPT_LIST_WITH_TARGET; pthread_cleanup_push (list_command_cleanup2, elements); @@ -1767,7 +1767,7 @@ list_command (assuan_context_t ctx, char *line) struct argv_s *args[] = { &(struct argv_s) {"no-recurse", OPTION_TYPE_NOARG, parse_list_opt_norecurse}, - &(struct argv_s) {"verbose", OPTION_TYPE_NOARG, parse_list_opt_verbose}, + &(struct argv_s) {"verbose", OPTION_TYPE_NOARG, parse_opt_verbose}, &(struct argv_s) {"inquire", OPTION_TYPE_NOARG, parse_opt_inquire}, &(struct argv_s) {"with-target", OPTION_TYPE_NOARG, parse_list_opt_target}, @@ -1784,7 +1784,7 @@ list_command (assuan_context_t ctx, char *line) return send_error (ctx, rc); if (client->opts & OPT_LIST_ALL) - client->opts |= OPT_LIST_RECURSE | OPT_LIST_VERBOSE; + client->opts |= OPT_LIST_RECURSE | OPT_VERBOSE; if (client->opts & OPT_INQUIRE) { @@ -3269,13 +3269,19 @@ option_command (assuan_context_t ctx, char *line) if (tmp) xfree (tmp); + MUTEX_LOCK (&cn_mutex); + xfree (client->thd->name); + client->thd->name = NULL; + if (!value || !*value) - { - pthread_setspecific (thread_name_key, str_dup ("")); - goto done; - } + pthread_setspecific (thread_name_key, str_dup ("")); + else + { + client->thd->name = str_dup (value); + pthread_setspecific (thread_name_key, str_dup (value)); + } - pthread_setspecific (thread_name_key, str_dup (value)); + MUTEX_UNLOCK (&cn_mutex); goto done; } else if (strcasecmp (name, (char *) "lc-messages") == 0) @@ -4365,6 +4371,64 @@ parse_opt_data (void *data, void *value) } static gpg_error_t +send_client_list (assuan_context_t ctx) +{ + struct client_s *client = assuan_get_pointer (ctx); + gpg_error_t rc = 0; + char buf[ASSUAN_LINELENGTH]; + + if (client->opts & OPT_VERBOSE) + { + unsigned i, t; + char **list = NULL; + char *line; + + MUTEX_LOCK (&cn_mutex); + pthread_cleanup_push (cleanup_mutex_cb, &cn_mutex); + t = slist_length (cn_thread_list); + + for (i = 0; i < t; i++) + { + struct client_thread_s *thd = slist_nth_data (cn_thread_list, i); + + if (!strv_printf (&list, "%p %s %s", thd->tid, + thd->name ? thd->name : "-", + thd->cl && thd->cl->filename + ? thd->cl->filename : "-")) + { + strv_free (list); + rc = GPG_ERR_ENOMEM; + break; + } + } + + pthread_cleanup_pop (1); + if (rc) + return rc; + + line = strv_join ("\n", list); + strv_free (list); + pthread_cleanup_push (xfree, line); + rc = xfer_data (ctx, line, strlen (line)); + pthread_cleanup_pop (1); + return rc; + } + + if (client->opts & OPT_DATA) + { + MUTEX_LOCK (&cn_mutex); + pthread_cleanup_push (cleanup_mutex_cb, &cn_mutex); + snprintf (buf, sizeof (buf), "%i", slist_length (cn_thread_list)); + pthread_cleanup_pop (1); + rc = xfer_data (ctx, buf, strlen (buf)); + } + else + rc = send_status (ctx, STATUS_CLIENTS, NULL); + + return rc; +} + +static gpg_error_t getinfo_command (assuan_context_t ctx, char *line) { struct client_s *client = assuan_get_pointer (ctx); @@ -4372,6 +4436,7 @@ getinfo_command (assuan_context_t ctx, char *line) char buf[ASSUAN_LINELENGTH]; struct argv_s *args[] = { &(struct argv_s) {"data", OPTION_TYPE_NOARG, parse_opt_data}, + &(struct argv_s) {"verbose", OPTION_TYPE_NOARG, parse_opt_verbose}, NULL }; @@ -4381,15 +4446,7 @@ getinfo_command (assuan_context_t ctx, char *line) if (!strcasecmp (line, "clients")) { - if (client->opts & OPT_DATA) - { - MUTEX_LOCK (&cn_mutex); - snprintf (buf, sizeof (buf), "%i", slist_length (cn_thread_list)); - MUTEX_UNLOCK (&cn_mutex); - rc = xfer_data (ctx, buf, strlen (buf)); - } - else - rc = send_status (ctx, STATUS_CLIENTS, NULL); + rc = send_client_list (ctx); } else if (!strcasecmp (line, "cache")) { @@ -4492,6 +4549,50 @@ send_status_cb (void *user, const char *line) #endif static gpg_error_t +kill_command (assuan_context_t ctx, char *line) +{ +#ifdef HAVE_PTHREAD_CANCEL + struct client_s *client = assuan_get_pointer (ctx); + gpg_error_t rc; + + if (!line || !*line) + return send_error (ctx, GPG_ERR_SYNTAX); + + rc = peer_is_invoker (client); + if (!rc) + { + unsigned i, t; + + MUTEX_LOCK (&cn_mutex); + pthread_cleanup_push (cleanup_mutex_cb, &cn_mutex); + t = slist_length (cn_thread_list); + + for (i = 0; i < t; i++) + { + struct client_thread_s *thd = slist_nth_data (cn_thread_list, i); + char *tmp = str_asprintf ("%p", thd->tid); + + if (strcmp (line, tmp)) + { + xfree (tmp); + continue; + } + + xfree (tmp); + rc = pthread_cancel (thd->tid); + break; + } + + pthread_cleanup_pop (1); + } + + return send_error (ctx, rc); +#else + return send_error (ctx, GPG_ERR_NOT_IMPLEMENTED); +#endif +} + +static gpg_error_t agent_command (assuan_context_t ctx, char *line) { gpg_error_t rc = 0; @@ -4548,11 +4649,21 @@ init_commands () "@command{gpg-agent}." )); + new_command("KILL", 1, 0, kill_command, _( +"KILL \n" +"Terminates the client identified by @var{thread_id} and releases any file " +"lock or other resources it has held. @xref{GETINFO} for details about listing " +"connected clients.\n" +)); + new_command("GETINFO", 1, 1, getinfo_command, _( -"GETINFO [--data] CACHE | CLIENTS | PID | USER | LAST_ERROR | VERSION\n" -"Get server and other information: @var{cache} returns the number of cached " -"documents via a status message. @var{clients} returns the number of " -"connected clients via a status message. @var{pid} returns the process ID " +"GETINFO [--data] [--verbose] CACHE | CLIENTS | PID | USER | LAST_ERROR | VERSION\n" +"Get server and other information: @var{CACHE} returns the number of cached " +"documents via a status message. @var{CLIENTS} returns the number of " +"connected clients via a status message or a list of connected clients when " +"the @option{--verbose} parameter is used. The list contains space delimited " +"fields specifying the thread ID, client name and opened file and is always " +"returned with a data response. @var{PID} returns the process ID " "number of the server via a data response. @var{VERSION} returns the server " "version number and compile-time features with a data response with each " "being space delimited. @var{LAST_ERROR} returns a detailed description of " diff --git a/src/common.h b/src/common.h index c80ad08d..9c727fde 100644 --- a/src/common.h +++ b/src/common.h @@ -61,6 +61,7 @@ struct client_thread_s { pthread_t tid; + char *name; int fd; pthread_mutex_t status_mutex; struct status_msg_s *msg_queue; diff --git a/src/pwmd.c b/src/pwmd.c index 41fc9917..191b2ef6 100644 --- a/src/pwmd.c +++ b/src/pwmd.c @@ -1069,6 +1069,7 @@ cleanup_cb (void *arg) send_status_all (STATUS_CLIENTS, NULL); } + xfree (cn->name); xfree (cn); pthread_cond_signal (&quit_cond); } -- 2.11.4.GIT