2 * User FTP Server, Share folders over FTP without being root.
3 * Copyright (C) 2008 Isaac Jurado
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option) any later
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 * Miscellaneous helper functions.
25 #include <sys/types.h>
26 #include <sys/socket.h>
35 * Show 'msg' followed by the system error and exit badly.
37 void fatal (char *msg
)
39 fputs("FATAL ERROR: ", stderr
);
48 * Send 'msg' through socket 'sk'. Because a single send() call doesn't ensure
49 * that all data is transferred (or maybe the call is interrupted), we need to
50 * place it in a small loop to wait until all 'msg' contents, at least, gets
51 * copied onto the internal TCP/IP stack buffers.
53 void send_reply (int sk
, char *msg
)
57 debug_msg("<<< %s", msg
);
61 b
= send(sk
, msg
, msglen
, 0);
63 fatal("Could not send reply");
75 * Converts a string to its numeric value in 64 bit representation. Quote from
76 * sysutil.c file of VsFTPd:
78 * ``atoll() is C99 standard - but even modern FreeBSD, OpenBSD don't
79 * haveit, so we'll supply our own''
81 * This function is almost a literal copy of vsf_sysutil_a_to_filesize_t(),
82 * present in that file. The only difference is that the string is processed
83 * from left to right, in contrast with the original. Therefore, here, negative
84 * numbers are directly converted to 0.
86 long long str_to_ll (char *str
)
90 if (strlen(str
) <= 15) {
92 if (*str
< '0' || *str
> '9')
109 * Check if 'path' is trying to access beyond the Basedir. We shouldn't allow
110 * that because we try to emulate chroot().
112 * This implementation is basically a small DFA (Deterministic Finite Automata)
113 * which parses the path looking for any of the substrings "./" or "../" at the
114 * beginning, "/./" or "/../" within, or else "/." or "/.." at the end.
116 int path_is_secure (char *path
)
119 * Current state ____ ____ Input value
121 const static int next_state
[5][3] = {
122 /* State 0 */ { 0, 1, 4 }, /* Input values: */
123 /* State 1 */ { 3, 2, 4 }, /* */
124 /* State 2 */ { 3, 4, 4 }, /* '/' = 0 */
125 /* State 3 */ { 3, 3, 3 }, /* '.' = 1 */
126 /* State 4 */ { 0, 4, 4 } /* other = 2 */
128 int state
= 0; /* Initial state */
131 while (*path
!= '\0') {
133 case '/': input
= 0; break;
134 case '.': input
= 1; break;
137 state
= next_state
[state
][input
];
141 /* Accepting states (safe path) are: */
142 return state
== 0 || state
== 4;
150 * Only implemented when debug flags are enabled. Display an information
151 * message to the stderr. Useful to follow the progress of the command-reply
152 * exchange without the need of a debugger.
154 void debug_msg (const char *format
, ...)
158 fprintf(stderr
, "(%d) ", getpid());
159 va_start(params
, format
);
160 vfprintf(stderr
, format
, params
);