summaryrefslogtreecommitdiff
path: root/src/openvpn/manage.c
diff options
context:
space:
mode:
authorAlberto Gonzalez Iniesta <agi@inittab.org>2016-11-21 09:37:33 +0100
committerAlberto Gonzalez Iniesta <agi@inittab.org>2016-11-21 09:37:33 +0100
commit20c8675ba46bda97330a4117c459a59a9f1c465e (patch)
treed888c714fb61947dd79dc44b64a4aaae2f70bfb7 /src/openvpn/manage.c
parentffca24bed7a03d95585ad02278667abe75d8b272 (diff)
New upstream version 2.4~beta1upstream/2.4_beta1
Diffstat (limited to 'src/openvpn/manage.c')
-rw-r--r--src/openvpn/manage.c449
1 files changed, 355 insertions, 94 deletions
diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c
index 0a4542a..77a8006 100644
--- a/src/openvpn/manage.c
+++ b/src/openvpn/manage.c
@@ -113,6 +113,8 @@ man_help ()
#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");
+ msg (M_CLIENT, "certificate : Enter a client certificate in response to >NEED-CERT challenge");
+ msg (M_CLIENT, " Enter certificate 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.");
@@ -268,7 +270,7 @@ man_delete_unix_socket (struct management *man)
static void
man_close_socket (struct management *man, const socket_descriptor_t sd)
{
-#ifndef WIN32
+#ifndef _WIN32
/*
* Windows doesn't need this because the ne32 event is permanently
* enabled at struct management scope.
@@ -701,7 +703,7 @@ man_query_need_str (struct management *man, const char *type, const char *action
static void
man_forget_passwords (struct management *man)
{
-#if defined(ENABLE_CRYPTO) && defined(ENABLE_SSL)
+#ifdef ENABLE_CRYPTO
ssl_purge_auth (false);
msg (M_CLIENT, "SUCCESS: Passwords were forgotten");
#endif
@@ -868,6 +870,12 @@ in_extra_dispatch (struct management *man)
man->connection.ext_key_input = man->connection.in_extra;
man->connection.in_extra = NULL;
return;
+ case IEC_CERTIFICATE:
+ man->connection.ext_cert_state = EKS_READY;
+ buffer_list_free (man->connection.ext_cert_input);
+ man->connection.ext_cert_input = man->connection.in_extra;
+ man->connection.in_extra = NULL;
+ return;
#endif
}
in_extra_reset (&man->connection, IER_RESET);
@@ -1030,6 +1038,20 @@ man_rsa_sig (struct management *man)
msg (M_CLIENT, "ERROR: The rsa-sig command is not currently available");
}
+static void
+man_certificate (struct management *man)
+{
+ struct man_connection *mc = &man->connection;
+ if (mc->ext_cert_state == EKS_SOLICIT)
+ {
+ mc->ext_cert_state = EKS_INPUT;
+ mc->in_extra_cmd = IEC_CERTIFICATE;
+ in_extra_reset (mc, IER_NEW);
+ }
+ else
+ msg (M_CLIENT, "ERROR: The certificate command is not currently available");
+}
+
#endif
static void
@@ -1105,6 +1127,27 @@ man_remote (struct management *man, const char **p)
}
}
+#ifdef TARGET_ANDROID
+static void
+man_network_change (struct management *man, bool samenetwork)
+{
+ /* Called to signal the OpenVPN that the network configuration has changed and
+ the client should either float or reconnect.
+
+ The code is currently only used by ics-openvpn
+ */
+ if (man->persist.callback.network_change)
+ {
+ int fd = (*man->persist.callback.network_change)
+ (man->persist.callback.arg, samenetwork);
+ man->connection.fdtosend = fd;
+ msg (M_CLIENT, "PROTECTFD: fd '%d' sent to be protected", fd);
+ if (fd == -2)
+ man_signal (man, "SIGUSR1");
+ }
+}
+#endif
+
static void
man_dispatch_command (struct management *man, struct status_output *so, const char **p, const int nparms)
{
@@ -1148,6 +1191,16 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
if (man_need (man, p, 1, 0))
man_signal (man, p[1]);
}
+#ifdef TARGET_ANDROID
+ else if (streq (p[0], "network-change"))
+ {
+ bool samenetwork = false;
+ if (p[1] && streq(p[1], "samenetwork"))
+ samenetwork = true;
+
+ man_network_change(man, samenetwork);
+ }
+#endif
else if (streq (p[0], "load-stats"))
{
man_load_stats (man);
@@ -1311,6 +1364,10 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
{
man_rsa_sig (man);
}
+ else if (streq (p[0], "certificate"))
+ {
+ man_certificate (man);
+ }
#endif
#ifdef ENABLE_PKCS11
else if (streq (p[0], "pkcs11-id-count"))
@@ -1356,7 +1413,7 @@ man_dispatch_command (struct management *man, struct status_output *so, const ch
gc_free (&gc);
}
-#ifdef WIN32
+#ifdef _WIN32
static void
man_start_ne32 (struct management *man)
@@ -1446,7 +1503,7 @@ man_new_connection_post (struct management *man, const char *description)
man_connection_settings_reset (man);
-#ifdef WIN32
+#ifdef _WIN32
man_start_ne32 (man);
#endif
@@ -1461,7 +1518,7 @@ man_new_connection_post (struct management *man, const char *description)
#endif
msg (D_MANAGEMENT, "MANAGEMENT: %s %s",
description,
- print_sockaddr (&man->settings.local, &gc));
+ print_sockaddr (man->settings.local->ai_addr, &gc));
buffer_list_reset (man->connection.out);
@@ -1533,7 +1590,7 @@ man_accept (struct management *man)
if (socket_defined (man->connection.sd_top))
{
-#ifdef WIN32
+#ifdef _WIN32
man_stop_ne32 (man);
#endif
}
@@ -1568,8 +1625,9 @@ man_listen (struct management *man)
else
#endif
{
- man->connection.sd_top = create_socket_tcp (AF_INET);
- socket_bind (man->connection.sd_top, &man->settings.local, "MANAGEMENT");
+ man->connection.sd_top = create_socket_tcp (man->settings.local);
+ socket_bind (man->connection.sd_top, man->settings.local,
+ man->settings.local->ai_family, "MANAGEMENT", false);
}
/*
@@ -1593,10 +1651,10 @@ man_listen (struct management *man)
else
#endif
msg (D_MANAGEMENT, "MANAGEMENT: TCP Socket listening on %s",
- print_sockaddr (&man->settings.local, &gc));
+ print_sockaddr (man->settings.local->ai_addr, &gc));
}
-#ifdef WIN32
+#ifdef _WIN32
man_start_ne32 (man);
#endif
@@ -1634,9 +1692,9 @@ man_connect (struct management *man)
else
#endif
{
- man->connection.sd_cli = create_socket_tcp (AF_INET);
+ man->connection.sd_cli = create_socket_tcp (man->settings.local);
status = openvpn_connect (man->connection.sd_cli,
- &man->settings.local,
+ man->settings.local->ai_addr,
5,
&signal_received);
}
@@ -1661,7 +1719,7 @@ man_connect (struct management *man)
#endif
msg (D_LINK_ERRORS,
"MANAGEMENT: connect to %s failed: %s",
- print_sockaddr (&man->settings.local, &gc),
+ print_sockaddr (man->settings.local->ai_addr, &gc),
strerror_ts (status, &gc));
throw_signal_soft (SIGTERM, "management-connect-failed");
goto done;
@@ -1679,7 +1737,7 @@ man_reset_client_socket (struct management *man, const bool exiting)
{
if (socket_defined (man->connection.sd_cli))
{
-#ifdef WIN32
+#ifdef _WIN32
man_stop_ne32 (man);
#endif
man_close_socket (man, man->connection.sd_cli);
@@ -1694,7 +1752,7 @@ man_reset_client_socket (struct management *man, const bool exiting)
}
if (!exiting)
{
-#if defined(ENABLE_CRYPTO) && defined(ENABLE_SSL)
+#ifdef ENABLE_CRYPTO
if (man->settings.flags & MF_FORGET_DISCONNECT)
ssl_purge_auth (false);
#endif
@@ -1779,6 +1837,120 @@ man_io_error (struct management *man, const char *prefix)
return false;
}
+#ifdef TARGET_ANDROID
+static ssize_t man_send_with_fd (int fd, void *ptr, size_t nbytes, int flags, int sendfd)
+{
+ struct msghdr msg;
+ struct iovec iov[1];
+
+ union {
+ struct cmsghdr cm;
+ char control[CMSG_SPACE(sizeof(int))];
+ } control_un;
+ struct cmsghdr *cmptr;
+
+ msg.msg_control = control_un.control;
+ msg.msg_controllen = sizeof(control_un.control);
+
+ cmptr = CMSG_FIRSTHDR(&msg);
+ cmptr->cmsg_len = CMSG_LEN(sizeof(int));
+ cmptr->cmsg_level = SOL_SOCKET;
+ cmptr->cmsg_type = SCM_RIGHTS;
+ *((int *) CMSG_DATA(cmptr)) = sendfd;
+
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+
+ iov[0].iov_base = ptr;
+ iov[0].iov_len = nbytes;
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+
+ return (sendmsg(fd, &msg, flags));
+}
+
+static ssize_t man_recv_with_fd (int fd, void *ptr, size_t nbytes, int flags, int *recvfd)
+{
+ struct msghdr msghdr;
+ struct iovec iov[1];
+ ssize_t n;
+
+ union {
+ struct cmsghdr cm;
+ char control[CMSG_SPACE(sizeof (int))];
+ } control_un;
+ struct cmsghdr *cmptr;
+
+ msghdr.msg_control = control_un.control;
+ msghdr.msg_controllen = sizeof(control_un.control);
+
+ msghdr.msg_name = NULL;
+ msghdr.msg_namelen = 0;
+
+ iov[0].iov_base = ptr;
+ iov[0].iov_len = nbytes;
+ msghdr.msg_iov = iov;
+ msghdr.msg_iovlen = 1;
+
+ if ( (n = recvmsg(fd, &msghdr, flags)) <= 0)
+ return (n);
+
+ if ( (cmptr = CMSG_FIRSTHDR(&msghdr)) != NULL &&
+ cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
+ if (cmptr->cmsg_level != SOL_SOCKET)
+ msg (M_ERR, "control level != SOL_SOCKET");
+ if (cmptr->cmsg_type != SCM_RIGHTS)
+ msg (M_ERR, "control type != SCM_RIGHTS");
+ *recvfd = *((int *) CMSG_DATA(cmptr));
+ } else
+ *recvfd = -1; /* descriptor was not passed */
+
+ return (n);
+}
+
+/*
+ * The android control method will instruct the GUI part of openvpn to do
+ * the route/ifconfig/open tun command. See doc/android.txt for details.
+ */
+bool management_android_control (struct management *man, const char *command, const char *msg)
+{
+ struct user_pass up;
+ CLEAR(up);
+ strncpy (up.username, msg, sizeof(up.username)-1);
+
+ management_query_user_pass(management, &up , command, GET_USER_PASS_NEED_OK,(void*) 0);
+ return strcmp ("ok", up.password)==0;
+}
+
+/*
+ * In Android 4.4 it is not possible to open a new tun device and then close the
+ * old tun device without breaking the whole VPNService stack until the device
+ * is rebooted. This management method ask the UI what method should be taken to
+ * ensure the optimal solution for the situation
+ */
+int managment_android_persisttun_action (struct management *man)
+{
+ struct user_pass up;
+ CLEAR(up);
+ strcpy(up.username,"tunmethod");
+ management_query_user_pass(management, &up , "PERSIST_TUN_ACTION",
+ GET_USER_PASS_NEED_OK,(void*) 0);
+ if (!strcmp("NOACTION", up.password))
+ return ANDROID_KEEP_OLD_TUN;
+ else if (!strcmp ("OPEN_AFTER_CLOSE", up.password))
+ return ANDROID_OPEN_AFTER_CLOSE;
+ else if (!strcmp ("OPEN_BEFORE_CLOSE", up.password))
+ return ANDROID_OPEN_BEFORE_CLOSE;
+ else
+ msg (M_ERR, "Got unrecognised '%s' from management for PERSIST_TUN_ACTION query", up.password);
+
+ ASSERT(0);
+ return ANDROID_OPEN_AFTER_CLOSE;
+}
+
+
+#endif
+
static int
man_read (struct management *man)
{
@@ -1788,7 +1960,15 @@ man_read (struct management *man)
unsigned char buf[256];
int len = 0;
+#ifdef TARGET_ANDROID
+ int fd;
+ len = man_recv_with_fd (man->connection.sd_cli, buf, sizeof (buf), MSG_NOSIGNAL, &fd);
+ if(fd >= 0)
+ man->connection.lastfdreceived = fd;
+#else
len = recv (man->connection.sd_cli, buf, sizeof (buf), MSG_NOSIGNAL);
+#endif
+
if (len == 0)
{
man_reset_client_socket (man, false);
@@ -1865,6 +2045,13 @@ man_write (struct management *man)
if (buf && BLEN (buf))
{
const int len = min_int (size_hint, BLEN (buf));
+#ifdef TARGET_ANDROID
+ if (man->connection.fdtosend > 0)
+ {
+ sent = man_send_with_fd (man->connection.sd_cli, BPTR (buf), len, MSG_NOSIGNAL,man->connection.fdtosend);
+ man->connection.fdtosend = -1;
+ } else
+#endif
sent = send (man->connection.sd_cli, BPTR (buf), len, MSG_NOSIGNAL);
if (sent >= 0)
{
@@ -1957,7 +2144,7 @@ man_persist_close (struct man_persist *mp)
static void
man_settings_init (struct man_settings *ms,
const char *addr,
- const int port,
+ const char *port,
const char *pass_file,
const char *client_user,
const char *client_group,
@@ -2010,12 +2197,6 @@ man_settings_init (struct man_settings *ms,
else
#endif
{
- /*
- * Initialize socket address
- */
- ms->local.addr.in4.sin_family = AF_INET;
- ms->local.addr.in4.sin_addr.s_addr = 0;
- ms->local.addr.in4.sin_port = htons (port);
/*
* Run management over tunnel, or
@@ -2027,8 +2208,15 @@ man_settings_init (struct man_settings *ms,
}
else
{
- ms->local.addr.in4.sin_addr.s_addr = getaddr
- (GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL, addr, 0, NULL, NULL);
+ int status;
+ int resolve_flags = GETADDR_RESOLVE|GETADDR_WARN_ON_SIGNAL|GETADDR_FATAL;
+
+ if (! (flags & MF_CONNECT_AS_CLIENT))
+ resolve_flags |= GETADDR_PASSIVE;
+
+ status = openvpn_getaddrinfo (resolve_flags, addr, port, 0,
+ NULL, AF_UNSPEC, &ms->local);
+ ASSERT(status==0);
}
}
@@ -2054,6 +2242,8 @@ man_settings_init (struct man_settings *ms,
static void
man_settings_close (struct man_settings *ms)
{
+ if (ms->local)
+ freeaddrinfo(ms->local);
free (ms->write_peer_info_file);
CLEAR (*ms);
}
@@ -2064,7 +2254,7 @@ man_connection_init (struct management *man)
{
if (man->connection.state == MS_INITIAL)
{
-#ifdef WIN32
+#ifdef _WIN32
/*
* This object is a sort of TCP/IP helper
* for Windows.
@@ -2105,7 +2295,7 @@ man_connection_close (struct management *man)
if (mc->es)
event_free (mc->es);
-#ifdef WIN32
+#ifdef _WIN32
net_event_win32_close (&mc->ne32);
#endif
if (socket_defined (mc->sd_top))
@@ -2147,7 +2337,7 @@ management_init (void)
bool
management_open (struct management *man,
const char *addr,
- const int port,
+ const char *port,
const char *pass_file,
const char *client_user,
const char *client_group,
@@ -2232,8 +2422,10 @@ void
management_set_state (struct management *man,
const int state,
const char *detail,
- const in_addr_t tun_local_ip,
- const in_addr_t tun_remote_ip)
+ const in_addr_t *tun_local_ip,
+ const struct in6_addr *tun_local_ip6,
+ const struct openvpn_sockaddr *local,
+ const struct openvpn_sockaddr *remote)
{
if (man->persist.state && (!(man->settings.flags & MF_SERVER) || state < OPENVPN_STATE_CLIENT_BASE))
{
@@ -2246,9 +2438,15 @@ management_set_state (struct management *man,
e.timestamp = now;
e.u.state = state;
e.string = detail;
- e.local_ip = tun_local_ip;
- e.remote_ip = tun_remote_ip;
-
+ if (tun_local_ip)
+ e.local_ip = *tun_local_ip;
+ if (tun_local_ip6)
+ e.local_ip6 = *tun_local_ip6;
+ if (local)
+ e.local_sock = *local;
+ if (remote)
+ e.remote_sock = *remote;
+
log_history_add (man->persist.state, &e);
if (man->connection.state_realtime)
@@ -2361,33 +2559,6 @@ management_notify_generic (struct management *man, const char *str)
#ifdef MANAGEMENT_DEF_AUTH
-static bool
-validate_peer_info_line(const char *line)
-{
- uint8_t c;
- int state = 0;
- while ((c=*line++))
- {
- switch (state)
- {
- case 0:
- case 1:
- if (c == '=' && state == 1)
- state = 2;
- else if (isalnum(c) || c == '_')
- state = 1;
- else
- return false;
- case 2:
- if (isprint(c))
- ;
- else
- return false;
- }
- }
- return (state == 2);
-}
-
static void
man_output_peer_info_env (struct management *man, struct man_def_auth_context *mdac)
{
@@ -2426,7 +2597,8 @@ management_notify_client_needing_auth (struct management *management,
mode = "REAUTH";
msg (M_CLIENT, ">CLIENT:%s,%lu,%u", mode, mdac->cid, mda_key_id);
man_output_extra_env (management, "CLIENT");
- man_output_peer_info_env(management, mdac);
+ if (management->connection.env_filter_level>0)
+ man_output_peer_info_env(management, mdac);
man_output_env (es, true, management->connection.env_filter_level, "CLIENT");
mdac->flags |= DAF_INITIAL_AUTH;
}
@@ -2513,7 +2685,13 @@ management_post_tunnel_open (struct management *man, const in_addr_t tun_local_i
&& man->connection.state == MS_INITIAL)
{
/* listen on our local TUN/TAP IP address */
- man->settings.local.addr.in4.sin_addr.s_addr = htonl (tun_local_ip);
+ struct in_addr ia;
+ int ret;
+
+ ia.s_addr = htonl(tun_local_ip);
+ ret = openvpn_getaddrinfo(GETADDR_PASSIVE, inet_ntoa(ia), NULL, 0, NULL,
+ AF_INET, &man->settings.local);
+ ASSERT (ret==0);
man_connection_init (man);
}
@@ -2553,7 +2731,7 @@ man_persist_state (unsigned int *persistent, const int n)
return true;
}
-#ifdef WIN32
+#ifdef _WIN32
void
management_socket_set (struct management *man,
@@ -2845,7 +3023,8 @@ management_event_loop_n_seconds (struct management *man, int sec)
man_check_for_signals (&signal_received);
if (signal_received)
return;
- } while (expire);
+ update_time();
+ } while (expire && expire > now);
/* revert state */
man->persist.standalone_disabled = standalone_disabled_save;
@@ -2984,15 +3163,14 @@ management_query_user_pass (struct management *man,
#ifdef MANAGMENT_EXTERNAL_KEY
-char * /* returns allocated base64 signature */
-management_query_rsa_sig (struct management *man,
- const char *b64_data)
+int
+management_query_multiline (struct management *man,
+ const char *b64_data, const char *prompt, const char *cmd, int *state, struct buffer_list **input)
{
struct gc_arena gc = gc_new ();
- char *ret = NULL;
+ int ret = 0;
volatile int signal_received = 0;
struct buffer alert_msg = clear_buf();
- struct buffer *buf;
const bool standalone_disabled_save = man->persist.standalone_disabled;
struct man_connection *mc = &man->connection;
@@ -3001,10 +3179,15 @@ management_query_rsa_sig (struct management *man,
man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */
man->persist.special_state_msg = NULL;
- mc->ext_key_state = EKS_SOLICIT;
+ *state = EKS_SOLICIT;
- alert_msg = alloc_buf_gc (strlen(b64_data)+64, &gc);
- buf_printf (&alert_msg, ">RSA_SIGN:%s", b64_data);
+ if (b64_data) {
+ alert_msg = alloc_buf_gc (strlen(b64_data)+strlen(prompt)+3, &gc);
+ buf_printf (&alert_msg, ">%s:%s", prompt, b64_data);
+ } else {
+ alert_msg = alloc_buf_gc (strlen(prompt)+3, &gc);
+ buf_printf (&alert_msg, ">%s", prompt);
+ }
man_wait_for_client_connection (man, &signal_received, 0, MWCC_OTHER_WAIT);
@@ -3022,40 +3205,107 @@ management_query_rsa_sig (struct management *man,
man_check_for_signals (&signal_received);
if (signal_received)
goto done;
- } while (mc->ext_key_state != EKS_READY);
+ } while (*state != EKS_READY);
- if (buffer_list_defined(mc->ext_key_input))
- {
- buffer_list_aggregate (mc->ext_key_input, 2048);
- buf = buffer_list_peek (mc->ext_key_input);
- 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';
- }
- }
+ ret = 1;
}
done:
- if (mc->ext_key_state == EKS_READY && ret)
- msg (M_CLIENT, "SUCCESS: rsa-sig command succeeded");
- else if (mc->ext_key_state == EKS_INPUT || mc->ext_key_state == EKS_READY)
- msg (M_CLIENT, "ERROR: rsa-sig command failed");
+ if (*state == EKS_READY && ret)
+ msg (M_CLIENT, "SUCCESS: %s command succeeded", cmd);
+ else if (*state == EKS_INPUT || *state == EKS_READY)
+ msg (M_CLIENT, "ERROR: %s command failed", cmd);
/* revert state */
man->persist.standalone_disabled = standalone_disabled_save;
man->persist.special_state_msg = NULL;
in_extra_reset (mc, IER_RESET);
- mc->ext_key_state = EKS_UNDEF;
- buffer_list_free (mc->ext_key_input);
- mc->ext_key_input = NULL;
+ *state = EKS_UNDEF;
gc_free (&gc);
return ret;
}
+char * /* returns allocated base64 signature */
+management_query_multiline_flatten_newline (struct management *man,
+ const char *b64_data, const char *prompt, const char *cmd, int *state, struct buffer_list **input)
+{
+ int ok;
+ char *result = NULL;
+ struct buffer *buf;
+
+ ok = management_query_multiline(man, b64_data, prompt, cmd, state, input);
+ if (ok && buffer_list_defined(*input))
+ {
+ buffer_list_aggregate_separator (*input, 10000, "\n");
+ buf = buffer_list_peek (*input);
+ if (buf && BLEN(buf) > 0)
+ {
+ result = (char *) malloc(BLEN(buf)+1);
+ check_malloc_return(result);
+ memcpy(result, buf->data, BLEN(buf));
+ result[BLEN(buf)] = '\0';
+ }
+ }
+
+ buffer_list_free (*input);
+ *input = NULL;
+
+ return result;
+}
+
+char * /* returns allocated base64 signature */
+management_query_multiline_flatten (struct management *man,
+ const char *b64_data, const char *prompt, const char *cmd, int *state, struct buffer_list **input)
+{
+ int ok;
+ char *result = NULL;
+ struct buffer *buf;
+
+ ok = management_query_multiline(man, b64_data, prompt, cmd, state, input);
+ if (ok && buffer_list_defined(*input))
+ {
+ buffer_list_aggregate (*input, 2048);
+ buf = buffer_list_peek (*input);
+ if (buf && BLEN(buf) > 0)
+ {
+ result = (char *) malloc(BLEN(buf)+1);
+ check_malloc_return(result);
+ memcpy(result, buf->data, BLEN(buf));
+ result[BLEN(buf)] = '\0';
+ }
+ }
+
+ buffer_list_free (*input);
+ *input = NULL;
+
+ return result;
+}
+
+char * /* returns allocated base64 signature */
+management_query_rsa_sig (struct management *man,
+ const char *b64_data)
+{
+ return management_query_multiline_flatten(man, b64_data, "RSA_SIGN", "rsa-sign",
+ &man->connection.ext_key_state, &man->connection.ext_key_input);
+}
+
+
+char* management_query_cert (struct management *man, const char *cert_name)
+{
+ const char prompt_1[] = "NEED-CERTIFICATE:";
+ struct buffer buf_prompt = alloc_buf(strlen(cert_name) + 20);
+ buf_write(&buf_prompt, prompt_1, strlen(prompt_1));
+ buf_write(&buf_prompt, cert_name, strlen(cert_name)+1); // +1 for \0
+
+ char *result;
+ result = management_query_multiline_flatten_newline(management,
+ NULL, (char*)buf_bptr(&buf_prompt), "certificate",
+ &man->connection.ext_cert_state, &man->connection.ext_cert_input);
+ free_buf(&buf_prompt);
+ return result;
+}
+
#endif
/*
@@ -3082,12 +3332,13 @@ management_should_daemonize (struct management *man)
* Return true if the caller should not sleep for an additional time interval.
*/
bool
-management_hold (struct management *man)
+management_hold (struct management *man, int holdtime)
{
if (management_would_hold (man))
{
volatile int signal_received = 0;
const bool standalone_disabled_save = man->persist.standalone_disabled;
+ struct gc_arena gc = gc_new ();
man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */
man->persist.special_state_msg = NULL;
@@ -3097,7 +3348,9 @@ management_hold (struct management *man)
if (!signal_received)
{
- man->persist.special_state_msg = ">HOLD:Waiting for hold release";
+ struct buffer out = alloc_buf_gc (128, &gc);
+ buf_printf (&out, ">HOLD:Waiting for hold release:%d", holdtime);
+ man->persist.special_state_msg = BSTR (&out);
msg (M_CLIENT, "%s", man->persist.special_state_msg);
/* run command processing event loop until we get our username/password */
@@ -3116,6 +3369,7 @@ management_hold (struct management *man)
man->persist.special_state_msg = NULL;
man->settings.mansig &= ~MANSIG_IGNORE_USR1_HUP;
+ gc_free (&gc);
return true;
}
return false;
@@ -3218,7 +3472,14 @@ log_entry_print (const struct log_entry *e, unsigned int flags, struct gc_arena
if (flags & LOG_PRINT_LOCAL_IP)
buf_printf (&out, ",%s", print_in_addr_t (e->local_ip, IA_EMPTY_IF_UNDEF, gc));
if (flags & LOG_PRINT_REMOTE_IP)
- buf_printf (&out, ",%s", print_in_addr_t (e->remote_ip, IA_EMPTY_IF_UNDEF, gc));
+ {
+ buf_printf (&out, ",%s", (!addr_defined (&e->remote_sock) ? "," :
+ print_sockaddr_ex (&e->remote_sock.addr.sa, ",", PS_DONT_SHOW_FAMILY|PS_SHOW_PORT, gc)));
+ buf_printf (&out, ",%s", (!addr_defined (&e->local_sock) ? "," :
+ print_sockaddr_ex (&e->local_sock.addr.sa, ",", PS_DONT_SHOW_FAMILY|PS_SHOW_PORT, gc)));
+ }
+ if (flags & LOG_PRINT_LOCAL_IP && !IN6_IS_ADDR_UNSPECIFIED(&e->local_ip6))
+ buf_printf (&out, ",%s", print_in6_addr (e->local_ip6, IA_EMPTY_IF_UNDEF, gc));
if (flags & LOG_ECHO_TO_LOG)
msg (D_MANAGEMENT, "MANAGEMENT: %s", BSTR (&out));
if (flags & LOG_PRINT_CRLF)