2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
3 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
4 * Internet Initiative Japan, Inc (IIJ)
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * $FreeBSD: src/usr.sbin/ppp/systems.c,v 1.58.2.7 2002/09/01 02:12:32 brian Exp $
31 #include <sys/param.h>
46 #define issep(ch) ((ch) == ' ' || (ch) == '\t')
49 OpenSecret(const char *file)
54 snprintf(line, sizeof line, "%s/%s", PPP_CONFDIR, file);
55 fp = ID0fopen(line, "r");
57 log_Printf(LogWARN, "OpenSecret: Can't open %s.\n", line);
67 /* Move string from ``from'' to ``to'', interpreting ``~'' and $.... */
69 InterpretArg(const char *from, char *to)
71 char *ptr, *startto, *endto;
78 endto = to + LINE_LEN - 1;
83 while (*from != '\0') {
93 break; /* Swallow the escapes */
96 *to++ = '\\'; /* Pass the escapes on, maybe skipping \# */
102 if (from[1] == '$') {
103 *to = '\0'; /* For an empty var name below */
105 } else if (from[1] == '{') {
106 ptr = strchr(from+2, '}');
108 len = ptr - from - 2;
109 if (endto - to < len )
112 strncpy(to, from+2, len);
125 for (from++; (isalnum(*from) || *from == '_') && ptr < endto; from++)
131 else if ((env = getenv(to)) != NULL) {
132 strncpy(to, env, endto - to);
139 ptr = strchr(++from, '/');
140 len = ptr ? ptr - from : strlen(from);
142 pwd = getpwuid(ID0realuid());
144 strncpy(to, from, len);
151 strncpy(to, pwd->pw_dir, endto - to);
165 while (to > startto) {
177 #define CTRL_UNKNOWN (0)
178 #define CTRL_INCLUDE (1)
181 DecodeCtrlCommand(char *line, char *arg)
185 if (!strncasecmp(line, "include", 7) && issep(line[7])) {
186 end = InterpretArg(line+8, arg);
187 if (*end && *end != '#')
188 log_Printf(LogWARN, "usage: !include filename\n");
196 * Initialised in system_IsValid(), set in ReadSystem(),
197 * used by system_IsValid()
204 AllowUsers(struct cmdargs const *arg)
206 /* arg->bundle may be NULL (see system_IsValid()) ! */
213 pwd = getpwuid(ID0realuid());
215 for (f = arg->argn; f < arg->argc; f++)
216 if (!strcmp("*", arg->argv[f]) || !strcmp(pwd->pw_name, arg->argv[f])) {
226 AllowModes(struct cmdargs const *arg)
228 /* arg->bundle may be NULL (see system_IsValid()) ! */
229 int f, mode, allowed;
232 for (f = arg->argn; f < arg->argc; f++) {
233 mode = Nam2mode(arg->argv[f]);
234 if (mode == PHYS_NONE || mode == PHYS_ALL)
235 log_Printf(LogWARN, "allow modes: %s: Invalid mode\n", arg->argv[f]);
240 modeok = modereq & allowed ? 1 : 0;
250 while (len && (line[len-1] == '\n' || line[len-1] == '\r' ||
264 xgets(char *buf, int buflen, FILE *fp)
269 while (fgets(buf, buflen-1, fp)) {
271 buf[buflen-1] = '\0';
273 while (len && (buf[len-1] == '\n' || buf[len-1] == '\r'))
275 if (len && buf[len-1] == '\\') {
278 if (!buflen) /* No buffer space */
286 /* Values for ``how'' in ReadSystem */
287 #define SYSTEM_EXISTS 1
288 #define SYSTEM_VALIDATE 2
289 #define SYSTEM_EXEC 3
292 GetLabel(char *line, const char *filename, int linenum)
297 argc = MakeArgs(line, argv, MAXARGS, PARSE_REDUCE);
299 if (argc == 2 && !strcmp(argv[1], ":"))
302 if (argc != 1 || (len = strlen(argv[0])) < 2 || argv[0][len-1] != ':') {
303 log_Printf(LogWARN, "Bad label in %s (line %d) - missing colon\n",
307 argv[0][len-1] = '\0'; /* Lose the ':' */
312 /* Returns -2 for ``file not found'' and -1 for ``label not found'' */
315 ReadSystem(struct bundle *bundle, const char *name, const char *file,
316 struct prompt *prompt, struct datalink *cx, int how)
322 char filename[PATH_MAX];
332 snprintf(filename, sizeof filename, "%s", file);
334 snprintf(filename, sizeof filename, "%s/%s", PPP_CONFDIR, file);
335 fp = ID0fopen(filename, "r");
337 log_Printf(LogDEBUG, "ReadSystem: Can't open %s.\n", filename);
340 log_Printf(LogDEBUG, "ReadSystem: Checking %s (%s).\n", name, filename);
343 while ((n = xgets(line, sizeof line, fp))) {
351 case '\0': /* empty/comment */
355 switch (DecodeCtrlCommand(cp+1, arg)) {
357 log_Printf(LogCOMMAND, "%s: Including \"%s\"\n", filename, arg);
358 n = ReadSystem(bundle, name, arg, prompt, cx, how);
359 log_Printf(LogCOMMAND, "%s: Done include of \"%s\"\n", filename, arg);
362 return 0; /* got it */
366 log_Printf(LogWARN, "%s: %s: Invalid command\n", filename, cp);
372 if ((cp = GetLabel(cp, filename, linenum)) == NULL)
375 if (strcmp(cp, name) == 0) {
376 /* We're in business */
377 if (how == SYSTEM_EXISTS) {
381 while ((n = xgets(line, sizeof line, fp))) {
383 indent = issep(*line);
386 if (*cp == '\0') /* empty / comment */
389 if (!indent) { /* start of next section */
390 if (*cp != '!' && how == SYSTEM_EXEC)
391 cp = GetLabel(cp, filename, linenum);
396 if ((argc = command_Expand_Interpret(cp, len, argv, cp - line)) < 0)
397 log_Printf(LogWARN, "%s: %d: Syntax error\n", filename, linenum);
399 allowcmd = argc > 0 && !strcasecmp(argv[0], "allow");
400 if ((how != SYSTEM_EXEC && allowcmd) ||
401 (how == SYSTEM_EXEC && !allowcmd)) {
403 * Disable any context so that warnings are given to everyone,
406 op = log_PromptContext;
407 log_PromptContext = NULL;
408 command_Run(bundle, argc, (char const *const *)argv, prompt,
410 log_PromptContext = op;
415 fclose(fp); /* everything read - get out */
426 system_IsValid(const char *name, struct prompt *prompt, int mode)
429 * Note: The ReadSystem() calls only result in calls to the Allow*
430 * functions. arg->bundle will be set to NULL for these commands !
435 def = !strcmp(name, "default");
436 how = ID0realuid() == 0 ? SYSTEM_EXISTS : SYSTEM_VALIDATE;
441 rs = ReadSystem(NULL, "default", CONFFILE, prompt, NULL, how);
448 rs = 0; /* we don't care that ``default'' doesn't exist */
451 rs = ReadSystem(NULL, name, CONFFILE, prompt, NULL, how);
454 return "Configuration label not found";
457 return PPP_CONFDIR "/" CONFFILE " : File not found";
463 if (how == SYSTEM_EXISTS)
467 return "User access denied";
470 return "Mode denied for this label";
476 system_Select(struct bundle *bundle, const char *name, const char *file,
477 struct prompt *prompt, struct datalink *cx)
481 return ReadSystem(bundle, name, file, prompt, cx, SYSTEM_EXEC);