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 $
29 * $DragonFly: src/usr.sbin/ppp/systems.c,v 1.3 2008/03/11 10:53:07 hasso Exp $
32 #include <sys/param.h>
47 #define issep(ch) ((ch) == ' ' || (ch) == '\t')
50 OpenSecret(const char *file
)
55 snprintf(line
, sizeof line
, "%s/%s", PPP_CONFDIR
, file
);
56 fp
= ID0fopen(line
, "r");
58 log_Printf(LogWARN
, "OpenSecret: Can't open %s.\n", line
);
69 * Move string from ``from'' to ``to'', interpreting ``~'' and $....
70 * Returns NULL if string expansion failed due to lack of buffer space.
73 InterpretArg(const char *from
, char *to
, size_t tosiz
)
75 char *ptr
, *startto
, *endto
;
82 endto
= to
+ tosiz
- 1;
87 while (*from
!= '\0') {
99 break; /* Swallow the escapes */
102 *to
++ = '\\'; /* Pass the escapes on, maybe skipping \# */
110 if (from
[1] == '$') {
111 *to
= '\0'; /* For an empty var name below */
113 } else if (from
[1] == '{') {
114 ptr
= strchr(from
+2, '}');
116 len
= ptr
- from
- 2;
117 if (endto
- to
< len
)
120 strncpy(to
, from
+2, len
);
133 for (from
++; (isalnum(*from
) || *from
== '_') && ptr
< endto
; from
++)
141 else if ((env
= getenv(to
)) != NULL
) {
142 if (endto
- to
< strlen(env
))
144 strncpy(to
, env
, endto
- to
);
151 ptr
= strchr(++from
, '/');
152 len
= ptr
? ptr
- from
: strlen(from
);
154 pwd
= getpwuid(ID0realuid());
156 if (endto
- to
< len
)
158 strncpy(to
, from
, len
);
167 if (endto
- to
< strlen(pwd
->pw_dir
))
169 strncpy(to
, pwd
->pw_dir
, endto
- to
);
183 while (to
> startto
) {
195 #define CTRL_UNKNOWN (0)
196 #define CTRL_INCLUDE (1)
199 DecodeCtrlCommand(char *line
, char *arg
, size_t argsiz
)
203 if (!strncasecmp(line
, "include", 7) && issep(line
[7])) {
204 end
= InterpretArg(line
+8, arg
, argsiz
);
206 log_Printf(LogWARN
, "Failed to expand command '%s': too long for the "
207 "destination buffer\n", line
);
210 if (*end
&& *end
!= '#')
211 log_Printf(LogWARN
, "usage: !include filename\n");
219 * Initialised in system_IsValid(), set in ReadSystem(),
220 * used by system_IsValid()
227 AllowUsers(struct cmdargs
const *arg
)
229 /* arg->bundle may be NULL (see system_IsValid()) ! */
236 pwd
= getpwuid(ID0realuid());
238 for (f
= arg
->argn
; f
< arg
->argc
; f
++)
239 if (!strcmp("*", arg
->argv
[f
]) || !strcmp(pwd
->pw_name
, arg
->argv
[f
])) {
249 AllowModes(struct cmdargs
const *arg
)
251 /* arg->bundle may be NULL (see system_IsValid()) ! */
252 int f
, mode
, allowed
;
255 for (f
= arg
->argn
; f
< arg
->argc
; f
++) {
256 mode
= Nam2mode(arg
->argv
[f
]);
257 if (mode
== PHYS_NONE
|| mode
== PHYS_ALL
)
258 log_Printf(LogWARN
, "allow modes: %s: Invalid mode\n", arg
->argv
[f
]);
263 modeok
= modereq
& allowed
? 1 : 0;
273 while (len
&& (line
[len
-1] == '\n' || line
[len
-1] == '\r' ||
287 xgets(char *buf
, int buflen
, FILE *fp
)
292 while (fgets(buf
, buflen
-1, fp
)) {
294 buf
[buflen
-1] = '\0';
296 while (len
&& (buf
[len
-1] == '\n' || buf
[len
-1] == '\r'))
298 if (len
&& buf
[len
-1] == '\\') {
301 if (!buflen
) /* No buffer space */
309 /* Values for ``how'' in ReadSystem */
310 #define SYSTEM_EXISTS 1
311 #define SYSTEM_VALIDATE 2
312 #define SYSTEM_EXEC 3
315 GetLabel(char *line
, const char *filename
, int linenum
)
320 argc
= MakeArgs(line
, argv
, MAXARGS
, PARSE_REDUCE
);
322 if (argc
== 2 && !strcmp(argv
[1], ":"))
325 if (argc
!= 1 || (len
= strlen(argv
[0])) < 2 || argv
[0][len
-1] != ':') {
326 log_Printf(LogWARN
, "Bad label in %s (line %d) - missing colon\n",
330 argv
[0][len
-1] = '\0'; /* Lose the ':' */
335 /* Returns -2 for ``file not found'' and -1 for ``label not found'' */
338 ReadSystem(struct bundle
*bundle
, const char *name
, const char *file
,
339 struct prompt
*prompt
, struct datalink
*cx
, int how
)
345 char filename
[PATH_MAX
];
355 snprintf(filename
, sizeof filename
, "%s", file
);
357 snprintf(filename
, sizeof filename
, "%s/%s", PPP_CONFDIR
, file
);
358 fp
= ID0fopen(filename
, "r");
360 log_Printf(LogDEBUG
, "ReadSystem: Can't open %s.\n", filename
);
363 log_Printf(LogDEBUG
, "ReadSystem: Checking %s (%s).\n", name
, filename
);
366 while ((n
= xgets(line
, sizeof line
, fp
))) {
374 case '\0': /* empty/comment */
378 switch (DecodeCtrlCommand(cp
+1, arg
, LINE_LEN
)) {
380 log_Printf(LogCOMMAND
, "%s: Including \"%s\"\n", filename
, arg
);
381 n
= ReadSystem(bundle
, name
, arg
, prompt
, cx
, how
);
382 log_Printf(LogCOMMAND
, "%s: Done include of \"%s\"\n", filename
, arg
);
385 return 0; /* got it */
389 log_Printf(LogWARN
, "%s: %s: Invalid command\n", filename
, cp
);
395 if ((cp
= GetLabel(cp
, filename
, linenum
)) == NULL
)
398 if (strcmp(cp
, name
) == 0) {
399 /* We're in business */
400 if (how
== SYSTEM_EXISTS
) {
404 while ((n
= xgets(line
, sizeof line
, fp
))) {
406 indent
= issep(*line
);
409 if (*cp
== '\0') /* empty / comment */
412 if (!indent
) { /* start of next section */
413 if (*cp
!= '!' && how
== SYSTEM_EXEC
)
414 cp
= GetLabel(cp
, filename
, linenum
);
419 if ((argc
= command_Expand_Interpret(cp
, len
, argv
, cp
- line
)) < 0)
420 log_Printf(LogWARN
, "%s: %d: Syntax error\n", filename
, linenum
);
422 allowcmd
= argc
> 0 && !strcasecmp(argv
[0], "allow");
423 if ((how
!= SYSTEM_EXEC
&& allowcmd
) ||
424 (how
== SYSTEM_EXEC
&& !allowcmd
)) {
426 * Disable any context so that warnings are given to everyone,
429 op
= log_PromptContext
;
430 log_PromptContext
= NULL
;
431 command_Run(bundle
, argc
, (char const *const *)argv
, prompt
,
433 log_PromptContext
= op
;
438 fclose(fp
); /* everything read - get out */
449 system_IsValid(const char *name
, struct prompt
*prompt
, int mode
)
452 * Note: The ReadSystem() calls only result in calls to the Allow*
453 * functions. arg->bundle will be set to NULL for these commands !
458 def
= !strcmp(name
, "default");
459 how
= ID0realuid() == 0 ? SYSTEM_EXISTS
: SYSTEM_VALIDATE
;
464 rs
= ReadSystem(NULL
, "default", CONFFILE
, prompt
, NULL
, how
);
471 rs
= 0; /* we don't care that ``default'' doesn't exist */
474 rs
= ReadSystem(NULL
, name
, CONFFILE
, prompt
, NULL
, how
);
477 return "Configuration label not found";
480 return PPP_CONFDIR
"/" CONFFILE
" : File not found";
486 if (how
== SYSTEM_EXISTS
)
490 return "User access denied";
493 return "Mode denied for this label";
499 system_Select(struct bundle
*bundle
, const char *name
, const char *file
,
500 struct prompt
*prompt
, struct datalink
*cx
)
504 return ReadSystem(bundle
, name
, file
, prompt
, cx
, SYSTEM_EXEC
);