diff --git a/common/atoid.c b/common/atoid.c index bd5aa1eed..2a1be3b04 100644 --- a/common/atoid.c +++ b/common/atoid.c @@ -32,6 +32,11 @@ #elif defined(HAVE_INTTYPES_H) # include #endif +#ifdef HAVE_STDBOOL_H +# include +#else +# include "compat/stdbool.h" +#endif #include #include @@ -42,16 +47,26 @@ #include "sudo_debug.h" id_t -atoid(const char *p, const char **errstr) +atoid(const char *p, const char *sep, char **endp, const char **errstr) { char *ep; id_t rval = 0; + bool valid = false; debug_decl(atoid, SUDO_DEBUG_UTIL) + if (sep == NULL) + sep = ""; errno = 0; if (*p == '-') { long lval = strtol(p, &ep, 10); - if (ep == p || *ep != '\0') { + if (ep != p) { + /* check for valid separator (including '\0') */ + do { + if (*ep == *sep) + valid = true; + } while (*sep++ != '\0'); + } + if (!valid) { *errstr = N_("invalid value"); errno = EINVAL; goto done; @@ -66,7 +81,14 @@ atoid(const char *p, const char **errstr) *errstr = NULL; } else { unsigned long ulval = strtoul(p, &ep, 10); - if (ep == p || *ep != '\0') { + if (ep != p) { + /* check for valid separator (including '\0') */ + do { + if (*ep == *sep) + valid = true; + } while (*sep++ != '\0'); + } + if (!valid) { *errstr = N_("invalid value"); errno = EINVAL; goto done; @@ -79,6 +101,8 @@ atoid(const char *p, const char **errstr) rval = (id_t)ulval; *errstr = NULL; } + if (endp != NULL) + *endp = ep; done: debug_return_int(rval); } diff --git a/plugins/sudoers/iolog.c b/plugins/sudoers/iolog.c index 61290681d..af7fcac84 100644 --- a/plugins/sudoers/iolog.c +++ b/plugins/sudoers/iolog.c @@ -471,7 +471,7 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[], if (runas_euid_str != NULL) runas_uid_str = runas_euid_str; if (runas_uid_str != NULL) { - id = atoid(runas_uid_str, &errstr); + id = atoid(runas_uid_str, NULL, NULL, &errstr); if (errstr != NULL) warningx("runas uid %s: %s", runas_uid_str, _(errstr)); else @@ -480,7 +480,7 @@ iolog_deserialize_info(struct iolog_details *details, char * const user_info[], if (runas_egid_str != NULL) runas_gid_str = runas_egid_str; if (runas_gid_str != NULL) { - id = atoid(runas_gid_str, &errstr); + id = atoid(runas_gid_str, NULL, NULL, &errstr); if (errstr != NULL) warningx("runas gid %s: %s", runas_gid_str, _(errstr)); else diff --git a/plugins/sudoers/policy.c b/plugins/sudoers/policy.c index e7cb31013..6f5af0a2e 100644 --- a/plugins/sudoers/policy.c +++ b/plugins/sudoers/policy.c @@ -103,14 +103,14 @@ sudoers_policy_deserialize_info(void *v, char **runas_user, char **runas_group) } if (MATCHES(*cur, "sudoers_uid=")) { p = *cur + sizeof("sudoers_uid=") - 1; - sudoers_uid = (uid_t) atoid(p, &errstr); + sudoers_uid = (uid_t) atoid(p, NULL, NULL, &errstr); if (errstr != NULL) fatalx("%s: %s", *cur, _(errstr)); continue; } if (MATCHES(*cur, "sudoers_gid=")) { p = *cur + sizeof("sudoers_gid=") - 1; - sudoers_gid = (gid_t) atoid(p, &errstr); + sudoers_gid = (gid_t) atoid(p, NULL, NULL, &errstr); if (errstr != NULL) fatalx("%s: %s", *cur, _(errstr)); continue; @@ -261,14 +261,14 @@ sudoers_policy_deserialize_info(void *v, char **runas_user, char **runas_group) } if (MATCHES(*cur, "uid=")) { p = *cur + sizeof("uid=") - 1; - user_uid = (uid_t) atoid(p, &errstr); + user_uid = (uid_t) atoid(p, NULL, NULL, &errstr); if (errstr != NULL) fatalx("%s: %s", *cur, _(errstr)); continue; } if (MATCHES(*cur, "gid=")) { p = *cur + sizeof("gid=") - 1; - user_gid = (gid_t) atoid(p, &errstr); + user_gid = (gid_t) atoid(p, NULL, NULL, &errstr); if (errstr != NULL) fatalx("%s: %s", *cur, _(errstr)); continue; @@ -303,7 +303,7 @@ sudoers_policy_deserialize_info(void *v, char **runas_user, char **runas_group) } if (MATCHES(*cur, "sid=")) { p = *cur + sizeof("sid=") - 1; - sudo_user.sid = (pid_t) atoid(p, &errstr); + sudo_user.sid = (pid_t) atoid(p, NULL, NULL, &errstr); if (errstr != NULL) fatalx("%s: %s", *cur, _(errstr)); continue; diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h index 99f4bd9e3..80dda0540 100644 --- a/plugins/sudoers/sudoers.h +++ b/plugins/sudoers/sudoers.h @@ -315,7 +315,7 @@ char *get_timestr(time_t, int); int atobool(const char *str); /* atoid.c */ -int atoid(const char *str, const char **errstr); +int atoid(const char *str, const char *sep, char **endp, const char **errstr); /* boottime.c */ int get_boottime(struct timeval *); diff --git a/plugins/sudoers/tsgetgrpw.c b/plugins/sudoers/tsgetgrpw.c index f5fecd96f..611e3dc7b 100644 --- a/plugins/sudoers/tsgetgrpw.c +++ b/plugins/sudoers/tsgetgrpw.c @@ -143,14 +143,14 @@ next_entry: if ((colon = strchr(cp = colon, ':')) == NULL) goto next_entry; *colon++ = '\0'; - id = atoid(cp, &errstr); + id = atoid(cp, NULL, NULL, &errstr); if (errstr != NULL) goto next_entry; pw.pw_uid = (uid_t)id; if ((colon = strchr(cp = colon, ':')) == NULL) goto next_entry; *colon++ = '\0'; - id = atoid(cp, &errstr); + id = atoid(cp, NULL, NULL, &errstr); if (errstr != NULL) goto next_entry; pw.pw_gid = (gid_t)id; @@ -273,7 +273,7 @@ next_entry: if ((colon = strchr(cp = colon, ':')) == NULL) goto next_entry; *colon++ = '\0'; - id = atoid(cp, &errstr); + id = atoid(cp, NULL, NULL, &errstr); if (errstr != NULL) goto next_entry; gr.gr_gid = (gid_t)id; diff --git a/src/sudo.c b/src/sudo.c index ea8f4d3c2..42570a255 100644 --- a/src/sudo.c +++ b/src/sudo.c @@ -611,7 +611,7 @@ command_info_to_details(char * const info[], struct command_details *details) case 'r': if (strncmp("runas_egid=", info[i], sizeof("runas_egid=") - 1) == 0) { cp = info[i] + sizeof("runas_egid=") - 1; - id = atoid(cp, &errstr); + id = atoid(cp, NULL, NULL, &errstr); if (errstr != NULL) { warningx(_("%s: %s"), info[i], _(errstr)); } else { @@ -622,7 +622,7 @@ command_info_to_details(char * const info[], struct command_details *details) } if (strncmp("runas_euid=", info[i], sizeof("runas_euid=") - 1) == 0) { cp = info[i] + sizeof("runas_euid=") - 1; - id = atoid(cp, &errstr); + id = atoid(cp, NULL, NULL, &errstr); if (errstr != NULL) { warningx(_("%s: %s"), info[i], _(errstr)); } else { @@ -633,7 +633,7 @@ command_info_to_details(char * const info[], struct command_details *details) } if (strncmp("runas_gid=", info[i], sizeof("runas_gid=") - 1) == 0) { cp = info[i] + sizeof("runas_gid=") - 1; - id = atoid(cp, &errstr); + id = atoid(cp, NULL, NULL, &errstr); if (errstr != NULL) { warningx(_("%s: %s"), info[i], _(errstr)); } else { @@ -660,7 +660,7 @@ command_info_to_details(char * const info[], struct command_details *details) emalloc2(details->ngroups, sizeof(GETGROUPS_T)); cp = info[i] + sizeof("runas_groups=") - 1; for (j = 0; j < details->ngroups;) { - id = atoid(cp, &errstr); + id = atoid(cp, ",", &ep, &errstr); if (errstr != NULL) { warningx(_("%s: %s"), cp, _(errstr)); break; @@ -674,7 +674,7 @@ command_info_to_details(char * const info[], struct command_details *details) } if (strncmp("runas_uid=", info[i], sizeof("runas_uid=") - 1) == 0) { cp = info[i] + sizeof("runas_uid=") - 1; - id = atoid(cp, &errstr); + id = atoid(cp, NULL, NULL, &errstr); if (errstr != NULL) { warningx(_("%s: %s"), info[i], _(errstr)); } else { diff --git a/src/sudo.h b/src/sudo.h index f5a63d0e1..37ae96fbb 100644 --- a/src/sudo.h +++ b/src/sudo.h @@ -188,7 +188,7 @@ char *fmt_string(const char *var, const char *value); bool atobool(const char *str); /* atoid.c */ -id_t atoid(const char *str, const char **errstr); +id_t atoid(const char *str, const char *sep, char **endp, const char **errstr); /* parse_args.c */ int parse_args(int argc, char **argv, int *nargc, char ***nargv,