From 8e0259728e6b7c447d795898f60a9281053c8303 Mon Sep 17 00:00:00 2001 From: James Youngman Date: Sat, 12 Apr 2008 12:53:07 +0100 Subject: [PATCH] login: rewrite is_local() to remove limits on line length Signed-off-by: James Youngman Signed-off-by: Karel Zak --- login-utils/Makefile.am | 7 ++- login-utils/islocal.c | 105 +++++++++++++++++++++++++------- login-utils/islocal.h | 2 +- tests/Makefile.am | 1 + tests/commands.sh.in | 1 + tests/expected/ts-login-islocal | 13 ++++ tests/input/ts-login-islocal | 10 +++ tests/ts-login-islocal | 28 +++++++++ 8 files changed, 144 insertions(+), 23 deletions(-) create mode 100644 tests/expected/ts-login-islocal create mode 100644 tests/input/ts-login-islocal create mode 100755 tests/ts-login-islocal diff --git a/login-utils/Makefile.am b/login-utils/Makefile.am index 8f5dc894..a660dacb 100644 --- a/login-utils/Makefile.am +++ b/login-utils/Makefile.am @@ -130,7 +130,12 @@ install-exec-hook:: endif -noinst_PROGRAMS = checktty_test +noinst_PROGRAMS = checktty_test islocal_test checktty_test_SOURCES = checktty.c login.h checktty_test_CPPFLAGS = -DMAIN_TEST_CHECKTTY $(AM_CPPFLAGS) +islocal_test_SOURCES = islocal.c +islocal_test_CPPFLAGS = -DMAIN_TEST_ISLOCAL $(AM_CPPFLAGS) +check-local: islocal_test$(EXEEXT) checktty_test$(EXEEXT) + ./islocal_test$(EXEEXT) + ./checktty_test$(EXEEXT) diff --git a/login-utils/islocal.c b/login-utils/islocal.c index 29769804..762a4e99 100644 --- a/login-utils/islocal.c +++ b/login-utils/islocal.c @@ -12,7 +12,10 @@ 1999-02-22 Arkadiusz Mi¶kiewicz - added Native Language Support - + + 2008-04-06 James Youngman, jay@gnu.org + - Completely rewritten to remove assumption that /etc/passwd + lines are < 1024 characters long. Also added unit tests. */ @@ -24,29 +27,89 @@ #include "pathnames.h" #include "islocal.h" -#define MAX_LENGTH 1024 - -int -is_local(char *user) +static int +is_local_in_file(const char *user, const char *filename) { - FILE *fd; - char line[MAX_LENGTH]; int local = 0; - size_t len; - - if(!(fd = fopen(_PATH_PASSWD, "r"))) { - fprintf(stderr,_("Can't read %s, exiting."),_PATH_PASSWD); - exit(1); - } - - len = strlen(user); - while(fgets(line, MAX_LENGTH, fd)) { - if(!strncmp(line, user, len) && line[len] == ':') { - local = 1; - break; - } + size_t match; + int chin, skip; + FILE *f; + + if (NULL == (f=fopen(filename, "r"))) + return -1; + + match = 0u; + skip = 0; + while ((chin = getc(f)) != EOF) { + if (skip) { + /* Looking for the start of the next line. */ + if ('\n' == chin) { + /* Start matching username at the next char. */ + skip = 0; + match = 0u; + } + } else { + if (':' == chin) { + if (0 == user[match]) { + local = 1; /* Success. */ + /* next line has no test coverage, but it is + * just an optimisation anyway. */ + break; + } else { + /* we read a whole username, but it is + * the wrong user. Skip to the next + * line. */ + skip = 1; + } + } else if ('\n' == chin) { + /* This line contains no colon; it's malformed. + * No skip since we are already at the start of + * the next line. */ + match = 0u; + } else if (chin != user[match]) { + /* username does not match. */ + skip = 1; + } else { + ++match; + } + } } - fclose(fd); + fclose(f); return local; } +int +is_local(const char *user) +{ + int rv; + if ((rv = is_local_in_file(user, _PATH_PASSWD)) < 0) { + perror(_PATH_PASSWD); + fprintf(stderr, _("Failed to open %s for reading, exiting."), + _PATH_PASSWD); + exit(1); + } else { + return rv; + } +} + +#if MAIN_TEST_ISLOCAL +int +main (int argc, char *argv[]) +{ + if (argc < 2) { + fprintf(stderr, "No test passwd file was specified.\n"); + return 1; + } else { + int i; + for (i = 2; i < argc; i++) { + const int rv = is_local_in_file(argv[i], argv[1]); + if (rv < 0) { + perror(argv[1]); + return 2; + } + printf("%d:%s\n", rv, argv[i]); + } + return 0; + } +} +#endif diff --git a/login-utils/islocal.h b/login-utils/islocal.h index 305bc57c..2c587990 100644 --- a/login-utils/islocal.h +++ b/login-utils/islocal.h @@ -1 +1 @@ -extern int is_local(char *user); +extern int is_local(const char *user); diff --git a/tests/Makefile.am b/tests/Makefile.am index 67bd5685..827b8493 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -28,6 +28,7 @@ EXTRA_DIST = expected \ ts-ipcs-limits2 \ ts-ipcs.sh \ ts-login-checktty \ + ts-login-islocal \ ts-look-separator \ ts-mount-noncanonical \ ts-mount-devname \ diff --git a/tests/commands.sh.in b/tests/commands.sh.in index 6035547a..c363aac9 100644 --- a/tests/commands.sh.in +++ b/tests/commands.sh.in @@ -36,6 +36,7 @@ TS_CMD_CAL=${TS_CMD_CAL-"$TOPDIR/misc-utils/cal"} TS_CMD_SCRIPT=${TS_CMD_SCRIPT-"$TOPDIR/misc-utils/script"} TS_CMD_CHECKTTY=${TS_CMD_CHECKTTY-"$TOPDIR/login-utils/checktty_test"} +TS_CMD_ISLOCAL=${TS_CMD_ISLOCAL-"$TOPDIR/login-utils/islocal_test"} TS_CMD_HWCLOCK=${TS_CMD_HWCLOCK-"$TOPDIR/hwclock/hwclock"} diff --git a/tests/expected/ts-login-islocal b/tests/expected/ts-login-islocal new file mode 100644 index 00000000..c5d43ff5 --- /dev/null +++ b/tests/expected/ts-login-islocal @@ -0,0 +1,13 @@ +1:root +1:nobody +0: +0:youngman +0:youngman2 +0:abcdefghx +0:nobo +1:long +0:rot +1:al +0:malformed +1:nonl +0:znobody diff --git a/tests/input/ts-login-islocal b/tests/input/ts-login-islocal new file mode 100644 index 00000000..916a8a9b --- /dev/null +++ b/tests/input/ts-login-islocal @@ -0,0 +1,10 @@ +root:x:0:0:root:/root:/bin/bash +sys:x:3:3:sys:/dev:/bin/sh +orac:x:33:33:sys:/dev:/bin/youngman +long:x:4:4:foo:/home/loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooonnnggg:/bin/sh +al:x:5:5:fnord:/dev:/bin/sh +abcdefgh:x:6:3:fnord:/dev:/bin/sh +malformed + +nobody:x:65534:65534:nobody:/nonexistent:/bin/sh +nonl:x:65532:65532:no newline:/:/bin/false diff --git a/tests/ts-login-islocal b/tests/ts-login-islocal new file mode 100755 index 00000000..0c8d7798 --- /dev/null +++ b/tests/ts-login-islocal @@ -0,0 +1,28 @@ +#!/bin/bash + +# +# Copyright (C) 2008 James Youngman +# +# This file is part of util-linux-ng. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This file is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +. ./commands.sh +. ./functions.sh + +TS_COMPONENT="login" +TS_DESC="islocal" + +ts_init "$*" +$TS_CMD_ISLOCAL "$TS_INPUT" root nobody "" youngman youngman2 \ + abcdefghx nobo long rot al malformed \ + nonl znobody >> $TS_OUTPUT +ts_finalize -- 2.39.5