aboutsummaryrefslogtreecommitdiffstats
path: root/guts
diff options
context:
space:
mode:
Diffstat (limited to 'guts')
-rw-r--r--guts/README31
-rw-r--r--guts/endgrent.c11
-rw-r--r--guts/endpwent.c11
-rw-r--r--guts/fopen.c2
-rw-r--r--guts/fopen64.c2
-rw-r--r--guts/getgrent.c18
-rw-r--r--guts/getgrent_r.c21
-rw-r--r--guts/getgrgid.c18
-rw-r--r--guts/getgrgid_r.c26
-rw-r--r--guts/getgrnam.c20
-rw-r--r--guts/getgrnam_r.c24
-rw-r--r--guts/getgrouplist.c39
-rw-r--r--guts/getgroups.c15
-rw-r--r--guts/getpw.c30
-rw-r--r--guts/getpwent.c18
-rw-r--r--guts/getpwent_r.c14
-rw-r--r--guts/getpwnam.c18
-rw-r--r--guts/getpwnam_r.c23
-rw-r--r--guts/getpwuid.c18
-rw-r--r--guts/getpwuid_r.c23
-rw-r--r--guts/setgrent.c11
-rw-r--r--guts/setpwent.c11
22 files changed, 402 insertions, 2 deletions
diff --git a/guts/README b/guts/README
index e933349..a1030c6 100644
--- a/guts/README
+++ b/guts/README
@@ -157,3 +157,34 @@ dummied them out:
renameat
tempnam
tmpnam
+
+The following functions are partially emulated in order to provide for
+emulation of various getpw*() and getgr*() functions. No handling is
+provided for putpw*() or putgr*(). Nearly everything is ultimately
+implemented in terms of fgetpwent_r() and fgetgrent_r(), which are
+GNU extensions corresponding to fgetpwent() and fgetgrent(), allowing
+pseudo to read password information from an arbitrary stream; the
+setpwent() and setgrent() functions are modified to pick /etc/* from
+the pseudo_chroot path, if one is set, or from PSEUDO_PASSWD, if that
+is set, or else the system /etc/* files.
+
+ endgrent
+ endpwent
+ getgrent
+ getgrent_r
+ getgrgid
+ getgrgid_r
+ getgrnam
+ getgrnam_r
+ getgrouplist
+ getgroups
+ getpw
+ getpwent
+ getpwent_r
+ getpwnam
+ getpwnam_r
+ getpwuid
+ getpwuid_r
+ setgrent
+ setgroups
+ setpwent
diff --git a/guts/endgrent.c b/guts/endgrent.c
new file mode 100644
index 0000000..8c40845
--- /dev/null
+++ b/guts/endgrent.c
@@ -0,0 +1,11 @@
+/*
+ * static void
+ * wrap_endgrent(void) {
+ *
+ */
+
+ pseudo_grp_close();
+
+/* return;
+ * }
+ */
diff --git a/guts/endpwent.c b/guts/endpwent.c
new file mode 100644
index 0000000..7180c0c
--- /dev/null
+++ b/guts/endpwent.c
@@ -0,0 +1,11 @@
+/*
+ * static void
+ * wrap_endpwent(void) {
+ *
+ */
+
+ pseudo_pwd_close();
+
+/* return;
+ * }
+ */
diff --git a/guts/fopen.c b/guts/fopen.c
index 69d9ce6..15b27f5 100644
--- a/guts/fopen.c
+++ b/guts/fopen.c
@@ -13,7 +13,7 @@
if (rc) {
int fd = fileno(rc);
- pseudo_debug(2, "fopen '%s': fd %d\n", path, fd);
+ pseudo_debug(2, "fopen '%s': fd %d <FILE %p>\n", path, fd, (void *) rc);
if (real___fxstat64(_STAT_VER, fd, &buf) != -1) {
if (!existed) {
pseudo_client_op(OP_CREAT, 0, -1, -1, path, &buf);
diff --git a/guts/fopen64.c b/guts/fopen64.c
index c2286f2..78cfdaa 100644
--- a/guts/fopen64.c
+++ b/guts/fopen64.c
@@ -14,7 +14,7 @@
if (rc) {
int fd = fileno(rc);
- pseudo_debug(2, "fopen64 '%s': fd %d\n", path, fd);
+ pseudo_debug(2, "fopen64 '%s': fd %d <FILE %p>\n", path, fd, (void *) rc);
if (real___fxstat64(_STAT_VER, fd, &buf) != -1) {
if (!existed) {
pseudo_client_op(OP_CREAT, 0, -1, -1, path, &buf);
diff --git a/guts/getgrent.c b/guts/getgrent.c
new file mode 100644
index 0000000..0be9ec5
--- /dev/null
+++ b/guts/getgrent.c
@@ -0,0 +1,18 @@
+/*
+ * static struct group *
+ * wrap_getgrent(void) {
+ * struct group * rc = NULL;
+ */
+ static struct group grp;
+ static char grbuf[PSEUDO_PWD_MAX];
+ int r_rc;
+
+ r_rc = wrap_getgrent_r(&grp, grbuf, PSEUDO_PWD_MAX, &rc);
+ /* different error return conventions */
+ if (r_rc != 0) {
+ errno = r_rc;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/guts/getgrent_r.c b/guts/getgrent_r.c
new file mode 100644
index 0000000..6bb9667
--- /dev/null
+++ b/guts/getgrent_r.c
@@ -0,0 +1,21 @@
+/*
+ * static int
+ * wrap_getgrent_r(struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) {
+ * int rc = -1;
+ */
+
+ /* note that we don't wrap fgetgrent_r, since there's no path
+ * references in it.
+ */
+ rc = fgetgrent_r(pseudo_grp, gbuf, buf, buflen, gbufp);
+ if (rc == 0 && *gbufp) {
+ if (*gbufp == gbuf) {
+ pseudo_debug(1, "found group: %d/%s\n", gbuf->gr_gid, gbuf->gr_name);
+ } else {
+ pseudo_debug(1, "found group, but it's wrong?");
+ }
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/guts/getgrgid.c b/guts/getgrgid.c
new file mode 100644
index 0000000..20c85c9
--- /dev/null
+++ b/guts/getgrgid.c
@@ -0,0 +1,18 @@
+/*
+ * static struct group *
+ * wrap_getgrgid(gid_t gid) {
+ * struct group * rc = NULL;
+ */
+ static struct group grp;
+ static char grbuf[PSEUDO_PWD_MAX];
+ int r_rc;
+
+ r_rc = wrap_getgrgid_r(gid, &grp, grbuf, PSEUDO_PWD_MAX, &rc);
+ /* different error return conventions */
+ if (r_rc != 0) {
+ errno = r_rc;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/guts/getgrgid_r.c b/guts/getgrgid_r.c
new file mode 100644
index 0000000..4ae6a93
--- /dev/null
+++ b/guts/getgrgid_r.c
@@ -0,0 +1,26 @@
+/*
+ * static int
+ * wrap_getgrgid_r(gid_t gid, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) {
+ * int rc = -1;
+ */
+
+ setgrent();
+ while ((rc = wrap_getgrent_r(gbuf, buf, buflen, gbufp)) == 0) {
+ /* 0 means no error occurred, and *gbufp == gbuf */
+ if (gbuf->gr_gid == gid) {
+ pseudo_debug(1, "found group gid %d, name %s\n",
+ gbuf->gr_gid, gbuf->gr_name);
+ return rc;
+ }
+ }
+ endgrent();
+ /* we never found a match; rc is 0 if there was no error, or
+ * non-zero if an error occurred. Either way, set the
+ * pwbufp pointer to NULL to indicate that we didn't find
+ * something, and leave rc alone.
+ */
+ *gbufp = NULL;
+
+/* return rc;
+ * }
+ */
diff --git a/guts/getgrnam.c b/guts/getgrnam.c
new file mode 100644
index 0000000..191fe25
--- /dev/null
+++ b/guts/getgrnam.c
@@ -0,0 +1,20 @@
+/*
+ * static struct group *
+ * wrap_getgrnam(const char *name) {
+ * struct group * rc = NULL;
+ */
+
+ static struct group grp;
+ static char grbuf[PSEUDO_PWD_MAX];
+ int r_rc;
+
+ r_rc = wrap_getgrnam_r(name, &grp, grbuf, PSEUDO_PWD_MAX, &rc);
+ /* different error return conventions */
+ if (r_rc != 0) {
+ errno = r_rc;
+ }
+
+
+/* return rc;
+ * }
+ */
diff --git a/guts/getgrnam_r.c b/guts/getgrnam_r.c
new file mode 100644
index 0000000..f70bbdc
--- /dev/null
+++ b/guts/getgrnam_r.c
@@ -0,0 +1,24 @@
+/*
+ * static int
+ * wrap_getgrnam_r(const char *name, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) {
+ * int rc = -1;
+ */
+
+ setgrent();
+ while ((rc = wrap_getgrent_r(gbuf, buf, buflen, gbufp)) == 0) {
+ /* 0 means no error occurred, and *gbufp == gbuf */
+ if (gbuf->gr_name && !strcmp(gbuf->gr_name, name))
+ return rc;
+ }
+ endgrent();
+ /* we never found a match; rc is 0 if there was no error, or
+ * non-zero if an error occurred. Either way, set the
+ * pwbufp pointer to NULL to indicate that we didn't find
+ * something, and leave rc alone.
+ */
+ *gbufp = NULL;
+
+
+/* return rc;
+ * }
+ */
diff --git a/guts/getgrouplist.c b/guts/getgrouplist.c
new file mode 100644
index 0000000..ef362bb
--- /dev/null
+++ b/guts/getgrouplist.c
@@ -0,0 +1,39 @@
+/*
+ * static int
+ * wrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) {
+ * int rc = -1;
+ */
+
+ int found = 0;
+ int found_group = 0;
+ char buf[PSEUDO_PWD_MAX];
+ struct group grp, *gbuf = &grp;
+
+ setgrent();
+ while ((rc = wrap_getgrent_r(gbuf, buf, PSEUDO_PWD_MAX, &gbuf)) == 0) {
+ int i = 0;
+ for (i = 0; gbuf->gr_mem[i]; ++i) {
+ if (!strcmp(gbuf->gr_mem[i], user)) {
+ if (found < *ngroups)
+ groups[found] = gbuf->gr_gid;
+ ++found;
+ if (gbuf->gr_gid == group)
+ found_group = 1;
+ }
+ }
+ }
+ endgrent();
+ if (!found_group) {
+ if (found < *ngroups)
+ groups[found] = group;
+ ++found;
+ }
+ if (found >= *ngroups)
+ rc = -1;
+ else
+ rc = found;
+ *ngroups = found;
+
+/* return rc;
+ * }
+ */
diff --git a/guts/getgroups.c b/guts/getgroups.c
new file mode 100644
index 0000000..8394325
--- /dev/null
+++ b/guts/getgroups.c
@@ -0,0 +1,15 @@
+/*
+ * static int
+ * wrap_getgroups(int size, gid_t *list) {
+ * int rc = -1;
+ */
+
+ /* you're only in group zero */
+ rc = 1;
+ if (size > 0) {
+ list[0] = 0;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/guts/getpw.c b/guts/getpw.c
new file mode 100644
index 0000000..cf41799
--- /dev/null
+++ b/guts/getpw.c
@@ -0,0 +1,30 @@
+/*
+ * static int
+ * wrap_getpw(uid_t uid, char *buf) {
+ * int rc = -1;
+ */
+ static struct passwd pwd;
+ static char pwbuf[PSEUDO_PWD_MAX];
+ struct passwd *pwp;
+
+ pseudo_diag("warning: unsafe getpw() called. hoping buf has at least %d chars.\n",
+ PSEUDO_PWD_MAX);
+ rc = wrap_getpwuid_r(uid, &pwd, pwbuf, PSEUDO_PWD_MAX, &pwp);
+ /* different error return conventions */
+ if (rc != 0) {
+ errno = rc;
+ rc = -1;
+ } else {
+ snprintf(buf, PSEUDO_PWD_MAX, "%s:%s:%d:%d:%s:%s:%s",
+ pwd.pw_name,
+ pwd.pw_passwd,
+ pwd.pw_uid,
+ pwd.pw_gid,
+ pwd.pw_gecos,
+ pwd.pw_dir,
+ pwd.pw_shell);
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/guts/getpwent.c b/guts/getpwent.c
new file mode 100644
index 0000000..5b76ad0
--- /dev/null
+++ b/guts/getpwent.c
@@ -0,0 +1,18 @@
+/*
+ * static struct passwd *
+ * wrap_getpwent(void) {
+ * struct passwd * rc = NULL;
+ */
+ static struct passwd pwd;
+ static char pwbuf[PSEUDO_PWD_MAX];
+ int r_rc;
+
+ r_rc = wrap_getpwent_r(&pwd, pwbuf, PSEUDO_PWD_MAX, &rc);
+ /* different error return conventions */
+ if (r_rc != 0) {
+ errno = r_rc;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/guts/getpwent_r.c b/guts/getpwent_r.c
new file mode 100644
index 0000000..2bf1db2
--- /dev/null
+++ b/guts/getpwent_r.c
@@ -0,0 +1,14 @@
+/*
+ * static int
+ * wrap_getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) {
+ * int rc = -1;
+ */
+
+ /* note that we don't wrap fgetpwent_r, since there's no path
+ * references in it.
+ */
+ return fgetpwent_r(pseudo_pwd, pwbuf, buf, buflen, pwbufp);
+
+/* return rc;
+ * }
+ */
diff --git a/guts/getpwnam.c b/guts/getpwnam.c
new file mode 100644
index 0000000..04aed89
--- /dev/null
+++ b/guts/getpwnam.c
@@ -0,0 +1,18 @@
+/*
+ * static struct passwd *
+ * wrap_getpwnam(const char *name) {
+ * struct passwd * rc = NULL;
+ */
+ static struct passwd pwd;
+ static char pwbuf[PSEUDO_PWD_MAX];
+ int r_rc;
+
+ r_rc = wrap_getpwnam_r(name, &pwd, pwbuf, PSEUDO_PWD_MAX, &rc);
+ /* different error return conventions */
+ if (r_rc != 0) {
+ errno = r_rc;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/guts/getpwnam_r.c b/guts/getpwnam_r.c
new file mode 100644
index 0000000..d292cdb
--- /dev/null
+++ b/guts/getpwnam_r.c
@@ -0,0 +1,23 @@
+/*
+ * static int
+ * wrap_getpwnam_r(const char *name, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) {
+ * int rc = -1;
+ */
+
+ setpwent();
+ while ((rc = wrap_getpwent_r(pwbuf, buf, buflen, pwbufp)) == 0) {
+ /* 0 means no error occurred, and *pwbufp == pwbuf */
+ if (pwbuf->pw_name && !strcmp(pwbuf->pw_name, name))
+ return rc;
+ }
+ endpwent();
+ /* we never found a match; rc is 0 if there was no error, or
+ * non-zero if an error occurred. Either way, set the
+ * pwbufp pointer to NULL to indicate that we didn't find
+ * something, and leave rc alone.
+ */
+ *pwbufp = NULL;
+
+/* return rc;
+ * }
+ */
diff --git a/guts/getpwuid.c b/guts/getpwuid.c
new file mode 100644
index 0000000..9407405
--- /dev/null
+++ b/guts/getpwuid.c
@@ -0,0 +1,18 @@
+/*
+ * static struct passwd *
+ * wrap_getpwuid(uid_t uid) {
+ * struct passwd * rc = NULL;
+ */
+ static struct passwd pwd;
+ static char pwbuf[PSEUDO_PWD_MAX];
+ int r_rc;
+
+ r_rc = wrap_getpwuid_r(uid, &pwd, pwbuf, PSEUDO_PWD_MAX, &rc);
+ /* different error return conventions */
+ if (r_rc != 0) {
+ errno = r_rc;
+ }
+
+/* return rc;
+ * }
+ */
diff --git a/guts/getpwuid_r.c b/guts/getpwuid_r.c
new file mode 100644
index 0000000..f2b6afb
--- /dev/null
+++ b/guts/getpwuid_r.c
@@ -0,0 +1,23 @@
+/*
+ * static int
+ * wrap_getpwuid_r(uid_t uid, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) {
+ * int rc = -1;
+ */
+
+ setpwent();
+ while ((rc = wrap_getpwent_r(pwbuf, buf, buflen, pwbufp)) == 0) {
+ /* 0 means no error occurred, and *pwbufp == pwbuf */
+ if (pwbuf->pw_uid == uid)
+ return rc;
+ }
+ endpwent();
+ /* we never found a match; rc is 0 if there was no error, or
+ * non-zero if an error occurred. Either way, set the
+ * pwbufp pointer to NULL to indicate that we didn't find
+ * something, and leave rc alone.
+ */
+ *pwbufp = NULL;
+
+/* return rc;
+ * }
+ */
diff --git a/guts/setgrent.c b/guts/setgrent.c
new file mode 100644
index 0000000..c840de0
--- /dev/null
+++ b/guts/setgrent.c
@@ -0,0 +1,11 @@
+/*
+ * static void
+ * wrap_setgrent(void) {
+ *
+ */
+
+ pseudo_grp_open();
+
+/* return;
+ * }
+ */
diff --git a/guts/setpwent.c b/guts/setpwent.c
new file mode 100644
index 0000000..3941e67
--- /dev/null
+++ b/guts/setpwent.c
@@ -0,0 +1,11 @@
+/*
+ * static void
+ * wrap_setpwent(void) {
+ *
+ */
+
+ pseudo_pwd_open();
+
+/* return;
+ * }
+ */