X-Git-Url: https://git.distorted.org.uk/~mdw/checkpath/blobdiff_plain/7868d789c2b2f6a074b7fc14cd4dc482957c90b5..9c42854ddcd101d7c18dbe762afeed91fca5c477:/checkpath.c diff --git a/checkpath.c b/checkpath.c index 28ca474..a396d14 100644 --- a/checkpath.c +++ b/checkpath.c @@ -1,13 +1,13 @@ /* -*-c-*- * - * $Id: checkpath.c,v 1.4 2001/01/25 22:16:02 mdw Exp $ + * $Id: checkpath.c,v 1.6 2004/04/08 01:36:22 mdw Exp $ * * Check a path for safety * * (c) 1999 Mark Wooding */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of chkpath. * @@ -15,36 +15,21 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * chkpath is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with chkpath; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: checkpath.c,v $ - * Revision 1.4 2001/01/25 22:16:02 mdw - * Make flags be unsigned. - * - * Revision 1.3 1999/05/21 22:07:20 mdw - * Take advantage of new dynamic string macros. - * - * 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 "config.h" + #include #include #include @@ -61,7 +46,7 @@ #include #include -#include "path.h" +#include "checkpath.h" /*----- Data structures ---------------------------------------------------*/ @@ -194,8 +179,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 @@ -205,7 +190,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 --- */ @@ -283,7 +268,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. @@ -291,16 +276,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 **"); } @@ -308,19 +297,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); } } @@ -338,10 +329,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. * @@ -349,12 +340,12 @@ 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; /* --- Initialize stack pointer and path string --- */ @@ -494,23 +485,23 @@ 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(); cp->cp_uid = getuid(); n = getgroups(sizeof(cp->cp_gid) / sizeof(cp->cp_gid[0]), cp->cp_gid); - + for (i = 0; i < n; i++) { if (cp->cp_gid[i] == g) goto gid_ok;