systems.c revision 31822
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.29 1997/12/15 20:21:47 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 "command.h"
35#include "mbuf.h"
36#include "log.h"
37#include "id.h"
38#include "defs.h"
39#include "timer.h"
40#include "fsm.h"
41#include "loadalias.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(const 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 cmdargs const *arg)
173{
174  int f;
175  char *user;
176
177  userok = 0;
178  user = getlogin();
179  if (user && *user)
180    for (f = 0; f < arg->argc; f++)
181      if (!strcmp("*", arg->argv[f]) || !strcmp(user, arg->argv[f])) {
182        userok = 1;
183        break;
184      }
185
186  return 0;
187}
188
189static struct {
190  int mode;
191  const 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 cmdargs const *arg)
207{
208  int f;
209  int m;
210  int allowed;
211
212  allowed = 0;
213  for (f = 0; f < arg->argc; f++) {
214    for (m = 0; modes[m].mode; m++)
215      if (!strcasecmp(modes[m].name, arg->argv[f])) {
216        allowed |= modes[m].mode;
217        break;
218      }
219    if (modes[m].mode == 0)
220      LogPrintf(LogWARN, "allow modes: %s: Invalid mode\n", arg->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(LogWARN, "%s: %s: Invalid command\n", filename, 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	      olauth = VarLocalAuth;
302	      if (VarLocalAuth == LOCAL_NO_AUTH)
303	        VarLocalAuth = LOCAL_AUTH;
304	      RunCommand(argc, (char const *const *)argv, name);
305	      VarLocalAuth = olauth;
306	    }
307	  } else if (*cp == '#' || *cp == '\n' || *cp == '\0') {
308	    continue;
309	  } else
310	    break;
311	}
312	fclose(fp);
313	return (0);
314      }
315      break;
316    }
317  }
318  fclose(fp);
319  return -1;
320}
321
322int
323ValidSystem(const char *name)
324{
325  if (ID0realuid() == 0)
326    return userok = modeok = 1;
327  userok = 0;
328  modeok = 1;
329  ReadSystem("default", CONFFILE, 0);
330  if (name != NULL)
331    ReadSystem(name, CONFFILE, 0);
332  return userok && modeok;
333}
334
335int
336SelectSystem(const char *name, const char *file)
337{
338  userok = modeok = 1;
339  return ReadSystem(name, file, 1);
340}
341
342int
343LoadCommand(struct cmdargs const *arg)
344{
345  const char *name;
346
347  if (arg->argc > 0)
348    name = *arg->argv;
349  else
350    name = "default";
351
352  if (!ValidSystem(name)) {
353    LogPrintf(LogERROR, "%s: Label not allowed\n", name);
354    return 1;
355  } else if (SelectSystem(name, CONFFILE) < 0) {
356    LogPrintf(LogWARN, "%s: label not found.\n", name);
357    return -1;
358  } else
359    SetLabel(arg->argc ? name : NULL);
360  return 0;
361}
362
363int
364SaveCommand(struct cmdargs const *arg)
365{
366  LogPrintf(LogWARN, "save command is not implemented (yet).\n");
367  return 1;
368}
369