Skip to content

Commit f5a6fb9

Browse files
authored
Merge pull request #577 from ppp-project/strict
Strict access checks for scripts, secrets files and call option files.
2 parents 3b6c011 + 1793d4c commit f5a6fb9

File tree

5 files changed

+168
-29
lines changed

5 files changed

+168
-29
lines changed

pppd/auth.c

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,7 +1545,8 @@ check_passwd(int unit,
15451545
* Open the file of pap secrets and scan for a suitable secret
15461546
* for authenticating this user.
15471547
*/
1548-
filename = path_upapfile;
1548+
if (!ppp_check_access(path_upapfile, &filename, 0, 0))
1549+
return UPAP_AUTHNAK;
15491550
addrs = opts = NULL;
15501551
ret = UPAP_AUTHNAK;
15511552
f = fopen(filename, "r");
@@ -1587,6 +1588,7 @@ check_passwd(int unit,
15871588
}
15881589
fclose(f);
15891590
}
1591+
free(filename);
15901592

15911593
if (ret == UPAP_AUTHNAK) {
15921594
if (**msg == 0)
@@ -1646,17 +1648,21 @@ null_login(int unit)
16461648
* Open the file of pap secrets and scan for a suitable secret.
16471649
*/
16481650
if (ret <= 0) {
1649-
filename = path_upapfile;
1651+
if (!ppp_check_access(path_upapfile, &filename, 0, 0))
1652+
return 0;
16501653
addrs = NULL;
16511654
f = fopen(filename, "r");
1652-
if (f == NULL)
1655+
if (f == NULL) {
1656+
free(filename);
16531657
return 0;
1658+
}
16541659
check_access(f, filename);
16551660

16561661
i = scan_authfile(f, "", our_name, secret, &addrs, &opts, filename, 0);
16571662
ret = i >= 0 && secret[0] == 0;
16581663
BZERO(secret, sizeof(secret));
16591664
fclose(f);
1665+
free(filename);
16601666
}
16611667

16621668
if (ret)
@@ -1730,14 +1736,18 @@ have_pap_secret(int *lacks_ipp)
17301736
return ret;
17311737
}
17321738

1733-
filename = path_upapfile;
1739+
if (!ppp_check_access(path_upapfile, &filename, 0, 0))
1740+
return 0;
17341741
f = fopen(filename, "r");
1735-
if (f == NULL)
1742+
if (f == NULL) {
1743+
free(filename);
17361744
return 0;
1745+
}
17371746

17381747
ret = scan_authfile(f, (explicit_remote? remote_name: NULL), our_name,
17391748
NULL, &addrs, NULL, filename, 0);
17401749
fclose(f);
1750+
free(filename);
17411751
if (ret >= 0 && !some_ip_ok(addrs)) {
17421752
if (lacks_ipp != 0)
17431753
*lacks_ipp = 1;
@@ -1772,10 +1782,13 @@ have_chap_secret(char *client, char *server,
17721782
}
17731783
}
17741784

1775-
filename = path_chapfile;
1785+
if (!ppp_check_access(path_chapfile, &filename, 0, 0))
1786+
return 0;
17761787
f = fopen(filename, "r");
1777-
if (f == NULL)
1788+
if (f == NULL) {
1789+
free(filename);
17781790
return 0;
1791+
}
17791792

17801793
if (client != NULL && client[0] == 0)
17811794
client = NULL;
@@ -1784,6 +1797,7 @@ have_chap_secret(char *client, char *server,
17841797

17851798
ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0);
17861799
fclose(f);
1800+
free(filename);
17871801
if (ret >= 0 && need_ip && !some_ip_ok(addrs)) {
17881802
if (lacks_ipp != 0)
17891803
*lacks_ipp = 1;
@@ -1810,10 +1824,13 @@ have_srp_secret(char *client, char *server, int need_ip, int *lacks_ipp)
18101824
char *filename;
18111825
struct wordlist *addrs;
18121826

1813-
filename = PPP_PATH_SRPFILE;
1827+
if (!ppp_check_access(PPP_PATH_SRPFILE, &filename, 0, 0))
1828+
return 0;
18141829
f = fopen(filename, "r");
1815-
if (f == NULL)
1830+
if (f == NULL) {
1831+
free(filename);
18161832
return 0;
1833+
}
18171834

18181835
if (client != NULL && client[0] == 0)
18191836
client = NULL;
@@ -1822,6 +1839,7 @@ have_srp_secret(char *client, char *server, int need_ip, int *lacks_ipp)
18221839

18231840
ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0);
18241841
fclose(f);
1842+
free(filename);
18251843
if (ret >= 0 && need_ip && !some_ip_ok(addrs)) {
18261844
if (lacks_ipp != 0)
18271845
*lacks_ipp = 1;
@@ -1858,19 +1876,22 @@ get_secret(int unit, char *client, char *server,
18581876
return 0;
18591877
}
18601878
} else {
1861-
filename = path_chapfile;
1879+
if (!ppp_check_access(path_chapfile, &filename, 0, 0))
1880+
return 0;
18621881
addrs = NULL;
18631882
secbuf[0] = 0;
18641883

18651884
f = fopen(filename, "r");
18661885
if (f == NULL) {
18671886
error("Can't open chap secret file %s: %m", filename);
1887+
free(filename);
18681888
return 0;
18691889
}
18701890
check_access(f, filename);
18711891

18721892
ret = scan_authfile(f, client, server, secbuf, &addrs, &opts, filename, 0);
18731893
fclose(f);
1894+
free(filename);
18741895
if (ret < 0)
18751896
return 0;
18761897

@@ -1912,12 +1933,14 @@ get_srp_secret(int unit, char *client, char *server,
19121933
if (!am_server && passwd[0] != '\0') {
19131934
strlcpy(secret, passwd, MAXWORDLEN);
19141935
} else {
1915-
filename = PPP_PATH_SRPFILE;
1936+
if (!ppp_check_access(PPP_PATH_SRPFILE, &filename, 0, 0))
1937+
return 0;
19161938
addrs = NULL;
19171939

19181940
fp = fopen(filename, "r");
19191941
if (fp == NULL) {
19201942
error("Can't open srp secret file %s: %m", filename);
1943+
free(filename);
19211944
return 0;
19221945
}
19231946
check_access(fp, filename);
@@ -1926,6 +1949,7 @@ get_srp_secret(int unit, char *client, char *server,
19261949
ret = scan_authfile(fp, client, server, secret, &addrs, &opts,
19271950
filename, am_server);
19281951
fclose(fp);
1952+
free(filename);
19291953
if (ret < 0)
19301954
return 0;
19311955

@@ -2304,18 +2328,25 @@ scan_authfile(FILE *f, char *client, char *server,
23042328
* Special syntax: @/pathname means read secret from file.
23052329
*/
23062330
if (word[0] == '@' && word[1] == '/') {
2331+
char *realname;
2332+
23072333
strlcpy(atfile, word+1, sizeof(atfile));
2308-
if ((sf = fopen(atfile, "r")) == NULL) {
2334+
if (!ppp_check_access(atfile, &realname, 0, 0))
2335+
continue;
2336+
if ((sf = fopen(realname, "r")) == NULL) {
23092337
warn("can't open indirect secret file %s", atfile);
2338+
free(realname);
23102339
continue;
23112340
}
23122341
check_access(sf, atfile);
23132342
if (!getword(sf, word, &xxx, atfile)) {
23142343
warn("no secret in indirect secret file %s", atfile);
23152344
fclose(sf);
2345+
free(realname);
23162346
continue;
23172347
}
23182348
fclose(sf);
2349+
free(realname);
23192350
}
23202351
strlcpy(lsecret, word, sizeof(lsecret));
23212352
}
@@ -2474,10 +2505,13 @@ have_eaptls_secret_server(char *client, char *server,
24742505
char cacertfile[MAXWORDLEN];
24752506
char pkfile[MAXWORDLEN];
24762507

2477-
filename = PPP_PATH_EAPTLSSERVFILE;
2508+
if (!ppp_check_access(PPP_PATH_EAPTLSSERVFILE, &filename, 0, 0))
2509+
return 0;
24782510
f = fopen(filename, "r");
2479-
if (f == NULL)
2480-
return 0;
2511+
if (f == NULL) {
2512+
free(filename);
2513+
return 0;
2514+
}
24812515

24822516
if (client != NULL && client[0] == 0)
24832517
client = NULL;
@@ -2490,6 +2524,7 @@ have_eaptls_secret_server(char *client, char *server,
24902524
0);
24912525

24922526
fclose(f);
2527+
free(filename);
24932528

24942529
/*
24952530
if (ret >= 0 && !eaptls_init_ssl(1, cacertfile, servcertfile,
@@ -2752,10 +2787,13 @@ get_eaptls_secret(int unit, char *client, char *server,
27522787
filename = (am_server ? PPP_PATH_EAPTLSSERVFILE : PPP_PATH_EAPTLSCLIFILE);
27532788
addrs = NULL;
27542789

2790+
if (!ppp_check_access(filename, &filename, 0, 0))
2791+
return 0;
27552792
fp = fopen(filename, "r");
27562793
if (fp == NULL)
27572794
{
27582795
error("Can't open eap-tls secret file %s: %m", filename);
2796+
free(filename);
27592797
return 0;
27602798
}
27612799

@@ -2765,6 +2803,7 @@ get_eaptls_secret(int unit, char *client, char *server,
27652803
cacertfile, pkfile, &addrs, &opts, filename, 0);
27662804

27672805
fclose(fp);
2806+
free(filename);
27682807

27692808
if (ret < 0) return 0;
27702809
}

pppd/main.c

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,21 +1921,14 @@ pid_t
19211921
run_program(char *prog, char * const *args, int must_exist, void (*done)(void *), void *arg, int wait)
19221922
{
19231923
int pid, status, ret;
1924-
struct stat sbuf;
1924+
char *rpath;
19251925

19261926
/*
1927-
* First check if the file exists and is executable.
1928-
* We don't use access() because that would use the
1929-
* real user-id, which might not be root, and the script
1930-
* might be accessible only to root.
1927+
* First check if the file exists and is executable by root,
1928+
* and couldn't have been modified by a non-root process.
19311929
*/
1932-
errno = EINVAL;
1933-
if (stat(prog, &sbuf) < 0 || !S_ISREG(sbuf.st_mode)
1934-
|| (sbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) {
1935-
if (must_exist || errno != ENOENT)
1936-
warn("Can't execute %s: %m", prog);
1930+
if (!ppp_check_access(prog, &rpath, must_exist, 1))
19371931
return 0;
1938-
}
19391932

19401933
pid = ppp_safe_fork(fd_devnull, fd_devnull, fd_devnull);
19411934
if (pid == -1) {
@@ -1954,6 +1947,7 @@ run_program(char *prog, char * const *args, int must_exist, void (*done)(void *)
19541947
}
19551948
forget_child(pid, status);
19561949
}
1950+
free(rpath);
19571951
return pid;
19581952
}
19591953

@@ -1981,12 +1975,12 @@ run_program(char *prog, char * const *args, int must_exist, void (*done)(void *)
19811975

19821976
/* run the program */
19831977
update_script_environment();
1984-
execve(prog, args, script_env);
1978+
execve(rpath, args, script_env);
19851979
if (must_exist || errno != ENOENT) {
19861980
/* have to reopen the log, there's nowhere else
19871981
for the message to go. */
19881982
reopen_log();
1989-
syslog(LOG_ERR, "Can't execute %s: %m", prog);
1983+
syslog(LOG_ERR, "Can't execute %s: %m", rpath);
19901984
closelog();
19911985
}
19921986
_exit(99);

pppd/options.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,7 @@ callfile(char **argv)
16401640
{
16411641
char *fname, *arg, *p;
16421642
int l, ok;
1643+
char *realname;
16431644

16441645
arg = *argv;
16451646
ok = 1;
@@ -1668,9 +1669,15 @@ callfile(char **argv)
16681669
slprintf(fname, l, "%s%s", PPP_PATH_PEERFILES, arg);
16691670
ppp_script_setenv("CALL_FILE", arg, 0);
16701671

1671-
ok = ppp_options_from_file(fname, 1, 1, 1);
1672+
if (!ppp_check_access(fname, &realname, 1, 0)) {
1673+
free(fname);
1674+
return 0;
1675+
}
1676+
1677+
ok = ppp_options_from_file(realname, 1, 1, 1);
16721678

16731679
free(fname);
1680+
free(realname);
16741681
return ok;
16751682
}
16761683

pppd/pppd.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,9 @@ void pr_log(void *, char *, ...);
299299
/* finish up after using pr_log */
300300
void end_pr_log(void);
301301

302+
/* Check that a file can safely be used */
303+
int ppp_check_access(const char *path, char **path_to_use, int must_exist, int exec);
304+
302305
/*
303306
* Get the current exist status of pppd
304307
*/

0 commit comments

Comments
 (0)