systems.c revision 50479
1158979Snetchild/* 2158979Snetchild * System configuration routines 3158979Snetchild * 4158979Snetchild * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5158979Snetchild * 6158979Snetchild * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7158979Snetchild * 8158979Snetchild * Redistribution and use in source and binary forms are permitted 9158979Snetchild * provided that the above copyright notice and this paragraph are 10158979Snetchild * duplicated in all such forms and that any documentation, 11158979Snetchild * advertising materials, and other materials related to such 12158979Snetchild * distribution and use acknowledge that the software was developed 13158979Snetchild * by the Internet Initiative Japan, Inc. The name of the 14158979Snetchild * IIJ may not be used to endorse or promote products derived 15158979Snetchild * from this software without specific prior written permission. 16158979Snetchild * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17158979Snetchild * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18158979Snetchild * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19158979Snetchild * 20158979Snetchild * $FreeBSD: head/usr.sbin/ppp/systems.c 50479 1999-08-28 01:35:59Z peter $ 21158979Snetchild * 22158979Snetchild * TODO: 23158979Snetchild */ 24158979Snetchild#include <sys/param.h> 25158979Snetchild 26158979Snetchild#include <ctype.h> 27158979Snetchild#include <pwd.h> 28158979Snetchild#include <stdio.h> 29158979Snetchild#include <stdlib.h> 30158979Snetchild#include <string.h> 31158979Snetchild#include <termios.h> 32158979Snetchild#include <unistd.h> 33158979Snetchild 34158979Snetchild#include "defs.h" 35158979Snetchild#include "command.h" 36158979Snetchild#include "log.h" 37158979Snetchild#include "id.h" 38158979Snetchild#include "systems.h" 39158979Snetchild 40158979Snetchild#define issep(ch) ((ch) == ' ' || (ch) == '\t') 41158979Snetchild 42158979SnetchildFILE * 43158979SnetchildOpenSecret(const char *file) 44158979Snetchild{ 45158979Snetchild FILE *fp; 46158979Snetchild char line[100]; 47158979Snetchild 48158979Snetchild snprintf(line, sizeof line, "%s/%s", _PATH_PPP, file); 49158979Snetchild fp = ID0fopen(line, "r"); 50158979Snetchild if (fp == NULL) 51158979Snetchild log_Printf(LogWARN, "OpenSecret: Can't open %s.\n", line); 52158979Snetchild return (fp); 53158979Snetchild} 54158979Snetchild 55158979Snetchildvoid 56158979SnetchildCloseSecret(FILE *fp) 57158979Snetchild{ 58158979Snetchild fclose(fp); 59158979Snetchild} 60158979Snetchild 61158979Snetchild/* Move string from ``from'' to ``to'', interpreting ``~'' and $.... */ 62158979Snetchildstatic void 63158979SnetchildInterpretArg(char *from, char *to) 64158979Snetchild{ 65158979Snetchild const char *env; 66158979Snetchild char *ptr, *startto, *endto; 67158979Snetchild int len; 68158979Snetchild 69158979Snetchild startto = to; 70158979Snetchild endto = to + LINE_LEN - 1; 71158979Snetchild 72158979Snetchild while(issep(*from)) 73158979Snetchild from++; 74158979Snetchild if (*from == '~') { 75158979Snetchild ptr = strchr(++from, '/'); 76158979Snetchild len = ptr ? ptr - from : strlen(from); 77158979Snetchild if (len == 0) { 78158979Snetchild if ((env = getenv("HOME")) == NULL) 79158979Snetchild env = _PATH_PPP; 80158979Snetchild strncpy(to, env, endto - to); 81158979Snetchild } else { 82158979Snetchild struct passwd *pwd; 83158979Snetchild 84158979Snetchild strncpy(to, from, len); 85158979Snetchild to[len] = '\0'; 86158979Snetchild pwd = getpwnam(to); 87158979Snetchild if (pwd) 88158979Snetchild strncpy(to, pwd->pw_dir, endto-to); 89158979Snetchild else 90158979Snetchild strncpy(to, _PATH_PPP, endto - to); 91158979Snetchild endpwent(); 92158979Snetchild } 93158979Snetchild *endto = '\0'; 94158979Snetchild to += strlen(to); 95158979Snetchild from += len; 96158979Snetchild } 97158979Snetchild 98158979Snetchild while (to < endto && *from != '\0') { 99158979Snetchild if (*from == '$') { 100158979Snetchild if (from[1] == '$') { 101158979Snetchild *to = '\0'; /* For an empty var name below */ 102158979Snetchild from += 2; 103158979Snetchild } else if (from[1] == '{') { 104158979Snetchild ptr = strchr(from+2, '}'); 105158979Snetchild if (ptr) { 106158979Snetchild len = ptr - from - 2; 107158979Snetchild if (endto - to < len ) 108158979Snetchild len = endto - to; 109158979Snetchild if (len) { 110158979Snetchild strncpy(to, from+2, len); 111158979Snetchild to[len] = '\0'; 112158979Snetchild from = ptr+1; 113158979Snetchild } else { 114158979Snetchild *to++ = *from++; 115158979Snetchild continue; 116158979Snetchild } 117158979Snetchild } else { 118158979Snetchild *to++ = *from++; 119158979Snetchild continue; 120158979Snetchild } 121158979Snetchild } else { 122158979Snetchild ptr = to; 123158979Snetchild for (from++; (isalnum(*from) || *from == '_') && ptr < endto; from++) 124158979Snetchild *ptr++ = *from; 125158979Snetchild *ptr = '\0'; 126158979Snetchild } 127158979Snetchild if (*to == '\0') 128158979Snetchild *to++ = '$'; 129158979Snetchild else if ((env = getenv(to)) != NULL) { 130158979Snetchild strncpy(to, env, endto - to); 131158979Snetchild *endto = '\0'; 132158979Snetchild to += strlen(to); 133158979Snetchild } 134158979Snetchild } else 135158979Snetchild *to++ = *from++; 136158979Snetchild } 137158979Snetchild while (to > startto) { 138158979Snetchild to--; 139158979Snetchild if (!issep(*to)) { 140158979Snetchild to++; 141158979Snetchild break; 142158979Snetchild } 143158979Snetchild } 144158979Snetchild *to = '\0'; 145158979Snetchild} 146158979Snetchild 147158979Snetchild#define CTRL_UNKNOWN (0) 148158979Snetchild#define CTRL_INCLUDE (1) 149158979Snetchild 150158979Snetchildstatic int 151158979SnetchildDecodeCtrlCommand(char *line, char *arg) 152158979Snetchild{ 153158979Snetchild if (!strncasecmp(line, "include", 7) && issep(line[7])) { 154158979Snetchild InterpretArg(line+8, arg); 155158979Snetchild return CTRL_INCLUDE; 156158979Snetchild } 157158979Snetchild return CTRL_UNKNOWN; 158158979Snetchild} 159158979Snetchild 160158979Snetchild/* 161158979Snetchild * Initialised in system_IsValid(), set in ReadSystem(), 162158979Snetchild * used by system_IsValid() 163158979Snetchild */ 164158979Snetchildstatic int modeok; 165158979Snetchildstatic int userok; 166158979Snetchildstatic int modereq; 167158979Snetchild 168158979Snetchildint 169158979SnetchildAllowUsers(struct cmdargs const *arg) 170158979Snetchild{ 171158979Snetchild /* arg->bundle may be NULL (see system_IsValid()) ! */ 172158979Snetchild int f; 173158979Snetchild char *user; 174158979Snetchild 175158979Snetchild userok = 0; 176158979Snetchild user = getlogin(); 177158979Snetchild if (user && *user) 178158979Snetchild for (f = arg->argn; f < arg->argc; f++) 179158979Snetchild if (!strcmp("*", arg->argv[f]) || !strcmp(user, arg->argv[f])) { 180158979Snetchild userok = 1; 181158979Snetchild break; 182158979Snetchild } 183158979Snetchild 184158979Snetchild return 0; 185158979Snetchild} 186158979Snetchild 187158979Snetchildint 188158979SnetchildAllowModes(struct cmdargs const *arg) 189158979Snetchild{ 190158979Snetchild /* arg->bundle may be NULL (see system_IsValid()) ! */ 191158979Snetchild int f, mode, allowed; 192158979Snetchild 193158979Snetchild allowed = 0; 194158979Snetchild for (f = arg->argn; f < arg->argc; f++) { 195158979Snetchild mode = Nam2mode(arg->argv[f]); 196158979Snetchild if (mode == PHYS_NONE || mode == PHYS_ALL) 197158979Snetchild log_Printf(LogWARN, "allow modes: %s: Invalid mode\n", arg->argv[f]); 198158979Snetchild else 199158979Snetchild allowed |= mode; 200158979Snetchild } 201158979Snetchild 202158979Snetchild modeok = modereq & allowed ? 1 : 0; 203158979Snetchild return 0; 204158979Snetchild} 205158979Snetchild 206158979Snetchildstatic char * 207158979Snetchildstrip(char *line) 208158979Snetchild{ 209158979Snetchild int len; 210158979Snetchild 211158979Snetchild len = strlen(line); 212158979Snetchild while (len && (line[len-1] == '\n' || line[len-1] == '\r' || 213158979Snetchild issep(line[len-1]))) 214158979Snetchild line[--len] = '\0'; 215158979Snetchild 216158979Snetchild while (issep(*line)) 217158979Snetchild line++; 218158979Snetchild 219158979Snetchild if (*line == '#') 220158979Snetchild *line = '\0'; 221158979Snetchild 222158979Snetchild return line; 223158979Snetchild} 224158979Snetchild 225158979Snetchildstatic int 226158979Snetchildxgets(char *buf, int buflen, FILE *fp) 227158979Snetchild{ 228158979Snetchild int len, n; 229158979Snetchild 230158979Snetchild n = 0; 231158979Snetchild while (fgets(buf, buflen-1, fp)) { 232158979Snetchild n++; 233158979Snetchild buf[buflen-1] = '\0'; 234158979Snetchild len = strlen(buf); 235158979Snetchild while (len && (buf[len-1] == '\n' || buf[len-1] == '\r')) 236158979Snetchild buf[--len] = '\0'; 237158979Snetchild if (len && buf[len-1] == '\\') { 238158979Snetchild buf += len - 1; 239158979Snetchild buflen -= len - 1; 240158979Snetchild if (!buflen) /* No buffer space */ 241158979Snetchild break; 242158979Snetchild } else 243158979Snetchild break; 244158979Snetchild } 245158979Snetchild return n; 246158979Snetchild} 247158979Snetchild 248158979Snetchild/* Values for ``how'' in ReadSystem */ 249158979Snetchild#define SYSTEM_EXISTS 1 250158979Snetchild#define SYSTEM_VALIDATE 2 251158979Snetchild#define SYSTEM_EXEC 3 252158979Snetchild 253158979Snetchild/* Returns -2 for ``file not found'' and -1 for ``label not found'' */ 254158979Snetchild 255158979Snetchildstatic int 256158979SnetchildReadSystem(struct bundle *bundle, const char *name, const char *file, 257158979Snetchild struct prompt *prompt, struct datalink *cx, int how) 258158979Snetchild{ 259158979Snetchild FILE *fp; 260158979Snetchild char *cp, *wp; 261158979Snetchild int n, len; 262158979Snetchild char line[LINE_LEN]; 263158979Snetchild char filename[MAXPATHLEN]; 264158979Snetchild int linenum; 265158979Snetchild int argc; 266158979Snetchild char *argv[MAXARGS]; 267158979Snetchild int allowcmd; 268158979Snetchild int indent; 269158979Snetchild char arg[LINE_LEN]; 270158979Snetchild 271158979Snetchild if (*file == '/') 272158979Snetchild snprintf(filename, sizeof filename, "%s", file); 273158979Snetchild else 274158979Snetchild snprintf(filename, sizeof filename, "%s/%s", _PATH_PPP, file); 275158979Snetchild fp = ID0fopen(filename, "r"); 276158979Snetchild if (fp == NULL) { 277158979Snetchild log_Printf(LogDEBUG, "ReadSystem: Can't open %s.\n", filename); 278158979Snetchild return -2; 279158979Snetchild } 280158979Snetchild log_Printf(LogDEBUG, "ReadSystem: Checking %s (%s).\n", name, filename); 281158979Snetchild 282158979Snetchild linenum = 0; 283158979Snetchild while ((n = xgets(line, sizeof line, fp))) { 284158979Snetchild linenum += n; 285158979Snetchild if (issep(*line)) 286158979Snetchild continue; 287158979Snetchild 288158979Snetchild cp = strip(line); 289158979Snetchild 290158979Snetchild switch (*cp) { 291158979Snetchild case '\0': /* empty/comment */ 292158979Snetchild break; 293158979Snetchild 294158979Snetchild case '!': 295158979Snetchild switch (DecodeCtrlCommand(cp+1, arg)) { 296158979Snetchild case CTRL_INCLUDE: 297158979Snetchild log_Printf(LogCOMMAND, "%s: Including \"%s\"\n", filename, arg); 298158979Snetchild n = ReadSystem(bundle, name, arg, prompt, cx, how); 299158979Snetchild log_Printf(LogCOMMAND, "%s: Done include of \"%s\"\n", filename, arg); 300158979Snetchild if (!n) 301158979Snetchild return 0; /* got it */ 302158979Snetchild break; 303158979Snetchild default: 304158979Snetchild log_Printf(LogWARN, "%s: %s: Invalid command\n", filename, cp); 305158979Snetchild break; 306158979Snetchild } 307158979Snetchild break; 308158979Snetchild 309158979Snetchild default: 310158979Snetchild wp = strchr(cp, ':'); 311158979Snetchild if (wp == NULL || wp[1] != '\0') { 312 log_Printf(LogWARN, "Bad rule in %s (line %d) - missing colon.\n", 313 filename, linenum); 314 continue; 315 } 316 *wp = '\0'; 317 cp = strip(cp); /* lose any spaces between the label and the ':' */ 318 319 if (strcmp(cp, name) == 0) { 320 /* We're in business */ 321 if (how == SYSTEM_EXISTS) 322 return 0; 323 while ((n = xgets(line, sizeof line, fp))) { 324 linenum += n; 325 indent = issep(*line); 326 cp = strip(line); 327 328 if (*cp == '\0') /* empty / comment */ 329 continue; 330 331 if (!indent) { /* start of next section */ 332 if (*cp != '!') { 333 wp = strchr(cp, ':'); 334 if ((how == SYSTEM_EXEC) && (wp == NULL || wp[1] != '\0')) 335 log_Printf(LogWARN, "Unindented command (%s line %d) -" 336 " ignored\n", filename, linenum); 337 } 338 break; 339 } 340 341 len = strlen(cp); 342 argc = command_Interpret(cp, len, argv); 343 allowcmd = argc > 0 && !strcasecmp(argv[0], "allow"); 344 if ((!(how == SYSTEM_EXEC) && allowcmd) || 345 ((how == SYSTEM_EXEC) && !allowcmd)) 346 command_Run(bundle, argc, (char const *const *)argv, prompt, 347 name, cx); 348 } 349 350 fclose(fp); /* everything read - get out */ 351 return 0; 352 } 353 break; 354 } 355 } 356 fclose(fp); 357 return -1; 358} 359 360const char * 361system_IsValid(const char *name, struct prompt *prompt, int mode) 362{ 363 /* 364 * Note: The ReadSystem() calls only result in calls to the Allow* 365 * functions. arg->bundle will be set to NULL for these commands ! 366 */ 367 int def, how, rs; 368 369 def = !strcmp(name, "default"); 370 how = ID0realuid() == 0 ? SYSTEM_EXISTS : SYSTEM_VALIDATE; 371 userok = 0; 372 modeok = 1; 373 modereq = mode; 374 375 rs = ReadSystem(NULL, "default", CONFFILE, prompt, NULL, how); 376 377 if (!def) { 378 if (rs == -1) 379 rs = 0; /* we don't care that ``default'' doesn't exist */ 380 381 if (rs == 0) 382 rs = ReadSystem(NULL, name, CONFFILE, prompt, NULL, how); 383 384 if (rs == -1) 385 return "Configuration label not found"; 386 387 if (rs == -2) 388 return _PATH_PPP "/" CONFFILE ": File not found"; 389 } 390 391 if (how == SYSTEM_EXISTS) 392 userok = modeok = 1; 393 394 if (!userok) 395 return "User access denied"; 396 397 if (!modeok) 398 return "Mode denied for this label"; 399 400 return NULL; 401} 402 403int 404system_Select(struct bundle *bundle, const char *name, const char *file, 405 struct prompt *prompt, struct datalink *cx) 406{ 407 userok = modeok = 1; 408 modereq = PHYS_ALL; 409 return ReadSystem(bundle, name, file, prompt, cx, SYSTEM_EXEC); 410} 411