X-Git-Url: https://git.distorted.org.uk/~mdw/checkpath/blobdiff_plain/558a9b222e80151fb6d97ce1c7109fc4bd877780..463b66afc93c5a712f9f9ab71efc53e0e05c5a9c:/checkpath.c diff --git a/checkpath.c b/checkpath.c index f470d49..b6ee94e 100644 --- a/checkpath.c +++ b/checkpath.c @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: checkpath.c,v 1.2 1999/05/18 20:49:12 mdw Exp $ + * $Id: checkpath.c,v 1.6 2004/04/08 01:36:22 mdw Exp $ * * Check a path for safety * @@ -26,17 +26,6 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: checkpath.c,v $ - * Revision 1.2 1999/05/18 20:49:12 mdw - * Use a dynamic string for reading symlinks. - * - * Revision 1.1.1.1 1999/04/06 20:12:07 mdw - * Import new project. - * - */ - /*----- Header files ------------------------------------------------------*/ #include @@ -55,7 +44,7 @@ #include #include -#include "path.h" +#include "checkpath.h" /*----- Data structures ---------------------------------------------------*/ @@ -72,19 +61,15 @@ struct elt { char e_name[1]; /* Name of the directory */ }; -enum { - f_sticky = 1 /* Directory has sticky bit set */ -}; +#define f_sticky 1u /* Directory has sticky bit set */ -enum { - f_last = 1 /* This is the final item to check */ -}; +#define f_last 1u /* This is the final item to check */ /*----- Static variables --------------------------------------------------*/ static struct elt rootnode = { 0, 0, 0 }; /* Root of the list */ static struct elt *sp; /* Stack pointer for list */ -static dstr d; /* Current path string */ +static dstr d = DSTR_INIT; /* Current path string */ /*----- Main code ---------------------------------------------------------*/ @@ -192,8 +177,8 @@ static void push(struct elt *e) /* --- @report@ --- * * - * Arguments: @struct chkpath *cp@ = pointer to context - * @int what@ = what sort of report is this? + * Arguments: @const struct checkpath *cp@ = pointer to context + * @unsigned what@ = what sort of report is this? * @int verbose@ = how verbose is this? * @const char *p@ = what path does it refer to? * @const char *msg@ = the message to give to the user @@ -203,7 +188,7 @@ static void push(struct elt *e) * Use: Formats and presents messages to the client. */ -static void report(struct chkpath *cp, int what, int verbose, +static void report(const struct checkpath *cp, unsigned what, int verbose, const char *p, const char *msg, ...) { /* --- Decide whether to bin this message --- */ @@ -214,13 +199,12 @@ static void report(struct chkpath *cp, int what, int verbose, /* --- Format the message nicely --- */ if (cp->cp_what & CP_REPORT) { - dstr d; + dstr d = DSTR_INIT; va_list ap; const char *q = msg; size_t n; int e = errno; - dstr_create(&d); va_start(ap, msg); if (verbose > 1) dstr_puts(&d, "[ "); @@ -282,7 +266,7 @@ static void report(struct chkpath *cp, int what, int verbose, * * Arguments: @const char *p@ = name of directory to check * @struct stat *st@ = pointer to @stat@(2) block for it - * @struct chkpath *cp@ = pointer to caller parameters + * @const struct checkpath *cp@ = pointer to caller parameters * @unsigned f@ = various flags * * Returns: Zero if everything's OK, else bitmask of problems. @@ -290,16 +274,20 @@ static void report(struct chkpath *cp, int what, int verbose, * Use: Performs the main load of sanity-checking on a directory. */ -static int sanity(const char *p, struct stat *st, - struct chkpath *cp, unsigned f) +static unsigned sanity(const char *p, struct stat *st, + const struct checkpath *cp, unsigned f) { - int bad = 0; - int sticky = (cp->cp_what & CP_STICKYOK) || !(f & f_last) ? 01000 : 0; + unsigned bad = 0; + int stickyok = 0; + + if (S_ISDIR(st->st_mode) && + (!(f & f_last) || (cp->cp_what & CP_STICKYOK))) + stickyok = 01000; /* --- Check for world-writability --- */ if ((cp->cp_what & CP_WRWORLD) && - (st->st_mode & (0002 | sticky)) == 0002) { + (st->st_mode & (0002 | stickyok)) == 0002) { bad |= CP_WRWORLD; report(cp, CP_WRWORLD, 1, p, "** world writable **"); } @@ -307,19 +295,21 @@ static int sanity(const char *p, struct stat *st, /* --- Check for group-writability --- */ if ((cp->cp_what & (CP_WRGRP | CP_WROTHGRP)) && - (st->st_mode & (0020 | sticky)) == 0020) { - if (cp->cp_what & CP_WRGRP) { - bad |= CP_WRGRP; - report(cp, CP_WRGRP, 1, p, "writable by group %g", st->st_gid); - } else { - int i; + (st->st_mode & (0020 | stickyok)) == 0020) { + int i; + unsigned b = CP_WRGRP; + + if (cp->cp_what & CP_WROTHGRP) { + b = CP_WROTHGRP; for (i = 0; i < cp->cp_gids; i++) { if (st->st_gid == cp->cp_gid[i]) - goto good_gid; + b = cp->cp_what & CP_WRGRP; } - bad |= CP_WROTHGRP; - report(cp, CP_WROTHGRP, 1, p, "writable by group %g", st->st_gid); - good_gid:; + } + if (b) { + bad |= b; + report(cp, b, 1, p, "writable by %sgroup %g", + (b == CP_WROTHGRP) ? "other " : "", st->st_gid); } } @@ -337,10 +327,10 @@ static int sanity(const char *p, struct stat *st, return (bad); } -/* --- @path_check@ --- * +/* --- @checkpath@ --- * * * Arguments: @const char *p@ = directory name which needs checking - * @struct chkpath *cp@ = caller parameters for the check + * @const struct checkpath *cp@ = parameters for the check * * Returns: Zero if all is well, otherwise bitmask of problems. * @@ -348,14 +338,14 @@ static int sanity(const char *p, struct stat *st, * users could do to it. */ -int path_check(const char *p, struct chkpath *cp) +unsigned checkpath(const char *p, const struct checkpath *cp) { char cwd[PATH_MAX]; struct elt *e, *ee; struct stat st; - int bad = 0; + unsigned bad = 0; - /* --- Initialise stack pointer and path string --- */ + /* --- Initialize stack pointer and path string --- */ sp = &rootnode; dstr_destroy(&d); @@ -421,12 +411,11 @@ int path_check(const char *p, struct chkpath *cp) /* --- Handle symbolic links specially --- */ if (S_ISLNK(st.st_mode)) { - dstr buf; + dstr buf = DSTR_INIT; int i; /* --- Resolve the link --- */ - dstr_create(&buf); dstr_ensure(&buf, st.st_size + 1); if ((i = readlink(d.buf, buf.buf, buf.sz)) < 0) { report(cp, CP_ERROR, 0, d.buf, "can't readlink: %e"); @@ -494,16 +483,16 @@ int path_check(const char *p, struct chkpath *cp) return (bad); } -/* --- @path_setids@ --- * +/* --- @checkpath_setids@ --- * * - * Arguments: @struct chkpath *cp@ = pointer to block to fill in + * Arguments: @struct checkpath *cp@ = pointer to block to fill in * - * Returns: Zero if OK, else @-1@. + * Returns: --- * * Use: Fills in the user ids and things in the structure. */ -void path_setids(struct chkpath *cp) +void checkpath_setids(struct checkpath *cp) { int n, i; gid_t g = getgid();