systems.c revision 32663
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.34 1997/12/24 09:29:17 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 "pathnames.h"
43#include "vars.h"
44#include "server.h"
45#include "systems.h"
46
47#define issep(ch) ((ch) == ' ' || (ch) == '\t')
48
49FILE *
50OpenSecret(const char *file)
51{
52  FILE *fp;
53  char line[100];
54
55  snprintf(line, sizeof line, "%s/%s", _PATH_PPP, file);
56  fp = ID0fopen(line, "r");
57  if (fp == NULL)
58    LogPrintf(LogWARN, "OpenSecret: Can't open %s.\n", line);
59  return (fp);
60}
61
62void
63CloseSecret(FILE * fp)
64{
65  fclose(fp);
66}
67
68/* Move string from ``from'' to ``to'', interpreting ``~'' and $.... */
69static void
70InterpretArg(char *from, char *to)
71{
72  const char *env;
73  char *ptr, *startto, *endto;
74  int len;
75
76  startto = to;
77  endto = to + LINE_LEN - 1;
78
79  while(issep(*from))
80    from++;
81  if (*from == '~') {
82    ptr = strchr(++from, '/');
83    len = ptr ? ptr - from : strlen(from);
84    if (len == 0) {
85      if ((env = getenv("HOME")) == NULL)
86        env = _PATH_PPP;
87      strncpy(to, env, endto - to);
88    } else {
89      struct passwd *pwd;
90
91      strncpy(to, from, len);
92      to[len] = '\0';
93      pwd = getpwnam(to);
94      if (pwd)
95        strncpy(to, pwd->pw_dir, endto-to);
96      else
97        strncpy(to, _PATH_PPP, endto - to);
98      endpwent();
99    }
100    *endto = '\0';
101    to += strlen(to);
102    from += len;
103  }
104
105  while (to < endto && *from != '\0') {
106    if (*from == '$') {
107      if (from[1] == '$') {
108        *to = '\0';	/* For an empty var name below */
109        from += 2;
110      } else if (from[1] == '{') {
111        ptr = strchr(from+2, '}');
112        if (ptr) {
113          len = ptr - from - 2;
114          if (endto - to < len )
115            len = endto - to;
116          if (len) {
117            strncpy(to, from+2, len);
118            to[len] = '\0';
119            from = ptr+1;
120          } else {
121            *to++ = *from++;
122            continue;
123          }
124        } else {
125          *to++ = *from++;
126          continue;
127        }
128      } else {
129        ptr = to;
130        for (from++; (isalnum(*from) || *from == '_') && ptr < endto; from++)
131          *ptr++ = *from;
132        *ptr = '\0';
133      }
134      if (*to == '\0')
135        *to++ = '$';
136      else if ((env = getenv(to)) != NULL) {
137        strncpy(to, env, endto - to);
138        *endto = '\0';
139        to += strlen(to);
140      }
141    } else
142      *to++ = *from++;
143  }
144  while (to > startto) {
145    to--;
146    if (!issep(*to)) {
147      to++;
148      break;
149    }
150  }
151  *to = '\0';
152}
153
154#define CTRL_UNKNOWN (0)
155#define CTRL_INCLUDE (1)
156
157static int
158DecodeCtrlCommand(char *line, char *arg)
159{
160  if (!strncasecmp(line, "include", 7) && issep(line[7])) {
161    InterpretArg(line+8, arg);
162    return CTRL_INCLUDE;
163  }
164  return CTRL_UNKNOWN;
165}
166
167static int userok;
168
169int
170AllowUsers(struct cmdargs const *arg)
171{
172  int f;
173  char *user;
174
175  userok = 0;
176  user = getlogin();
177  if (user && *user)
178    for (f = 0; 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
187static struct {
188  int mode;
189  const char *name;
190} modes[] = {
191  { MODE_INTER, "interactive" },
192  { MODE_AUTO, "auto" },
193  { MODE_DIRECT, "direct" },
194  { MODE_DEDICATED, "dedicated" },
195  { MODE_DDIAL, "ddial" },
196  { MODE_BACKGROUND, "background" },
197  { ~0, "*" },
198  { 0, 0 }
199};
200
201static int modeok;
202
203int
204AllowModes(struct cmdargs const *arg)
205{
206  int f;
207  int m;
208  int allowed;
209
210  allowed = 0;
211  for (f = 0; f < arg->argc; f++) {
212    for (m = 0; modes[m].mode; m++)
213      if (!strcasecmp(modes[m].name, arg->argv[f])) {
214        allowed |= modes[m].mode;
215        break;
216      }
217    if (modes[m].mode == 0)
218      LogPrintf(LogWARN, "allow modes: %s: Invalid mode\n", arg->argv[f]);
219  }
220
221  modeok = (mode | allowed) == allowed ? 1 : 0;
222  return 0;
223}
224
225static int
226ReadSystem(const char *name, const char *file, int doexec)
227{
228  FILE *fp;
229  char *cp, *wp;
230  int n, len;
231  u_char olauth;
232  char line[LINE_LEN];
233  char filename[MAXPATHLEN];
234  int linenum;
235  int argc;
236  char **argv;
237  int allowcmd;
238
239  if (*file == '/')
240    snprintf(filename, sizeof filename, "%s", file);
241  else
242    snprintf(filename, sizeof filename, "%s/%s", _PATH_PPP, file);
243  fp = ID0fopen(filename, "r");
244  if (fp == NULL) {
245    LogPrintf(LogDEBUG, "ReadSystem: Can't open %s.\n", filename);
246    return (-1);
247  }
248  LogPrintf(LogDEBUG, "ReadSystem: Checking %s (%s).\n", name, filename);
249
250  linenum = 0;
251  while (fgets(line, sizeof line, fp)) {
252    linenum++;
253    cp = line;
254    switch (*cp) {
255    case '#':			/* comment */
256      break;
257    case ' ':
258    case '\t':
259      break;
260    default:
261      wp = strpbrk(cp, ":\n");
262      if (wp == NULL) {
263	LogPrintf(LogWARN, "Bad rule in %s (line %d) - missing colon.\n",
264		  filename, linenum);
265	ServerClose();
266	exit(1);
267      }
268      *wp = '\0';
269      if (*cp == '!') {
270        char arg[LINE_LEN];
271        switch (DecodeCtrlCommand(cp+1, arg)) {
272        case CTRL_INCLUDE:
273          LogPrintf(LogCOMMAND, "%s: Including \"%s\"\n", filename, arg);
274          n = ReadSystem(name, arg, doexec);
275          LogPrintf(LogCOMMAND, "%s: Done include of \"%s\"\n", filename, arg);
276          if (!n)
277            return 0;	/* got it */
278          break;
279        default:
280          LogPrintf(LogWARN, "%s: %s: Invalid command\n", filename, cp);
281          break;
282        }
283      } else if (strcmp(cp, name) == 0) {
284	while (fgets(line, sizeof line, fp)) {
285	  cp = line;
286          if (issep(*cp)) {
287	    n = strspn(cp, " \t");
288	    cp += n;
289            len = strlen(cp);
290            if (!len || *cp == '#')
291              continue;
292            if (cp[len-1] == '\n')
293              cp[--len] = '\0';
294            if (!len)
295              continue;
296            InterpretCommand(cp, len, &argc, &argv);
297            allowcmd = argc > 0 && !strcasecmp(*argv, "allow");
298            if ((!doexec && allowcmd) || (doexec && !allowcmd)) {
299	      olauth = VarLocalAuth;
300	      if (VarLocalAuth == LOCAL_NO_AUTH)
301	        VarLocalAuth = LOCAL_AUTH;
302	      RunCommand(argc, (char const *const *)argv, name);
303	      VarLocalAuth = olauth;
304	    }
305	  } else if (*cp == '#' || *cp == '\n' || *cp == '\0') {
306	    continue;
307	  } else
308	    break;
309	}
310	fclose(fp);
311	return (0);
312      }
313      break;
314    }
315  }
316  fclose(fp);
317  return -1;
318}
319
320int
321ValidSystem(const char *name)
322{
323  if (ID0realuid() == 0)
324    return userok = modeok = 1;
325  userok = 0;
326  modeok = 1;
327  ReadSystem("default", CONFFILE, 0);
328  if (name != NULL)
329    ReadSystem(name, CONFFILE, 0);
330  return userok && modeok;
331}
332
333int
334SelectSystem(const char *name, const char *file)
335{
336  userok = modeok = 1;
337  return ReadSystem(name, file, 1);
338}
339
340int
341LoadCommand(struct cmdargs const *arg)
342{
343  const char *name;
344
345  if (arg->argc > 0)
346    name = *arg->argv;
347  else
348    name = "default";
349
350  if (!ValidSystem(name)) {
351    LogPrintf(LogERROR, "%s: Label not allowed\n", name);
352    return 1;
353  } else if (SelectSystem(name, CONFFILE) < 0) {
354    LogPrintf(LogWARN, "%s: label not found.\n", name);
355    return -1;
356  } else
357    SetLabel(arg->argc ? name : NULL);
358  return 0;
359}
360
361int
362SaveCommand(struct cmdargs const *arg)
363{
364  LogPrintf(LogWARN, "save command is not implemented (yet).\n");
365  return 1;
366}
367