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
27 struct _SessionScope SS
; /* SS --> Session State*/
33 * Reaper function. For "zombies".
35 static void child_finish (int sig
)
37 while (waitpid(-1, NULL
, WNOHANG
) > 0)
38 debug("Collecting children");
45 * End. What where you expecting?
47 static void end (int sig
)
49 notice("Signal caught, exiting");
55 * Main program. Opens the command port until a client requests a connection.
56 * Then the server is forked the child will manage all that client's requests.
58 * Attending multiple clients is necessary to allow some clients (like lftp(1))
59 * perform multiple concurrent jops. Like moving current transfer to de
60 * background and then browse through directories.
62 * Also note that here the root directory is fixed. As we can't protect with
63 * chroot(), due to de lack of privilege, we must do a series of safety checks
64 * to simulate that behaviour. Because of this, some strong restrictions have
65 * arised; which could reduce de number of FTP clients compatible with this
69 int main (int argc
, char **argv
)
71 int bind_sk
, cmd_sk
, e
, yes
;
72 int port
= DEFAULT_PORT
;
73 struct sigaction my_sa
;
74 struct sockaddr_in sai
;
75 socklen_t sai_len
= sizeof(struct sockaddr_in
);
81 port
= atoi(argv
[1]) & 0x00FFFF;
83 fatal("This port number is restricted");
87 sigfillset(&my_sa
.sa_mask
);
88 my_sa
.sa_flags
= SA_RESTART
;
89 my_sa
.sa_handler
= child_finish
;
90 sigaction(SIGCHLD
, &my_sa
, NULL
);
92 my_sa
.sa_flags
= SA_NOMASK
;
93 my_sa
.sa_handler
= end
;
94 sigaction(SIGINT
, &my_sa
, NULL
);
96 /* Connection handling */
97 sai
.sin_family
= AF_INET
;
98 sai
.sin_port
= htons(port
);
99 sai
.sin_addr
.s_addr
= INADDR_ANY
;
101 bind_sk
= socket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
103 fatal("Creating main server socket");
106 setsockopt(bind_sk
, SOL_SOCKET
, SO_REUSEADDR
, &yes
, sizeof(yes
));
107 e
= bind(bind_sk
, (struct sockaddr
*) &sai
, sai_len
);
109 fatal("Binding main server socket");
111 e
= listen(bind_sk
, 5);
113 fatal("Listening at main server socket");
115 notice("UFTPS listening on port %d (TCP)", port
);
116 notice("Use CTRL + C to finish");
117 notice("If you want to use a different port, specify it as the only argument in the command line");
119 /* Main server loop (accepting connections) */
121 sai_len
= sizeof(struct sockaddr_in
);
122 cmd_sk
= accept(bind_sk
, (struct sockaddr
*) &sai
, &sai_len
);
125 error("Accepting incoming connection");
135 error("Closing server socket from child");
137 init_session(cmd_sk
);
144 error("Could not create a child process");
148 error("Closing control channel %d from parent",