Add atomode() function for parsing a file mode.

This commit is contained in:
Todd C. Miller
2013-12-10 16:56:54 -07:00
parent 8f9ce7249a
commit d83bfb9fe6
9 changed files with 111 additions and 40 deletions

View File

@@ -13,6 +13,7 @@ common/aix.c
common/alloc.c common/alloc.c
common/atobool.c common/atobool.c
common/atoid.c common/atoid.c
common/atomode.c
common/event.c common/event.c
common/event_poll.c common/event_poll.c
common/event_select.c common/event_select.c

View File

@@ -66,7 +66,7 @@ DEFS = @OSDEFS@ -D_PATH_SUDO_CONF=\"$(sysconfdir)/sudo.conf\"
SHELL = @SHELL@ SHELL = @SHELL@
LTOBJS = alloc.lo atobool.lo atoid.lo event.lo fatal.lo fileops.lo \ LTOBJS = alloc.lo atobool.lo atoid.lo atomode.lo event.lo fatal.lo fileops.lo \
fmt_string.lo gidlist.lo lbuf.lo progname.lo secure_path.lo \ fmt_string.lo gidlist.lo lbuf.lo progname.lo secure_path.lo \
setgroups.lo sudo_conf.lo sudo_debug.lo sudo_dso.lo sudo_printf.lo \ setgroups.lo sudo_conf.lo sudo_debug.lo sudo_dso.lo sudo_printf.lo \
term.lo ttysize.lo @COMMON_OBJS@ term.lo ttysize.lo @COMMON_OBJS@
@@ -179,6 +179,9 @@ atoid.lo: $(srcdir)/atoid.c $(incdir)/gettext.h $(incdir)/missing.h \
$(incdir)/sudo_debug.h $(top_builddir)/config.h \ $(incdir)/sudo_debug.h $(top_builddir)/config.h \
$(top_srcdir)/compat/stdbool.h $(top_srcdir)/compat/stdbool.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/atoid.c $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/atoid.c
atomode.lo: $(srcdir)/atomode.c $(incdir)/gettext.h $(incdir)/missing.h \
$(incdir)/sudo_debug.h $(top_builddir)/config.h
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(DEFS) $(srcdir)/atomode.c
conf_test.lo: $(srcdir)/regress/sudo_conf/conf_test.c $(incdir)/missing.h \ conf_test.lo: $(srcdir)/regress/sudo_conf/conf_test.c $(incdir)/missing.h \
$(incdir)/queue.h $(incdir)/sudo_conf.h $(top_builddir)/config.h \ $(incdir)/queue.h $(incdir)/sudo_conf.h $(top_builddir)/config.h \
$(top_srcdir)/compat/stdbool.h $(top_srcdir)/compat/stdbool.h

View File

@@ -74,18 +74,24 @@ atoid(const char *p, const char *sep, char **endp, const char **errstr)
} while (*sep++ != '\0'); } while (*sep++ != '\0');
} }
if (!valid) { if (!valid) {
*errstr = N_("invalid value"); if (errstr != NULL)
*errstr = N_("invalid");
errno = EINVAL; errno = EINVAL;
goto done; goto done;
} }
if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) || if ((errno == ERANGE && lval == LONG_MAX) || lval > INT_MAX) {
(lval > INT_MAX || lval < INT_MIN)) {
errno = ERANGE; errno = ERANGE;
*errstr = N_("value out of range"); if (errstr != NULL)
*errstr = N_("too large");
goto done;
}
if ((errno == ERANGE && lval == LONG_MIN) || lval < INT_MIN) {
errno = ERANGE;
if (errstr != NULL)
*errstr = N_("too small");
goto done; goto done;
} }
rval = (id_t)lval; rval = (id_t)lval;
*errstr = NULL;
} else { } else {
unsigned long ulval = strtoul(p, &ep, 10); unsigned long ulval = strtoul(p, &ep, 10);
if (ep != p) { if (ep != p) {
@@ -96,18 +102,21 @@ atoid(const char *p, const char *sep, char **endp, const char **errstr)
} while (*sep++ != '\0'); } while (*sep++ != '\0');
} }
if (!valid) { if (!valid) {
*errstr = N_("invalid value"); if (errstr != NULL)
*errstr = N_("invalid");
errno = EINVAL; errno = EINVAL;
goto done; goto done;
} }
if ((errno == ERANGE && ulval == ULONG_MAX) || ulval > UINT_MAX) { if ((errno == ERANGE && ulval == ULONG_MAX) || ulval > UINT_MAX) {
errno = ERANGE; errno = ERANGE;
*errstr = N_("value too large"); if (errstr != NULL)
*errstr = N_("too large");
goto done; goto done;
} }
rval = (id_t)ulval; rval = (id_t)ulval;
*errstr = NULL;
} }
if (errstr != NULL)
*errstr = NULL;
if (endp != NULL) if (endp != NULL)
*endp = ep; *endp = ep;
done: done:

65
common/atomode.c Normal file
View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2013 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <config.h>
#include <sys/types.h>
#include <stdio.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif /* STDC_HEADERS */
#include <errno.h>
#define DEFAULT_TEXT_DOMAIN "sudo"
#include "gettext.h"
#include "missing.h"
#include "sudo_debug.h"
/*
* Parse an octal file mode in the range [0, 0777].
* On success, returns the parsed mode and clears errstr.
* On error, returns 0 and sets errstr.
*/
int
atomode(const char *cp, const char **errstr)
{
char *ep;
long lval;
debug_decl(atomode, SUDO_DEBUG_UTIL)
errno = 0;
lval = strtol(cp, &ep, 8);
if (ep == cp || *ep != '\0') {
if (errstr != NULL)
*errstr = N_("invalid");
errno = EINVAL;
debug_return_int(0);
}
if (lval < 0 || lval > 0777) {
if (errstr != NULL)
*errstr = lval < 0 ? N_("too small") : N_("too large");
errno = ERANGE;
debug_return_int(0);
}
debug_return_int((int)lval);
}

View File

@@ -811,17 +811,20 @@ logpri2str(int n)
static bool static bool
store_mode(char *val, struct sudo_defs_types *def, int op) store_mode(char *val, struct sudo_defs_types *def, int op)
{ {
char *endp; mode_t mode;
long l; const char *errstr;
debug_decl(store_mode, SUDO_DEBUG_DEFAULTS) debug_decl(store_mode, SUDO_DEBUG_DEFAULTS)
if (op == false) { if (op == false) {
def->sd_un.mode = (mode_t)0777; def->sd_un.mode = 0777;
} else { } else {
l = strtol(val, &endp, 8); mode = atomode(val, &errstr);
if (endp == val || *endp != '\0' || l < 0 || l > 0777) if (errstr != NULL) {
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"%s is %s", val, errstr);
debug_return_bool(false); debug_return_bool(false);
def->sd_un.mode = (mode_t)l; }
def->sd_un.mode = mode;
} }
if (def->callback) if (def->callback)
debug_return_bool(def->callback(val)); debug_return_bool(def->callback(val));

View File

@@ -91,7 +91,6 @@ sudoers_policy_deserialize_info(void *v, char **runas_user, char **runas_group)
const char *debug_flags = NULL; const char *debug_flags = NULL;
const char *remhost = NULL; const char *remhost = NULL;
int flags = 0; int flags = 0;
char *ep;
debug_decl(sudoers_policy_deserialize_info, SUDO_DEBUG_PLUGIN) debug_decl(sudoers_policy_deserialize_info, SUDO_DEBUG_PLUGIN)
#define MATCHES(s, v) (strncmp(s, v, sizeof(v) - 1) == 0) #define MATCHES(s, v) (strncmp(s, v, sizeof(v) - 1) == 0)
@@ -118,17 +117,10 @@ sudoers_policy_deserialize_info(void *v, char **runas_user, char **runas_group)
continue; continue;
} }
if (MATCHES(*cur, "sudoers_mode=")) { if (MATCHES(*cur, "sudoers_mode=")) {
long lval;
errno = 0;
p = *cur + sizeof("sudoers_mode=") - 1; p = *cur + sizeof("sudoers_mode=") - 1;
lval = strtol(p, &ep, 8); sudoers_mode = atomode(p, &errstr);
if (ep == p || *ep != '\0') if (errstr != NULL)
fatalx(U_("%s: %s"), *cur, U_("invalid")); fatalx(U_("%s: %s"), *cur, U_(errstr));
if (lval < 0)
fatalx(U_("%s: %s"), *cur, U_("too small"));
if (lval > 0777)
fatalx(U_("%s: %s"), *cur, U_("too large"));
sudoers_mode = (mode_t) lval;
continue; continue;
} }
if (MATCHES(*cur, "ldap_conf=")) { if (MATCHES(*cur, "ldap_conf=")) {

View File

@@ -321,6 +321,9 @@ int atobool(const char *str);
/* atoid.c */ /* atoid.c */
int atoid(const char *str, const char *sep, char **endp, const char **errstr); int atoid(const char *str, const char *sep, char **endp, const char **errstr);
/* atomode.c */
int atomode(const char *cp, const char **errstr);
/* boottime.c */ /* boottime.c */
int get_boottime(struct timeval *); int get_boottime(struct timeval *);

View File

@@ -555,7 +555,7 @@ command_info_to_details(char * const info[], struct command_details *details)
cp = info[i] + sizeof("closefrom=") - 1; cp = info[i] + sizeof("closefrom=") - 1;
details->closefrom = strtonum(cp, 0, INT_MAX, &errstr); details->closefrom = strtonum(cp, 0, INT_MAX, &errstr);
if (errstr != NULL) if (errstr != NULL)
fatalx(U_("%s: %s"), cp, U_(errstr)); fatalx(U_("%s: %s"), info[i], U_(errstr));
break; break;
} }
break; break;
@@ -574,7 +574,7 @@ command_info_to_details(char * const info[], struct command_details *details)
cp = info[i] + sizeof("nice=") - 1; cp = info[i] + sizeof("nice=") - 1;
details->priority = strtonum(cp, INT_MIN, INT_MAX, &errstr); details->priority = strtonum(cp, INT_MIN, INT_MAX, &errstr);
if (errstr != NULL) if (errstr != NULL)
fatalx(U_("%s: %s"), cp, U_(errstr)); fatalx(U_("%s: %s"), info[i], U_(errstr));
SET(details->flags, CD_SET_PRIORITY); SET(details->flags, CD_SET_PRIORITY);
break; break;
} }
@@ -676,25 +676,17 @@ command_info_to_details(char * const info[], struct command_details *details)
cp = info[i] + sizeof("timeout=") - 1; cp = info[i] + sizeof("timeout=") - 1;
details->timeout = strtonum(cp, 0, INT_MAX, &errstr); details->timeout = strtonum(cp, 0, INT_MAX, &errstr);
if (errstr != NULL) if (errstr != NULL)
fatalx(U_("%s: %s"), cp, U_(errstr)); fatalx(U_("%s: %s"), info[i], U_(errstr));
SET(details->flags, CD_SET_TIMEOUT); SET(details->flags, CD_SET_TIMEOUT);
break; break;
} }
break; break;
case 'u': case 'u':
if (strncmp("umask=", info[i], sizeof("umask=") - 1) == 0) { if (strncmp("umask=", info[i], sizeof("umask=") - 1) == 0) {
long lval;
char *ep;
errno = 0;
cp = info[i] + sizeof("umask=") - 1; cp = info[i] + sizeof("umask=") - 1;
lval = strtol(cp, &ep, 8); details->umask = atomode(cp, &errstr);
if (ep == cp || *ep != '\0') if (errstr != NULL)
fatalx(U_("%s: %s"), info[i], U_("invalid")); fatalx(U_("%s: %s"), info[i], U_(errstr));
if (lval < 0)
fatalx(U_("%s: %s"), info[i], U_("too small"));
if (lval > 0777)
fatalx(U_("%s: %s"), info[i], U_("too large"));
details->umask = (mode_t)lval;
SET(details->flags, CD_SET_UMASK); SET(details->flags, CD_SET_UMASK);
break; break;
} }

View File

@@ -189,6 +189,9 @@ bool atobool(const char *str);
/* atoid.c */ /* atoid.c */
id_t atoid(const char *str, const char *sep, char **endp, const char **errstr); id_t atoid(const char *str, const char *sep, char **endp, const char **errstr);
/* atomode.c */
int atomode(const char *cp, const char **errstr);
/* parse_args.c */ /* parse_args.c */
int parse_args(int argc, char **argv, int *nargc, char ***nargv, int parse_args(int argc, char **argv, int *nargc, char ***nargv,
char ***settingsp, char ***env_addp); char ***settingsp, char ***env_addp);