Skip to content
Open
204 changes: 163 additions & 41 deletions src/gpupdate.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@

#define _(_x) _x
static const char *exe;
static const char *gpo_exe;
static char *gpo_exe;
static struct passwd *pwd;

#define FLAG_QUIET (1 << 1)
#define FLAG_STDIN (1 << 1)
#define FLAG_FORCE (1 << 2)

/*
Expand All @@ -69,7 +69,7 @@ get_gpo_exe(void)
return gpo_exe ? gpo_exe : "/usr/sbin/gpoa";
}

static int apply_gpo(const char *user, int flags)
static int apply_gpo(const char *user, int flags, char* loglevel)
{
int status;
pid_t pid = fork();
Expand All @@ -79,9 +79,9 @@ static int apply_gpo(const char *user, int flags)
return 1;
case 0:
if (flags & FLAG_FORCE) {
execl(exe, exe, "--force", user, NULL);
execl(exe, exe, "--force", "--loglevel", loglevel, user, NULL);
} else {
execl(exe, exe, user, NULL);
execl(exe, exe, "--loglevel", loglevel, user, NULL);
}
return 3;
default:
Expand All @@ -93,11 +93,12 @@ static int apply_gpo(const char *user, int flags)

/* Apply group policies via GPO applier. */
static int
gpupdate(const char *user, int flags)
gpupdate(const char *user, int flags, char* loglevel)
{
int ret;
struct stat st;
const char *log_user = user;
int i_loglevel = atoi(loglevel);

/* Now make sure that the user or computer
a) no user (computer)
Expand Down Expand Up @@ -127,7 +128,7 @@ gpupdate(const char *user, int flags)
exe = get_gpo_exe();
if (exe != NULL) {
/* Set the text of the result message. */
if (!(flags & FLAG_QUIET)) {
if (!(i_loglevel < 4)) {
printf(_("Apply group policies for %s."), log_user);
}
syslog(LOG_NOTICE, "Apply group policies for %s.", log_user);
Expand All @@ -141,7 +142,7 @@ gpupdate(const char *user, int flags)
return HANDLER_INVALID_INVOCATION;
}
}
ret = apply_gpo(user, flags);
ret = apply_gpo(user, flags, loglevel);
if (ret != 0) {
syslog(LOG_ERR,
"error applying GPO for %s (error code %d)", log_user, ret);
Expand All @@ -152,53 +153,174 @@ gpupdate(const char *user, int flags)
}

int
main(int argc, char **argv)
getFlags(int argc, char** argv, char** gpo_exe, char** loglevel, int *flags)
{
char **oddjob_argv, *p;
int oddjob_argc, ret, flags = 0;
if (argc == 0)
{
return 0;
}
if (!argv || !gpo_exe || !gpo_exe || !loglevel || !flags)
{
return -1;
}

openlog(PACKAGE "-gpupdate", LOG_PID, LOG_DAEMON);
gpo_exe = "/usr/sbin/gpoa";
if (*gpo_exe)
{
free(*gpo_exe);
}
(*gpo_exe) = strdup("/usr/sbin/gpoa");
if (*loglevel)
{
free(*loglevel);
}
(*loglevel) = strdup("4");

while ((ret = getopt(argc, argv, "qfp:")) != -1) {
switch (ret) {
case 'q':
flags |= FLAG_QUIET;
break;
case 'f':
flags |= FLAG_FORCE;
break;
case 'p':
gpo_exe = optarg;
break;
int ret;
while ((ret = getopt(argc, argv, "ifl:p:")) != -1)
{
switch (ret){
case 'f':
(*flags) |= FLAG_FORCE;
break;
case 'p':
if (*gpo_exe)
{
free(*gpo_exe);
}
(*gpo_exe) = strdup(optarg);
break;
case 'i': {
(*flags) |= FLAG_STDIN;
break;
}
case 'l':
if (*loglevel)
{
free(*loglevel);
}
(*loglevel) = strdup(optarg);
break;
default:
fprintf(stderr, "Valid options:\n"
"-q\tDo not print messages when applying "
"a policy.\n"
"-f\tForce GPT download.\n"
"-l LEVEL\tSet loglevel.\n"
"-p PATH\tOverride the gpo applier "
"binary (\"%s\").\n", gpo_exe);
return 1;
"binary (\"%s\").\n", *gpo_exe);
return -1;
}
}

return 0;
}

int
main(int argc, char **argv)
{
char *user = NULL, **oddjob_args, *stdin_args = NULL, *loglevel = NULL;
int flags = 0, oddjob_argc, ret = HANDLER_INVALID_INVOCATION;

openlog(PACKAGE "-gpupdate", LOG_PID, LOG_DAEMON);

oddjob_args = oddjob_collect_args(stdin);
for (oddjob_argc = 0; oddjob_args && oddjob_args[oddjob_argc]; ++oddjob_argc);

if (getFlags(argc, argv, &gpo_exe, &loglevel, &flags) == -1)
{
return ret;
}

if (flags & FLAG_STDIN)
{
// Parse args.
switch(oddjob_argc)
{
case 2:
user = oddjob_args[0];
stdin_args = oddjob_args[1];
break;
case 1:
stdin_args = oddjob_args[0];
break;
default:
syslog(LOG_ERR, "invoked with wrong arguments");

free(loglevel);
free(gpo_exe);

return ret;
}

if (!stdin_args || !*stdin_args)
{
syslog(LOG_ERR, "invoked with wrong arguments");

free(loglevel);
free(gpo_exe);

return ret;
}

size_t newArgc = 0;
// split stdin by ' '.
char** newArgv = make_argv(stdin_args, &newArgc, ' ');

// flags fallback
flags = FLAG_STDIN;

optind = 1;
// rerun getFlags with STDIN
if (getFlags(newArgc, newArgv, &gpo_exe, &loglevel, &flags) == -1)
{
return ret;
}

for (int i = newArgc; i > 0; --i)
{
free(newArgv[i - 1]);
}
free(newArgv);
}
ret = HANDLER_INVALID_INVOCATION;
oddjob_argv = oddjob_collect_args(stdin);
for (oddjob_argc = 0; (oddjob_argv != NULL) && (oddjob_argv[oddjob_argc] != NULL); oddjob_argc++) {
if (oddjob_argc > 1)
else switch(oddjob_argc)
{
case 1:
user = oddjob_args[0];
break;
case 0:
break;

default:
syslog(LOG_ERR, "invoked with wrong arguments");

free(loglevel);
free(gpo_exe);

return ret;
}
switch (oddjob_argc) {
case 0:
ret = gpupdate(NULL, flags);
break;
case 1:
if (strlen(oddjob_argv[0]) > 0)
ret = gpupdate(oddjob_argv[0], flags);
break;
default:
syslog(LOG_ERR, "invoked with wrong arguments");

if (user)
{
if (strlen(user) == 0)
{
syslog(LOG_ERR, "invoked with wrong arguments");

free(loglevel);
free(gpo_exe);

return ret;
}
ret = gpupdate(user, flags, loglevel);
}
oddjob_free_args(oddjob_argv);
else
{
ret = gpupdate(NULL, flags, loglevel);
}

free(loglevel);
free(gpo_exe);

oddjob_free_args(oddjob_args);
closelog();
return ret;
}
21 changes: 21 additions & 0 deletions src/oddjob-gpupdate.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,27 @@
send_member="gpupdate_computer"/>
</policy>


<!-- Allow anyone to try to call the gpupdate method, which is part of
the "gpupdate" interface implemented by the "/" object provided
by the @NAMESPACE@.oddjob_gpupdate service. -->
<policy context="default">
<allow send_destination="@NAMESPACE@.oddjob_gpupdate"
send_path="/"
send_interface="@NAMESPACE@.oddjob_gpupdate"
send_member="gpupdate_arg"/>
</policy>

<!-- Allow anyone to try to call the gpupdate method, which is part of
the "gpupdate" interface implemented by the "/" object provided
by the @NAMESPACE@.oddjob_gpupdate service. -->
<policy context="default">
<allow send_destination="@NAMESPACE@.oddjob_gpupdate"
send_path="/"
send_interface="@NAMESPACE@.oddjob_gpupdate"
send_member="gpupdate_computer_arg"/>
</policy>

<!-- Allow anyone to try to call the gpupdate method, which is part of
the "gpupdate" interface implemented by the "/" object provided
by the @NAMESPACE@.oddjob_gpupdate_force service. -->
Expand Down
13 changes: 13 additions & 0 deletions src/oddjobd-gpupdate.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,19 @@
<allow user="root"/>
</method>

<method name="gpupdate_computer_arg">
<helper exec="@mypkglibexecdir@/gpupdate -i"
arguments="1"/>
<allow/>
</method>

<method name="gpupdate_arg">
<helper exec="@mypkglibexecdir@/gpupdate -i"
arguments="1"
prepend_user_name="yes"/>
<allow/>
</method>

<method name="gpupdate_computer_force">
<helper exec="@mypkglibexecdir@/gpupdate -f"
arguments="0"/>
Expand Down
29 changes: 29 additions & 0 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,35 @@
#include <string.h>
#include <unistd.h>

/* Generate argv and argc from argument string (a_str) */
char** make_argv(char* a_str, size_t* argc_out, const char a_delim)
{
if (!argc_out)
{
return NULL;
}

char delim[2] = {a_delim, 0};
char** result = NULL;
char* token = strtok(a_str, delim);

(*argc_out) = 0;

// getopt skip first argument........
result = reallocarray(result, ++(*argc_out), sizeof(char*));
result[0] = NULL;

while(token)
{
result = reallocarray(result, ++(*argc_out), sizeof(char*));
result[(*argc_out) - 1] = strdup(token);
token = strtok(NULL, delim);
}

return result;
}


/* Write to a file, handling transient errors. */
ssize_t
retry_write(int fd, unsigned char *buf, size_t length)
Expand Down
1 change: 1 addition & 0 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#ifndef oddjob_util_h
#define oddjob_util_h

char** make_argv(char* a_str, size_t* argc_out, const char a_delim);
ssize_t retry_write(int fd, unsigned char *buf, size_t length);
void *oddjob_malloc(size_t size);
void *oddjob_malloc0(size_t size);
Expand Down