1 /* rdperm.c
2 Read the HDB Permissions file.
3
4 Copyright (C) 1992, 1993, 2002 Ian Lance Taylor
5
6 This file is part of the Taylor UUCP uuconf library.
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public License
10 as published by the Free Software Foundation; either version 2 of
11 the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21
22 The author of the program may be contacted at ian@airs.com.
23 */
24
25 #include "uucnfi.h"
26
27 #if USE_RCS_ID
28 const char _uuconf_rdperm_rcsid[] = "$FreeBSD$";
29 #endif
30
31 #include <errno.h>
32 #include <ctype.h>
33
34 static int ihcolon P((pointer pglobal, int argc, char **argv, pointer pvar,
35 pointer pinfo));
36 static int ihsendfiles P((pointer pglobal, int argc, char **argv,
37 pointer pvar, pointer pinfo));
38 static int ihunknownperm P((pointer pglobal, int argc, char **argv,
39 pointer pvar, pointer pinfo));
40 static int ihadd_norw P((struct sglobal *qglobal, char ***ppz, char **pzno));
41
42 /* These routines reads in the HDB Permissions file. We store the
43 entries in a linked list of shpermissions structures, so we only
44 have to actually read the file once. */
45
46 /* This command table and static structure are used to parse a line
47 from Permissions. The entries are parsed as follows:
48
49 Multiple strings separated by colons: LOGNAME, MACHINE, READ,
50 WRITE, NOREAD, NOWRITE, COMMANDS, VALIDATE, ALIAS.
51
52 Boolean values: REQUEST, CALLBACK.
53
54 Simple strings: MYNAME, PUBDIR.
55
56 "Yes" or "call": SENDFILES.
57
58 The NOREAD and NOWRITE entries are merged into the READ and WRITE
59 entries, rather than being permanently stored. They are handled
60 specially in the uuconf_cmdtab table. */
61
62 static const struct cmdtab_offset asHperm_cmds[] =
63 {
64 { "NOREAD", UUCONF_CMDTABTYPE_FN | 2, (size_t) -1, ihcolon },
65 { "NOWRITE", UUCONF_CMDTABTYPE_FN | 2, (size_t) -1, ihcolon },
66 { "LOGNAME", UUCONF_CMDTABTYPE_FN | 2,
67 offsetof (struct shpermissions, pzlogname), ihcolon },
68 { "MACHINE", UUCONF_CMDTABTYPE_FN | 2,
69 offsetof (struct shpermissions, pzmachine), ihcolon },
70 { "REQUEST", UUCONF_CMDTABTYPE_BOOLEAN,
71 offsetof (struct shpermissions, frequest), NULL },
72 { "SENDFILES", UUCONF_CMDTABTYPE_FN | 2,
73 offsetof (struct shpermissions, fsendfiles), ihsendfiles },
74 { "READ", UUCONF_CMDTABTYPE_FN | 2,
75 offsetof (struct shpermissions, pzread), ihcolon },
76 { "WRITE", UUCONF_CMDTABTYPE_FN | 2,
77 offsetof (struct shpermissions, pzwrite), ihcolon },
78 { "CALLBACK", UUCONF_CMDTABTYPE_BOOLEAN,
79 offsetof (struct shpermissions, fcallback), NULL },
80 { "COMMANDS", UUCONF_CMDTABTYPE_FN | 2,
81 offsetof (struct shpermissions, pzcommands), ihcolon },
82 { "VALIDATE", UUCONF_CMDTABTYPE_FN | 2,
83 offsetof (struct shpermissions, pzvalidate), ihcolon },
84 { "MYNAME", UUCONF_CMDTABTYPE_STRING,
85 offsetof (struct shpermissions, zmyname), NULL },
86 { "PUBDIR", UUCONF_CMDTABTYPE_STRING,
87 offsetof (struct shpermissions, zpubdir), NULL },
88 { "ALIAS", UUCONF_CMDTABTYPE_FN | 2,
89 offsetof (struct shpermissions, pzalias), ihcolon },
90 { NULL, 0, 0, NULL }
91 };
92
93 #define CHPERM_CMDS (sizeof asHperm_cmds / sizeof asHperm_cmds[0])
94
95 /* Actually read the Permissions file into a linked list of
96 structures. */
97
98 int
_uuconf_ihread_permissions(qglobal)99 _uuconf_ihread_permissions (qglobal)
100 struct sglobal *qglobal;
101 {
102 char *zperm;
103 FILE *e;
104 int iret;
105 struct uuconf_cmdtab as[CHPERM_CMDS];
106 char **pznoread, **pznowrite;
107 struct shpermissions shperm;
108 char *zline;
109 size_t cline;
110 char **pzsplit;
111 size_t csplit;
112 int cchars;
113 struct shpermissions *qlist, **pq;
114
115 if (qglobal->qprocess->fhdb_read_permissions)
116 return UUCONF_SUCCESS;
117
118 zperm = (char *) uuconf_malloc (qglobal->pblock,
119 (sizeof OLDCONFIGLIB
120 + sizeof HDB_PERMISSIONS - 1));
121 if (zperm == NULL)
122 {
123 qglobal->ierrno = errno;
124 return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
125 }
126
127 memcpy ((pointer) zperm, (pointer) OLDCONFIGLIB,
128 sizeof OLDCONFIGLIB - 1);
129 memcpy ((pointer) (zperm + sizeof OLDCONFIGLIB - 1),
130 (pointer) HDB_PERMISSIONS, sizeof HDB_PERMISSIONS);
131
132 e = fopen (zperm, "r");
133 if (e == NULL)
134 {
135 uuconf_free (qglobal->pblock, zperm);
136 qglobal->qprocess->fhdb_read_permissions = TRUE;
137 return UUCONF_SUCCESS;
138 }
139
140 _uuconf_ucmdtab_base (asHperm_cmds, CHPERM_CMDS, (char *) &shperm, as);
141 as[0].uuconf_pvar = (pointer) &pznoread;
142 as[1].uuconf_pvar = (pointer) &pznowrite;
143
144 zline = NULL;
145 cline = 0;
146 pzsplit = NULL;
147 csplit = 0;
148
149 qlist = NULL;
150 pq = &qlist;
151
152 qglobal->ilineno = 0;
153
154 iret = UUCONF_SUCCESS;
155
156 while ((cchars = _uuconf_getline (qglobal, &zline, &cline, e)) > 0)
157 {
158 int centries;
159 struct shpermissions *qnew;
160 int i;
161
162 ++qglobal->ilineno;
163
164 --cchars;
165 if (zline[cchars] == '\n')
166 zline[cchars] = '\0';
167 if (zline[0] == '#')
168 continue;
169
170 centries = _uuconf_istrsplit (zline, '\0', &pzsplit, &csplit);
171 if (centries < 0)
172 {
173 qglobal->ierrno = errno;
174 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
175 break;
176 }
177
178 if (centries == 0)
179 continue;
180
181 shperm.pzlogname = (char **) &_uuconf_unset;
182 shperm.pzmachine = (char **) &_uuconf_unset;
183 shperm.frequest = -1;
184 shperm.fsendfiles = -1;
185 shperm.pzread = (char **) &_uuconf_unset;
186 shperm.pzwrite = (char **) &_uuconf_unset;
187 shperm.fcallback = -1;
188 shperm.pzcommands = (char **) &_uuconf_unset;
189 shperm.pzvalidate = (char **) &_uuconf_unset;
190 shperm.zmyname = (char *) &_uuconf_unset;
191 shperm.zpubdir = (char *) &_uuconf_unset;
192 shperm.pzalias = (char **) &_uuconf_unset;
193 pznoread = (char **) &_uuconf_unset;
194 pznowrite = (char **) &_uuconf_unset;
195
196 for (i = 0; i < centries; i++)
197 {
198 char *zeq;
199 char *azargs[2];
200
201 zeq = strchr (pzsplit[i], '=');
202 if (zeq == NULL)
203 {
204 iret = UUCONF_SYNTAX_ERROR;
205 qglobal->qprocess->fhdb_read_permissions = TRUE;
206 break;
207 }
208 *zeq = '\0';
209
210 azargs[0] = pzsplit[i];
211 azargs[1] = zeq + 1;
212
213 iret = uuconf_cmd_args (qglobal, 2, azargs, as, (pointer) NULL,
214 ihunknownperm, 0, qglobal->pblock);
215 if ((iret & UUCONF_CMDTABRET_KEEP) != 0)
216 {
217 iret &=~ UUCONF_CMDTABRET_KEEP;
218
219 if (uuconf_add_block (qglobal->pblock, zline) != 0)
220 {
221 qglobal->ierrno = errno;
222 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
223 break;
224 }
225
226 zline = NULL;
227 cline = 0;
228 }
229 if ((iret & UUCONF_CMDTABRET_EXIT) != 0)
230 {
231 iret &=~ UUCONF_CMDTABRET_EXIT;
232 break;
233 }
234 }
235
236 if (iret != UUCONF_SUCCESS)
237 break;
238
239 if (shperm.pzmachine == (char **) &_uuconf_unset
240 && shperm.pzlogname == (char **) &_uuconf_unset)
241 {
242 iret = UUCONF_SYNTAX_ERROR;
243 qglobal->qprocess->fhdb_read_permissions = TRUE;
244 break;
245 }
246
247 /* Attach any NOREAD or NOWRITE entries to the corresponding
248 READ or WRITE entries in the format expected for the
249 pzlocal_receive, etc., fields in uuconf_system. */
250 if (pznoread != NULL)
251 {
252 iret = ihadd_norw (qglobal, &shperm.pzread, pznoread);
253 if (iret != UUCONF_SUCCESS)
254 break;
255 uuconf_free (qglobal->pblock, pznoread);
256 }
257
258 if (pznowrite != NULL)
259 {
260 iret = ihadd_norw (qglobal, &shperm.pzwrite, pznowrite);
261 if (iret != UUCONF_SUCCESS)
262 break;
263 uuconf_free (qglobal->pblock, pznowrite);
264 }
265
266 qnew = ((struct shpermissions *)
267 uuconf_malloc (qglobal->pblock,
268 sizeof (struct shpermissions)));
269 if (qnew == NULL)
270 {
271 qglobal->ierrno = errno;
272 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
273 break;
274 }
275
276 *qnew = shperm;
277 *pq = qnew;
278 pq = &qnew->qnext;
279 *pq = NULL;
280 }
281
282 (void) fclose (e);
283
284 if (zline != NULL)
285 free ((pointer) zline);
286 if (pzsplit != NULL)
287 free ((pointer) pzsplit);
288
289 if (iret == UUCONF_SUCCESS)
290 {
291 qglobal->qprocess->qhdb_permissions = qlist;
292 qglobal->qprocess->fhdb_read_permissions = TRUE;
293 }
294 else
295 {
296 qglobal->zfilename = zperm;
297 iret |= UUCONF_ERROR_FILENAME | UUCONF_ERROR_LINENO;
298 }
299
300 return iret;
301 }
302
303 /* Split the argument into colon separated strings, and assign a NULL
304 terminated array of strings to pvar. */
305
306 /*ARGSUSED*/
307 static int
ihcolon(pglobal,argc,argv,pvar,pinfo)308 ihcolon (pglobal, argc, argv, pvar, pinfo)
309 pointer pglobal;
310 int argc ATTRIBUTE_UNUSED;
311 char **argv;
312 pointer pvar;
313 pointer pinfo ATTRIBUTE_UNUSED;
314 {
315 struct sglobal *qglobal = (struct sglobal *) pglobal;
316 char ***ppz = (char ***) pvar;
317 char **pzsplit;
318 size_t csplit;
319 int centries;
320 int i;
321 int iret;
322
323 *ppz = NULL;
324
325 pzsplit = NULL;
326 csplit = 0;
327
328 centries = _uuconf_istrsplit (argv[1], ':', &pzsplit, &csplit);
329 if (centries < 0)
330 {
331 qglobal->ierrno = errno;
332 return (UUCONF_MALLOC_FAILED
333 | UUCONF_ERROR_ERRNO
334 | UUCONF_CMDTABRET_EXIT);
335 }
336
337 if (centries == 0)
338 {
339 if (pzsplit != NULL)
340 free ((pointer) pzsplit);
341 return UUCONF_CMDTABRET_CONTINUE;
342 }
343
344 iret = UUCONF_SUCCESS;
345
346 for (i = 0; i < centries; i++)
347 {
348 iret = _uuconf_iadd_string (qglobal, pzsplit[i], FALSE, FALSE,
349 ppz, qglobal->pblock);
350 if (iret != UUCONF_SUCCESS)
351 {
352 iret |= UUCONF_CMDTABRET_EXIT;
353 break;
354 }
355 }
356
357 free ((pointer) pzsplit);
358
359 return UUCONF_CMDTABRET_KEEP;
360 }
361
362 /* Handle the SENDFILES parameter, which can take "yes" or "call" or
363 "no" as an argument. The string "call" is equivalent to "no". */
364
365 /*ARGSUSED*/
366 static int
ihsendfiles(pglobal,argc,argv,pvar,pinfo)367 ihsendfiles (pglobal, argc, argv, pvar, pinfo)
368 pointer pglobal ATTRIBUTE_UNUSED;
369 int argc ATTRIBUTE_UNUSED;
370 char **argv;
371 pointer pvar;
372 pointer pinfo ATTRIBUTE_UNUSED;
373 {
374 int *pi = (int *) pvar;
375
376 switch (argv[1][0])
377 {
378 case 'C':
379 case 'c':
380 case 'N':
381 case 'n':
382 *pi = FALSE;
383 break;
384 case 'Y':
385 case 'y':
386 *pi = TRUE;
387 break;
388 default:
389 return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT;
390 }
391
392 return UUCONF_CMDTABRET_CONTINUE;
393 }
394
395 /* If there is an unknown Permissions entry, return a syntax error.
396 This should probably be more clever. */
397
398 /*ARGSUSED*/
399 static int
ihunknownperm(pglobal,argc,argv,pvar,pinfo)400 ihunknownperm (pglobal, argc, argv, pvar, pinfo)
401 pointer pglobal ATTRIBUTE_UNUSED;
402 int argc ATTRIBUTE_UNUSED;
403 char **argv ATTRIBUTE_UNUSED;
404 pointer pvar ATTRIBUTE_UNUSED;
405 pointer pinfo ATTRIBUTE_UNUSED;
406 {
407 return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT;
408 }
409
410 /* Add a NOREAD or NOWRITE entry to a READ or WRITE entry. */
411
412 static int
ihadd_norw(qglobal,ppz,pzno)413 ihadd_norw (qglobal, ppz, pzno)
414 struct sglobal *qglobal;
415 char ***ppz;
416 char **pzno;
417 {
418 register char **pz;
419
420 if (pzno == (char **) &_uuconf_unset)
421 return UUCONF_SUCCESS;
422
423 for (pz = pzno; *pz != NULL; pz++)
424 {
425 size_t csize;
426 char *znew;
427 int iret;
428
429 /* Ignore an attempt to say NOREAD or NOWRITE with an empty
430 string, since it will be interpreted as an attempt to deny
431 everything. */
432 if (**pz != '\0')
433 {
434 csize = strlen (*pz) + 1;
435 znew = (char *) uuconf_malloc (qglobal->pblock, csize + 1);
436 if (znew == NULL)
437 {
438 qglobal->ierrno = errno;
439 return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
440 }
441 znew[0] = '!';
442 memcpy ((pointer) (znew + 1), (pointer) *pz, csize);
443 iret = _uuconf_iadd_string (qglobal, znew, FALSE, FALSE, ppz,
444 qglobal->pblock);
445 if (iret != UUCONF_SUCCESS)
446 return iret;
447 }
448 }
449
450 return UUCONF_SUCCESS;
451 }
452