chiark / gitweb /
Script to transform CVS sources into buildable source tree.
[checkpath] / chkpath.c
1 /* -*-c-*-
2  *
3  * $Id: chkpath.c,v 1.1 1999/04/06 20:12:07 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.1  1999/04/06 20:12:07  mdw
33  * Initial revision
34  *
35  */
36
37 /*----- Header files ------------------------------------------------------*/
38
39 #include <errno.h>
40 #include <limits.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include <mLib/alloc.h>
46 #include <mLib/mdwopt.h>
47 #include <mLib/quis.h>
48 #include <mLib/report.h>
49
50 #include "path.h"
51
52 /*----- Main code ---------------------------------------------------------*/
53
54 static void report(int what, int verbose,
55                    const char *p, const char *msg,
56                    void *arg)
57 {
58   moan("%s", msg);
59 }
60
61 /* --- @usage@ --- */
62
63 static void usage(FILE *fp)
64 {
65   fprintf(fp, "Usage: %s [-vqstp] [PATH...]\n", QUIS);
66 }
67
68 /* --- @version@ --- */
69
70 static void version(FILE *fp)
71 {
72   fprintf(fp, "%s version %s\n", QUIS, VERSION);
73 }
74
75 /* --- @help@ --- */
76
77 static void help(FILE *fp)
78 {
79   version(fp);
80   putc('\n', fp);
81   usage(fp);
82   fputs("\n\
83 Checks a path string (by default the PATH variable) for security.  It\n\
84 ensures that only `root' or the calling user can write to all the parent\n\
85 directories of the path elements, so nobody can maliciously replace the\n\
86 binaries unexpectedly.\n\
87 \n\
88 Options provided are:\n\
89 \n\
90 -h, --help              Display this help message.\n\
91 -V, --version           Display the program's version number.\n\
92 -u, --usage             Show a terse usage summary.\n\
93 \n\
94 -v, --verbose           Be verbose about the search progress (cumulative).\n\
95 -q, --quiet             Be quiet about the search progress (cumulative).\n\
96 -s, --sticky            Consider sticky directories secure against\n\
97                         modification by world and group (not recommended).\n\
98 -t, --trust-group       Consider other members of your group trustworthy.\n\
99 -p, --print             Write the secure path elements to standard output.\n\
100 ",
101         fp);
102 }
103
104 int main(int argc, char *argv[])
105 {
106   int bad = 0;
107   int i;
108   char *p, *q, *path;
109   struct chkpath cp;
110   int f = 0;
111
112   enum {
113     f_print = 1,
114     f_colon = 2
115   };
116
117   /* --- Initialize the world --- */
118
119   ego(argv[0]);
120
121   /* --- Set up path scanning defaults --- */
122
123   cp.cp_verbose = 1;
124   cp.cp_what = (CP_WRWORLD | CP_WRGRP | CP_WROTHUSR |
125                 CP_ERROR | CP_REPORT | CP_SYMLINK);
126   cp.cp_report = report;
127   cp.cp_arg = 0;
128   path_setids(&cp);
129
130   /* --- Parse the options --- */
131
132   for (;;) {
133     static struct option opts[] = {
134       { "help",         0,              0,      'h' },
135       { "version",      0,              0,      'V' },
136       { "usage",        0,              0,      'u' },
137       { "verbose",      0,              0,      'v' },
138       { "quiet",        0,              0,      'q' },
139       { "sticky",       0,              0,      's' },
140       { "trust-group",  0,              0,      't' },
141       { "print",        0,              0,      'p' },
142       { 0,              0,              0,      0 }
143     };
144     int i = mdwopt(argc, argv, "hVu vqstp", opts, 0, 0, 0);
145
146     if (i < 0)
147       break;
148     switch (i) {
149       case 'h':
150         help(stdout);
151         exit(0);
152       case 'V':
153         version(stdout);
154         exit(0);
155       case 'u':
156         usage(stdout);
157         exit(0);
158       case 'v':
159         cp.cp_verbose++;
160         break;
161       case 'q':
162         if (cp.cp_verbose)
163           cp.cp_verbose--;
164         break;
165       case 's':
166         cp.cp_what |= CP_STICKYOK;
167         break;
168       case 't':
169         cp.cp_what = (cp.cp_what & ~CP_WRGRP) | CP_WROTHGRP;
170         break;
171       case 'p':
172         f |= f_print;
173         break;
174       default:
175         bad = 1;
176         break;
177     }
178   }
179
180   if (bad) {
181     usage(stderr);
182     exit(1);
183   }
184
185   /* --- Sort out what needs doing --- */
186
187   if (optind == argc) {
188     path = getenv("PATH");
189     argv = &path;
190     argc = 1;
191     optind = 0;
192   }
193
194   for (i = optind; i < argc; i++) {
195     p = xstrdup(argv[i]);
196     q = strtok(p, ":");
197     while (q) {
198       int b = path_check(q, &cp);
199       if (!b && (f & f_print)) {
200         if (f & f_colon)
201           putchar(':');
202         fputs(q, stdout);
203         f |= f_colon;
204       }
205       bad |= b;
206       q = strtok(0, ":");
207     }
208     free(p);
209   }
210
211   if (f & f_colon)
212     putchar('\n');
213
214   return (bad);
215 }
216
217 /*----- That's all, folks -------------------------------------------------*/