Advertisement
parkdream1

pure-ftpd

Mar 28th, 2012
232
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 27.30 KB | None | 0 0
  1. pure-ftpd-1.0.29/src/ftp_parserc.c
  2. #include <config.h>
  3.  
  4. #include "ftpd.h"
  5. #include "dynamic.h"
  6. #include "ftpwho-update.h"
  7. #include "globals.h"
  8. #include "messages.h"
  9. #ifdef WITH_DIRALIASES
  10. # include "diraliases.h"
  11. #endif
  12. #ifdef WITH_TLS
  13. # include "tls.h"
  14. #endif
  15.  
  16. #ifdef WITH_DMALLOC
  17. # include <dmalloc.h>
  18. #endif
  19.  
  20. static void antiidle(void)
  21. {
  22.     if (noopidle == (time_t) -1) {
  23.         noopidle = time(NULL);
  24.     } else {
  25.         if ((time(NULL) - noopidle) > (time_t) idletime_noop) {
  26.             die(421, LOG_INFO, MSG_TIMEOUT_NOOP, (unsigned long) idletime_noop);
  27.         }
  28.     }    
  29. }
  30.  
  31. /*
  32.  * Introduce a random delay, to avoid guessing existing user names by
  33.  * mesuring delay. It's especially true when LDAP is used.
  34.  * No need to call usleep2() because we are root at this point.
  35.  */
  36.  
  37. static void randomdelay(void)
  38. {
  39.     usleep(rand() % 15000UL);          /* dummy... no need for arc4 */
  40. }
  41.  
  42. /*
  43.  * Simple but fast command-line reader. We break the FTP protocol here,
  44.  * because we deny access to files with strange characters in their name.
  45.  * Now, I seriously doubt that clients should be allowed to upload files
  46.  * with carriage returns, bells, cursor moves and other fancy stuff in the
  47.  * names. It can indirectly lead to security flaws with scripts, it's
  48.  * annoying for the sysadmin, it can be a client error, it can bring unexpected
  49.  * results on some filesystems, etc. So control chars are replaced by "_".
  50.  * Better be safe than 100% RFC crap compliant but unsafe. If you really want
  51.  * RFC compliance, define RFC_CONFORMANT_PARSER. But I will hate you.
  52.  *
  53.  * RFC_CONFORMANT_LINES is another thing that clients should implement
  54.  * properly (and it's trivial to do) : lines must be ended with \r\n .
  55.  * Guess what ?
  56.  * Some broken clients are just sending \n ... Grrrrrrrrrrrr !!!!!!!!!!!!!!!
  57.  *
  58.  * -Frank.
  59.  */
  60.  
  61. int sfgets(void)
  62. {
  63.     struct pollfd pfd;
  64.     int pollret;
  65.     ssize_t readnb;
  66.     signed char seen_r = 0;
  67.     static size_t scanned;
  68.     static size_t readnbd;
  69.    
  70.     if (scanned > (size_t) 0U) {       /* support pipelining */
  71.         readnbd -= scanned;        
  72.         memmove(cmd, cmd + scanned, readnbd);   /* safe */
  73.         scanned = (size_t) 0U;
  74.     }
  75.     pfd.fd = clientfd;
  76. #ifdef __APPLE_CC__
  77.     pfd.events = POLLIN | POLLERR | POLLHUP;
  78. #else
  79.     pfd.events = POLLIN | POLLPRI | POLLERR | POLLHUP;
  80. #endif
  81.     while (scanned < cmdsize) {
  82.         if (scanned >= readnbd) {      /* nothing left in the buffer */
  83.             pfd.revents = 0;
  84.             while ((pollret = poll(&pfd, 1U, idletime * 1000UL)) < 0 &&
  85.                    errno == EINTR);
  86.             if (pollret == 0) {
  87.                 return -1;
  88.             }
  89.             if (pollret <= 0 ||
  90.                 (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) != 0) {
  91.                 return -2;
  92.             }
  93.             if ((pfd.revents & (POLLIN | POLLPRI)) == 0) {
  94.                 continue;
  95.             }
  96.             if (readnbd >= cmdsize) {
  97.                 break;
  98.             }
  99. #ifdef WITH_TLS
  100.             if (tls_cnx != NULL) {
  101.                 while ((readnb = SSL_read
  102.                         (tls_cnx, cmd + readnbd, cmdsize - readnbd))
  103.                        < (ssize_t) 0 && errno == EINTR);
  104.             } else
  105. #endif
  106.             {
  107.                 while ((readnb = read(clientfd, cmd + readnbd,
  108.                                       cmdsize - readnbd)) < (ssize_t) 0 &&
  109.                        errno == EINTR);
  110.             }
  111.             if (readnb <= (ssize_t) 0) {
  112.                 return -2;
  113.             }
  114.             readnbd += readnb;
  115.             if (readnbd > cmdsize) {
  116.                 return -2;
  117.             }
  118.         }
  119. #ifdef RFC_CONFORMANT_LINES
  120.         if (seen_r != 0) {
  121. #endif
  122.             if (cmd[scanned] == '\n') {
  123. #ifndef RFC_CONFORMANT_LINES
  124.                 if (seen_r != 0) {
  125. #endif
  126.                     cmd[scanned - 1U] = 0;
  127. #ifndef RFC_CONFORMANT_LINES
  128.                 } else {
  129.                     cmd[scanned] = 0;
  130.                 }
  131. #endif
  132.                 if (++scanned >= readnbd) {   /* non-pipelined command */
  133.                     scanned = readnbd = (size_t) 0U;
  134.                 }
  135.                 return 0;
  136.             }
  137.             seen_r = 0;
  138. #ifdef RFC_CONFORMANT_LINES
  139.         }
  140. #endif
  141.         if (ISCTRLCODE(cmd[scanned])) {
  142.             if (cmd[scanned] == '\r') {
  143.                 seen_r = 1;
  144.             }
  145. #ifdef RFC_CONFORMANT_PARSER                   /* disabled by default, intentionnaly */
  146.             else if (cmd[scanned] == 0) {
  147.                 cmd[scanned] = '\n';
  148.             }
  149. #else
  150.             /* replace control chars with _ */
  151.             cmd[scanned] = '_';                
  152. #endif
  153.         }
  154.         scanned++;
  155.     }
  156.     die(421, LOG_WARNING, MSG_LINE_TOO_LONG);   /* don't remove this */
  157.    
  158.     return 0;                         /* to please GCC */
  159. }
  160.  
  161. /* Replace extra spaces before and after a string with '_' */
  162.  
  163. #ifdef MINIMAL
  164. # define revealextraspc(X) (X)
  165. #else
  166. static char *revealextraspc(char * const s_)
  167. {
  168.     unsigned char *s = (unsigned char *) s_;
  169.     unsigned char *sn;
  170.    
  171.     if (s == NULL) {
  172.         return s_;
  173.     }
  174.     simplify(s_);
  175.     while (*s != 0U && isspace(*s)) {
  176.         *s++ = '_';
  177.     }
  178.     if (*s == 0U) {
  179.         return s_;
  180.     }
  181.     sn = s;
  182.     do {
  183.         sn++;
  184.     } while (*sn != 0U);
  185.     do {
  186.         sn--;        
  187.         if (!isspace(*sn)) {
  188.             break;
  189.         }
  190.         *sn = '_';
  191.     } while (sn != s);
  192.    
  193.     return s_;
  194. }
  195. #endif
  196.  
  197. #ifdef WITH_RFC2640
  198. char *charset_client2fs(const char * const string)
  199. {
  200.     char *output = NULL, *output_;
  201.     size_t inlen, outlen, outlen_;
  202.    
  203.     inlen = strlen(string);
  204.     outlen_ = outlen = inlen * (size_t) 4U + (size_t) 1U;
  205.     if (outlen <= inlen ||
  206.         (output_ = output = calloc(outlen, (size_t) 1U)) == NULL) {
  207.         die_mem();
  208.     }
  209.     if (utf8 > 0 && strcasecmp(charset_fs, "utf-8") != 0) {
  210.         if (iconv(iconv_fd_utf82fs, (char **) &string,
  211.                   &inlen, &output_, &outlen_) == (size_t) -1) {
  212.             strncpy(output, string, outlen);
  213.         }
  214.     } else if (utf8 <= 0 && strcasecmp(charset_fs, charset_client) != 0) {
  215.         if (iconv(iconv_fd_client2fs, (char **) &string,
  216.                   &inlen, &output_, &outlen_) == (size_t) -1) {
  217.             strncpy(output, string, outlen);
  218.         }
  219.     } else {
  220.         strncpy(output, string, outlen);
  221.     }
  222.     output[outlen - 1] = 0;    
  223.    
  224.     return output;
  225. }
  226. #endif
  227.  
  228. void parser(void)
  229. {
  230.     char *arg;
  231. #ifndef MINIMAL
  232.     char *sitearg;
  233. #endif
  234. #ifdef WITH_RFC2640
  235.     char *narg = NULL;
  236. #endif
  237.     size_t n;
  238.  
  239. #ifdef IMPLICIT_TLS
  240.     (void) tls_init_new_session();
  241.     data_protection_level = CPL_PRIVATE;
  242. #endif
  243.     for (;;) {
  244.         xferfd = -1;
  245.         if (state_needs_update != 0) {
  246.             state_needs_update = 0;
  247.             setprocessname("pure-ftpd (IDLE)");
  248. #ifdef FTPWHO
  249.             if (shm_data_cur != NULL) {
  250.                 ftpwho_lock();
  251.                 shm_data_cur->state = FTPWHO_STATE_IDLE;
  252.                 *shm_data_cur->filename = 0;
  253.                 ftpwho_unlock();
  254.             }
  255. #endif
  256.         }
  257.         doreply();
  258.         alarm(idletime * 2);
  259.         switch (sfgets()) {
  260.         case -1:
  261. #ifdef BORING_MODE
  262.             die(421, LOG_INFO, MSG_TIMEOUT);
  263. #else
  264.             die(421, LOG_INFO, MSG_TIMEOUT_PARSER);
  265. #endif
  266.         case -2:
  267.             return;
  268.         }
  269. #ifdef DEBUG
  270.         if (debug != 0) {
  271.             addreply(0, "%s", cmd);
  272.         }
  273. #endif
  274.         n = (size_t) 0U;
  275.         while ((isalpha((unsigned char) cmd[n]) || cmd[n] == '@') &&
  276.                n < cmdsize) {
  277.             cmd[n] = (char) tolower((unsigned char) cmd[n]);
  278.             n++;
  279.         }
  280.         if (n >= cmdsize) {            /* overparanoid, it should never happen */
  281.             die(421, LOG_WARNING, MSG_LINE_TOO_LONG);
  282.         }
  283.         if (n == (size_t) 0U) {
  284.             nop:
  285.             addreply_noformat(500, "?");
  286.             continue;
  287.         }
  288. #ifdef SKIP_COMMAND_TRAILING_SPACES        
  289.         while (isspace((unsigned char) cmd[n]) && n < cmdsize) {
  290.             cmd[n++] = 0;
  291.         }
  292.         arg = cmd + n;        
  293.         while (cmd[n] != 0 && n < cmdsize) {
  294.             n++;
  295.         }
  296.         n--;
  297.         while (isspace((unsigned char) cmd[n])) {
  298.             cmd[n--] = 0;
  299.         }
  300. #else
  301.         if (cmd[n] == 0) {
  302.             arg = cmd + n;
  303.         } else if (isspace((unsigned char) cmd[n])) {
  304.             cmd[n] = 0;
  305.             arg = cmd + n + 1;
  306.         } else {
  307.             goto nop;
  308.         }
  309. #endif
  310.         if (logging != 0) {
  311. #ifdef DEBUG
  312.             logfile(LOG_DEBUG, MSG_DEBUG_COMMAND " [%s] [%s]",
  313.                    cmd, arg);
  314. #else
  315.             logfile(LOG_DEBUG, MSG_DEBUG_COMMAND " [%s] [%s]",
  316.                    cmd, strcmp(cmd, "pass") ? arg : "<*>");
  317. #endif
  318.         }
  319. #ifdef WITH_RFC2640
  320.         narg = charset_client2fs(arg);
  321.     arg = narg;
  322. #endif
  323.         /*
  324.          * antiidle() is called with dummy commands, usually used by clients
  325.          * who are wanting extra idle time. We give them some, but not too much.
  326.          * When we jump to wayout, the idle timer is not zeroed. It means that
  327.          * we didn't issue an 'active' command like RETR.
  328.          */
  329.        
  330. #ifndef MINIMAL
  331.         if (!strcmp(cmd, "noop")) {
  332.             antiidle();
  333.             donoop();
  334.             goto wayout;
  335.         }
  336. #endif
  337.         if (!strcmp(cmd, "user")) {
  338. #ifdef WITH_TLS
  339.             if (enforce_tls_auth > 1 && tls_cnx == NULL) {
  340.                 die(421, LOG_WARNING, MSG_TLS_NEEDED);
  341.             }
  342. #endif
  343.             douser(arg);
  344.         } else if (!strcmp(cmd, "acct")) {
  345.             addreply(202, MSG_WHOAREYOU);
  346.         } else if (!strcmp(cmd, "pass")) {
  347.             if (guest == 0) {
  348.                 randomdelay();
  349.             }
  350.             dopass(arg);
  351.         } else if (!strcmp(cmd, "quit")) {
  352.             addreply(221, MSG_GOODBYE,
  353.                      (unsigned long long) ((uploaded + 1023ULL) / 1024ULL),
  354.                      (unsigned long long) ((downloaded + 1023ULL) / 1024ULL));
  355.             return;
  356.         } else if (!strcmp(cmd, "syst")) {
  357.             antiidle();
  358.             addreply_noformat(215, "UNIX Type: L8");
  359.             goto wayout;
  360. #ifdef WITH_TLS
  361.         } else if (enforce_tls_auth > 0 &&
  362.                    !strcmp(cmd, "auth") && !strcasecmp(arg, "tls")) {
  363.             addreply_noformat(234, "AUTH TLS OK.");
  364.             doreply();
  365.             if (tls_cnx == NULL) {
  366.                 (void) tls_init_new_session();
  367.             }
  368.             goto wayout;
  369.         } else if (!strcmp(cmd, "pbsz")) {
  370.             addreply_noformat(tls_cnx == NULL ? 503 : 200, "PBSZ=0");
  371.         } else if (!strcmp(cmd, "prot")) {
  372.             if (tls_cnx == NULL) {
  373.                 addreply_noformat(503, MSG_PROT_BEFORE_PBSZ);
  374.                 goto wayout;
  375.             }
  376.             switch (*arg) {
  377.             case 0:
  378.                 addreply_noformat(503, MSG_MISSING_ARG);
  379.                 data_protection_level = CPL_NONE;
  380.                 break;
  381.             case 'C':
  382.                 if (arg[1] == 0) {
  383.                     addreply(200, MSG_PROT_OK, "clear");
  384.                     data_protection_level = CPL_CLEAR;
  385.                     break;
  386.                 }
  387.             case 'S':
  388.             case 'E':
  389.                 if (arg[1] == 0) {
  390.                     addreply(200, MSG_PROT_UNKNOWN_LEVEL, arg, "private");
  391.                     data_protection_level = CPL_PRIVATE;
  392.                     break;
  393.                 }
  394.             case 'P':
  395.                 if (arg[1] == 0) {
  396.                     addreply(200, MSG_PROT_OK, "private");
  397.                     data_protection_level = CPL_PRIVATE;
  398.                     break;
  399.                 }
  400.             default:
  401.                 addreply_noformat(534, "Fallback to [C]");
  402.                 data_protection_level = CPL_CLEAR;
  403.                 break;
  404.             }
  405. #endif
  406.         } else if (!strcmp(cmd, "auth") || !strcmp(cmd, "adat")) {
  407.             addreply_noformat(500, MSG_AUTH_UNIMPLEMENTED);
  408.         } else if (!strcmp(cmd, "type")) {
  409.             antiidle();
  410.             dotype(arg);
  411.             goto wayout;
  412.         } else if (!strcmp(cmd, "mode")) {
  413.             antiidle();                
  414.             domode(arg);
  415.             goto wayout;
  416. #ifndef MINIMAL
  417.         } else if (!strcmp(cmd, "feat")) {
  418.             dofeat();
  419.             goto wayout;
  420.     } else if (!strcmp(cmd, "opts")) {
  421.         doopts(arg);
  422.         goto wayout;
  423. #endif
  424.         } else if (!strcmp(cmd, "stru")) {
  425.             dostru(arg);
  426.             goto wayout;
  427. #ifndef MINIMAL
  428.         } else if (!strcmp(cmd, "help")) {
  429.             goto help_site;
  430. #endif
  431. #ifdef DEBUG
  432.         } else if (!strcmp(cmd, "xdbg")) {
  433.             debug++;
  434.             addreply(200, MSG_XDBG_OK, debug);
  435.             goto wayout;
  436. #endif            
  437.         } else if (loggedin == 0) {            
  438.             /* from this point, all commands need authentication */
  439.             addreply_noformat(530, MSG_NOT_LOGGED_IN);
  440.             goto wayout;
  441.         } else {
  442.             if (!strcmp(cmd, "cwd") || !strcmp(cmd, "xcwd")) {
  443.                 antiidle();
  444.                 docwd(arg);
  445.                 goto wayout;
  446.             } else if (!strcmp(cmd, "port")) {
  447.                 doport(arg);
  448. #ifndef MINIMAL
  449.             } else if (!strcmp(cmd, "eprt")) {
  450.                 doeprt(arg);
  451.             } else if (!strcmp(cmd, "esta") &&
  452.                        disallow_passive == 0 &&
  453.                        STORAGE_FAMILY(force_passive_ip) == 0) {
  454.                 doesta();
  455.             } else if (!strcmp(cmd, "estp")) {
  456.                 doestp();
  457. #endif
  458.             } else if (disallow_passive == 0 &&
  459.                        (!strcmp(cmd, "pasv") || !strcmp(cmd, "p@sw"))) {
  460.                 dopasv(0);
  461.             } else if (disallow_passive == 0 &&
  462.                        (!strcmp(cmd, "epsv") &&
  463.                        (broken_client_compat == 0 ||
  464.                         STORAGE_FAMILY(ctrlconn) == AF_INET6))) {
  465.                 if (!strcasecmp(arg, "all")) {
  466.                     epsv_all = 1;
  467.                     addreply_noformat(220, MSG_ACTIVE_DISABLED);
  468.                 } else if (!strcmp(arg, "2") && !v6ready) {
  469.                     addreply_noformat(522, MSG_ONLY_IPV4);
  470.                 } else {
  471.                     dopasv(1);
  472.                 }
  473. #ifndef MINIMAL            
  474.             } else if (disallow_passive == 0 && !strcmp(cmd, "spsv")) {
  475.                 dopasv(2);
  476.             } else if (!strcmp(cmd, "allo")) {
  477.                 if (*arg == 0) {
  478.                     addreply_noformat(501, MSG_STAT_FAILURE);
  479.                 } else {
  480.                     const off_t size = (off_t) strtoull(arg, NULL, 10);
  481.                    
  482.                     if (size < (off_t) 0) {
  483.                         addreply_noformat(501, MSG_STAT_FAILURE);                        
  484.                     } else {
  485.                         doallo(size);
  486.                     }
  487.                 }
  488. #endif
  489.             } else if (!strcmp(cmd, "pwd") || !strcmp(cmd, "xpwd")) {
  490. #ifdef WITH_RFC2640
  491.         char *nwd;
  492. #endif
  493.                 antiidle();
  494. #ifdef WITH_RFC2640
  495.         nwd = charset_fs2client(wd);
  496.         addreply(257, "\"%s\" " MSG_IS_YOUR_CURRENT_LOCATION, nwd);
  497.         free(nwd);
  498. #else
  499.                 addreply(257, "\"%s\" " MSG_IS_YOUR_CURRENT_LOCATION, wd);
  500. #endif
  501.                 goto wayout;                
  502.             } else if (!strcmp(cmd, "cdup") || !strcmp(cmd, "xcup")) {
  503.                 docwd("..");
  504.             } else if (!strcmp(cmd, "retr")) {
  505.                 if (*arg != 0) {
  506. #ifdef WITH_TLS
  507.                     if (enforce_tls_auth == 3 &&
  508.                         data_protection_level != CPL_PRIVATE) {
  509.                         addreply_noformat(521, MSG_PROT_PRIVATE_NEEDED);
  510.                     }
  511.                     else
  512. #endif
  513.                     {
  514.                         doretr(arg);
  515.                     }
  516.                 } else {
  517.                     addreply_noformat(501, MSG_NO_FILE_NAME);
  518.                 }
  519.             } else if (!strcmp(cmd, "rest")) {
  520.                 antiidle();
  521.                 if (*arg != 0) {
  522.                     dorest(arg);
  523.                 } else {
  524.                     addreply_noformat(501, MSG_NO_RESTART_POINT);
  525.                     restartat = (off_t) 0;
  526.                 }
  527.                 goto wayout;
  528.             } else if (!strcmp(cmd, "dele")) {
  529.                 if (*arg != 0) {
  530.                     dodele(arg);
  531.                 } else {
  532.                     addreply_noformat(501, MSG_NO_FILE_NAME);
  533.                 }
  534.             } else if (!strcmp(cmd, "stor")) {
  535.                 arg = revealextraspc(arg);
  536.                 if (*arg != 0) {
  537. #ifdef WITH_TLS
  538.                     if (enforce_tls_auth == 3 &&
  539.                         data_protection_level != CPL_PRIVATE) {
  540.                         addreply_noformat(521, MSG_PROT_PRIVATE_NEEDED);
  541.                     } else
  542. #endif
  543.                     {
  544.                         dostor(arg, 0, autorename);
  545.                     }
  546.                 } else {
  547.                     addreply_noformat(501, MSG_NO_FILE_NAME);
  548.                 }
  549.             } else if (!strcmp(cmd, "appe")) {
  550.                 arg = revealextraspc(arg);
  551.                 if (*arg != 0) {
  552. #ifdef WITH_TLS
  553.                     if (enforce_tls_auth == 3 &&
  554.                         data_protection_level != CPL_PRIVATE) {
  555.                         addreply_noformat(521, MSG_PROT_PRIVATE_NEEDED);
  556.                     } else
  557. #endif
  558.                     {
  559.                         dostor(arg, 1, 0);
  560.                     }
  561.                 } else {
  562.                     addreply_noformat(501, MSG_NO_FILE_NAME);
  563.                 }
  564. #ifndef MINIMAL
  565.             } else if (!strcmp(cmd, "stou")) {
  566. #ifdef WITH_TLS
  567.                 if (enforce_tls_auth == 3 &&
  568.                     data_protection_level != CPL_PRIVATE) {
  569.                     addreply_noformat(521, MSG_PROT_PRIVATE_NEEDED);
  570.                 } else
  571. #endif
  572.                 {
  573.                      dostou();
  574.                 }
  575. #endif
  576. #ifndef DISABLE_MKD_RMD
  577.             } else if (!strcmp(cmd, "mkd") || !strcmp(cmd, "xmkd")) {
  578.                 arg = revealextraspc(arg);
  579.                 if (*arg != 0) {
  580.                     domkd(arg);
  581.                 } else {
  582.                     addreply_noformat(501, MSG_NO_DIRECTORY_NAME);
  583.                 }
  584.             } else if (!strcmp(cmd, "rmd") || !strcmp(cmd, "xrmd")) {
  585.                 if (*arg != 0) {
  586.                     dormd(arg);
  587.                 } else {
  588.                     addreply_noformat(550, MSG_NO_DIRECTORY_NAME);
  589.                 }
  590. #endif
  591. #ifndef MINIMAL
  592.             } else if (!strcmp(cmd, "stat")) {
  593.                 if (*arg != 0) {
  594.                     modern_listings = 0;
  595.                     donlist(arg, 1, 1, 1, 1);
  596.                 } else {
  597.                     addreply_noformat(211, "http://www.pureftpd.org/");
  598.                 }
  599. #endif
  600.             } else if (!strcmp(cmd, "list")) {
  601. #ifndef MINIMAL
  602.                 modern_listings = 0;
  603. #endif
  604. #ifdef WITH_TLS
  605.                 if (enforce_tls_auth == 3 &&
  606.                     data_protection_level != CPL_PRIVATE) {
  607.                     addreply_noformat(521, MSG_PROT_PRIVATE_NEEDED);
  608.                 } else
  609. #endif
  610.                 {
  611.                     donlist(arg, 0, 1, 0, 1);
  612.                 }
  613.             } else if (!strcmp(cmd, "nlst")) {
  614. #ifndef MINIMAL                
  615.                 modern_listings = 0;
  616. #endif
  617. #ifdef WITH_TLS
  618.                 if (enforce_tls_auth == 3 &&
  619.                     data_protection_level != CPL_PRIVATE) {
  620.                     addreply_noformat(521, MSG_PROT_PRIVATE_NEEDED);
  621.                 } else
  622. #endif
  623.                 {
  624.                     donlist(arg, 0, 0, 0, broken_client_compat);
  625.                 }
  626. #ifndef MINIMAL
  627.             } else if (!strcmp(cmd, "mlst")) {
  628. #ifdef WITH_TLS
  629.                 if (enforce_tls_auth == 3 &&
  630.                     data_protection_level != CPL_PRIVATE) {
  631.                     addreply_noformat(521, MSG_PROT_PRIVATE_NEEDED);
  632.                 } else
  633. #endif
  634.                 {
  635.                     domlst(*arg != 0 ? arg : ".");
  636.                 }
  637.             } else if (!strcmp(cmd, "mlsd")) {
  638.                 modern_listings = 1;
  639. #ifdef WITH_TLS
  640.                 if (enforce_tls_auth == 3 &&
  641.                     data_protection_level != CPL_PRIVATE) {
  642.                     addreply_noformat(521, MSG_PROT_PRIVATE_NEEDED);
  643.                 } else
  644. #endif
  645.                 {
  646.                     donlist(arg, 0, 1, 1, 0);
  647.                 }
  648. #endif
  649.             } else if (!strcmp(cmd, "abor")) {
  650.                 addreply_noformat(226, MSG_ABOR_SUCCESS);
  651. #ifndef MINIMAL
  652.             } else if (!strcmp(cmd, "site")) {
  653.                 if ((sitearg = arg) != NULL) {
  654.                     while (*sitearg != 0 && !isspace((unsigned char) *sitearg)) {
  655.                         sitearg++;
  656.                     }
  657.                     if (*sitearg != 0) {
  658.                         *sitearg++ = 0;
  659.                     }
  660.                 }
  661.                 if (!strcasecmp(arg, "idle")) {
  662.                     if (sitearg == NULL || *sitearg == 0) {
  663.                         addreply_noformat(501, "SITE IDLE: " MSG_MISSING_ARG);
  664.                     } else {
  665.                         unsigned long int i = 0;
  666.  
  667.                         i = strtoul(sitearg, &sitearg, 10);
  668.                         if (sitearg && *sitearg)
  669.                             addreply(501, MSG_GARBAGE_FOUND " : %s", sitearg);
  670.                         else if (i > MAX_SITE_IDLE)
  671.                             addreply_noformat(501, MSG_VALUE_TOO_LARGE);
  672.                         else {
  673.                             idletime = i;
  674.                             addreply(200, MSG_IDLE_TIME, idletime);
  675.                             idletime_noop = (double) idletime * 2.0;
  676.                         }
  677.                     }
  678.                 } else if (!strcasecmp(arg, "time")) {
  679.                     dositetime();
  680.                 } else if (!strcasecmp(arg, "help")) {
  681.                     help_site:
  682.                    
  683.                     addreply_noformat(214, MSG_SITE_HELP CRLF
  684. # ifdef WITH_DIRALIASES
  685.                                       " ALIAS" CRLF
  686. # endif
  687.                                       " CHMOD" CRLF " IDLE" CRLF " UTIME");
  688.                     addreply_noformat(214, "Pure-FTPd - http://pureftpd.org/");
  689.                 } else if (!strcasecmp(arg, "chmod")) {
  690.                     char *sitearg2;
  691.                     mode_t mode;
  692.                    
  693.                     parsechmod:
  694.                     if (sitearg == NULL || *sitearg == 0) {
  695.                         addreply_noformat(501, MSG_MISSING_ARG);
  696.                         goto chmod_wayout;
  697.                     }
  698.                     sitearg2 = sitearg;
  699.                     while (*sitearg2 != 0 && !isspace((unsigned char) *sitearg2)) {
  700.                         sitearg2++;
  701.                     }                    
  702.                     while (*sitearg2 != 0 && isspace((unsigned char) *sitearg2)) {
  703.                         sitearg2++;
  704.                     }                    
  705.                     if (*sitearg2 == 0) {
  706.                         addreply_noformat(550, MSG_NO_FILE_NAME);
  707.                         goto chmod_wayout;
  708.                     }
  709.                     mode = (mode_t) strtoul(sitearg, NULL, 8);
  710.                     if (mode > (mode_t) 07777) {
  711.                         addreply_noformat(501, MSG_BAD_CHMOD);
  712.                         goto chmod_wayout;
  713.                     }
  714.                     dochmod(sitearg2, mode);
  715.                     chmod_wayout:
  716.                     (void) 0;
  717.                 } else if (!strcasecmp(arg, "utime")) {
  718.                     char *sitearg2;
  719.                    
  720.                     if (sitearg == NULL || *sitearg == 0) {
  721.                         addreply_noformat(501, MSG_NO_FILE_NAME);
  722.                         goto utime_wayout;
  723.                     }          
  724.                     if ((sitearg2 = strrchr(sitearg, ' ')) == NULL ||
  725.                         sitearg2 == sitearg) {
  726.                         addreply_noformat(501, MSG_MISSING_ARG);
  727.                         goto utime_wayout;
  728.                     }
  729.                     if (strcasecmp(sitearg2, " UTC") != 0) {
  730.                         addreply_noformat(500, "UTC Only");
  731.                         goto utime_wayout;         
  732.                     }
  733.                     *sitearg2-- = 0;
  734.                     if ((sitearg2 = strrchr(sitearg, ' ')) == NULL ||
  735.                         sitearg2 == sitearg) {
  736.                         utime_no_arg:
  737.                         addreply_noformat(501, MSG_MISSING_ARG);
  738.                         goto utime_wayout;
  739.                     }
  740.                     *sitearg2-- = 0;
  741.                     if ((sitearg2 = strrchr(sitearg, ' ')) == NULL ||
  742.                         sitearg2 == sitearg) {
  743.                         goto utime_no_arg;
  744.                     }
  745.                     *sitearg2-- = 0;
  746.                     if ((sitearg2 = strrchr(sitearg, ' ')) == NULL ||
  747.                         sitearg2 == sitearg) {
  748.                         goto utime_no_arg;
  749.                     }
  750.                     *sitearg2++ = 0;
  751.                     if (*sitearg2 == 0) {
  752.                         goto utime_no_arg;         
  753.                     }
  754.                     doutime(sitearg, sitearg2);
  755.                     utime_wayout:
  756.                     (void) 0;
  757. # ifdef WITH_DIRALIASES        
  758.                 } else if (!strcasecmp(arg, "alias")) {
  759.                     if (sitearg == NULL || *sitearg == 0) {
  760.                         print_aliases();
  761.                     } else {
  762.                         const char *alias;
  763.                        
  764.                         if ((alias = lookup_alias(sitearg)) != NULL) {
  765.                             addreply(214, MSG_ALIASES_ALIAS, sitearg, alias);
  766.                         } else {
  767.                             addreply(502, MSG_ALIASES_UNKNOWN, sitearg);
  768.                         }
  769.                     }
  770. # endif
  771.                 } else if (*arg != 0) {
  772.                     addreply(500, "SITE %s " MSG_UNKNOWN_EXTENSION, arg);
  773.                 } else {
  774.                     addreply_noformat(500, "SITE: " MSG_MISSING_ARG);
  775.                 }
  776. #endif
  777.             } else if (!strcmp(cmd, "mdtm")) {
  778.                 domdtm(arg);
  779.             } else if (!strcmp(cmd, "size")) {
  780.                 dosize(arg);
  781. #ifndef MINIMAL
  782.             } else if (!strcmp(cmd, "chmod")) {
  783.                 sitearg = arg;
  784.                 goto parsechmod;
  785. #endif
  786.             } else if (!strcmp(cmd, "rnfr")) {
  787.                 if (*arg != 0) {
  788.                     dornfr(arg);
  789.                 } else {
  790.                     addreply_noformat(550, MSG_NO_FILE_NAME);
  791.                 }
  792.             } else if (!strcmp(cmd, "rnto")) {
  793.                 arg = revealextraspc(arg);
  794.                 if (*arg != 0) {
  795.                     dornto(arg);
  796.                 } else {
  797.                     addreply_noformat(550, MSG_NO_FILE_NAME);
  798.                 }
  799.             } else {
  800.                 addreply_noformat(500, MSG_UNKNOWN_COMMAND);
  801.             }
  802.         }
  803.         noopidle = (time_t) -1;
  804.         wayout:
  805. #ifdef WITH_RFC2640
  806.         free(narg);
  807.         narg = NULL;
  808. #endif
  809. #ifdef THROTTLING
  810.         if (throttling_delay != 0UL) {
  811.             usleep2(throttling_delay);
  812.         }
  813. #else
  814.         (void) 0;
  815. #endif
  816.     }
  817. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement