/
upload-pipe.c
151 lines (140 loc) · 3.64 KB
/
upload-pipe.c
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
141
142
143
144
145
146
147
148
149
150
151
#include <config.h>
#if defined(WITH_UPLOAD_SCRIPT)
# include "ftpd.h"
# include "ftpwho-update.h"
# include "globals.h"
# include "upload-pipe.h"
# include "safe_rw.h"
# ifdef WITH_DMALLOC
# include <dmalloc.h>
# endif
int upload_pipe_open(void)
{
struct stat st;
upload_pipe_close();
anew:
if ((upload_pipe_lock =
open(UPLOAD_PIPE_LOCK,
O_CREAT | O_RDWR | O_NOFOLLOW, (mode_t) 0600)) == -1) {
unlink(UPLOAD_PIPE_LOCK);
return -1;
}
if (fstat(upload_pipe_lock, &st) < 0 ||
(st.st_mode & 0777) != 0600 || !S_ISREG(st.st_mode) ||
# ifdef NON_ROOT_FTP
st.st_uid != geteuid()
# else
st.st_uid != (uid_t) 0
# endif
) {
return -1;
}
if (lstat(UPLOAD_PIPE_LOCK, &st) < 0 ||
(st.st_mode & 0777) != 0600 || !S_ISREG(st.st_mode) ||
# ifdef NON_ROOT_FTP
st.st_uid != geteuid()
# else
st.st_uid != (uid_t) 0
# endif
) {
unlink(UPLOAD_PIPE_LOCK);
(void) close(upload_pipe_lock);
goto anew;
}
anew2:
upload_pipe_fd =
open(UPLOAD_PIPE_FILE, O_WRONLY | O_NOFOLLOW);
if (upload_pipe_fd == -1 && errno == ENXIO) {
upload_pipe_fd =
open(UPLOAD_PIPE_FILE, O_RDWR | O_NOFOLLOW);
}
if (upload_pipe_fd == -1) {
if (mkfifo(UPLOAD_PIPE_FILE, (mode_t) 0600) < 0) {
upload_pipe_close();
return -1;
}
goto anew2;
}
if (fstat(upload_pipe_fd, &st) < 0 ||
(st.st_mode & 0777) != 0600 || !S_ISFIFO(st.st_mode) ||
# ifdef NON_ROOT_FTP
st.st_uid != geteuid()
# else
st.st_uid != (uid_t) 0
# endif
) {
upload_pipe_close();
return -1; /* Don't fight, I'm too old for that */
}
if (lstat(UPLOAD_PIPE_FILE, &st) < 0 ||
(st.st_mode & 0777) != 0600 || !S_ISFIFO(st.st_mode) ||
# ifdef NON_ROOT_FTP
st.st_uid != geteuid()
# else
st.st_uid != (uid_t) 0
# endif
) {
unlink(UPLOAD_PIPE_FILE); /* Okay, fight a bit :) */
(void) close(upload_pipe_fd);
goto anew2;
}
return upload_pipe_fd;
}
/* File is already prefixed by \001 */
int upload_pipe_push(const char *vuser, const char *file)
{
struct flock lock;
const char starter = 2;
size_t sizeof_starter;
size_t sizeof_vuser;
size_t sizeof_file;
size_t sizeof_buf;
char *buf;
char *pnt;
if (upload_pipe_lock == -1 || upload_pipe_fd == -1 ||
file == NULL || *file == 0) {
return 0;
}
lock.l_whence = SEEK_SET;
lock.l_start = (off_t) 0;
lock.l_len = (off_t) 0;
lock.l_pid = getpid();
lock.l_type = F_WRLCK;
while (fcntl(upload_pipe_lock, F_SETLKW, &lock) < 0) {
if (errno != EINTR) {
return -1;
}
}
sizeof_starter = (size_t) 1U;
sizeof_vuser = strlen(vuser);
sizeof_file = strlen(file) + (size_t) 1U;
sizeof_buf = sizeof_starter + sizeof_vuser + sizeof_file;
if ((buf = malloc(sizeof_buf)) == NULL) {
return -1;
}
pnt = buf;
*buf = starter;
pnt += sizeof_starter;
memcpy(pnt, vuser, sizeof_vuser);
pnt += sizeof_vuser;
memcpy(pnt, file, sizeof_file);
(void) safe_write(upload_pipe_fd, buf, sizeof_buf, -1);
free(buf);
lock.l_type = F_UNLCK;
while (fcntl(upload_pipe_lock, F_SETLK, &lock) < 0 && errno == EINTR);
return 0;
}
void upload_pipe_close(void)
{
if (upload_pipe_fd != -1) {
close(upload_pipe_fd);
upload_pipe_fd = -1;
}
if (upload_pipe_lock != -1) {
close(upload_pipe_lock);
upload_pipe_lock = -1;
}
}
#else
extern signed char v6ready;
#endif