From c6dd59e392fc90d13da75c8700b68fa3e71e00a6 Mon Sep 17 00:00:00 2001 From: hanez Date: Wed, 18 Jun 2025 22:19:48 +0200 Subject: [PATCH] Added an extended version. My favorite. --- .gitignore | 1 + Makefile | 4 ++ chkgrp-native-min-extended.c | 102 +++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 chkgrp-native-min-extended.c diff --git a/.gitignore b/.gitignore index 538d43e..f03ba1c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ chkgrp chkgrp-min chkgrp-native chkgrp-native-min +chkgrp-native-min-extended diff --git a/Makefile b/Makefile index 8de95ca..f6bb51d 100644 --- a/Makefile +++ b/Makefile @@ -3,22 +3,26 @@ all: $(CC) -Wall -o ./chkgrp-min ./chkgrp-min.c $(CC) -Wall -o ./chkgrp-native ./chkgrp-native.c $(CC) -Wall -o ./chkgrp-native-min ./chkgrp-native-min.c + $(CC) -Wall -o ./chkgrp-native-min-extended ./chkgrp-native-min-extended.c clean: rm -f ./chkgrp rm -f ./chkgrp-min rm -f ./chkgrp-native rm -f ./chkgrp-native-min + rm -f ./chkgrp-native-min-extended install: install -g 0 -o 0 -m 0655 ./chkgrp /usr/bin/ install -g 0 -o 0 -m 0655 ./chkgrp-min /usr/bin/ install -g 0 -o 0 -m 0655 ./chkgrp-native /usr/bin/ install -g 0 -o 0 -m 0655 ./chkgrp-native-min /usr/bin/ + install -g 0 -o 0 -m 0655 ./chkgrp-native-min-extended /usr/bin/ uninstall: rm -f /usr/bin/chkgrp rm -f /usr/bin/chkgrp-min rm -f /usr/bin/chkgrp-native rm -f /usr/bin/chkgrp-native-min + rm -f /usr/bin/chkgrp-native-min-extended diff --git a/chkgrp-native-min-extended.c b/chkgrp-native-min-extended.c new file mode 100644 index 0000000..c46d184 --- /dev/null +++ b/chkgrp-native-min-extended.c @@ -0,0 +1,102 @@ +/** + * chkgrp-min-native-extended is a program that checks if a user is a member + * of a group. + * + * Author: Johannes Findeisen - 2025 + * Homepage: https://git.xw3.org/hanez/chkgrp + * License: Apache-2.0 (see LICENSE) + */ + +#include +#include +#include +#include + +#define MAX_LINE 1024 +#define MAX_NAME 256 + +int main(int argc, char *argv[]) +{ + if (argc != 3) + return 2; + + const char *username = argv[1]; + const char *groupname = argv[2]; + + if (strlen(username) > MAX_NAME || strlen(groupname) > MAX_NAME) + return 2; + + // Step 1: Find user in /etc/passwd to get their primary GID + FILE *passwd = fopen("/etc/passwd", "r"); + if (!passwd) + return 2; + + char line[MAX_LINE]; + int user_gid = -1; + while (fgets(line, sizeof(line), passwd)) { + char *u = strtok(line, ":"); + if (!u || strcmp(u, username) != 0) + continue; + + strtok(NULL, ":"); // skip password + strtok(NULL, ":"); // skip UID + char *gid_str = strtok(NULL, ":"); + if (!gid_str) + break; + + user_gid = atoi(gid_str); + break; + } + fclose(passwd); + if (user_gid < 0) + return 2; + + // Step 2: Find group in /etc/group and check membership or GID match + FILE *group = fopen("/etc/group", "r"); + if (!group) + return 2; + + int found = 0; + while (fgets(line, sizeof(line), group)) { + char *grp = strtok(line, ":"); + if (!grp || strcmp(grp, groupname) != 0) + continue; + + strtok(NULL, ":"); // skip password + char *gid_str = strtok(NULL, ":"); + if (!gid_str) + break; + + int group_gid = atoi(gid_str); + if (group_gid == user_gid) { + puts("Yes"); + fclose(group); + return 0; + } + + char *members = strtok(NULL, ":\n"); + if (!members) + break; + + char *m = strtok(members, ","); + while (m) { + if (!strcmp(m, username)) { + puts("Yes"); + fclose(group); + return 0; + } + m = strtok(NULL, ","); + } + + found = 1; + break; + } + + fclose(group); + if (!found) + return 2; + + puts("No"); + return 1; +} +