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
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
;
79 endto
= to
+ LINE_LEN
- 1;
84 while (*from
!= '\0') {
94 break; /* Swallow the escapes */
97 *to
++ = '\\'; /* Pass the escapes on, maybe skipping \# */
103 if (from
[1] == '$') {
104 *to
= '\0'; /* For an empty var name below */
106 } else if (from
[1] == '{') {
107 ptr
= strchr(from
+2, '}');
109 len
= ptr
- from
- 2;
110 if (endto
- to
< (int)len
)
113 strncpy(to
, from
+2, len
);
126 for (from
++; (isalnum(*from
) || *from
== '_') && ptr
< endto
; from
++)
132 else if ((env
= getenv(to
)) != NULL
) {
133 strncpy(to
, env
, endto
- to
);
140 ptr
= strchr(++from
, '/');
141 len
= ptr
? (size_t)(ptr
- from
) : strlen(from
);
143 pwd
= getpwuid(ID0realuid());
145 strncpy(to
, from
, len
);
152 strncpy(to
, pwd
->pw_dir
, endto
- to
);
166 while (to
> startto
) {
178 #define CTRL_UNKNOWN (0)
179 #define CTRL_INCLUDE (1)
182 DecodeCtrlCommand(char *line
, char *arg
)
186 if (!strncasecmp(line
, "include", 7) && issep(line
[7])) {
187 end
= InterpretArg(line
+8, arg
);
188 if (*end
&& *end
!= '#')
189 log_Printf(LogWARN
, "usage: !include filename\n");
197 * Initialised in system_IsValid(), set in ReadSystem(),
198 * used by system_IsValid()
205 AllowUsers(struct cmdargs
const *arg
)
207 /* arg->bundle may be NULL (see system_IsValid()) ! */
214 pwd
= getpwuid(ID0realuid());
216 for (f
= arg
->argn
; f
< arg
->argc
; f
++)
217 if (!strcmp("*", arg
->argv
[f
]) || !strcmp(pwd
->pw_name
, arg
->argv
[f
])) {
227 AllowModes(struct cmdargs
const *arg
)
229 /* arg->bundle may be NULL (see system_IsValid()) ! */
230 int f
, mode
, allowed
;
233 for (f
= arg
->argn
; f
< arg
->argc
; f
++) {
234 mode
= Nam2mode(arg
->argv
[f
]);
235 if (mode
== PHYS_NONE
|| mode
== PHYS_ALL
)
236 log_Printf(LogWARN
, "allow modes: %s: Invalid mode\n", arg
->argv
[f
]);
241 modeok
= modereq
& allowed
? 1 : 0;
251 while (len
&& (line
[len
-1] == '\n' || line
[len
-1] == '\r' ||
265 xgets(char *buf
, int buflen
, FILE *fp
)
270 while (fgets(buf
, buflen
-1, fp
)) {
272 buf
[buflen
-1] = '\0';
274 while (len
&& (buf
[len
-1] == '\n' || buf
[len
-1] == '\r'))
276 if (len
&& buf
[len
-1] == '\\') {
279 if (!buflen
) /* No buffer space */
287 /* Values for ``how'' in ReadSystem */
288 #define SYSTEM_EXISTS 1
289 #define SYSTEM_VALIDATE 2
290 #define SYSTEM_EXEC 3
293 GetLabel(char *line
, const char *filename
, int linenum
)
298 argc
= MakeArgs(line
, argv
, MAXARGS
, PARSE_REDUCE
);
300 if (argc
== 2 && !strcmp(argv
[1], ":"))
303 if (argc
!= 1 || (len
= strlen(argv
[0])) < 2 || argv
[0][len
-1] != ':') {
304 log_Printf(LogWARN
, "Bad label in %s (line %d) - missing colon\n",
308 argv
[0][len
-1] = '\0'; /* Lose the ':' */
313 /* Returns -2 for ``file not found'' and -1 for ``label not found'' */
316 ReadSystem(struct bundle
*bundle
, const char *name
, const char *file
,
317 struct prompt
*prompt
, struct datalink
*cx
, int how
)
323 char filename
[PATH_MAX
];
333 snprintf(filename
, sizeof filename
, "%s", file
);
335 snprintf(filename
, sizeof filename
, "%s/%s", PPP_CONFDIR
, file
);
336 fp
= ID0fopen(filename
, "r");
338 log_Printf(LogDEBUG
, "ReadSystem: Can't open %s.\n", filename
);
341 log_Printf(LogDEBUG
, "ReadSystem: Checking %s (%s).\n", name
, filename
);
344 while ((n
= xgets(line
, sizeof line
, fp
))) {
352 case '\0': /* empty/comment */
356 switch (DecodeCtrlCommand(cp
+1, arg
)) {
358 log_Printf(LogCOMMAND
, "%s: Including \"%s\"\n", filename
, arg
);
359 n
= ReadSystem(bundle
, name
, arg
, prompt
, cx
, how
);
360 log_Printf(LogCOMMAND
, "%s: Done include of \"%s\"\n", filename
, arg
);
363 return 0; /* got it */
367 log_Printf(LogWARN
, "%s: %s: Invalid command\n", filename
, cp
);
373 if ((cp
= GetLabel(cp
, filename
, linenum
)) == NULL
)
376 if (strcmp(cp
, name
) == 0) {
377 /* We're in business */
378 if (how
== SYSTEM_EXISTS
) {
382 while ((n
= xgets(line
, sizeof line
, fp
))) {
384 indent
= issep(*line
);
387 if (*cp
== '\0') /* empty / comment */
390 if (!indent
) { /* start of next section */
391 if (*cp
!= '!' && how
== SYSTEM_EXEC
)
392 cp
= GetLabel(cp
, filename
, linenum
);
397 if ((argc
= command_Expand_Interpret(cp
, len
, argv
, cp
- line
)) < 0)
398 log_Printf(LogWARN
, "%s: %d: Syntax error\n", filename
, linenum
);
400 allowcmd
= argc
> 0 && !strcasecmp(argv
[0], "allow");
401 if ((how
!= SYSTEM_EXEC
&& allowcmd
) ||
402 (how
== SYSTEM_EXEC
&& !allowcmd
)) {
404 * Disable any context so that warnings are given to everyone,
407 op
= log_PromptContext
;
408 log_PromptContext
= NULL
;
409 command_Run(bundle
, argc
, (char const *const *)argv
, prompt
,
411 log_PromptContext
= op
;
416 fclose(fp
); /* everything read - get out */
427 system_IsValid(const char *name
, struct prompt
*prompt
, int mode
)
430 * Note: The ReadSystem() calls only result in calls to the Allow*
431 * functions. arg->bundle will be set to NULL for these commands !
436 def
= !strcmp(name
, "default");
437 how
= ID0realuid() == 0 ? SYSTEM_EXISTS
: SYSTEM_VALIDATE
;
442 rs
= ReadSystem(NULL
, "default", CONFFILE
, prompt
, NULL
, how
);
449 rs
= 0; /* we don't care that ``default'' doesn't exist */
452 rs
= ReadSystem(NULL
, name
, CONFFILE
, prompt
, NULL
, how
);
455 return "Configuration label not found";
458 return PPP_CONFDIR
"/" CONFFILE
" : File not found";
464 if (how
== SYSTEM_EXISTS
)
468 return "User access denied";
471 return "Mode denied for this label";
477 system_Select(struct bundle
*bundle
, const char *name
, const char *file
,
478 struct prompt
*prompt
, struct datalink
*cx
)
482 return ReadSystem(bundle
, name
, file
, prompt
, cx
, SYSTEM_EXEC
);