Stop sending an InterceptResponse to a PolicyCheckRequest for log_subcmds.
There's no real reason for the command to wait for sudo send back a response that will always be a PolicyAcceptMessage.
This commit is contained in:
@@ -72,6 +72,7 @@ struct InterceptHello
|
|||||||
/*
|
/*
|
||||||
* Sudo response to an InterceptHello from sudo_intercept.so.
|
* Sudo response to an InterceptHello from sudo_intercept.so.
|
||||||
* The client uses the port number and token to connect back to sudo.
|
* The client uses the port number and token to connect back to sudo.
|
||||||
|
* If log_only is set there is no InterceptResponse to a PolicyCheckRequest.
|
||||||
*/
|
*/
|
||||||
struct HelloResponse
|
struct HelloResponse
|
||||||
{
|
{
|
||||||
@@ -79,10 +80,11 @@ struct HelloResponse
|
|||||||
uint64_t token_lo;
|
uint64_t token_lo;
|
||||||
uint64_t token_hi;
|
uint64_t token_hi;
|
||||||
int32_t portno;
|
int32_t portno;
|
||||||
|
protobuf_c_boolean log_only;
|
||||||
};
|
};
|
||||||
#define HELLO_RESPONSE__INIT \
|
#define HELLO_RESPONSE__INIT \
|
||||||
{ PROTOBUF_C_MESSAGE_INIT (&hello_response__descriptor) \
|
{ PROTOBUF_C_MESSAGE_INIT (&hello_response__descriptor) \
|
||||||
, 0, 0, 0 }
|
, 0, 0, 0, 0 }
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -192,6 +192,9 @@ sudo_dso_public bool sudo_ev_got_break_v1(struct sudo_event_base *base);
|
|||||||
/* Return the base an event is associated with or NULL. */
|
/* Return the base an event is associated with or NULL. */
|
||||||
#define sudo_ev_get_base(_ev) ((_ev) ? (_ev)->base : NULL)
|
#define sudo_ev_get_base(_ev) ((_ev) ? (_ev)->base : NULL)
|
||||||
|
|
||||||
|
/* Set the base an event is associated with. */
|
||||||
|
#define sudo_ev_set_base(_ev, _b) ((_ev)->base = (_b))
|
||||||
|
|
||||||
/* Magic pointer value to use self pointer as callback arg. */
|
/* Magic pointer value to use self pointer as callback arg. */
|
||||||
#define sudo_ev_self_cbarg() ((void *)-1)
|
#define sudo_ev_self_cbarg() ((void *)-1)
|
||||||
|
|
||||||
|
@@ -53,6 +53,44 @@ static struct intercept_closure *accept_closure;
|
|||||||
static void intercept_accept_cb(int fd, int what, void *v);
|
static void intercept_accept_cb(int fd, int what, void *v);
|
||||||
static void intercept_cb(int fd, int what, void *v);
|
static void intercept_cb(int fd, int what, void *v);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable the closure->ev event with the specified events and callback,
|
||||||
|
* and set the connection state to new_state if it is valid.
|
||||||
|
* Returns true on success, else false.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
intercept_enable_event(int fd, short events, enum intercept_state new_state,
|
||||||
|
sudo_ev_callback_t callback, struct intercept_closure *closure)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
debug_decl(intercept_enable_event, SUDO_DEBUG_EXEC);
|
||||||
|
|
||||||
|
rc = sudo_ev_set(&closure->ev, fd, events, callback, closure);
|
||||||
|
if (rc == -1 || sudo_ev_add(NULL, &closure->ev, NULL, false) == -1) {
|
||||||
|
sudo_warn("%s", U_("unable to add event to queue"));
|
||||||
|
debug_return_bool(false);
|
||||||
|
}
|
||||||
|
if (new_state != INVALID_STATE)
|
||||||
|
closure->state = new_state;
|
||||||
|
debug_return_bool(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
enable_read_event(int fd, enum intercept_state new_state,
|
||||||
|
sudo_ev_callback_t callback, struct intercept_closure *closure)
|
||||||
|
{
|
||||||
|
return intercept_enable_event(fd, SUDO_EV_READ|SUDO_EV_PERSIST,
|
||||||
|
new_state, callback, closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
enable_write_event(int fd, sudo_ev_callback_t callback,
|
||||||
|
struct intercept_closure *closure)
|
||||||
|
{
|
||||||
|
return intercept_enable_event(fd, SUDO_EV_WRITE|SUDO_EV_PERSIST,
|
||||||
|
INVALID_STATE, callback, closure);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create an intercept closure.
|
* Create an intercept closure.
|
||||||
* Returns an opaque pointer to the closure, which is also
|
* Returns an opaque pointer to the closure, which is also
|
||||||
@@ -63,7 +101,6 @@ intercept_setup(int fd, struct sudo_event_base *evbase,
|
|||||||
struct command_details *details)
|
struct command_details *details)
|
||||||
{
|
{
|
||||||
struct intercept_closure *closure;
|
struct intercept_closure *closure;
|
||||||
int rc;
|
|
||||||
debug_decl(intercept_setup, SUDO_DEBUG_EXEC);
|
debug_decl(intercept_setup, SUDO_DEBUG_EXEC);
|
||||||
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO,
|
||||||
@@ -76,6 +113,7 @@ intercept_setup(int fd, struct sudo_event_base *evbase,
|
|||||||
}
|
}
|
||||||
closure->details = details;
|
closure->details = details;
|
||||||
closure->listen_sock = -1;
|
closure->listen_sock = -1;
|
||||||
|
sudo_ev_set_base(&closure->ev, evbase);
|
||||||
|
|
||||||
if (ISSET(details->flags, CD_USE_PTRACE)) {
|
if (ISSET(details->flags, CD_USE_PTRACE)) {
|
||||||
/*
|
/*
|
||||||
@@ -92,15 +130,10 @@ intercept_setup(int fd, struct sudo_event_base *evbase,
|
|||||||
* Not using ptrace(2), use LD_PRELOAD (or its equivalent). If
|
* Not using ptrace(2), use LD_PRELOAD (or its equivalent). If
|
||||||
* we've already seen an InterceptHello, expect a policy check first.
|
* we've already seen an InterceptHello, expect a policy check first.
|
||||||
*/
|
*/
|
||||||
closure->state = sudo_token_isset(intercept_token) ?
|
const int new_state = sudo_token_isset(intercept_token) ?
|
||||||
RECV_SECRET : RECV_HELLO_INITIAL;
|
RECV_SECRET : RECV_HELLO_INITIAL;
|
||||||
|
if (!enable_read_event(fd, new_state, intercept_cb, closure))
|
||||||
rc = sudo_ev_set(&closure->ev, fd, SUDO_EV_READ|SUDO_EV_PERSIST,
|
|
||||||
intercept_cb, closure);
|
|
||||||
if (rc == -1 || sudo_ev_add(evbase, &closure->ev, NULL, false) == -1) {
|
|
||||||
sudo_warn("%s", U_("unable to add event to queue"));
|
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_return_ptr(closure);
|
debug_return_ptr(closure);
|
||||||
@@ -546,11 +579,9 @@ intercept_verify_token(int fd, struct intercept_closure *closure)
|
|||||||
static bool
|
static bool
|
||||||
intercept_read(int fd, struct intercept_closure *closure)
|
intercept_read(int fd, struct intercept_closure *closure)
|
||||||
{
|
{
|
||||||
struct sudo_event_base *evbase = sudo_ev_get_base(&closure->ev);
|
|
||||||
InterceptRequest *req = NULL;
|
InterceptRequest *req = NULL;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
int rc;
|
|
||||||
debug_decl(intercept_read, SUDO_DEBUG_EXEC);
|
debug_decl(intercept_read, SUDO_DEBUG_EXEC);
|
||||||
|
|
||||||
if (closure->state == RECV_SECRET) {
|
if (closure->state == RECV_SECRET) {
|
||||||
@@ -644,7 +675,7 @@ unpack:
|
|||||||
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO,
|
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||||
"%s: finished receiving %u bytes from client", __func__, closure->len);
|
"%s: finished receiving %u bytes from client", __func__, closure->len);
|
||||||
sudo_ev_del(evbase, &closure->ev);
|
sudo_ev_del(NULL, &closure->ev);
|
||||||
free(closure->buf);
|
free(closure->buf);
|
||||||
closure->buf = NULL;
|
closure->buf = NULL;
|
||||||
closure->len = 0;
|
closure->len = 0;
|
||||||
@@ -663,6 +694,11 @@ unpack:
|
|||||||
ret = intercept_check_policy_req(req->u.policy_check_req, closure);
|
ret = intercept_check_policy_req(req->u.policy_check_req, closure);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (!ISSET(closure->details->flags, CD_INTERCEPT)) {
|
||||||
|
/* Just logging, re-use event to read next InterceptHello. */
|
||||||
|
ret = enable_read_event(fd, RECV_HELLO, intercept_cb, closure);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case INTERCEPT_REQUEST__TYPE_HELLO:
|
case INTERCEPT_REQUEST__TYPE_HELLO:
|
||||||
switch (closure->state) {
|
switch (closure->state) {
|
||||||
@@ -686,12 +722,8 @@ unpack:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Switch event to write mode for the reply. */
|
/* Switch event to write mode for the reply. */
|
||||||
rc = sudo_ev_set(&closure->ev, fd, SUDO_EV_WRITE|SUDO_EV_PERSIST,
|
if (!enable_write_event(fd, intercept_cb, closure))
|
||||||
intercept_cb, closure);
|
|
||||||
if (rc == -1 || sudo_ev_add(evbase, &closure->ev, NULL, false) == -1) {
|
|
||||||
sudo_warn("%s", U_("unable to add event to queue"));
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
|
|
||||||
ret = true;
|
ret = true;
|
||||||
|
|
||||||
@@ -744,6 +776,7 @@ fmt_hello_response(struct intercept_closure *closure)
|
|||||||
hello_resp.portno = intercept_listen_port;
|
hello_resp.portno = intercept_listen_port;
|
||||||
hello_resp.token_lo = intercept_token.u64[0];
|
hello_resp.token_lo = intercept_token.u64[0];
|
||||||
hello_resp.token_hi = intercept_token.u64[1];
|
hello_resp.token_hi = intercept_token.u64[1];
|
||||||
|
hello_resp.log_only = !ISSET(closure->details->flags, CD_INTERCEPT);
|
||||||
|
|
||||||
resp.u.hello_resp = &hello_resp;
|
resp.u.hello_resp = &hello_resp;
|
||||||
resp.type_case = INTERCEPT_RESPONSE__TYPE_HELLO_RESP;
|
resp.type_case = INTERCEPT_RESPONSE__TYPE_HELLO_RESP;
|
||||||
@@ -811,10 +844,8 @@ fmt_error_message(struct intercept_closure *closure)
|
|||||||
static bool
|
static bool
|
||||||
intercept_write(int fd, struct intercept_closure *closure)
|
intercept_write(int fd, struct intercept_closure *closure)
|
||||||
{
|
{
|
||||||
struct sudo_event_base *evbase = sudo_ev_get_base(&closure->ev);
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
ssize_t nwritten;
|
ssize_t nwritten;
|
||||||
int rc;
|
|
||||||
debug_decl(intercept_write, SUDO_DEBUG_EXEC);
|
debug_decl(intercept_write, SUDO_DEBUG_EXEC);
|
||||||
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, "state %d",
|
sudo_debug_printf(SUDO_DEBUG_INFO|SUDO_DEBUG_LINENO, "state %d",
|
||||||
@@ -864,9 +895,9 @@ intercept_write(int fd, struct intercept_closure *closure)
|
|||||||
debug_return_bool(true);
|
debug_return_bool(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: sent %u bytes to client",
|
sudo_debug_printf(SUDO_DEBUG_INFO,
|
||||||
__func__, closure->len);
|
"%s: sent %u bytes to client", __func__, closure->len);
|
||||||
sudo_ev_del(evbase, &closure->ev);
|
sudo_ev_del(NULL, &closure->ev);
|
||||||
free(closure->buf);
|
free(closure->buf);
|
||||||
closure->buf = NULL;
|
closure->buf = NULL;
|
||||||
closure->len = 0;
|
closure->len = 0;
|
||||||
@@ -874,27 +905,19 @@ intercept_write(int fd, struct intercept_closure *closure)
|
|||||||
|
|
||||||
switch (closure->state) {
|
switch (closure->state) {
|
||||||
case RECV_HELLO_INITIAL:
|
case RECV_HELLO_INITIAL:
|
||||||
/* Re-use event for the listener. */
|
/* Re-use the listener event. */
|
||||||
close(fd);
|
close(fd);
|
||||||
rc = sudo_ev_set(&closure->ev, closure->listen_sock,
|
if (!enable_read_event(closure->listen_sock, RECV_CONNECTION,
|
||||||
SUDO_EV_READ|SUDO_EV_PERSIST, intercept_accept_cb, closure);
|
intercept_accept_cb, closure))
|
||||||
if (rc == -1 || sudo_ev_add(evbase, &closure->ev, NULL, false) == -1) {
|
|
||||||
sudo_warn("%s", U_("unable to add event to queue"));
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
closure->listen_sock = -1;
|
closure->listen_sock = -1;
|
||||||
closure->state = RECV_CONNECTION;
|
closure->state = RECV_CONNECTION;
|
||||||
accept_closure = closure;
|
accept_closure = closure;
|
||||||
break;
|
break;
|
||||||
case POLICY_ACCEPT:
|
case POLICY_ACCEPT:
|
||||||
/* Re-use event to read InterceptHello from sudo_intercept.so ctor. */
|
/* Re-use event to read InterceptHello from sudo_intercept.so ctor. */
|
||||||
rc = sudo_ev_set(&closure->ev, fd, SUDO_EV_READ|SUDO_EV_PERSIST,
|
if (!enable_read_event(fd, RECV_HELLO, intercept_cb, closure))
|
||||||
intercept_cb, closure);
|
|
||||||
if (rc == -1 || sudo_ev_add(evbase, &closure->ev, NULL, false) == -1) {
|
|
||||||
sudo_warn("%s", U_("unable to add event to queue"));
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
|
||||||
closure->state = RECV_HELLO;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Done with this connection. */
|
/* Done with this connection. */
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#define SUDO_EXEC_INTERCEPT_H
|
#define SUDO_EXEC_INTERCEPT_H
|
||||||
|
|
||||||
enum intercept_state {
|
enum intercept_state {
|
||||||
|
INVALID_STATE,
|
||||||
RECV_HELLO_INITIAL,
|
RECV_HELLO_INITIAL,
|
||||||
RECV_HELLO,
|
RECV_HELLO,
|
||||||
RECV_SECRET,
|
RECV_SECRET,
|
||||||
|
@@ -456,7 +456,7 @@ const ProtobufCMessageDescriptor intercept_hello__descriptor =
|
|||||||
(ProtobufCMessageInit) intercept_hello__init,
|
(ProtobufCMessageInit) intercept_hello__init,
|
||||||
NULL,NULL,NULL /* reserved[123] */
|
NULL,NULL,NULL /* reserved[123] */
|
||||||
};
|
};
|
||||||
static const ProtobufCFieldDescriptor hello_response__field_descriptors[3] =
|
static const ProtobufCFieldDescriptor hello_response__field_descriptors[4] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
"token_lo",
|
"token_lo",
|
||||||
@@ -494,8 +494,21 @@ static const ProtobufCFieldDescriptor hello_response__field_descriptors[3] =
|
|||||||
0, /* flags */
|
0, /* flags */
|
||||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"log_only",
|
||||||
|
4,
|
||||||
|
PROTOBUF_C_LABEL_NONE,
|
||||||
|
PROTOBUF_C_TYPE_BOOL,
|
||||||
|
0, /* quantifier_offset */
|
||||||
|
offsetof(HelloResponse, log_only),
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
0, /* flags */
|
||||||
|
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||||
|
},
|
||||||
};
|
};
|
||||||
static const unsigned hello_response__field_indices_by_name[] = {
|
static const unsigned hello_response__field_indices_by_name[] = {
|
||||||
|
3, /* field[3] = log_only */
|
||||||
2, /* field[2] = portno */
|
2, /* field[2] = portno */
|
||||||
1, /* field[1] = token_hi */
|
1, /* field[1] = token_hi */
|
||||||
0, /* field[0] = token_lo */
|
0, /* field[0] = token_lo */
|
||||||
@@ -503,7 +516,7 @@ static const unsigned hello_response__field_indices_by_name[] = {
|
|||||||
static const ProtobufCIntRange hello_response__number_ranges[1 + 1] =
|
static const ProtobufCIntRange hello_response__number_ranges[1 + 1] =
|
||||||
{
|
{
|
||||||
{ 1, 0 },
|
{ 1, 0 },
|
||||||
{ 0, 3 }
|
{ 0, 4 }
|
||||||
};
|
};
|
||||||
const ProtobufCMessageDescriptor hello_response__descriptor =
|
const ProtobufCMessageDescriptor hello_response__descriptor =
|
||||||
{
|
{
|
||||||
@@ -513,7 +526,7 @@ const ProtobufCMessageDescriptor hello_response__descriptor =
|
|||||||
"HelloResponse",
|
"HelloResponse",
|
||||||
"",
|
"",
|
||||||
sizeof(HelloResponse),
|
sizeof(HelloResponse),
|
||||||
3,
|
4,
|
||||||
hello_response__field_descriptors,
|
hello_response__field_descriptors,
|
||||||
hello_response__field_indices_by_name,
|
hello_response__field_indices_by_name,
|
||||||
1, hello_response__number_ranges,
|
1, hello_response__number_ranges,
|
||||||
|
@@ -22,11 +22,13 @@ message InterceptHello {
|
|||||||
/*
|
/*
|
||||||
* Sudo response to an InterceptHello from sudo_intercept.so.
|
* Sudo response to an InterceptHello from sudo_intercept.so.
|
||||||
* The client uses the port number and token to connect back to sudo.
|
* The client uses the port number and token to connect back to sudo.
|
||||||
|
* If log_only is set there is no InterceptResponse to a PolicyCheckRequest.
|
||||||
*/
|
*/
|
||||||
message HelloResponse {
|
message HelloResponse {
|
||||||
fixed64 token_lo = 1;
|
fixed64 token_lo = 1;
|
||||||
fixed64 token_hi = 2;
|
fixed64 token_hi = 2;
|
||||||
int32 portno = 3;
|
int32 portno = 3;
|
||||||
|
bool log_only = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: ISC
|
* SPDX-License-Identifier: ISC
|
||||||
*
|
*
|
||||||
* Copyright (c) 2021 Todd C. Miller <Todd.Miller@sudo.ws>
|
* Copyright (c) 2021-2022 Todd C. Miller <Todd.Miller@sudo.ws>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -61,6 +61,7 @@ extern char **environ;
|
|||||||
|
|
||||||
static union sudo_token_un intercept_token;
|
static union sudo_token_un intercept_token;
|
||||||
static in_port_t intercept_port;
|
static in_port_t intercept_port;
|
||||||
|
static bool log_only;
|
||||||
|
|
||||||
/* Send entire request to sudo (blocking). */
|
/* Send entire request to sudo (blocking). */
|
||||||
static bool
|
static bool
|
||||||
@@ -273,6 +274,7 @@ sudo_interposer_init(void)
|
|||||||
intercept_token.u64[0] = res->u.hello_resp->token_lo;
|
intercept_token.u64[0] = res->u.hello_resp->token_lo;
|
||||||
intercept_token.u64[1] = res->u.hello_resp->token_hi;
|
intercept_token.u64[1] = res->u.hello_resp->token_hi;
|
||||||
intercept_port = res->u.hello_resp->portno;
|
intercept_port = res->u.hello_resp->portno;
|
||||||
|
log_only = res->u.hello_resp->log_only;
|
||||||
} else {
|
} else {
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
"unexpected type_case value %d in %s from %s",
|
"unexpected type_case value %d in %s from %s",
|
||||||
@@ -420,6 +422,18 @@ command_allowed(const char *cmnd, char * const argv[],
|
|||||||
if (!send_policy_check_req(sock, cmnd, argv, envp))
|
if (!send_policy_check_req(sock, cmnd, argv, envp))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
if (log_only) {
|
||||||
|
/* Just logging, no policy check. */
|
||||||
|
nenvp = sudo_preload_dso(envp, sudo_conf_intercept_path(), sock);
|
||||||
|
if (nenvp == NULL)
|
||||||
|
goto oom;
|
||||||
|
*ncmndp = (char *)cmnd; /* safe */
|
||||||
|
*nargvp = (char **)argv; /* safe */
|
||||||
|
*nenvpp = nenvp;
|
||||||
|
ret = true;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
res = recv_intercept_response(sock);
|
res = recv_intercept_response(sock);
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
@@ -467,7 +481,7 @@ command_allowed(const char *cmnd, char * const argv[],
|
|||||||
default:
|
default:
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
"unexpected type_case value %d in %s from %s",
|
"unexpected type_case value %d in %s from %s",
|
||||||
res->type_case, "InterceptResponse", "sudo");
|
res->type_case, "InterceptResponse", "sudo");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user