aboutsummaryrefslogtreecommitdiff
path: root/manage.c
diff options
context:
space:
mode:
Diffstat (limited to 'manage.c')
-rw-r--r--manage.c204
1 files changed, 157 insertions, 47 deletions
diff --git a/manage.c b/manage.c
index 820621e..0c99d0f 100644
--- a/manage.c
+++ b/manage.c
@@ -102,6 +102,10 @@ man_help ()
msg (M_CLIENT, "client-pf CID : Define packet filter for client CID (MULTILINE)");
#endif
#endif
+#ifdef MANAGMENT_EXTERNAL_KEY
+ msg (M_CLIENT, "rsa-sig : Enter an RSA signature in response to >RSA_SIGN challenge");
+ msg (M_CLIENT, " Enter signature base64 on subsequent lines followed by END");
+#endif
msg (M_CLIENT, "signal s : Send signal s to daemon,");
msg (M_CLIENT, " s = SIGHUP|SIGTERM|SIGUSR1|SIGUSR2.");
msg (M_CLIENT, "state [on|off] [N|all] : Like log, but show state history.");
@@ -768,49 +772,31 @@ man_hold (struct management *man, const char *cmd)
msg (M_CLIENT, "SUCCESS: hold=%d", BOOL_CAST(man->settings.flags & MF_HOLD));
}
-#ifdef MANAGEMENT_DEF_AUTH
-
-static bool
-parse_cid (const char *str, unsigned long *cid)
-{
- if (sscanf (str, "%lu", cid) == 1)
- return true;
- else
- {
- msg (M_CLIENT, "ERROR: cannot parse CID");
- return false;
- }
-}
+#ifdef MANAGEMENT_IN_EXTRA
-static bool
-parse_kid (const char *str, unsigned int *kid)
-{
- if (sscanf (str, "%u", kid) == 1)
- return true;
- else
- {
- msg (M_CLIENT, "ERROR: cannot parse KID");
- return false;
- }
-}
+#define IER_RESET 0
+#define IER_NEW 1
+#define IER_CONDRESET 2
static void
-in_extra_reset (struct man_connection *mc, const bool new)
+in_extra_reset (struct man_connection *mc, const int mode)
{
- if (mc)
+ if (mc && (mc->in_extra_cmd < IEC_STATEFUL_BASE || mode != IER_CONDRESET))
{
- if (!new)
+ if (mode != IER_NEW)
{
mc->in_extra_cmd = IEC_UNDEF;
+#ifdef MANAGEMENT_DEF_AUTH
mc->in_extra_cid = 0;
mc->in_extra_kid = 0;
+#endif
}
if (mc->in_extra)
{
buffer_list_free (mc->in_extra);
mc->in_extra = NULL;
}
- if (new)
+ if (mode == IER_NEW)
mc->in_extra = buffer_list_new (0);
}
}
@@ -820,6 +806,7 @@ in_extra_dispatch (struct management *man)
{
switch (man->connection.in_extra_cmd)
{
+#ifdef MANAGEMENT_DEF_AUTH
case IEC_CLIENT_AUTH:
if (man->persist.callback.client_auth)
{
@@ -846,6 +833,7 @@ in_extra_dispatch (struct management *man)
msg (M_CLIENT, "ERROR: The client-auth command is not supported by the current daemon mode");
}
break;
+#endif
#ifdef MANAGEMENT_PF
case IEC_CLIENT_PF:
if (man->persist.callback.client_pf)
@@ -870,8 +858,41 @@ in_extra_dispatch (struct management *man)
}
break;
#endif
+#ifdef MANAGMENT_EXTERNAL_KEY
+ case IEC_RSA_SIGN:
+ man->connection.in_extra_cmd = IEC_RSA_SIGN_FINAL;
+ return;
+#endif
+ }
+ in_extra_reset (&man->connection, IER_RESET);
+}
+
+#endif /* MANAGEMENT_IN_EXTRA */
+
+#ifdef MANAGEMENT_DEF_AUTH
+
+static bool
+parse_cid (const char *str, unsigned long *cid)
+{
+ if (sscanf (str, "%lu", cid) == 1)
+ return true;
+ else
+ {
+ msg (M_CLIENT, "ERROR: cannot parse CID");
+ return false;
+ }
+}
+
+static bool
+parse_kid (const char *str, unsigned int *kid)
+{
+ if (sscanf (str, "%u", kid) == 1)
+ return true;
+ else
+ {
+ msg (M_CLIENT, "ERROR: cannot parse KID");
+ return false;
}
- in_extra_reset (&man->connection, false);
}
static void
@@ -884,7 +905,7 @@ man_client_auth (struct management *man, const char *cid_str, const char *kid_st
&& parse_kid (kid_str, &mc->in_extra_kid))
{
mc->in_extra_cmd = IEC_CLIENT_AUTH;
- in_extra_reset (mc, true);
+ in_extra_reset (mc, IER_NEW);
if (!extra)
in_extra_dispatch (man);
}
@@ -980,11 +1001,28 @@ man_client_pf (struct management *man, const char *cid_str)
if (parse_cid (cid_str, &mc->in_extra_cid))
{
mc->in_extra_cmd = IEC_CLIENT_PF;
- in_extra_reset (mc, true);
+ in_extra_reset (mc, IER_NEW);
}
}
-#endif
+#endif /* MANAGEMENT_PF */
+#endif /* MANAGEMENT_DEF_AUTH */
+
+#ifdef MANAGMENT_EXTERNAL_KEY
+
+static void
+man_rsa_sig (struct management *man)
+{
+ struct man_connection *mc = &man->connection;
+ if (mc->in_extra_cmd == IEC_RSA_SIGN_PRE)
+ {
+ in_extra_reset (&man->connection, IER_NEW);
+ mc->in_extra_cmd = IEC_RSA_SIGN;
+ }
+ else
+ msg (M_CLIENT, "ERROR: The rsa-sig command is not currently available");
+}
+
#endif
static void
@@ -1250,6 +1288,12 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
}
#endif
#endif
+#ifdef MANAGMENT_EXTERNAL_KEY
+ else if (streq (p[0], "rsa-sig"))
+ {
+ man_rsa_sig (man);
+ }
+#endif
#ifdef ENABLE_PKCS11
else if (streq (p[0], "pkcs11-id-count"))
{
@@ -1626,8 +1670,8 @@ man_reset_client_socket (struct management *man, const bool exiting)
man->connection.state = MS_INITIAL;
command_line_reset (man->connection.in);
buffer_list_reset (man->connection.out);
-#ifdef MANAGEMENT_DEF_AUTH
- in_extra_reset (&man->connection, false);
+#ifdef MANAGEMENT_IN_EXTRA
+ in_extra_reset (&man->connection, IER_RESET);
#endif
msg (D_MANAGEMENT, "MANAGEMENT: Client disconnected");
}
@@ -1666,8 +1710,8 @@ man_process_command (struct management *man, const char *line)
CLEAR (parms);
so = status_open (NULL, 0, -1, &man->persist.vout, 0);
-#ifdef MANAGEMENT_DEF_AUTH
- in_extra_reset (&man->connection, false);
+#ifdef MANAGEMENT_IN_EXTRA
+ in_extra_reset (&man->connection, IER_CONDRESET);
#endif
if (man_password_needed (man))
@@ -1751,18 +1795,13 @@ man_read (struct management *man)
const unsigned char *line;
while ((line = command_line_get (man->connection.in)))
{
-#ifdef MANAGEMENT_DEF_AUTH
+#ifdef MANAGEMENT_IN_EXTRA
if (man->connection.in_extra)
{
if (!strcmp ((char *)line, "END"))
- {
- in_extra_dispatch (man);
- in_extra_reset (&man->connection, false);
- }
+ in_extra_dispatch (man);
else
- {
- buffer_list_push (man->connection.in_extra, line);
- }
+ buffer_list_push (man->connection.in_extra, line);
}
else
#endif
@@ -2063,8 +2102,8 @@ man_connection_close (struct management *man)
command_line_free (mc->in);
if (mc->out)
buffer_list_free (mc->out);
-#ifdef MANAGEMENT_DEF_AUTH
- in_extra_reset (&man->connection, false);
+#ifdef MANAGEMENT_IN_EXTRA
+ in_extra_reset (&man->connection, IER_RESET);
#endif
man_connection_clear (mc);
}
@@ -2387,7 +2426,7 @@ management_learn_addr (struct management *management,
gc_free (&gc);
}
-#endif
+#endif /* MANAGEMENT_DEF_AUTH */
void
management_echo (struct management *man, const char *string, const bool pull)
@@ -2693,6 +2732,7 @@ man_standalone_event_loop (struct management *man, volatile int *signal_received
#define MWCC_PASSWORD_WAIT (1<<0)
#define MWCC_HOLD_WAIT (1<<1)
+#define MWCC_OTHER_WAIT (1<<2)
/*
* Block until client connects
@@ -2710,6 +2750,8 @@ man_wait_for_client_connection (struct management *man,
msg (D_MANAGEMENT, "Need password(s) from management interface, waiting...");
if (flags & MWCC_HOLD_WAIT)
msg (D_MANAGEMENT, "Need hold release from management interface, waiting...");
+ if (flags & MWCC_OTHER_WAIT)
+ msg (D_MANAGEMENT, "Need information from management interface, waiting...");
do {
man_standalone_event_loop (man, signal_received, expire);
if (signal_received && *signal_received)
@@ -2873,6 +2915,74 @@ management_query_user_pass (struct management *man,
return ret;
}
+#ifdef MANAGMENT_EXTERNAL_KEY
+
+char * /* returns allocated base64 signature */
+management_query_rsa_sig (struct management *man,
+ const char *b64_data)
+{
+ struct gc_arena gc = gc_new ();
+ char *ret = NULL;
+ volatile int signal_received = 0;
+ struct buffer alert_msg = clear_buf();
+ struct buffer *buf;
+ const bool standalone_disabled_save = man->persist.standalone_disabled;
+
+ if (man_standalone_ok (man))
+ {
+ man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */
+ man->persist.special_state_msg = NULL;
+
+ in_extra_reset (&man->connection, IER_RESET);
+ man->connection.in_extra_cmd = IEC_RSA_SIGN_PRE;
+
+ alert_msg = alloc_buf_gc (strlen(b64_data)+64, &gc);
+ buf_printf (&alert_msg, ">RSA_SIGN:%s", b64_data);
+
+ man_wait_for_client_connection (man, &signal_received, 0, MWCC_OTHER_WAIT);
+
+ if (signal_received)
+ goto done;
+
+ man->persist.special_state_msg = BSTR (&alert_msg);
+ msg (M_CLIENT, "%s", man->persist.special_state_msg);
+
+ /* run command processing event loop until we get our signature */
+ do
+ {
+ man_standalone_event_loop (man, &signal_received, 0);
+ if (!signal_received)
+ man_check_for_signals (&signal_received);
+ if (signal_received)
+ goto done;
+ } while (man->connection.in_extra_cmd != IEC_RSA_SIGN_FINAL);
+
+ if (buffer_list_defined(man->connection.in_extra))
+ {
+ buffer_list_aggregate (man->connection.in_extra, 2000);
+ buf = buffer_list_peek (man->connection.in_extra);
+ if (buf && BLEN(buf) > 0)
+ {
+ ret = (char *) malloc(BLEN(buf)+1);
+ check_malloc_return(ret);
+ memcpy(ret, buf->data, BLEN(buf));
+ ret[BLEN(buf)] = '\0';
+ }
+ }
+ }
+
+ done:
+ /* revert state */
+ man->persist.standalone_disabled = standalone_disabled_save;
+ man->persist.special_state_msg = NULL;
+ in_extra_reset (&man->connection, IER_RESET);
+
+ gc_free (&gc);
+ return ret;
+}
+
+#endif
+
/*
* Return true if management_hold() would block
*/