systems.c revision 31918
1222417Sjulian/* 2222417Sjulian * System configuration routines 3241310Sdteske * 4222417Sjulian * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5222417Sjulian * 6222417Sjulian * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7222417Sjulian * 8222417Sjulian * Redistribution and use in source and binary forms are permitted 9222417Sjulian * provided that the above copyright notice and this paragraph are 10222417Sjulian * duplicated in all such forms and that any documentation, 11222417Sjulian * advertising materials, and other materials related to such 12222417Sjulian * distribution and use acknowledge that the software was developed 13222417Sjulian * by the Internet Initiative Japan, Inc. The name of the 14222417Sjulian * IIJ may not be used to endorse or promote products derived 15222417Sjulian * from this software without specific prior written permission. 16222417Sjulian * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17222417Sjulian * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18222417Sjulian * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19222417Sjulian * 20222417Sjulian * $Id: systems.c,v 1.32 1997/12/21 02:11:48 brian Exp $ 21222417Sjulian * 22222417Sjulian * TODO: 23222417Sjulian */ 24222417Sjulian#include <sys/param.h> 25222417Sjulian#include <netinet/in.h> 26222417Sjulian 27222417Sjulian#include <ctype.h> 28222417Sjulian#include <pwd.h> 29222417Sjulian#include <stdio.h> 30222417Sjulian#include <stdlib.h> 31222417Sjulian#include <string.h> 32222417Sjulian#include <unistd.h> 33222417Sjulian 34222417Sjulian#include "command.h" 35222417Sjulian#include "mbuf.h" 36222417Sjulian#include "log.h" 37222417Sjulian#include "id.h" 38222417Sjulian#include "defs.h" 39222417Sjulian#include "timer.h" 40222417Sjulian#include "fsm.h" 41222417Sjulian#include "loadalias.h" 42222417Sjulian#include "ipcp.h" 43222417Sjulian#include "pathnames.h" 44222417Sjulian#include "vars.h" 45222417Sjulian#include "server.h" 46222417Sjulian#include "chat.h" 47222417Sjulian#include "systems.h" 48222417Sjulian 49222417Sjulian#define issep(ch) ((ch) == ' ' || (ch) == '\t') 50222417Sjulian 51222417SjulianFILE * 52222417SjulianOpenSecret(const char *file) 53222417Sjulian{ 54222417Sjulian FILE *fp; 55222417Sjulian char line[100]; 56222417Sjulian 57222417Sjulian snprintf(line, sizeof line, "%s/%s", _PATH_PPP, file); 58222417Sjulian fp = ID0fopen(line, "r"); 59222417Sjulian if (fp == NULL) 60222417Sjulian LogPrintf(LogWARN, "OpenSecret: Can't open %s.\n", line); 61222417Sjulian return (fp); 62222417Sjulian} 63222417Sjulian 64222417Sjulianvoid 65222417SjulianCloseSecret(FILE * fp) 66222417Sjulian{ 67222417Sjulian fclose(fp); 68222417Sjulian} 69222417Sjulian 70222417Sjulian/* Move string from ``from'' to ``to'', interpreting ``~'' and $.... */ 71222417Sjulianstatic void 72222417SjulianInterpretArg(char *from, char *to) 73222417Sjulian{ 74222417Sjulian const char *env; 75222417Sjulian char *ptr, *startto, *endto; 76222417Sjulian int len; 77222417Sjulian 78222417Sjulian startto = to; 79222417Sjulian endto = to + LINE_LEN - 1; 80222417Sjulian 81222417Sjulian while(issep(*from)) 82222417Sjulian from++; 83222417Sjulian if (*from == '~') { 84222417Sjulian ptr = strchr(++from, '/'); 85222417Sjulian len = ptr ? ptr - from : strlen(from); 86222417Sjulian if (len == 0) { 87222417Sjulian if ((env = getenv("HOME")) == NULL) 88222417Sjulian env = _PATH_PPP; 89222417Sjulian strncpy(to, env, endto - to); 90222417Sjulian } else { 91222417Sjulian struct passwd *pwd; 92222417Sjulian 93222417Sjulian strncpy(to, from, len); 94222417Sjulian to[len] = '\0'; 95222417Sjulian pwd = getpwnam(to); 96222417Sjulian if (pwd) 97222417Sjulian strncpy(to, pwd->pw_dir, endto-to); 98222417Sjulian else 99222417Sjulian strncpy(to, _PATH_PPP, endto - to); 100222417Sjulian endpwent(); 101222417Sjulian } 102222417Sjulian *endto = '\0'; 103222417Sjulian to += strlen(to); 104222417Sjulian from += len; 105222417Sjulian } 106222417Sjulian 107222417Sjulian while (to < endto && *from != '\0') { 108222417Sjulian if (*from == '$') { 109222417Sjulian if (from[1] == '$') { 110222417Sjulian *to = '\0'; /* For an empty var name below */ 111222417Sjulian from += 2; 112222417Sjulian } else if (from[1] == '{') { 113222417Sjulian ptr = strchr(from+2, '}'); 114222417Sjulian if (ptr) { 115222417Sjulian len = ptr - from - 2; 116222417Sjulian if (endto - to < len ) 117222417Sjulian len = endto - to; 118222417Sjulian if (len) { 119222417Sjulian strncpy(to, from+2, len); 120222417Sjulian to[len] = '\0'; 121222417Sjulian from = ptr+1; 122222417Sjulian } else { 123222417Sjulian *to++ = *from++; 124222417Sjulian continue; 125222417Sjulian } 126222417Sjulian } else { 127222417Sjulian *to++ = *from++; 128222417Sjulian continue; 129222417Sjulian } 130222417Sjulian } else { 131222417Sjulian ptr = to; 132222417Sjulian for (from++; (isalnum(*from) || *from == '_') && ptr < endto; from++) 133222417Sjulian *ptr++ = *from; 134228985Spluknet *ptr = '\0'; 135222417Sjulian } 136222417Sjulian if (*to == '\0') 137222417Sjulian *to++ = '$'; 138228985Spluknet else if ((env = getenv(to)) != NULL) { 139222417Sjulian strncpy(to, env, endto - to); 140222417Sjulian *endto = '\0'; 141222417Sjulian to += strlen(to); 142222417Sjulian } 143222417Sjulian } else 144222417Sjulian *to++ = *from++; 145222417Sjulian } 146222417Sjulian while (to > startto) { 147222417Sjulian to--; 148222417Sjulian if (!issep(*to)) { 149222417Sjulian to++; 150222417Sjulian break; 151222417Sjulian } 152222417Sjulian } 153222417Sjulian *to = '\0'; 154222417Sjulian} 155222417Sjulian 156222417Sjulian#define CTRL_UNKNOWN (0) 157222417Sjulian#define CTRL_INCLUDE (1) 158222417Sjulian 159222417Sjulianstatic int 160222417SjulianDecodeCtrlCommand(char *line, char *arg) 161222417Sjulian{ 162222417Sjulian if (!strncasecmp(line, "include", 7) && issep(line[7])) { 163222417Sjulian InterpretArg(line+8, arg); 164222417Sjulian return CTRL_INCLUDE; 165222417Sjulian } 166222417Sjulian return CTRL_UNKNOWN; 167222417Sjulian} 168222417Sjulian 169222417Sjulianstatic int userok; 170222417Sjulian 171222417Sjulianint 172222417SjulianAllowUsers(struct cmdargs const *arg) 173222417Sjulian{ 174222417Sjulian int f; 175222417Sjulian char *user; 176222417Sjulian 177222417Sjulian userok = 0; 178222417Sjulian user = getlogin(); 179222417Sjulian if (user && *user) 180222417Sjulian for (f = 0; f < arg->argc; f++) 181222417Sjulian if (!strcmp("*", arg->argv[f]) || !strcmp(user, arg->argv[f])) { 182222417Sjulian userok = 1; 183222417Sjulian break; 184222417Sjulian } 185222417Sjulian 186222417Sjulian return 0; 187222417Sjulian} 188222417Sjulian 189222417Sjulianstatic struct { 190222417Sjulian int mode; 191222417Sjulian const char *name; 192222417Sjulian} modes[] = { 193222417Sjulian { MODE_INTER, "interactive" }, 194222417Sjulian { MODE_AUTO, "auto" }, 195222417Sjulian { MODE_DIRECT, "direct" }, 196222417Sjulian { MODE_DEDICATED, "dedicated" }, 197222417Sjulian { MODE_DDIAL, "ddial" }, 198222417Sjulian { MODE_BACKGROUND, "background" }, 199222417Sjulian { ~0, "*" }, 200222417Sjulian { 0, 0 } 201222417Sjulian}; 202222417Sjulian 203222417Sjulianstatic int modeok; 204222417Sjulian 205222417Sjulianint 206222417SjulianAllowModes(struct cmdargs const *arg) 207222417Sjulian{ 208222417Sjulian int f; 209222417Sjulian int m; 210222417Sjulian int allowed; 211222417Sjulian 212222417Sjulian allowed = 0; 213222417Sjulian for (f = 0; f < arg->argc; f++) { 214222417Sjulian for (m = 0; modes[m].mode; m++) 215222417Sjulian if (!strcasecmp(modes[m].name, arg->argv[f])) { 216222417Sjulian allowed |= modes[m].mode; 217222417Sjulian break; 218222417Sjulian } 219222417Sjulian if (modes[m].mode == 0) 220222417Sjulian LogPrintf(LogWARN, "allow modes: %s: Invalid mode\n", arg->argv[f]); 221222417Sjulian } 222222417Sjulian 223222417Sjulian modeok = (mode | allowed) == allowed ? 1 : 0; 224222417Sjulian return 0; 225222417Sjulian} 226222417Sjulian 227222417Sjulianstatic int 228222417SjulianReadSystem(const char *name, const char *file, int doexec) 229222417Sjulian{ 230222417Sjulian FILE *fp; 231222417Sjulian char *cp, *wp; 232222417Sjulian int n, len; 233222417Sjulian u_char olauth; 234222417Sjulian char line[LINE_LEN]; 235222417Sjulian char filename[MAXPATHLEN]; 236222417Sjulian int linenum; 237222417Sjulian int argc; 238222417Sjulian char **argv; 239222417Sjulian int allowcmd; 240222417Sjulian 241222417Sjulian if (*file == '/') 242222417Sjulian snprintf(filename, sizeof filename, "%s", file); 243222417Sjulian else 244222417Sjulian snprintf(filename, sizeof filename, "%s/%s", _PATH_PPP, file); 245222417Sjulian fp = ID0fopen(filename, "r"); 246222417Sjulian if (fp == NULL) { 247222417Sjulian LogPrintf(LogDEBUG, "ReadSystem: Can't open %s.\n", filename); 248222417Sjulian return (-1); 249222417Sjulian } 250222417Sjulian LogPrintf(LogDEBUG, "ReadSystem: Checking %s (%s).\n", name, filename); 251222417Sjulian 252222417Sjulian linenum = 0; 253222417Sjulian while (fgets(line, sizeof(line), fp)) { 254222417Sjulian linenum++; 255222417Sjulian cp = line; 256222417Sjulian switch (*cp) { 257222417Sjulian case '#': /* comment */ 258222417Sjulian break; 259222417Sjulian case ' ': 260222417Sjulian case '\t': 261222417Sjulian break; 262222417Sjulian default: 263222417Sjulian wp = strpbrk(cp, ":\n"); 264222417Sjulian if (wp == NULL) { 265222417Sjulian LogPrintf(LogWARN, "Bad rule in %s (line %d) - missing colon.\n", 266222417Sjulian filename, linenum); 267222417Sjulian ServerClose(); 268222417Sjulian exit(1); 269222417Sjulian } 270222417Sjulian *wp = '\0'; 271222417Sjulian if (*cp == '!') { 272222417Sjulian char arg[LINE_LEN]; 273222417Sjulian switch (DecodeCtrlCommand(cp+1, arg)) { 274222417Sjulian case CTRL_INCLUDE: 275222417Sjulian LogPrintf(LogCOMMAND, "%s: Including \"%s\"\n", filename, arg); 276222417Sjulian n = ReadSystem(name, arg, doexec); 277222417Sjulian LogPrintf(LogCOMMAND, "%s: Done include of \"%s\"\n", filename, arg); 278222417Sjulian if (!n) 279222417Sjulian return 0; /* got it */ 280222417Sjulian break; 281222417Sjulian default: 282222417Sjulian LogPrintf(LogWARN, "%s: %s: Invalid command\n", filename, cp); 283222417Sjulian break; 284222417Sjulian } 285222417Sjulian } else if (strcmp(cp, name) == 0) { 286222417Sjulian while (fgets(line, sizeof(line), fp)) { 287222417Sjulian cp = line; 288222417Sjulian if (issep(*cp)) { 289222417Sjulian n = strspn(cp, " \t"); 290222417Sjulian cp += n; 291222417Sjulian len = strlen(cp); 292222417Sjulian if (!len || *cp == '#') 293222417Sjulian continue; 294222417Sjulian if (cp[len-1] == '\n') 295222417Sjulian cp[--len] = '\0'; 296222417Sjulian if (!len) 297222417Sjulian continue; 298222417Sjulian InterpretCommand(cp, len, &argc, &argv); 299222417Sjulian allowcmd = argc > 0 && !strcasecmp(*argv, "allow"); 300222417Sjulian if ((!doexec && allowcmd) || (doexec && !allowcmd)) { 301222417Sjulian olauth = VarLocalAuth; 302222417Sjulian if (VarLocalAuth == LOCAL_NO_AUTH) 303222417Sjulian VarLocalAuth = LOCAL_AUTH; 304222417Sjulian RunCommand(argc, (char const *const *)argv, name); 305222417Sjulian VarLocalAuth = olauth; 306222417Sjulian } 307222417Sjulian } else if (*cp == '#' || *cp == '\n' || *cp == '\0') { 308222417Sjulian continue; 309222417Sjulian } else 310222417Sjulian break; 311222417Sjulian } 312222417Sjulian fclose(fp); 313222417Sjulian return (0); 314222417Sjulian } 315222417Sjulian break; 316222417Sjulian } 317222417Sjulian } 318222417Sjulian fclose(fp); 319222417Sjulian return -1; 320222417Sjulian} 321222417Sjulian 322222417Sjulianint 323222417SjulianValidSystem(const char *name) 324222417Sjulian{ 325222417Sjulian if (ID0realuid() == 0) 326222417Sjulian return userok = modeok = 1; 327222417Sjulian userok = 0; 328222417Sjulian modeok = 1; 329222417Sjulian ReadSystem("default", CONFFILE, 0); 330222417Sjulian if (name != NULL) 331222417Sjulian ReadSystem(name, CONFFILE, 0); 332222417Sjulian return userok && modeok; 333222417Sjulian} 334222417Sjulian 335222417Sjulianint 336222417SjulianSelectSystem(const char *name, const char *file) 337222417Sjulian{ 338222417Sjulian userok = modeok = 1; 339222417Sjulian return ReadSystem(name, file, 1); 340222417Sjulian} 341222417Sjulian 342222417Sjulianint 343222417SjulianLoadCommand(struct cmdargs const *arg) 344222417Sjulian{ 345222417Sjulian const char *name; 346222417Sjulian 347222417Sjulian if (arg->argc > 0) 348222417Sjulian name = *arg->argv; 349222417Sjulian else 350222417Sjulian name = "default"; 351222417Sjulian 352222417Sjulian if (!ValidSystem(name)) { 353222417Sjulian LogPrintf(LogERROR, "%s: Label not allowed\n", name); 354222417Sjulian return 1; 355222417Sjulian } else if (SelectSystem(name, CONFFILE) < 0) { 356222417Sjulian LogPrintf(LogWARN, "%s: label not found.\n", name); 357222417Sjulian return -1; 358222417Sjulian } else 359222417Sjulian SetLabel(arg->argc ? name : NULL); 360222417Sjulian return 0; 361222417Sjulian} 362222417Sjulian 363222417Sjulianint 364222417SjulianSaveCommand(struct cmdargs const *arg) 365222417Sjulian{ 366222417Sjulian LogPrintf(LogWARN, "save command is not implemented (yet).\n"); 367222417Sjulian return 1; 368222417Sjulian} 369222417Sjulian