📄 ftpdlib.c
字号:
if (ftpsCurrentClients != 0) serverActive = TRUE; ftpsShutdownFlag = TRUE; pData = (FTPD_SESSION_DATA *)lstFirst (&ftpsSessionList); while (pData != NULL) { ftpdSockFree (&pData->cmdSock); pData = (FTPD_SESSION_DATA *)lstNext (&pData->node); } semGive (ftpsMutexSem); if (serverActive) { semTake (ftpsSignalSem, WAIT_FOREVER); } ftpdSockFree (&ftpdServerSock); lstFree (&ftpsSessionList); semDelete (ftpsMutexSem); semDelete (ftpsSignalSem); ftpsActive = FALSE; return (OK); }/********************************************************************************/LOCAL FTPD_SESSION_DATA *ftpdSessionAdd (void) { FAST FTPD_SESSION_DATA *pSlot; if (ftpsCurrentClients >= ftpsMaxClients) return (NULL); pSlot = (FTPD_SESSION_DATA *) calloc (sizeof (FTPD_SESSION_DATA), 1); if (pSlot == NULL) { return (NULL); } if (ftpdWindowSize < 0 || ftpdWindowSize > 65536) ftpdWindowSize = FTPD_WINDOW_SIZE; pSlot->bufSize = ftpdWindowSize ; ftpdDebugMsg ("allocating new session buffer %d bytes\n", pSlot->bufSize,0,0,0); pSlot->buf = malloc( pSlot->bufSize ); if( pSlot->buf == NULL ) { free(pSlot); return (NULL); } pSlot->dataSock = FTPD_SOCK_FREE; pSlot->cmdSock = FTPD_SOCK_FREE; pSlot->cmdSockError = OK; pSlot->status = FTPD_STREAM_MODE | FTPD_BINARY_TYPE | FTPD_NO_RECORD_STRU; pSlot->byteCount = 0; strcpy( pSlot->curDirName,"/tffs0/" ); semTake (ftpsMutexSem, WAIT_FOREVER); lstAdd (&ftpsSessionList, &pSlot->node); ftpdNumTasks++; ftpsCurrentClients++; semGive (ftpsMutexSem); return (pSlot); }/********************************************************************************/LOCAL void ftpdSessionDelete ( FAST FTPD_SESSION_DATA *pSlot ) { if (pSlot == NULL) /* null slot? don't do anything */ return; semTake (ftpsMutexSem, WAIT_FOREVER); --ftpdNumTasks; --ftpsCurrentClients; lstDelete (&ftpsSessionList, &pSlot->node); ftpdSockFree (&pSlot->cmdSock); /* release data and command sockets */ ftpdSockFree (&pSlot->dataSock); free (pSlot->buf); free (pSlot); if (ftpsShutdownFlag) { if (ftpsCurrentClients == 0) semGive (ftpsSignalSem); } semGive (ftpsMutexSem); return; }/********************************************************************************* ftpPathAccessVerify - verify client access to a path**/LOCAL STATUS ftpPathAccessVerify ( FTPD_SESSION_DATA *pSlot, char * path, int mode ) { char * where ; int len; /* allways allow access if not anonymous user */ if( (pSlot->status & FTPD_ANONYMOUS) == 0 ) return (OK); if( mode == O_RDONLY ) { where = guestHomeDir ; } else { where = writeDirName ; } len = strlen(where); if (*where==EOS||*path==EOS) goto deny; /* perform case-insensitive comparison a la strncmp() */ { FAST char *s1, *s2; FAST int i; for( s1 = where, s2 = path, i = 0; (*s1!=EOS && *s2!=EOS) && i<len; s1++, s2++, i-- ) { if(toupper(*s1) == toupper(*s2)) continue ; else goto deny; } } ftpdDebugMsg ("access mode %d allowed for path %s\n", mode, (int)path,0,0); return OK ;deny: ftpdDebugMsg ("access mode %d denied for path %s\n", mode, (int)path,0,0); return ERROR; }/********************************************************************************* ftpdPathForPrint - prepare a path to be printed to client**/LOCAL char * ftpdPathForPrint( FTPD_SESSION_DATA *pSlot, char * path ) { if( pSlot->status & FTPD_ANONYMOUS ) { int len = strlen( guestHomeDir ); if( strncmp( guestHomeDir, path, len) != 0) return NULL ; strcpy( path, path+len ); } return(path); }/***********************************************************************************/LOCAL void ftpPathNormalize ( FTPD_SESSION_DATA *pSlot, char * path, char * buffer, char ** pResult ) { if ( (strcmp(path,".") == 0) || (path[0] == EOS) ) { *pResult = &pSlot->curDirName [0]; return ; } (void) pathCat (pSlot->curDirName, path, buffer); pathCondense (buffer); /* condense ".." shit */ *pResult = buffer; }/********************************************************************************/LOCAL STATUS ftpdWorkTask ( FTPD_SESSION_DATA *pSlot /* pointer to the active slot to be handled */ ) { FAST int sock; FAST char *pBuf, *pBufEnd; struct sockaddr_in passiveAddr; char *dirName; FAST int numRead; int addrLen = sizeof (passiveAddr); int portNum [6]; u_long value; char renFile [MAX_FILENAME_LENGTH]; char newPath [MAX_FILENAME_LENGTH]; char *pFileName; FILE *outStream; char *upperCommand; pBuf = &pSlot->buf [0]; pBufEnd = pSlot->bufSize-1 + pBuf ; sock = pSlot->cmdSock; if (ftpsShutdownFlag) { ftpdCmdSend (pSlot, sock, 421, "Service not available, closing control connection", 0, 0, 0, 0, 0, 0); ftpdSessionDelete (pSlot); return (OK); } if (ftpdCmdSend (pSlot, sock, 220, messages [MSG_SERVER_READY], (int)vxWorksVersion, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; FOREVER { taskDelay (0); /* time share among same priority tasks */ if (pSlot->cmdSockError == ERROR) goto connectionLost; pSlot->byteCount = 0 ; (void) time( &pSlot->timeUsed ); if (ftpsShutdownFlag) break; bzero( pBuf, 8 ); FOREVER { taskDelay (0); if ((numRead = read (sock, pBuf, 1)) <= 0) { if (ftpsShutdownFlag) { *pBuf = EOS; break; } if (numRead == 0) ftpdCmdSend (pSlot, sock, 221, messages [MSG_NO_GOOD_BYE], 0, 0, 0, 0, 0, 0); ftpdSessionDelete (pSlot); return ERROR; } if ( *pBuf == '\r' ) continue; if (( *pBuf == '\n' ) || (pBuf == pBufEnd)) { *pBuf = EOS; break; } pBuf++; } /* FOREVER - read line */ pBuf = &pSlot->buf [0]; for (upperCommand = pBuf; (*upperCommand != ' ') && (*upperCommand != EOS); upperCommand++) *upperCommand = toupper (*upperCommand); ftpdDebugMsg ("read command %s\n", (int)pBuf,0,0,0); if (ftpsShutdownFlag) { ftpdCmdSend (pSlot, sock, 421, "Service not available, closing control connection", 0, 0, 0, 0, 0, 0); break; } if (strncmp (pBuf, "USER", 4) == 0) { if ( *(pBuf + 4) == '\0' ) pSlot->curUserName[0] = '\0'; else strncpy(pSlot->curUserName, pBuf+5, MAX_LOGIN_NAME_LEN); pSlot->status &= ~(FTPD_USER_OK | FTPD_ANONYMOUS); if( (strcmp(pSlot->curUserName, FTPD_ANONYMOUS_USER_1) ==0) || (strcmp(pSlot->curUserName, FTPD_ANONYMOUS_USER_2) ==0) || (strcmp(pSlot->curUserName, FTPD_ANONYMOUS_USER_3) ==0) ) { pSlot->status |= FTPD_ANONYMOUS ; /* tentative */ ftpdCmdSend (pSlot, sock, 331, messages [MSG_GUEST_PASS], 0, 0, 0, 0, 0, 0) ; continue; } if (ftpdCmdSend (pSlot, sock, 331, messages [MSG_PASSWORD_REQUIRED], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } else if (strncmp (pBuf, "PASS", 4) == 0) { if( pSlot->status & FTPD_ANONYMOUS ) { if( (guestHomeDir[0] == EOS) || (pBuf[5]==EOS) ) { ftpdCmdSend (pSlot, sock, 530, messages [MSG_USER_LOGIN_FAILED], 0, 0, 0, 0, 0, 0); continue; } pSlot->status |= FTPD_USER_OK; strcpy (pSlot->curDirName, guestHomeDir); if( guestHomeDir [ strlen(guestHomeDir) -1 ] != '/'); strcat(pSlot->curDirName, "/"); strcpy(newPath, writeDirName); if( writeDirName[0] == EOS ) ftpdCmdSend (pSlot, sock, 230, messages [MSG_GUEST_OK], 0, 0, 0, 0, 0, 0); else ftpdCmdSend (pSlot, sock, 230, messages [MSG_GUEST_UPLOAD_OK], (int) ftpdPathForPrint(pSlot, newPath), 0, 0, 0, 0, 0); continue; } if ( pLoginVrfyFunc != (FUNCPTR)NULL ) { ftpdDebugMsg ("Verifying login for user %s\n", (int)pSlot->curUserName,0,0,0); if ( (*pLoginVrfyFunc)(pSlot->curUserName, pBuf+5) != OK ) { if (ftpdCmdSend (pSlot, sock, 530, messages [MSG_USER_LOGIN_FAILED], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; pSlot->status &= ~FTPD_USER_OK; continue; } } else if( guestHomeDir[0] != EOS ) { if (ftpdCmdSend (pSlot, sock, 530, messages [MSG_USER_LOGIN_FAILED], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; pSlot->status &= ~FTPD_USER_OK; continue; } pSlot->status |= FTPD_USER_OK; if (ftpdCmdSend (pSlot, sock, 230, messages [MSG_USER_LOGGED_IN], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } else if (strncmp (pBuf, "QUIT", 4) == 0) { /* sayonara */ ftpdCmdSend (pSlot, sock, 221, messages [MSG_SEE_YOU_LATER], 0, 0, 0, 0, 0, 0); ftpdSessionDelete (pSlot); return OK; } else if (strncmp (pBuf, "SYST", 4) == 0) { ftpdCmdSend (pSlot, sock, 215, messages [MSG_SYST_REPLY], 0, 0, 0, 0, 0, 0); continue; } else if (strncmp (pBuf, "HELP", 4) == 0) { if (ftpdCmdSend (pSlot, sock, FTPD_MULTI_LINE | 214, messages [MSG_COMMAND_LIST_BEGIN], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; if (write (pSlot->cmdSock, ftpdCommandList, strlen (ftpdCommandList)) <= 0) goto connectionLost; if (ftpdCmdSend (pSlot, sock, 214, messages [MSG_COMMAND_LIST_END], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; /* All is well go wait for the next command */ } else if ((pSlot->status & FTPD_USER_OK) == 0) /* validated yet? */ { if (ftpdCmdSend (pSlot, sock, 530, messages [MSG_USER_PASS_REQ], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; /* do not proceed further until he's legit */ continue; } if (strncmp (pBuf, "LIST", 4) == 0 || strncmp (pBuf, "NLST", 4) == 0) { STATUS retVal; ftpPathNormalize ( pSlot, &pBuf[5], newPath, &dirName ); ftpdDebugMsg ("listing %s\n", (int)dirName,0,0,0); if( ftpPathAccessVerify(pSlot, dirName, O_RDONLY) == ERROR ) { if (ftpdCmdSend (pSlot, sock, 550, messages [MSG_GUEST_ACCESS], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } if (ftpdDataConnGet (pSlot) == ERROR) { if (ftpdCmdSend (pSlot, sock, 426, messages [MSG_DATA_CONN_ERROR], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; continue; } retVal = ftpdDirListGet (pSlot->dataSock, dirName, (strncmp (pBuf, "LIST", 4) == 0)); if (retVal == ERROR) { if (ftpdCmdSend (pSlot, sock, 550, messages [MSG_DIR_ERROR], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; } else { if (ftpdCmdSend (pSlot, sock, 226, messages [MSG_TRANS_COMPLETE], 0, 0, 0, 0, 0, 0) == ERROR) goto connectionLost; } ftpdSockFree (&pSlot->dataSock); } else if ( (strncmp (pBuf, "RETR", 4) == 0) || (strncmp (pBuf, "SIZE", 4) == 0) || (strncmp (pBuf, "MDTM", 4) == 0) ) { struct stat fileStat ; ftpPathNormalize ( pSlot, &pBuf[5], newPath, &pFileName );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -