From 3bac2635472491c45e6efa1f9f76522590ab11fb Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 14 Jun 2026 01:36:56 +0200 Subject: [PATCH 01/12] src/login_nopam.c: Remove string_match() Calling strcaseeq() explicitly is more readable, and it allows removing the comments. The code becomes simpler. Signed-off-by: Alejandro Colomar --- src/login_nopam.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/src/login_nopam.c b/src/login_nopam.c index 3269e74f74..53f0c0dbfc 100644 --- a/src/login_nopam.c +++ b/src/login_nopam.c @@ -76,7 +76,6 @@ static bool list_match (char *list, const char *item, bool (*match_fn) (char *, const char *)); static bool user_match (char *tok, const char *string); static bool from_match (char *tok, const char *string); -static bool string_match (const char *tok, const char *string); static const char *resolve_hostname (const char *string); /* login_access - match username/group and host/tty with access control file */ @@ -228,7 +227,7 @@ static bool user_match (char *tok, const char *string) } else if (strprefix(tok, "@")) { /* netgroup */ return (netgroup_match (tok + 1, NULL, string)); #endif - } else if (string_match (tok, string)) { /* ALL or exact match */ + } else if (strcaseeq(tok, "ALL") || strcaseeq(tok, string)) { return true; /* local, no need for xgetgrnam */ } else if ((group = getgrnam (tok)) != NULL) { /* try group membership */ @@ -302,7 +301,7 @@ static bool from_match (char *tok, const char *string) return (netgroup_match (tok + 1, string, NULL)); } else #endif - if (string_match (tok, string)) { /* ALL or exact match */ + if (strcaseeq(tok, "ALL") || strcaseeq(tok, string)) { return true; } else if (strprefix(tok, ".")) { /* domain: match last fields */ size_t str_len, tok_len; @@ -322,23 +321,6 @@ static bool from_match (char *tok, const char *string) } return false; } - -/* string_match - match a string against one token */ -static bool string_match (const char *tok, const char *string) -{ - - /* - * If the token has the magic value "ALL" the match always succeeds. - * Otherwise, return true if the token fully matches the string. - */ - if (strcaseeq(tok, "ALL")) { /* ALL: always matches */ - return true; - } else if (strcaseeq(tok, string)) { /* try exact match */ - return true; - } - return false; -} - #else /* !USE_PAM */ extern int ISO_C_forbids_an_empty_translation_unit; #endif /* !USE_PAM */ From 9edd0a0e727e9b46b90d53c1a17e16fda7a75913 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 14 Jun 2026 01:55:22 +0200 Subject: [PATCH 02/12] src/login_nopam.c: from_match(): Unify style of conditionals Signed-off-by: Alejandro Colomar --- src/login_nopam.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/login_nopam.c b/src/login_nopam.c index 53f0c0dbfc..dd0a4a922c 100644 --- a/src/login_nopam.c +++ b/src/login_nopam.c @@ -308,16 +308,14 @@ static bool from_match (char *tok, const char *string) str_len = strlen (string); tok_len = strlen (tok); - if ( (str_len > tok_len) - && strcaseeq(tok, string + str_len - tok_len)) { + if (str_len > tok_len && strcaseeq(tok, string + str_len - tok_len)) return true; - } } else if (strcaseeq(tok, "LOCAL")) { /* LOCAL: no dots */ if (!strchr(string, '.')) return true; - } else if ( (!streq(tok, "") && tok[strlen(tok) - 1] == '.') /* network */ - && strprefix(resolve_hostname(string), tok)) { - return true; + } else if (!streq(tok, "") && tok[strlen(tok) - 1] == '.') { /* network */ + if (strprefix(resolve_hostname(string), tok)) + return true; } return false; } From fadafa8fa9474e4d25b5fa4f25fc121605066d79 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 14 Jun 2026 01:57:28 +0200 Subject: [PATCH 03/12] src/login_nopam.c: from_match(): return directly in all cases This simplifies the conditionals, allowing the removal of 'else's. Signed-off-by: Alejandro Colomar --- src/login_nopam.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/login_nopam.c b/src/login_nopam.c index dd0a4a922c..2f3c8a02a9 100644 --- a/src/login_nopam.c +++ b/src/login_nopam.c @@ -308,14 +308,11 @@ static bool from_match (char *tok, const char *string) str_len = strlen (string); tok_len = strlen (tok); - if (str_len > tok_len && strcaseeq(tok, string + str_len - tok_len)) - return true; + return str_len > tok_len && strcaseeq(tok, string + str_len - tok_len); } else if (strcaseeq(tok, "LOCAL")) { /* LOCAL: no dots */ - if (!strchr(string, '.')) - return true; + return !strchr(string, '.'); } else if (!streq(tok, "") && tok[strlen(tok) - 1] == '.') { /* network */ - if (strprefix(resolve_hostname(string), tok)) - return true; + return !!strprefix(resolve_hostname(string), tok); } return false; } From 2f39983c89a102771772ff8c3dc3db881d643bc2 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 14 Jun 2026 02:00:46 +0200 Subject: [PATCH 04/12] src/login_nopam.c: Don't else after return Signed-off-by: Alejandro Colomar --- src/login_nopam.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/login_nopam.c b/src/login_nopam.c index 2f3c8a02a9..16c6829cb3 100644 --- a/src/login_nopam.c +++ b/src/login_nopam.c @@ -221,16 +221,16 @@ static bool user_match (char *tok, const char *string) * the token is a group that contains the username. */ host = stpsep(tok + 1, "@"); /* split user@host pattern */ - if (host != NULL) { + if (host != NULL) return user_match(tok, string) && from_match(host, myhostname()); #if HAVE_INNETGR - } else if (strprefix(tok, "@")) { /* netgroup */ + if (strprefix(tok, "@")) /* netgroup */ return (netgroup_match (tok + 1, NULL, string)); #endif - } else if (strcaseeq(tok, "ALL") || strcaseeq(tok, string)) { + if (strcaseeq(tok, "ALL") || strcaseeq(tok, string)) return true; /* local, no need for xgetgrnam */ - } else if ((group = getgrnam (tok)) != NULL) { /* try group membership */ + if ((group = getgrnam (tok)) != NULL) { /* try group membership */ int i; for (i = 0; NULL != group->gr_mem[i]; i++) { if (strcaseeq(string, group->gr_mem[i])) { @@ -297,23 +297,22 @@ static bool from_match (char *tok, const char *string) * if it matches the head of the string. */ #if HAVE_INNETGR - if (strprefix(tok, "@")) { /* netgroup */ + if (strprefix(tok, "@")) /* netgroup */ return (netgroup_match (tok + 1, string, NULL)); - } else #endif - if (strcaseeq(tok, "ALL") || strcaseeq(tok, string)) { + if (strcaseeq(tok, "ALL") || strcaseeq(tok, string)) return true; - } else if (strprefix(tok, ".")) { /* domain: match last fields */ + if (strprefix(tok, ".")) { /* domain: match last fields */ size_t str_len, tok_len; str_len = strlen (string); tok_len = strlen (tok); return str_len > tok_len && strcaseeq(tok, string + str_len - tok_len); - } else if (strcaseeq(tok, "LOCAL")) { /* LOCAL: no dots */ + } + if (strcaseeq(tok, "LOCAL")) /* LOCAL: no dots */ return !strchr(string, '.'); - } else if (!streq(tok, "") && tok[strlen(tok) - 1] == '.') { /* network */ + if (!streq(tok, "") && tok[strlen(tok) - 1] == '.') /* network */ return !!strprefix(resolve_hostname(string), tok); - } return false; } #else /* !USE_PAM */ From 320b5ddc98c370a5ee79b5d924765717488ee1ac Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 14 Jun 2026 03:05:53 +0200 Subject: [PATCH 05/12] src/login_nopam.c: login_access(): Reduce scope of local variables Signed-off-by: Alejandro Colomar --- src/login_nopam.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/login_nopam.c b/src/login_nopam.c index 16c6829cb3..7d580420ba 100644 --- a/src/login_nopam.c +++ b/src/login_nopam.c @@ -84,9 +84,6 @@ login_access(const char *user, const char *from) { FILE *fp; char line[BUFSIZ]; - char *perm; /* becomes permission field */ - char *users; /* becomes list of login names */ - char *froms; /* becomes list of terminals or hosts */ bool match = false; /* @@ -103,6 +100,9 @@ login_access(const char *user, const char *from) && (fgets_a(line, fp) != NULL)) { char *p; + char *perm; /* becomes permission field */ + char *users; /* becomes list of login names */ + char *froms; /* becomes list of terminals or hosts */ lineno++; if (stpsep(line, "\n") == NULL) { From d6264edfdf72500ea380676d33a36a5ed378860e Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 14 Jun 2026 15:09:14 +0200 Subject: [PATCH 06/12] src/login_nopam.c: login_access(): Move error handling earlier This will allow reducing indentation for the rest of the code. Signed-off-by: Alejandro Colomar --- src/login_nopam.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/login_nopam.c b/src/login_nopam.c index 7d580420ba..dcc4845471 100644 --- a/src/login_nopam.c +++ b/src/login_nopam.c @@ -90,11 +90,17 @@ login_access(const char *user, const char *from) * Process the table one line at a time and stop at the first match. * Blank lines and lines that begin with a '#' character are ignored. * Non-comment lines are broken at the ':' character. All fields are - * mandatory. The first field should be a "+" or "-" character. A - * non-existing table means no access control. + * mandatory. The first field should be a "+" or "-" character. */ fp = fopen (TABLE, "r"); - if (NULL != fp) { + if (fp == NULL) { + if (errno != ENOENT) { + int err = errno; + SYSLOG(LOG_ERR, "cannot open %s: %s", TABLE, strerror(err)); + } + return true; // A non-existent table means no access control. + } + { intmax_t lineno = 0; /* for diagnostics */ while ( !match && (fgets_a(line, fp) != NULL)) @@ -136,9 +142,6 @@ login_access(const char *user, const char *from) && list_match (users, user, user_match)); } (void) fclose (fp); - } else if (errno != ENOENT) { - int err = errno; - SYSLOG(LOG_ERR, "cannot open %s: %s", TABLE, strerror(err)); } return (!match || strprefix(line, "+"))?1:0; } From 1dbaed7b1ea358e0365685ea7b057abbdde24261 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 14 Jun 2026 15:13:15 +0200 Subject: [PATCH 07/12] src/login_nopam.c: login_access(): Reduce indentation Signed-off-by: Alejandro Colomar --- src/login_nopam.c | 80 +++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/login_nopam.c b/src/login_nopam.c index dcc4845471..67f930cdb5 100644 --- a/src/login_nopam.c +++ b/src/login_nopam.c @@ -100,49 +100,49 @@ login_access(const char *user, const char *from) } return true; // A non-existent table means no access control. } + + intmax_t lineno = 0; /* for diagnostics */ + while ( !match + && (fgets_a(line, fp) != NULL)) { - intmax_t lineno = 0; /* for diagnostics */ - while ( !match - && (fgets_a(line, fp) != NULL)) - { - char *p; - char *perm; /* becomes permission field */ - char *users; /* becomes list of login names */ - char *froms; /* becomes list of terminals or hosts */ - - lineno++; - if (stpsep(line, "\n") == NULL) { - SYSLOG(LOG_ERR, - "%s: line %jd: missing newline or line too long", - TABLE, lineno); - continue; - } - if (strprefix(line, "#")) { - continue; /* comment line */ - } - stpcpy(stprspn(line, " \t"), ""); - if (streq(line, "")) { /* skip blank lines */ - continue; - } - p = line; - perm = strsep(&p, ":"); - users = strsep(&p, ":"); - froms = strsep(&p, ":"); - if (froms == NULL || p != NULL) { - SYSLOG(LOG_ERR, "%s: line %jd: bad field count", - TABLE, lineno); - continue; - } - if (perm[0] != '+' && perm[0] != '-') { - SYSLOG(LOG_ERR, "%s: line %jd: bad first field", - TABLE, lineno); - continue; - } - match = ( list_match (froms, from, from_match) - && list_match (users, user, user_match)); + char *p; + char *perm; /* becomes permission field */ + char *users; /* becomes list of login names */ + char *froms; /* becomes list of terminals or hosts */ + + lineno++; + if (stpsep(line, "\n") == NULL) { + SYSLOG(LOG_ERR, + "%s: line %jd: missing newline or line too long", + TABLE, lineno); + continue; } - (void) fclose (fp); + if (strprefix(line, "#")) { + continue; /* comment line */ + } + stpcpy(stprspn(line, " \t"), ""); + if (streq(line, "")) { /* skip blank lines */ + continue; + } + p = line; + perm = strsep(&p, ":"); + users = strsep(&p, ":"); + froms = strsep(&p, ":"); + if (froms == NULL || p != NULL) { + SYSLOG(LOG_ERR, "%s: line %jd: bad field count", + TABLE, lineno); + continue; + } + if (perm[0] != '+' && perm[0] != '-') { + SYSLOG(LOG_ERR, "%s: line %jd: bad first field", + TABLE, lineno); + continue; + } + match = ( list_match(froms, from, from_match) + && list_match(users, user, user_match)); } + (void) fclose(fp); + return (!match || strprefix(line, "+"))?1:0; } From 30c20ba4ca8ca0b7dfe53b8ce712514d9213b00a Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 14 Jun 2026 15:19:09 +0200 Subject: [PATCH 08/12] src/login_nopam.c: login_access(): Use for instead of while loop And rename the iterator to the usual 'i'. Signed-off-by: Alejandro Colomar --- src/login_nopam.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/login_nopam.c b/src/login_nopam.c index 67f930cdb5..e72e6b7e02 100644 --- a/src/login_nopam.c +++ b/src/login_nopam.c @@ -101,20 +101,16 @@ login_access(const char *user, const char *from) return true; // A non-existent table means no access control. } - intmax_t lineno = 0; /* for diagnostics */ - while ( !match - && (fgets_a(line, fp) != NULL)) - { + for (intmax_t i = 1; !match && fgets_a(line, fp) != NULL; i++) { char *p; char *perm; /* becomes permission field */ char *users; /* becomes list of login names */ char *froms; /* becomes list of terminals or hosts */ - lineno++; if (stpsep(line, "\n") == NULL) { SYSLOG(LOG_ERR, "%s: line %jd: missing newline or line too long", - TABLE, lineno); + TABLE, i); continue; } if (strprefix(line, "#")) { @@ -130,12 +126,12 @@ login_access(const char *user, const char *from) froms = strsep(&p, ":"); if (froms == NULL || p != NULL) { SYSLOG(LOG_ERR, "%s: line %jd: bad field count", - TABLE, lineno); + TABLE, i); continue; } if (perm[0] != '+' && perm[0] != '-') { SYSLOG(LOG_ERR, "%s: line %jd: bad first field", - TABLE, lineno); + TABLE, i); continue; } match = ( list_match(froms, from, from_match) From f999479e2bf96dde41d960e4f5faa4d36edaa11b Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 14 Jun 2026 15:32:15 +0200 Subject: [PATCH 09/12] src/login_nopam.c: login_access(): Handle a match earlier This makes the logic more readable, and removes one variable. Signed-off-by: Alejandro Colomar --- src/login_nopam.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/login_nopam.c b/src/login_nopam.c index e72e6b7e02..77149ec64a 100644 --- a/src/login_nopam.c +++ b/src/login_nopam.c @@ -84,7 +84,6 @@ login_access(const char *user, const char *from) { FILE *fp; char line[BUFSIZ]; - bool match = false; /* * Process the table one line at a time and stop at the first match. @@ -101,7 +100,7 @@ login_access(const char *user, const char *from) return true; // A non-existent table means no access control. } - for (intmax_t i = 1; !match && fgets_a(line, fp) != NULL; i++) { + for (intmax_t i = 1; fgets_a(line, fp) != NULL; i++) { char *p; char *perm; /* becomes permission field */ char *users; /* becomes list of login names */ @@ -134,12 +133,15 @@ login_access(const char *user, const char *from) TABLE, i); continue; } - match = ( list_match(froms, from, from_match) - && list_match(users, user, user_match)); + if ( list_match(froms, from, from_match) + && list_match(users, user, user_match)) + { + fclose(fp); + return !!strprefix(line, "+"); + } } - (void) fclose(fp); - - return (!match || strprefix(line, "+"))?1:0; + fclose(fp); + return true; } /* list_match - match an item against a list of tokens with exceptions */ From 2b5979522d4f008158253c7c9296bf70979b0888 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 14 Jun 2026 15:51:01 +0200 Subject: [PATCH 10/12] src/login_nopam.c: login_access(): Consistently use 'perm' line and perm point to the same thing, but perm is more appropriate. Signed-off-by: Alejandro Colomar --- src/login_nopam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/login_nopam.c b/src/login_nopam.c index 77149ec64a..58c1f30be4 100644 --- a/src/login_nopam.c +++ b/src/login_nopam.c @@ -137,7 +137,7 @@ login_access(const char *user, const char *from) && list_match(users, user, user_match)) { fclose(fp); - return !!strprefix(line, "+"); + return !!strprefix(perm, "+"); } } fclose(fp); From dd0fd366ea1bbef9a281185fdc9369f887f74d13 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 14 Jun 2026 15:59:02 +0200 Subject: [PATCH 11/12] src/login_nopam.c: login_access(): Remove redundant comments And remove some superfluous braces. Signed-off-by: Alejandro Colomar --- src/login_nopam.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/login_nopam.c b/src/login_nopam.c index 58c1f30be4..c85d7b70c5 100644 --- a/src/login_nopam.c +++ b/src/login_nopam.c @@ -85,12 +85,6 @@ login_access(const char *user, const char *from) FILE *fp; char line[BUFSIZ]; - /* - * Process the table one line at a time and stop at the first match. - * Blank lines and lines that begin with a '#' character are ignored. - * Non-comment lines are broken at the ':' character. All fields are - * mandatory. The first field should be a "+" or "-" character. - */ fp = fopen (TABLE, "r"); if (fp == NULL) { if (errno != ENOENT) { @@ -112,13 +106,12 @@ login_access(const char *user, const char *from) TABLE, i); continue; } - if (strprefix(line, "#")) { - continue; /* comment line */ - } + if (strprefix(line, "#")) // comment line + continue; stpcpy(stprspn(line, " \t"), ""); - if (streq(line, "")) { /* skip blank lines */ + if (streq(line, "")) continue; - } + p = line; perm = strsep(&p, ":"); users = strsep(&p, ":"); From 3fe331f1e6a81f6e23ffbbdee647c022f5e893a0 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Sun, 14 Jun 2026 15:44:30 +0200 Subject: [PATCH 12/12] lib/, src/login_nopam.c: login_access(): Return bool Signed-off-by: Alejandro Colomar --- lib/prototypes.h | 2 +- src/login_nopam.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/prototypes.h b/lib/prototypes.h index d22c477ae1..c3b0d6ef43 100644 --- a/lib/prototypes.h +++ b/lib/prototypes.h @@ -201,7 +201,7 @@ extern void dolastlog ( #endif /* ENABLE_LASTLOG */ /* login_nopam.c */ -extern int login_access (const char *user, const char *from); +extern bool login_access(const char *user, const char *from); /* loginprompt.c */ extern void login_prompt (char *, int); diff --git a/src/login_nopam.c b/src/login_nopam.c index c85d7b70c5..494a21b506 100644 --- a/src/login_nopam.c +++ b/src/login_nopam.c @@ -79,7 +79,7 @@ static bool from_match (char *tok, const char *string); static const char *resolve_hostname (const char *string); /* login_access - match username/group and host/tty with access control file */ -int +bool login_access(const char *user, const char *from) { FILE *fp;