1 --- proftpd-1.3.3e/modules/mod_core.c Sun Feb 20 18:36:38 2011 |
1 --- a/include/dirtree.h |
2 +++ proftpd-1.3.3e/modules/mod_core.c Tue Jun 7 02:34:09 2011 |
2 +++ b/include/dirtree.h |
3 @@ -3974,11 +3974,13 @@ |
3 @@ -113,6 +113,9 @@ typedef struct cmd_struc { |
|
4 pr_table_t *notes; /* Private data for passing/retaining between handlers */ |
|
5 |
|
6 int cmd_id; /* Index into commands list, for faster comparisons */ |
|
7 + int error_code; /* Stores errno of failed file transfer |
|
8 + * commands. Required for Solaris auditing. |
|
9 + */ |
|
10 } cmd_rec; |
|
11 |
|
12 struct config_struc { |
|
13 diff --git a/modules/mod_core.c b/modules/mod_core.c |
|
14 index ff400f6..18a47c2 100644 |
|
15 --- a/modules/mod_core.c |
|
16 +++ b/modules/mod_core.c |
|
17 @@ -4554,6 +4554,7 @@ MODRET core_rmd(cmd_rec *cmd) { |
4 dir = dir_canonical_path(cmd->tmp_pool, dir); |
18 dir = dir_canonical_path(cmd->tmp_pool, dir); |
5 |
19 if (dir == NULL) { |
6 if (!dir) { |
20 int xerrno = EINVAL; |
7 + cmd->error_code = EINVAL; |
21 + cmd->error_code = EINVAL; |
8 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EINVAL)); |
22 |
9 return PR_ERROR(cmd); |
23 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
10 } |
24 |
|
25 @@ -4563,6 +4564,7 @@ MODRET core_rmd(cmd_rec *cmd) { |
11 |
26 |
12 if (!dir_check_canon(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) { |
27 if (!dir_check_canon(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) { |
|
28 int xerrno = EACCES; |
13 + cmd->error_code = EACCES; |
29 + cmd->error_code = EACCES; |
14 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EACCES)); |
30 |
15 return PR_ERROR(cmd); |
31 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
16 } |
32 |
17 @@ -3985,6 +3987,7 @@ |
33 @@ -4572,6 +4574,7 @@ MODRET core_rmd(cmd_rec *cmd) { |
18 |
34 |
19 if (pr_fsio_rmdir(dir) < 0) { |
35 if (pr_fsio_rmdir(dir) < 0) { |
20 int xerrno = errno; |
36 int xerrno = errno; |
21 + cmd->error_code = errno; |
37 + cmd->error_code = errno; |
22 |
38 |
23 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
39 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
24 "error removing directory '%s': %s", cmd->argv[0], session.user, |
40 "error removing directory '%s': %s", cmd->argv[0], session.user, |
25 @@ -4033,11 +4036,13 @@ |
41 @@ -4628,6 +4631,7 @@ MODRET core_mkd(cmd_rec *cmd) { |
26 |
|
27 dir = dir_canonical_path(cmd->tmp_pool, dir); |
42 dir = dir_canonical_path(cmd->tmp_pool, dir); |
28 if (!dir) { |
43 if (dir == NULL) { |
|
44 int xerrno = EINVAL; |
29 + cmd->error_code = EINVAL; |
45 + cmd->error_code = EINVAL; |
30 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EINVAL)); |
46 |
31 return PR_ERROR(cmd); |
47 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
32 } |
48 |
|
49 @@ -4637,6 +4641,7 @@ MODRET core_mkd(cmd_rec *cmd) { |
33 |
50 |
34 if (!dir_check_canon(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) { |
51 if (!dir_check_canon(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) { |
|
52 int xerrno = EACCES; |
35 + cmd->error_code = EACCES; |
53 + cmd->error_code = EACCES; |
|
54 |
36 pr_log_debug(DEBUG8, "%s command denied by <Limit> config", cmd->argv[0]); |
55 pr_log_debug(DEBUG8, "%s command denied by <Limit> config", cmd->argv[0]); |
37 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(EACCES)); |
56 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
38 return PR_ERROR(cmd); |
57 @@ -4648,6 +4653,7 @@ MODRET core_mkd(cmd_rec *cmd) { |
39 @@ -4045,6 +4050,7 @@ |
58 if (pr_fsio_smkdir(cmd->tmp_pool, dir, 0777, session.fsuid, |
40 |
59 session.fsgid) < 0) { |
41 if (pr_fsio_mkdir(dir, 0777) < 0) { |
|
42 int xerrno = errno; |
60 int xerrno = errno; |
43 + cmd->error_code = errno; |
61 + cmd->error_code = errno; |
44 |
62 |
45 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
63 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
46 "error making directory '%s': %s", cmd->argv[0], session.user, |
64 "error making directory '%s': %s", cmd->argv[0], session.user, |
47 @@ -4067,6 +4073,7 @@ |
65 @@ -4694,6 +4700,7 @@ MODRET core_mdtm(cmd_rec *cmd) { |
48 if (pr_fsio_chown(dir, session.fsuid, session.fsgid) == -1) { |
|
49 iserr++; |
|
50 err = errno; |
|
51 + cmd->error_code = errno; |
|
52 } |
|
53 PRIVS_RELINQUISH |
|
54 |
|
55 @@ -4111,6 +4118,7 @@ |
|
56 } |
|
57 |
|
58 if (res == -1) { |
|
59 + cmd->error_code = errno; |
|
60 pr_log_pri(PR_LOG_WARNING, "%schown() failed: %s", |
|
61 use_root_privs ? "root " : "", strerror(errno)); |
|
62 |
|
63 @@ -4153,6 +4161,7 @@ |
|
64 if (!path || |
|
65 !dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL) || |
66 !dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL) || |
66 pr_fsio_stat(path, &st) == -1) { |
67 pr_fsio_stat(path, &st) == -1) { |
67 + cmd->error_code = errno; |
68 int xerrno = errno; |
68 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(errno)); |
69 + cmd->error_code = errno; |
69 return PR_ERROR(cmd); |
70 |
70 |
71 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
71 @@ -4251,11 +4260,13 @@ |
72 |
72 /* If told to delete a symlink, don't delete the file it points to! */ |
73 @@ -4805,6 +4812,7 @@ MODRET core_dele(cmd_rec *cmd) { |
73 path = dir_canonical_path(cmd->tmp_pool, path); |
74 path = dir_canonical_path(cmd->tmp_pool, path); |
74 if (!path) { |
75 if (path == NULL) { |
75 + cmd->error_code = ENOENT; |
76 int xerrno = ENOENT; |
76 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(ENOENT)); |
77 + cmd->error_code = ENONET; |
77 return PR_ERROR(cmd); |
78 |
78 } |
79 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
|
80 |
|
81 @@ -4814,6 +4822,7 @@ MODRET core_dele(cmd_rec *cmd) { |
79 |
82 |
80 if (!dir_check_canon(cmd->tmp_pool, cmd, cmd->group, path, NULL)) { |
83 if (!dir_check_canon(cmd->tmp_pool, cmd, cmd->group, path, NULL)) { |
81 + cmd->error_code = errno; |
84 int xerrno = errno; |
|
85 + cmd->error_code = errno; |
|
86 |
82 pr_log_debug(DEBUG7, "deleting '%s' denied by <Limit> configuration", path); |
87 pr_log_debug(DEBUG7, "deleting '%s' denied by <Limit> configuration", path); |
83 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(errno)); |
88 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
84 return PR_ERROR(cmd); |
89 @@ -4830,6 +4839,7 @@ MODRET core_dele(cmd_rec *cmd) { |
85 @@ -4268,6 +4279,7 @@ |
|
86 memset(&st, 0, sizeof(st)); |
|
87 pr_fs_clear_cache(); |
90 pr_fs_clear_cache(); |
88 if (pr_fsio_lstat(path, &st) < 0) { |
91 if (pr_fsio_lstat(path, &st) < 0) { |
89 + cmd->error_code = errno; |
92 int xerrno = errno; |
90 pr_log_debug(DEBUG3, "unable to lstat '%s': %s", path, strerror(errno)); |
93 + cmd->error_code = errno; |
91 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(errno)); |
94 |
92 return PR_ERROR(cmd); |
95 pr_log_debug(DEBUG3, "unable to lstat '%s': %s", path, strerror(xerrno)); |
93 @@ -4278,6 +4290,7 @@ |
96 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
94 * EISDIR). |
97 @@ -4844,6 +4854,7 @@ MODRET core_dele(cmd_rec *cmd) { |
95 */ |
98 */ |
96 if (S_ISDIR(st.st_mode)) { |
99 if (S_ISDIR(st.st_mode)) { |
|
100 int xerrno = EISDIR; |
97 + cmd->error_code = EISDIR; |
101 + cmd->error_code = EISDIR; |
|
102 |
98 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
103 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
99 "error deleting '%s': %s", cmd->argv[0], session.user, |
104 "error deleting '%s': %s", cmd->argv[0], session.user, |
100 (unsigned long) session.uid, (unsigned long) session.gid, path, |
105 @@ -4860,6 +4871,7 @@ MODRET core_dele(cmd_rec *cmd) { |
101 @@ -4291,6 +4304,7 @@ |
|
102 |
106 |
103 if (pr_fsio_unlink(path) < 0) { |
107 if (pr_fsio_unlink(path) < 0) { |
104 int xerrno = errno; |
108 int xerrno = errno; |
105 + cmd->error_code = errno; |
109 + cmd->error_code = errno; |
106 |
110 |
107 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
111 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
108 "error deleting '%s': %s", cmd->argv[0], session.user, |
112 "error deleting '%s': %s", cmd->argv[0], session.user, |
109 @@ -4375,6 +4389,7 @@ |
113 @@ -4951,6 +4963,7 @@ MODRET core_rnto(cmd_rec *cmd) { |
110 !dir_check_canon(cmd->tmp_pool, cmd, cmd->group, path, NULL) || |
114 !dir_check_canon(cmd->tmp_pool, cmd, cmd->group, path, NULL) || |
111 pr_fsio_rename(session.xfer.path, path) == -1) { |
115 pr_fsio_rename(session.xfer.path, path) == -1) { |
112 int xerrno = errno; |
116 int xerrno = errno; |
113 + cmd->error_code = errno; |
117 + cmd->error_code = errno; |
114 |
118 |
115 if (xerrno != EXDEV) { |
119 if (xerrno != EXDEV) { |
116 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
120 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
117 @@ -4391,6 +4406,7 @@ |
121 @@ -4997,6 +5010,7 @@ MODRET core_rnto(cmd_rec *cmd) { |
118 */ |
122 */ |
119 if (pr_fs_copy_file(session.xfer.path, path) < 0) { |
123 if (pr_fs_copy_file(session.xfer.path, path) < 0) { |
120 xerrno = errno; |
124 xerrno = errno; |
121 + cmd->error_code = errno; |
125 + cmd->error_code = errno; |
122 |
126 |
123 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
127 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
124 "error copying '%s' to '%s': %s", cmd->argv[0], session.user, |
128 "error copying '%s' to '%s': %s", cmd->argv[0], session.user, |
125 @@ -4404,6 +4420,8 @@ |
129 @@ -5012,6 +5026,8 @@ MODRET core_rnto(cmd_rec *cmd) { |
126 |
130 |
127 /* Once copied, unlink the original file. */ |
131 /* Once copied, unlink the original file. */ |
128 if (pr_fsio_unlink(session.xfer.path) < 0) { |
132 if (pr_fsio_unlink(session.xfer.path) < 0) { |
129 + cmd->error_code = errno; |
133 + cmd->error_code = errno; |
130 + |
134 + |
131 pr_log_debug(DEBUG0, "error unlinking '%s': %s", session.xfer.path, |
135 pr_log_debug(DEBUG0, "error unlinking '%s': %s", session.xfer.path, |
132 strerror(errno)); |
136 strerror(errno)); |
133 } |
137 } |
134 @@ -4458,6 +4476,7 @@ |
138 @@ -5069,6 +5085,7 @@ MODRET core_rnfr(cmd_rec *cmd) { |
135 if (!path || |
|
136 !dir_check_canon(cmd->tmp_pool, cmd, cmd->group, path, NULL) || |
139 !dir_check_canon(cmd->tmp_pool, cmd, cmd->group, path, NULL) || |
137 !exists(path)) { |
140 !exists(path)) { |
138 + cmd->error_code = errno; |
141 int xerrno = errno; |
139 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(errno)); |
142 + cmd->error_code = errno; |
140 return PR_ERROR(cmd); |
143 |
141 } |
144 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
142 --- proftpd-1.3.3e/modules/mod_xfer.c Fri Feb 25 18:46:45 2011 |
145 |
143 +++ x/proftpd-1.3.3e/modules/mod_xfer.c Tue Jun 7 03:45:03 2011 |
146 diff --git a/modules/mod_xfer.c b/modules/mod_xfer.c |
144 @@ -1180,6 +1180,7 @@ |
147 index c153bb3..762b542 100644 |
|
148 --- a/modules/mod_xfer.c |
|
149 +++ b/modules/mod_xfer.c |
|
150 @@ -1211,6 +1211,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
145 |
151 |
146 if (cmd->argc < 2) { |
152 if (cmd->argc < 2) { |
147 pr_response_add_err(R_500, _("'%s' not understood"), get_full_cmd(cmd)); |
153 pr_response_add_err(R_500, _("'%s' not understood"), get_full_cmd(cmd)); |
148 + cmd->error_code = EINVAL; |
154 + cmd->error_code = EINVAL; |
149 errno = EINVAL; |
155 errno = EINVAL; |
150 return PR_ERROR(cmd); |
156 return PR_ERROR(cmd); |
151 } |
157 } |
152 @@ -1190,6 +1191,7 @@ |
158 @@ -1221,6 +1222,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
153 if (!path || |
159 if (!path || |
154 !dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL)) { |
160 !dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL)) { |
155 int xerrno = errno; |
161 int xerrno = errno; |
156 + cmd->error_code = errno; |
162 + cmd->error_code = errno; |
157 |
163 |
158 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
164 pr_log_debug(DEBUG8, "%s %s denied by <Limit> configuration", cmd->argv[0], |
159 |
165 cmd->arg); |
160 @@ -1200,6 +1202,7 @@ |
166 @@ -1233,6 +1235,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
161 if (xfer_check_limit(cmd) < 0) { |
167 if (xfer_check_limit(cmd) < 0) { |
162 pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg); |
168 pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg); |
163 errno = EPERM; |
169 errno = EPERM; |
164 + cmd->error_code = EPERM; |
170 + cmd->error_code = EPERM; |
165 return PR_ERROR(cmd); |
171 return PR_ERROR(cmd); |
166 } |
172 } |
167 |
173 |
168 @@ -1212,6 +1215,7 @@ |
174 @@ -1245,6 +1248,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
169 pr_log_debug(DEBUG6, "AllowOverwrite denied permission for %s", cmd->arg); |
175 pr_log_debug(DEBUG6, "AllowOverwrite denied permission for %s", cmd->arg); |
170 pr_response_add_err(R_550, _("%s: Overwrite permission denied"), cmd->arg); |
176 pr_response_add_err(R_550, _("%s: Overwrite permission denied"), cmd->arg); |
171 errno = EACCES; |
177 errno = EACCES; |
172 + cmd->error_code = EACCES; |
178 + cmd->error_code = EACCES; |
173 return PR_ERROR(cmd); |
179 return PR_ERROR(cmd); |
174 } |
180 } |
175 |
181 |
176 @@ -1233,6 +1237,7 @@ |
182 @@ -1268,6 +1272,8 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
177 ) { |
183 |
178 pr_response_add_err(R_550, _("%s: Not a regular file"), cmd->arg); |
184 /* Deliberately use EISDIR for anything non-file (e.g. directories). */ |
179 errno = EPERM; |
185 errno = EISDIR; |
180 + cmd->error_code = EPERM; |
186 + cmd->error_code = EISDIR; |
|
187 + |
181 return PR_ERROR(cmd); |
188 return PR_ERROR(cmd); |
182 } |
189 } |
183 } |
190 } |
184 @@ -1250,6 +1255,7 @@ |
191 @@ -1286,6 +1292,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
185 cmd->arg); |
|
186 session.restart_pos = 0L; |
192 session.restart_pos = 0L; |
187 session.xfer.xfer_type = STOR_DEFAULT; |
193 session.xfer.xfer_type = STOR_DEFAULT; |
188 + cmd->error_code = EPERM; |
|
189 errno = EPERM; |
194 errno = EPERM; |
190 return PR_ERROR(cmd); |
195 + cmd->error_code = EPERM; |
191 } |
196 return PR_ERROR(cmd); |
192 @@ -1256,9 +1262,11 @@ |
197 } |
|
198 |
|
199 @@ -1304,9 +1311,11 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
193 |
200 |
194 /* Otherwise everthing is good */ |
201 /* Otherwise everthing is good */ |
195 if (pr_table_add(cmd->notes, "mod_xfer.store-path", |
202 if (pr_table_add(cmd->notes, "mod_xfer.store-path", |
196 - pstrdup(cmd->pool, path), 0) < 0) |
203 - pstrdup(cmd->pool, path), 0) < 0) |
197 + pstrdup(cmd->pool, path), 0) < 0) { |
204 + pstrdup(cmd->pool, path), 0) < 0) { |
200 strerror(errno)); |
207 strerror(errno)); |
201 + } |
208 + } |
202 |
209 |
203 c = find_config(CURRENT_CONF, CONF_PARAM, "HiddenStores", FALSE); |
210 c = find_config(CURRENT_CONF, CONF_PARAM, "HiddenStores", FALSE); |
204 if (c && |
211 if (c && |
205 @@ -1269,6 +1277,7 @@ |
212 @@ -1319,6 +1328,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
206 if (session.restart_pos) { |
|
207 pr_response_add_err(R_501, |
213 pr_response_add_err(R_501, |
208 _("REST not compatible with server configuration")); |
214 _("REST not compatible with server configuration")); |
|
215 errno = EINVAL; |
209 + cmd->error_code = EINVAL; |
216 + cmd->error_code = EINVAL; |
210 errno = EINVAL; |
|
211 return PR_ERROR(cmd); |
217 return PR_ERROR(cmd); |
212 } |
218 } |
213 @@ -1333,6 +1342,7 @@ |
219 |
|
220 @@ -1328,6 +1338,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
|
221 pr_response_add_err(R_550, |
|
222 _("APPE not compatible with server configuration")); |
|
223 errno = EINVAL; |
|
224 + cmd->error_code = EINVAL; |
|
225 return PR_ERROR(cmd); |
|
226 } |
|
227 |
|
228 @@ -1391,6 +1402,7 @@ MODRET xfer_pre_stou(cmd_rec *cmd) { |
214 |
229 |
215 tmpfd = mkstemp(filename); |
230 tmpfd = mkstemp(filename); |
216 if (tmpfd < 0) { |
231 if (tmpfd < 0) { |
217 + cmd->error_code = errno; |
232 + cmd->error_code = errno; |
218 pr_log_pri(PR_LOG_ERR, "error: unable to use mkstemp(): %s", |
233 pr_log_pri(PR_LOG_ERR, "error: unable to use mkstemp(): %s", |
219 strerror(errno)); |
234 strerror(errno)); |
220 |
235 |
221 @@ -1357,6 +1367,7 @@ |
236 @@ -1416,6 +1428,7 @@ MODRET xfer_pre_stou(cmd_rec *cmd) { |
222 |
|
223 if (!filename || |
237 if (!filename || |
224 !dir_check(cmd->tmp_pool, cmd, cmd->group, filename, NULL)) { |
238 !dir_check(cmd->tmp_pool, cmd, cmd->group, filename, NULL)) { |
225 + cmd->error_code = errno; |
239 int xerrno = errno; |
226 int xerrno = errno; |
240 + cmd->error_code = errno; |
227 |
241 |
228 /* Do not forget to delete the file created by mkstemp(3) if there is |
242 /* Do not forget to delete the file created by mkstemp(3) if there is |
229 @@ -1434,6 +1445,7 @@ |
243 * an error. |
|
244 @@ -1495,6 +1508,7 @@ MODRET xfer_pre_appe(cmd_rec *cmd) { |
230 if (xfer_check_limit(cmd) < 0) { |
245 if (xfer_check_limit(cmd) < 0) { |
231 pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg); |
246 pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg); |
232 errno = EPERM; |
247 errno = EPERM; |
233 + cmd->error_code = EPERM; |
248 + cmd->error_code = EPERM; |
234 return PR_ERROR(cmd); |
249 return PR_ERROR(cmd); |
235 } |
250 } |
236 |
251 |
237 @@ -1487,6 +1499,7 @@ |
252 @@ -1550,6 +1564,7 @@ MODRET xfer_stor(cmd_rec *cmd) { |
238 O_WRONLY|(session.restart_pos ? 0 : O_CREAT|O_EXCL)); |
253 O_WRONLY|(session.restart_pos ? 0 : O_CREAT|O_EXCL)); |
239 if (stor_fh == NULL) { |
254 if (stor_fh == NULL) { |
240 ferrno = errno; |
255 ferrno = errno; |
241 + cmd->error_code = errno; |
256 + cmd->error_code = errno; |
242 |
257 |
243 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
258 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
244 "error opening '%s': %s", cmd->argv[0], session.user, |
259 "error opening '%s': %s", cmd->argv[0], session.user, |
245 @@ -1499,6 +1512,7 @@ |
260 @@ -1562,6 +1577,7 @@ MODRET xfer_stor(cmd_rec *cmd) { |
246 |
261 |
247 if (stor_fh) { |
262 if (stor_fh) { |
248 if (pr_fsio_lseek(stor_fh, 0, SEEK_END) == (off_t) -1) { |
263 if (pr_fsio_lseek(stor_fh, 0, SEEK_END) == (off_t) -1) { |
249 + cmd->error_code = errno; |
264 + cmd->error_code = errno; |
250 pr_log_debug(DEBUG4, "unable to seek to end of '%s' for appending: %s", |
265 pr_log_debug(DEBUG4, "unable to seek to end of '%s' for appending: %s", |
251 cmd->arg, strerror(errno)); |
266 cmd->arg, strerror(errno)); |
252 (void) pr_fsio_close(stor_fh); |
267 (void) pr_fsio_close(stor_fh); |
253 @@ -1507,6 +1521,7 @@ |
268 @@ -1570,6 +1586,7 @@ MODRET xfer_stor(cmd_rec *cmd) { |
254 |
269 |
255 } else { |
270 } else { |
256 ferrno = errno; |
271 ferrno = errno; |
257 + cmd->error_code = errno; |
272 + cmd->error_code = errno; |
258 |
273 |
259 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
274 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
260 "error opening '%s': %s", cmd->argv[0], session.user, |
275 "error opening '%s': %s", cmd->argv[0], session.user, |
261 @@ -1520,6 +1535,7 @@ |
276 @@ -1583,6 +1600,7 @@ MODRET xfer_stor(cmd_rec *cmd) { |
262 O_WRONLY|(session.restart_pos ? 0 : O_TRUNC|O_CREAT)); |
277 O_WRONLY|(session.restart_pos ? 0 : O_TRUNC|O_CREAT)); |
263 if (stor_fh == NULL) { |
278 if (stor_fh == NULL) { |
264 ferrno = errno; |
279 ferrno = errno; |
265 + cmd->error_code = errno; |
280 + cmd->error_code = errno; |
266 |
281 |
267 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
282 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
268 "error opening '%s': %s", cmd->argv[0], session.user, |
283 "error opening '%s': %s", cmd->argv[0], session.user, |
269 @@ -1533,11 +1549,13 @@ |
284 @@ -1596,11 +1614,13 @@ MODRET xfer_stor(cmd_rec *cmd) { |
270 int xerrno = 0; |
285 int xerrno = 0; |
271 |
286 |
272 if (pr_fsio_lseek(stor_fh, session.restart_pos, SEEK_SET) == -1) { |
287 if (pr_fsio_lseek(stor_fh, session.restart_pos, SEEK_SET) == -1) { |
273 + cmd->error_code = errno; |
288 + cmd->error_code = errno; |
274 pr_log_debug(DEBUG4, "unable to seek to position %" PR_LU " of '%s': %s", |
289 pr_log_debug(DEBUG4, "unable to seek to position %" PR_LU " of '%s': %s", |
278 } else if (pr_fsio_stat(path, &st) == -1) { |
293 } else if (pr_fsio_stat(path, &st) == -1) { |
279 + cmd->error_code = errno; |
294 + cmd->error_code = errno; |
280 pr_log_debug(DEBUG4, "unable to stat '%s': %s", cmd->arg, |
295 pr_log_debug(DEBUG4, "unable to stat '%s': %s", cmd->arg, |
281 strerror(errno)); |
296 strerror(errno)); |
282 xerrno = errno; |
297 xerrno = errno; |
283 @@ -1665,6 +1683,7 @@ |
298 @@ -1748,6 +1768,7 @@ MODRET xfer_stor(cmd_rec *cmd) { |
284 res = pr_fsio_write(stor_fh, lbuf, len); |
299 res = pr_fsio_write(stor_fh, lbuf, len); |
285 if (res != len) { |
300 if (res != len) { |
286 int xerrno = EIO; |
301 int xerrno = EIO; |
287 + cmd->error_code = errno; |
302 + cmd->error_code = errno; |
288 |
303 |
289 if (res < 0) |
304 if (res < 0) |
290 xerrno = errno; |
305 xerrno = errno; |
291 @@ -1716,16 +1735,19 @@ |
306 @@ -1806,18 +1827,21 @@ MODRET xfer_stor(cmd_rec *cmd) { |
292 */ |
307 */ |
293 #if defined(EDQUOT) |
308 #if defined(EDQUOT) |
294 if (errno == EDQUOT) { |
309 if (xerrno == EDQUOT) { |
295 + cmd->error_code = EDQUOT; |
310 + cmd->error_code = EDQUOT; |
296 pr_response_add_err(R_552, "%s: %s", cmd->arg, strerror(errno)); |
311 pr_response_add_err(R_552, "%s: %s", cmd->arg, strerror(xerrno)); |
|
312 errno = xerrno; |
297 return PR_ERROR(cmd); |
313 return PR_ERROR(cmd); |
298 } |
314 } |
299 #elif defined(EFBIG) |
315 #elif defined(EFBIG) |
300 if (errno == EFBIG) { |
316 if (xerrno == EFBIG) { |
301 + cmd->error_code = EFBIG; |
317 + cmd->error_code = EFBIG; |
302 pr_response_add_err(R_552, "%s: %s", cmd->arg, strerror(errno)); |
318 pr_response_add_err(R_552, "%s: %s", cmd->arg, strerror(xerrno)); |
|
319 errno = xerrno; |
303 return PR_ERROR(cmd); |
320 return PR_ERROR(cmd); |
304 } |
321 } |
305 #endif |
322 #endif |
306 |
323 |
307 + cmd->error_code = errno; |
324 + cmd->error_code = EFBIG; |
308 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(errno)); |
325 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
|
326 errno = xerrno; |
309 return PR_ERROR(cmd); |
327 return PR_ERROR(cmd); |
310 } |
328 @@ -1826,6 +1850,7 @@ MODRET xfer_stor(cmd_rec *cmd) { |
311 @@ -1733,6 +1755,7 @@ |
|
312 if (session.xfer.path && |
329 if (session.xfer.path && |
313 session.xfer.path_hidden) { |
330 session.xfer.path_hidden) { |
314 if (pr_fsio_rename(session.xfer.path_hidden, session.xfer.path) != 0) { |
331 if (pr_fsio_rename(session.xfer.path_hidden, session.xfer.path) != 0) { |
315 + cmd->error_code = errno; |
332 + cmd->error_code = errno; |
316 |
333 |
317 /* This should only fail on a race condition with a chmod/chown |
334 /* This should only fail on a race condition with a chmod/chown |
318 * or if STOR_APPEND is on and the permissions are squirrely. |
335 * or if STOR_APPEND is on and the permissions are squirrely. |
319 @@ -1830,6 +1853,7 @@ |
336 @@ -1924,6 +1949,7 @@ MODRET xfer_pre_retr(cmd_rec *cmd) { |
320 if (cmd->argc < 2) { |
337 if (cmd->argc < 2) { |
321 pr_response_add_err(R_500, _("'%s' not understood"), get_full_cmd(cmd)); |
338 pr_response_add_err(R_500, _("'%s' not understood"), get_full_cmd(cmd)); |
322 errno = EINVAL; |
339 errno = EINVAL; |
323 + cmd->error_code = EINVAL; |
340 + cmd->error_code = EINVAL; |
324 return PR_ERROR(cmd); |
341 return PR_ERROR(cmd); |
325 } |
342 } |
326 |
343 |
327 @@ -1839,6 +1863,7 @@ |
344 @@ -1933,6 +1959,7 @@ MODRET xfer_pre_retr(cmd_rec *cmd) { |
328 if (!dir || |
345 if (!dir || |
329 !dir_check(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) { |
346 !dir_check(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) { |
330 int xerrno = errno; |
347 int xerrno = errno; |
331 + cmd->error_code = errno; |
348 + cmd->error_code = EINVAL; |
332 |
349 |
333 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
350 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
334 |
351 |
335 @@ -1849,6 +1874,7 @@ |
352 @@ -1955,6 +1982,7 @@ MODRET xfer_pre_retr(cmd_rec *cmd) { |
336 if (xfer_check_limit(cmd) < 0) { |
353 if (xfer_check_limit(cmd) < 0) { |
337 pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg); |
354 pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg); |
338 errno = EPERM; |
355 errno = EPERM; |
339 + cmd->error_code = EPERM; |
356 + cmd->error_code = EPERM; |
340 return PR_ERROR(cmd); |
357 return PR_ERROR(cmd); |
341 } |
358 } |
342 |
359 |
343 @@ -1865,6 +1891,7 @@ |
360 @@ -1977,6 +2005,7 @@ MODRET xfer_pre_retr(cmd_rec *cmd) { |
344 ) { |
361 |
345 pr_response_add_err(R_550, _("%s: Not a regular file"), cmd->arg); |
362 /* Deliberately use EISDIR for anything non-file (e.g. directories). */ |
346 errno = EPERM; |
363 errno = EISDIR; |
347 + cmd->error_code = EPERM; |
364 + cmd->error_code = EISDIR; |
348 return PR_ERROR(cmd); |
365 return PR_ERROR(cmd); |
349 } |
366 } |
350 |
367 |
351 @@ -1879,6 +1906,7 @@ |
368 @@ -1991,6 +2020,7 @@ MODRET xfer_pre_retr(cmd_rec *cmd) { |
352 cmd->arg); |
369 cmd->arg); |
353 session.restart_pos = 0L; |
370 session.restart_pos = 0L; |
354 errno = EPERM; |
371 errno = EPERM; |
355 + cmd->error_code = EPERM; |
372 + cmd->error_code = EPERM; |
356 return PR_ERROR(cmd); |
373 return PR_ERROR(cmd); |
357 } |
374 } |
358 |
375 |
359 @@ -1908,6 +1936,7 @@ |
376 @@ -2020,6 +2050,7 @@ MODRET xfer_retr(cmd_rec *cmd) { |
360 retr_fh = pr_fsio_open(dir, O_RDONLY); |
377 retr_fh = pr_fsio_open(dir, O_RDONLY); |
361 if (retr_fh == NULL) { |
378 if (retr_fh == NULL) { |
362 int xerrno = errno; |
379 int xerrno = errno; |
363 + cmd->error_code = errno; |
380 + cmd->error_code = errno; |
364 |
381 |
365 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
382 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
366 "error opening '%s': %s", cmd->argv[0], session.user, |
383 "error opening '%s': %s", cmd->argv[0], session.user, |
367 @@ -1921,6 +1950,7 @@ |
384 @@ -2033,6 +2064,8 @@ MODRET xfer_retr(cmd_rec *cmd) { |
368 if (pr_fsio_stat(dir, &st) < 0) { |
385 if (pr_fsio_stat(dir, &st) < 0) { |
369 /* Error stat'ing the file. */ |
386 /* Error stat'ing the file. */ |
370 int xerrno = errno; |
387 int xerrno = errno; |
371 + cmd->error_code = errno; |
388 + cmd->error_code = errno; |
|
389 + |
372 pr_fsio_close(retr_fh); |
390 pr_fsio_close(retr_fh); |
373 errno = xerrno; |
391 errno = xerrno; |
374 |
392 |
375 @@ -1945,6 +1975,7 @@ |
393 @@ -2057,6 +2090,8 @@ MODRET xfer_retr(cmd_rec *cmd) { |
376 if (pr_fsio_lseek(retr_fh, session.restart_pos, |
394 if (pr_fsio_lseek(retr_fh, session.restart_pos, |
377 SEEK_SET) == (off_t) -1) { |
395 SEEK_SET) == (off_t) -1) { |
378 int xerrno = errno; |
396 int xerrno = errno; |
379 + cmd->error_code = errno; |
397 + cmd->error_code = errno; |
|
398 + |
380 pr_fsio_close(retr_fh); |
399 pr_fsio_close(retr_fh); |
381 errno = xerrno; |
400 errno = xerrno; |
382 retr_fh = NULL; |
401 retr_fh = NULL; |
383 @@ -2003,6 +2034,7 @@ |
402 @@ -2115,6 +2150,7 @@ MODRET xfer_retr(cmd_rec *cmd) { |
384 retr_abort(); |
403 retr_abort(); |
385 |
404 |
386 /* Set errno to EPERM ("Operation not permitted") */ |
405 /* Set errno to EPERM ("Operation not permitted") */ |
387 + cmd->error_code = EPERM; |
406 + cmd->error_code = EPERM; |
388 pr_data_abort(EPERM, FALSE); |
407 pr_data_abort(EPERM, FALSE); |
389 return PR_ERROR(cmd); |
408 return PR_ERROR(cmd); |
390 } |
409 } |
391 @@ -2034,6 +2066,7 @@ |
410 @@ -2146,6 +2182,7 @@ MODRET xfer_retr(cmd_rec *cmd) { |
392 * is preserved; errno itself might be overwritten in retr_abort(). |
411 * is preserved; errno itself might be overwritten in retr_abort(). |
393 */ |
412 */ |
394 int xerrno = errno; |
413 int xerrno = errno; |
395 + cmd->error_code = errno; |
414 + cmd->error_code = errno; |
396 |
415 |
397 retr_abort(); |
416 retr_abort(); |
|
417 |
398 |
418 |
399 --- proftpd-1.3.3e/include/dirtree.h Fri Mar 25 17:49:04 2011 |
|
400 +++ x/proftpd-1.3.3e/include/dirtree.h Tue Jun 7 02:07:51 2011 |
|
401 @@ -113,6 +113,8 @@ |
|
402 int class; /* The command class */ |
|
403 int stash_index; /* hack to speed up symbol hashing in modules.c */ |
|
404 pr_table_t *notes; /* Private data for passing/retaining between handlers */ |
|
405 + |
|
406 + int error_code; /* stores errno of failed file transfer commands*/ |
|
407 } cmd_rec; |
|
408 |
|
409 struct config_struc { |
|