systems.c revision 46828
1139743Simp/* 239212Sgibbs * System configuration routines 339212Sgibbs * 439212Sgibbs * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 539212Sgibbs * 639212Sgibbs * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 739212Sgibbs * 839212Sgibbs * Redistribution and use in source and binary forms are permitted 939212Sgibbs * provided that the above copyright notice and this paragraph are 1039212Sgibbs * duplicated in all such forms and that any documentation, 1139212Sgibbs * advertising materials, and other materials related to such 1239212Sgibbs * distribution and use acknowledge that the software was developed 1339212Sgibbs * by the Internet Initiative Japan, Inc. The name of the 1439212Sgibbs * IIJ may not be used to endorse or promote products derived 1539212Sgibbs * from this software without specific prior written permission. 1639212Sgibbs * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1739212Sgibbs * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1839212Sgibbs * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1939212Sgibbs * 2039212Sgibbs * $Id: systems.c,v 1.43 1999/05/08 11:07:43 brian Exp $ 2139212Sgibbs * 2239212Sgibbs * TODO: 2339212Sgibbs */ 2439212Sgibbs#include <sys/param.h> 2539212Sgibbs 2639212Sgibbs#include <ctype.h> 2739212Sgibbs#include <pwd.h> 2850477Speter#include <stdio.h> 2939212Sgibbs#include <stdlib.h> 3039212Sgibbs#include <string.h> 3139212Sgibbs#include <termios.h> 3239212Sgibbs#include <unistd.h> 3339212Sgibbs 3455206Speter#include "defs.h" 3539212Sgibbs#include "command.h" 3639212Sgibbs#include "log.h" 3739212Sgibbs#include "id.h" 3839212Sgibbs#include "systems.h" 3939212Sgibbs 4039212Sgibbs#define issep(ch) ((ch) == ' ' || (ch) == '\t') 4139212Sgibbs 4239212SgibbsFILE * 4339212SgibbsOpenSecret(const char *file) 4439212Sgibbs{ 4539212Sgibbs FILE *fp; 4639212Sgibbs char line[100]; 4739212Sgibbs 4839212Sgibbs snprintf(line, sizeof line, "%s/%s", _PATH_PPP, file); 4939212Sgibbs fp = ID0fopen(line, "r"); 5039212Sgibbs if (fp == NULL) 5139212Sgibbs log_Printf(LogWARN, "OpenSecret: Can't open %s.\n", line); 5239212Sgibbs return (fp); 5339212Sgibbs} 5439212Sgibbs 5539212Sgibbsvoid 5671507SjhbCloseSecret(FILE *fp) 5739212Sgibbs{ 5839212Sgibbs fclose(fp); 59168752Sscottl} 6046581Sken 6146581Sken/* Move string from ``from'' to ``to'', interpreting ``~'' and $.... */ 6239212Sgibbsstatic void 6339212SgibbsInterpretArg(char *from, char *to) 64186185Strasz{ 65186185Strasz const char *env; 6639212Sgibbs char *ptr, *startto, *endto; 6739212Sgibbs int len; 6839212Sgibbs 6939212Sgibbs startto = to; 7039212Sgibbs endto = to + LINE_LEN - 1; 7139212Sgibbs 7239212Sgibbs while(issep(*from)) 7371507Sjhb from++; 7471507Sjhb if (*from == '~') { 7571507Sjhb ptr = strchr(++from, '/'); 7671507Sjhb len = ptr ? ptr - from : strlen(from); 7771507Sjhb if (len == 0) { 7839212Sgibbs if ((env = getenv("HOME")) == NULL) 7939212Sgibbs env = _PATH_PPP; 8039212Sgibbs strncpy(to, env, endto - to); 8139212Sgibbs } else { 8239212Sgibbs struct passwd *pwd; 8339212Sgibbs 8439212Sgibbs strncpy(to, from, len); 8539212Sgibbs to[len] = '\0'; 8639212Sgibbs pwd = getpwnam(to); 8739212Sgibbs if (pwd) 8839212Sgibbs strncpy(to, pwd->pw_dir, endto-to); 8939212Sgibbs else 9039212Sgibbs strncpy(to, _PATH_PPP, endto - to); 9139212Sgibbs endpwent(); 9239212Sgibbs } 9339212Sgibbs *endto = '\0'; 9471507Sjhb to += strlen(to); 9539212Sgibbs from += len; 96168752Sscottl } 97168864Sscottl 98168864Sscottl while (to < endto && *from != '\0') { 9939212Sgibbs if (*from == '$') { 10039212Sgibbs if (from[1] == '$') { 10139212Sgibbs *to = '\0'; /* For an empty var name below */ 10246581Sken from += 2; 10346581Sken } else if (from[1] == '{') { 10439212Sgibbs ptr = strchr(from+2, '}'); 105168752Sscottl if (ptr) { 106168752Sscottl len = ptr - from - 2; 107168752Sscottl if (endto - to < len ) 10839212Sgibbs len = endto - to; 109186185Strasz if (len) { 11039212Sgibbs strncpy(to, from+2, len); 11139212Sgibbs to[len] = '\0'; 112249224Smav from = ptr+1; 113249224Smav } else { 114168752Sscottl *to++ = *from++; 11539212Sgibbs continue; 11639212Sgibbs } 11739212Sgibbs } else { 11839212Sgibbs *to++ = *from++; 11939212Sgibbs continue; 12039212Sgibbs } 12171507Sjhb } else { 12239212Sgibbs ptr = to; 12339212Sgibbs for (from++; (isalnum(*from) || *from == '_') && ptr < endto; from++) 12439212Sgibbs *ptr++ = *from; 12539212Sgibbs *ptr = '\0'; 12639212Sgibbs } 12739212Sgibbs if (*to == '\0') 12839212Sgibbs *to++ = '$'; 12939212Sgibbs else if ((env = getenv(to)) != NULL) { 13039212Sgibbs strncpy(to, env, endto - to); 13139212Sgibbs *endto = '\0'; 13239212Sgibbs to += strlen(to); 13339212Sgibbs } 13439212Sgibbs } else 13539212Sgibbs *to++ = *from++; 13639212Sgibbs } 13739212Sgibbs while (to > startto) { 13839212Sgibbs to--; 13939212Sgibbs if (!issep(*to)) { 14039212Sgibbs to++; 14139212Sgibbs break; 14239212Sgibbs } 14339212Sgibbs } 14439212Sgibbs *to = '\0'; 14555206Speter} 14639212Sgibbs 147#define CTRL_UNKNOWN (0) 148#define CTRL_INCLUDE (1) 149 150static int 151DecodeCtrlCommand(char *line, char *arg) 152{ 153 if (!strncasecmp(line, "include", 7) && issep(line[7])) { 154 InterpretArg(line+8, arg); 155 return CTRL_INCLUDE; 156 } 157 return CTRL_UNKNOWN; 158} 159 160/* 161 * Initialised in system_IsValid(), set in ReadSystem(), 162 * used by system_IsValid() 163 */ 164static int modeok; 165static int userok; 166static int modereq; 167 168int 169AllowUsers(struct cmdargs const *arg) 170{ 171 /* arg->bundle may be NULL (see system_IsValid()) ! */ 172 int f; 173 char *user; 174 175 userok = 0; 176 user = getlogin(); 177 if (user && *user) 178 for (f = arg->argn; f < arg->argc; f++) 179 if (!strcmp("*", arg->argv[f]) || !strcmp(user, arg->argv[f])) { 180 userok = 1; 181 break; 182 } 183 184 return 0; 185} 186 187int 188AllowModes(struct cmdargs const *arg) 189{ 190 /* arg->bundle may be NULL (see system_IsValid()) ! */ 191 int f, mode, allowed; 192 193 allowed = 0; 194 for (f = arg->argn; f < arg->argc; f++) { 195 mode = Nam2mode(arg->argv[f]); 196 if (mode == PHYS_NONE || mode == PHYS_ALL) 197 log_Printf(LogWARN, "allow modes: %s: Invalid mode\n", arg->argv[f]); 198 else 199 allowed |= mode; 200 } 201 202 modeok = modereq & allowed ? 1 : 0; 203 return 0; 204} 205 206static char * 207strip(char *line) 208{ 209 int len; 210 211 len = strlen(line); 212 while (len && (line[len-1] == '\n' || line[len-1] == '\r' || 213 issep(line[len-1]))) 214 line[--len] = '\0'; 215 216 while (issep(*line)) 217 line++; 218 219 if (*line == '#') 220 *line = '\0'; 221 222 return line; 223} 224 225static int 226xgets(char *buf, int buflen, FILE *fp) 227{ 228 int len, n; 229 230 n = 0; 231 while (fgets(buf, buflen-1, fp)) { 232 n++; 233 buf[buflen-1] = '\0'; 234 len = strlen(buf); 235 while (len && (buf[len-1] == '\n' || buf[len-1] == '\r')) 236 buf[--len] = '\0'; 237 if (len && buf[len-1] == '\\') { 238 buf += len - 1; 239 buflen -= len - 1; 240 if (!buflen) /* No buffer space */ 241 break; 242 } else 243 break; 244 } 245 return n; 246} 247 248/* Values for ``how'' in ReadSystem */ 249#define SYSTEM_EXISTS 1 250#define SYSTEM_VALIDATE 2 251#define SYSTEM_EXEC 3 252 253/* Returns -2 for ``file not found'' and -1 for ``label not found'' */ 254 255static int 256ReadSystem(struct bundle *bundle, const char *name, const char *file, 257 struct prompt *prompt, struct datalink *cx, int how) 258{ 259 FILE *fp; 260 char *cp, *wp; 261 int n, len; 262 char line[LINE_LEN]; 263 char filename[MAXPATHLEN]; 264 int linenum; 265 int argc; 266 char *argv[MAXARGS]; 267 int allowcmd; 268 int indent; 269 char arg[LINE_LEN]; 270 271 if (*file == '/') 272 snprintf(filename, sizeof filename, "%s", file); 273 else 274 snprintf(filename, sizeof filename, "%s/%s", _PATH_PPP, file); 275 fp = ID0fopen(filename, "r"); 276 if (fp == NULL) { 277 log_Printf(LogDEBUG, "ReadSystem: Can't open %s.\n", filename); 278 return -2; 279 } 280 log_Printf(LogDEBUG, "ReadSystem: Checking %s (%s).\n", name, filename); 281 282 linenum = 0; 283 while ((n = xgets(line, sizeof line, fp))) { 284 linenum += n; 285 if (issep(*line)) 286 continue; 287 288 cp = strip(line); 289 290 switch (*cp) { 291 case '\0': /* empty/comment */ 292 break; 293 294 case '!': 295 switch (DecodeCtrlCommand(cp+1, arg)) { 296 case CTRL_INCLUDE: 297 log_Printf(LogCOMMAND, "%s: Including \"%s\"\n", filename, arg); 298 n = ReadSystem(bundle, name, arg, prompt, cx, how); 299 log_Printf(LogCOMMAND, "%s: Done include of \"%s\"\n", filename, arg); 300 if (!n) 301 return 0; /* got it */ 302 break; 303 default: 304 log_Printf(LogWARN, "%s: %s: Invalid command\n", filename, cp); 305 break; 306 } 307 break; 308 309 default: 310 wp = strchr(cp, ':'); 311 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 wp = strchr(cp, ':'); 333 if ((how == SYSTEM_EXEC) && (wp == NULL || wp[1] != '\0')) 334 log_Printf(LogWARN, "Unindented command (%s line %d) - ignored\n", 335 filename, linenum); 336 break; 337 } 338 339 len = strlen(cp); 340 argc = command_Interpret(cp, len, argv); 341 allowcmd = argc > 0 && !strcasecmp(argv[0], "allow"); 342 if ((!(how == SYSTEM_EXEC) && allowcmd) || 343 ((how == SYSTEM_EXEC) && !allowcmd)) 344 command_Run(bundle, argc, (char const *const *)argv, prompt, 345 name, cx); 346 } 347 348 fclose(fp); /* everything read - get out */ 349 return 0; 350 } 351 break; 352 } 353 } 354 fclose(fp); 355 return -1; 356} 357 358const char * 359system_IsValid(const char *name, struct prompt *prompt, int mode) 360{ 361 /* 362 * Note: The ReadSystem() calls only result in calls to the Allow* 363 * functions. arg->bundle will be set to NULL for these commands ! 364 */ 365 int def, how, rs; 366 367 def = !strcmp(name, "default"); 368 how = ID0realuid() == 0 ? SYSTEM_EXISTS : SYSTEM_VALIDATE; 369 userok = 0; 370 modeok = 1; 371 modereq = mode; 372 373 rs = ReadSystem(NULL, "default", CONFFILE, prompt, NULL, how); 374 375 if (!def) { 376 if (rs == -1) 377 rs = 0; /* we don't care that ``default'' doesn't exist */ 378 379 if (rs == 0) 380 rs = ReadSystem(NULL, name, CONFFILE, prompt, NULL, how); 381 382 if (rs == -1) 383 return "Configuration label not found"; 384 385 if (rs == -2) 386 return _PATH_PPP "/" CONFFILE ": File not found"; 387 } 388 389 if (how == SYSTEM_EXISTS) 390 userok = modeok = 1; 391 392 if (!userok) 393 return "User access denied"; 394 395 if (!modeok) 396 return "Mode denied for this label"; 397 398 return NULL; 399} 400 401int 402system_Select(struct bundle *bundle, const char *name, const char *file, 403 struct prompt *prompt, struct datalink *cx) 404{ 405 userok = modeok = 1; 406 modereq = PHYS_ALL; 407 return ReadSystem(bundle, name, file, prompt, cx, SYSTEM_EXEC); 408} 409