]> err.no Git - util-linux/commitdiff
login: rewrite is_local() to remove limits on line length
authorJames Youngman <jay@gnu.org>
Sat, 12 Apr 2008 11:53:07 +0000 (12:53 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 14 Apr 2008 11:12:14 +0000 (13:12 +0200)
Signed-off-by: James Youngman <jay@gnu.org>
Signed-off-by: Karel Zak <kzak@redhat.com>
login-utils/Makefile.am
login-utils/islocal.c
login-utils/islocal.h
tests/Makefile.am
tests/commands.sh.in
tests/expected/ts-login-islocal [new file with mode: 0644]
tests/input/ts-login-islocal [new file with mode: 0644]
tests/ts-login-islocal [new file with mode: 0755]

index 8f5dc894340c062e689a9ea42b5112adb23777f1..a660dacb3600344246842032dcaf273bee8c46ee 100644 (file)
@@ -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)
index 297698041f44de7446079b5c32e8cef96c571765..762a4e9900db8006e3e276d326da9cfce8af611b 100644 (file)
 
    1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
    - 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.
 
 */
 
 #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
index 305bc57c68962a3c2ba557cb208a97e678f3bea7..2c5879906c01a2662f1685662276fe5ed352eccd 100644 (file)
@@ -1 +1 @@
-extern int is_local(char *user);
+extern int is_local(const char *user);
index 67bd568590b612dbcfc4ae5f2eb9162e3025672b..827b8493e250bdf431680838c63306db18f53728 100644 (file)
@@ -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 \
index 6035547a34ca6d6a4e56f273ceda06ae739d5f24..c363aac9a7d8f83fc74fa907de3b53e0a7300fd5 100644 (file)
@@ -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 (file)
index 0000000..c5d43ff
--- /dev/null
@@ -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 (file)
index 0000000..916a8a9
--- /dev/null
@@ -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 (executable)
index 0000000..0c8d779
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+#
+# Copyright (C) 2008 James Youngman <jay@gnu.org>
+#
+# 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