]> granicus.if.org Git - sudo/commitdiff
Add atoid() function to convert a string to an id_t (uid, gid or
authorTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 7 Aug 2013 19:13:56 +0000 (13:13 -0600)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Wed, 7 Aug 2013 19:13:56 +0000 (13:13 -0600)
pid).  We have to be careful to choose() either strtol() or strtoul()
depending on whether the string appears to be signed or unsigned.
Always using strtoul() is unsafe on 64-bit platforms since the
uid might be represented as a negative number and (unsigned long)-1
on a 64-bit system is 0xffffffffffffffff not 0xffffffff.
Fixes a problem with uids larger than 0x7fffffff on 32-bit platforms.

plugins/sudoers/atoid.c [new file with mode: 0644]

diff --git a/plugins/sudoers/atoid.c b/plugins/sudoers/atoid.c
new file mode 100644 (file)
index 0000000..bd5aa1e
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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 */
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif
+#include <errno.h>
+#include <limits.h>
+
+#define DEFAULT_TEXT_DOMAIN    "sudoers"
+#include "gettext.h"
+
+#include "missing.h"
+#include "sudo_debug.h"
+
+id_t
+atoid(const char *p, const char **errstr)
+{
+    char *ep;
+    id_t rval = 0;
+    debug_decl(atoid, SUDO_DEBUG_UTIL)
+
+    errno = 0;
+    if (*p == '-') {
+       long lval = strtol(p, &ep, 10);
+       if (ep == p || *ep != '\0') {
+           *errstr = N_("invalid value");
+           errno = EINVAL;
+           goto done;
+       }
+       if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) ||
+           (lval > INT_MAX || lval < INT_MIN)) {
+           errno = ERANGE;
+           *errstr = N_("value out of range");
+           goto done;
+       }
+       rval = (id_t)lval;
+       *errstr = NULL;
+    } else {
+       unsigned long ulval = strtoul(p, &ep, 10);
+       if (ep == p || *ep != '\0') {
+           *errstr = N_("invalid value");
+           errno = EINVAL;
+           goto done;
+       }
+       if ((errno == ERANGE && ulval == ULONG_MAX) || ulval > UINT_MAX) {
+           errno = ERANGE;
+           *errstr = N_("value too large");
+           goto done;
+       }
+       rval = (id_t)ulval;
+       *errstr = NULL;
+    }
+done:
+    debug_return_int(rval);
+}