1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
--- tftpd.c.orig Mon Mar 20 14:14:39 1995
+++ tftpd.c Fri Aug 27 12:46:59 1999
@@ -294,7 +294,10 @@
}
int validate_access();
-int sendfile(), recvfile();
+
+struct formats;
+int tftpsendfile(struct formats *);
+int tftprecvfile(struct formats *);
struct formats {
char *f_mode;
@@ -303,8 +306,8 @@
int (*f_recv)();
int f_convert;
} formats[] = {
- { "netascii", validate_access, sendfile, recvfile, 1 },
- { "octet", validate_access, sendfile, recvfile, 0 },
+ { "netascii", validate_access, tftpsendfile, tftprecvfile, 1 },
+ { "octet", validate_access, tftpsendfile, tftprecvfile, 0 },
#ifdef notdef
{ "mail", validate_user, sendmail, recvmail, 1 },
#endif
@@ -459,17 +462,25 @@
/* Rule 2:
*/
- if (tftpRootDirectory != 0 && IS_ROOTED(filename)) {
+ if ((tftpRootDirectory != 0 && IS_ROOTED(filename)) ||
+ (tftpDefaultDirectory != 0 && IS_ROOTED(filename))) {
char _tmp[1024];
+ char* realRootDir;
int maxPath;
int rootLen;
- rootLen = strlen (tftpRootDirectory);
+ if (tftpRootDirectory != 0 ) {
+ realRootDir = tftpRootDirectory;
+ }
+ else {
+ realRootDir = tftpDefaultDirectory;
+ }
+
+ rootLen = strlen (realRootDir);
/* make sure the pathname doesn't already contain
* the virtual root.
*/
- if (strncmp(filename,tftpRootDirectory,rootLen) != 0) {
/* Insure our temporary space is big enough */
maxPath = ((sizeof _tmp) - 1) - rootLen;
@@ -481,6 +492,8 @@
return EACCESS;
}
+ if (strncmp(filename,realRootDir,rootLen) != 0) {
+
/* Squeeze out any '.' or '..' components */
strcpy (tmpPath, filename);
if (realPath (tmpPath, _tmp) < 0) {
@@ -492,21 +505,54 @@
/* Create the full pathname, prefixed by the
* virtual root.
*/
- strcpy (tmpPath, tftpRootDirectory);
+ strcpy (tmpPath, realRootDir);
strcat (tmpPath, _tmp);
filename = tmpPath;
}
+ else {
+ /* Squeeze out any '.' or '..' components */
+ strcpy (tmpPath, filename);
+ if (realPath (tmpPath, _tmp) < 0) {
+ if (tftpDebugLevel > 1)
+ syslog (LOG_DEBUG, "realPath fails");
+ return EACCESS;
+ }
+ /* Create the full pathname */
+ strcpy (tmpPath,_tmp);
+ filename = tmpPath;
+ if (strncmp(filename,realRootDir,rootLen) != 0) {
+ if (tftpDebugLevel > 1) {
+ syslog(LOG_DEBUG, "file=%s; invalid access denied", filename);
+ return EACCESS;
+ }
+ }
+ }
}
/* Rule 3:
*/
- if (!IS_ROOTED(filename) && tftpDefaultDirectory == 0) {
- strcpy (tmpPath, tftpRootDirectory);
- strcat (tmpPath, "/");
+ if ((!IS_ROOTED(filename) && tftpRootDirectory != 0) ||
+ (!IS_ROOTED(filename) && tftpDefaultDirectory != 0)) {
+ char _tmp[1024];
strcat (tmpPath, filename);
+ /* Squeeze out any '.' or '..' components */
+ strcpy (tmpPath, filename);
+ if (realPath (tmpPath, _tmp) < 0) {
+ if (tftpDebugLevel > 1)
+ syslog (LOG_DEBUG, "realPath fails");
+ return EACCESS;
+ }
+ if ( tftpDefaultDirectory == 0 ) {
+ strcpy (tmpPath, tftpRootDirectory);
+ }
+ else {
+ strcpy (tmpPath, tftpDefaultDirectory);
+ }
+ strcat (tmpPath, _tmp);
filename = tmpPath;
}
+
/* Check access lists */
/* Rules 4&5:
*/
@@ -593,7 +639,7 @@
/*
* Send the requested file.
*/
-sendfile(pf)
+tftpsendfile(pf)
struct formats *pf;
{
struct tftphdr *dp, *r_init();
@@ -664,7 +710,7 @@
/*
* Receive a file.
*/
-recvfile(pf)
+tftprecvfile(pf)
struct formats *pf;
{
struct tftphdr *dp, *w_init();
|