chiark / gitweb /
Make flags be unsigned.
[checkpath] / chkpath.c
1 /* -*-c-*-
2  *
3  * $Id: chkpath.c,v 1.2 2001/01/25 22:16:02 mdw Exp $
4  *
5  * Check a user's file search path
6  *
7  * (c) 1999 Mark Wooding
8  */
9
10 /*----- Licensing notice --------------------------------------------------* 
11  *
12  * This file is part of chkpath.
13  *
14  * chkpath is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  * 
19  * chkpath is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with chkpath; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  */
28
29 /*----- Revision history --------------------------------------------------* 
30  *
31  * $Log: chkpath.c,v $
32  * Revision 1.2  2001/01/25 22:16:02  mdw
33  * Make flags be unsigned.
34  *
35  * Revision 1.1.1.1  1999/04/06 20:12:07  mdw
36  * Import new project.
37  *
38  */
39
40 /*----- Header files ------------------------------------------------------*/
41
42 #include <errno.h>
43 #include <limits.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #include <mLib/alloc.h>
49 #include <mLib/mdwopt.h>
50 #include <mLib/quis.h>
51 #include <mLib/report.h>
52
53 #include "path.h"
54
55 /*----- Main code ---------------------------------------------------------*/
56
57 static void report(int what, int verbose,
58                    const char *p, const char *msg,
59                    void *arg)
60 {
61   moan("%s", msg);
62 }
63
64 /* --- @usage@ --- */
65
66 static void usage(FILE *fp)
67 {
68   fprintf(fp, "Usage: %s [-vqstp] [PATH...]\n", QUIS);
69 }
70
71 /* --- @version@ --- */
72
73 static void version(FILE *fp)
74 {
75   fprintf(fp, "%s version %s\n", QUIS, VERSION);
76 }
77
78 /* --- @help@ --- */
79
80 static void help(FILE *fp)
81 {
82   version(fp);
83   putc('\n', fp);
84   usage(fp);
85   fputs("\n\
86 Checks a path string (by default the PATH variable) for security.  It\n\
87 ensures that only `root' or the calling user can write to all the parent\n\
88 directories of the path elements, so nobody can maliciously replace the\n\
89 binaries unexpectedly.\n\
90 \n\
91 Options provided are:\n\
92 \n\
93 -h, --help              Display this help message.\n\
94 -V, --version           Display the program's version number.\n\
95 -u, --usage             Show a terse usage summary.\n\
96 \n\
97 -v, --verbose           Be verbose about the search progress (cumulative).\n\
98 -q, --quiet             Be quiet about the search progress (cumulative).\n\
99 -s, --sticky            Consider sticky directories secure against\n\
100                         modification by world and group (not recommended).\n\
101 -t, --trust-group       Consider other members of your group trustworthy.\n\
102 -p, --print             Write the secure path elements to standard output.\n\
103 ",
104         fp);
105 }
106
107 int main(int argc, char *argv[])
108 {
109   int bad = 0;
110   int i;
111   char *p, *q, *path;
112   struct chkpath cp;
113   int f = 0;
114
115 #define f_print 1u
116 #define f_colon 2u
117
118   /* --- Initialize the world --- */
119
120   ego(argv[0]);
121
122   /* --- Set up path scanning defaults --- */
123
124   cp.cp_verbose = 1;
125   cp.cp_what = (CP_WRWORLD | CP_WRGRP | CP_WROTHUSR |
126                 CP_ERROR | CP_REPORT | CP_SYMLINK);
127   cp.cp_report = report;
128   cp.cp_arg = 0;
129   path_setids(&cp);
130
131   /* --- Parse the options --- */
132
133   for (;;) {
134     static struct option opts[] = {
135       { "help",         0,              0,      'h' },
136       { "version",      0,              0,      'V' },
137       { "usage",        0,              0,      'u' },
138       { "verbose",      0,              0,      'v' },
139       { "quiet",        0,              0,      'q' },
140       { "sticky",       0,              0,      's' },
141       { "trust-group",  0,              0,      't' },
142       { "print",        0,              0,      'p' },
143       { 0,              0,              0,      0 }
144     };
145     int i = mdwopt(argc, argv, "hVu vqstp", opts, 0, 0, 0);
146
147     if (i < 0)
148       break;
149     switch (i) {
150       case 'h':
151         help(stdout);
152         exit(0);
153       case 'V':
154         version(stdout);
155         exit(0);
156       case 'u':
157         usage(stdout);
158         exit(0);
159       case 'v':
160         cp.cp_verbose++;
161         break;
162       case 'q':
163         if (cp.cp_verbose)
164           cp.cp_verbose--;
165         break;
166       case 's':
167         cp.cp_what |= CP_STICKYOK;
168         break;
169       case 't':
170         cp.cp_what = (cp.cp_what & ~CP_WRGRP) | CP_WROTHGRP;
171         break;
172       case 'p':
173         f |= f_print;
174         break;
175       default:
176         bad = 1;
177         break;
178     }
179   }
180
181   if (bad) {
182     usage(stderr);
183     exit(1);
184   }
185
186   /* --- Sort out what needs doing --- */
187
188   if (optind == argc) {
189     path = getenv("PATH");
190     argv = &path;
191     argc = 1;
192     optind = 0;
193   }
194
195   for (i = optind; i < argc; i++) {
196     p = xstrdup(argv[i]);
197     q = strtok(p, ":");
198     while (q) {
199       int b = path_check(q, &cp);
200       if (!b && (f & f_print)) {
201         if (f & f_colon)
202           putchar(':');
203         fputs(q, stdout);
204         f |= f_colon;
205       }
206       bad |= b;
207       q = strtok(0, ":");
208     }
209     free(p);
210   }
211
212   if (f & f_colon)
213     putchar('\n');
214
215   return (bad);
216 }
217
218 /*----- That's all, folks -------------------------------------------------*/