1 /* vi:ai:et:ts=8 sw=2
2 */
3 /*
4 * wzdftpd - a modular and cool ftp server
5 * Copyright (C) 2002-2004 Pierre Chifflier
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 * As a special exemption, Pierre Chifflier
22 * and other respective copyright holders give permission to link this program
23 * with OpenSSL, and distribute the resulting executable, without including
24 * the source code for OpenSSL in the source distribution.
25 */
26
27 #include "wzd_all.h"
28
29 #ifndef WZD_USE_PCH
30 #include <stdio.h>
31 #include <string.h>
32
33 #include "wzd_structs.h"
34
35 #include "wzd_libmain.h"
36 #include "wzd_log.h"
37 #include "wzd_messages.h"
38 #include "wzd_mutex.h"
39 #include "wzd_tls.h"
40 #include "wzd_ClientThread.h"
41
42 #include "wzd_debug.h"
43
44 #endif /* WZD_USE_PCH */
45
46 #include "wzd_version.h"
47
48 wzd_config_t * mainConfig;
49 List * context_list;
50 static uid_t _wzd_server_uid;
51 static gid_t _wzd_server_gid;
52
53 wzd_mutex_t * limiter_mutex;
54 wzd_mutex_t * server_mutex = NULL;
55
56 wzd_mutex_t * mutex_set[SET_MUTEX_NUM];
57
58 unsigned long mutex_set_key[SET_MUTEX_NUM] = {
59 0x22005400,
60 0x22005401,
61 0x22005402,
62 0x22005403,
63 0x22005404,
64 0x22005405,
65 0x22005406,
66 0x22005407,
67 0x22005408,
68 0x22005409,
69 0x2200540a,
70 0x2200540b,
71 };
72
73 time_t server_time;
74
75
wzd_get_version(void)76 const char * wzd_get_version(void)
77 {
78 return WZD_VERSION;
79 }
80
wzd_get_version_long(void)81 const char * wzd_get_version_long(void)
82 {
83 return WZD_VERSION_LONG;
84 }
85
getlib_mainConfig(void)86 wzd_config_t * getlib_mainConfig(void)
87 { return mainConfig; }
88
setlib_mainConfig(wzd_config_t * c)89 void setlib_mainConfig(wzd_config_t *c)
90 { mainConfig = c; }
91
getlib_contextList(void)92 List * getlib_contextList(void)
93 { return context_list; }
94
setlib_contextList(List * c)95 void setlib_contextList(List *c)
96 { context_list = c; }
97
getlib_server_gid(void)98 gid_t getlib_server_gid(void)
99 { return _wzd_server_gid; }
100
setlib_server_gid(gid_t gid)101 void setlib_server_gid(gid_t gid)
102 { _wzd_server_gid = gid; }
103
getlib_server_uid(void)104 int getlib_server_uid(void)
105 { return _wzd_server_uid; }
106
setlib_server_uid(int uid)107 void setlib_server_uid(int uid)
108 { _wzd_server_uid = uid; }
109
libtest(void)110 void libtest(void)
111 {
112 out_log(LEVEL_CRITICAL,"TEST LIB OK\n");
113 }
114
server_mutex_set_init(void)115 int server_mutex_set_init(void)
116 {
117 unsigned int i;
118
119 for (i=0; i<SET_MUTEX_NUM; i++) {
120 mutex_set[i] = wzd_mutex_create(mutex_set_key[i]);
121 }
122
123 return 0;
124 }
125
server_mutex_set_fini(void)126 int server_mutex_set_fini(void)
127 {
128 unsigned int i;
129
130 for (i=0; i<SET_MUTEX_NUM; i++) {
131 wzd_mutex_destroy(mutex_set[i]);
132 }
133
134 return 0;
135 }
136
137 /** called when SIGHUP received, need to restart the main server
138 * (and re-read config file)
139 * Currently loggued users are NOT kicked
140 */
server_restart(int signum)141 void server_restart(int signum)
142 {
143 #if 0
144 wzd_config_t * config;
145 int sock;
146 int rebind=0;
147
148 out_err(LEVEL_HIGH,"Sighup received\n");
149
150 /* 1- Re-read config file, abort if error */
151 config = readConfigFile(mainConfig->config_filename);
152 if (!config) return;
153
154 /* 2- Shutdown existing socket */
155 if (config->port != mainConfig->port) {
156 sock = mainConfig->mainSocket;
157 close(sock);
158 rebind = 1;
159 }
160
161 /* 3- Copy new config */
162 {
163 /* do not touch serverstop */
164 /* do not touch backend */
165 mainConfig->max_threads = config->max_threads;
166 /* do not touch logfile */
167 mainConfig->loglevel = config->loglevel;
168 /* do not touch messagefile */
169 /* mainSocket will be modified later */
170 mainConfig->port = config->port;
171 mainConfig->pasv_low_range = config->pasv_low_range;
172 mainConfig->pasv_high_range = config->pasv_high_range;
173 memcpy(mainConfig->pasv_ip, config->pasv_ip, sizeof(mainConfig->pasv_ip));
174 mainConfig->login_pre_ip_check = config->login_pre_ip_check;
175 /* reload pre-ip lists */
176 /* reload vfs lists */
177 vfs_free(&mainConfig->vfs);
178 mainConfig->vfs = config->vfs;
179 /* do not touch hooks */
180 hook_free(&mainConfig->hook);
181 mainConfig->hook = config->hook;
182 /* do not touch modules */
183 #ifdef HAVE_OPENSSL
184 /* what can we do with ssl ? */
185 /* reload certificate ? */
186 #endif
187 /* reload permission list ?? */
188 /* reload global_ul_limiter ?? */
189 /* reload global_dl_limiter ?? */
190 mainConfig->site_config = config->site_config;
191 }
192
193 /* 4- Re-open server */
194
195 /* create socket iff different ports ! */
196 if (rebind) {
197 sock = mainConfig->mainSocket = socket_make((const char *)mainConfig->ip,&mainConfig->port,mainConfig->max_threads);
198 if (sock == -1) {
199 out_log(LEVEL_CRITICAL,"Error creating socket %s:%d\n",
200 __FILE__, __LINE__);
201 serverMainThreadExit(-1);
202 }
203 {
204 int one=1;
205
206 if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(int)) < 0) {
207 out_log(LEVEL_CRITICAL,"setsockopt(SO_KEEPALIVE");
208 serverMainThreadExit(-1);
209 }
210 }
211 out_log(LEVEL_CRITICAL,"New file descriptor %d\n",mainConfig->mainSocket);
212 }
213
214 /* 5. Re-open log files */
215 if ( !CFG_GET_OPTION(mainConfig,CFG_OPT_USE_SYSLOG) )
216 {
217 int fd;
218 log_close();
219 if (log_open(mainConfig->logfilename,mainConfig->logfilemode))
220 {
221 out_err(LEVEL_CRITICAL,"Could not reopen log file !!!\n");
222 }
223 if (mainConfig->xferlog_name) {
224 xferlog_close(mainConfig->xferlog_fd);
225 fd = xferlog_open(mainConfig->xferlog_name, 0600);
226 if (fd==-1)
227 out_log(LEVEL_HIGH,"Could not open xferlog file: %s\n",
228 mainConfig->xferlog_name);
229 mainConfig->xferlog_fd = fd;
230 }
231 }
232 #endif
233
234 out_log(LEVEL_CRITICAL, " ** server_restart: Not yet implemented\n");
235 }
236
237 /** \brief remove a context from the list */
context_remove(List * context_list,wzd_context_t * context)238 int context_remove(List * context_list, wzd_context_t * context)
239 {
240 ListElmt * elmnt;
241 void * data;
242
243 out_log(LEVEL_FLOOD,"DEBUG removing context %p from list\n",context);
244
245 if (!context_list->head) return -1;
246 wzd_mutex_lock(server_mutex);
247
248 if (context == context_list->head->data)
249 {
250 list_rem_next(context_list, NULL, &data);
251 context_free(context);
252 wzd_mutex_unlock(server_mutex);
253 return 0;
254 }
255
256 for (elmnt=context_list->head; elmnt; elmnt=list_next(elmnt))
257 {
258 if ( list_next(elmnt) && context == list_next(elmnt)->data )
259 {
260 list_rem_next(context_list, elmnt, &data);
261 context_free(context);
262 wzd_mutex_unlock(server_mutex);
263 return 0;
264 }
265 }
266 wzd_mutex_unlock(server_mutex);
267
268 return -1;
269 }
270
271 /** \brief Allocate a new context */
context_alloc(void)272 wzd_context_t * context_alloc(void)
273 {
274 return wzd_malloc(sizeof(wzd_context_t));
275 }
276
277 /** \brief Initialize a context struct */
context_init(wzd_context_t * context)278 void context_init(wzd_context_t * context)
279 {
280 WZD_ASSERT_VOID(context != NULL);
281 if (context == NULL) return;
282
283 memset(context,0,sizeof(wzd_context_t));
284 context->controlfd = -1;
285 context->datafd = -1;
286 context->pasvsock = -1;
287 context->userid = (unsigned int)-1;
288 context->thread_id = (unsigned long)-1;
289 context->state = STATE_UNKNOWN;
290 context->datamode = DATA_PORT;
291 context->current_action.current_file = -1;
292 context->current_action.token = TOK_UNKNOWN;
293 memset(&context->last_file,0,sizeof(context->last_file));
294
295 tls_context_init(context);
296 context->reply = reply_alloc();
297
298 context->peer_ip = ip_create();
299
300 context->tls_role = TLS_SERVER_MODE;
301 context->read_fct = (read_fct_t)clear_read;
302 context->write_fct = (write_fct_t)clear_write;
303 }
304
305 /** \brief Frees a context
306 */
context_free(wzd_context_t * context)307 void context_free(wzd_context_t * context)
308 {
309 WZD_ASSERT_VOID(context != NULL);
310
311 wzd_free(context->ssl); context->ssl = NULL;
312 wzd_free(context->ident); context->ident = NULL;
313 wzd_free(context->idnt_address); context->idnt_address = NULL;
314 wzd_free(context->data_buffer); context->data_buffer = NULL;
315 wzd_free(context->control_buffer); context->control_buffer = NULL;
316 reply_free(context->reply);
317 str_deallocate(context->current_action.command);
318 ip_free(context->peer_ip);
319 wzd_free(context);
320 }
321
322