ftpd.c
上传用户:zibowangxu
上传日期:2007-01-04
资源大小:331k
文件大小:183k
源码类别:

Ftp客户端

开发平台:

Unix_Linux

  1.     if (strcmp(realdir, "*") == 0 || strcmp(realdir + strlen(realdir) - 2, "/*") == 0)
  2. isDir = 2;
  3.     else {
  4. if (lstat(realdir, &s) == 0) {
  5.     if (S_ISDIR(s.st_mode)) {
  6. strcat(realdir, "/*");
  7. isDir = 2;
  8.     }
  9. }
  10.     }
  11.     if (isDir == 0) {
  12. if (ls_l) {
  13.     lsentry = ls_file(realdir, 0, 0, ls_F);
  14.     if (lsentry != NULL) {
  15. if (draconian_FILE != NULL) {
  16.     (void) signal(SIGALRM, draconian_alarm_signal);
  17.     alarm(timeout_data);
  18.     fputs(lsentry, out);
  19. }
  20. free(lsentry);
  21.     }
  22. }
  23. else {
  24.     if (draconian_FILE != NULL) {
  25. (void) signal(SIGALRM, draconian_alarm_signal);
  26. alarm(timeout_data);
  27. fputs(realdir, out);
  28.     }
  29. }
  30. free(realdir);
  31.     }
  32.     else {
  33. if (ls_R) {
  34.     numSubdirs = 0;
  35.     subdirs = (char **) malloc(200 * sizeof(char *));
  36.     memset(subdirs, 0, 200 * sizeof(char *));
  37. }
  38. dl_size = 65536;
  39. dirlist = (char *) malloc(65536);
  40. memset(dirlist, 0, 65536);
  41. dl_used = 0;
  42. total = 0;
  43. memset(&g, 0, sizeof(g));
  44. if (ls_a) {
  45. #ifdef GLOB_PERIOD
  46.     if (glob(realdir, GLOB_ERR | GLOB_PERIOD, NULL, &g) != 0)
  47. g.gl_pathc = 0;
  48. #else
  49.     dperiod = (char *) malloc(strlen(realdir) + 2);
  50.     memset(dperiod, 0, strlen(realdir) + 2);
  51.     strcpy(dperiod, ".");
  52.     strcat(dperiod, realdir);
  53.     if (glob(dperiod, GLOB_ERR, NULL, &g) != 0)
  54. g.gl_pathc = 0;
  55.     glob(realdir, GLOB_ERR | GLOB_APPEND, NULL, &g);
  56.     free(dperiod);
  57. #endif
  58. }
  59. else if (glob(realdir, GLOB_ERR, NULL, &g) != 0)
  60.     g.gl_pathc = 0;
  61. free(realdir);
  62. for (i = 0; i < g.gl_pathc; i++) {
  63.     c = g.gl_pathv[i];
  64.     if (lstat(c, &s) != -1) {
  65. if (ls_l) {
  66.     total += s.st_blocks;
  67.     lsentry = ls_file(c, 0, 1, ls_F);
  68.     if (lsentry != NULL) {
  69. /* This can actually happen even though the lstat() worked - 
  70.    if someone deletes the file between the lstat() and ls_file()
  71.    calls. Unlikely, but better safe than sorry... */
  72. int flag = snprintf(dirlist + dl_used, dl_size - dl_used, "%s", lsentry);
  73. dl_used += (flag == -1 ? dl_size - dl_used : flag);
  74. free(lsentry);
  75.     }
  76. }
  77. else {
  78.     int flag;
  79.     lsentry = ls_file(c, 1, 1, ls_F);
  80.     flag = snprintf(dirlist + dl_used, dl_size - dl_used, "%s", lsentry);
  81.     dl_used += (flag == -1 ? dl_size - dl_used : flag);
  82. }
  83. if ((ls_R != 0) && (S_ISDIR(s.st_mode))
  84.     && (strcmp(c, "..") != 0) && (strcmp(c, ".") != 0)
  85. && !(strlen(c) > 3 && strcmp(c + strlen(c) - 3, "/..") == 0)
  86.     && !(strlen(c) > 2 && strcmp(c + strlen(c) - 2, "/.") == 0)) {
  87.     subdirs[numSubdirs++] = strdup(c);
  88.     if ((numSubdirs % 200) == 0)
  89. subdirs = (char **) realloc(subdirs, (numSubdirs + 200) * sizeof(char *));
  90. }
  91.     }
  92.     if (dl_used + 512 >= dl_size) {
  93. dl_size += 65536;
  94. dirlist = (char *) realloc(dirlist, dl_size);
  95.     }
  96. }
  97. globfree(&g);
  98. if (ls_l && isDir == 2 && omit_total == 0) {
  99.     if (draconian_FILE != NULL) {
  100. (void) signal(SIGALRM, draconian_alarm_signal);
  101. alarm(timeout_data);
  102. fprintf(out, "total %urn", total);
  103.     }
  104. }
  105. if (draconian_FILE != NULL) {
  106.     (void) signal(SIGALRM, draconian_alarm_signal);
  107.     alarm(timeout_data);
  108.     fputs(dirlist, out);
  109. }
  110. free(dirlist);
  111. if (ls_R) {
  112.     for (i = 0; i < numSubdirs; i++) {
  113. if (draconian_FILE != NULL) {
  114.     (void) signal(SIGALRM, draconian_alarm_signal);
  115.     alarm(timeout_data);
  116.     fprintf(out, "rn%s:rn", subdirs[i]);
  117.     ls_dir(subdirs[i], ls_a, ls_F, ls_l, ls_R, 0, out);
  118. }
  119. free(subdirs[i]);
  120.     }
  121.     free(subdirs);
  122. }
  123.     }
  124. }
  125. void ls(char *file, char nlst)
  126. {
  127.     FILE *out;
  128.     char free_file = 0;
  129.     char ls_l = 0, ls_a = 0, ls_R = 0, ls_F = 0;
  130.     if (nlst == 0)
  131. ls_l = 1; /* LIST defaults to ls -l */
  132.     if (file == NULL) {
  133. file = strdup(".");
  134. free_file = 1;
  135.     }
  136.     if (strcmp(file, "*") == 0)
  137. file[0] = '.';
  138.     if (file[0] == '-') { /* options... */
  139. if (strchr(file, ' ') == 0) {
  140.     if (strchr(file, 'l'))
  141. ls_l = 1;
  142.     if (strchr(file, 'a'))
  143. ls_a = 1;
  144.     if (strchr(file, 'R'))
  145. ls_R = 1;
  146.     if (strchr(file, 'F'))
  147. ls_F = 1;
  148.     file = strdup(".");
  149.     free_file = 1;
  150. }
  151. else {
  152.     if (strchr(file, 'l') != NULL && strchr(file, 'l') < strchr(file, ' '))
  153. ls_l = 1;
  154.     if (strchr(file, 'a') != NULL && strchr(file, 'a') < strchr(file, ' '))
  155. ls_a = 1;
  156.     if (strchr(file, 'R') != NULL && strchr(file, 'R') < strchr(file, ' '))
  157. ls_R = 1;
  158.     if (strchr(file, 'F') != NULL && strchr(file, 'F') < strchr(file, ' '))
  159. ls_F = 1;
  160.     file = strchr(file, ' ');
  161. }
  162.     }
  163.     while (file[0] == ' ') /* ignore additional whitespaces between parameters */
  164. file++;
  165.     if (strlen(file) == 0) {
  166. file = strdup(".");
  167. free_file = 1;
  168.     }
  169.     out = dataconn("directory listing", -1, "w");
  170.     draconian_FILE = out;
  171.     transflag++;
  172.     fixpath(file);
  173.     if (file[0] == '') {
  174. if (free_file != 0)
  175.     free(file);
  176. file = strdup(".");
  177. free_file = 1;
  178.     }
  179.     ls_dir(file, ls_a, ls_F, ls_l, ls_R, 0, out);
  180.     data = -1;
  181.     pdata = -1;
  182.     if (draconian_FILE != NULL) {
  183. (void) signal(SIGALRM, draconian_alarm_signal);
  184. alarm(timeout_data);
  185. fflush(out);
  186.     }
  187.     if (draconian_FILE != NULL) {
  188. (void) signal(SIGALRM, draconian_alarm_signal);
  189. alarm(timeout_data);
  190. socket_flush_wait(out);
  191.     }
  192.     if (draconian_FILE != NULL) {
  193. (void) signal(SIGALRM, draconian_alarm_signal);
  194. alarm(timeout_data);
  195. fclose(out);
  196. draconian_FILE = NULL;
  197.     }
  198.     alarm(0);
  199.     transflag = 0;
  200.     reply(226, "Transfer complete.");
  201.     if (free_file != 0)
  202. free(file);
  203. }
  204. #endif /* INTERNAL_LS */
  205. void retrieve(char *cmd, char *name)
  206. {
  207.     FILE *fin = NULL, *dout;
  208.     struct stat st, junk;
  209.     int (*closefunc) () = NULL;
  210.     int options = 0;
  211.     int ThisRetrieveIsData = retrieve_is_data;
  212.     time_t start_time = time(NULL);
  213.     char *logname;
  214.     char namebuf[MAXPATHLEN];
  215.     char fnbuf[MAXPATHLEN];
  216.     int TransferComplete = 0;
  217.     struct convert *cptr;
  218.     char realname[MAXPATHLEN];
  219.     int stat_ret = -1;
  220.     extern int checknoretrieve(char *);
  221.     wu_realpath(name, realname, chroot_path);
  222. #ifdef TRANSFER_COUNT
  223. #ifdef TRANSFER_LIMIT
  224.     if (retrieve_is_data)
  225. if (((file_limit_data_out > 0) && (file_count_out >= file_limit_data_out))
  226.     || ((file_limit_data_total > 0) && (file_count_total >= file_limit_data_total))
  227.     || ((data_limit_data_out > 0) && (data_count_out >= data_limit_data_out))
  228.     || ((data_limit_data_total > 0) && (data_count_total >= data_limit_data_total))) {
  229.     if (log_security)
  230. if (anonymous)
  231.     syslog(LOG_NOTICE, "anonymous(%s) of %s tried to retrieve %s (Transfer limits exceeded)",
  232.    guestpw, remoteident, realname);
  233. else
  234.     syslog(LOG_NOTICE, "%s of %s tried to retrieve %s (Transfer limits exceeded)",
  235.    pw->pw_name, remoteident, realname);
  236.     reply(553, "Permission denied on server. (Transfer limits exceeded)");
  237.     return;
  238. }
  239.     if (((file_limit_raw_out > 0) && (xfer_count_out >= file_limit_raw_out))
  240. || ((file_limit_raw_total > 0) && (xfer_count_total >= file_limit_raw_total))
  241.      || ((data_limit_raw_out > 0) && (byte_count_out >= data_limit_raw_out))
  242. || ((data_limit_raw_total > 0) && (byte_count_total >= data_limit_raw_total))) {
  243. if (log_security)
  244.     if (anonymous)
  245. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to retrieve %s (Transfer limits exceeded)",
  246.        guestpw, remoteident, realname);
  247.     else
  248. syslog(LOG_NOTICE, "%s of %s tried to retrieve %s (Transfer limits exceeded)",
  249.        pw->pw_name, remoteident, realname);
  250. reply(553, "Permission denied on server. (Transfer limits exceeded)");
  251. return;
  252.     }
  253. #endif
  254. #endif
  255.     if (cmd == NULL && (stat_ret = stat(name, &st)) == 0)
  256. /* there isn't a command and the file exists */
  257. if (use_accessfile && checknoretrieve(name)) { /* see above.  _H */
  258.     if (log_security)
  259. if (anonymous)
  260.     syslog(LOG_NOTICE, "anonymous(%s) of %s tried to download %s (noretrieve)",
  261.    guestpw, remoteident, realname);
  262. else
  263.     syslog(LOG_NOTICE, "%s of %s tried to download %s (noretrieve)",
  264.    pw->pw_name, remoteident, realname);
  265.     return;
  266. }
  267.     logname = (char *) NULL;
  268.     if (cmd == NULL && stat_ret != 0) { /* file does not exist */
  269. char *ptr;
  270. for (cptr = cvtptr; cptr != NULL; cptr = cptr->next) {
  271.     if (!(mangleopts & O_COMPRESS) && (cptr->options & O_COMPRESS))
  272. continue;
  273.     if (!(mangleopts & O_UNCOMPRESS) && (cptr->options & O_UNCOMPRESS))
  274. continue;
  275.     if (!(mangleopts & O_TAR) && (cptr->options & O_TAR))
  276. continue;
  277.     if ((cptr->stripfix) && (cptr->postfix)) {
  278. int pfxlen = strlen(cptr->postfix);
  279. int sfxlen = strlen(cptr->stripfix);
  280. int namelen = strlen(name);
  281. (void) strcpy(fnbuf, name);
  282. if (namelen <= pfxlen)
  283.     continue;
  284. if ((namelen - pfxlen + sfxlen) >= sizeof(fnbuf))
  285.     continue;
  286. if (strcmp(fnbuf + namelen - pfxlen, cptr->postfix))
  287.     continue;
  288. *(fnbuf + namelen - pfxlen) = '';
  289. (void) strcat(fnbuf, cptr->stripfix);
  290. if (stat(fnbuf, &st) != 0)
  291.     continue;
  292.     }
  293.     else if (cptr->postfix) {
  294. int pfxlen = strlen(cptr->postfix);
  295. int namelen = strlen(name);
  296. if (namelen <= pfxlen)
  297.     continue;
  298. (void) strcpy(fnbuf, name);
  299. if (strcmp(fnbuf + namelen - pfxlen, cptr->postfix))
  300.     continue;
  301. *(fnbuf + namelen - pfxlen) = (char) NULL;
  302. if (stat(fnbuf, &st) != 0)
  303.     continue;
  304.     }
  305.     else if (cptr->stripfix) {
  306. (void) strcpy(fnbuf, name);
  307. (void) strcat(fnbuf, cptr->stripfix);
  308. if (stat(fnbuf, &st) != 0)
  309.     continue;
  310.     }
  311.     else {
  312. continue;
  313.     }
  314.     if (S_ISDIR(st.st_mode)) {
  315. if (!cptr->types || !(cptr->types & T_DIR)) {
  316.     reply(550, "Cannot %s directories.", cptr->name);
  317.     return;
  318. }
  319. if ((cptr->options & O_TAR)) {
  320.     strcpy(namebuf, fnbuf);
  321.     strcat(namebuf, "/.notar");
  322.     if (stat(namebuf, &junk) == 0) {
  323. if (log_security)
  324.     if (anonymous)
  325. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to tar %s (.notar)",
  326.        guestpw, remoteident, realname);
  327.     else
  328. syslog(LOG_NOTICE, "%s of %s tried to tar %s (.notar)",
  329.        pw->pw_name, remoteident, realname);
  330. reply(550, "Sorry, you may not TAR that directory.");
  331. return;
  332.     }
  333. }
  334.     }
  335. /* XXX: checknoretrieve() test is weak in that if I can't get /etc/passwd
  336.    but I can tar /etc or /, I still win.  Be careful out there... _H*
  337.    but you could put .notar in / and /etc and stop that ! */
  338.     if (use_accessfile && checknoretrieve(fnbuf)) {
  339. if (log_security)
  340.     if (anonymous)
  341. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to download %s (noretrieve)",
  342.        guestpw, remoteident, realname);
  343.     else
  344. syslog(LOG_NOTICE, "%s of %s tried to download %s (noretrieve)",
  345.        pw->pw_name, remoteident, realname);
  346. return;
  347.     }
  348.     if (S_ISREG(st.st_mode) && (!cptr->types || (cptr->types & T_REG) == 0)) {
  349. reply(550, "Cannot %s plain files.", cptr->name);
  350. return;
  351.     }
  352.     if (S_ISREG(st.st_mode) != 0 && S_ISDIR(st.st_mode) != 0) {
  353. reply(550, "Cannot %s special files.", cptr->name);
  354. return;
  355.     }
  356.     if ((!cptr->types || !(cptr->types & T_ASCII)) && deny_badasciixfer(550, ""))
  357. return;
  358.     logname = &fnbuf[0];
  359.     options |= cptr->options;
  360.     strcpy(namebuf, cptr->external_cmd);
  361.     if ((ptr = strchr(namebuf, ' ')) != NULL)
  362. *ptr = '';
  363.     if (stat(namebuf, &st) != 0) {
  364. syslog(LOG_ERR, "external command %s not found",
  365.        namebuf);
  366. reply(550,
  367. "Local error: conversion program not found. Cannot %s file.",
  368.       cptr->name);
  369. return;
  370.     }
  371.     (void) retrieve(cptr->external_cmd, logname);
  372.     goto logresults; /* transfer of converted file completed */
  373. }
  374.     }
  375.     if (cmd == NULL) { /* no command */
  376. fin = fopen(name, "r"), closefunc = fclose;
  377. st.st_size = 0;
  378.     }
  379.     else { /* run command */
  380. static char line[BUFSIZ];
  381. (void) snprintf(line, sizeof line, cmd, name), name = line;
  382. fin = ftpd_popen(line, "r", 1), closefunc = ftpd_pclose;
  383. st.st_size = -1;
  384. #ifdef HAVE_ST_BLKSIZE
  385. st.st_blksize = BUFSIZ;
  386. #endif
  387.     }
  388.     if (fin == NULL) {
  389. if (errno != 0)
  390.     perror_reply(550, name);
  391. if ((errno == EACCES) || (errno == EPERM))
  392.     if (log_security)
  393. if (anonymous)
  394.     syslog(LOG_NOTICE, "anonymous(%s) of %s tried to download %s (file permissions)",
  395.    guestpw, remoteident, realname);
  396. else
  397.     syslog(LOG_NOTICE, "%s of %s tried to download %s (file permissions)",
  398.    pw->pw_name, remoteident, realname);
  399. return;
  400.     }
  401.     if (cmd == NULL &&
  402. (fstat(fileno(fin), &st) < 0 || (st.st_mode & S_IFMT) != S_IFREG)) {
  403. reply(550, "%s: not a plain file.", name);
  404. goto done;
  405.     }
  406.     if (restart_point) {
  407. if (type == TYPE_A) {
  408.     register int i, n, c;
  409.     n = restart_point;
  410.     i = 0;
  411.     while (i++ < n) {
  412. if ((c = getc(fin)) == EOF) {
  413.     perror_reply(550, name);
  414.     goto done;
  415. }
  416. if (c == 'n')
  417.     i++;
  418.     }
  419. }
  420. else if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) {
  421.     perror_reply(550, name);
  422.     goto done;
  423. }
  424.     }
  425.     dout = dataconn(name, st.st_size, "w");
  426.     if (dout == NULL)
  427. goto done;
  428. #ifdef BUFFER_SIZE
  429. #ifdef THROUGHPUT
  430.     TransferComplete = send_data(name, fin, dout, BUFFER_SIZE);
  431. #else
  432.     TransferComplete = send_data(fin, dout, BUFFER_SIZE);
  433. #endif
  434. #else
  435. #ifdef HAVE_ST_BLKSIZE
  436. #ifdef THROUGHPUT
  437.     TransferComplete = send_data(name, fin, dout, st.st_blksize * 2);
  438. #else
  439.     TransferComplete = send_data(fin, dout, st.st_blksize * 2);
  440. #endif
  441. #else
  442. #ifdef THROUGHPUT
  443.     TransferComplete = send_data(name, fin, dout, BUFSIZ);
  444. #else
  445.     TransferComplete = send_data(fin, dout, BUFSIZ);
  446. #endif
  447. #endif
  448. #endif
  449.     (void) fclose(dout);
  450.   logresults:
  451.     if (ThisRetrieveIsData)
  452. fb_realpath((logname != NULL) ? logname : name, LastFileTransferred);
  453.     if (log_outbound_xfers && (xferlog || syslogmsg) && (cmd == 0)) {
  454. char msg[MAXPATHLEN + 2 * MAXHOSTNAMELEN + 100 + 128]; /* AUTHNAMESIZE is 100 */
  455. size_t msglen; /* for stupid_sprintf */
  456. int xfertime = time(NULL) - start_time;
  457. time_t curtime = time(NULL);
  458. int loop;
  459. if (!xfertime)
  460.     xfertime++;
  461. #ifdef XFERLOG_REALPATH
  462. wu_realpath((logname != NULL) ? logname : name, &namebuf[0], chroot_path);
  463. #else
  464. fb_realpath((logname != NULL) ? logname : name, &namebuf[0]);
  465. #endif
  466. for (loop = 0; namebuf[loop]; loop++)
  467.     if (isspace(namebuf[loop]) || iscntrl(namebuf[loop]))
  468. namebuf[loop] = '_';
  469. /* Some systems use one format, some another.  This takes care of the garbage */
  470. #ifndef L_FORMAT /* Autoconf detects this... */
  471. #if (defined(BSD) && (BSD >= 199103)) && !defined(LONGOFF_T)
  472. #define L_FORMAT "qd"
  473. #else
  474. #ifdef _AIX42
  475. #define L_FORMAT "lld"
  476. #else
  477. #ifdef SOLARIS_2
  478. #define L_FORMAT "ld"
  479. #else
  480. #define L_FORMAT "d"
  481. #endif
  482. #endif
  483. #endif
  484. #endif
  485. /* Some sprintfs can't deal with a lot of arguments, so we split this */
  486. /* Note it also needs fixing for C9X, so we ALWAYS split it. */
  487. sprintf(msg, "%.24s %d %s %" L_FORMAT " ",
  488. ctime(&curtime),
  489. xfertime,
  490. remotehost,
  491. byte_count
  492.     );
  493. msglen = strlen(msg); /* sigh */
  494. snprintf(msg + msglen, sizeof(msg) - msglen, "%s %c %s %c %c %s ftp %d %s %cn",
  495.  namebuf,
  496.  (type == TYPE_A) ? 'a' : 'b',
  497.  opt_string(options),
  498.  'o',
  499.  anonymous ? 'a' : (guest ? 'g' : 'r'),
  500.  anonymous ? guestpw : pw->pw_name,
  501.  authenticated,
  502.  authenticated ? authuser : "*",
  503.  TransferComplete ? 'c' : 'i'
  504.     );
  505. /* Ensure msg always ends with 'n' */
  506. if (strlen(msg) == sizeof(msg) - 1)
  507.     msg[sizeof(msg) - 2] = 'n';
  508. if (syslogmsg != 1)
  509.     write(xferlog, msg, strlen(msg));
  510. if (syslogmsg != 0)
  511.     syslog(LOG_INFO, "xferlog (send): %s", msg + 25);
  512.     }
  513.     data = -1;
  514.     pdata = -1;
  515.   done:
  516.     if (closefunc)
  517. (*closefunc) (fin);
  518. }
  519. void store(char *name, char *mode, int unique)
  520. {
  521.     FILE *fout, *din;
  522.     struct stat st;
  523.     int TransferIncomplete = 1;
  524.     char *gunique(char *local);
  525.     time_t start_time = time(NULL);
  526.     struct aclmember *entry = NULL;
  527.     int fdout;
  528.     char realname[MAXPATHLEN];
  529. #ifdef OVERWRITE
  530.     int overwrite = 1;
  531.     int exists = 0;
  532. #endif /* OVERWRITE */
  533.     int open_flags = 0;
  534. #ifdef UPLOAD
  535.     mode_t oldmask;
  536.     uid_t uid;
  537.     gid_t gid;
  538.     uid_t oldid;
  539.     int f_mode = -1, match_value = -1;
  540.     int valid = 0;
  541.     open_flags = (O_RDWR | O_CREAT |
  542.   ((mode != NULL && *mode == 'a') ? O_APPEND : O_TRUNC));
  543. #endif /* UPLOAD */
  544.     wu_realpath(name, realname, chroot_path);
  545. #ifdef TRANSFER_COUNT
  546. #ifdef TRANSFER_LIMIT
  547.     if (((file_limit_data_in > 0) && (file_count_in >= file_limit_data_in))
  548. || ((file_limit_data_total > 0) && (file_count_total >= file_limit_data_total))
  549.       || ((data_limit_data_in > 0) && (data_count_in >= data_limit_data_in))
  550. || ((data_limit_data_total > 0) && (data_count_total >= data_limit_data_total))) {
  551. if (log_security)
  552.     if (anonymous)
  553. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to upload %s (Transfer limits exceeded)",
  554.        guestpw, remoteident, realname);
  555.     else
  556. syslog(LOG_NOTICE, "%s of %s tried to upload %s (Transfer limits exceeded)",
  557.        pw->pw_name, remoteident, realname);
  558. reply(553, "Permission denied on server. (Transfer limits exceeded)");
  559. return;
  560.     }
  561.     if (((file_limit_raw_in > 0) && (xfer_count_in >= file_limit_raw_in))
  562. || ((file_limit_raw_total > 0) && (xfer_count_total >= file_limit_raw_total))
  563. || ((data_limit_raw_in > 0) && (byte_count_in >= data_limit_raw_in))
  564. || ((data_limit_raw_total > 0) && (byte_count_total >= data_limit_raw_total))) {
  565. if (log_security)
  566.     if (anonymous)
  567. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to upload %s (Transfer limits exceeded)",
  568.        guestpw, remoteident, realname);
  569.     else
  570. syslog(LOG_NOTICE, "%s of %s tried to upload %s (Transfer limits exceeded)",
  571.        pw->pw_name, remoteident, realname);
  572. reply(553, "Permission denied on server. (Transfer limits exceeded)");
  573. return;
  574.     }
  575. #endif
  576. #endif
  577.     if (unique && stat(name, &st) == 0 &&
  578. (name = gunique(name)) == NULL)
  579. return;
  580.     /*
  581.      * check the filename, is it legal?
  582.      */
  583.     if ((fn_check(name)) <= 0) {
  584. if (log_security)
  585.     if (anonymous)
  586. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to upload "%s" (path-filter)",
  587.        guestpw, remoteident, realname);
  588.     else
  589. syslog(LOG_NOTICE, "%s of %s tried to upload "%s" (path-filter)",
  590.        pw->pw_name, remoteident, realname);
  591. return;
  592.     }
  593. #ifdef OVERWRITE
  594.     /* if overwrite permission denied and file exists... then deny the user
  595.      * permission to write the file. */
  596.     while (getaclentry("overwrite", &entry) && ARG0 && ARG1 != NULL) {
  597. if (type_match(ARG1))
  598.     if (strcasecmp(ARG0, "yes") != 0) {
  599. overwrite = 0;
  600. open_flags |= O_EXCL;
  601.     }
  602.     }
  603. #ifdef PARANOID
  604.     overwrite = 0;
  605. #endif
  606.     if (!stat(name, &st))
  607. exists = 1;
  608.     if (!overwrite && exists) {
  609. if (log_security)
  610.     if (anonymous)
  611. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to overwrite %s",
  612.        guestpw, remoteident, realname);
  613.     else
  614. syslog(LOG_NOTICE, "%s of %s tried to overwrite %s",
  615.        pw->pw_name, remoteident, realname);
  616. reply(553, "%s: Permission denied on server. (Overwrite)", name);
  617. return;
  618.     }
  619. #endif /* OVERWRITE */
  620. #ifdef UPLOAD
  621.     if ((match_value = upl_check(name, &uid, &gid, &f_mode, &valid)) < 0) {
  622. if (log_security)
  623.     if (anonymous)
  624. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to upload %s (upload denied)",
  625.        guestpw, remoteident, realname);
  626.     else
  627. syslog(LOG_NOTICE, "%s of %s tried to upload %s (upload denied)",
  628.        pw->pw_name, remoteident, realname);
  629. return;
  630.     }
  631.     /* do not truncate the file if we are restarting */
  632.     if (restart_point)
  633. open_flags &= ~O_TRUNC;
  634.     /* if the user has an explicit new file mode, than open the file using
  635.      * that mode.  We must take care to not let the umask affect the file
  636.      * mode.
  637.      * 
  638.      * else open the file and let the default umask determine the file mode. */
  639.     if (f_mode >= 0) {
  640. oldmask = umask(0000);
  641. fdout = open(name, open_flags, f_mode);
  642. umask(oldmask);
  643.     }
  644.     else
  645. fdout = open(name, open_flags, 0666);
  646.     if (fdout < 0) {
  647. if (log_security)
  648.     if (anonymous)
  649. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to upload %s (permissions)",
  650.        guestpw, remoteident, realname);
  651.     else
  652. syslog(LOG_NOTICE, "%s of %s tried to upload %s (permissions)",
  653.        pw->pw_name, remoteident, realname);
  654. perror_reply(553, name);
  655. return;
  656.     }
  657.     /* if we have a uid and gid, then use them. */
  658. #ifdef OVERWRITE
  659.     if (!exists)
  660. #endif
  661. if (valid > 0) {
  662.     oldid = geteuid();
  663.     if (uid != 0)
  664. (void) seteuid((uid_t) uid);
  665.     if ((uid == 0) || ((fchown(fdout, uid, gid)) < 0)) {
  666. delay_signaling(); /* we can't allow any signals while euid==0: kinch */
  667. (void) seteuid((uid_t) 0);
  668. if ((fchown(fdout, uid, gid)) < 0) {
  669.     (void) seteuid(oldid);
  670.     enable_signaling(); /* we can allow signals once again: kinch */
  671.     perror_reply(550, "fchown");
  672.     return;
  673. }
  674. (void) seteuid(oldid);
  675. enable_signaling(); /* we can allow signals once again: kinch */
  676.     }
  677.     else
  678. (void) seteuid(oldid);
  679. }
  680. #endif /* UPLOAD */
  681.     if (restart_point && (open_flags & O_APPEND) == 0)
  682. mode = "r+";
  683. #ifdef UPLOAD
  684.     fout = fdopen(fdout, mode);
  685. #else
  686.     fout = fopen(name, mode);
  687. #endif /* UPLOAD */
  688.     if (fout == NULL) {
  689. if (log_security)
  690.     if (anonymous)
  691. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to upload %s (permissions)",
  692.        guestpw, remoteident, realname);
  693.     else
  694. syslog(LOG_NOTICE, "%s of %s tried to upload %s (permissions)",
  695.        pw->pw_name, remoteident, realname);
  696. perror_reply(553, name);
  697. return;
  698.     }
  699.     if (restart_point) {
  700. if (type == TYPE_A) {
  701.     register int i, n, c;
  702.     n = restart_point;
  703.     i = 0;
  704.     while (i++ < n) {
  705. if ((c = getc(fout)) == EOF) {
  706.     perror_reply(550, name);
  707.     goto done;
  708. }
  709. if (c == 'n')
  710.     i++;
  711.     }
  712.     /* We must do this seek to "current" position because we are
  713.      * changing from reading to writing. */
  714.     if (fseek(fout, 0L, SEEK_CUR) < 0) {
  715. perror_reply(550, name);
  716. goto done;
  717.     }
  718. }
  719. else if (lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
  720.     perror_reply(550, name);
  721.     goto done;
  722. }
  723.     }
  724.     din = dataconn(name, (off_t) - 1, "r");
  725.     if (din == NULL)
  726. goto done;
  727.     TransferIncomplete = receive_data(din, fout);
  728.     (void) fclose(din);
  729.     if (TransferIncomplete == 0) {
  730. if (unique)
  731.     reply(226, "Transfer complete (unique file name:%s).", name);
  732. else
  733.     reply(226, "Transfer complete.");
  734.     }
  735.     fb_realpath(name, LastFileTransferred);
  736. #ifdef MAIL_ADMIN
  737.     if (anonymous && incmails > 0) {
  738. FILE *sck = NULL;
  739. unsigned char temp = 0, temp2 = 0;
  740. char pathname[MAXPATHLEN];
  741. while ((temp < mailservers) && (sck == NULL))
  742.     sck = SockOpen(mailserver[temp++], 25);
  743. if (sck == NULL) {
  744.     syslog(LOG_ERR, "Can't connect to a mailserver.");
  745.     goto mailfail;
  746. }
  747. if (Reply(sck) != 220) {
  748.     syslog(LOG_ERR, "Mailserver failed to initiate contact.");
  749.     goto mailfail;
  750. }
  751. if (Send(sck, "HELO localhostrn") != 250) {
  752.     syslog(LOG_ERR, "Mailserver doesn't understand HELO.");
  753.     goto mailfail;
  754. }
  755. if (Send(sck, "MAIL FROM: <%s>rn", email(mailfrom)) != 250) {
  756.     syslog(LOG_ERR, "Mailserver didn't accept MAIL FROM.");
  757.     goto mailfail;
  758. }
  759. for (temp = 0; temp < incmails; temp++) {
  760.     if (Send(sck, "RCPT TO: <%s>rn", email(incmail[temp])) == 250)
  761. temp2++;
  762. }
  763. if (temp2 == 0) {
  764.     syslog(LOG_ERR, "Mailserver didn't accept any RCPT TO.");
  765.     goto mailfail;
  766. }
  767. if (Send(sck, "DATArn") != 354) {
  768.     syslog(LOG_ERR, "Mailserver didn't accept DATA.");
  769.     goto mailfail;
  770. }
  771. SockPrintf(sck, "From: wu-ftpd <%s>rn", mailfrom);
  772. SockPrintf(sck, "Subject: New file uploaded: %srnrn", name);
  773. fb_realpath(name, pathname);
  774. SockPrintf(sck, "%s uploaded %s from %s.rnFile size is %d.rnPlease move the file where it belongs.rn", guestpw, pathname, remotehost, byte_count);
  775. if (Send(sck, ".rn") != 250)
  776.     syslog(LOG_ERR, "Message rejected by mailserver.");
  777. if (Send(sck, "QUITrn") != 221)
  778.     syslog(LOG_ERR, "Mailserver didn't accept QUIT.");
  779. goto mailok;
  780.       mailfail:
  781. if (sck != NULL)
  782.     fclose(sck);
  783.       mailok:
  784. sck = NULL; /* We don't need this, but some (stupid) compilers need an
  785.    instruction after a label. This one can't hurt. */
  786.     }
  787. #endif /* MAIL_ADMIN */
  788.     if (log_incoming_xfers && (xferlog || syslogmsg)) {
  789. char namebuf[MAXPATHLEN], msg[MAXPATHLEN + 2 * MAXHOSTNAMELEN + 100 + 128]; /* AUTHNAMESIZE is 100 */
  790. size_t msglen; /* for stupid_sprintf */
  791. int xfertime = time(NULL) - start_time;
  792. time_t curtime = time(NULL);
  793. int loop;
  794. if (!xfertime)
  795.     xfertime++;
  796. #ifdef XFERLOG_REALPATH
  797. wu_realpath(name, namebuf, chroot_path);
  798. #else
  799. fb_realpath(name, namebuf);
  800. #endif
  801. for (loop = 0; namebuf[loop]; loop++)
  802.     if (isspace(namebuf[loop]) || iscntrl(namebuf[loop]))
  803. namebuf[loop] = '_';
  804. /* see above */
  805. sprintf(msg, "%.24s %d %s %" L_FORMAT " ",
  806. ctime(&curtime),
  807. xfertime,
  808. remotehost,
  809. byte_count
  810.     );
  811. msglen = strlen(msg); /* sigh */
  812. snprintf(msg + msglen, sizeof(msg) - msglen, "%s %c %s %c %c %s ftp %d %s %cn",
  813.  namebuf,
  814.  (type == TYPE_A) ? 'a' : 'b',
  815.  opt_string(0),
  816.  'i',
  817.  anonymous ? 'a' : (guest ? 'g' : 'r'),
  818.  anonymous ? guestpw : pw->pw_name,
  819.  authenticated,
  820.  authenticated ? authuser : "*",
  821.  TransferIncomplete ? 'i' : 'c'
  822.     );
  823. /* Ensure msg always ends with 'n' */
  824. if (strlen(msg) == sizeof(msg) - 1)
  825.     msg[sizeof(msg) - 2] = 'n';
  826. if (syslogmsg != 1)
  827.     write(xferlog, msg, strlen(msg));
  828. if (syslogmsg != 0)
  829.     syslog(LOG_INFO, "xferlog (recv): %s", msg + 25);
  830.     }
  831.     data = -1;
  832.     pdata = -1;
  833.   done:
  834.     (void) fclose(fout);
  835. }
  836. FILE *getdatasock(char *mode)
  837. {
  838.     int s, on = 1, tries;
  839.     if (data >= 0)
  840. return (fdopen(data, mode));
  841.     delay_signaling(); /* we can't allow any signals while euid==0: kinch */
  842.     (void) seteuid((uid_t) 0);
  843.     s = socket(AF_INET, SOCK_STREAM, 0);
  844.     if (s < 0)
  845. goto bad;
  846.     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
  847.    (char *) &on, sizeof(on)) < 0)
  848. goto bad;
  849.     if (keepalive)
  850. (void) setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on));
  851.     if (TCPwindowsize)
  852. (void) setsockopt(s, SOL_SOCKET, (*mode == 'w' ? SO_SNDBUF : SO_RCVBUF),
  853.   (char *) &TCPwindowsize, sizeof(TCPwindowsize));
  854.     /* anchor socket to avoid multi-homing problems */
  855.     data_source.sin_family = AF_INET;
  856.     data_source.sin_addr = ctrl_addr.sin_addr;
  857. #if defined(VIRTUAL) && defined(CANT_BIND) /* can't bind to virtual address */
  858.     data_source.sin_addr.s_addr = htonl(INADDR_ANY);
  859. #endif
  860.     for (tries = 1;; tries++) {
  861. if (bind(s, (struct sockaddr *) &data_source,
  862.  sizeof(data_source)) >= 0)
  863.     break;
  864. if (errno != EADDRINUSE || tries > 10)
  865.     goto bad;
  866. sleep(tries);
  867.     }
  868. #if defined(M_UNIX) && !defined(_M_UNIX) /* bug in old TCP/IP release */
  869.     {
  870. struct linger li;
  871. li.l_onoff = 1;
  872. li.l_linger = 900;
  873. if (setsockopt(s, SOL_SOCKET, SO_LINGER,
  874.        (char *) &li, sizeof(struct linger)) < 0) {
  875.     syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m");
  876.     goto bad;
  877. }
  878.     }
  879. #endif
  880.     (void) seteuid((uid_t) pw->pw_uid);
  881.     enable_signaling(); /* we can allow signals once again: kinch */
  882. #ifdef IPTOS_THROUGHPUT
  883.     on = IPTOS_THROUGHPUT;
  884.     if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *) &on, sizeof(int)) < 0)
  885.     syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
  886. #endif
  887. #ifdef TCP_NOPUSH
  888.     /*
  889.      * Turn off push flag to keep sender TCP from sending short packets
  890.      * at the boundaries of each write().  Should probably do a SO_SNDBUF
  891.      * to set the send buffer size as well, but that may not be desirable
  892.      * in heavy-load situations.
  893.      */
  894.     on = 1;
  895.     if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *) &on, sizeof on) < 0)
  896. syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");
  897. #endif
  898.     return (fdopen(s, mode));
  899.   bad:
  900.     on = errno; /* hold errno for return */
  901.     (void) seteuid((uid_t) pw->pw_uid);
  902.     enable_signaling(); /* we can allow signals once again: kinch */
  903.     if (s != -1)
  904. (void) close(s);
  905.     errno = on;
  906.     return (NULL);
  907. }
  908. FILE *dataconn(char *name, off_t size, char *mode)
  909. {
  910.     char sizebuf[32];
  911.     FILE *file;
  912.     int retry = 0;
  913.     int on = 1;
  914. #ifdef IPTOS_LOWDELAY
  915.     int tos;
  916. #endif
  917. #ifdef THROUGHPUT
  918.     int bps;
  919.     double bpsmult;
  920. #endif
  921.     file_size = size;
  922.     byte_count = 0;
  923.     if (size != (off_t) - 1)
  924. (void) sprintf(sizebuf, " (%" L_FORMAT " bytes)", size);
  925.     else
  926. (void) strcpy(sizebuf, "");
  927.     if (pdata >= 0) {
  928. struct sockaddr_in from;
  929. char dataaddr[MAXHOSTNAMELEN];
  930. #if defined(UNIXWARE) || defined(AIX)
  931. size_t fromlen = sizeof(from);
  932. #else
  933. int fromlen = sizeof(from);
  934. #endif
  935. int s;
  936. #ifdef FD_ZERO
  937. int rv;
  938. #endif
  939. if (keepalive)
  940.     (void) setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on));
  941. if (TCPwindowsize)
  942.     (void) setsockopt(pdata, SOL_SOCKET, (*mode == 'w' ? SO_SNDBUF : SO_RCVBUF),
  943.     (char *) &TCPwindowsize, sizeof(TCPwindowsize));
  944. #ifdef FD_ZERO
  945. do {
  946.     struct timeval timeout;
  947.     fd_set set;
  948.     FD_ZERO(&set);
  949.     FD_SET(pdata, &set);
  950.     timeout.tv_usec = 0;
  951.     timeout.tv_sec = timeout_accept;
  952. #ifdef HPUX_SELECT
  953.     rv = select(pdata + 1, (int *) &set, NULL, NULL, &timeout);
  954. #else
  955.     rv = select(pdata + 1, &set, (fd_set *) 0, (fd_set *) 0,
  956. (struct timeval *) &timeout);
  957. #endif
  958. } while ((rv == -1) && (errno == EINTR));
  959. if ((rv != -1) && (rv != 0))
  960.     s = accept(pdata, (struct sockaddr *) &from, &fromlen);
  961. else
  962.     s = -1;
  963. #else /* FD_ZERO */
  964. (void) signal(SIGALRM, alarm_signal);
  965. alarm(timeout_accept);
  966. s = accept(pdata, (struct sockaddr *) &from, &fromlen);
  967. alarm(0);
  968. #endif
  969. if (s == -1) {
  970.     reply(425, "Can't open data connection.");
  971.     (void) close(pdata);
  972.     pdata = -1;
  973.     return (NULL);
  974. }
  975. (void) close(pdata);
  976. pdata = s;
  977. #ifdef IPTOS_LOWDELAY
  978. tos = IPTOS_LOWDELAY;
  979. (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *) &tos,
  980.   sizeof(int));
  981. #endif
  982. (void) strncpy(dataaddr, inet_ntoa(from.sin_addr), sizeof(dataaddr));
  983. if (!pasv_allowed(dataaddr))
  984.     if (strcasecmp(dataaddr, remoteaddr) != 0) {
  985. /* 
  986.  * This will log when data connection comes from an address different
  987.  * than the control connection.
  988.  */
  989. #ifdef FIGHT_PASV_PORT_RACE
  990. syslog(LOG_ERR, "%s of %s: data connect from %s for %s%s",
  991.        anonymous ? guestpw : pw->pw_name, remoteident,
  992.        dataaddr, name, sizebuf);
  993. reply(425, "Possible PASV port theft, cannot open data connection.");
  994. (void) close(pdata);
  995. pdata = -1;
  996. return (NULL);
  997. #else
  998. syslog(LOG_NOTICE, "%s of %s: data connect from %s for %s%s",
  999.        anonymous ? guestpw : pw->pw_name, remoteident,
  1000.        dataaddr, name, sizebuf);
  1001. #endif
  1002.     }
  1003. #ifdef THROUGHPUT
  1004. throughput_calc(name, &bps, &bpsmult);
  1005. if (bps != -1) {
  1006.     lreply(150, "Opening %s mode data connection for %s%s.",
  1007.    type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
  1008.     reply(150, "Restricting network throughput to %d bytes/s.", bps);
  1009. }
  1010. else
  1011. #endif
  1012.     reply(150, "Opening %s mode data connection for %s%s.",
  1013.   type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
  1014. return (fdopen(pdata, mode));
  1015.     }
  1016.     if (data >= 0) {
  1017. reply(125, "Using existing data connection for %s%s.",
  1018.       name, sizebuf);
  1019. usedefault = 1;
  1020. return (fdopen(data, mode));
  1021.     }
  1022.     if (usedefault)
  1023. data_dest = his_addr;
  1024.     if (data_dest.sin_port == 0) {
  1025. reply(500, "Can't build data connection: no PORT specified");
  1026. return (NULL);
  1027.     }
  1028.     usedefault = 1;
  1029.     file = getdatasock(mode);
  1030.     if (file == NULL) {
  1031. reply(425, "Can't create data socket (%s,%d): %s.",
  1032.       inet_ntoa(data_source.sin_addr),
  1033.       ntohs(data_source.sin_port), strerror(errno));
  1034. return (NULL);
  1035.     }
  1036.     data = fileno(file);
  1037.     (void) signal(SIGALRM, alarm_signal);
  1038.     alarm(timeout_connect);
  1039.     while (connect(data, (struct sockaddr *) &data_dest,
  1040.    sizeof(data_dest)) < 0) {
  1041. alarm(0);
  1042. if ((errno == EADDRINUSE || errno == EINTR) && retry < swaitmax) {
  1043.     sleep((unsigned) swaitint);
  1044.     retry += swaitint;
  1045.     (void) signal(SIGALRM, alarm_signal);
  1046.     alarm(timeout_connect);
  1047.     continue;
  1048. }
  1049. perror_reply(425, "Can't build data connection");
  1050. (void) fclose(file);
  1051. data = -1;
  1052. return (NULL);
  1053.     }
  1054.     alarm(0);
  1055.     if (keepalive)
  1056. (void) setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on));
  1057.     if (TCPwindowsize)
  1058. (void) setsockopt(data, SOL_SOCKET, (*mode == 'w' ? SO_SNDBUF : SO_RCVBUF),
  1059.   (char *) &TCPwindowsize, sizeof(TCPwindowsize));
  1060. #ifdef THROUGHPUT
  1061.     throughput_calc(name, &bps, &bpsmult);
  1062.     if (bps != -1) {
  1063. lreply(150, "Opening %s mode data connection for %s%s.",
  1064.        type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
  1065. reply(150, "Restricting network throughput to %d bytes/s.", bps);
  1066.     }
  1067.     else
  1068. #endif
  1069. reply(150, "Opening %s mode data connection for %s%s.",
  1070.       type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
  1071.     return (file);
  1072. }
  1073. /* Tranfer the contents of "instr" to "outstr" peer using the appropriate
  1074.  * encapsulation of the data subject to Mode, Structure, and Type.
  1075.  *
  1076.  * NB: Form isn't handled. */
  1077. int
  1078. #ifdef THROUGHPUT
  1079.     send_data(char *name, FILE *instr, FILE *outstr, off_t blksize)
  1080. #else
  1081.      send_data(FILE *instr, FILE *outstr, off_t blksize)
  1082. #endif
  1083. {
  1084.     register int c, cnt = 0;
  1085.     static char *buf;
  1086.     int netfd, filefd;
  1087. #ifdef THROUGHPUT
  1088.     int bps;
  1089.     double bpsmult;
  1090.     time_t t1, t2;
  1091. #endif
  1092. #ifdef THROUGHPUT
  1093.     throughput_calc(name, &bps, &bpsmult);
  1094. #endif
  1095.     buf = NULL;
  1096.     if (wu_setjmp(urgcatch)) {
  1097. draconian_FILE = NULL;
  1098. alarm(0);
  1099. transflag = 0;
  1100. if (buf)
  1101.     (void) free(buf);
  1102. retrieve_is_data = 1;
  1103. return (0);
  1104.     }
  1105.     transflag++;
  1106.     switch (type) {
  1107.     case TYPE_A:
  1108. draconian_FILE = outstr;
  1109. (void) signal(SIGALRM, draconian_alarm_signal);
  1110. alarm(timeout_data);
  1111. while ((draconian_FILE != NULL) && ((c = getc(instr)) != EOF)) {
  1112.     if (++byte_count % 4096 == 0) {
  1113. (void) signal(SIGALRM, draconian_alarm_signal);
  1114. alarm(timeout_data);
  1115.     }
  1116.     if (c == 'n') {
  1117. if (ferror(outstr))
  1118.     goto data_err;
  1119. (void) putc('r', outstr);
  1120. #ifdef TRANSFER_COUNT
  1121. if (retrieve_is_data) {
  1122.     data_count_total++;
  1123.     data_count_out++;
  1124. }
  1125. byte_count_total++;
  1126. byte_count_out++;
  1127. #endif
  1128.     }
  1129.     (void) putc(c, outstr);
  1130. #ifdef TRANSFER_COUNT
  1131.     if (retrieve_is_data) {
  1132. data_count_total++;
  1133. data_count_out++;
  1134.     }
  1135.     byte_count_total++;
  1136.     byte_count_out++;
  1137. #endif
  1138. }
  1139. if (draconian_FILE != NULL) {
  1140.     (void) signal(SIGALRM, draconian_alarm_signal);
  1141.     alarm(timeout_data);
  1142.     fflush(outstr);
  1143. }
  1144. if (draconian_FILE != NULL) {
  1145.     (void) signal(SIGALRM, draconian_alarm_signal);
  1146.     alarm(timeout_data);
  1147.     socket_flush_wait(outstr);
  1148. }
  1149. transflag = 0;
  1150. if (ferror(instr))
  1151.     goto file_err;
  1152. if ((draconian_FILE == NULL) || ferror(outstr))
  1153.     goto data_err;
  1154. draconian_FILE = NULL;
  1155. alarm(0);
  1156. reply(226, "Transfer complete.");
  1157. #ifdef TRANSFER_COUNT
  1158. if (retrieve_is_data) {
  1159.     file_count_total++;
  1160.     file_count_out++;
  1161. }
  1162. xfer_count_total++;
  1163. xfer_count_out++;
  1164. #endif
  1165. retrieve_is_data = 1;
  1166. return (1);
  1167.     case TYPE_I:
  1168.     case TYPE_L:
  1169. #ifdef THROUGHPUT
  1170. if (bps != -1)
  1171.     blksize = bps;
  1172. #endif
  1173. if ((buf = (char *) malloc(blksize)) == NULL) {
  1174.     transflag = 0;
  1175.     perror_reply(451, "Local resource failure: malloc");
  1176.     retrieve_is_data = 1;
  1177.     return (0);
  1178. }
  1179. netfd = fileno(outstr);
  1180. filefd = fileno(instr);
  1181. draconian_FILE = outstr;
  1182. (void) signal(SIGALRM, draconian_alarm_signal);
  1183. alarm(timeout_data);
  1184. #ifdef THROUGHPUT
  1185. if (bps != -1)
  1186.     t1 = time(NULL);
  1187. #endif
  1188. while ((draconian_FILE != NULL) && ((cnt = read(filefd, buf, blksize)) > 0 && write(netfd, buf, cnt) == cnt)) {
  1189.     (void) signal(SIGALRM, draconian_alarm_signal);
  1190.     alarm(timeout_data);
  1191.     byte_count += cnt;
  1192. #ifdef TRANSFER_COUNT
  1193.     if (retrieve_is_data) {
  1194. data_count_total += cnt;
  1195. data_count_out += cnt;
  1196.     }
  1197.     byte_count_total += cnt;
  1198.     byte_count_out += cnt;
  1199. #endif
  1200. #ifdef THROUGHPUT
  1201.     if (bps != -1) {
  1202. t2 = time(NULL);
  1203. if (t2 == t1)
  1204.     sleep(1);
  1205. t1 = time(NULL);
  1206.     }
  1207. #endif
  1208. }
  1209. #ifdef THROUGHPUT
  1210. if (bps != -1)
  1211.     throughput_adjust(name);
  1212. #endif
  1213. transflag = 0;
  1214. (void) free(buf);
  1215. if (draconian_FILE != NULL) {
  1216.     (void) signal(SIGALRM, draconian_alarm_signal);
  1217.     alarm(timeout_data);
  1218.     socket_flush_wait(outstr);
  1219. }
  1220. if (cnt != 0) {
  1221.     if (cnt < 0)
  1222. goto file_err;
  1223.     goto data_err;
  1224. }
  1225. if (draconian_FILE == NULL)
  1226.     goto data_err;
  1227. draconian_FILE = NULL;
  1228. alarm(0);
  1229. reply(226, "Transfer complete.");
  1230. #ifdef TRANSFER_COUNT
  1231. if (retrieve_is_data) {
  1232.     file_count_total++;
  1233.     file_count_out++;
  1234. }
  1235. xfer_count_total++;
  1236. xfer_count_out++;
  1237. #endif
  1238. retrieve_is_data = 1;
  1239. return (1);
  1240.     default:
  1241. transflag = 0;
  1242. reply(550, "Unimplemented TYPE %d in send_data", type);
  1243. retrieve_is_data = 1;
  1244. return (0);
  1245.     }
  1246.   data_err:
  1247.     draconian_FILE = NULL;
  1248.     alarm(0);
  1249.     transflag = 0;
  1250.     perror_reply(426, "Data connection");
  1251.     retrieve_is_data = 1;
  1252.     return (0);
  1253.   file_err:
  1254.     draconian_FILE = NULL;
  1255.     alarm(0);
  1256.     transflag = 0;
  1257.     perror_reply(551, "Error on input file");
  1258.     retrieve_is_data = 1;
  1259.     return (0);
  1260. }
  1261. /* Transfer data from peer to "outstr" using the appropriate encapulation of
  1262.  * the data subject to Mode, Structure, and Type.
  1263.  *
  1264.  * N.B.: Form isn't handled. */
  1265. int receive_data(FILE *instr, FILE *outstr)
  1266. {
  1267.     register int c;
  1268.     int cnt = 0, bare_lfs = 0;
  1269.     static char *buf;
  1270.     int netfd, filefd;
  1271. #ifdef BUFFER_SIZE
  1272.     size_t buffer_size = BUFFER_SIZE;
  1273. #else
  1274.     size_t buffer_size = BUFSIZ;
  1275. #endif
  1276.     buf = NULL;
  1277.     if (wu_setjmp(urgcatch)) {
  1278. alarm(0);
  1279. transflag = 0;
  1280. if (buf)
  1281.     (void) free(buf);
  1282. return (-1);
  1283.     }
  1284.     transflag++;
  1285.     switch (type) {
  1286.     case TYPE_I:
  1287.     case TYPE_L:
  1288. if ((buf = (char *) malloc(buffer_size)) == NULL) {
  1289.     transflag = 0;
  1290.     perror_reply(451, "Local resource failure: malloc");
  1291.     return (-1);
  1292. }
  1293. netfd = fileno(instr);
  1294. filefd = fileno(outstr);
  1295. draconian_FILE = instr;
  1296. (void) signal(SIGALRM, draconian_alarm_signal);
  1297. alarm(timeout_data);
  1298. while ((draconian_FILE != NULL) && ((cnt = read(netfd, buf, buffer_size)) > 0 && write(filefd, buf, cnt) == cnt)) {
  1299.     byte_count += cnt;
  1300. #ifdef TRANSFER_COUNT
  1301.     data_count_total += cnt;
  1302.     data_count_in += cnt;
  1303.     byte_count_total += cnt;
  1304.     byte_count_in += cnt;
  1305. #endif
  1306.     (void) signal(SIGALRM, draconian_alarm_signal);
  1307.     alarm(timeout_data);
  1308. }
  1309. transflag = 0;
  1310. (void) free(buf);
  1311. if (cnt != 0) {
  1312.     if (cnt < 0)
  1313. goto data_err;
  1314.     goto file_err;
  1315. }
  1316. if (draconian_FILE == NULL)
  1317.     goto data_err;
  1318. draconian_FILE = NULL;
  1319. alarm(0);
  1320. #ifdef TRANSFER_COUNT
  1321. file_count_total++;
  1322. file_count_in++;
  1323. xfer_count_total++;
  1324. xfer_count_in++;
  1325. #endif
  1326. return (0);
  1327.     case TYPE_E:
  1328. reply(553, "TYPE E not implemented.");
  1329. transflag = 0;
  1330. return (-1);
  1331.     case TYPE_A:
  1332. draconian_FILE = instr;
  1333. (void) signal(SIGALRM, draconian_alarm_signal);
  1334. alarm(timeout_data);
  1335. while ((draconian_FILE != NULL) && ((c = getc(instr)) != EOF)) {
  1336.     if (++byte_count % 4096 == 0) {
  1337. (void) signal(SIGALRM, draconian_alarm_signal);
  1338. alarm(timeout_data);
  1339.     }
  1340.     if (c == 'n')
  1341. bare_lfs++;
  1342.     while (c == 'r') {
  1343. if (ferror(outstr))
  1344.     goto file_err;
  1345. (void) signal(SIGALRM, draconian_alarm_signal);
  1346. alarm(timeout_data);
  1347. if ((draconian_FILE != NULL) && ((c = getc(instr)) != 'n')) {
  1348.     (void) putc('r', outstr);
  1349. #ifdef TRANSFER_COUNT
  1350.     data_count_total++;
  1351.     data_count_in++;
  1352.     byte_count_total++;
  1353.     byte_count_in++;
  1354. #endif
  1355.     if (c == EOF) /* null byte fix, noid@cyborg.larc.nasa.gov */
  1356. goto contin2;
  1357.     if (++byte_count % 4096 == 0) {
  1358. (void) signal(SIGALRM, draconian_alarm_signal);
  1359. alarm(timeout_data);
  1360.     }
  1361. }
  1362.     }
  1363.     (void) putc(c, outstr);
  1364. #ifdef TRANSFER_COUNT
  1365.     data_count_total++;
  1366.     data_count_in++;
  1367.     byte_count_total++;
  1368.     byte_count_in++;
  1369. #endif
  1370.   contin2:;
  1371. }
  1372. fflush(outstr);
  1373. if ((draconian_FILE == NULL) || ferror(instr))
  1374.     goto data_err;
  1375. if (ferror(outstr))
  1376.     goto file_err;
  1377. transflag = 0;
  1378. draconian_FILE = NULL;
  1379. alarm(0);
  1380. if (bare_lfs) {
  1381.     lreply(226, "WARNING! %d bare linefeeds received in ASCII mode", bare_lfs);
  1382.     lreply(0, "   File may not have transferred correctly.");
  1383. }
  1384. #ifdef TRANSFER_COUNT
  1385. file_count_total++;
  1386. file_count_in++;
  1387. xfer_count_total++;
  1388. xfer_count_in++;
  1389. #endif
  1390. return (0);
  1391.     default:
  1392. reply(550, "Unimplemented TYPE %d in receive_data", type);
  1393. transflag = 0;
  1394. return (-1);
  1395.     }
  1396.   data_err:
  1397.     draconian_FILE = NULL;
  1398.     alarm(0);
  1399.     transflag = 0;
  1400.     perror_reply(426, "Data Connection");
  1401.     return (-1);
  1402.   file_err:
  1403.     draconian_FILE = NULL;
  1404.     alarm(0);
  1405.     transflag = 0;
  1406.     perror_reply(452, "Error writing file");
  1407.     return (-1);
  1408. }
  1409. void statfilecmd(char *filename)
  1410. {
  1411. #ifndef INTERNAL_LS
  1412.     char line[BUFSIZ], *ptr;
  1413.     FILE *fin;
  1414.     int c;
  1415. #endif /* ! INTERNAL_LS */
  1416.     fixpath(filename);
  1417.     if (filename[0] == '')
  1418. filename = ".";
  1419. #ifndef INTERNAL_LS
  1420.     if (anonymous && dolreplies)
  1421. (void) snprintf(line, sizeof(line), ls_long, filename);
  1422.     else
  1423. (void) snprintf(line, sizeof(line), ls_short, filename);
  1424.     fin = ftpd_popen(line, "r", 0);
  1425. #endif /* ! INTERNAL_LS */
  1426.     lreply(213, "status of %s:", filename);
  1427. #ifndef INTERNAL_LS
  1428.     /*
  1429.        while ((c = getc(fin)) != EOF) {
  1430.        if (c == 'n') {
  1431.        if (ferror(stdout)) {
  1432.        perror_reply(421, "control connection");
  1433.        (void) ftpd_pclose(fin);
  1434.        dologout(1);
  1435.        / * NOTREACHED * /
  1436.        }
  1437.        if (ferror(fin)) {
  1438.        perror_reply(551, filename);
  1439.        (void) ftpd_pclose(fin);
  1440.        return;
  1441.        }
  1442.        (void) putc('r', stdout);
  1443.        }
  1444.        (void) putc(c, stdout);
  1445.        }
  1446.      */
  1447.     while (fgets(line, sizeof(line), fin) != NULL) {
  1448. if ((ptr = strchr(line, 'n'))) /* clip out unnecessary newline */
  1449.     *ptr = '';
  1450. lreply(0, "%s", line);
  1451.     }
  1452.     (void) ftpd_pclose(fin);
  1453. #else /* INTERNAL_LS */
  1454.     ls_dir(filename, 1, 0, 1, 0, 1, stdout);
  1455. #endif /* INTERNAL_LS */
  1456.     reply(213, "End of Status");
  1457. }
  1458. void statcmd(void)
  1459. {
  1460.     struct sockaddr_in *sin;
  1461.     u_char *a, *p;
  1462.     lreply(211, "%s FTP server status:", hostname);
  1463.     lreply(0, "     %s", version);
  1464.     if (!isdigit(remotehost[0]))
  1465. lreply(0, "     Connected to %s (%s)", remotehost,
  1466.        inet_ntoa(his_addr.sin_addr));
  1467.     else
  1468. lreply(0, "     Connected to %s", remotehost);
  1469.     if (logged_in) {
  1470. if (anonymous)
  1471.     lreply(0, "     Logged in anonymously");
  1472. else
  1473.     lreply(0, "     Logged in as %s", pw->pw_name);
  1474.     }
  1475.     else if (askpasswd)
  1476. lreply(0, "     Waiting for password");
  1477.     else
  1478. lreply(0, "     Waiting for user name");
  1479.     if (type == TYPE_L)
  1480. #ifdef NBBY
  1481. lreply(0, "     TYPE: %s %d; STRUcture: %s; transfer MODE: %s",
  1482.        typenames[type], NBBY, strunames[stru], modenames[mode]);
  1483. #else
  1484. lreply(0, "     TYPE: %s %d; STRUcture: %s; transfer MODE: %s",
  1485.        typenames[type], bytesize, strunames[stru], modenames[mode]);
  1486. #endif /* NBBY */
  1487.     else
  1488. lreply(0, "     TYPE: %s%s%s; STRUcture: %s; transfer MODE: %s",
  1489.        typenames[type], (type == TYPE_A || type == TYPE_E) ?
  1490.        ", FORM: " : "", (type == TYPE_A || type == TYPE_E) ?
  1491.        formnames[form] : "", strunames[stru], modenames[mode]);
  1492.     if (data != -1)
  1493. lreply(0, "     Data connection open");
  1494.     else if (pdata != -1 || usedefault == 0) {
  1495. if (usedefault == 0)
  1496.     sin = &data_dest;
  1497. else if (route_vectored)
  1498.     sin = &vect_addr;
  1499. else
  1500.     sin = &pasv_addr;
  1501. a = (u_char *) & sin->sin_addr;
  1502. p = (u_char *) & sin->sin_port;
  1503. #define UC(b) (((int) b) & 0xff)
  1504. lreply(0, "     %s (%d,%d,%d,%d,%d,%d)",
  1505.        usedefault == 0 ? "PORT" : "in Passive mode",
  1506.        UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
  1507. #undef UC
  1508.     }
  1509.     else
  1510. lreply(0, "     No data connection");
  1511. #ifdef TRANSFER_COUNT
  1512.     lreply(0, "     %d data bytes received in %d files", data_count_in, file_count_in);
  1513.     lreply(0, "     %d data bytes transmitted in %d files", data_count_out, file_count_out);
  1514.     lreply(0, "     %d data bytes total in %d files", data_count_total, file_count_total);
  1515.     lreply(0, "     %d traffic bytes received in %d transfers", byte_count_in, xfer_count_in);
  1516.     lreply(0, "     %d traffic bytes transmitted in %d transfers", byte_count_out, xfer_count_out);
  1517.     lreply(0, "     %d traffic bytes total in %d transfers", byte_count_total, xfer_count_total);
  1518. #endif
  1519.     reply(211, "End of status");
  1520. }
  1521. void fatal(char *s)
  1522. {
  1523.     reply(451, "Error in server: %sn", s);
  1524.     reply(221, "Closing connection due to server error.");
  1525.     dologout(0);
  1526.     /* NOTREACHED */
  1527. }
  1528. #define USE_REPLY_NOTFMT (1<<1) /* fmt is not a printf fmt (KLUDGE) */
  1529. #define USE_REPLY_LONG (1<<2) /* this is a long reply; use a - */
  1530. void vreply(long flags, int n, char *fmt, va_list ap)
  1531. {
  1532.     char buf[BUFSIZ];
  1533.     flags &= USE_REPLY_NOTFMT | USE_REPLY_LONG;
  1534.     if (n) /* if numeric is 0, don't output one; use n==0 in place of printf's */
  1535. sprintf(buf, "%03d%c", n, flags & USE_REPLY_LONG ? '-' : ' ');
  1536.     /* This is somewhat of a kludge for autospout.  I personally think that
  1537.      * autospout should be done differently, but that's not my department. -Kev
  1538.      */
  1539.     if (flags & USE_REPLY_NOTFMT)
  1540. snprintf(buf + (n ? 4 : 0), n ? sizeof(buf) - 4 : sizeof(buf), "%s", fmt);
  1541.     else
  1542. vsnprintf(buf + (n ? 4 : 0), n ? sizeof(buf) - 4 : sizeof(buf), fmt, ap);
  1543.     if (debug) /* debugging output :) */
  1544. syslog(LOG_DEBUG, "<--- %s", buf);
  1545.     /* Yes, you want the debugging output before the client output; wrapping
  1546.      * stuff goes here, you see, and you want to log the cleartext and send
  1547.      * the wrapped text to the client.
  1548.      */
  1549.     printf("%srn", buf); /* and send it to the client */
  1550. #ifdef TRANSFER_COUNT
  1551.     byte_count_total += strlen(buf);
  1552.     byte_count_out += strlen(buf);
  1553. #endif
  1554.     fflush(stdout);
  1555. }
  1556. void reply(int n, char *fmt,...)
  1557. {
  1558.     VA_LOCAL_DECL
  1559. if (autospout != NULL) { /* deal with the autospout stuff... */
  1560. char *p, *ptr = autospout;
  1561. while (*ptr) {
  1562.     if ((p = strchr(ptr, 'n')) != NULL) /* step through line by line */
  1563. *p = '';
  1564.     /* send a line...(note that this overrides dolreplies!) */
  1565.     vreply(USE_REPLY_LONG | USE_REPLY_NOTFMT, n, ptr, ap);
  1566.     if (p)
  1567. ptr = p + 1; /* set to the next line... ( is handled in the while) */
  1568.     else
  1569. break; /* oh, we're done; drop out of the loop */
  1570. }
  1571. if (autospout_free) { /* free autospout if necessary */
  1572.     (void) free(autospout);
  1573.     autospout_free = 0;
  1574. }
  1575. autospout = 0; /* clear the autospout */
  1576.     }
  1577.     VA_START(fmt);
  1578.     /* send the reply */
  1579.     vreply(0L, n, fmt, ap);
  1580.     VA_END;
  1581. }
  1582. void lreply(int n, char *fmt,...)
  1583. {
  1584.     VA_LOCAL_DECL
  1585. if (!dolreplies) /* prohibited from doing long replies? */
  1586. return;
  1587.     VA_START(fmt);
  1588.     /* send the reply */
  1589.     vreply(USE_REPLY_LONG, n, fmt, ap);
  1590.     VA_END;
  1591. }
  1592. void ack(char *s)
  1593. {
  1594.     reply(250, "%s command successful.", s);
  1595. }
  1596. void nack(char *s)
  1597. {
  1598.     reply(502, "%s command not implemented.", s);
  1599. }
  1600. void yyerror(char *s)
  1601. {
  1602.     char *cp;
  1603.     if (s == NULL || yyerrorcalled != 0)
  1604. return;
  1605.     if ((cp = strchr(cbuf, 'n')) != NULL)
  1606. *cp = '';
  1607.     reply(500, "'%s': command not understood.", cbuf);
  1608.     yyerrorcalled = 1;
  1609.     return;
  1610. }
  1611. void delete(char *name)
  1612. {
  1613.     struct stat st;
  1614.     char realname[MAXPATHLEN];
  1615.     /*
  1616.      * delete permission?
  1617.      */
  1618.     wu_realpath(name, realname, chroot_path);
  1619.     if ((del_check(name)) == 0) {
  1620. if (log_security)
  1621.     if (anonymous)
  1622. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to delete %s",
  1623.        guestpw, remoteident, realname);
  1624.     else
  1625. syslog(LOG_NOTICE, "%s of %s tried to delete %s",
  1626.        pw->pw_name, remoteident, realname);
  1627. return;
  1628.     }
  1629.     if (lstat(name, &st) < 0) {
  1630. perror_reply(550, name);
  1631. return;
  1632.     }
  1633.     if ((st.st_mode & S_IFMT) == S_IFDIR) {
  1634. uid_t uid;
  1635. gid_t gid;
  1636. int d_mode;
  1637. int valid;
  1638. /*
  1639.  * check the directory, can we rmdir here?
  1640.  */
  1641. if ((dir_check(name, &uid, &gid, &d_mode, &valid)) <= 0) {
  1642.     if (log_security)
  1643. if (anonymous)
  1644.     syslog(LOG_NOTICE, "anonymous(%s) of %s tried to delete directory %s",
  1645.    guestpw, remoteident, realname);
  1646. else
  1647.     syslog(LOG_NOTICE, "%s of %s tried to delete directory %s",
  1648.    pw->pw_name, remoteident, realname);
  1649.     return;
  1650. }
  1651. if (rmdir(name) < 0) {
  1652.     if (log_security)
  1653. if (anonymous)
  1654.     syslog(LOG_NOTICE, "anonymous(%s) of %s tried to delete directory %s (permissions)",
  1655.    guestpw, remoteident, realname);
  1656. else
  1657.     syslog(LOG_NOTICE, "%s of %s tried to delete directory %s (permissions)",
  1658.    pw->pw_name, remoteident, realname);
  1659.     perror_reply(550, name);
  1660.     return;
  1661. }
  1662. goto done;
  1663.     }
  1664.     if (unlink(name) < 0) {
  1665. if (log_security)
  1666.     if (anonymous)
  1667. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to delete %s (permissions)",
  1668.        guestpw, remoteident, realname);
  1669.     else
  1670. syslog(LOG_NOTICE, "%s of %s tried to delete %s (permissions)",
  1671.        pw->pw_name, remoteident, realname);
  1672. perror_reply(550, name);
  1673. return;
  1674.     }
  1675.   done:
  1676.     {
  1677. char path[MAXPATHLEN];
  1678. wu_realpath(name, path, chroot_path);
  1679. if (log_security)
  1680.     if ((st.st_mode & S_IFMT) == S_IFDIR)
  1681. if (anonymous) {
  1682.     syslog(LOG_NOTICE, "%s of %s deleted directory %s", guestpw, remoteident, path);
  1683. }
  1684. else {
  1685.     syslog(LOG_NOTICE, "%s of %s deleted directory %s", pw->pw_name,
  1686.    remoteident, path);
  1687. }
  1688.     else if (anonymous) {
  1689. syslog(LOG_NOTICE, "%s of %s deleted %s", guestpw,
  1690.        remoteident, path);
  1691.     }
  1692.     else {
  1693. syslog(LOG_NOTICE, "%s of %s deleted %s", pw->pw_name,
  1694.        remoteident, path);
  1695.     }
  1696.     }
  1697.     ack("DELE");
  1698. }
  1699. void cwd(char *path)
  1700. {
  1701.     struct aclmember *entry = NULL;
  1702.     char cdpath[MAXPATHLEN + 1];
  1703.     if (chdir(path) < 0) {
  1704. /* alias checking */
  1705. while (getaclentry("alias", &entry) && ARG0 && ARG1 != NULL) {
  1706.     if (!strcasecmp(ARG0, path)) {
  1707. if (chdir(ARG1) < 0)
  1708.     perror_reply(550, path);
  1709. else {
  1710.     show_message(250, C_WD);
  1711.     show_readme(250, C_WD);
  1712.     ack("CWD");
  1713. }
  1714. return;
  1715.     }
  1716. }
  1717. /* check for "cdpath" directories. */
  1718. entry = (struct aclmember *) NULL;
  1719. while (getaclentry("cdpath", &entry) && ARG0 != NULL) {
  1720.     snprintf(cdpath, sizeof cdpath, "%s/%s", ARG0, path);
  1721.     if (chdir(cdpath) >= 0) {
  1722. show_message(250, C_WD);
  1723. show_readme(250, C_WD);
  1724. ack("CWD");
  1725. return;
  1726.     }
  1727. }
  1728. perror_reply(550, path);
  1729.     }
  1730.     else {
  1731. show_message(250, C_WD);
  1732. show_readme(250, C_WD);
  1733. ack("CWD");
  1734.     }
  1735. }
  1736. void makedir(char *name)
  1737. {
  1738.     uid_t uid;
  1739.     gid_t gid;
  1740.     int d_mode;
  1741.     mode_t oldumask;
  1742.     int valid;
  1743.     uid_t oldid;
  1744.     char path[MAXPATHLEN + 1]; /* for realpath() later  - cky */
  1745.     char realname[MAXPATHLEN];
  1746.     wu_realpath(name, realname, chroot_path);
  1747.     /*
  1748.      * check the directory, can we mkdir here?
  1749.      */
  1750.     if ((dir_check(name, &uid, &gid, &d_mode, &valid)) <= 0) {
  1751. if (log_security)
  1752.     if (anonymous)
  1753. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to create directory %s",
  1754.        guestpw, remoteident, realname);
  1755.     else
  1756. syslog(LOG_NOTICE, "%s of %s tried to create directory %s",
  1757.        pw->pw_name, remoteident, realname);
  1758. return;
  1759.     }
  1760.     /*
  1761.      * check the filename, is it legal?
  1762.      */
  1763.     if ((fn_check(name)) <= 0) {
  1764. if (log_security)
  1765.     if (anonymous)
  1766. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to create directory %s (path-filter)",
  1767.        guestpw, remoteident, realname);
  1768.     else
  1769. syslog(LOG_NOTICE, "%s of %s tried to create directory %s (path-filter)",
  1770.        pw->pw_name, remoteident, realname);
  1771. return;
  1772.     }
  1773.     oldumask = umask(0000);
  1774.     if (valid <= 0) {
  1775. d_mode = 0777;
  1776. umask(oldumask);
  1777.     }
  1778.     if (mkdir(name, d_mode) < 0) {
  1779. if (errno == EEXIST) {
  1780.     if (log_security)
  1781. if (anonymous)
  1782.     syslog(LOG_NOTICE, "anonymous(%s) of %s tried to create directory %s (exists)",
  1783.    guestpw, remoteident, realname);
  1784. else
  1785.     syslog(LOG_NOTICE, "%s of %s tried to create directory %s (exists)",
  1786.    pw->pw_name, remoteident, realname);
  1787.     fb_realpath(name, path);
  1788.     reply(521, ""%s" directory exists", path);
  1789. }
  1790. else {
  1791.     if (log_security)
  1792. if (anonymous)
  1793.     syslog(LOG_NOTICE, "anonymous(%s) of %s tried to create directory %s (permissions)",
  1794.    guestpw, remoteident, realname);
  1795. else
  1796.     syslog(LOG_NOTICE, "%s of %s tried to create directory %s (permissions)",
  1797.    pw->pw_name, remoteident, realname);
  1798.     perror_reply(550, name);
  1799. }
  1800. umask(oldumask);
  1801. return;
  1802.     }
  1803.     umask(oldumask);
  1804.     if (valid > 0) {
  1805. oldid = geteuid();
  1806. if (uid != 0)
  1807.     (void) seteuid((uid_t) uid);
  1808. if ((uid == 0) || ((chown(name, uid, gid)) < 0)) {
  1809.     delay_signaling(); /* we can't allow any signals while euid==0: kinch */
  1810.     (void) seteuid((uid_t) 0);
  1811.     if ((chown(name, uid, gid)) < 0) {
  1812. (void) seteuid(oldid);
  1813. enable_signaling(); /* we can allow signals once again: kinch */
  1814. perror_reply(550, "chown");
  1815. return;
  1816.     }
  1817.     (void) seteuid(oldid);
  1818.     enable_signaling(); /* we can allow signals once again: kinch */
  1819. }
  1820. else
  1821.     (void) seteuid(oldid);
  1822.     }
  1823.     wu_realpath(name, path, chroot_path);
  1824.     if (log_security)
  1825. if (anonymous) {
  1826.     syslog(LOG_NOTICE, "%s of %s created directory %s", guestpw, remoteident, path);
  1827. }
  1828. else {
  1829.     syslog(LOG_NOTICE, "%s of %s created directory %s", pw->pw_name,
  1830.    remoteident, path);
  1831. }
  1832.     fb_realpath(name, path);
  1833.     /* According to RFC 959:
  1834.      *   The 257 reply to the MKD command must always contain the
  1835.      *   absolute pathname of the created directory.
  1836.      * This is implemented here using similar code to the PWD command.
  1837.      * XXX - still need to do `quote-doubling'.
  1838.      */
  1839.     reply(257, ""%s" new directory created.", path);
  1840. }
  1841. void removedir(char *name)
  1842. {
  1843.     uid_t uid;
  1844.     gid_t gid;
  1845.     int d_mode;
  1846.     int valid;
  1847.     char realname[MAXPATHLEN];
  1848.     wu_realpath(name, realname, chroot_path);
  1849.     /*
  1850.      * delete permission?
  1851.      */
  1852.     if ((del_check(name)) == 0)
  1853. return;
  1854.     /*
  1855.      * check the directory, can we rmdir here?
  1856.      */
  1857.     if ((dir_check(name, &uid, &gid, &d_mode, &valid)) <= 0) {
  1858. if (log_security)
  1859.     if (anonymous)
  1860. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to remove directory %s",
  1861.        guestpw, remoteident, realname);
  1862.     else
  1863. syslog(LOG_NOTICE, "%s of %s tried to remove directory %s",
  1864.        pw->pw_name, remoteident, realname);
  1865. return;
  1866.     }
  1867.     if (rmdir(name) < 0) {
  1868. if (errno == EBUSY)
  1869.     perror_reply(450, name);
  1870. else {
  1871.     if (log_security)
  1872. if (anonymous)
  1873.     syslog(LOG_NOTICE, "anonymous(%s) of %s tried to remove directory %s (permissions)",
  1874.    guestpw, remoteident, realname);
  1875. else
  1876.     syslog(LOG_NOTICE, "%s of %s tried to remove directory %s (permissions)",
  1877.    pw->pw_name, remoteident, realname);
  1878.     perror_reply(550, name);
  1879. }
  1880.     }
  1881.     else {
  1882. char path[MAXPATHLEN];
  1883. wu_realpath(name, path, chroot_path);
  1884. if (log_security)
  1885.     if (anonymous) {
  1886. syslog(LOG_NOTICE, "%s of %s deleted directory %s", guestpw, remoteident, path);
  1887.     }
  1888.     else {
  1889. syslog(LOG_NOTICE, "%s of %s deleted directory %s", pw->pw_name,
  1890.        remoteident, path);
  1891.     }
  1892. ack("RMD");
  1893.     }
  1894. }
  1895. void pwd(void)
  1896. {
  1897.     char path[MAXPATHLEN + 1];
  1898.     char rhome[MAXPATHLEN + 1];
  1899.     char *rpath = path; /* Path to return to client */
  1900.     int pathlen;
  1901. #ifndef MAPPING_CHDIR
  1902. #ifdef HAVE_GETCWD
  1903.     extern char *getcwd();
  1904. #else
  1905.     extern char *getwd(char *);
  1906. #endif
  1907. #endif /* MAPPING_CHDIR */
  1908. #ifdef HAVE_GETCWD
  1909.     if (getcwd(path, MAXPATHLEN) == (char *) NULL)
  1910. #else
  1911.     if (getwd(path) == (char *) NULL)
  1912. #endif
  1913. /* Dink!  If you couldn't get the path and the buffer is now likely to
  1914.    be undefined, why are you trying to PRINT it?!  _H*
  1915.    reply(550, "%s.", path); */
  1916.     {
  1917. fb_realpath(".", path); /* realpath_on_steroids can deal */
  1918.     }
  1919.     /* relative to home directory if restricted_user */
  1920.     if (restricted_user) {
  1921. fb_realpath(home, rhome);
  1922. pathlen = strlen(rhome);
  1923. if (pathlen && rhome[pathlen - 1] == '/')
  1924.     pathlen--;
  1925. rpath = rpath + pathlen;
  1926. if (!*rpath)
  1927.     strcpy(rpath, "/");
  1928.     }
  1929.     reply(257, ""%s" is current directory.", rpath);
  1930. }
  1931. char *renamefrom(char *name)
  1932. {
  1933.     struct stat st;
  1934.     if (lstat(name, &st) < 0) {
  1935. perror_reply(550, name);
  1936. return ((char *) 0);
  1937.     }
  1938.     reply(350, "File exists, ready for destination name");
  1939.     return (name);
  1940. }
  1941. void renamecmd(char *from, char *to)
  1942. {
  1943.     int allowed = (anonymous ? 0 : 1);
  1944.     char realfrom[MAXPATHLEN];
  1945.     char realto[MAXPATHLEN];
  1946.     struct aclmember *entry = NULL;
  1947. #ifdef PARANOID
  1948.     struct stat st;
  1949. #endif
  1950.     wu_realpath(from, realfrom, chroot_path);
  1951.     wu_realpath(to, realto, chroot_path);
  1952.     /*
  1953.      * check the filename, is it legal?
  1954.      */
  1955.     if ((fn_check(to)) == 0) {
  1956. if (log_security)
  1957.     if (anonymous)
  1958. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to rename %s to "%s" (path-filter)",
  1959.        guestpw, remoteident, realfrom, realto);
  1960.     else
  1961. syslog(LOG_NOTICE, "%s of %s tried to rename %s to "%s" (path-filter)",
  1962.        pw->pw_name, remoteident, realfrom, realto);
  1963. return;
  1964.     }
  1965.     /* 
  1966.      * if rename permission denied and file exists... then deny the user
  1967.      * permission to rename the file. 
  1968.      */
  1969.     while (getaclentry("rename", &entry) && ARG0 && ARG1 != NULL) {
  1970. if (type_match(ARG1))
  1971.     if (anonymous) {
  1972. if (*ARG0 == 'y')
  1973.     allowed = 1;
  1974.     }
  1975.     else if (*ARG0 == 'n')
  1976. allowed = 0;
  1977.     }
  1978.     if (!allowed) {
  1979. if (log_security)
  1980.     if (anonymous)
  1981. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to rename %s to %s",
  1982.        guestpw, remoteident, realfrom, realto);
  1983.     else
  1984. syslog(LOG_NOTICE, "%s of %s tried to rename %s to %s",
  1985.        pw->pw_name, remoteident, realfrom, realto);
  1986. reply(553, "%s: Permission denied on server. (rename)", from);
  1987. return;
  1988.     }
  1989. #ifdef PARANOID
  1990. /* Almost forgot about this.  Don't allow renaming TO existing files --
  1991.    otherwise someone can rename "trivial" to "warez", and "warez" is gone!
  1992.    XXX: This part really should do the same "overwrite" check as store(). */
  1993.     if (!stat(to, &st)) {
  1994. if (log_security)
  1995.     if (anonymous)
  1996. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to rename %s to %s",
  1997.        guestpw, remoteident, realfrom, realto);
  1998.     else
  1999. syslog(LOG_NOTICE, "%s of %s tried to rename %s to %s",
  2000.        pw->pw_name, remoteident, realfrom, realto);
  2001. reply(550, "%s: Permission denied on server. (rename)", to);
  2002. return;
  2003.     }
  2004. #endif
  2005.     if (rename(from, to) < 0) {
  2006. if (log_security)
  2007.     if (anonymous)
  2008. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to rename %s to %s",
  2009.        guestpw, remoteident, realfrom, realto);
  2010.     else
  2011. syslog(LOG_NOTICE, "%s of %s tried to rename %s to %s",
  2012.        pw->pw_name, remoteident, realfrom, realto);
  2013. perror_reply(550, "rename");
  2014.     }
  2015.     else {
  2016. char frompath[MAXPATHLEN];
  2017. char topath[MAXPATHLEN];
  2018. wu_realpath(from, frompath, chroot_path);
  2019. wu_realpath(to, topath, chroot_path);
  2020. if (log_security)
  2021.     if (anonymous) {
  2022. syslog(LOG_NOTICE, "%s of %s renamed %s to %s", guestpw, remoteident, frompath, topath);
  2023.     }
  2024.     else {
  2025. syslog(LOG_NOTICE, "%s of %s renamed %s to %s", pw->pw_name,
  2026.        remoteident, frompath, topath);
  2027.     }
  2028. ack("RNTO");
  2029.     }
  2030. }
  2031. void dolog(struct sockaddr_in *sin)
  2032. {
  2033. #ifndef NO_DNS
  2034.     struct hostent *hp;
  2035.     char *blah;
  2036. #ifdef DNS_TRYAGAIN
  2037.     int num_dns_tries = 0;
  2038.     /*
  2039.      * 27-Apr-93    EHK/BM
  2040.      * far away connections might take some time to get their IP address
  2041.      * resolved. That's why we try again -- maybe our DNS cache has the
  2042.      * PTR-RR now. This code is sloppy. Far better is to check what the
  2043.      * resolver returned so that in case of error, there's no need to
  2044.      * try again.
  2045.      */
  2046.   dns_again:
  2047.     hp = gethostbyaddr((char *) &sin->sin_addr,
  2048.        sizeof(struct in_addr), AF_INET);
  2049.     if (!hp && ++num_dns_tries <= 1) {
  2050. sleep(3);
  2051. goto dns_again; /* try DNS lookup once more     */
  2052.     }
  2053. #else
  2054.     hp = gethostbyaddr((char *) &sin->sin_addr, sizeof(struct in_addr), AF_INET);
  2055. #endif
  2056.     blah = inet_ntoa(sin->sin_addr);
  2057.     (void) strncpy(remoteaddr, blah, sizeof(remoteaddr));
  2058.     if (!strcasecmp(remoteaddr, "0.0.0.0")) {
  2059. nameserved = 1;
  2060. strncpy(remotehost, "localhost", sizeof(remotehost));
  2061.     }
  2062.     else {
  2063. if (hp) {
  2064.     nameserved = 1;
  2065.     (void) strncpy(remotehost, hp->h_name, sizeof(remotehost));
  2066. }
  2067. else {
  2068.     nameserved = 0;
  2069.     (void) strncpy(remotehost, remoteaddr, sizeof(remotehost));
  2070. }
  2071.     }
  2072. #else
  2073.     char *blah;
  2074.     blah = inet_ntoa(sin->sin_addr);
  2075.     (void) strncpy(remoteaddr, blah, sizeof(remoteaddr));
  2076.     nameserved = 0;
  2077.     (void) strncpy(remotehost, remoteaddr, sizeof(remotehost));
  2078. #endif
  2079.     remotehost[sizeof(remotehost) - 1] = '';
  2080.     sprintf(proctitle, "%s: connected", remotehost);
  2081.     setproctitle(proctitle);
  2082.     wu_authenticate();
  2083. /* Create a composite source identification string, to improve the logging
  2084.  * when RFC 931 is being used. */
  2085.     {
  2086. int n = 20 + strlen(remotehost) + strlen(remoteaddr) +
  2087. (authenticated ? strlen(authuser + 5) : 0);
  2088. if ((remoteident = malloc(n)) == NULL) {
  2089.     syslog(LOG_ERR, "malloc: %m");
  2090. #ifndef DEBUG
  2091.     exit(1);
  2092. #endif
  2093. }
  2094. else if (authenticated)
  2095.     sprintf(remoteident, "%s @ %s [%s]",
  2096.     authuser, remotehost, remoteaddr);
  2097. else
  2098.     sprintf(remoteident, "%s [%s]", remotehost, remoteaddr);
  2099.     }
  2100. #ifdef DAEMON
  2101.     if (be_daemon && logging)
  2102. syslog(LOG_INFO, "connection from %s", remoteident);
  2103. #else
  2104. #if 0 /* this is redundant unless the caller doesn't do *anything*, and
  2105.    tcpd will pick it up and deal with it better anyways. _H */
  2106.     if (logging)
  2107. syslog(LOG_INFO, "connection from %s", remoteident);
  2108. #endif
  2109. #endif
  2110. }
  2111. /* Record logout in wtmp file and exit with supplied status. */
  2112. void dologout(int status)
  2113. {
  2114.     /*
  2115.      * Prevent reception of SIGURG from resulting in a resumption
  2116.      * back to the main program loop.
  2117.      */
  2118.     transflag = 0;
  2119.     /*
  2120.      * Cancel any pending alarm request, reception of SIGALRM would cause
  2121.      * dologout() to be called again from the SIGALRM handler toolong().
  2122.      */
  2123.     (void) alarm(0);
  2124.     if (logged_in) {
  2125. delay_signaling(); /* we can't allow any signals while euid==0: kinch */
  2126. (void) seteuid((uid_t) 0);
  2127. if (wtmp_logging)
  2128.     wu_logwtmp(ttyline, pw->pw_name, remotehost, 0);
  2129.     }
  2130.     if (logging)
  2131. syslog(LOG_INFO, "FTP session closed");
  2132.     if (xferlog)
  2133. close(xferlog);
  2134.     acl_remove();
  2135.     close(data); /* H* fix: clean up a little better */
  2136.     close(pdata);
  2137. #ifdef AFS_AUTH
  2138.     ktc_ForgetAllTokens();
  2139. #endif
  2140.     /* beware of flushing buffers after a SIGPIPE */
  2141.     _exit(status);
  2142. }
  2143. SIGNAL_TYPE myoob(int sig)
  2144. {
  2145.     char *cp;
  2146.     /* only process if transfer occurring */
  2147.     if (!transflag) {
  2148. #ifdef SIGURG
  2149. (void) signal(SIGURG, myoob);
  2150. #endif
  2151. return;
  2152.     }
  2153.     cp = tmpline;
  2154.     if (wu_getline(cp, sizeof(tmpline) - 1, stdin) == NULL) {
  2155. reply(221, "You could at least say goodbye.");
  2156. dologout(0);
  2157.     }
  2158.     upper(cp);
  2159.     if (strcasecmp(cp, "ABORrn") == 0) {
  2160. tmpline[0] = '';
  2161. reply(426, "Transfer aborted. Data connection closed.");
  2162. reply(226, "Abort successful");
  2163. #ifdef SIGURG
  2164. (void) signal(SIGURG, myoob);
  2165. #endif
  2166. if (ftwflag > 0) {
  2167.     ftwflag++;
  2168.     return;
  2169. }
  2170. wu_longjmp(urgcatch, 1);
  2171.     }
  2172.     if (strcasecmp(cp, "STATrn") == 0) {
  2173. tmpline[0] = '';
  2174. if (file_size != (off_t) - 1)
  2175.     reply(213, "Status: %" L_FORMAT " of %" L_FORMAT " bytes transferred",
  2176.   byte_count, file_size);
  2177. else
  2178.     reply(213, "Status: %" L_FORMAT " bytes transferred", byte_count);
  2179.     }
  2180. #ifdef SIGURG
  2181.     (void) signal(SIGURG, myoob);
  2182. #endif
  2183. }
  2184. /* Note: a response of 425 is not mentioned as a possible response to the
  2185.  * PASV command in RFC959. However, it has been blessed as a legitimate
  2186.  * response by Jon Postel in a telephone conversation with Rick Adams on 25
  2187.  * Jan 89. */
  2188. void passive(void)
  2189. {
  2190. #if defined(UNIXWARE) || defined(AIX)
  2191.     size_t len;
  2192. #else
  2193.     int len;
  2194. #endif
  2195.     int bind_error;
  2196.     int on = 1;
  2197.     register char *p, *a;
  2198. /* H* fix: if we already *have* a passive socket, close it first.  Prevents
  2199.    a whole variety of entertaining clogging attacks. */
  2200.     if (pdata > 0) {
  2201. close(pdata);
  2202. pdata = -1;
  2203.     }
  2204.     if (!logged_in) {
  2205. reply(530, "Login with USER first.");
  2206. return;
  2207.     }
  2208.     pdata = socket(AF_INET, SOCK_STREAM, 0);
  2209.     if (pdata < 0) {
  2210. perror_reply(425, "Can't open passive connection");
  2211. return;
  2212.     }
  2213.     if (keepalive)
  2214. (void) setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on));
  2215.     if (TCPwindowsize) {
  2216. (void) setsockopt(pdata, SOL_SOCKET, SO_SNDBUF, (char *) &TCPwindowsize, sizeof(TCPwindowsize));
  2217. (void) setsockopt(pdata, SOL_SOCKET, SO_RCVBUF, (char *) &TCPwindowsize, sizeof(TCPwindowsize));
  2218.     }
  2219.     pasv_addr = ctrl_addr;
  2220.     pasv_addr.sin_port = 0;
  2221.     delay_signaling(); /* we can't allow any signals while euid==0: kinch */
  2222.     (void) seteuid((uid_t) 0); /* XXX: not needed if > 1024 */
  2223.     checkports();
  2224.     if (passive_port_min == -1) {
  2225. passive_port_max = 65534;
  2226. passive_port_min = 1024;
  2227.     }
  2228.     {
  2229. int *port_array;
  2230. int *pasv_port_array;
  2231. int i;
  2232. int j;
  2233. int k;
  2234. if (passive_port_max < passive_port_min) {
  2235.     (void) seteuid((uid_t) pw->pw_uid);
  2236.     enable_signaling(); /* we can allow signals once again: kinch */
  2237.     goto pasv_error;
  2238. }
  2239. i = passive_port_max - passive_port_min + 1;
  2240. port_array = calloc(i, sizeof(int));
  2241. if (port_array == NULL) {
  2242.     (void) seteuid((uid_t) pw->pw_uid);
  2243.     enable_signaling(); /* we can allow signals once again: kinch */
  2244.     goto pasv_error;
  2245. }
  2246. pasv_port_array = calloc(i, sizeof(int));
  2247. if (pasv_port_array == NULL) {
  2248.     free(port_array);
  2249.     (void) seteuid((uid_t) pw->pw_uid);
  2250.     enable_signaling(); /* we can allow signals once again: kinch */
  2251.     goto pasv_error;
  2252. }
  2253. do {
  2254.     --i;
  2255.     port_array[i] = passive_port_min + i;
  2256. } while (i > 0);
  2257. srand(time(NULL));
  2258. /*
  2259.    i = passive_port_max - passive_port_min + 1;
  2260.    do {
  2261.    --i;
  2262.    j = (int) (((1.0 + i) * rand()) / (RAND_MAX + 1.0));
  2263.    pasv_port_array [i] = port_array [j];
  2264.    while (++j <= i)
  2265.    port_array [j-1] = port_array [j];
  2266.    } while (i > 0);
  2267.  */
  2268. bind_error = -1;
  2269. errno = EADDRINUSE;
  2270. for (i = 3; (bind_error < 0) && (errno == EADDRINUSE) && (i > 0); i--) {
  2271.     for (j = passive_port_max - passive_port_min + 1; (bind_error < 0) && (errno == EADDRINUSE) && (j > 0); j--) {
  2272. if (i == 3) {
  2273.     k = (int) ((1.0 * j * rand()) / (RAND_MAX + 1.0));
  2274.     pasv_port_array[j - 1] = port_array[k];
  2275.     while (++k < j)
  2276. port_array[k - 1] = port_array[k];
  2277. }
  2278. pasv_addr.sin_port = htons(pasv_port_array[j - 1]);
  2279. bind_error = bind(pdata, (struct sockaddr *) &pasv_addr, sizeof(pasv_addr));
  2280.     }
  2281. }
  2282. free(pasv_port_array);
  2283. free(port_array);
  2284. if (bind_error < 0) {
  2285.     (void) seteuid((uid_t) pw->pw_uid);
  2286.     enable_signaling(); /* we can allow signals once again: kinch */
  2287.     goto pasv_error;
  2288. }
  2289.     }
  2290.     (void) seteuid((uid_t) pw->pw_uid);
  2291.     enable_signaling(); /* we can allow signals once again: kinch */
  2292.     len = sizeof(pasv_addr);
  2293.     if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
  2294. goto pasv_error;
  2295.     if (listen(pdata, 1) < 0)
  2296. goto pasv_error;
  2297.     usedefault = 1;
  2298.     if (route_vectored)
  2299. a = (char *) &vect_addr.sin_addr;
  2300.     else
  2301. a = (char *) &pasv_addr.sin_addr;
  2302.     p = (char *) &pasv_addr.sin_port;
  2303. #define UC(b) (((int) b) & 0xff)
  2304.     if (debug) {
  2305. char *s = calloc(128 + strlen(remoteident), sizeof(char));
  2306. if (s) {
  2307.     int i = ntohs(pasv_addr.sin_port);
  2308.     sprintf(s, "PASV port %i assigned to %s", i, remoteident);
  2309.     syslog(LOG_DEBUG, s);
  2310.     free(s);
  2311. }
  2312.     }
  2313.     reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
  2314.   UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
  2315.     return;
  2316.   pasv_error:
  2317.     (void) close(pdata);
  2318.     pdata = -1;
  2319.     if (debug) {
  2320. char *s = calloc(128 + strlen(remoteident), sizeof(char));
  2321. if (s) {
  2322.     sprintf(s, "PASV port assignment assigned for %s", remoteident);
  2323.     syslog(LOG_DEBUG, s);
  2324.     free(s);
  2325. }
  2326.     }
  2327.     perror_reply(425, "Can't open passive connection");
  2328.     return;
  2329. }
  2330. /*
  2331.  * Generate unique name for file with basename "local". The file named
  2332.  * "local" is already known to exist. Generates failure reply on error. 
  2333.  */
  2334. char *gunique(char *local)
  2335. {
  2336.     static char new[MAXPATHLEN];
  2337.     struct stat st;
  2338.     char *cp = strrchr(local, '/');
  2339.     int count = 0;
  2340.     if (cp)
  2341. *cp = '';
  2342.     if (stat(cp ? local : ".", &st) < 0) {
  2343. perror_reply(553, cp ? local : ".");
  2344. return ((char *) 0);
  2345.     }
  2346.     if (cp)
  2347. *cp = '/';
  2348.     (void) strncpy(new, local, (sizeof new) - 3);
  2349.     new[sizeof(new) - 3] = '';
  2350.     cp = new + strlen(new);
  2351.     *cp++ = '.';
  2352.     for (count = 1; count < 100; count++) {
  2353. if (count == 10) {
  2354.     cp -= 2;
  2355.     *cp++ = '.';
  2356. }
  2357. (void) sprintf(cp, "%d", count);
  2358. if (stat(new, &st) < 0)
  2359.     return (new);
  2360.     }
  2361.     reply(452, "Unique file name cannot be created.");
  2362.     return ((char *) 0);
  2363. }
  2364. /* Format and send reply containing system error number. */
  2365. void perror_reply(int code, char *string)
  2366. {
  2367.     /*
  2368.      * If restricted user and string starts with home dir path, strip it off
  2369.      * and return only the relative path.
  2370.      */
  2371.     if (restricted_user && (home != NULL) && (home[0] != '')) {
  2372. size_t len = strlen (home);
  2373. if (strncmp (home, string, len) == 0) {
  2374.     if (string[len - 1] == '/')
  2375. string += len - 1;
  2376.     else if (string[len] == '/')
  2377. string += len;
  2378.     else if (string[len] == '')
  2379. string = "/";
  2380. }
  2381.     }
  2382.     reply(code, "%s: %s.", string, strerror(errno));
  2383. }
  2384. static char *onefile[] =
  2385. {"", 0};
  2386. extern char **ftpglob(register char *v);
  2387. extern char *globerr;
  2388. void send_file_list(char *whichfiles)
  2389. {
  2390.     /* static so not clobbered by longjmp(), volatile would also work */
  2391.     static FILE *dout;
  2392.     static DIR *dirp;
  2393.     static char **sdirlist;
  2394.     static char *wildcard = NULL;
  2395.     struct stat st;
  2396.     register char **dirlist, *dirname;
  2397.     int simple = 0;
  2398.     /* This is ANSI/ISO C .. strpbrk should be in <string.h> which we've 
  2399.        ** already included so we don't need the following line.  'sides, it 
  2400.        ** breaks the GNU EGCS C compiler
  2401.        ** extern char *strpbrk(const char *, const char *);
  2402.      */
  2403. #ifdef TRANSFER_COUNT
  2404. #ifdef TRANSFER_LIMIT
  2405.     if (((file_limit_raw_out > 0) && (xfer_count_out >= file_limit_raw_out))
  2406. || ((file_limit_raw_total > 0) && (xfer_count_total >= file_limit_raw_total))
  2407.      || ((data_limit_raw_out > 0) && (byte_count_out >= data_limit_raw_out))
  2408. || ((data_limit_raw_total > 0) && (byte_count_total >= data_limit_raw_total))) {
  2409. if (log_security)
  2410.     if (anonymous)
  2411. syslog(LOG_NOTICE, "anonymous(%s) of %s tried to list files (Transfer limits exceeded)",
  2412.        guestpw, remoteident);
  2413.     else
  2414. syslog(LOG_NOTICE, "%s of %s tried to list files (Transfer limits exceeded)",
  2415.        pw->pw_name, remoteident);
  2416. reply(553, "Permission denied on server. (Transfer limits exceeded)");
  2417. return;
  2418.     }
  2419. #endif
  2420. #endif
  2421.     draconian_FILE = NULL;
  2422.     dout = NULL;
  2423.     dirp = NULL;
  2424.     sdirlist = NULL;
  2425.     wildcard = NULL;
  2426.     if (strpbrk(whichfiles, "~{[*?") == NULL) {
  2427. if (whichfiles[0] == '') {
  2428.     wildcard = strdup("*");
  2429.     if (wildcard == NULL) {
  2430. reply(550, "Memory allocation error");
  2431. goto globfree;
  2432.     }
  2433.     whichfiles = wildcard;
  2434. }
  2435. else if (stat(whichfiles, &st) >= 0) {
  2436.     if ((st.st_mode & S_IFMT) == S_IFDIR) {
  2437. wildcard = malloc(strlen(whichfiles) + 3);
  2438. if (wildcard == NULL) {
  2439.     reply(550, "Memory allocation error");
  2440.     goto globfree;
  2441. }
  2442. strcpy(wildcard, whichfiles);
  2443. strcat(wildcard, "/*");
  2444. whichfiles = wildcard;
  2445.     }
  2446. }
  2447.     }
  2448.     if (strpbrk(whichfiles, "~{[*?") != NULL) {
  2449. globerr = NULL;
  2450. dirlist = ftpglob(whichfiles);
  2451. sdirlist = dirlist; /* save to free later */
  2452. if (globerr != NULL) {
  2453.     reply(550, globerr);
  2454.     goto globfree;
  2455. }
  2456. else if (dirlist == NULL) {
  2457.     errno = ENOENT;
  2458.     perror_reply(550, whichfiles);
  2459.     goto globfree;
  2460. }
  2461.     }
  2462.     else {
  2463. onefile[0] = whichfiles;
  2464. dirlist = onefile;
  2465. simple = 1;
  2466.     }
  2467.     if (wu_setjmp(urgcatch)) {
  2468. transflag = 0;
  2469. if (dout != NULL)
  2470.     (void) fclose(dout);
  2471. if (dirp != NULL)
  2472.     (void) closedir(dirp);
  2473. data = -1;
  2474. pdata = -1;
  2475. goto globfree;
  2476.     }
  2477.     while ((dirname = *dirlist++) != NULL) {
  2478. if (stat(dirname, &st) < 0) {
  2479.     /* If user typed "ls -l", etc, and the client used NLST, do what
  2480.      * the user meant. */
  2481.     if (dirname[0] == '-' && *dirlist == NULL && transflag == 0) {
  2482. retrieve_is_data = 0;
  2483. #ifndef INTERNAL_LS
  2484. retrieve(ls_plain, dirname);
  2485. #else
  2486. ls(dirname, 1);
  2487. #endif
  2488. retrieve_is_data = 1;
  2489. goto globfree;
  2490.     }
  2491.     perror_reply(550, dirname);
  2492.     if (dout != NULL) {
  2493. (void) fclose(dout);
  2494. transflag = 0;
  2495. data = -1;
  2496. pdata = -1;
  2497.     }
  2498.     goto globfree;
  2499. }
  2500. if ((st.st_mode & S_IFMT) != S_IFDIR) {
  2501.     if (dout == NULL) {
  2502. dout = dataconn("file list", (off_t) - 1, "w");
  2503. if (dout == NULL)
  2504.     goto globfree;
  2505. transflag++;
  2506. draconian_FILE = dout;
  2507.     }
  2508.     if (draconian_FILE != NULL) {
  2509. (void) signal(SIGALRM, draconian_alarm_signal);
  2510. alarm(timeout_data);
  2511. fprintf(dout, "%s%sn", dirname,
  2512. type == TYPE_A ? "r" : "");
  2513.     }
  2514.     byte_count += strlen(dirname) + 1;
  2515. #ifdef TRANSFER_COUNT
  2516.     byte_count_total += strlen(dirname) + 1;
  2517.     byte_count_out += strlen(dirname) + 1;
  2518.     if (type == TYPE_A) {
  2519. byte_count_total++;
  2520. byte_count_out++;
  2521.     }
  2522. #endif
  2523. }
  2524.     }
  2525.     if (dout != NULL) {
  2526. if (draconian_FILE != NULL) {
  2527.     (void) signal(SIGALRM, draconian_alarm_signal);
  2528.     alarm(timeout_data);
  2529.     fflush(dout);
  2530. }
  2531. if (draconian_FILE != NULL) {
  2532.     (void) signal(SIGALRM, draconian_alarm_signal);
  2533.     alarm(timeout_data);
  2534.     socket_flush_wait(dout);
  2535. }
  2536.     }
  2537.     if (dout == NULL)
  2538. reply(550, "No files found.");
  2539.     else if ((draconian_FILE == NULL) || ferror(dout) != 0) {
  2540. alarm(0);
  2541. perror_reply(550, "Data connection");
  2542.     }
  2543.     else {
  2544. #ifdef TRANSFER_COUNT
  2545. xfer_count_total++;
  2546. xfer_count_out++;
  2547. #endif
  2548. alarm(0);
  2549. reply(226, "Transfer complete.");
  2550.     }
  2551.     transflag = 0;
  2552.     if ((dout != NULL) && (draconian_FILE != NULL))
  2553. (void) fclose(dout);
  2554.     data = -1;
  2555.     pdata = -1;
  2556.   globfree:
  2557.     if (wildcard != NULL) {
  2558. free(wildcard);
  2559. wildcard = NULL;
  2560.     }
  2561.     if (sdirlist) {
  2562. blkfree(sdirlist);
  2563. free((char *) sdirlist);
  2564.     }
  2565. }
  2566. /*
  2567.    **  SETPROCTITLE -- set process title for ps
  2568.    **
  2569.    **   Parameters:
  2570.    **           fmt -- a printf style format string.
  2571.    **           a, b, c -- possible parameters to fmt.
  2572.    **
  2573.    **   Returns:
  2574.    **           none.
  2575.    **
  2576.    **   Side Effects:
  2577.    **           Clobbers argv of our main procedure so ps(1) will
  2578.    **           display the title.
  2579.  */
  2580. #define SPT_NONE 0 /* don't use it at all */
  2581. #define SPT_REUSEARGV 1 /* cover argv with title information */
  2582. #define SPT_BUILTIN 2 /* use libc builtin */
  2583. #define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */
  2584. #define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */
  2585. #define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */
  2586. #define SPT_SCO 6 /* write kernel u. area */
  2587. #define SPT_CHANGEARGV 7 /* write our own strings into argv[] */
  2588. #define MAXLINE      2048 /* max line length for setproctitle */
  2589. #define SPACELEFT(buf, ptr)  (sizeof buf - ((ptr) - buf))
  2590. #ifndef SPT_TYPE
  2591. #define SPT_TYPE SPT_REUSEARGV
  2592. #endif
  2593. #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
  2594. #if SPT_TYPE == SPT_PSTAT
  2595. #include <sys/pstat.h>
  2596. #endif
  2597. #if SPT_TYPE == SPT_PSSTRINGS
  2598. #include <machine/vmparam.h>
  2599. #include <sys/exec.h>
  2600. #ifndef PS_STRINGS /* hmmmm....  apparently not available after all */
  2601. #undef SPT_TYPE
  2602. #define SPT_TYPE SPT_REUSEARGV
  2603. #else
  2604. #ifndef NKPDE /* FreeBSD 2.0 */
  2605. #define NKPDE 63
  2606. typedef unsigned int *pt_entry_t;
  2607. #endif
  2608. #endif
  2609. #endif
  2610. #if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV
  2611. #define SETPROC_STATIC static
  2612. #else
  2613. #define SETPROC_STATIC
  2614. #endif
  2615. #if SPT_TYPE == SPT_SYSMIPS
  2616. #include <sys/sysmips.h>
  2617. #include <sys/sysnews.h>
  2618. #endif
  2619. #if SPT_TYPE == SPT_SCO
  2620. #ifdef UNIXWARE
  2621. #include <sys/exec.h>
  2622. #include <sys/ksym.h>
  2623. #include <sys/proc.h>
  2624. #include <sys/user.h>
  2625. #else /* UNIXWARE */
  2626. #include <sys/immu.h>
  2627. #include <sys/dir.h>
  2628. #include <sys/user.h>
  2629. #include <sys/fs/s5param.h>
  2630. #endif /* UNIXWARE */
  2631. #if PSARGSZ > MAXLINE
  2632. #define SPT_BUFSIZE PSARGSZ
  2633. #endif
  2634. #ifndef _PATH_KMEM
  2635. #define _PATH_KMEM "/dev/kmem"
  2636. #endif /* _PATH_KMEM */
  2637. #endif /* SPT_SCO */
  2638. #ifndef SPT_PADCHAR
  2639. #define SPT_PADCHAR ' '
  2640. #endif
  2641. #ifndef SPT_BUFSIZE
  2642. #define SPT_BUFSIZE MAXLINE
  2643. #endif
  2644. #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
  2645. #if SPT_TYPE == SPT_REUSEARGV || SPT_TYPE == SPT_CHANGEARGV
  2646. char **Argv = NULL; /* pointer to argument vector */
  2647. #endif
  2648. #if SPT_TYPE == SPT_REUSEARGV
  2649. char *LastArgv = NULL; /* end of argv */
  2650. #endif
  2651. /*
  2652.    **  Pointers for setproctitle.
  2653.    **   This allows "ps" listings to give more useful information.
  2654.  */
  2655. void initsetproctitle(argc, argv, envp)
  2656.      int argc;
  2657.      char **argv;
  2658.      char **envp;
  2659. {
  2660. #if SPT_TYPE == SPT_REUSEARGV
  2661.     register int i, envpsize = 0;
  2662.     char **newenviron;
  2663.     extern char **environ;
  2664.     /*
  2665.        **  Save start and extent of argv for setproctitle.
  2666.      */
  2667.     LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
  2668.     if (envp != NULL) {
  2669. /*
  2670.    **  Move the environment so setproctitle can use the space at
  2671.    **  the top of memory.
  2672.  */
  2673. for (i = 0; envp[i] != NULL; i++)
  2674.     envpsize += strlen(envp[i]) + 1;
  2675. newenviron = (char **) malloc(sizeof(char *) * (i + 1));
  2676. if (newenviron) {
  2677.     int err = 0;
  2678.     for (i = 0; envp[i] != NULL; i++) {
  2679. if ((newenviron[i] = strdup(envp[i])) == NULL) {
  2680.     err = 1;
  2681.     break;
  2682. }
  2683.     }
  2684.     if (err) {
  2685. for (i = 0; newenviron[i] != NULL; i++)
  2686.     free(newenviron[i]);
  2687. free(newenviron);
  2688. i = 0;
  2689.     }
  2690.     else {
  2691. newenviron[i] = NULL;
  2692. environ = newenviron;
  2693.     }
  2694. }
  2695. else {
  2696.     i = 0;
  2697. }
  2698. /*
  2699.    **  Find the last environment variable within wu-ftpd's
  2700.    **  process memory area.
  2701.  */
  2702. while (i > 0 && (envp[i - 1] < argv[0] ||
  2703.     envp[i - 1] > (argv[argc - 1] + strlen(argv[argc - 1]) +
  2704.    1 + envpsize)))
  2705.     i--;
  2706. if (i > 0)
  2707.     LastArgv = envp[i - 1] + strlen(envp[i - 1]);
  2708.     }
  2709. #endif /* SPT_TYPE == SPT_REUSEARGV */
  2710. #if SPT_TYPE == SPT_REUSEARGV || SPT_TYPE == SPT_CHANGEARGV
  2711.     Argv = argv;
  2712. #endif
  2713. }
  2714. #if SPT_TYPE != SPT_BUILTIN
  2715. /*VARARGS1 */
  2716. void setproctitle(const char *fmt,...)
  2717. {
  2718. #if SPT_TYPE != SPT_NONE
  2719.     register char *p;
  2720.     register int i;
  2721.     SETPROC_STATIC char buf[SPT_BUFSIZE];
  2722.     VA_LOCAL_DECL
  2723. #if SPT_TYPE == SPT_PSTAT
  2724. union pstun pst;
  2725. #endif
  2726. #if SPT_TYPE == SPT_SCO
  2727.     static off_t seek_off;
  2728.     static int kmemfd = -1;
  2729.     static int kmempid = -1;
  2730. #ifdef UNIXWARE
  2731.     off_t offset;
  2732.     void *ptr;
  2733.     struct mioc_rksym rks;
  2734. #endif /* UNIXWARE */
  2735. #endif /* SPT_SCO */
  2736.     p = buf;
  2737.     /* print ftpd: heading for grep */
  2738.     (void) strcpy(p, "ftpd: ");
  2739.     p += strlen(p);
  2740.     /* print the argument string */
  2741.     VA_START(fmt);
  2742.     (void) vsnprintf(p, SPACELEFT(buf, p), fmt, ap);
  2743.     VA_END;
  2744.     i = strlen(buf);
  2745. #if SPT_TYPE == SPT_PSTAT
  2746.     pst.pst_command = buf;
  2747.     pstat(PSTAT_SETCMD, pst, i, 0, 0);
  2748. #endif
  2749. #if SPT_TYPE == SPT_PSSTRINGS
  2750.     PS_STRINGS->ps_nargvstr = 1;
  2751.     PS_STRINGS->ps_argvstr = buf;
  2752. #endif
  2753. #if SPT_TYPE == SPT_SYSMIPS
  2754.     sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf);
  2755. #endif
  2756. #if SPT_TYPE == SPT_SCO
  2757.     if (kmemfd < 0 || kmempid != getpid()) {
  2758. if (kmemfd >= 0)
  2759.     close(kmemfd);
  2760. if ((kmemfd = open(_PATH_KMEM, O_RDWR, 0)) < 0)
  2761.     return;
  2762. (void) fcntl(kmemfd, F_SETFD, 1);
  2763. kmempid = getpid();
  2764. #ifdef UNIXWARE
  2765. seek_off = 0;
  2766. rks.mirk_symname = "upointer";
  2767. rks.mirk_buf = &ptr;
  2768. rks.mirk_buflen = sizeof(ptr);
  2769. if (ioctl(kmemfd, MIOC_READKSYM, &rks) < 0)
  2770.     return;
  2771. offset = (off_t) ptr + (off_t) & ((struct user *) 0)->u_procp;
  2772. if (lseek(kmemfd, offset, SEEK_SET) != offset)
  2773.     return;
  2774. if (read(kmemfd, &ptr, sizeof(ptr)) != sizeof(ptr))
  2775.     return;
  2776. offset = (off_t) ptr + (off_t) & ((struct proc *) 0)->p_execinfo;
  2777. if (lseek(kmemfd, offset, SEEK_SET) != offset)
  2778.     return;
  2779. if (read(kmemfd, &ptr, sizeof(ptr)) != sizeof(ptr))
  2780.     return;
  2781. seek_off = (off_t) ptr + (off_t) ((struct execinfo *) 0)->ei_psargs;
  2782. #else /* UNIXWARE */
  2783. seek_off = UVUBLK + (off_t) & ((struct user *) 0)->u_psargs;
  2784. #endif /* UNIXWARE */
  2785.     }
  2786. #ifdef UNIXWARE
  2787.     if (seek_off == 0)
  2788. return;
  2789. #endif /* UNIXWARE */
  2790.     buf[PSARGSZ - 1] = '';
  2791.     if (lseek(kmemfd, (off_t) seek_off, SEEK_SET) == seek_off)
  2792. (void) write(kmemfd, buf, PSARGSZ);
  2793. #endif /* SPT_SCO */
  2794. #if SPT_TYPE == SPT_REUSEARGV
  2795.     if (i > LastArgv - Argv[0] - 2) {
  2796. i = LastArgv - Argv[0] - 2;
  2797. buf[i] = '';
  2798.     }
  2799.     (void) strcpy(Argv[0], buf);
  2800.     p = &Argv[0][i];
  2801.     while (p < LastArgv)
  2802. *p++ = SPT_PADCHAR;
  2803.     Argv[1] = NULL;
  2804. #endif
  2805. #if SPT_TYPE == SPT_CHANGEARGV
  2806.     Argv[0] = buf;
  2807.     Argv[1] = 0;
  2808. #endif
  2809. #endif /* SPT_TYPE != SPT_NONE */
  2810. }
  2811. #endif /* SPT_TYPE != SPT_BUILTIN */
  2812. #ifdef KERBEROS
  2813. /* thanks to gshapiro@wpi.wpi.edu for the following kerberosities */
  2814. void init_krb()
  2815. {
  2816.     char hostname[100];
  2817. #ifdef HAVE_SYSINFO
  2818.     if (sysinfo(SI_HOSTNAME, hostname, sizeof(hostname)) < 0) {
  2819. perror("sysinfo");
  2820. #else
  2821.     if (gethostname(hostname, sizeof(hostname)) < 0) {
  2822. perror("gethostname");
  2823. #endif
  2824. exit(1);
  2825.     }
  2826.     if (strchr(hostname, '.'))
  2827. *(strchr(hostname, '.')) = 0;
  2828.     sprintf(krb_ticket_name, "/var/dss/kerberos/tkt/tkt.%d", getpid());
  2829.     krb_set_tkt_string(krb_ticket_name);
  2830.     config_auth();
  2831.     if (krb_svc_init("hesiod", hostname, (char *) NULL, 0, (char *) NULL,
  2832.      (char *) NULL) != KSUCCESS) {
  2833. fprintf(stderr, "Couldn't initialize Kerberosn");
  2834. exit(1);
  2835.     }
  2836. }
  2837. void end_krb()
  2838. {
  2839.     unlink(krb_ticket_name);
  2840. }
  2841. #endif /* KERBEROS */
  2842. #ifdef ULTRIX_AUTH
  2843. static int ultrix_check_pass(char *passwd, char *xpasswd)
  2844. {
  2845.     struct svcinfo *svp;
  2846.     int auth_status;
  2847.     if ((svp = getsvc()) == (struct svcinfo *) NULL) {
  2848. syslog(LOG_WARNING, "getsvc() failed in ultrix_check_pass");
  2849. return -1;
  2850.     }
  2851.     if (pw == (struct passwd *) NULL) {
  2852. return -1;
  2853.     }
  2854.     if (((svp->svcauth.seclevel == SEC_UPGRADE) &&
  2855.  (!strcmp(pw->pw_passwd, "*")))
  2856. || (svp->svcauth.seclevel == SEC_ENHANCED)) {
  2857. if ((auth_status = authenticate_user(pw, passwd, "/dev/ttypXX")) >= 0) {
  2858.     /* Indicate successful validation */
  2859.     return auth_status;
  2860. }
  2861. if (auth_status < 0 && errno == EPERM) {
  2862.     /* Log some information about the failed login attempt. */
  2863.     switch (abs(auth_status)) {
  2864.     case A_EBADPASS:
  2865. break;
  2866.     case A_ESOFTEXP:
  2867. syslog(LOG_NOTICE, "password will expire soon for user %s",
  2868.        pw->pw_name);
  2869. break;
  2870.     case A_EHARDEXP:
  2871. syslog(LOG_NOTICE, "password has expired for user %s",
  2872.        pw->pw_name);
  2873. break;
  2874.     case A_ENOLOGIN:
  2875. syslog(LOG_NOTICE, "user %s attempted login to disabled acct",
  2876.        pw->pw_name);
  2877. break;
  2878.     }
  2879. }
  2880.     }
  2881.     else {
  2882. if ((*pw->pw_passwd != '') && (!strcmp(xpasswd, pw->pw_passwd))) {
  2883.     /* passwd in /etc/passwd isn't empty && encrypted passwd matches */
  2884.     return 0;
  2885. }
  2886.     }
  2887.     return -1;
  2888. }
  2889. #endif /* ULTRIX_AUTH */
  2890. #ifdef USE_PAM
  2891. /* This is rather an abuse of PAM, but the FTP protocol doesn't allow much
  2892.  * flexibility here.  :-(
  2893.  */
  2894. #include <security/pam_appl.h>
  2895. /* Static variables used to communicate between the conversation function
  2896.  * and the server_login function
  2897.  */
  2898. static char *PAM_password;
  2899. /* PAM conversation function
  2900.  * Here we assume (for now, at least) that echo on means login name, and
  2901.  * echo off means password.
  2902.  */
  2903. static int PAM_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
  2904. {
  2905.     int replies = 0;
  2906.     struct pam_response *reply = NULL;
  2907. #define COPY_STRING(s) (s) ? strdup(s) : NULL
  2908.     reply = malloc(sizeof(struct pam_response) * num_msg);
  2909.     if (!reply)
  2910. return PAM_CONV_ERR;
  2911.     for (replies = 0; replies < num_msg; replies++) {
  2912. switch (msg[replies]->msg_style) {
  2913. case PAM_PROMPT_ECHO_ON:
  2914.     return PAM_CONV_ERR;
  2915.     break;
  2916. case PAM_PROMPT_ECHO_OFF:
  2917.     reply[replies].resp_retcode = PAM_SUCCESS;
  2918.     reply[replies].resp = COPY_STRING(PAM_password);
  2919.     /* PAM frees resp */
  2920.     break;
  2921. case PAM_TEXT_INFO:
  2922.     /* ignore it... */
  2923.     reply[replies].resp_retcode = PAM_SUCCESS;
  2924.     reply[replies].resp = NULL;
  2925.     break;
  2926. case PAM_ERROR_MSG:
  2927.     /* ignore it... */
  2928.     reply[replies].resp_retcode = PAM_SUCCESS;
  2929.     reply[replies].resp = NULL;
  2930.     break;
  2931. default:
  2932.     /* Must be an error of some sort... */
  2933.     return PAM_CONV_ERR;
  2934. }
  2935.     }
  2936.     *resp = reply;
  2937.     return PAM_SUCCESS;
  2938. }
  2939. static struct pam_conv PAM_conversation =
  2940. {
  2941.     &PAM_conv,
  2942.     NULL
  2943. };
  2944. static int pam_check_pass(char *user, char *passwd)
  2945. {
  2946.     pam_handle_t *pamh;
  2947.     int pam_error;
  2948.     /* Now use PAM to do authentication.  For now, we won't worry about
  2949.      * session logging, only authentication.  Bail out if there are any
  2950.      * errors.  Since this is a limited protocol, and an even more limited
  2951.      * function within a server speaking this protocol, we can't be as
  2952.      * verbose as would otherwise make sense.
  2953.      */
  2954. #define PAM_BAIL if (pam_error != PAM_SUCCESS) { pam_end(pamh, 0); return 0; }
  2955.     PAM_password = passwd;
  2956.     pam_error = pam_start("ftp", user, &PAM_conversation, &pamh);
  2957.     pam_set_item(pamh, PAM_RHOST, remotehost);
  2958.     PAM_BAIL;
  2959.     pam_error = pam_authenticate(pamh, 0);
  2960.     PAM_BAIL;
  2961.     pam_error = pam_acct_mgmt(pamh, 0);
  2962.     PAM_BAIL;
  2963. #ifdef PAM_ESTABLISH_CRED
  2964.     pam_error = pam_setcred(pamh, PAM_ESTABLISH_CRED);
  2965. #else
  2966.     pam_error = pam_setcred(pamh, PAM_CRED_ESTABLISH);
  2967. #endif
  2968.     PAM_BAIL;
  2969.     pam_end(pamh, PAM_SUCCESS);
  2970.     /* If this point is reached, the user has been authenticated. */
  2971.     return 1;
  2972. }
  2973. #endif
  2974. #ifdef DAEMON
  2975. static unsigned long int acl_DaemonAddress(void)
  2976. {
  2977.     unsigned long int rv = INADDR_ANY;
  2978.     struct aclmember *entry = NULL;
  2979.     if (getaclentry("daemonaddress", &entry) && ARG0) {
  2980. rv = inet_addr(ARG0);
  2981. if (rv == -1)
  2982.     rv = INADDR_ANY;
  2983.     }
  2984.     return rv;
  2985. }
  2986. /* I am running as a standalone daemon (not under inetd) */
  2987. void do_daemon(int argc, char **argv, char **envp)
  2988. {
  2989.     struct sockaddr_in server;
  2990.     struct servent *serv;
  2991.     int pgrp;
  2992.     int lsock;
  2993.     int one = 1;
  2994.     FILE *pidfile;
  2995.     int i;
  2996.     /* Some of this is "borrowed" from inn - lots of it isn't */
  2997.     if (be_daemon == 2) {
  2998. /* Fork - so I'm not the owner of the process group any more */
  2999. i = fork();
  3000. if (i < 0) {
  3001.     syslog(LOG_ERR, "cant fork %m");
  3002.     exit(1);
  3003. }
  3004. /* No need for the parent any more */
  3005. if (i > 0)
  3006.     exit(0);
  3007. #ifdef NO_SETSID
  3008. pgrp = setpgrp(0, getpid());
  3009. #else
  3010. pgrp = setsid();
  3011. #endif
  3012. if (pgrp < 0) {
  3013.     syslog(LOG_ERR, "cannot daemonise: %m");
  3014.     exit(1);
  3015. }
  3016.     }
  3017.     if (!Bypass_PID_Files)
  3018. if ((pidfile = fopen(_PATH_FTPD_PID, "w"))) {
  3019.     fprintf(pidfile, "%ldn", (long) getpid());
  3020.     fclose(pidfile);
  3021. }
  3022. else {
  3023.     syslog(LOG_ERR, "Cannot write pidfile: %m");
  3024. }
  3025.     /* Close off all file descriptors and reopen syslog */
  3026.     if (be_daemon == 2) {
  3027. int i, fds;
  3028. #ifdef HAVE_GETRLIMIT
  3029. struct rlimit rlp;
  3030. rlp.rlim_cur = rlp.rlim_max = RLIM_INFINITY;
  3031. if (getrlimit(RLIMIT_NOFILE, &rlp))
  3032.     return;
  3033. fds = rlp.rlim_cur;
  3034. #else
  3035. #ifdef HAVE_GETDTABLESIZE
  3036. if ((fds = getdtablesize()) <= 0)
  3037.     return;
  3038. #else
  3039. #ifdef OPEN_MAX
  3040. fds = OPEN_MAX; /* need to include limits.h somehow */
  3041. #else
  3042. fds = sizeof(long); /* XXX -- magic */
  3043. #endif
  3044. #endif
  3045. #endif
  3046. closelog();
  3047. for (i = 0; i <= fds; i++) {
  3048.     close(i);
  3049. }
  3050. #ifdef FACILITY
  3051. openlog("ftpd", LOG_PID | LOG_NDELAY, FACILITY);
  3052. #else
  3053. openlog("ftpd", LOG_PID);
  3054. #endif
  3055. /* junk stderr */
  3056. (void) freopen(_PATH_DEVNULL, "w", stderr);
  3057.     }
  3058.     if (RootDirectory != NULL) {
  3059. if ((chroot(RootDirectory) < 0)
  3060.     || (chdir("/") < 0)) {
  3061.     syslog(LOG_ERR, "Cannot chroot to initial directory, aborting.");
  3062.     exit(1);
  3063. }
  3064. free(RootDirectory);
  3065. RootDirectory = NULL;
  3066.     }
  3067.     if (!use_accessfile)
  3068. syslog(LOG_WARNING, "FTP server started without ftpaccess file");
  3069.     syslog(LOG_INFO, "FTP server (%s) ready.", version);
  3070.     /* Create a socket to listen on */
  3071.     lsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  3072.     if (lsock < 0) {
  3073. syslog(LOG_ERR, "Cannot create socket to listen on: %m");
  3074. exit(1);
  3075.     }
  3076.     if (setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) < 0) {
  3077. syslog(LOG_ERR, "Cannot set SO_REUSEADDR option: %m");
  3078. exit(1);
  3079.     }
  3080.     if (keepalive)
  3081. (void) setsockopt(lsock, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one));
  3082.     server.sin_family = AF_INET;
  3083.     server.sin_addr.s_addr = acl_DaemonAddress();
  3084.     if (daemon_port == 0) {
  3085. if (!(serv = getservbyname("ftp", "tcp"))) {
  3086.     syslog(LOG_ERR, "Cannot find service ftp: %m");
  3087.     exit(1);
  3088. }
  3089. server.sin_port = serv->s_port;
  3090. daemon_port = ntohs(serv->s_port);
  3091.     }
  3092.     else
  3093. server.sin_port = htons(daemon_port);
  3094.     if (bind(lsock, (struct sockaddr *) &server, sizeof(server)) < 0) {
  3095. syslog(LOG_ERR, "Cannot bind socket: %m");
  3096. exit(1);
  3097.     }
  3098.     listen(lsock, MAX_BACKLOG);
  3099.     sprintf(proctitle, "accepting connections on port %i", daemon_port);
  3100.     setproctitle("%s", proctitle);
  3101.     while (1) {
  3102. int pid;
  3103. int msgsock;
  3104. msgsock = accept(lsock, 0, 0);
  3105. if (msgsock < 0) {
  3106.     syslog(LOG_ERR, "Accept failed: %m");
  3107.     sleep(1);
  3108.     continue;
  3109. }
  3110. if (keepalive)
  3111.     (void) setsockopt(msgsock, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one));
  3112. /* Fork off a handler */
  3113. pid = fork();
  3114. if (pid < 0) {
  3115.     syslog(LOG_ERR, "failed to fork: %m");
  3116.     sleep(1);
  3117.     continue;
  3118. }
  3119. if (pid == 0) {
  3120.     /* I am that forked off child */
  3121.     closelog();
  3122.     /* Make sure that stdin/stdout are the new socket */
  3123.     dup2(msgsock, 0);
  3124.     dup2(msgsock, 1);
  3125.     /* Only parent needs lsock */
  3126.     if (lsock != 0 && lsock != 1)
  3127. close(lsock);
  3128. #ifdef FACILITY
  3129.     openlog("ftpd", LOG_PID | LOG_NDELAY, FACILITY);
  3130. #else
  3131.     openlog("ftpd", LOG_PID);
  3132. #endif
  3133.     return;
  3134. }
  3135. /* I am the parent */
  3136. close(msgsock);
  3137. /* Quick check to see if any of the forked off children have
  3138.  * terminated. */
  3139. while ((pid = waitpid((pid_t) -1, (int *) 0, WNOHANG)) > 0) {
  3140.     /* A child has finished */
  3141. }
  3142.     }
  3143. }
  3144. #endif /* DAEMON */
  3145. int pasv_allowed(char *remoteaddr)
  3146. {
  3147.     char class[MAXPATHLEN];
  3148.     int which;
  3149.     struct aclmember *entry = NULL;
  3150.     (void) acl_getclass(class);
  3151.     while (getaclentry("pasv-allow", &entry)) {
  3152. if ((ARG0 != NULL) && (strcasecmp(class, ARG0) == 0))
  3153.     for (which = 1; (which < MAXARGS) && (ARG[which] != NULL); which++) {
  3154. if (hostmatch(ARG[which], remoteaddr, NULL))
  3155.     return 1;
  3156.     }
  3157.     }
  3158.     return 0;
  3159. }
  3160. int port_allowed(char *remoteaddr)
  3161. {
  3162.     char class[MAXPATHLEN];
  3163.     int which;
  3164.     struct aclmember *entry = NULL;
  3165.     (void) acl_getclass(class);
  3166.     while (getaclentry("pasv-allow", &entry)) {
  3167. if ((ARG0 != NULL) && (strcasecmp(class, ARG0) == 0))
  3168.     for (which = 1; (which < MAXARGS) && (ARG[which] != NULL); which++) {
  3169. if (hostmatch(ARG[which], remoteaddr, NULL))
  3170.     return 1;
  3171.     }
  3172.     }
  3173.     return 0;
  3174. }
  3175. #ifdef MAIL_ADMIN
  3176. char *email(char *full_address)
  3177. {
  3178.     /* Get the plain address part from an e-mail address
  3179.        (i.e. remove realname) */
  3180.     char *addr;
  3181.     addr = (char *) malloc(strlen(full_address) + 1);
  3182.     memset(addr, 0, strlen(full_address) + 1);
  3183.     strcpy(addr, full_address);
  3184.     /* Realname <user@host> type address */
  3185.     if (((char *) strchr(addr, '<')) != NULL) {
  3186. addr = (char *) strchr(addr, '<') + 1;
  3187. addr[strchr(addr, '>') - addr] = '';
  3188.     }
  3189.     /* user@host (Realname) type address */
  3190.     if (((char *) strchr(addr, ' ')) != NULL)
  3191. addr[strchr(addr, ' ') - addr] = '';
  3192.     return addr;
  3193. }
  3194. FILE *SockOpen(char *host, int clientPort)
  3195. {
  3196.     int sock;
  3197.     unsigned long inaddr;
  3198.     struct sockaddr_in ad;
  3199.     struct hostent *hp;
  3200.     FILE *fp;
  3201.     memset(&ad, 0, sizeof(ad));
  3202.     ad.sin_family = AF_INET;
  3203.     inaddr = inet_addr(host);
  3204.     if (inaddr != (unsigned long) -1)
  3205. memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));
  3206.     else {
  3207. hp = gethostbyname(host);
  3208. if (hp == NULL)
  3209.     return (FILE *) NULL;
  3210. memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);
  3211.     }
  3212.     ad.sin_port = htons(clientPort);
  3213.     sock = socket(AF_INET, SOCK_STREAM, 0);
  3214.     if (sock < 0)
  3215. return (FILE *) NULL;
  3216.     if (connect(sock, (struct sockaddr *) &ad, sizeof(ad)) < 0) {
  3217. close(sock);
  3218. return (FILE *) NULL;
  3219.     }
  3220.     fp = fdopen(sock, "r+");
  3221.     setvbuf(fp, NULL, _IOLBF, 2048);
  3222.     return (fp);
  3223. }
  3224. int SockPrintf(FILE *sockfp, char *format,...)
  3225. {
  3226.     va_list ap;
  3227.     char buf[32768];
  3228.     va_start(ap, format);
  3229.     vsprintf(buf, format, ap);
  3230.     va_end(ap);
  3231.     return SockWrite(buf, 1, strlen(buf), sockfp);
  3232. }
  3233. int SockWrite(char *buf, int size, int len, FILE *sockfp)
  3234. {
  3235.     return (fwrite(buf, size, len, sockfp));
  3236. }
  3237. char *SockGets(FILE *sockfp, char *buf, int len)
  3238. {
  3239.     return (fgets(buf, len, sockfp));
  3240. }
  3241. int SockPuts(FILE *sockfp, char *buf)
  3242. {
  3243.     int rc;
  3244.     if ((rc = SockWrite(buf, 1, strlen(buf), sockfp)))
  3245. return rc;
  3246.     return SockWrite("rn", 1, 2, sockfp);
  3247. }
  3248. int Reply(FILE *sockfp)
  3249. {
  3250.     char *reply, *rec, *separator;
  3251.     int ret = 0;
  3252.     reply = (char *) malloc(1024);
  3253.     memset(reply, 0, 1024);
  3254.     do {
  3255. rec = SockGets(sockfp, reply, 1024);
  3256. if (rec != NULL) {
  3257.     ret = strtol(reply, &separator, 10);
  3258. }
  3259. else
  3260.     ret = 250;
  3261.     } while ((rec != NULL) && (separator[0] != ' '));
  3262.     return ret;
  3263. }
  3264. int Send(FILE *sockfp, char *format,...)
  3265. {
  3266.     va_list ap;
  3267.     char buf[32728];
  3268.     va_start(ap, format);
  3269.     vsprintf(buf, format, ap);
  3270.     va_end(ap);
  3271.     SockWrite(buf, 1, strlen(buf), sockfp);
  3272.     return Reply(sockfp);
  3273. }
  3274. #endif /* MAIL_ADMIN */
  3275. /*
  3276.  * fixpath
  3277.  *
  3278.  * In principal, this is similar to realpath() or the mapping chdir function.
  3279.  * It removes unnecessary path components.  We do this to put a stop to
  3280.  * attempts to cause a memory starvation DoS.
  3281.  *
  3282.  */
  3283. void fixpath(char *path)
  3284. {
  3285.     int abs = 0;
  3286.     char *in;
  3287.     char *out;
  3288.     if (*path == '/') {
  3289. abs = 1;
  3290. path++;
  3291.     }
  3292.     else if (*path == '~') {
  3293. do
  3294.     path++;
  3295. while ((*path != '') && (*path != '/'));
  3296. if (*path == '/')
  3297.     path++;
  3298.     }
  3299.     in = path;
  3300.     out = path;
  3301.     while (*in != '') {
  3302. if (*in == '/')
  3303.     in++;
  3304. else if ((in[0] == '.') && ((in[1] == '/') || (in[1] == ''))) {
  3305.     in++;
  3306.     if (*in == '/')
  3307. in++;
  3308. }
  3309. else if ((in[0] == '.') && (in[1] == '.') && ((in[2] == '/') || (in[2] == ''))) {
  3310.     if (out == path) {
  3311. if (abs) {
  3312.     in++;
  3313.     in++;
  3314.     if (*in == '/')
  3315. in++;
  3316. }
  3317. else {
  3318.     *out++ = *in++;
  3319.     *out++ = *in++;
  3320.     if (*in == '/')
  3321. *out++ = *in++;
  3322.     path = out;
  3323. }
  3324.     }
  3325.     else {
  3326. out--;
  3327. while ((out != path) && (*--out != '/'));
  3328. in++;
  3329. in++;
  3330. if (*in == '/')
  3331.     in++;
  3332.     }
  3333. }
  3334. else {
  3335.     do
  3336. *out++ = *in++;
  3337.     while ((*in != '') && (*in != '/'));
  3338.     if (*in == '/')
  3339. *out++ = *in++;
  3340. }
  3341.     }
  3342.     *out = '';
  3343. }