1 /* utftpd: the tftp daemon */
2
3 /*
4 * Copyright (C) 1999 Uwe Ohse
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "config.h"
22 #include <sys/types.h>
23 #include <sys/ioctl.h>
24 #include <sys/stat.h>
25 #include <signal.h>
26 #include <fcntl.h>
27
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include "no_tftp.h"
31 #include <netdb.h>
32 #include <pwd.h>
33 #include <grp.h>
34 #ifdef HAVE_ARPA_INET_H
35 #include <arpa/inet.h>
36 #endif
37
38 #include <syslog.h>
39 #include <errno.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include "uogetopt.h"
44 #include "timselsysdep.h"
45 #include "timing.h"
46 #include "nonblock.h"
47 #include "str2num.h"
48 #include "uostr.h"
49 #include "uoio.h"
50 #include "cdb.h"
51 #include "sys/wait.h"
52 #include "wildmat.h"
53 #include "utftpd.h"
54 #include "str_ulong.h"
55 #include "uosock.h"
56
57 #ifndef errno
58 extern int errno;
59 #endif
60
61 int nullfd;
62
63 #define TFTP_OFFSET 4
64 static struct utftpd_ctrl *ctrl;
65
66 static uostr_t rules=UOSTR_INIT;
67 ssize_t got;
68
69 static char *opt_configfile;
70 static char *opt_global_chdir;
71 #ifdef HAVE_CHROOT
72 static char *opt_global_chroot;
73 #endif
74 static char *opt_global_uid;
75 static char **opt_old_style_ac;
76 int opt_verbose;
77
78 /* from configfile */
79 static char *opt_chdir;
80 static char *opt_chroot;
81 static char *opt_write;
82 static char *opt_create;
83 static char *opt_read;
84 static char *opt_uid;
85 char *opt_rcs_ci;
86 char *opt_rcs_co;
87 char *opt_sccs_get;
88 char *opt_sccs_unget;
89 char *opt_sccs_clean;
90 char *opt_sccs_delta;
91 static int opt_syslog; /* "-l" option of inetutils tftpd. This is just a dummy variable */
92 static int opt_keeprun;
93 static const char *opt_standalone;
94 int opt_suppress_naks;
95 int opt_timing;
96
97 static const char *need_commit; /* a filename */
98 static char *argv0;
99
100 char *remoteip=NULL;
101 static struct utftpd_ctrl *
102 utftpd_setup_ctrl(struct utftpd_ctrl *old, size_t segsize);
103
104 static uogetopt_t myopts[]={
105 {'c',"config-file", UOGO_STRING,&opt_configfile,0,
106 "Specify location of configuration file.\n"
107 "This has to be a cdb file, created by utftpd_make.\n"
108 "It will be opened before a chroot, if any.","CDBFILE"},
109 #ifdef HAVE_CHROOT
110 {'C',"global-chroot", UOGO_STRING,&opt_global_chroot,0,
111 /*12345678901234567890123456789012345678901234567890 */
112 "Chroot to DIRECTORY before reading configuration.\n"
113 "This will change the working directory, too.","DIR"},
114 #endif
115 {'d',"global-chdir", UOGO_STRING,&opt_global_chdir,0,
116 "Chdir to DIRECTORY before reading configuration.\n"
117 "This will happen _after_ the chroot.", "DIR"},
118 {'k',"keeprunning", UOGO_FLAG,&opt_keeprun,1,
119 "Accept other request until all are finished",0},
120 {'l',0, UOGO_FLAG,&opt_syslog,1,
121 "Log all request to syslog() (active by default).\n"
122 "This option is for compatability",0},
123 {'n',"suppress-naks", UOGO_FLAG,&opt_suppress_naks,1,
124 "Suppress NAKs for nonexistant files.\n"
125 /*12345678901234567890123456789012345678901234567890 */
126 "Don't send ACK on read requests for nonexistant\n"
127 "relative filenames.",0},
128 {'s',"standalone", UOGO_STRING,&opt_standalone,1,
129 "Don't use inetd.\n"
130 "Needs an address and port to bind to:\n"
131 " HOST:PORT -> bind to address HOST, port PORT\n"
132 " HOST -> bind to address HOST, port 69\n"
133 " HOST: -> same\n"
134 " :PORT -> bind to IPADDR_ANY, port PORT\n"
135 " : -> bind to IPADDR_ANY, port 69\n" ,"ADDRESS:PORT"},
136 {'t',"timing", UOGO_FLAG,&opt_timing,1,
137 "Log transfer rates to syslog().",0},
138 {'u',"global-uid", UOGO_STRING,&opt_global_uid,0,
139 "Change user id before reading configuration.\n"
140 "Use \"user.group\" to spefify a group.\n"
141 "Use \".group\" to specify only a group.\n"
142 "Numerical ids are allowed, as are names."
143 ,0},
144 {'v',"verbose", UOGO_FLAG,&opt_verbose,1,
145 "Be verbose to syslog().",0},
146 { 0,"copyright", UOGO_HIDDEN|UOGO_PRINT,0,0,
147 "Copyright (C) 1999 Uwe Ohse\n"
148 PACKAGE " comes with NO WARRANTY,\n"
149 "to the extent permitted by law.\n"
150 "You may redistribute copies of " PACKAGE "\n"
151 "under the terms of the GNU General Public License.\n"
152 "For more information about these matters,\n"
153 "see the files named COPYING.\n"
154 ,0},
155 {0,0,0,0,0,0,0}
156 };
157
158 static struct utftpd_vc *
find_vc(const char * filename,struct utftpd_ctrl * flags)159 find_vc(const char *filename, struct utftpd_ctrl *flags)
160 {
161 if (0==utftpd_sccs.test(filename,flags)) return &utftpd_sccs;
162 if (0==utftpd_rcs.test(filename,flags)) return &utftpd_rcs;
163 return &utftpd_novc;
164 }
165
166 static char *
rule_lookup(const char * tag)167 rule_lookup(const char *tag)
168 {
169 char *s;
170 size_t tl=strlen(tag);
171 s=rules.data;
172 while (*s) {
173 char *nul;
174 char *eq;
175 char *q;
176 char *end;
177 int found=0;
178 end=rules.data+rules.len;
179 eq=s;
180 while (eq!=end && *eq!='=') eq++;
181 if (eq==end) goto bad_format;
182 nul=eq+1;
183 while (nul!=end && *nul!='\0') nul++;
184 if (nul==end) goto bad_format;
185 q=strstr(s,tag);
186 if (q && (q==s || q[-1]==',') && (q[tl]=='=' || q[tl]==','))
187 found=1;
188 if (found) {
189 char *v;
190 v=(char *) malloc(nul-eq);
191 if (!v) goto oom;
192 memcpy(v,eq+1,nul-eq);
193 if (opt_verbose)
194 syslog(LOG_INFO,"CONFIG %s=%s",tag,v);
195 return v;
196 }
197 s=nul+1;
198 if (s==end) break;
199 }
200 return NULL;
201 bad_format:
202 syslog(LOG_ERR,"bad config file %s",opt_configfile);
203 _exit(1);
204 oom:
205 syslog(LOG_ERR,"out of memory");
206 _exit(1);
207 }
208
209 static void
do_config(int config_fd)210 do_config(int config_fd)
211 {
212 int did_default=0;
213 uostr_t a;
214 a.data=0;
215 if (!uostr_dup_cstr(&a,remoteip)) goto oom;
216
217 /* try 1.2.3.4 1.2.3. 1.2. 1. */
218 while (a.len || !did_default) {
219 uint32 dlen32;
220 unsigned int datalen;
221 if (!a.len)
222 did_default=0;
223 switch(cdb_seek(config_fd,
224 (const unsigned char *) (a.len ? a.data : "default"),
225 a.len ? a.len : 7,
226 &dlen32)) {
227 case -1: goto some_error;
228 case 0: break;
229 default:
230 datalen = dlen32;
231 if (!uostr_needmore(&rules,datalen)) goto oom;
232 if (cdb_bread(config_fd,
233 (unsigned char *)(rules.data+rules.len),
234 datalen) != 0) goto some_error;
235 rules.len+=datalen;
236 break;
237 }
238 if (!a.len)
239 break;
240 a.len--;
241 while (a.len) {
242 if (a.data[a.len-1]=='.')
243 break;
244 a.len--;
245 }
246 }
247 if (!rules.data)
248 return;
249 if (!uostr_add_mem(&rules,"",1)) goto oom;
250 opt_uid=rule_lookup("uid");
251 opt_chroot=rule_lookup("root");
252 opt_chdir=rule_lookup("dir");
253 opt_read=rule_lookup("read");
254 opt_write=rule_lookup("write");
255 opt_create=rule_lookup("create");
256 opt_sccs_clean=rule_lookup("sccs-clean"); if (opt_sccs_clean && !*opt_sccs_clean) opt_sccs_clean=0;
257 opt_sccs_unget=rule_lookup("sccs-unget"); if (opt_sccs_unget && !*opt_sccs_unget) opt_sccs_unget=0;
258 opt_sccs_get=rule_lookup("sccs-get"); if (opt_sccs_get && !*opt_sccs_get) opt_sccs_get=0;
259 opt_sccs_delta=rule_lookup("sccs-delta"); if (opt_sccs_delta && !*opt_sccs_delta) opt_sccs_delta=0;
260 opt_rcs_ci=rule_lookup("rcs-ci"); if (opt_rcs_ci && !*opt_rcs_ci) opt_rcs_ci=0;
261 opt_rcs_co=rule_lookup("rcs-co"); if (opt_rcs_co && !*opt_rcs_co) opt_rcs_co=0;
262 return;
263 some_error:
264 syslog(LOG_ERR,"error reading %s: %s",opt_configfile,strerror(errno));
265 _exit(1);
266 oom:
267 syslog(LOG_ERR,"out of memory");
268 _exit(1);
269 }
270
271 static void
get_ids(char * str,uid_t * puid,gid_t * pgid)272 get_ids(char *str,uid_t *puid, gid_t *pgid)
273 {
274 uid_t uid;
275 unsigned long ul;
276 char *dot;
277 *pgid=(uid_t) -1; /* magic */
278 *puid=(gid_t) -1; /* magic */
279 dot=strchr(str,'.');
280 if (!dot) dot=strchr(str,':');
281 if (dot) {
282 gid_t gid;
283 *dot++=0;
284 if (0>=str2ulong(dot,&ul,0)) {
285 struct group * g;
286 g=getgrnam(dot);
287 if (!g) {
288 syslog(LOG_ERR,"%s is not a valid group name",dot);
289 _exit(1);
290 }
291 gid=g->gr_gid;
292 } else {
293 gid=(gid_t) ul;
294 if ((unsigned long) gid != ul) {
295 syslog(LOG_ERR,"%s is not a valid group number",dot);
296 _exit(1);
297 }
298 }
299 *pgid=gid;
300 }
301 if (!*str) /* .gid */
302 return;
303
304 if (0>=str2ulong(str,&ul,0)) {
305 struct passwd * pw;
306 pw=getpwnam(str);
307 if (!pw) {
308 syslog(LOG_ERR,"%s is not a valid user name",str);
309 _exit(1);
310 }
311 uid=pw->pw_uid;
312 } else {
313 uid=(uid_t) ul;
314 if ((unsigned long) uid != ul) {
315 syslog(LOG_ERR,"%s is not a valid user number",str);
316 _exit(1);
317 }
318 }
319 *puid=uid;
320 }
321
322 static void
set_ids(uid_t uid,gid_t gid)323 set_ids(uid_t uid, gid_t gid)
324 {
325 if (gid != (gid_t) -1 && -1==setgid(gid)) {
326 syslog(LOG_ERR,"setgid(%lu): %s",(unsigned long) gid, strerror(errno));
327 _exit(1);
328 }
329 if (uid!=(uid_t) -1 && -1==setuid(uid)) {
330 syslog(LOG_ERR,"setuid(%lu): %s",(unsigned long) uid, strerror(errno));
331 _exit(1);
332 }
333 }
334
335 void
do_nak(int peer,int ec,const char * et)336 do_nak(int peer, int ec, const char *et)
337 {
338 utftpd_nak(peer,ec,et,ctrl);
339 }
340
341 static char *
qualify(const char * prefix,const char * filename)342 qualify(const char *prefix, const char *filename)
343 {
344 char *n;
345 size_t l1,l2;
346 l1=strlen(prefix);
347 l2=strlen(filename);
348 n=(char *) malloc(l1+l2+2);
349 if (!n) return 0;
350 memcpy(n,prefix,l1);
351 if (prefix[l1-1]!='/')
352 n[l1++]='/';
353 memcpy(n+l1,filename,l2+1);
354 return n;
355 }
356
357 static const char *
qualify_filename(int peer,int opcode,const char * filename)358 qualify_filename(int peer, int opcode, const char *filename)
359 {
360 const char *old_filename=filename;
361 /* first qualify the filename, if it doesn't start with a / */
362 /* this is actually very simple, although it looks somewhat complicated:
363 * prefix with opt_chdir (from configfile), and if that's still not enough:
364 * prefix with opt_global_chdir, if we didn't chroot since then
365 */
366 if (*filename!='/' && opt_chdir) {
367 filename=qualify(opt_chdir,filename);
368 if (!filename) goto oom;
369 }
370 if (*filename!='/' && opt_global_chdir && !opt_chroot) {
371 filename=qualify(opt_global_chdir,filename);
372 if (!filename) goto oom;
373 }
374 if (*filename!='/') {
375 if (!opt_configfile) {
376 char **a;
377 uostr_t s;
378 /* traditional mode */
379 if (opcode!=RRQ) {
380 syslog(LOG_ERR,"denied write access to relative filename");
381 do_nak(peer, EACCESS,"denied write access to relative filename");
382 _exit(1);
383 }
384 /* walk through all directories trying to find that file */
385 s.data=0;
386 a=opt_old_style_ac;
387 while (*a) {
388 struct stat st;
389 if (!uostr_dup_cstr(&s,*a)) goto oom;
390 if (!uostr_add_mem(&s,"/",1)) goto oom;
391 if (!uostr_add_cstr(&s,filename)) goto oom;
392 if (!uostr_add_mem(&s,"",1)) goto oom;
393 if (0==stat(s.data,&st)) {
394 if (S_ISREG(st.st_mode) && (st.st_mode & S_IROTH) != 0) {
395 filename=s.data;
396 return filename;
397 }
398 break;
399 }
400 a++;
401 }
402 syslog(LOG_ERR,"denied read access to relative filename");
403 do_nak(peer, EACCESS,"access denied");
404 _exit(1);
405 }
406 filename=qualify("/",filename);
407 if (!filename) goto oom;
408 }
409 if (opt_verbose && filename!=old_filename) syslog(LOG_INFO,"qualified filename %s to %s",old_filename,filename);
410 return filename;
411 oom:
412 syslog(LOG_ERR,"out of memory");
413 do_nak(peer, EUNDEF,"out of memory");
414 _exit(1);
415 }
416
417 #define AC_READ 0
418 #define AC_WRITE 1
419 #define AC_CREATE 2
420 static struct utftpd_vc *
check_access(const char * dir,const char * filename,int mode)421 check_access(const char *dir,const char *filename, int mode)
422 {
423 int ok=0;
424 struct utftpd_vc *vc;
425 /* prevent simple trickery */
426 if (strstr(filename,"/../")) goto deny;
427 if (!dir && !opt_configfile) {
428 /* old style compatibility */
429 char **a=opt_old_style_ac;
430 /* /xx will allow /xx/y, but not /xxy */
431 while (*a) {
432 size_t l=strlen(*a);
433 if (l==1 && **a=='/') break; /* "/" */
434 if (0==strncmp(filename,*a,l) && filename[l]=='/') break;
435 a++;
436 }
437 if (*a) {
438 /* found it. now check access rights */
439 struct stat st;
440 if (stat(filename,&st)==-1) goto deny;
441 if (!S_ISREG(st.st_mode)) goto deny;
442 if (mode==AC_READ) {
443 if (st.st_mode & S_IROTH) {
444 utftpd_novc.checkout(TSG_READ,ctrl);
445 return &utftpd_novc;
446 }
447 } else {
448 if (st.st_mode & S_IWOTH) {
449 utftpd_novc.checkout(TSG_WRITE,ctrl);
450 return &utftpd_novc;
451 }
452 }
453 }
454 goto deny;
455 }
456 if (!dir || !*dir) /* means: no dir found in config file */
457 goto deny;
458 if (opt_verbose) syslog(LOG_INFO,"check access to %s against %s",filename,dir);
459 /* go through the list of directories */
460 while (dir) {
461 char *dp=strchr(dir,':');
462 size_t l;
463 if (dp) {
464 *dp=0;
465 l=dp-dir;
466 } else
467 l=strlen(dir);
468 /* cut of trailing / */
469 while (l && dir[l-1]=='/') l--;
470 if (0==l) {
471 /* uah, access to root directory allowed. Hope admin chroot()ed */
472 ok=1;
473 } else {
474 if (0==memcmp(filename,dir,l)) { /* "/xxx/Z" | "/xxxB/Z", "/xxxA" | "/xxx", 4|5 */
475 if (filename[l]=='/' || filename[l]=='\0')
476 ok=1;
477 }
478 if (!ok) ok=dir_wildmat(filename,dir);
479 }
480 if (ok) break;
481 if (dp) dir=dp+1;
482 else dir=0;
483 }
484 if (ok) {
485 struct stat st;
486 int ret;
487 vc=find_vc(filename, ctrl);
488 if (mode==AC_READ) {
489 vc->checkout(TSG_READ,ctrl);
490 return vc;
491 }
492 ret=stat(filename,&st);
493 if (mode==AC_CREATE) {
494 if (ret==-1 && vc==&utftpd_novc) {
495 vc->checkout(TSG_CREATE,ctrl);
496 /* yup, that's create */
497 return vc;
498 }
499 return 0; /* that would be a write */
500 }
501 if (ret!=-1 && vc!=&utftpd_novc) {
502 /* writeable file? can't overwrite it, maybe some other process does
503 * also an upload now.
504 */
505 if (st.st_mode & (S_IWOTH |S_IWGRP|S_IWUSR)) {
506 syslog(LOG_ERR,"writeable %s exists -> DENY",filename);
507 goto deny;
508 }
509 unlink(filename);
510 }
511 if (ret==-1 && vc==&utftpd_novc) {
512 /* this would be an create */
513 if (mode==AC_WRITE) return 0;
514 }
515
516 vc->checkout(TSG_WRITE,ctrl);
517 need_commit=filename;
518 return vc;
519 }
520 /* FALLTHROUGH */
521 deny:
522 return 0;
523 }
524
525 static void
oack_append(int peer,size_t * oack_length,const char * n,const char * v)526 oack_append(int peer, size_t *oack_length, const char *n, const char *v)
527 {
528 size_t l1,l2;
529 l1=strlen(n)+1;
530 l2=strlen(v)+1;
531 if (*oack_length+l1+l2 >ctrl->segsize) {
532 syslog(LOG_ERR,"OACK too large for new %s %s",n,v);
533 utftpd_nak(peer,EUNDEF,"OACK too large",ctrl);
534 _exit(1);
535 }
536 memcpy(ctrl->sendbuf.buf+TFTP_OFFSET+*oack_length,n,l1);
537 memcpy(ctrl->sendbuf.buf+TFTP_OFFSET+*oack_length+l1,v,l2);
538 *oack_length+=l1+l2;
539 }
540
541 static void
do_init(int peer)542 do_init(int peer)
543 {
544 char *filename;
545 char *convert;
546 char *p;
547 struct tftphdr *hdr;
548 size_t oack_length=0;
549 size_t new_blksize=512;
550 const char *realfilename;
551 short opcode;
552 int got_options=0;
553 hdr = ctrl->recvbuf.hdr;
554 opcode = ntohs(hdr->th_opcode);
555 if (opcode != RRQ && opcode != WRQ) {
556 syslog(LOG_ERR,"got opcode %d in init",(int) opcode);
557 _exit(1);
558 }
559 filename=((char *)&hdr->th_opcode)+2; /* slowlartis doesn't have th_u union */
560 /* proceed to end of filename */
561 p=filename;
562 while (p!=ctrl->recvbuf.buf+got && *p!=0) p++;
563 if (p==ctrl->recvbuf.buf+got) {
564 syslog(LOG_ERR,"unterminated filename in init packet");
565 _exit(1);
566 }
567
568 convert=p+1;
569 /* proceed to end of conversion */
570 p=convert;
571 while (p!=ctrl->recvbuf.buf+got && *p!=0) p++;
572 if (p==ctrl->recvbuf.buf+got) {
573 syslog(LOG_ERR,"unterminated conversion in init packet");
574 _exit(1);
575 }
576 if (opcode==RRQ) {
577 syslog(LOG_INFO,"peer requests %s, conversion %s", filename, convert);
578 } else {
579 syslog(LOG_INFO,"peer sends %s, conversion %s", filename, convert);
580 }
581
582 /* now there may be options */
583 p++;
584 while (p!=ctrl->recvbuf.buf+got) {
585 char *opt;
586 char *val;
587 opt=p;
588 /* proceed to end of option name */
589 while (p!=ctrl->recvbuf.buf+got && *p!=0) p++;
590 if (p==ctrl->recvbuf.buf+got) {
591 if (got_options) {
592 syslog(LOG_ERR,"unterminated option name in init packet");
593 utftpd_nak(peer,EUNDEF,"unterminated option name in init packet",ctrl);
594 _exit(1);
595 } else {
596 syslog(LOG_INFO,"ignored unterminated option name in init "
597 "packet. bad client implementation?");
598 break;
599 }
600 }
601 got_options++;
602 val=p+1;
603 p=val;
604 /* proceed to end of option name */
605 while (p!=ctrl->recvbuf.buf+got && *p!=0) p++;
606 if (p==ctrl->recvbuf.buf+got) {
607 syslog(LOG_ERR,"unterminated option value in init packet");
608 utftpd_nak(peer,EUNDEF,"unterminated option value in init packet",
609 ctrl);
610 _exit(1);
611 }
612 if (opt_verbose)
613 syslog(LOG_INFO,"peer requests option %s, value %s", opt, val);
614 p++;
615 if (0==strcasecmp(opt,"blksize")) {
616 unsigned long x;
617 /* the actual resizing of the buffers is done later, we know parse a set of strings
618 * inside those buffers.
619 * ignore illegal numbers or blksizes below 512 (which can't work).
620 */
621 if (-1!=str2ulong(val,&x,0) && x >= 512) {
622 if (x>=65464) {
623 x=65464;
624 if (opt_verbose) syslog(LOG_INFO,"changed that to %lu bytes", x);
625 }
626 new_blksize=x;
627 }
628 } else if (0==strcasecmp(opt,"timeout")) {
629 unsigned long x;
630 /* must be between 1 and 255 inclusivly */
631 if (-1!=str2ulong(val,&x,0) && x>=1 && x<=256) {
632 ctrl->timeout=x;
633 oack_append(peer,&oack_length, opt,val);
634 }
635 } else if (0==strcasecmp(opt,"revision")) {
636 size_t x=strlen(val)+1;
637 /* we will NACK that later, if that revision doesn't exist */
638 ctrl->revision=(char *) malloc(x);
639 if (!ctrl->revision) goto oom;
640 memcpy(ctrl->revision,val,x);
641 oack_append(peer,&oack_length, opt,val);
642 }
643 }
644 filename=strdup(filename);
645 convert=strdup(convert);
646 if (!filename || !convert) goto oom;
647
648 /* stop using "hdr" now: it will move. */
649
650 if (new_blksize != 512) {
651 struct utftpd_ctrl *n;
652 char buf[STR_ULONG];
653 n=utftpd_setup_ctrl(ctrl, new_blksize);
654 if (!n) goto oom;
655 ctrl=n;
656 str_ulong(buf,new_blksize);
657 /* note: this also checks wether the buffer now is to small to hold the old OACK values */
658 oack_append(peer,&oack_length,"blksize",buf);
659 }
660 if (0==strcasecmp(convert,"netascii")) {
661 ctrl->netascii=1;
662 } else if (0==strcasecmp(convert,"octet")) {
663 ctrl->netascii=0;
664 } else {
665 syslog(LOG_ERR,"unknown conversion -> NAK");
666 utftpd_nak(peer,EUNDEF,"unknown conversion",ctrl);
667 _exit(1);
668 }
669
670 realfilename=qualify_filename(peer, opcode, filename);
671 ctrl->filename=strdup(realfilename);
672 if (!ctrl->filename) goto oom;
673 ctrl->origfilename=filename;
674 if (opcode==RRQ) {
675 int ret;
676 ctrl->vc=check_access(opt_read,realfilename,AC_READ);
677 if (!ctrl->vc) {
678 syslog(LOG_NOTICE,"denied read access to %s", filename);
679 do_nak(peer, EACCESS,"access denied");
680 _exit(1);
681 }
682 ctrl->first_packet_length=oack_length;
683 ctrl->sendbuf.hdr->th_opcode=htons(OACK);
684 ret=utftpd_send(ctrl);
685 if (opt_timing) {
686 unsigned long used=stop();
687 char buf[STR_ULONG];
688 unsigned long x,y;
689 x=str_ulong(buf,used/1000000);
690 buf[x++]='.';
691 y=used%1000000;
692 if (y>99999) str_ulong(buf+x,y);
693 else if (y>9999) {buf[x++]='0'; str_ulong(buf+x,y);}
694 else if (y>999) {buf[x++]='0'; buf[x++]='0'; str_ulong(buf+x,y);}
695 else if (y>99) {buf[x++]='0'; buf[x++]='0'; buf[x++]='0'; str_ulong(buf+x,y);}
696 else if (y>9) {buf[x++]='0'; buf[x++]='0'; buf[x++]='0'; buf[x++]='0'; str_ulong(buf+x,y);}
697 else {buf[x++]='0'; buf[x++]='0'; buf[x++]='0'; buf[x++]='0'; buf[x++]='0'; str_ulong(buf+x,y);}
698
699 syslog(LOG_INFO,"transferred %lu bytes in %s seconds", ctrl->bytes,buf);
700 }
701 _exit (0!=ret);
702 } else {
703 int retcode;
704
705 /* if we are root we never write. */
706 if (getuid()==0) {
707 syslog(LOG_ERR,"%s: will not write as root",realfilename);
708 do_nak(peer, EACCESS,"access denied");
709 _exit(1);
710 }
711
712 ctrl->vc=check_access(opt_write,realfilename,AC_WRITE);
713 if (!ctrl->vc) {
714 ctrl->vc=check_access(opt_create,realfilename,AC_CREATE);
715 if (!ctrl->vc) {
716 syslog(LOG_NOTICE,"denied write access to %s", filename);
717 do_nak(peer, EACCESS,"access denied");
718 _exit(1);
719 }
720 }
721
722 /* we have to send either an OACK or an ACK. We prepare that here, but sending (and possible resending)
723 * is done in the receiving code.
724 */
725 ctrl->first_packet_length=oack_length;
726 if (oack_length)
727 ctrl->sendbuf.hdr->th_opcode=htons(OACK);
728 else
729 ctrl->sendbuf.hdr->th_opcode=htons(ACK);
730
731
732 retcode=utftpd_recv(ctrl);
733 if (retcode==-1) {
734 if (need_commit && ctrl->vc->unget)
735 ctrl->vc->unget(ctrl);
736 unlink(ctrl->filename);
737 _exit(1);
738 }
739 /* we _do_ have the whole file now, but didn't send the last ACK.
740 * we delay that until we did the version control checkin
741 */
742 if (need_commit) {
743 ctrl->vc->commit("got from remote",ctrl);
744 }
745
746 syslog(LOG_INFO,"got %s",realfilename);
747 if (send(peer, ctrl->sendbuf.buf, TFTP_OFFSET, 0) != (ssize_t) TFTP_OFFSET) {
748 syslog(LOG_ERR,"send() for final ACK failed for %s: %s",remoteip,strerror(errno));
749 /* minor problem, so we return 0 */
750 }
751 if (opt_timing) {
752 unsigned long used=stop();
753 char buf[STR_ULONG];
754 unsigned long x,y;
755 x=str_ulong(buf,used/1000000);
756 buf[x++]='.';
757 y=used%1000000;
758 if (y>99999) str_ulong(buf+x,y);
759 else if (y>9999) {buf[x++]='0'; str_ulong(buf+x,y);}
760 else if (y>999) {buf[x++]='0'; buf[x++]='0'; str_ulong(buf+x,y);}
761 else if (y>99) {buf[x++]='0'; buf[x++]='0'; buf[x++]='0'; str_ulong(buf+x,y);}
762 else if (y>9) {buf[x++]='0'; buf[x++]='0'; buf[x++]='0'; buf[x++]='0'; str_ulong(buf+x,y);}
763 else {buf[x++]='0'; buf[x++]='0'; buf[x++]='0'; buf[x++]='0'; buf[x++]='0'; str_ulong(buf+x,y);}
764
765 syslog(LOG_INFO,"received %lu bytes in %s seconds", ctrl->bytes,buf);
766 }
767 _exit(0);
768 }
769 oom:
770 syslog(LOG_ERR,"out of memory");
771 utftpd_nak(peer,EUNDEF,"out of memory",ctrl);
772 _exit(1);
773 }
774
775 static void
chld_handler(int x)776 chld_handler(int x)
777 {
778 (void) x;
779 signal(SIGCHLD,&chld_handler);
780 }
781
782 int
main(int argc,char ** argv)783 main(int argc, char **argv)
784 {
785 int config_fd=-1;
786 struct sockaddr_in from;
787 struct sockaddr_in s_in;
788 socklen_t fromlen;
789 pid_t pid;
790 uid_t guid,uid;
791 gid_t ggid,gid;
792 size_t l;
793 const char *s;
794 int initial_packet_errno;
795 int peer;
796 struct in_addr ina;
797 unsigned short port;
798 int mastersocket=0;
799
800 nullfd=open("/dev/null",O_RDWR);
801 if (nullfd==-1) {
802 syslog(LOG_ERR,"cannot open /dev/null: %s",strerror(errno));
803 _exit(1);
804 }
805 #ifdef HAVE_LIBEFENCE
806 /* hack around efence */
807 {int fd2;void *waste;
808 if (-1==(fd2=dup(2))) _exit(1);
809 if (-1==(dup2(nullfd,2))) _exit(1);
810 waste=malloc(1);
811 if (-1==(dup2(fd2,2))) _exit(1);
812 close(fd2);
813 }
814 #endif
815
816 argv0=strrchr(argv[0],'/');
817 if (!argv0++) argv0=argv[0];
818 ctrl=utftpd_setup_ctrl(0,512);
819 if (!ctrl) goto oom;
820
821
822 /* at least read input even in case we crash / exit very early due to a
823 * configuration or resource problem. We have to to that
824 */
825 fromlen = sizeof (from);
826 got = recvfrom(mastersocket, ctrl->recvbuf.buf, ctrl->segsize+TFTP_OFFSET, 0,
827 (struct sockaddr *)&from, &fromlen);
828 initial_packet_errno=errno;
829
830 uogetopt("utftpd","GNU " PACKAGE,VERSION,&argc,argv,uogetopt_out,0,myopts,
831 "Report bugs to uwe-utftpd@bulkmail.ohse.de");
832 /* in standalone mode it's okay to lose here, nobody gave us a socket on fd 0 */
833 if (opt_standalone
834 #ifdef ENOTSOCK /* BEOS doesn't know this */
835 && got==-1 && errno==ENOTSOCK
836 #endif
837 ) {
838 got=0;
839 initial_packet_errno=0;
840 }
841
842 openlog("utftpd", LOG_PID|LOG_NDELAY, LOG_DAEMON);
843 /* open configuration file now */
844 if (opt_configfile) {
845 config_fd=open(opt_configfile, O_RDONLY);
846 if (config_fd==-1) {
847 syslog(LOG_ERR,"cannot open %s: %s", opt_configfile, strerror(errno));
848 _exit(1);
849 }
850 } else {
851 opt_old_style_ac=argv;
852 }
853
854 /* parse host:port before the chroot happens. No /etc/services and so on afterwards */
855 if (opt_standalone) {
856 int r;
857 port=htons(69);
858 ina.s_addr=INADDR_ANY;
859 r=parse_ip_port(opt_standalone,&ina,&port,"udp");
860 if (r==-1) {
861 syslog(LOG_ERR,"cannot understand %s", opt_standalone);
862 _exit(1);
863 }
864 mastersocket=socket(AF_INET,SOCK_DGRAM, 0);
865 if (mastersocket < 0) { syslog (LOG_ERR, "socket: %s", strerror (errno)); _exit (1); }
866 s_in.sin_addr.s_addr=ina.s_addr;
867 s_in.sin_port=port;
868 s_in.sin_family=AF_INET;
869 if (bind (mastersocket, (struct sockaddr *) &s_in, sizeof (s_in)) < 0) {
870 syslog (LOG_ERR, "bind: %s", strerror (errno)); _exit (1);
871 }
872 }
873
874 /* now get rid of rights ... */
875 if (opt_global_uid) get_ids(opt_global_uid,&guid,&ggid);
876 #ifdef HAVE_CHROOT
877 if (opt_global_chroot) {
878 if (-1==chdir(opt_global_chroot)) { syslog(LOG_ERR,"chdir %s: %s",opt_global_chroot,strerror(errno)); _exit(1); }
879 if (-1==chroot(opt_global_chroot)) { syslog(LOG_ERR,"chroot %s: %s",opt_global_chroot,strerror(errno)); _exit(1); }
880 if (opt_verbose) syslog(LOG_INFO,"did chdir/root to %s",opt_global_chroot);
881 }
882 #endif
883 if (opt_global_uid) set_ids(guid,ggid);
884 if (opt_global_chdir) {
885 if (-1==chdir(opt_global_chdir)) { syslog(LOG_ERR,"chdir %s: %s",opt_global_chdir,strerror(errno)); _exit(1); }
886 if (opt_verbose) syslog(LOG_INFO,"did chdir to %s",opt_global_chdir);
887 }
888
889
890 #ifndef __BEOS__
891 /* why did i do this? */
892 nonblock(0,1); /* it's a UDP socket - this should not be needed! */
893 #endif
894
895 if (got < 0) {
896 #ifdef ENOTSOCK /* BEOS doesn't know this */
897 /* try to be nice to the user */
898 if (got==-1 && errno==ENOTSOCK) {
899 const char *m1,*m2;
900 m1=": must be started by inetd.\n";
901 m2=" Give --help option for usage information.\n";
902 write(2,argv0,strlen(argv0));
903 write(2,m1,strlen(m1));
904 write(2,m2,strlen(m2));
905 _exit(2);
906 }
907
908 #endif
909 syslog(LOG_ERR, "recvfrom(initial packet): %s",
910 strerror(initial_packet_errno));
911 exit(1);
912 }
913
914 /* fork/exit for inetd nowait mode */
915 if (!opt_standalone) {
916 pid = fork();
917 if (pid==-1) {
918 syslog(LOG_ERR,"can't fork: %s", strerror(errno));
919 _exit(1);
920 }
921 }
922 if (opt_standalone || pid!=0) {
923 int childs;
924 if (opt_standalone) childs=0;
925 else childs=1;
926 /* mother */
927 if (!opt_keeprun && !opt_standalone)
928 _exit(0);
929 signal(SIGCHLD,&chld_handler);
930 while (1) {
931 fd_set set;
932 int r;
933 FD_ZERO(&set);
934 FD_SET(mastersocket,&set);
935 r=select(mastersocket+1,&set,0,0,0);
936 if (r==-1 && errno!=EINTR) {
937 syslog(LOG_ERR,"select failed: %s", strerror(errno));
938 _exit(1);
939 }
940 if (FD_ISSET(mastersocket,&set)) {
941 fromlen = sizeof (from);
942 got = recvfrom(mastersocket, ctrl->recvbuf.buf, ctrl->segsize+TFTP_OFFSET, 0,
943 (struct sockaddr *)&from, &fromlen);
944 if (got==-1) {
945 syslog(LOG_ERR, "recvfrom(initial packet on new connection): %s", strerror(errno));
946 } else {
947 pid=fork();
948 if (pid==0)
949 break; /* child */
950 if (pid!=-1)
951 childs++;
952 }
953 }
954 while (r==-1) {
955 pid_t pi=waitpid(WAIT_ANY,0,WNOHANG);
956 if (pi==0 || pi==-1)
957 break;
958 childs--;
959 }
960 if (!childs && opt_keeprun) _exit(0);
961 }
962 }
963 /* child */
964 if (opt_timing) start();
965 /* make a copy of the remote ip address, as string */
966 s=inet_ntoa(from.sin_addr);
967 l=strlen(s)+1;
968 remoteip=(char *) malloc(l);
969 if (!remoteip) goto oom;
970 memcpy(remoteip,s,l);
971
972 openlog("utftpd", LOG_PID|LOG_NDELAY, LOG_DAEMON);
973 syslog(LOG_INFO,"connect from %s",remoteip);
974
975 if (config_fd!=-1) {
976 do_config(config_fd);
977 close(config_fd);
978 }
979
980 from.sin_family = AF_INET;
981 alarm(0);
982 if (-1==dup2(nullfd,0)) { syslog(LOG_ERR,"cannot dup2 /dev/null -> 0: %s",strerror(errno)); _exit(1); }
983 if (-1==dup2(nullfd,1)) { syslog(LOG_ERR,"cannot dup2 /dev/null -> 1: %s",strerror(errno)); _exit(1); }
984
985 peer = socket(AF_INET, SOCK_DGRAM, 0);
986 if (peer < 0) { syslog(LOG_ERR, "socket: %s",strerror(errno)); _exit(1); }
987 ctrl->remotefd=peer;
988
989 /* we need to bind to the same port we received this on ... */
990 s_in.sin_addr.s_addr=INADDR_ANY;
991 s_in.sin_port=0;
992 s_in.sin_family=AF_INET;
993 if (bind(peer, (struct sockaddr *)&s_in, sizeof (s_in)) < 0) { syslog(LOG_ERR, "bind: %s",strerror(errno)); _exit(1); }
994
995 /* now get rid of rights ... */
996 if (opt_uid) get_ids(opt_uid,&uid,&gid);
997 if (opt_chroot) {
998 #ifdef HAVE_CHROOT
999 const char *e;
1000 if (-1==chdir(opt_chroot)) { e=strerror(errno); syslog(LOG_ERR,"chdir %s: %s",opt_chroot,e);_exit(1); }
1001 if (-1==chroot(opt_chroot)) { e=strerror(errno); syslog(LOG_ERR,"chroot %s: %s",opt_chroot,e); _exit(1); }
1002 if (opt_verbose) syslog(LOG_INFO,"did chdir/root to %s",opt_chroot);
1003 #else
1004 syslog(LOG_ERR,"chroot is not available on this platform");
1005 /* XXX should send a nak, but socket is still not connected */
1006 _exit(1);
1007 #endif
1008 }
1009 if (opt_uid) set_ids(uid,gid);
1010 if (opt_chdir) {
1011 const char *e;
1012 if (-1==chdir(opt_chdir)) { e=strerror(errno); syslog(LOG_ERR,"chdir %s: %s",opt_chdir,e); _exit(1); }
1013 if (opt_verbose) syslog(LOG_INFO,"did chdir to %s",opt_chdir);
1014 }
1015 if (connect(peer, (struct sockaddr *)&from, sizeof(from)) < 0) { syslog(LOG_ERR, "connect: %s",strerror(errno)); exit(1); }
1016 setsid();
1017
1018 do_init(peer);
1019 _exit(1);
1020 oom:
1021 syslog(LOG_ERR,"out of memory");
1022 _exit(1);
1023 }
1024
1025
1026 static struct utftpd_ctrl *
utftpd_setup_ctrl(struct utftpd_ctrl * old,size_t segsize)1027 utftpd_setup_ctrl(struct utftpd_ctrl *old, size_t segsize)
1028 {
1029 if (!old) {
1030 old=(struct utftpd_ctrl *)malloc(sizeof(struct utftpd_ctrl));
1031 if (!old) return 0;
1032 memset(old,0,sizeof(*old));
1033 old->segsize=512; /* default */
1034 old->netascii=0;
1035 old->timeout=5;
1036 old->retries=5;
1037 old->first_packet_length=0; /* tftp_open() adjusts this */
1038 old->filefd=-1;
1039 old->sendbuf.buf=(char *) malloc(old->segsize+TFTP_OFFSET);
1040 old->recvbuf.buf=(char *) malloc(old->segsize+TFTP_OFFSET);
1041 if (!old->sendbuf.buf || !old->recvbuf.buf) {
1042 free(old->sendbuf.buf);
1043 free(old->recvbuf.buf);
1044 free(old);
1045 return 0;
1046 }
1047 }
1048 if (segsize!=0 && old->segsize!=segsize) {
1049 void *v,*u;
1050 u=realloc(old->sendbuf.buf,segsize+TFTP_OFFSET);
1051 v=realloc(old->recvbuf.buf,segsize+TFTP_OFFSET);
1052 if (!u || !v) {
1053 if (u) free(u); else free(old->sendbuf.buf);
1054 if (v) free(v); else free(old->recvbuf.buf);
1055 free(old);
1056 return 0;
1057 }
1058 old->sendbuf.buf=(char *) u;
1059 old->recvbuf.buf=(char *) v;
1060 old->segsize=segsize;
1061 }
1062 return old;
1063 }
1064
1065