00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00094
00095
00096 #include <sys/version.h>
00097
00098 #include <sys/socket.h>
00099 #include <netinet/tcp.h>
00100 #include <sys/timer.h>
00101
00102 #include <string.h>
00103 #include <stdio.h>
00104 #include <stdlib.h>
00105 #include <io.h>
00106 #include <fcntl.h>
00107 #include <sys/stat.h>
00108 #include <dirent.h>
00109 #include <unistd.h>
00110 #include <memdebug.h>
00111
00112 #include <pro/ftpd.h>
00113
00114 #ifdef FTPD_DEBUG
00115 #include <sys/heap.h>
00116 #endif
00117
00124
00131
00137 #ifndef FTP_ROOTPATH
00138 #define FTP_ROOTPATH "PNUT:"
00139 #endif
00140
00146 #ifndef FTP_DATA_PORT
00147 #define FTP_DATA_PORT 20
00148 #endif
00149
00152 static char *ftp_root;
00153 static char *ftp_user;
00154 static char *ftp_pass;
00155
00156
00157
00158
00159
00160 static prog_char cmd_cwd_P[] = "CWD";
00161 static prog_char cmd_dele_P[] = "DELE";
00162 static prog_char cmd_list_P[] = "LIST";
00163 static prog_char cmd_mkd_P[] = "MKD";
00164 static prog_char cmd_xmkd_P[] = "XMKD";
00165 static prog_char cmd_nlst_P[] = "NLST";
00166 static prog_char cmd_noop_P[] = "NOOP";
00167 static prog_char cmd_pass_P[] = "PASS";
00168 static prog_char cmd_pasv_P[] = "PASV";
00169 static prog_char cmd_port_P[] = "PORT";
00170 static prog_char cmd_pwd_P[] = "PWD";
00171 static prog_char cmd_xpwd_P[] = "XPWD";
00172 static prog_char cmd_quit_P[] = "QUIT";
00173 static prog_char cmd_retr_P[] = "RETR";
00174 static prog_char cmd_rmd_P[] = "RMD";
00175 static prog_char cmd_xrmd_P[] = "XRMD";
00176 static prog_char cmd_stor_P[] = "STOR";
00177 static prog_char cmd_syst_P[] = "SYST";
00178 static prog_char cmd_type_P[] = "TYPE";
00179 static prog_char cmd_user_P[] = "USER";
00180 static prog_char cmd_rename1_P[] = "RNFR";
00181 static prog_char cmd_rename2_P[] = "RNTO";
00182
00183
00184 static char *mon_name = "JanFebMarAprMayJunJulAugSepOctNovDec";
00185
00186 static prog_char rep_banner[] = "220 Nut/OS FTP %s ready at %.3s%3d %02d:%02d:%02d\r\n";
00187
00200 static void SplitCmdArg(char * line, char ** cmd, char ** args)
00201 {
00202
00203 while (*line && *line <= ' ') {
00204 line++;
00205 }
00206
00207
00208 *cmd = line;
00209 while (*line > ' ') {
00210 if (*line >= (uint8_t) 'a' && *line <= (uint8_t) 'z') {
00211 *line -= (uint8_t) 'a' - 'A';
00212 }
00213 line++;
00214 }
00215
00216
00217 if (*line) {
00218 *line++ = '\0';
00219 }
00220
00221
00222 while (*line && *line <= ' ') {
00223 ++line;
00224 }
00225
00226
00227 *args = line;
00228 while (*line && *line != '\r' && *line != '\n') {
00229 line++;
00230 }
00231
00232
00233 *line = 0;
00234 }
00235
00251 static int ParseIpPort(CONST char * arg, uint32_t * ip, uint16_t * port)
00252 {
00253 int rc;
00254
00255 *ip = 0;
00256 *port = 0;
00257 for (rc = 0; rc < 6; rc++) {
00258 if (*arg < '0' || *arg > '9') {
00259 break;
00260 }
00261 if (rc < 4) {
00262 *ip >>= 8;
00263 *ip += atol(arg) << 24;
00264 } else {
00265 *port <<= 8;
00266 *port += atoi(arg);
00267 }
00268 while (*arg && *arg != ',') {
00269 arg++;
00270 }
00271 if (*arg == ',') {
00272 arg++;
00273 }
00274 }
00275 return rc;
00276 }
00277
00287 int NutFtpRespondOk(FTPSESSION * session, int code)
00288 {
00289 static prog_char fmt_P[] = "%d OK\r\n";
00290
00291 #ifdef FTPD_DEBUG
00292 printf("\n<'%d OK' ", code);
00293 #endif
00294 fprintf_P(session->ftp_stream, fmt_P, code);
00295 fflush(session->ftp_stream);
00296
00297 return 0;
00298 }
00299
00309 int NutFtpRespondBad(FTPSESSION * session, int code)
00310 {
00311 static prog_char fmt_P[] = "%d Failed\r\n";
00312
00313 #ifdef FTPD_DEBUG
00314 printf("\n<'%d Failed' ", code);
00315 #endif
00316 fprintf_P(session->ftp_stream, fmt_P, code);
00317 fflush(session->ftp_stream);
00318
00319 return 0;
00320 }
00321
00331 int NutFtpSendMode(FTPSESSION * session, int binary)
00332 {
00333 static prog_char intro_P[] = "150 Opening ";
00334 static prog_char amode_P[] = "ASCII.\r\n";
00335 static prog_char bmode_P[] = "BINARY.\r\n";
00336
00337 #ifdef FTPD_DEBUG
00338 printf("\n<'150 Opening %s' ", binary ? "BINARY" : "ASCII");
00339 #endif
00340 fputs_P(intro_P, session->ftp_stream);
00341 fputs_P(binary ? bmode_P : amode_P, session->ftp_stream);
00342 fflush(session->ftp_stream);
00343
00344 return 0;
00345 }
00346
00367 char *CreateFullPathName(char *root, char *work, char *path)
00368 {
00369 char *full;
00370 char *cp;
00371 size_t rl = root ? strlen(root) : 0;
00372 size_t wl = work ? strlen(work) : 0;
00373 size_t pl = path ? strlen(path) : 0;
00374
00375
00376 if (rl && *(root + rl - 1) == '/') {
00377 rl--;
00378 }
00379 if (wl && *(work + wl - 1) == '/') {
00380 wl--;
00381 }
00382
00383 if ((full = malloc(rl + wl + pl + 3)) != NULL) {
00384
00385 cp = full;
00386 if (rl) {
00387 cp = strcpy(full, root) + rl;
00388 }
00389
00390
00391 if(pl == 0 || *path != '/') {
00392 if (wl) {
00393 if (*work != '/') {
00394 *cp++ = '/';
00395 }
00396 cp = strcpy(cp, work) + wl;
00397 }
00398 *cp++ = '/';
00399 rl++;
00400 }
00401
00402 if (pl) {
00403 *cp = 0;
00404 work = full + rl;
00405
00406 while (*path) {
00407
00408 if (*path == '/') {
00409
00410 if ((cp == full) || (*(cp-1) != '/')) {
00411 *cp++ = *path++;
00412 }
00413 while (*path == '/') {
00414 path++;
00415 }
00416 }
00417
00418 if (*path == '.') {
00419 path++;
00420 if (*path == '/') {
00421 path++;
00422 continue;
00423 }
00424 if (*path == 0) {
00425 break;
00426 }
00427 if (*path == '.') {
00428 path++;
00429 if (*path == '/' || *path == 0) {
00430 if (cp != work) {
00431 cp--;
00432 while (cp != work) {
00433 cp--;
00434 if (*cp == '/') {
00435 break;
00436 }
00437 }
00438 }
00439 continue;
00440 }
00441 path--;
00442 }
00443 path--;
00444 }
00445
00446 while (*path && *path != '/') {
00447 *cp++ = *path++;
00448 }
00449 }
00450 }
00451 *cp = 0;
00452 }
00453 return full;
00454 }
00455
00465 TCPSOCKET *NutFtpDataConnect(FTPSESSION * session)
00466 {
00467 #ifdef FTPD_DEBUG
00468 static prog_char errorcode_P[] = "errorcode of active socket: %i\n";
00469 static prog_char socfailed_P[] = "Create socket failed";
00470 #endif
00471 TCPSOCKET *sock;
00472 int rc;
00473
00474 if ((sock = NutTcpCreateSocket()) != 0) {
00475
00476 if (session->ftp_maxseg) {
00477 NutTcpSetSockOpt(sock, TCP_MAXSEG, &session->ftp_maxseg, sizeof(session->ftp_maxseg));
00478 }
00479 if (session->ftp_passive) {
00480 rc = NutTcpAccept(sock, session->ftp_data_port);
00481 } else {
00482 rc = NutTcpConnect(sock, session->ftp_data_ip, session->ftp_data_port);
00483 #ifdef FTPD_DEBUG
00484 if (rc) {
00485 int errorcode = NutTcpError(sock);
00486 printf_P(errorcode_P, errorcode);
00487 }
00488 #endif
00489 }
00490 if (rc) {
00491 NutTcpCloseSocket(sock);
00492 sock = 0;
00493 }
00494 }
00495 #ifdef FTPD_DEBUG
00496 else {
00497 puts_P(socfailed_P);
00498 }
00499 #endif
00500 return sock;
00501 }
00502
00516 int NutRegisterFtpRoot(CONST char *path)
00517 {
00518
00519 if (path == NULL || *path == 0) {
00520
00521 if (ftp_root) {
00522 free(ftp_root);
00523 }
00524 if ((ftp_root = malloc(sizeof(FTP_ROOTPATH))) == 0) {
00525 return -1;
00526 }
00527 strcpy(ftp_root, FTP_ROOTPATH);
00528 }
00529
00530
00531 else {
00532 char *cp = strchr(path, ':');
00533 int len = strlen(path);
00534
00535
00536 if (len < 2 || cp == 0 || (*++cp && *cp != '/')) {
00537 return -1;
00538 }
00539
00540
00541 if ((cp = malloc(len + 1)) == 0) {
00542 return -1;
00543 }
00544
00545
00546 strcpy(cp, path);
00547 if (ftp_root) {
00548 free(ftp_root);
00549 }
00550 ftp_root = cp;
00551
00552
00553 cp = cp + strlen(cp) - 1;
00554 if (*cp == '/') {
00555 *cp = 0;
00556 }
00557 }
00558 return 0;
00559 }
00560
00576 int NutRegisterFtpUser(CONST char *user, CONST char *pass)
00577 {
00578 if (ftp_user) {
00579 free(ftp_user);
00580 ftp_user = NULL;
00581 }
00582 if (user && *user) {
00583 if ((ftp_user = strdup(user)) == NULL) {
00584 return -1;
00585 }
00586 }
00587 if (ftp_pass) {
00588 free(ftp_pass);
00589 ftp_pass = NULL;
00590 }
00591 if (pass && *pass) {
00592 if ((ftp_pass = strdup(pass)) == NULL) {
00593 return -1;
00594 }
00595 }
00596 return 0;
00597 }
00598
00599
00609 FTPSESSION *NutFtpOpenSession(TCPSOCKET * sock)
00610 {
00611 FTPSESSION *session;
00612
00613 session = malloc(sizeof(FTPSESSION));
00614
00615 if (session) {
00616 memset(session, 0, sizeof(FTPSESSION));
00617 session->ftp_data_port = FTP_DATA_PORT;
00618 session->ftp_maxseg = sock->so_mss;
00619 session->ftp_sock = sock;
00620
00621
00622 if ((session->ftp_cwd = malloc(2)) == 0) {
00623 free(session);
00624 session = 0;
00625 } else {
00626 session->ftp_cwd[0] = '/';
00627 session->ftp_cwd[1] = 0;
00628
00629
00630
00631
00632
00633
00634 if ((session->ftp_stream = _fdopen((int) sock, "r+b")) == 0) {
00635 free(session->ftp_cwd);
00636 free(session);
00637 session = 0;
00638 }
00639 }
00640 }
00641 return session;
00642 }
00643
00650 void NutFtpCloseSession(FTPSESSION * session)
00651 {
00652 if (session) {
00653
00654 fclose(session->ftp_stream);
00655 if (session->ftp_cwd) {
00656 free(session->ftp_cwd);
00657 }
00658 if (session->ftp_renamesource) {
00659 free(session->ftp_renamesource);
00660 }
00661 free(session);
00662 }
00663 }
00664
00675 int NutFtpProcessCwd(FTPSESSION * session, char *path)
00676 {
00677 struct stat st;
00678 char *cp = path + strlen(ftp_root);
00679
00680 if (*cp && strcmp(cp, "/")) {
00681
00682
00683
00684 if (stat(path, &st) || !S_ISDIR(st.st_mode)) {
00685 return NutFtpRespondBad(session, 550);
00686 }
00687 }
00688
00689
00690
00691
00692 if (*cp == 0) {
00693 cp = "/";
00694 }
00695 if (session->ftp_cwd) {
00696 free(session->ftp_cwd);
00697 }
00698 if ((session->ftp_cwd = strdup(cp)) == NULL) {
00699 return NutFtpRespondBad(session, 550);
00700 }
00701 return NutFtpRespondOk(session, 250);
00702 }
00703
00716 int NutFtpProcessDelete(FTPSESSION * session, char *path)
00717 {
00718 if (unlink(path)) {
00719 return NutFtpRespondBad(session, 550);
00720 }
00721 return NutFtpRespondOk(session, 250);
00722 }
00723
00741 int NutFtpTransferFile(FTPSESSION * session, char *path, int mode)
00742 {
00743 #ifdef FTPD_DEBUG
00744 static prog_char dataconnectfailed_P[] = "NutFtpDataConnect failed";
00745 #endif
00746 TCPSOCKET *sock;
00747 int ec = 550;
00748 int fh = -1;
00749
00750 if (mode) {
00751
00752 struct stat st;
00753 if (stat(path, &st) == 0) {
00754 if (S_ISREG(st.st_mode)) {
00755 fh = _open(path, _O_BINARY | _O_RDONLY);
00756 } else {
00757 #ifdef FTPD_DEBUG
00758 printf("Not a regular file\n");
00759 #endif
00760 }
00761 } else {
00762 #ifdef FTPD_DEBUG
00763 printf("'%s' stat() failed\n", path);
00764 #endif
00765 }
00766 }
00767
00768 else {
00769 fh = _open(path, _O_CREAT | _O_TRUNC);
00770 }
00771 if (fh != -1) {
00772
00773 NutFtpSendMode(session, session->ftp_tran_mode);
00774 if ((sock = NutFtpDataConnect(session)) != 0) {
00775 uint16_t mss = sock->so_mss;
00776 uint8_t *buf;
00777
00778 if (mss < 256) {
00779 mss = 256;
00780 }
00781 if ((buf = malloc(mss)) != 0) {
00782 int got;
00783
00784 ec = 0;
00785
00786
00787 if (mode) {
00788 while ((got = _read(fh, buf, mss)) > 0) {
00789 int send = 0;
00790 int retcode;
00791 uint8_t timeout = 0;
00792
00793
00794
00795 do {
00796 retcode = NutTcpSend(sock, buf+send, got-send);
00797 send += retcode;
00798 if (send == 0) {
00799 timeout++;
00800 NutSleep(10);
00801 } else {
00802 timeout = 0;
00803 }
00804 } while ((send < got ) && (retcode >= 0) && (timeout < 200));
00805 if (retcode <= 0) {
00806 #ifdef FTPD_DEBUG
00807 printf("Error in NutTcpSend\n");
00808 #endif
00809 ec = 551;
00810 break;
00811 }
00812 }
00813 }
00814
00815
00816 else {
00817 while ((got = NutTcpReceive(sock, buf, mss)) > 0) {
00818 int x;
00819 if ((x = _write(fh, buf, got)) != got) {
00820 ec = 552;
00821 break;
00822 }
00823 }
00824 }
00825 free(buf);
00826 }
00827 NutTcpCloseSocket(sock);
00828 }
00829 #ifdef FTPD_DEBUG
00830 else {
00831 puts_P(dataconnectfailed_P);
00832 }
00833 #endif
00834 _close(fh);
00835
00836
00837 if (mode == 0 && ec) {
00838 unlink(path);
00839 }
00840 }
00841 if (ec) {
00842 return NutFtpRespondBad(session, ec);
00843 }
00844 return NutFtpRespondOk(session, 226);
00845 }
00846
00860 int NutFtpTransferDirectoryOptions(FTPSESSION * session, char *path, int options)
00861 {
00862 static prog_char fileattributes_P[] = "rw-rw-rw- 1 0 0 %6lu ";
00863 static prog_char dateattribute_P[] = "%.3s %u ";
00864 static prog_char timeattribute_P[] = "%02u:%02u ";
00865 TCPSOCKET *sock;
00866 FILE *fp;
00867
00868 struct stat st;
00869 DIR *dir;
00870 struct dirent *d_ent;
00871 tm *gmt;
00872 uint32_t size;
00873 int ec = 550;
00874 char *name;
00875 size_t pathlen;
00876
00877 dir = opendir(path);
00878 if (dir) {
00879 NutFtpSendMode(session, 0);
00880 if ((sock = NutFtpDataConnect(session)) != 0) {
00881 if ((fp = _fdopen((int) sock, "r+b")) != 0) {
00882 ec = 0;
00883 pathlen = strlen(path);
00884 while ((d_ent = readdir(dir)) != 0) {
00885 if ((d_ent->d_name[0] == '.') && ((options & 1) == 0)) {
00886 continue;
00887 }
00888 if ((name = malloc(pathlen + strlen(d_ent->d_name) + 2)) != 0) {
00889 strcpy(name, path);
00890 if (pathlen == 0 || name[pathlen - 1] != '/') {
00891 strcat(name, "/");
00892 }
00893 strcat(name, d_ent->d_name);
00894 if (stat(name, &st) == 0) {
00895 if (S_ISDIR(st.st_mode)) {
00896 fputc('d', fp);
00897 size = 0;
00898 } else {
00899 fputc('-', fp);
00900 size = st.st_size;
00901 }
00902 fprintf_P(fp, fileattributes_P, size);
00903 gmt = gmtime(&st.st_mtime);
00904
00905 fprintf_P(fp, dateattribute_P, mon_name + gmt->tm_mon * 3, gmt->tm_mday);
00906
00907 fprintf_P(fp, timeattribute_P, gmt->tm_hour, gmt->tm_min);
00908 fputs(d_ent->d_name, fp);
00909 fputs("\r\n", fp);
00910 }
00911 free(name);
00912 }
00913 }
00914 fclose(fp);
00915 }
00916 NutTcpCloseSocket(sock);
00917 }
00918 closedir(dir);
00919 }
00920 if (ec) {
00921 return NutFtpRespondBad(session, ec);
00922 }
00923 return NutFtpRespondOk(session, 226);
00924 }
00925
00938 int NutFtpTransferDirectory(FTPSESSION * session, char *path)
00939 {
00940 return NutFtpTransferDirectoryOptions(session, path, 0);
00941 }
00942
00955 int NutFtpProcessMkd(FTPSESSION * session, char *path)
00956 {
00957 if (mkdir(path, 0777)) {
00958 return NutFtpRespondBad(session, 550);
00959 }
00960 return NutFtpRespondOk(session, 257);
00961 }
00962
00963
00964 int NutFtpRenamePrepare(FTPSESSION * session, char *path)
00965 {
00966 if (session->ftp_renamesource) {
00967 free(session->ftp_renamesource);
00968 session->ftp_renamesource = NULL;
00969 }
00970 if (path) {
00971 struct stat st;
00972 if (stat(path, &st) == 0) {
00973 session->ftp_renamesource = strdup(path);
00974 if (session->ftp_renamesource) {
00975 return NutFtpRespondOk(session, 350);
00976 }
00977 } else {
00978 return NutFtpRespondBad(session, 450);
00979 }
00980 }
00981 return NutFtpRespondBad(session, 501);
00982 }
00983
00984 int NutFtpRenameAction(FTPSESSION * session, char *path)
00985 {
00986 uint16_t responsebad;
00987 if (session->ftp_renamesource) {
00988 if (path) {
00989 int res = rename(session->ftp_renamesource, path);
00990 free(session->ftp_renamesource);
00991 session->ftp_renamesource = NULL;
00992 if (res == 0) {
00993 return NutFtpRespondOk(session, 250);
00994 } else {
00995 responsebad = 550;
00996 }
00997 } else {
00998 responsebad = 501;
00999 }
01000 } else {
01001 responsebad = 503;
01002 }
01003 return NutFtpRespondBad(session, responsebad);
01004 }
01005
01006
01019 int NutFtpProcessPass(FTPSESSION * session, char *pass)
01020 {
01021 if (ftp_pass && *ftp_pass) {
01022 if (session->ftp_login != 1 || strcmp(ftp_pass, pass)) {
01023 session->ftp_login = 0;
01024 return NutFtpRespondBad(session, 550);
01025 }
01026 }
01027 session->ftp_login = 2;
01028 return NutFtpRespondOk(session, 230);
01029 }
01030
01044 int NutFtpProcessPassiv(FTPSESSION * session)
01045 {
01046 static prog_char passiveprint_P[] = "227 Passive (%u,%u,%u,%u,%u,%u).\r\n";
01047 uint32_t ip = session->ftp_sock->so_local_addr;
01048 uint16_t port = 20;
01049
01050 fprintf_P(session->ftp_stream, passiveprint_P,
01051 (uint8_t) ip, (uint8_t) (ip >> 8), (uint8_t) (ip >> 16), (uint8_t) (ip >> 24),
01052 (uint8_t) (port >> 8), (uint8_t) port);
01053 fflush(session->ftp_stream);
01054 session->ftp_passive = 1;
01055
01056 return 0;
01057 }
01058
01073 int NutFtpProcessPort(FTPSESSION * session, char *args)
01074 {
01075 if (ParseIpPort(args, &session->ftp_data_ip, &session->ftp_data_port) == 6) {
01076 if (session->ftp_sock->so_remote_addr == session->ftp_data_ip) {
01077 return NutFtpRespondOk(session, 200);
01078 }
01079 return NutFtpRespondBad(session, 425);
01080 }
01081 return NutFtpRespondBad(session, 501);;
01082 }
01083
01096 int NutFtpProcessPwd(FTPSESSION * session)
01097 {
01098 static prog_char pwdanswer_P[] = "257 \"%s\"\r\n";
01099 #ifdef FTPD_DEBUG
01100 printf("\n<'257 \"%s\"' ", session->ftp_cwd);
01101 #endif
01102 fprintf_P(session->ftp_stream, pwdanswer_P, session->ftp_cwd);
01103 return 0;
01104 }
01105
01118 int NutFtpProcessRmd(FTPSESSION * session, char *path)
01119 {
01120 if (rmdir(path)) {
01121 return NutFtpRespondBad(session, 451);
01122 }
01123 return NutFtpRespondOk(session, 257);
01124 }
01125
01135 int NutFtpProcessSystem(FTPSESSION * session)
01136 {
01137 static prog_char unixtype_P[] = "215 UNIX Type: L8\r\n";
01138 #ifdef FTPD_DEBUG
01139 printf("\n<'215 UNIX Type: L8' ");
01140 #endif
01141 fputs_P(unixtype_P, session->ftp_stream);
01142 return 0;
01143 }
01144
01159 int NutFtpProcessType(FTPSESSION * session, char *typecode)
01160 {
01161 session->ftp_tran_mode = (*typecode != 'A') && (*typecode != 'a');
01162 return NutFtpRespondOk(session, 200);
01163 }
01164
01177 int NutFtpProcessUser(FTPSESSION * session, char *user)
01178 {
01179 if (ftp_user && *ftp_user) {
01180 if (session->ftp_login && strcmp(ftp_user, user)) {
01181 session->ftp_login = 0;
01182 return NutFtpRespondBad(session, 550);
01183 }
01184 }
01185
01186
01187 if (ftp_pass && *ftp_pass) {
01188 session->ftp_login = 1;
01189 return NutFtpRespondOk(session, 331);
01190 }
01191
01192
01193 session->ftp_login = 2;
01194 return NutFtpRespondOk(session, 230);
01195 }
01196
01208 int NutFtpProcessRequest(FTPSESSION * session, char *request)
01209 {
01210 int rc = 0;
01211 char *cmd;
01212 char *args;
01213
01214
01215 SplitCmdArg(request, &cmd, &args);
01216 #ifdef FTPD_DEBUG
01217 printf("\n>'%s %s' ", cmd, args);
01218 #endif
01219
01220
01221 if ((session->ftp_renamesource) && (strcmp_P(cmd, cmd_rename2_P))) {
01222 free(session->ftp_renamesource);
01223 session->ftp_renamesource = NULL;
01224 }
01225
01226 if (strcmp_P(cmd, cmd_quit_P) == 0) {
01227 NutFtpRespondOk(session, 221);
01228 rc = -1;
01229 }
01230
01231 else if (strcmp_P(cmd, cmd_user_P) == 0) {
01232 rc = NutFtpProcessUser(session, args);
01233 }
01234
01235
01236 else if (strcmp_P(cmd, cmd_pass_P) == 0) {
01237 rc = NutFtpProcessPass(session, args);
01238 } else if (strcmp_P(cmd, cmd_noop_P) == 0) {
01239 NutFtpRespondOk(session, 200);
01240 }
01241
01242 else if (session->ftp_login < 2) {
01243 rc = NutFtpRespondBad(session, 530);
01244 }
01245
01246
01247 else {
01248
01249
01250 if (strcmp_P(cmd, cmd_pasv_P) == 0) {
01251 rc = NutFtpProcessPassiv(session);
01252 }
01253
01254
01255 else if (strcmp_P(cmd, cmd_port_P) == 0) {
01256 rc = NutFtpProcessPort(session, args);
01257 }
01258
01259
01260 else if (strcmp_P(cmd, cmd_pwd_P) == 0 || strcmp_P(cmd, cmd_xpwd_P) == 0) {
01261 rc = NutFtpProcessPwd(session);
01262 }
01263
01264
01265 else if (strcmp_P(cmd, cmd_syst_P) == 0) {
01266 rc = NutFtpProcessSystem(session);
01267 }
01268
01269
01270 else if (strcmp_P(cmd, cmd_type_P) == 0) {
01271 rc = NutFtpProcessType(session, args);
01272 }
01273
01274 else {
01275 char *path;
01276 char *argsredux = args;
01277 int options = 0;
01278 if (args[0] == '-') {
01279 if (strchr(args, 'a')) {
01280 options = 1;
01281 }
01282 argsredux = strchr(args, ' ');
01283 if ((argsredux) && (strlen(argsredux) > 0)) {
01284 argsredux++;
01285 } else {
01286 argsredux = "";
01287 }
01288 }
01289 if ((path = CreateFullPathName(ftp_root, session->ftp_cwd, argsredux)) == 0) {
01290 rc = NutFtpRespondBad(session, 451);
01291 }
01292
01293
01294 else if (strcmp_P(cmd, cmd_cwd_P) == 0) {
01295 rc = NutFtpProcessCwd(session, path);
01296 }
01297
01298
01299 else if (strcmp_P(cmd, cmd_dele_P) == 0) {
01300 rc = NutFtpProcessDelete(session, path);
01301 }
01302
01303
01304 else if (strcmp_P(cmd, cmd_list_P) == 0 || strcmp_P(cmd, cmd_nlst_P) == 0) {
01305 rc = NutFtpTransferDirectoryOptions(session, path, options);
01306 }
01307
01308
01309 else if (strcmp_P(cmd, cmd_mkd_P) == 0 || strcmp_P(cmd, cmd_xmkd_P) == 0) {
01310 rc = NutFtpProcessMkd(session, path);
01311 }
01312
01313
01314 else if (strcmp_P(cmd, cmd_retr_P) == 0) {
01315 rc = NutFtpTransferFile(session, path, 1);
01316 }
01317
01318
01319 else if (strcmp_P(cmd, cmd_rmd_P) == 0 || strcmp_P(cmd, cmd_xrmd_P) == 0) {
01320 rc = NutFtpProcessRmd(session, path);
01321 }
01322
01323
01324 else if (strcmp_P(cmd, cmd_stor_P) == 0) {
01325 rc = NutFtpTransferFile(session, path, 0);
01326 }
01327
01328 else if (strcmp_P(cmd, cmd_rename1_P) == 0) {
01329 rc = NutFtpRenamePrepare(session, path);
01330 }
01331
01332 else if (strcmp_P(cmd, cmd_rename2_P) == 0) {
01333 rc = NutFtpRenameAction(session, path);
01334 }
01335
01336 else {
01337 rc = NutFtpRespondBad(session, 502);
01338 }
01339
01340 if (path) {
01341 free(path);
01342 }
01343 }
01344 }
01345 return rc;
01346 }
01347
01363 int NutFtpServerSession(TCPSOCKET * sock)
01364 {
01365 int rc = 0;
01366 FTPSESSION *session;
01367 char *buff;
01368 time_t now;
01369 struct _tm *tip;
01370 char ch;
01371
01372
01373 if (NutRegisterFtpRoot(ftp_root)) {
01374 return -1;
01375 }
01376
01377
01378 if ((buff = malloc(FTP_MAX_CMDBUF)) == 0) {
01379 return -1;
01380 }
01381
01382
01383 if ((session = NutFtpOpenSession(sock)) == 0) {
01384 free(buff);
01385 return -1;
01386 }
01387
01388
01389 time(&now);
01390 tip = localtime(&now);
01391 #ifdef FTPD_DEBUG
01392 printf("\n<'");
01393 printf_P(rep_banner, NutVersionString(), &mon_name[tip->tm_mon * 3],
01394 tip->tm_mday, tip->tm_hour, tip->tm_min, tip->tm_sec);
01395 #endif
01396 fprintf_P(session->ftp_stream, rep_banner, NutVersionString(),
01397 &mon_name[tip->tm_mon * 3],
01398 tip->tm_mday, tip->tm_hour, tip->tm_min, tip->tm_sec);
01399
01400
01401
01402
01403 while (rc == 0) {
01404
01405
01406 fflush(session->ftp_stream);
01407 if (fgets(buff, FTP_MAX_CMDBUF, session->ftp_stream) == 0) {
01408 rc = -1;
01409 break;
01410 }
01411
01412
01413 if ((ch = *(buff + strlen(buff) - 1)) != '\n' && ch != '\r') {
01414 do {
01415 if (fgets(buff, FTP_MAX_CMDBUF, session->ftp_stream) == 0) {
01416 rc = -1;
01417 break;
01418 }
01419 } while ((ch = *(buff + strlen(buff) - 1)) != '\n' && ch != '\r');
01420 if (rc == 0) {
01421 rc = NutFtpRespondBad(session, 500);
01422 }
01423 }
01424
01425
01426 else {
01427 rc = NutFtpProcessRequest(session, buff);
01428 }
01429 }
01430
01431
01432 NutFtpCloseSession(session);
01433 free(buff);
01434 return rc;
01435 }
01436