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