on a populated table.
.BI "int checkpath(const char *" path ,
.BI " const struct checkpath *" cp ");"
+.BI "int checkpath_addgid(struct checkpath *" cp ", gid_t " g ");"
+.BI "void checkpath_setuid(struct checkpath *" cp ");"
+.BI "int checkpath_setgid(struct checkpath *" cp ");"
+.BI "int checkpath_setgroups(struct checkpath *" cp ");"
.BI "void checkpath_setids(struct checkpath *" cp ");"
.fi
.SH DESCRIPTION
can be set up to reflect the current user and group memberships by
calling
.B checkpath_setids
-passing the address of the structure to fill in.
+passing the address of the structure to fill in; this overwrites the
+previous contents of the
+.BR cp_uid ,
+.BR cp_gid ,
+and
+.BR cp_gids
+members. Alternatively, the functions
+.BR checkpath_setuid ,
+.BR checkpath_setgid ,
+and
+.B checkpath_setgroups
+can be called to do the job in stages. The
+.B checkpath_setuid
+function simply stores the process's real uid in
+.BR cp_uid .
+The
+.B checkpath_setgid
+and
+.B checkpath_setgroups
+functions store respectively the process's real gid and supplementary
+gids in the
+.B cp_gid
+array; they avoid inserting duplicate entries; they return 0 on success
+or \-1 if the table would overflow; they assume that the table is
+properly set up (minimally, just set
+.BR "cp_gids = 0" ).
+They use a utility function
+.B checkpath_addgid
+to do their work; it takes a pointer to a
+.B struct checkpath
+and a gid, and again returns 0 on success or \-1 if overflow would
+occur.
.SS "The cp_what flags"
The
.B cp_what
#include <mLib/alloc.h>
#include <mLib/dstr.h>
+#include <mLib/macros.h>
#include "checkpath.h"
return (bad);
}
-/* --- @checkpath_setids@ --- *
+/* --- @checkpath_addgid@ --- *
*
* Arguments: @struct checkpath *cp@ = pointer to block to fill in
+ * @gid_t g@ = group id to add
*
- * Returns: ---
+ * Returns: Zero if successful, nonzero if the array is full.
*
- * Use: Fills in the user ids and things in the structure.
+ * Use: Adds the group @g@ to the structure.
*/
-void checkpath_setids(struct checkpath *cp)
+int checkpath_addgid(struct checkpath *cp, gid_t g)
{
- int n, i;
- gid_t g = getgid();
+ int i;
+
+ for (i = 0; i < cp->cp_gids; i++) {
+ if (cp->cp_gid[i] == g)
+ return (0);
+ }
+ if (cp->cp_gids >= N(cp->cp_gid))
+ return (-1);
+ cp->cp_gid[cp->cp_gids++] = g;
+ return (0);
+}
+
+/* --- @checkpath_setuid@ --- *
+ *
+ * Arguments: @struct checkpath *cp@ = pointer to block to fill in
+ *
+ * Returns: ---
+ *
+ * Use: Fills in the @cp_uid@ slot of the structure with the real uid
+ * of the current process.
+ */
+
+void checkpath_setuid(struct checkpath *cp) { cp->cp_uid = getuid(); }
+
+/* --- @checkpath_setgid@ --- *
+ *
+ * Arguments: @struct checkpath *cp@ = pointer to block to fill in
+ *
+ * Returns: Zero if successful, nonzero if the array is full.
+ *
+ * Use: Adds the real gid of the current process to the @cp_gid@
+ * array.
+ */
- cp->cp_uid = getuid();
- n = getgroups(sizeof(cp->cp_gid) / sizeof(cp->cp_gid[0]), cp->cp_gid);
+int checkpath_setgid(struct checkpath *cp)
+ { return (checkpath_addgid(cp, getgid())); }
+/* --- @checkpath_setgroups@ --- *
+ *
+ * Arguments: @struct checkpath *cp@ = pointer to block to fill in
+ *
+ * Returns: Zero if successful, nonzero if the array is full.
+ *
+ * Use: Adds the current process's supplementary groups to the
+ * @cp_gid@ table.
+ */
+
+int checkpath_setgroups(struct checkpath *cp)
+{
+ int i, n;
+ gid_t gg[NGROUPS_MAX];
+
+ n = getgroups(N(gg), gg);
for (i = 0; i < n; i++) {
- if (cp->cp_gid[i] == g)
- goto gid_ok;
+ if (checkpath_addgid(cp, gg[i]))
+ return (-1);
}
- cp->cp_gid[n++] = g;
-gid_ok:
- cp->cp_gids = n;
+ return (0);
+}
+
+/* --- @checkpath_setids@ --- *
+ *
+ * Arguments: @struct checkpath *cp@ = pointer to block to fill in
+ *
+ * Returns: ---
+ *
+ * Use: Fills in the user ids and things in the structure. This is
+ * equivalent to setting @cp_gids = 0@ and then calling
+ * @_setuid@, @_setgid@ and @_setgroups@. It can't fail.
+ */
+
+void checkpath_setids(struct checkpath *cp)
+{
+ cp->cp_gids = 0;
+ checkpath_setuid(cp);
+ checkpath_setgid(cp);
+ checkpath_setgroups(cp);
}
/*----- That's all, folks -------------------------------------------------*/
extern unsigned checkpath(const char */*p*/, const struct checkpath */*cp*/);
+/* --- @checkpath_addgid@ --- *
+ *
+ * Arguments: @struct checkpath *cp@ = pointer to block to fill in
+ * @gid_t g@ = group id to add
+ *
+ * Returns: Zero if successful, nonzero if the array is full.
+ *
+ * Use: Adds the group @g@ to the structure.
+ */
+
+extern int checkpath_addgid(struct checkpath */*cp*/, gid_t /*g*/);
+
+/* --- @checkpath_setuid@ --- *
+ *
+ * Arguments: @struct checkpath *cp@ = pointer to block to fill in
+ *
+ * Returns: ---
+ *
+ * Use: Fills in the @cp_uid@ slot of the structure with the real uid
+ * of the current process.
+ */
+
+extern void checkpath_setuid(struct checkpath */*cp*/);
+
+/* --- @checkpath_setgid@ --- *
+ *
+ * Arguments: @struct checkpath *cp@ = pointer to block to fill in
+ *
+ * Returns: Zero if successful, nonzero if the array is full.
+ *
+ * Use: Adds the real gid of the current process to the @cp_gid@
+ * array.
+ */
+
+extern int checkpath_setgid(/*cp*/);
+
+/* --- @checkpath_setgroups@ --- *
+ *
+ * Arguments: @struct checkpath *cp@ = pointer to block to fill in
+ *
+ * Returns: Zero if successful, nonzero if the array is full.
+ *
+ * Use: Adds the current process's supplementary groups to the
+ * @cp_gid@ table.
+ */
+
+extern int checkpath_setgroups(struct checkpath */*cp*/);
+
/* --- @checkpath_setids@ --- *
*
* Arguments: @struct checkpath *cp@ = pointer to block to fill in
*
* Returns: ---
*
- * Use: Fills in the user ids and things in the structure.
+ * Use: Fills in the user ids and things in the structure. This is
+ * equivalent to setting @cp_gids = 0@ and then calling
+ * @_setuid@, @_setgid@ and @_setgroups@. It can't fail.
*/
extern void checkpath_setids(struct checkpath */*cp*/);