Update runcwd in command_info[] before passing it to the audit plugin.
Since sudoers does rejected commands itself the runcwd will still not be correct for those.
This commit is contained in:
@@ -94,6 +94,7 @@ struct _PolicyCheckRequest
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
char *command;
|
||||
char *cwd;
|
||||
size_t n_argv;
|
||||
char **argv;
|
||||
size_t n_envp;
|
||||
@@ -103,7 +104,7 @@ struct _PolicyCheckRequest
|
||||
};
|
||||
#define POLICY_CHECK_REQUEST__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&policy_check_request__descriptor) \
|
||||
, (char *)protobuf_c_empty_string, 0,NULL, 0,NULL, 0, 0 }
|
||||
, (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, 0,NULL, 0,NULL, 0, 0 }
|
||||
|
||||
|
||||
struct _PolicyAcceptMessage
|
||||
|
@@ -203,45 +203,76 @@ bad:
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new command_info[] and update the command in it.
|
||||
* Only allocates new space for command_info[] itseld and the new command.
|
||||
* Stores a pointer to the new command in the tofree parameter.
|
||||
* Allocate a new command_info[] and update command and runcwd in it.
|
||||
* Fills in cmnd_out with a copy of the command if not NULL.
|
||||
* Returns the new command_info[] which the caller must free.
|
||||
*/
|
||||
static char **
|
||||
update_command_info(char * const *old_command_info, const char *cmnd,
|
||||
char **tofree)
|
||||
const char *runcwd, char **cmnd_out)
|
||||
{
|
||||
char **command_info;
|
||||
char *tmp_command = NULL;
|
||||
char * const *oci;
|
||||
size_t n;
|
||||
debug_decl(update_command_info, SUDO_DEBUG_EXEC);
|
||||
|
||||
/* Rebuild command_info[] with new command. */
|
||||
/* Rebuild command_info[] with new command and add a runcwd. */
|
||||
for (n = 0; old_command_info[n] != NULL; n++)
|
||||
continue;
|
||||
command_info = reallocarray(NULL, n + 1, sizeof(char *));
|
||||
command_info = reallocarray(NULL, n + 2, sizeof(char *));
|
||||
if (command_info == NULL) {
|
||||
goto bad;
|
||||
}
|
||||
for (n = 0; old_command_info[n] != NULL; n++) {
|
||||
const char *cp = old_command_info[n];
|
||||
if (strncmp(cp, "command=", sizeof("command=") - 1) == 0) {
|
||||
if (tmp_command != NULL)
|
||||
continue;
|
||||
tmp_command = sudo_new_key_val("command", cmnd);
|
||||
if (tmp_command == NULL) {
|
||||
goto bad;
|
||||
for (oci = old_command_info, n = 0; *oci != NULL; oci++) {
|
||||
const char *cp = *oci;
|
||||
switch (*cp) {
|
||||
case 'c':
|
||||
if (strncmp(cp, "command=", sizeof("command=") - 1) == 0) {
|
||||
if (cmnd != NULL) {
|
||||
command_info[n] = sudo_new_key_val("command", cmnd);
|
||||
if (command_info[n] == NULL) {
|
||||
goto bad;
|
||||
}
|
||||
n++;
|
||||
continue;
|
||||
} else if (cmnd_out != NULL) {
|
||||
*cmnd_out = strdup(cp + sizeof("command=") - 1);
|
||||
if (*cmnd_out == NULL) {
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
}
|
||||
cp = tmp_command;
|
||||
break;
|
||||
case 'r':
|
||||
if (strncmp(cp, "runcwd=", sizeof("runcwd=") - 1) == 0) {
|
||||
/* Filled in at the end. */
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
command_info[n] = (char *)cp;
|
||||
command_info[n] = strdup(cp);
|
||||
if (command_info[n] == NULL) {
|
||||
goto bad;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
/* Append actual runcwd. */
|
||||
command_info[n] = sudo_new_key_val("runcwd", runcwd);
|
||||
if (command_info[n] == NULL) {
|
||||
goto bad;
|
||||
}
|
||||
n++;
|
||||
|
||||
command_info[n] = NULL;
|
||||
*tofree = tmp_command;
|
||||
|
||||
debug_return_ptr(command_info);
|
||||
bad:
|
||||
free(command_info);
|
||||
if (command_info != NULL) {
|
||||
for (n = 0; command_info[n] != NULL; n++) {
|
||||
free(command_info[n]);
|
||||
}
|
||||
free(command_info);
|
||||
}
|
||||
debug_return_ptr(NULL);
|
||||
}
|
||||
|
||||
@@ -252,7 +283,6 @@ intercept_check_policy(PolicyCheckRequest *req,
|
||||
char **command_info = NULL;
|
||||
char **user_env_out = NULL;
|
||||
char **argv = NULL, **run_argv = NULL;
|
||||
char *tofree = NULL;
|
||||
bool ret = false;
|
||||
int result;
|
||||
size_t n;
|
||||
@@ -302,17 +332,12 @@ intercept_check_policy(PolicyCheckRequest *req,
|
||||
|
||||
switch (result) {
|
||||
case 1:
|
||||
/* Extract command path from command_info[] */
|
||||
for (n = 0; command_info[n] != NULL; n++) {
|
||||
const char *cp = command_info[n];
|
||||
if (strncmp(cp, "command=", sizeof("command=") - 1) == 0) {
|
||||
closure->command = strdup(cp + sizeof("command=") - 1);
|
||||
if (closure->command == NULL) {
|
||||
closure->errstr = N_("unable to allocate memory");
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Rebuild command_info[] with runcwd and extract command. */
|
||||
command_info = update_command_info(command_info, NULL,
|
||||
req->cwd ? req->cwd : "unknown", &closure->command);
|
||||
if (command_info == NULL) {
|
||||
closure->errstr = N_("unable to allocate memory");
|
||||
goto done;
|
||||
}
|
||||
closure->state = POLICY_ACCEPT;
|
||||
break;
|
||||
@@ -336,9 +361,9 @@ intercept_check_policy(PolicyCheckRequest *req,
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Rebuild command_info[] with new command. */
|
||||
/* Rebuild command_info[] with new command and runcwd. */
|
||||
command_info = update_command_info(closure->details->info,
|
||||
req->command, &tofree);
|
||||
req->command, req->cwd ? req->cwd : "unknown", NULL);
|
||||
if (command_info == NULL) {
|
||||
closure->errstr = N_("unable to allocate memory");
|
||||
goto done;
|
||||
@@ -415,8 +440,10 @@ done:
|
||||
command_info ? command_info : closure->details->info);
|
||||
closure->state = POLICY_ERROR;
|
||||
}
|
||||
if (!ISSET(closure->details->flags, CD_INTERCEPT)) {
|
||||
free(tofree);
|
||||
if (command_info != NULL) {
|
||||
for (n = 0; command_info[n] != NULL; n++) {
|
||||
free(command_info[n]);
|
||||
}
|
||||
free(command_info);
|
||||
}
|
||||
free(argv);
|
||||
|
@@ -507,7 +507,7 @@ const ProtobufCMessageDescriptor hello_response__descriptor =
|
||||
(ProtobufCMessageInit) hello_response__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[5] =
|
||||
static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[6] =
|
||||
{
|
||||
{
|
||||
"command",
|
||||
@@ -522,8 +522,20 @@ static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[5]
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"argv",
|
||||
"cwd",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_STRING,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(PolicyCheckRequest, cwd),
|
||||
NULL,
|
||||
&protobuf_c_empty_string,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"argv",
|
||||
3,
|
||||
PROTOBUF_C_LABEL_REPEATED,
|
||||
PROTOBUF_C_TYPE_STRING,
|
||||
offsetof(PolicyCheckRequest, n_argv),
|
||||
@@ -535,7 +547,7 @@ static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[5]
|
||||
},
|
||||
{
|
||||
"envp",
|
||||
3,
|
||||
4,
|
||||
PROTOBUF_C_LABEL_REPEATED,
|
||||
PROTOBUF_C_TYPE_STRING,
|
||||
offsetof(PolicyCheckRequest, n_envp),
|
||||
@@ -547,7 +559,7 @@ static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[5]
|
||||
},
|
||||
{
|
||||
"intercept_fd",
|
||||
4,
|
||||
5,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_INT32,
|
||||
0, /* quantifier_offset */
|
||||
@@ -559,7 +571,7 @@ static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[5]
|
||||
},
|
||||
{
|
||||
"secret",
|
||||
5,
|
||||
6,
|
||||
PROTOBUF_C_LABEL_NONE,
|
||||
PROTOBUF_C_TYPE_FIXED64,
|
||||
0, /* quantifier_offset */
|
||||
@@ -571,16 +583,17 @@ static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[5]
|
||||
},
|
||||
};
|
||||
static const unsigned policy_check_request__field_indices_by_name[] = {
|
||||
1, /* field[1] = argv */
|
||||
2, /* field[2] = argv */
|
||||
0, /* field[0] = command */
|
||||
2, /* field[2] = envp */
|
||||
3, /* field[3] = intercept_fd */
|
||||
4, /* field[4] = secret */
|
||||
1, /* field[1] = cwd */
|
||||
3, /* field[3] = envp */
|
||||
4, /* field[4] = intercept_fd */
|
||||
5, /* field[5] = secret */
|
||||
};
|
||||
static const ProtobufCIntRange policy_check_request__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 5 }
|
||||
{ 0, 6 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor policy_check_request__descriptor =
|
||||
{
|
||||
@@ -590,7 +603,7 @@ const ProtobufCMessageDescriptor policy_check_request__descriptor =
|
||||
"PolicyCheckRequest",
|
||||
"",
|
||||
sizeof(PolicyCheckRequest),
|
||||
5,
|
||||
6,
|
||||
policy_check_request__field_descriptors,
|
||||
policy_check_request__field_indices_by_name,
|
||||
1, policy_check_request__number_ranges,
|
||||
|
@@ -36,10 +36,11 @@ message HelloResponse {
|
||||
*/
|
||||
message PolicyCheckRequest {
|
||||
string command = 1;
|
||||
repeated string argv = 2;
|
||||
repeated string envp = 3;
|
||||
int32 intercept_fd = 4;
|
||||
fixed64 secret = 5;
|
||||
string cwd = 2;
|
||||
repeated string argv = 3;
|
||||
repeated string envp = 4;
|
||||
int32 intercept_fd = 5;
|
||||
fixed64 secret = 6;
|
||||
}
|
||||
|
||||
message PolicyAcceptMessage {
|
||||
|
@@ -253,6 +253,7 @@ send_policy_check_req(int sock, const char *cmnd, char * const argv[],
|
||||
{
|
||||
InterceptRequest msg = INTERCEPT_REQUEST__INIT;
|
||||
PolicyCheckRequest req = POLICY_CHECK_REQUEST__INIT;
|
||||
char cwdbuf[PATH_MAX];
|
||||
uint8_t *buf = NULL;
|
||||
bool ret = false;
|
||||
uint32_t msg_len;
|
||||
@@ -271,6 +272,9 @@ send_policy_check_req(int sock, const char *cmnd, char * const argv[],
|
||||
for (len = 0; envp[len] != NULL; len++)
|
||||
continue;
|
||||
req.n_envp = len;
|
||||
if (getcwd(cwdbuf, sizeof(cwdbuf)) != NULL) {
|
||||
req.cwd = cwdbuf;
|
||||
}
|
||||
msg.type_case = INTERCEPT_REQUEST__TYPE_POLICY_CHECK_REQ;
|
||||
msg.u.policy_check_req = &req;
|
||||
|
||||
|
Reference in New Issue
Block a user