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 28const char _uuconf_rdperm_rcsid[] = "$Id: rdperm.c,v 1.12 2002/03/05 19:10:42 ian Rel $"; 29#endif 30 31#include <errno.h> 32#include <ctype.h> 33 34static int ihcolon P((pointer pglobal, int argc, char **argv, pointer pvar, 35 pointer pinfo)); 36static int ihsendfiles P((pointer pglobal, int argc, char **argv, 37 pointer pvar, pointer pinfo)); 38static int ihunknownperm P((pointer pglobal, int argc, char **argv, 39 pointer pvar, pointer pinfo)); 40static 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 62static 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 98int 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*/ 307static int 308ihcolon (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*/ 366static int 367ihsendfiles (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*/ 399static int 400ihunknownperm (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 412static int 413ihadd_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