systems.c revision 31139
1/*
2 *	          System configuration routines
3 *
4 *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan, Inc.  The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * $Id: systems.c,v 1.23 1997/11/11 22:58:13 brian Exp $
21 *
22 *  TODO:
23 */
24#include <sys/param.h>
25#include <netinet/in.h>
26
27#include <ctype.h>
28#include <pwd.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <unistd.h>
33
34#include "mbuf.h"
35#include "log.h"
36#include "id.h"
37#include "defs.h"
38#include "timer.h"
39#include "fsm.h"
40#include "loadalias.h"
41#include "command.h"
42#include "ipcp.h"
43#include "pathnames.h"
44#include "vars.h"
45#include "server.h"
46#include "chat.h"
47#include "systems.h"
48
49#define issep(ch) ((ch) == ' ' || (ch) == '\t')
50
51FILE *
52OpenSecret(char *file)
53{
54  FILE *fp;
55  char line[100];
56
57  snprintf(line, sizeof line, "%s/%s", _PATH_PPP, file);
58  fp = ID0fopen(line, "r");
59  if (fp == NULL)
60    LogPrintf(LogWARN, "OpenSecret: Can't open %s.\n", line);
61  return (fp);
62}
63
64void
65CloseSecret(FILE * fp)
66{
67  fclose(fp);
68}
69
70/* Move string from ``from'' to ``to'', interpreting ``~'' and $.... */
71static void
72InterpretArg(char *from, char *to)
73{
74  const char *env;
75  char *ptr, *startto, *endto;
76  int len;
77
78  startto = to;
79  endto = to + LINE_LEN - 1;
80
81  while(issep(*from))
82    from++;
83  if (*from == '~') {
84    ptr = strchr(++from, '/');
85    len = ptr ? ptr - from : strlen(from);
86    if (len == 0) {
87      if ((env = getenv("HOME")) == NULL)
88        env = _PATH_PPP;
89      strncpy(to, env, endto - to);
90    } else {
91      struct passwd *pwd;
92
93      strncpy(to, from, len);
94      to[len] = '\0';
95      pwd = getpwnam(to);
96      if (pwd)
97        strncpy(to, pwd->pw_dir, endto-to);
98      else
99        strncpy(to, _PATH_PPP, endto - to);
100      endpwent();
101    }
102    *endto = '\0';
103    to += strlen(to);
104    from += len;
105  }
106
107  while (to < endto && *from != '\0') {
108    if (*from == '$') {
109      if (from[1] == '$') {
110        *to = '\0';	/* For an empty var name below */
111        from += 2;
112      } else if (from[1] == '{') {
113        ptr = strchr(from+2, '}');
114        if (ptr) {
115          len = ptr - from - 2;
116          if (endto - to < len )
117            len = endto - to;
118          if (len) {
119            strncpy(to, from+2, len);
120            to[len] = '\0';
121            from = ptr+1;
122          } else {
123            *to++ = *from++;
124            continue;
125          }
126        } else {
127          *to++ = *from++;
128          continue;
129        }
130      } else {
131        ptr = to;
132        for (from++; (isalnum(*from) || *from == '_') && ptr < endto; from++)
133          *ptr++ = *from;
134        *ptr = '\0';
135      }
136      if (*to == '\0')
137        *to++ = '$';
138      else if ((env = getenv(to)) != NULL) {
139        strncpy(to, env, endto - to);
140        *endto = '\0';
141        to += strlen(to);
142      }
143    } else
144      *to++ = *from++;
145  }
146  while (to > startto) {
147    to--;
148    if (!issep(*to)) {
149      to++;
150      break;
151    }
152  }
153  *to = '\0';
154}
155
156#define CTRL_UNKNOWN (0)
157#define CTRL_INCLUDE (1)
158
159static int
160DecodeCtrlCommand(char *line, char *arg)
161{
162  if (!strncasecmp(line, "include", 7) && issep(line[7])) {
163    InterpretArg(line+8, arg);
164    return CTRL_INCLUDE;
165  }
166  return CTRL_UNKNOWN;
167}
168
169static int userok;
170
171int
172AllowUsers(struct cmdtab const *list, int argc, char **argv)
173{
174  int f;
175  char *user;
176
177  userok = 0;
178  user = getlogin();
179  if (user && *user)
180    for (f = 0; f < argc; f++)
181      if (!strcmp("*", argv[f]) || !strcmp(user, argv[f])) {
182        userok = 1;
183        break;
184      }
185
186  return 0;
187}
188
189static struct {
190  int mode;
191  char *name;
192} modes[] = {
193  { MODE_INTER, "interactive" },
194  { MODE_AUTO, "auto" },
195  { MODE_DIRECT, "direct" },
196  { MODE_DEDICATED, "dedicated" },
197  { MODE_DDIAL, "ddial" },
198  { MODE_BACKGROUND, "background" },
199  { ~0, "*" },
200  { 0, 0 }
201};
202
203static int modeok;
204
205int
206AllowModes(struct cmdtab const *list, int argc, char **argv)
207{
208  int f;
209  int m;
210  int allowed;
211
212  allowed = 0;
213  for (f = 0; f < argc; f++) {
214    for (m = 0; modes[m].mode; m++)
215      if (!strcasecmp(modes[m].name, argv[f])) {
216        allowed |= modes[m].mode;
217        break;
218      }
219    if (modes[m].mode == 0)
220      LogPrintf(LogWARN, "%s: Invalid mode\n", argv[f]);
221  }
222
223  modeok = (mode | allowed) == allowed ? 1 : 0;
224  return 0;
225}
226
227static int
228ReadSystem(const char *name, const char *file, int doexec)
229{
230  FILE *fp;
231  char *cp, *wp;
232  int n, len;
233  u_char olauth;
234  char line[LINE_LEN];
235  char filename[200];
236  int linenum;
237  int argc;
238  char **argv;
239  int allowcmd;
240
241  if (*file == '/')
242    snprintf(filename, sizeof filename, "%s", file);
243  else
244    snprintf(filename, sizeof filename, "%s/%s", _PATH_PPP, file);
245  fp = ID0fopen(filename, "r");
246  if (fp == NULL) {
247    LogPrintf(LogDEBUG, "ReadSystem: Can't open %s.\n", filename);
248    return (-1);
249  }
250  LogPrintf(LogDEBUG, "ReadSystem: Checking %s (%s).\n", name, filename);
251
252  linenum = 0;
253  while (fgets(line, sizeof(line), fp)) {
254    linenum++;
255    cp = line;
256    switch (*cp) {
257    case '#':			/* comment */
258      break;
259    case ' ':
260    case '\t':
261      break;
262    default:
263      wp = strpbrk(cp, ":\n");
264      if (wp == NULL) {
265	LogPrintf(LogWARN, "Bad rule in %s (line %d) - missing colon.\n",
266		  filename, linenum);
267	ServerClose();
268	exit(1);
269      }
270      *wp = '\0';
271      if (*cp == '!') {
272        char arg[LINE_LEN];
273        switch (DecodeCtrlCommand(cp+1, arg)) {
274        case CTRL_INCLUDE:
275          LogPrintf(LogCOMMAND, "%s: Including \"%s\"\n", filename, arg);
276          n = ReadSystem(name, arg, doexec);
277          LogPrintf(LogCOMMAND, "%s: Done include of \"%s\"\n", filename, arg);
278          if (!n)
279            return 0;	/* got it */
280          break;
281        default:
282          LogPrintf(LogCOMMAND, "%s: %s: Invalid command\n", name, cp);
283          break;
284        }
285      } else if (strcmp(cp, name) == 0) {
286	while (fgets(line, sizeof(line), fp)) {
287	  cp = line;
288          if (issep(*cp)) {
289	    n = strspn(cp, " \t");
290	    cp += n;
291            len = strlen(cp);
292            if (!len)
293              continue;
294            if (cp[len-1] == '\n')
295              cp[--len] = '\0';
296            if (!len)
297              continue;
298            InterpretCommand(cp, len, &argc, &argv);
299            allowcmd = argc > 0 && !strcasecmp(*argv, "allow");
300            if ((!doexec && allowcmd) || (doexec && !allowcmd)) {
301	      LogPrintf(LogCOMMAND, "%s: %s\n", name, cp);
302	      olauth = VarLocalAuth;
303	      if (VarLocalAuth == LOCAL_NO_AUTH)
304	        VarLocalAuth = LOCAL_AUTH;
305	      RunCommand(argc, argv, 0);
306	      VarLocalAuth = olauth;
307	    }
308	  } else if (*cp == '#') {
309	    continue;
310	  } else
311	    break;
312	}
313	fclose(fp);
314	return (0);
315      }
316      break;
317    }
318  }
319  fclose(fp);
320  return -1;
321}
322
323int
324ValidSystem(const char *name)
325{
326  if (ID0realuid() == 0)
327    return userok = modeok = 1;
328  userok = 0;
329  modeok = 1;
330  ReadSystem("default", CONFFILE, 0);
331  if (name != NULL)
332    ReadSystem(name, CONFFILE, 0);
333  return userok && modeok;
334}
335
336int
337SelectSystem(const char *name, const char *file)
338{
339  userok = modeok = 1;
340  return ReadSystem(name, file, 1);
341}
342
343int
344LoadCommand(struct cmdtab const * list, int argc, char **argv)
345{
346  char *name;
347
348  if (argc > 0)
349    name = *argv;
350  else
351    name = "default";
352
353  if (!ValidSystem(name))
354    LogPrintf(LogERROR, "%s: Label not allowed\n", name);
355  else if (SelectSystem(name, CONFFILE) < 0) {
356    LogPrintf(LogWARN, "%s: not found.\n", name);
357    return -1;
358  } else
359    SetLabel(argc ? name : NULL);
360  return 0;
361}
362
363int
364SaveCommand(struct cmdtab const *list, int argc, char **argv)
365{
366  LogPrintf(LogWARN, "save command is not implemented (yet).\n");
367  return 1;
368}
369