1 | /* |
---|
2 | * bbftpd/bbftpd.c |
---|
3 | * Copyright (C) 1999, 2000, 2001, 2002 IN2P3, CNRS |
---|
4 | * bbftp@in2p3.fr |
---|
5 | * http://doc.in2p3.fr/bbftp |
---|
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 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 | |
---|
22 | /**************************************************************************** |
---|
23 | |
---|
24 | |
---|
25 | |
---|
26 | bbftpd.c v 0.0.0 1999/11/24 |
---|
27 | v 1.3.0 2000/03/16 - Version in openlog |
---|
28 | v 1.4.0 2000/03/22 - Modify the connection protocole |
---|
29 | in order to send the crypt type |
---|
30 | after the connection. |
---|
31 | v 1.5.0 2000/03/24 - Change the wait timer in default |
---|
32 | v 1.6.0 2000/03/24 - Change the main loop to make it more |
---|
33 | modular |
---|
34 | v 1.6.1 2000/03/24 - Portage on OSF1 |
---|
35 | - Make the control socket non blocking |
---|
36 | v 1.8.0 2000/04/14 - Introduce RSA Cryptage |
---|
37 | v 1.8.6 2000/05/21 - Allow to run with inetd |
---|
38 | v 1.8.7 2000/05/24 - Introduce version.h and config.h |
---|
39 | v 1.8.10 2000/08/11 - Portage to Linux |
---|
40 | v 1.9.0 2000/08/18 - Use configure to help portage |
---|
41 | - default time out set to 900 s |
---|
42 | v 1.9.3 2000/10/12 - Add -b and -w option in order to overwrite |
---|
43 | the fixed values |
---|
44 | v 1.9.4 2000/10/16 - Make all sockets blocking in order |
---|
45 | to prevent the error in case of lack |
---|
46 | of memory |
---|
47 | - Supress %m |
---|
48 | v 2.0.0 2001/03/26 - Protocol V2 implementation |
---|
49 | v 2.0.1 2001/04/23 - Correct indentation |
---|
50 | - Port to IRIX |
---|
51 | v 2.0.2 2001/05/07 - Add debug option for RFIO |
---|
52 | v 2.1.0 2001/05/28 - Add private authentication |
---|
53 | - Correct syslog level |
---|
54 | - Add -l option |
---|
55 | v 2.2.0 2001/10/03 - Add the certificate authentication process |
---|
56 | |
---|
57 | *****************************************************************************/ |
---|
58 | |
---|
59 | |
---|
60 | #include <bbftpd.h> |
---|
61 | |
---|
62 | #include <errno.h> |
---|
63 | #include <fcntl.h> |
---|
64 | #include <limits.h> |
---|
65 | #include <netdb.h> |
---|
66 | #include <netinet/in.h> |
---|
67 | #include <arpa/inet.h> |
---|
68 | #include <netinet/tcp.h> |
---|
69 | #include <pwd.h> |
---|
70 | #include <signal.h> |
---|
71 | #include <stdio.h> |
---|
72 | #include <syslog.h> |
---|
73 | #include <sys/socket.h> |
---|
74 | #include <sys/wait.h> |
---|
75 | #if TIME_WITH_SYS_TIME |
---|
76 | # include <sys/time.h> |
---|
77 | # include <time.h> |
---|
78 | #else |
---|
79 | # if HAVE_SYS_TIME_H |
---|
80 | # include <sys/time.h> |
---|
81 | # else |
---|
82 | # include <time.h> |
---|
83 | # endif |
---|
84 | #endif |
---|
85 | #include <sys/stat.h> |
---|
86 | #include <unistd.h> |
---|
87 | #include <utime.h> |
---|
88 | #if HAVE_STRING_H |
---|
89 | # include <string.h> |
---|
90 | #endif |
---|
91 | |
---|
92 | #include <common.h> |
---|
93 | #include <config.h> |
---|
94 | #include <daemon.h> |
---|
95 | #include <daemon_proto.h> |
---|
96 | #include <status.h> |
---|
97 | #include <structures.h> |
---|
98 | #include <version.h> |
---|
99 | #ifdef CERTIFICATE_AUTH |
---|
100 | #include <gssapi.h> |
---|
101 | #include <gfw.h> |
---|
102 | #endif |
---|
103 | #ifdef HAVE_BYTESWAP_H |
---|
104 | #include <byteswap.h> |
---|
105 | #endif |
---|
106 | |
---|
107 | #include <openssl/rsa.h> |
---|
108 | |
---|
109 | #ifdef WITH_GZIP |
---|
110 | #include <zlib.h> |
---|
111 | #endif |
---|
112 | |
---|
113 | #ifdef CERTIFICATE_AUTH |
---|
114 | #define OPTIONS "bcd:fl:m:pR:suvw:" |
---|
115 | #else |
---|
116 | #define OPTIONS "bd:e:fl:m:R:suvw:" |
---|
117 | #endif |
---|
118 | |
---|
119 | /* |
---|
120 | ** Common variables for BBFTP protocole version 1 and 2 |
---|
121 | */ |
---|
122 | /* |
---|
123 | ** be_daemon : |
---|
124 | ** That is the way the daemon is going to be run. |
---|
125 | ** 0 means run by inetd (that can be done trought |
---|
126 | ** a wrapper) (run as bbftpd) |
---|
127 | ** 1 means that the control socket are stdin and |
---|
128 | ** stdout (run as bbftpd -s) |
---|
129 | ** 2 means running in background (run as bbftpd -b) |
---|
130 | ** Default 0 |
---|
131 | */ |
---|
132 | int be_daemon = 0 ; |
---|
133 | /* |
---|
134 | ** daemonchar: |
---|
135 | ** String used to initialize openlog |
---|
136 | */ |
---|
137 | char daemonchar[50] ; |
---|
138 | /* |
---|
139 | ** fixeddataport : |
---|
140 | ** If set to 1 then the server will use CONTROLPORT-1 |
---|
141 | ** to use as local port number for the data socket. |
---|
142 | ** It is useful to set it to 1 if the server is |
---|
143 | ** running behing a firewall. (run as bbftpd) |
---|
144 | ** If set to 0 then the server will not fixe the |
---|
145 | ** local data port (run as bbftpd -f) |
---|
146 | ** Default 1 |
---|
147 | */ |
---|
148 | int fixeddataport = 1 ; |
---|
149 | /* |
---|
150 | ** state : |
---|
151 | ** Define the state of the server. values differ depending |
---|
152 | ** of the BBFTP protocol version |
---|
153 | */ |
---|
154 | int state ; |
---|
155 | /* |
---|
156 | ** newcontrolport : |
---|
157 | ** Define the control port to listen on |
---|
158 | */ |
---|
159 | int newcontrolport ; |
---|
160 | /* |
---|
161 | ** currentusername : |
---|
162 | ** Define the local username |
---|
163 | */ |
---|
164 | char currentusername[MAXLEN] ; |
---|
165 | /* |
---|
166 | ** myrsa : |
---|
167 | ** Define the local location where is store the key pair |
---|
168 | */ |
---|
169 | RSA *myrsa ; |
---|
170 | /* |
---|
171 | ** his_addr : |
---|
172 | ** Remote address (the client) |
---|
173 | */ |
---|
174 | struct sockaddr_in his_addr; |
---|
175 | /* |
---|
176 | ** ctrl_addr : |
---|
177 | ** Local adresse (the server) |
---|
178 | */ |
---|
179 | struct sockaddr_in ctrl_addr; |
---|
180 | /* |
---|
181 | ** bbftpdrc: |
---|
182 | ** Where to store the bbftpdrc file |
---|
183 | */ |
---|
184 | char *bbftpdrc = NULL ; |
---|
185 | /* |
---|
186 | ** protocolversion : |
---|
187 | ** Set to 0 before any PROT message exchange, that also means |
---|
188 | ** that no children have been started |
---|
189 | */ |
---|
190 | int protocolversion ; |
---|
191 | int protocolmin = 1 ; |
---|
192 | int protocolmax = 3 ; |
---|
193 | /* |
---|
194 | ** fatherpid : |
---|
195 | ** The pid of the process keepng the control connection |
---|
196 | */ |
---|
197 | pid_t fatherpid ; |
---|
198 | /* |
---|
199 | ** flagsighup: |
---|
200 | ** Set to one when a SIGHUP is received |
---|
201 | **/ |
---|
202 | int flagsighup = 0 ; |
---|
203 | /* |
---|
204 | ** killdone: |
---|
205 | ** Set to one when the father has send a kill to all chidren |
---|
206 | */ |
---|
207 | int killdone= 0 ; |
---|
208 | /* |
---|
209 | ** childendinerror: |
---|
210 | ** Set to one when one child has been detected in error in order |
---|
211 | ** to prevent father to send multiple answer |
---|
212 | */ |
---|
213 | int childendinerror = 0 ; |
---|
214 | /* |
---|
215 | ** unlinkfile: |
---|
216 | ** Set to one when father has to unlink the file to store. Used |
---|
217 | ** in case of child ended incorrectly (kill -9 for example) |
---|
218 | */ |
---|
219 | int unlinkfile = 0 ; |
---|
220 | /* |
---|
221 | ** debug: |
---|
222 | ** Set to one for RFIO debug. Valid only with the -b option |
---|
223 | ** set to the value needed for RFIO_TRACE |
---|
224 | */ |
---|
225 | int debug = 0 ; |
---|
226 | /* |
---|
227 | ** castfd: |
---|
228 | ** CASTOR file descriptor use with RFIO and CASTOR |
---|
229 | */ |
---|
230 | int castfd ; |
---|
231 | /* |
---|
232 | ** castfilename: |
---|
233 | ** CASTOR/SHIFT real file name |
---|
234 | */ |
---|
235 | char *castfilename = NULL ; |
---|
236 | /* |
---|
237 | ** End Common variables for BBFTP protocole version 1 and 2 ******************** |
---|
238 | */ |
---|
239 | /* |
---|
240 | ** Variables for BBFTP protocole version 1 |
---|
241 | */ |
---|
242 | /* |
---|
243 | ** msgsock : |
---|
244 | ** Define control socket for the server |
---|
245 | */ |
---|
246 | int msgsock ; |
---|
247 | /* |
---|
248 | ** currentfilename : |
---|
249 | ** Define the file we are working on |
---|
250 | */ |
---|
251 | char currentfilename[MAXLENFILE]; |
---|
252 | /* |
---|
253 | ** pid_child : |
---|
254 | ** Array to store the children pid |
---|
255 | */ |
---|
256 | pid_t pid_child[MAXPORT] ; |
---|
257 | /* |
---|
258 | ** End Variables for BBFTP protocole version 1 ********************************* |
---|
259 | */ |
---|
260 | /* |
---|
261 | ** Variables for BBFTP protocole version 2 |
---|
262 | */ |
---|
263 | /* |
---|
264 | ** incontrolsock : |
---|
265 | ** Define the control socket for reading |
---|
266 | ** outcontrolsock : |
---|
267 | ** Define the control socket for writing |
---|
268 | ** |
---|
269 | ** For be_daemon equal to 0 or 2 incontrolsock = outcontrolsock |
---|
270 | */ |
---|
271 | int incontrolsock ; |
---|
272 | int outcontrolsock ; |
---|
273 | /* |
---|
274 | ** curfilename : |
---|
275 | ** Define the pointer to the current file |
---|
276 | */ |
---|
277 | char *curfilename = NULL ; |
---|
278 | /* |
---|
279 | ** curfilenamelen : |
---|
280 | ** Define the length of the memory used by curfilename |
---|
281 | */ |
---|
282 | int curfilenamelen ; |
---|
283 | /* |
---|
284 | ** realfilename : |
---|
285 | ** Define the pointer to the real file (= curfilename if TROPT_TMP not |
---|
286 | ** set) |
---|
287 | */ |
---|
288 | char *realfilename = NULL ; |
---|
289 | /* |
---|
290 | ** mychildren : |
---|
291 | ** Pointer to the first pid of children |
---|
292 | */ |
---|
293 | int *mychildren = NULL ; |
---|
294 | /* |
---|
295 | ** nbpidchid : |
---|
296 | ** Number of pid pointed by mychildren |
---|
297 | */ |
---|
298 | int nbpidchild ; |
---|
299 | /* |
---|
300 | ** myports : |
---|
301 | ** Pointer to the first port |
---|
302 | */ |
---|
303 | int *myports = NULL ; |
---|
304 | /* |
---|
305 | ** mysockets : |
---|
306 | ** Pointer to the first socket |
---|
307 | */ |
---|
308 | int *mysockets = NULL ; |
---|
309 | /* |
---|
310 | ** readbuffer : |
---|
311 | ** Pointer to the readbuffer |
---|
312 | */ |
---|
313 | int *readbuffer = NULL ; |
---|
314 | /* |
---|
315 | ** compbuffer : |
---|
316 | ** Pointer to the compression buffer |
---|
317 | */ |
---|
318 | int *compbuffer = NULL ; |
---|
319 | /* |
---|
320 | ** myumask : |
---|
321 | ** Umask for the bbftpd process, the default will be 022 which |
---|
322 | ** means that group and other write permissions are denied |
---|
323 | ** This can be changed by the bbftp umask command |
---|
324 | **/ |
---|
325 | int myumask = 022 ; |
---|
326 | /* |
---|
327 | ** Parameters describing the connection |
---|
328 | */ |
---|
329 | int ackto = ACKTO; |
---|
330 | int recvcontrolto = CONTROLSOCKTO; |
---|
331 | int sendcontrolto = SENDCONTROLTO; |
---|
332 | int datato = DATASOCKTO; |
---|
333 | int checkstdinto = CHECKSTDINTO; |
---|
334 | int force_encoding = 1; |
---|
335 | #ifdef CERTIFICATE_AUTH |
---|
336 | int accept_certs_only = 0; |
---|
337 | int accept_pass_only = 0; |
---|
338 | #endif |
---|
339 | /* |
---|
340 | ** Parameters describing the transfer |
---|
341 | */ |
---|
342 | int transferoption ; |
---|
343 | int filemode ; |
---|
344 | char lastaccess[9] ; |
---|
345 | char lastmodif[9] ; |
---|
346 | int sendwinsize ; |
---|
347 | int recvwinsize ; |
---|
348 | int buffersizeperstream ; |
---|
349 | int requestedstreamnumber ; |
---|
350 | my64_t filesize ; |
---|
351 | int mycos = 0 ; |
---|
352 | /* |
---|
353 | ** maxstreams : |
---|
354 | ** That is to fix the maximum number of stream the deamon will accept. |
---|
355 | ** (run as bbftpd -m 25) |
---|
356 | ** Default 25 |
---|
357 | */ |
---|
358 | int maxstreams = 25 ; |
---|
359 | /* |
---|
360 | ** End Variables for BBFTP protocole version 2 ********************************* |
---|
361 | */ |
---|
362 | /* |
---|
363 | * Variables for protocol version 3 (PASV mode) ****************************** |
---|
364 | */ |
---|
365 | /* |
---|
366 | * Range for the ephemeral ports for data connections |
---|
367 | */ |
---|
368 | int pasvport_min ; |
---|
369 | int pasvport_max ; |
---|
370 | /* |
---|
371 | ** End Variables for BBFTP protocole version 3 ********************************* |
---|
372 | */ |
---|
373 | /* |
---|
374 | ** credentials for certificate authentication |
---|
375 | */ |
---|
376 | #ifdef CERTIFICATE_AUTH |
---|
377 | gss_cred_id_t server_creds; |
---|
378 | #endif |
---|
379 | |
---|
380 | |
---|
381 | /* |
---|
382 | * Stats |
---|
383 | */ |
---|
384 | struct timeval tstart; |
---|
385 | |
---|
386 | #ifdef NDG_PYTHON_EMBED |
---|
387 | int bbftpd_main (argc, argv, envp) |
---|
388 | #else |
---|
389 | main (argc,argv,envp) |
---|
390 | #endif //NDG_PYTHON_EMBED |
---|
391 | int argc ; |
---|
392 | char **argv ; |
---|
393 | char **envp ; |
---|
394 | { |
---|
395 | extern char *optarg; |
---|
396 | extern int optind, opterr, optopt; |
---|
397 | /* |
---|
398 | #if defined(SUNOS) || defined(_HPUX_SOURCE) || defined(IRIX) |
---|
399 | int addrlen ; |
---|
400 | #else |
---|
401 | size_t addrlen ; |
---|
402 | #endif |
---|
403 | */ |
---|
404 | #ifdef HAVE_SOCKLEN_T |
---|
405 | socklen_t addrlen ; |
---|
406 | #else |
---|
407 | int addrlen ; |
---|
408 | #endif |
---|
409 | struct timeval wait_timer; |
---|
410 | fd_set selectmask ; |
---|
411 | int nfds ; |
---|
412 | int retcode ; |
---|
413 | int i, j, k ; |
---|
414 | struct message *msg ; |
---|
415 | char buffer[MINMESSLEN] ; |
---|
416 | char logmessage[1024] ; |
---|
417 | char rfio_trace[20] ; |
---|
418 | struct passwd *mypasswd ; |
---|
419 | char *bbftpdrcfile = NULL ; |
---|
420 | int fd ; |
---|
421 | char *carret ; |
---|
422 | char *startcmd ; |
---|
423 | int nooption ; |
---|
424 | struct stat statbuf ; |
---|
425 | int alluse ; |
---|
426 | |
---|
427 | sprintf(daemonchar,"bbftpd v%s",VERSION) ; |
---|
428 | openlog(daemonchar, LOG_PID | LOG_NDELAY, BBFTPD_FACILITY); |
---|
429 | /* |
---|
430 | ** Set the log mask to BBFTPD_EMERG (0) |
---|
431 | */ |
---|
432 | setlogmask(LOG_UPTO(BBFTPD_DEFAULT)); |
---|
433 | /* |
---|
434 | ** Initialize variables |
---|
435 | */ |
---|
436 | protocolversion = 0 ; |
---|
437 | #ifdef PORT_RANGE |
---|
438 | sscanf(PORT_RANGE,"%d:%d",&pasvport_min, &pasvport_max) ; |
---|
439 | #endif |
---|
440 | |
---|
441 | newcontrolport = CONTROLPORT ; |
---|
442 | opterr = 0 ; |
---|
443 | while ((j = getopt(argc, argv, OPTIONS)) != -1) { |
---|
444 | switch (j) { |
---|
445 | case 'v' :{ |
---|
446 | printf("bbftpd version %s\n",VERSION) ; |
---|
447 | printf("Compiled with : default port %d\n",CONTROLPORT) ; |
---|
448 | printf(" default maximum streams = %d \n",maxstreams) ; |
---|
449 | #ifdef PORT_RANGE |
---|
450 | printf(" data ports range = %s \n", PORT_RANGE) ; |
---|
451 | #endif |
---|
452 | #ifdef WITH_GZIP |
---|
453 | printf(" compression with Zlib-%s\n", zlibVersion()) ; |
---|
454 | #endif |
---|
455 | printf(" encryption with %s \n",SSLeay_version(SSLEAY_VERSION)) ; |
---|
456 | #ifdef WITH_RFIO |
---|
457 | # ifdef CASTOR |
---|
458 | printf(" CASTOR support (RFIO)\n") ; |
---|
459 | # else |
---|
460 | printf(" HPSS support (RFIO)\n") ; |
---|
461 | # endif |
---|
462 | #endif |
---|
463 | #ifdef WITH_RFIO64 |
---|
464 | # ifdef CASTOR |
---|
465 | printf(" CASTOR support (RFIO64)\n") ; |
---|
466 | # else |
---|
467 | printf(" HPSS support (RFIO64)\n") ; |
---|
468 | # endif |
---|
469 | #endif |
---|
470 | #ifdef AFS |
---|
471 | printf(" AFS authentication \n") ; |
---|
472 | #endif |
---|
473 | #ifdef CERTIFICATE_AUTH |
---|
474 | printf(" GSI authentication \n") ; |
---|
475 | #endif |
---|
476 | #ifdef PRIVATE_AUTH |
---|
477 | printf(" private authentication \n") ; |
---|
478 | #endif |
---|
479 | exit(0) ; |
---|
480 | } |
---|
481 | } |
---|
482 | } |
---|
483 | /* Check zlib version */ |
---|
484 | #ifdef WITH_GZIP |
---|
485 | { |
---|
486 | int z0, z1; |
---|
487 | if (0 != strcmp(zlibVersion(), ZLIB_VERSION)) { |
---|
488 | printf ("WARNING zlib version changed since last compile.\n"); |
---|
489 | printf ("Compiled Version is %s\n", ZLIB_VERSION); |
---|
490 | printf ("Linked Version is %s\n", zlibVersion()); |
---|
491 | } |
---|
492 | z0 = atoi (ZLIB_VERSION); |
---|
493 | z1 = atoi (zlibVersion()); |
---|
494 | if (z0 != z1) { |
---|
495 | printf ("ERROR: zlib is not compatible!\n"); |
---|
496 | printf ("zlib source can found at http://www.gzip.org/zlib/\n"); |
---|
497 | exit (0); |
---|
498 | } |
---|
499 | |
---|
500 | } |
---|
501 | #endif |
---|
502 | /* |
---|
503 | ** Look at the loglevel option |
---|
504 | */ |
---|
505 | i = 0 ; |
---|
506 | opterr = 0 ; |
---|
507 | optind = 1 ; |
---|
508 | while ((j = getopt(argc, argv, OPTIONS)) != -1) { |
---|
509 | switch (j) { |
---|
510 | case 'l' :{ |
---|
511 | for ( i=0 ; i< strlen(optarg) ; i++ ) { |
---|
512 | optarg[i] = toupper(optarg[i]) ; |
---|
513 | } |
---|
514 | i = 0 ; |
---|
515 | if ( !strcmp(optarg,"EMERGENCY") ) { |
---|
516 | i = BBFTPD_EMERG; |
---|
517 | } else if ( !strcmp(optarg,"ALERT") ) { |
---|
518 | i = BBFTPD_ALERT; |
---|
519 | } else if ( !strcmp(optarg,"CRITICAL") ) { |
---|
520 | i = BBFTPD_CRIT; |
---|
521 | } else if ( !strcmp(optarg,"ERROR") ) { |
---|
522 | i = BBFTPD_ERR; |
---|
523 | } else if ( !strcmp(optarg,"WARNING") ) { |
---|
524 | i = BBFTPD_WARNING; |
---|
525 | } else if ( !strcmp(optarg,"NOTICE") ) { |
---|
526 | i = BBFTPD_NOTICE; |
---|
527 | } else if ( !strcmp(optarg,"INFORMATION") ) { |
---|
528 | i = BBFTPD_INFO; |
---|
529 | } else if ( !strcmp(optarg,"DEBUG") ) { |
---|
530 | i = BBFTPD_DEBUG; |
---|
531 | } |
---|
532 | if ( i > 0 ) { |
---|
533 | setlogmask(LOG_UPTO(i)); |
---|
534 | } |
---|
535 | break ; |
---|
536 | } |
---|
537 | } |
---|
538 | } |
---|
539 | syslog(BBFTPD_DEBUG,"Starting bbftpd") ; |
---|
540 | opterr = 0 ; |
---|
541 | optind = 1 ; |
---|
542 | while ((j = getopt(argc, argv, OPTIONS)) != -1) { |
---|
543 | switch (j) { |
---|
544 | case 'b' :{ |
---|
545 | if ( be_daemon != 0 ) { |
---|
546 | syslog(BBFTPD_ERR,"-b and -s options are incompatibles") ; |
---|
547 | exit(1) ; |
---|
548 | } |
---|
549 | be_daemon = 2 ; |
---|
550 | break ; |
---|
551 | } |
---|
552 | case 'd' :{ |
---|
553 | sscanf(optarg,"%d",&i) ; |
---|
554 | if ( i > 0 ) debug = i ; |
---|
555 | break ; |
---|
556 | } |
---|
557 | case 'e' :{ |
---|
558 | if ((sscanf(optarg,"%d:%d",&i, &k) == 2) && (i < k)) { |
---|
559 | pasvport_min = i; pasvport_max = k; |
---|
560 | } else { |
---|
561 | syslog(BBFTPD_ERR,"Invalid port range : %s",optarg) ; |
---|
562 | fprintf(stderr,"Invalid port range : %s\n",optarg) ; |
---|
563 | exit(1) ; |
---|
564 | } |
---|
565 | break ; |
---|
566 | } |
---|
567 | case 'f' :{ |
---|
568 | fixeddataport = 0 ; |
---|
569 | break ; |
---|
570 | } |
---|
571 | case 'm' :{ |
---|
572 | sscanf(optarg,"%d",&i) ; |
---|
573 | if ( i > 0 ) maxstreams = i ; |
---|
574 | break ; |
---|
575 | } |
---|
576 | case 'R' :{ |
---|
577 | bbftpdrcfile = optarg ; |
---|
578 | break ; |
---|
579 | } |
---|
580 | case 's' :{ |
---|
581 | if ( be_daemon != 0 ) { |
---|
582 | syslog(BBFTPD_ERR,"-b and -s options are incompatibles") ; |
---|
583 | exit(1) ; |
---|
584 | } |
---|
585 | #ifdef PRIVATE_AUTH |
---|
586 | syslog(BBFTPD_ERR,"-s option cannot be used with private authentication") ; |
---|
587 | exit(1) ; |
---|
588 | #endif |
---|
589 | be_daemon = 1 ; |
---|
590 | break ; |
---|
591 | } |
---|
592 | case 'u' :{ |
---|
593 | force_encoding = 0 ; |
---|
594 | break ; |
---|
595 | } |
---|
596 | case 'w' :{ |
---|
597 | sscanf(optarg,"%d",&newcontrolport) ; |
---|
598 | break ; |
---|
599 | } |
---|
600 | #ifdef CERTIFICATE_AUTH |
---|
601 | case 'c' :{ |
---|
602 | accept_certs_only = 1 ; |
---|
603 | break ; |
---|
604 | } |
---|
605 | case 'p' :{ |
---|
606 | accept_pass_only = 1 ; |
---|
607 | break ; |
---|
608 | } |
---|
609 | #endif |
---|
610 | default : { |
---|
611 | break ; |
---|
612 | } |
---|
613 | } |
---|
614 | } |
---|
615 | |
---|
616 | /* |
---|
617 | ** Check for the local user in order to find the .bbftpdrc file |
---|
618 | */ |
---|
619 | if ( bbftpdrcfile == NULL ) { |
---|
620 | /* |
---|
621 | ** look for the local user in order to find the .bbftpdrc file |
---|
622 | ** use /etc/bbftpd.conf if root |
---|
623 | */ |
---|
624 | if ( getuid() == 0) { |
---|
625 | if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1 )) == NULL ) { |
---|
626 | syslog(BBFTPD_ERR, "Error allocationg space for config file name.\n") ; |
---|
627 | } else { |
---|
628 | strcpy(bbftpdrcfile,BBFTPD_CONF); |
---|
629 | } |
---|
630 | } else if ( (mypasswd = getpwuid(getuid())) == NULL ) { |
---|
631 | syslog(BBFTPD_WARNING, "Unable to get passwd entry, using %s\n", BBFTPD_CONF) ; |
---|
632 | if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1) ) != NULL ) { |
---|
633 | strcpy(bbftpdrcfile,BBFTPD_CONF); |
---|
634 | } |
---|
635 | } else if ( mypasswd->pw_dir == NULL ) { |
---|
636 | syslog(BBFTPD_WARNING, "No home directory, using %s\n", BBFTPD_CONF) ; |
---|
637 | if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1) ) != NULL ) { |
---|
638 | strcpy(bbftpdrcfile,BBFTPD_CONF); |
---|
639 | } |
---|
640 | } else if ( (bbftpdrcfile = (char *) malloc (strlen(mypasswd->pw_dir)+11) ) == NULL ) { |
---|
641 | syslog(BBFTPD_ERR, "Error allocationg space for bbftpdrc file name, .bbftpdrc will not be used\n") ; |
---|
642 | } else { |
---|
643 | strcpy(bbftpdrcfile,mypasswd->pw_dir) ; |
---|
644 | strcat(bbftpdrcfile,"/.bbftpdrc") ; |
---|
645 | if ( stat(bbftpdrcfile,&statbuf) < 0 ) { |
---|
646 | bbftpdrcfile == NULL; |
---|
647 | if ( (bbftpdrcfile = (char *) malloc (strlen(BBFTPD_CONF)+1) ) != NULL ) { |
---|
648 | strcpy(bbftpdrcfile,BBFTPD_CONF); |
---|
649 | } |
---|
650 | } |
---|
651 | } |
---|
652 | } |
---|
653 | if ( bbftpdrcfile != NULL ) { |
---|
654 | if ( strncmp(bbftpdrcfile,"none",4) != 0 ) { |
---|
655 | /* |
---|
656 | ** Stat the file in order to get the length |
---|
657 | */ |
---|
658 | if ( stat(bbftpdrcfile,&statbuf) < 0 ) { |
---|
659 | /* |
---|
660 | syslog(BBFTPD_WARNING, "Error stating bbftpdrc file (%s)\n",bbftpdrcfile) ; |
---|
661 | */ |
---|
662 | } else if ( statbuf.st_size == 0 ) { |
---|
663 | /* |
---|
664 | ** do nothing |
---|
665 | */ |
---|
666 | } else if ( (bbftpdrc = (char *) malloc (statbuf.st_size + 1 ) ) == NULL ) { |
---|
667 | syslog(BBFTPD_ERR, "Error allocation memory for bbftpdrc, .bbftpdrc will not be used\n") ; |
---|
668 | } else if ( ( fd = open (bbftpdrcfile,O_RDONLY) ) < 0 ) { |
---|
669 | syslog(BBFTPD_ERR, "Error openning .bbftpdrc file (%s) : %s \n",bbftpdrcfile,strerror(errno)) ; |
---|
670 | } else if ( ( j = read( fd, bbftpdrc , statbuf.st_size )) != statbuf.st_size ) { |
---|
671 | syslog(BBFTPD_ERR, "Error reading .bbftpdrc file (%s)\n",bbftpdrcfile) ; |
---|
672 | } else { |
---|
673 | bbftpdrc[j] = '\0' ; |
---|
674 | } |
---|
675 | } |
---|
676 | } |
---|
677 | /* |
---|
678 | ** Analyse the bbftpdrc command in order to supress forbiden command |
---|
679 | ** Allowed commands are : |
---|
680 | ** setackto %d |
---|
681 | ** setrecvcontrolto %d |
---|
682 | ** setsendcontrolto %d |
---|
683 | ** setdatato %d |
---|
684 | ** setcheckstdinto %d |
---|
685 | ** setoption fixeddataport |
---|
686 | */ |
---|
687 | if ( bbftpdrc != NULL ) { |
---|
688 | carret = bbftpdrc ; |
---|
689 | startcmd = bbftpdrc ; |
---|
690 | /* |
---|
691 | ** Strip starting CR |
---|
692 | */ |
---|
693 | while (1) { |
---|
694 | while ( *carret == 10 || *carret == ' ' ) carret++ ; |
---|
695 | startcmd = carret ; |
---|
696 | carret = (char *) strchr (carret, 10); |
---|
697 | if ( carret == NULL ) break ; |
---|
698 | *carret = '\0' ; |
---|
699 | if (!strncmp(startcmd,"setackto",8)) { |
---|
700 | retcode = sscanf(startcmd,"setackto %d",&alluse) ; |
---|
701 | if ( retcode != 1 || alluse <= 0 ) { |
---|
702 | syslog(BBFTPD_WARNING, "Acknowledge timeout must be numeric and > 0\n") ; |
---|
703 | } else { |
---|
704 | ackto = alluse ; |
---|
705 | } |
---|
706 | } else if (!strncmp(startcmd,"setrecvcontrolto",16)) { |
---|
707 | retcode = sscanf(startcmd,"setrecvcontrolto %d",&alluse) ; |
---|
708 | if ( retcode != 1 || alluse <= 0 ) { |
---|
709 | syslog(BBFTPD_WARNING, "Input control timeout must be numeric and > 0\n") ; |
---|
710 | } else { |
---|
711 | recvcontrolto = alluse ; |
---|
712 | } |
---|
713 | } else if (!strncmp(startcmd,"setsendcontrolto",16)) { |
---|
714 | retcode = sscanf(startcmd,"setsendcontrolto %d",&alluse) ; |
---|
715 | if ( retcode != 1 || alluse <= 0 ) { |
---|
716 | syslog(BBFTPD_WARNING, "Output control timeout must be numeric and > 0\n") ; |
---|
717 | } else { |
---|
718 | sendcontrolto = alluse ; |
---|
719 | } |
---|
720 | } else if (!strncmp(startcmd,"setdatato",9)) { |
---|
721 | retcode = sscanf(startcmd,"setdatato %d",&alluse) ; |
---|
722 | if ( retcode != 1 || alluse <= 0 ) { |
---|
723 | syslog(BBFTPD_WARNING, "Data timeout must be numeric and > 0\n") ; |
---|
724 | } else { |
---|
725 | datato = alluse ; |
---|
726 | } |
---|
727 | } else if (!strncmp(startcmd,"setcheckstdinto",15)) { |
---|
728 | retcode = sscanf(startcmd,"setcheckstdinto %d",&alluse) ; |
---|
729 | if ( retcode != 1 || alluse <= 0 ) { |
---|
730 | syslog(BBFTPD_WARNING, "Check input timeout must be numeric and > 0\n") ; |
---|
731 | } else { |
---|
732 | checkstdinto = alluse ; |
---|
733 | } |
---|
734 | } else if (!strncmp(startcmd,"setoption",9)) { |
---|
735 | /* |
---|
736 | ** look for the option |
---|
737 | */ |
---|
738 | startcmd = startcmd + 9 ; |
---|
739 | while (*startcmd == ' ' && *startcmd != '\0' ) startcmd++ ; |
---|
740 | if ( !strncmp(startcmd,"no",2) ) { |
---|
741 | nooption = 1 ; |
---|
742 | startcmd = startcmd+2 ; |
---|
743 | } else { |
---|
744 | nooption = 0 ; |
---|
745 | } |
---|
746 | if ( !strncmp(startcmd,"fixeddataport",9) ) { |
---|
747 | if ( nooption ) { |
---|
748 | if (fixeddataport == 1) { /* default value */ |
---|
749 | fixeddataport = 0; |
---|
750 | } |
---|
751 | } |
---|
752 | } |
---|
753 | } else { |
---|
754 | syslog(BBFTPD_WARNING, "Unkown command in .bbftpdrc file (%s)\n",startcmd) ; |
---|
755 | } |
---|
756 | carret++ ; |
---|
757 | } |
---|
758 | } |
---|
759 | /* |
---|
760 | ** Get 5K for castfilename in order to work with CASTOR |
---|
761 | ** software (even if we are not using it) |
---|
762 | */ |
---|
763 | if ( (castfilename = (char *) malloc (5000)) == NULL ) { |
---|
764 | /* |
---|
765 | ** Starting badly if we are unable to malloc 5K |
---|
766 | */ |
---|
767 | syslog(BBFTPD_ERR,"No memory for CASTOR : %s",strerror(errno)) ; |
---|
768 | fprintf(stderr,"No memory for CASTOR : %s\n",strerror(errno)) ; |
---|
769 | exit(1) ; |
---|
770 | } |
---|
771 | /* |
---|
772 | ** Reset debug to zero if -b option is not present |
---|
773 | */ |
---|
774 | if ( (be_daemon != 2) ) debug = 0 ; |
---|
775 | /* |
---|
776 | ** Check if be_daemon = 0 and in this case reset the |
---|
777 | ** control port to CONTROLPORT |
---|
778 | */ |
---|
779 | if ( be_daemon == 0 ) newcontrolport = CONTROLPORT ; |
---|
780 | |
---|
781 | #ifdef CERTIFICATE_AUTH |
---|
782 | if (be_daemon != 1 && !accept_pass_only) { |
---|
783 | OM_uint32 min_stat, maj_stat; |
---|
784 | maj_stat = gfw_acquire_cred(&min_stat, NULL, &server_creds); |
---|
785 | if (maj_stat != GSS_S_COMPLETE) { |
---|
786 | gfw_msgs_list *messages = NULL; |
---|
787 | gfw_status_to_strings(maj_stat, min_stat, &messages) ; |
---|
788 | while (messages != NULL) { |
---|
789 | syslog(BBFTPD_ERR,"gfw_acquire_cred: %s", messages->msg) ; |
---|
790 | if (be_daemon == 2) fprintf(stderr,"Acquire credentials: %s\n", messages->msg) ; |
---|
791 | messages = messages->next; |
---|
792 | } |
---|
793 | exit(1); |
---|
794 | } |
---|
795 | } |
---|
796 | #endif |
---|
797 | if ( be_daemon == 2 ) { |
---|
798 | /* |
---|
799 | ** Run as a daemon |
---|
800 | */ |
---|
801 | #ifdef NDG_PYTHON_EMBED |
---|
802 | if ((fatherpid = do_daemon(argc, argv, envp)) > 0) return fatherpid; |
---|
803 | #else |
---|
804 | do_daemon(argc, argv, envp); |
---|
805 | #endif |
---|
806 | /* |
---|
807 | ** Check for debug |
---|
808 | */ |
---|
809 | if ( debug != 0 ) { |
---|
810 | #if defined(WITH_RFIO) || defined(WITH_RFIO64) |
---|
811 | sprintf(rfio_trace,"RFIO_TRACE=%d",debug) ; |
---|
812 | retcode = putenv(rfio_trace) ; |
---|
813 | #endif |
---|
814 | if ( retcode == 0 ) { |
---|
815 | /* |
---|
816 | ** reopen stdout to a file like /tmp/bbftpd.rfio.trace.pid |
---|
817 | */ |
---|
818 | close(STDOUT_FILENO) ; |
---|
819 | sprintf(logmessage,"/tmp/bbftp.rfio.trace.level.%d.%d",debug,getpid()) ; |
---|
820 | (void) freopen(logmessage,"w",stdout) ; |
---|
821 | } |
---|
822 | } |
---|
823 | } else if ( be_daemon == 1 ) { |
---|
824 | /* |
---|
825 | ** Run by a remote user |
---|
826 | */ |
---|
827 | /* |
---|
828 | ** Get the username |
---|
829 | */ |
---|
830 | struct passwd *result ; |
---|
831 | if ( (result = getpwuid(getuid())) == NULL ) { |
---|
832 | syslog(BBFTPD_WARNING,"Error getting username") ; |
---|
833 | sprintf(currentusername,"UID %d",getuid()) ; |
---|
834 | } else { |
---|
835 | strcpy(currentusername,result->pw_name) ; |
---|
836 | } |
---|
837 | /* |
---|
838 | ** Set the control sock to stdin and stdout |
---|
839 | */ |
---|
840 | incontrolsock = 0 ; |
---|
841 | outcontrolsock = 1 ; |
---|
842 | /* |
---|
843 | ** As we cannot rely on the env variables to know the |
---|
844 | ** remote host, we are going to wait on an undefined |
---|
845 | ** port, send the MSG_LOGGED_STDIN and the port number |
---|
846 | ** and wait for a connection... |
---|
847 | */ |
---|
848 | checkfromwhere() ; |
---|
849 | syslog(BBFTPD_INFO,"bbftpd started by : %s from %s",currentusername,inet_ntoa(his_addr.sin_addr)) ; |
---|
850 | } else { |
---|
851 | char buffrand[NBITSINKEY] ; |
---|
852 | struct timeval tp ; |
---|
853 | unsigned int seed ; |
---|
854 | /* |
---|
855 | ** Load the error message from the crypto lib |
---|
856 | */ |
---|
857 | ERR_load_crypto_strings() ; |
---|
858 | /* |
---|
859 | ** Initialize the buffrand buffer which is giong to be used to initialize the |
---|
860 | ** random generator |
---|
861 | */ |
---|
862 | /* |
---|
863 | ** Take the usec to initialize the random session |
---|
864 | */ |
---|
865 | gettimeofday(&tp,NULL) ; |
---|
866 | seed = tp.tv_usec ; |
---|
867 | srandom(seed) ; |
---|
868 | for (i=0; i < sizeof(buffrand) ; i++) { |
---|
869 | buffrand[i] = random() ; |
---|
870 | } |
---|
871 | /* |
---|
872 | ** Initialize the random generator |
---|
873 | */ |
---|
874 | RAND_seed(buffrand,NBITSINKEY) ; |
---|
875 | incontrolsock = 0 ; |
---|
876 | outcontrolsock = incontrolsock ; |
---|
877 | msgsock = incontrolsock ; |
---|
878 | /* |
---|
879 | ** set the state |
---|
880 | */ |
---|
881 | state = S_PROTWAIT ; |
---|
882 | } |
---|
883 | fatherpid = getpid() ; |
---|
884 | if ( be_daemon == 2 || be_daemon == 0 ) { |
---|
885 | /* Get the remote address */ |
---|
886 | addrlen = sizeof(his_addr); |
---|
887 | if (getpeername(incontrolsock, (struct sockaddr *) &his_addr, &addrlen) < 0) { |
---|
888 | syslog(BBFTPD_ERR, "getpeername (%s): %s", argv[0],strerror(errno)); |
---|
889 | exit(1); |
---|
890 | } |
---|
891 | addrlen = sizeof(ctrl_addr); |
---|
892 | if (getsockname(incontrolsock, (struct sockaddr *) &ctrl_addr, &addrlen) < 0) { |
---|
893 | syslog(BBFTPD_ERR, "getsockname (%s): %s", argv[0],strerror(errno)); |
---|
894 | exit(1); |
---|
895 | } |
---|
896 | syslog(BBFTPD_INFO,"Getting new bbftp connexion from : %s",inet_ntoa(his_addr.sin_addr)) ; |
---|
897 | /* |
---|
898 | ** Send the encryption supported |
---|
899 | */ |
---|
900 | sendcrypt() ; |
---|
901 | /* |
---|
902 | ** set the state |
---|
903 | */ |
---|
904 | login: |
---|
905 | state = S_CONN ; |
---|
906 | nfds = sysconf(_SC_OPEN_MAX) ; |
---|
907 | FD_ZERO(&selectmask) ; |
---|
908 | FD_SET(incontrolsock,&selectmask) ; |
---|
909 | wait_timer.tv_sec = 10 ; |
---|
910 | wait_timer.tv_usec = 0 ; |
---|
911 | if ( (retcode = select(nfds,&selectmask,0,0,&wait_timer) ) == -1 ) { |
---|
912 | syslog(BBFTPD_ERR,"Select error : %s",strerror(errno)) ; |
---|
913 | exit(1) ; |
---|
914 | } else if ( retcode == 0 ) { |
---|
915 | syslog(BBFTPD_ERR,"Time OUT ") ; |
---|
916 | exit(1) ; |
---|
917 | } else { |
---|
918 | if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) { |
---|
919 | syslog(BBFTPD_ERR,"Error reading MSG_LOG ") ; |
---|
920 | exit(1) ; |
---|
921 | } |
---|
922 | msg = (struct message *) buffer ; |
---|
923 | if ( msg->code == MSG_SERVER_STATUS ) { |
---|
924 | sprintf(logmessage, "bbftpd version %s\n",VERSION) ; |
---|
925 | sprintf(logmessage,"%sCompiled with : default port %d\n",logmessage,CONTROLPORT) ; |
---|
926 | #ifdef WITH_GZIP |
---|
927 | sprintf(logmessage,"%s compression with Zlib-%s\n", logmessage,zlibVersion()) ; |
---|
928 | #endif |
---|
929 | sprintf(logmessage,"%s encryption with %s \n",logmessage,SSLeay_version(SSLEAY_VERSION)) ; |
---|
930 | #ifdef WITH_RFIO |
---|
931 | # ifdef CASTOR |
---|
932 | sprintf(logmessage,"%s CASTOR support (RFIO)\n",logmessage) ; |
---|
933 | # else |
---|
934 | sprintf(logmessage,"%s HPSS support (RFIO)\n",logmessage) ; |
---|
935 | # endif |
---|
936 | #endif |
---|
937 | #ifdef WITH_RFIO64 |
---|
938 | # ifdef CASTOR |
---|
939 | sprintf(logmessage,"%s CASTOR support (RFIO64)\n",logmessage) ; |
---|
940 | # else |
---|
941 | sprintf(logmessage,"%s HPSS support (RFIO64)\n",logmessage) ; |
---|
942 | # endif |
---|
943 | #endif |
---|
944 | #ifdef AFS |
---|
945 | sprintf(logmessage,"%s AFS authentication \n",logmessage) ; |
---|
946 | #endif |
---|
947 | #ifdef CERTIFICATE_AUTH |
---|
948 | sprintf(logmessage,"%s GSI authentication \n",logmessage) ; |
---|
949 | #endif |
---|
950 | #ifdef PRIVATE_AUTH |
---|
951 | sprintf(logmessage,"%s private authentication \n",logmessage) ; |
---|
952 | #ifdef NDG_AUTH |
---|
953 | sprintf(logmessage,"%s NDG private autentication/authorisation extensions \n", logmessage); |
---|
954 | #endif // NDG_AUTH |
---|
955 | #endif |
---|
956 | #ifdef NDG_PYTHON_EMBED |
---|
957 | sprintf(logmessage,"%s NDG server embedded in Python \n", logmessage); |
---|
958 | sprintf(logmessage,"%sRunning options:\n",logmessage) ; |
---|
959 | sprintf(logmessage,"%s Maximum number of streams = %d \n",logmessage,maxstreams) ; |
---|
960 | if (pasvport_min) { |
---|
961 | sprintf(logmessage,"%s data ports range = [%d-%d] \n", logmessage,pasvport_min, pasvport_max) ; |
---|
962 | } |
---|
963 | #endif // NDG_PYTHON_EMBED |
---|
964 | #ifdef CERTIFICATE_AUTH |
---|
965 | if (accept_pass_only) { |
---|
966 | sprintf(logmessage, "%s The server only accepts USER/PASS\n",logmessage); |
---|
967 | } |
---|
968 | if (accept_certs_only) { |
---|
969 | sprintf(logmessage, "%s The server only accepts certificates\n",logmessage); |
---|
970 | } |
---|
971 | #endif |
---|
972 | #ifndef PRIVATE_AUTH |
---|
973 | if (force_encoding) { |
---|
974 | sprintf(logmessage, "%s The server requires encrypted login\n",logmessage); |
---|
975 | } else { |
---|
976 | sprintf(logmessage, "%s The server allows non-encrypted login\n",logmessage); |
---|
977 | } |
---|
978 | #endif |
---|
979 | |
---|
980 | |
---|
981 | reply(MSG_OK,logmessage); |
---|
982 | exit(0); |
---|
983 | } |
---|
984 | #ifdef CERTIFICATE_AUTH |
---|
985 | if ( msg->code == MSG_CERT_LOG ) { |
---|
986 | int retval; |
---|
987 | if (accept_pass_only) { |
---|
988 | sprintf(logmessage, "The server only accepts USER/PASS"); |
---|
989 | syslog(BBFTPD_ERR,"%s",logmessage) ; |
---|
990 | reply(MSG_BAD_NO_RETRY,logmessage); |
---|
991 | exit(1); |
---|
992 | } |
---|
993 | retval=bbftpd_cert_receive_connection(msg->msglen); |
---|
994 | if ( retval < 0 ) { |
---|
995 | /* |
---|
996 | ** The login failed, do not wait for a new one |
---|
997 | */ |
---|
998 | exit(1) ; |
---|
999 | } |
---|
1000 | /* |
---|
1001 | ** If retval >0, means an MSG_WARN has been sent already |
---|
1002 | */ |
---|
1003 | state = S_PROTWAIT ; |
---|
1004 | if (retval == 0) { |
---|
1005 | sprintf(logmessage,"bbftpd version %s : OK",VERSION) ; |
---|
1006 | reply(MSG_OK,logmessage) ; |
---|
1007 | } |
---|
1008 | } else if ( msg->code == MSG_LOG ) { |
---|
1009 | if (accept_certs_only) { |
---|
1010 | sprintf(logmessage, "The server only accepts certificates"); |
---|
1011 | syslog(BBFTPD_ERR,"%s",logmessage) ; |
---|
1012 | reply(MSG_BAD_NO_RETRY,logmessage); |
---|
1013 | } else { |
---|
1014 | /* |
---|
1015 | ** It seems that it is the message we were waiting |
---|
1016 | ** so lets decrypt |
---|
1017 | */ |
---|
1018 | if ( loginsequence() < 0 ) { |
---|
1019 | /* |
---|
1020 | ** The login failed, do not wait for a new one |
---|
1021 | */ |
---|
1022 | exit(1) ; |
---|
1023 | } |
---|
1024 | state = S_PROTWAIT ; |
---|
1025 | sprintf(logmessage,"bbftpd version %s : OK",VERSION) ; |
---|
1026 | reply(MSG_OK,logmessage) ; |
---|
1027 | } |
---|
1028 | } else if (msg->code == MSG_CRYPT) { |
---|
1029 | if (accept_certs_only) { |
---|
1030 | sprintf(logmessage, "The server only accepts certificates"); |
---|
1031 | reply(MSG_BAD_NO_RETRY,logmessage); |
---|
1032 | } else if (force_encoding) { |
---|
1033 | /* |
---|
1034 | ** The client can't encode and ask if it can send uncrypted |
---|
1035 | ** login information |
---|
1036 | */ |
---|
1037 | sprintf(logmessage, "The server requires encrypted login"); |
---|
1038 | reply(MSG_BAD_NO_RETRY,logmessage); |
---|
1039 | } else { |
---|
1040 | sprintf(logmessage, "Uncrypted login dialog accepted"); |
---|
1041 | reply(MSG_OK,logmessage); |
---|
1042 | goto login; |
---|
1043 | } |
---|
1044 | } else { |
---|
1045 | syslog(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ; |
---|
1046 | reply(MSG_BAD,"Unkown message in connected state") ; |
---|
1047 | exit(1) ; |
---|
1048 | } |
---|
1049 | #else |
---|
1050 | #ifndef PRIVATE_AUTH |
---|
1051 | if ( msg->code == MSG_LOG ) { |
---|
1052 | /* |
---|
1053 | ** It seems that it is the message we were waiting |
---|
1054 | ** so lets decrypt |
---|
1055 | */ |
---|
1056 | if ( loginsequence() < 0 ) { |
---|
1057 | /* |
---|
1058 | ** The login failed, do not wait for a new one |
---|
1059 | */ |
---|
1060 | exit(1) ; |
---|
1061 | } |
---|
1062 | state = S_PROTWAIT ; |
---|
1063 | sprintf(logmessage,"bbftpd version %s : OK",VERSION) ; |
---|
1064 | reply(MSG_OK,logmessage) ; |
---|
1065 | } else if (msg->code == MSG_CRYPT) { |
---|
1066 | /* |
---|
1067 | ** The client can't encode and ask if it can send uncrypted |
---|
1068 | ** login information |
---|
1069 | */ |
---|
1070 | if (force_encoding) { |
---|
1071 | sprintf(logmessage, "The server requires encrypted login"); |
---|
1072 | reply(MSG_BAD_NO_RETRY,logmessage); |
---|
1073 | exit(1); |
---|
1074 | } |
---|
1075 | sprintf(logmessage, "Uncrypted login dialog accepted"); |
---|
1076 | reply(MSG_OK,logmessage); |
---|
1077 | goto login; |
---|
1078 | } else { |
---|
1079 | syslog(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ; |
---|
1080 | reply(MSG_BAD,"Unkown message in connected state") ; |
---|
1081 | exit(1) ; |
---|
1082 | } |
---|
1083 | #else |
---|
1084 | if ( msg->code == MSG_PRIV_LOG ) { |
---|
1085 | if ( bbftpd_private_receive_connection(msg->msglen) < 0 ) { |
---|
1086 | /* |
---|
1087 | ** The login failed, do not wait for a new one |
---|
1088 | */ |
---|
1089 | exit(1) ; |
---|
1090 | } |
---|
1091 | state = S_PROTWAIT ; |
---|
1092 | sprintf(logmessage,"bbftpd version %s : OK",VERSION) ; |
---|
1093 | reply(MSG_OK,logmessage) ; |
---|
1094 | } else { |
---|
1095 | syslog(BBFTPD_ERR,"Unkown message in connected state : %d",msg->code) ; |
---|
1096 | reply(MSG_BAD,"Unkown message in connected state") ; |
---|
1097 | exit(1) ; |
---|
1098 | } |
---|
1099 | #endif |
---|
1100 | #endif |
---|
1101 | } |
---|
1102 | } |
---|
1103 | |
---|
1104 | /* |
---|
1105 | ** At this stage we are in the S_PROTWAIT state |
---|
1106 | */ |
---|
1107 | nfds = sysconf(_SC_OPEN_MAX) ; |
---|
1108 | FD_ZERO(&selectmask) ; |
---|
1109 | FD_SET(incontrolsock,&selectmask) ; |
---|
1110 | wait_timer.tv_sec = 10 ; |
---|
1111 | wait_timer.tv_usec = 0 ; |
---|
1112 | if ( (retcode = select(nfds,&selectmask,0,0,&wait_timer) ) == -1 ) { |
---|
1113 | syslog(BBFTPD_ERR,"Select error in S_PROTWAIT state : %s",strerror(errno)) ; |
---|
1114 | exit(1) ; |
---|
1115 | } else if ( retcode == 0 ) { |
---|
1116 | syslog(BBFTPD_ERR,"Time OUT in S_PROTWAIT state") ; |
---|
1117 | exit(1) ; |
---|
1118 | } else { |
---|
1119 | if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) { |
---|
1120 | syslog(BBFTPD_ERR,"Error reading in S_PROTWAIT state") ; |
---|
1121 | exit(1) ; |
---|
1122 | } |
---|
1123 | msg = (struct message *) buffer ; |
---|
1124 | if ( msg->code == MSG_PROT ) { |
---|
1125 | /* |
---|
1126 | ** The client is using bbftp v2 protocol or higher |
---|
1127 | */ |
---|
1128 | if ( checkprotocol() < 0 ) { |
---|
1129 | exit_clean() ; |
---|
1130 | exit(1) ; |
---|
1131 | } |
---|
1132 | syslog(BBFTPD_INFO,"Using bbftp protocol version %d",protocolversion) ; |
---|
1133 | state = S_LOGGED ; |
---|
1134 | /* |
---|
1135 | ** Initialize the variables |
---|
1136 | */ |
---|
1137 | mychildren = NULL ; |
---|
1138 | nbpidchild = 0 ; |
---|
1139 | curfilename = NULL ; |
---|
1140 | curfilenamelen = 0 ; |
---|
1141 | } else { |
---|
1142 | /* |
---|
1143 | ** This is a bbftp v1 client |
---|
1144 | */ |
---|
1145 | protocolversion = 1 ; |
---|
1146 | syslog(BBFTPD_INFO,"Using bbftp protocol version 1") ; |
---|
1147 | state = S_LOGGED ; |
---|
1148 | /* |
---|
1149 | ** So set up the v1 handlers |
---|
1150 | */ |
---|
1151 | if ( set_signals_v1() < 0 ) { |
---|
1152 | exit(1) ; |
---|
1153 | } |
---|
1154 | /* |
---|
1155 | ** Initialize the pid array |
---|
1156 | */ |
---|
1157 | for ( i=0 ; i< MAXPORT ; i++) { |
---|
1158 | pid_child[i] = 0 ; |
---|
1159 | } |
---|
1160 | /* |
---|
1161 | ** As we have already read the message |
---|
1162 | */ |
---|
1163 | if ( readcontrol(msg->code,msg->msglen) < 0 ) { |
---|
1164 | clean_child() ; |
---|
1165 | exit_clean() ; |
---|
1166 | exit(0) ; |
---|
1167 | } |
---|
1168 | } |
---|
1169 | } |
---|
1170 | if ( protocolversion == 1 ) goto loopv1 ; |
---|
1171 | if ( protocolversion == 2 || protocolversion == 3) goto loopv2 ; |
---|
1172 | syslog(BBFTPD_ERR,"Unknown protocol version %d",protocolversion) ; |
---|
1173 | exit(1) ; |
---|
1174 | /* |
---|
1175 | ** Loop for the v2 protocol (also available for v3) |
---|
1176 | */ |
---|
1177 | loopv2: |
---|
1178 | /* |
---|
1179 | ** Set up v2 handlers |
---|
1180 | */ |
---|
1181 | if ( bbftpd_setsignals() < 0 ) { |
---|
1182 | exit(1) ; |
---|
1183 | } |
---|
1184 | /* |
---|
1185 | ** Set the umask ; first unset it and then reset to the default value |
---|
1186 | */ |
---|
1187 | umask(0) ; |
---|
1188 | umask(myumask) ; |
---|
1189 | for (;;) { |
---|
1190 | /* |
---|
1191 | ** Initialize the selectmask |
---|
1192 | */ |
---|
1193 | nfds = sysconf(_SC_OPEN_MAX) ; |
---|
1194 | FD_ZERO(&selectmask) ; |
---|
1195 | FD_SET(incontrolsock,&selectmask) ; |
---|
1196 | /* |
---|
1197 | ** Depending on the state set a timer or not |
---|
1198 | */ |
---|
1199 | switch (state) { |
---|
1200 | case S_WAITING_STORE_START : |
---|
1201 | case S_WAITING_FILENAME_STORE : |
---|
1202 | case S_WAITING_FILENAME_RETR : { |
---|
1203 | /* |
---|
1204 | ** Timer of 10s between XX_V2 and FILENAME_XX |
---|
1205 | */ |
---|
1206 | wait_timer.tv_sec = 10 ; |
---|
1207 | wait_timer.tv_usec = 0 ; |
---|
1208 | break ; |
---|
1209 | } |
---|
1210 | |
---|
1211 | case S_SENDING : |
---|
1212 | case S_RECEIVING : { |
---|
1213 | /* |
---|
1214 | ** No timer while receiving or sending |
---|
1215 | */ |
---|
1216 | wait_timer.tv_sec = 0 ; |
---|
1217 | wait_timer.tv_usec = 0 ; |
---|
1218 | break ; |
---|
1219 | } |
---|
1220 | default : { |
---|
1221 | /* |
---|
1222 | ** Timer of 900s between commands |
---|
1223 | */ |
---|
1224 | wait_timer.tv_sec = 900 ; |
---|
1225 | wait_timer.tv_usec = 0 ; |
---|
1226 | break ; |
---|
1227 | } |
---|
1228 | } |
---|
1229 | if ( (retcode = select(nfds,&selectmask,0,0,(wait_timer.tv_sec == 0) ? NULL : &wait_timer) ) == -1 ) { |
---|
1230 | if ( errno != EINTR ) { |
---|
1231 | syslog(BBFTPD_ERR,"Select error : %s",strerror(errno)) ; |
---|
1232 | } |
---|
1233 | } else if ( retcode == 0 ) { |
---|
1234 | syslog(BBFTPD_ERR,"Time OUT ") ; |
---|
1235 | if ( state == S_WAITING_STORE_START ) { |
---|
1236 | bbftpd_storeunlink(realfilename) ; |
---|
1237 | } |
---|
1238 | clean_child() ; |
---|
1239 | exit_clean() ; |
---|
1240 | exit(0) ; |
---|
1241 | } else { |
---|
1242 | /* |
---|
1243 | ** At this stage we can only receive a command |
---|
1244 | */ |
---|
1245 | if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) { |
---|
1246 | if ( state == S_WAITING_STORE_START || state == S_RECEIVING) { |
---|
1247 | bbftpd_storeunlink(realfilename) ; |
---|
1248 | sleep(5) ; |
---|
1249 | } |
---|
1250 | clean_child() ; |
---|
1251 | exit_clean() ; |
---|
1252 | exit(0) ; |
---|
1253 | } |
---|
1254 | if ( bbftpd_readcontrol(msg->code,msg->msglen) < 0 ) { |
---|
1255 | clean_child() ; |
---|
1256 | exit_clean() ; |
---|
1257 | exit(0) ; |
---|
1258 | } else { |
---|
1259 | } |
---|
1260 | } |
---|
1261 | } |
---|
1262 | /* |
---|
1263 | ** Loop for the v1 protocol |
---|
1264 | */ |
---|
1265 | loopv1: |
---|
1266 | for (;;) { |
---|
1267 | /* |
---|
1268 | ** Initialize the selectmask |
---|
1269 | */ |
---|
1270 | nfds = sysconf(_SC_OPEN_MAX) ; |
---|
1271 | FD_ZERO(&selectmask) ; |
---|
1272 | FD_SET(incontrolsock,&selectmask) ; |
---|
1273 | /* |
---|
1274 | ** Depending on the state set a timer or not |
---|
1275 | */ |
---|
1276 | switch (state) { |
---|
1277 | case S_SENDING : |
---|
1278 | case S_RECEIVING : { |
---|
1279 | /* |
---|
1280 | ** No timer while receiving or sending |
---|
1281 | */ |
---|
1282 | wait_timer.tv_sec = 0 ; |
---|
1283 | wait_timer.tv_usec = 0 ; |
---|
1284 | break ; |
---|
1285 | } |
---|
1286 | default : { |
---|
1287 | /* |
---|
1288 | ** Timer of 900s between commands |
---|
1289 | */ |
---|
1290 | wait_timer.tv_sec = 900 ; |
---|
1291 | wait_timer.tv_usec = 0 ; |
---|
1292 | break ; |
---|
1293 | } |
---|
1294 | } |
---|
1295 | if ( (retcode = select(nfds,&selectmask,0,0,(wait_timer.tv_sec == 0) ? NULL : &wait_timer) ) == -1 ) { |
---|
1296 | if ( errno != EINTR ) { |
---|
1297 | syslog(BBFTPD_ERR,"Select error : %s",strerror(errno)) ; |
---|
1298 | } |
---|
1299 | } else if ( retcode == 0 ) { |
---|
1300 | syslog(BBFTPD_ERR,"Time OUT ") ; |
---|
1301 | clean_child() ; |
---|
1302 | exit_clean() ; |
---|
1303 | exit(0) ; |
---|
1304 | } else { |
---|
1305 | /* |
---|
1306 | ** At this stage we can only receive a command |
---|
1307 | */ |
---|
1308 | if ( (retcode = readmessage(incontrolsock,buffer,MINMESSLEN,recvcontrolto)) < 0 ) { |
---|
1309 | clean_child() ; |
---|
1310 | exit_clean() ; |
---|
1311 | exit(0) ; |
---|
1312 | } |
---|
1313 | if ( readcontrol(msg->code,msg->msglen) < 0 ) { |
---|
1314 | clean_child() ; |
---|
1315 | exit_clean() ; |
---|
1316 | exit(0) ; |
---|
1317 | } else { |
---|
1318 | } |
---|
1319 | } |
---|
1320 | } |
---|
1321 | } |
---|
1322 | |
---|
1323 | void clean_child() |
---|
1324 | { |
---|
1325 | int *pidfree ; |
---|
1326 | int i ; |
---|
1327 | |
---|
1328 | if ( protocolversion == 0 ) return ; |
---|
1329 | if ( protocolversion == 1 ) { |
---|
1330 | if ( killdone == 0 ) { |
---|
1331 | killdone = 1 ; |
---|
1332 | for ( i=0 ; i<MAXPORT ; i++) { |
---|
1333 | if ( pid_child[i] != 0 ) { |
---|
1334 | syslog(BBFTPD_DEBUG,"Killing child %d",pid_child[i]) ; |
---|
1335 | kill(pid_child[i],SIGKILL) ; |
---|
1336 | } |
---|
1337 | } |
---|
1338 | } |
---|
1339 | return ; |
---|
1340 | } |
---|
1341 | if ( protocolversion >= 2 ) { |
---|
1342 | if ( killdone == 0 ) { |
---|
1343 | killdone = 1 ; |
---|
1344 | pidfree = mychildren ; |
---|
1345 | for ( i=0 ; i<nbpidchild ; i++) { |
---|
1346 | if ( *pidfree != 0 ) { |
---|
1347 | syslog(BBFTPD_DEBUG,"Killing child %d",*pidfree) ; |
---|
1348 | kill(*pidfree,SIGKILL) ; |
---|
1349 | } |
---|
1350 | pidfree++ ; |
---|
1351 | } |
---|
1352 | } |
---|
1353 | return ; |
---|
1354 | } |
---|
1355 | } |
---|
1356 | |
---|
1357 | void exit_clean() |
---|
1358 | { |
---|
1359 | |
---|
1360 | switch (state) { |
---|
1361 | case S_CONN : { |
---|
1362 | return ; |
---|
1363 | } |
---|
1364 | case S_LOGGED : |
---|
1365 | case S_PROTWAIT : |
---|
1366 | case S_WAITING_FILENAME_STORE : |
---|
1367 | case S_WAITING_STORE_START : |
---|
1368 | case S_SENDING: |
---|
1369 | case S_RECEIVING : { |
---|
1370 | syslog(BBFTPD_INFO,"User %s disconnected",currentusername) ; |
---|
1371 | return ; |
---|
1372 | } |
---|
1373 | default :{ |
---|
1374 | return ; |
---|
1375 | } |
---|
1376 | } |
---|
1377 | } |
---|
1378 | |
---|
1379 | my64_t convertlong(my64_t v) { |
---|
1380 | struct bb { |
---|
1381 | int fb ; |
---|
1382 | int sb ; |
---|
1383 | } ; |
---|
1384 | struct bb *bbpt ; |
---|
1385 | int tmp ; |
---|
1386 | my64_t tmp64 ; |
---|
1387 | |
---|
1388 | tmp64 = v ; |
---|
1389 | bbpt = (struct bb *) &tmp64 ; |
---|
1390 | tmp = bbpt->fb ; |
---|
1391 | bbpt->fb = ntohl(bbpt->sb) ; |
---|
1392 | bbpt->sb = ntohl(tmp) ; |
---|
1393 | return tmp64 ; |
---|
1394 | } |
---|
1395 | |
---|
1396 | #ifndef HAVE_NTOHLL |
---|
1397 | my64_t ntohll(my64_t v) { |
---|
1398 | # ifdef HAVE_BYTESWAP_H |
---|
1399 | return bswap_64(v); |
---|
1400 | # else |
---|
1401 | long lo = v & 0xffffffff; |
---|
1402 | long hi = v >> 32U; |
---|
1403 | lo = ntohl(lo); |
---|
1404 | hi = ntohl(hi); |
---|
1405 | return ((my64_t) lo) << 32U | hi; |
---|
1406 | # endif |
---|
1407 | } |
---|
1408 | #define htonll ntohll |
---|
1409 | #endif |
---|
1410 | |
---|