Changeset 82673 in vbox for trunk/src/VBox/Runtime/generic/ftp-server.cpp
- Timestamp:
- Jan 8, 2020 4:19:35 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/generic/ftp-server.cpp
r82665 r82673 44 44 #include <iprt/ftp.h> 45 45 #include <iprt/mem.h> 46 #include <iprt/log.h> 46 47 #include <iprt/poll.h> 47 48 #include <iprt/socket.h> 48 49 #include <iprt/string.h> 50 #include <iprt/system.h> 49 51 #include <iprt/tcp.h> 50 52 … … 102 104 RTFTPSERVER_CMD_CWD, 103 105 /** Lists a directory. */ 104 RTFTPSERVER_CMD_LS, 106 RTFTPSERVER_CMD_LIST, 107 /** Sets the transfer mode. */ 108 RTFTPSERVER_CMD_MODE, 105 109 /** Sends a nop ("no operation") to the server. */ 106 110 RTFTPSERVER_CMD_NOOP, 107 111 /** Sets the password for authentication. */ 108 112 RTFTPSERVER_CMD_PASS, 113 /** Sets the port to use for the data connection. */ 114 RTFTPSERVER_CMD_PORT, 109 115 /** Gets the current working directory. */ 110 116 RTFTPSERVER_CMD_PWD, … … 117 123 /** Retrieves the current status of a transfer. */ 118 124 RTFTPSERVER_CMD_STAT, 125 /** Gets the server's OS info. */ 126 RTFTPSERVER_CMD_SYST, 119 127 /** Sets the (data) representation type. */ 120 128 RTFTPSERVER_CMD_TYPE, 121 129 /** Sets the user name for authentication. */ 122 130 RTFTPSERVER_CMD_USER, 131 /** End marker. */ 132 RTFTPSERVER_CMD_LAST, 123 133 /** The usual 32-bit hack. */ 124 134 RTFTPSERVER_CMD_32BIT_HACK = 0x7fffffff … … 138 148 typedef RTFTPSERVERCLIENTSTATE *PRTFTPSERVERCLIENTSTATE; 139 149 140 141 static int rtFTPServerSendReply(PRTFTPSERVERCLIENTSTATE pClient, RTFTPSERVER_REPLY enmReply) 142 { 143 RT_NOREF(enmReply); 144 145 RTTcpWrite(pClient->hSocket, "hello\n", sizeof("hello\n") - 1); 146 147 int rc = 0; 148 RT_NOREF(rc); 150 typedef DECLCALLBACK(int) FNRTFTPSERVERCMD(PRTFTPSERVERCLIENTSTATE pClient); 151 /** Pointer to a FNRTFTPSERVERCMD(). */ 152 typedef FNRTFTPSERVERCMD *PFNRTFTPSERVERCMD; 153 154 static FNRTFTPSERVERCMD rtFTPServerHandleSYST; 155 156 typedef struct RTFTPSERVER_CMD_ENTRY 157 { 158 RTFTPSERVER_CMD enmCmd; 159 char szCmd[RTFTPSERVER_MAX_CMD_LEN]; 160 PFNRTFTPSERVERCMD pfnCmd; 161 } RTFTPSERVER_CMD_ENTRY; 162 163 const RTFTPSERVER_CMD_ENTRY g_aCmdMap[] = 164 { 165 { RTFTPSERVER_CMD_SYST, "SYST", rtFTPServerHandleSYST }, 166 { RTFTPSERVER_CMD_LAST, "", NULL } 167 }; 168 169 170 static int rtFTPServerSendReplyRc(PRTFTPSERVERCLIENTSTATE pClient, RTFTPSERVER_REPLY enmReply) 171 { 172 char szReply[32]; 173 RTStrPrintf2(szReply, sizeof(szReply), "%RU32\r\n", enmReply); 174 175 return RTTcpWrite(pClient->hSocket, szReply, strlen(szReply) + 1); 176 } 177 178 static int rtFTPServerSendReplyStr(PRTFTPSERVERCLIENTSTATE pClient, const char *pcszStr) 179 { 180 char *pszReply; 181 int rc = RTStrAPrintf(&pszReply, "%s\r\n", pcszStr); 182 if (RT_SUCCESS(rc)) 183 { 184 rc = RTTcpWrite(pClient->hSocket, pszReply, strlen(pszReply) + 1); 185 RTStrFree(pszReply); 186 return rc; 187 } 188 189 return VERR_NO_MEMORY; 190 } 191 192 static int rtFTPServerLookupUser(PRTFTPSERVERCLIENTSTATE pClient, const char *pcszUser) 193 { 194 RT_NOREF(pClient, pcszUser); 195 196 LogFunc(("User='%s'\n", pcszUser)); 197 198 return VINF_SUCCESS; /** @todo Implement lookup. */ 199 } 200 201 static int rtFTPServerAuthenticate(PRTFTPSERVERCLIENTSTATE pClient, const char *pcszUser, const char *pcszPassword) 202 { 203 RT_NOREF(pClient, pcszUser, pcszPassword); 204 205 LogFunc(("User='%s', Password='%s'\n", pcszUser, pcszPassword)); 206 207 return VINF_SUCCESS; /** @todo Implement authentication. */ 208 } 209 210 static int rtFTPServerHandleSYST(PRTFTPSERVERCLIENTSTATE pClient) 211 { 212 char szOSInfo[64]; 213 int rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szOSInfo, sizeof(szOSInfo)); 214 if (RT_SUCCESS(rc)) 215 rc = rtFTPServerSendReplyStr(pClient, szOSInfo); 149 216 150 217 return rc; … … 153 220 static int rtFTPServerDoLogin(PRTFTPSERVERCLIENTSTATE pClient) 154 221 { 155 int rc = rtFTPServerSendReply(pClient, RTFTPSERVER_REPLY_READY_FOR_NEW_USER); 222 LogFlowFuncEnter(); 223 224 /* Send welcome message. */ 225 int rc = rtFTPServerSendReplyRc(pClient, RTFTPSERVER_REPLY_READY_FOR_NEW_USER); 226 if (RT_SUCCESS(rc)) 227 { 228 size_t cbRead; 229 230 char szUser[64]; 231 rc = RTTcpRead(pClient->hSocket, szUser, sizeof(szUser), &cbRead); 232 if (RT_SUCCESS(rc)) 233 { 234 rc = rtFTPServerLookupUser(pClient, szUser); 235 if (RT_SUCCESS(rc)) 236 { 237 rc = rtFTPServerSendReplyRc(pClient, RTFTPSERVER_REPLY_USERNAME_OKAY_NEED_PASSWORD); 238 if (RT_SUCCESS(rc)) 239 { 240 char szPass[64]; 241 rc = RTTcpRead(pClient->hSocket, szPass, sizeof(szPass), &cbRead); 242 { 243 if (RT_SUCCESS(rc)) 244 { 245 rc = rtFTPServerAuthenticate(pClient, szUser, szPass); 246 if (RT_SUCCESS(rc)) 247 { 248 rc = rtFTPServerSendReplyRc(pClient, RTFTPSERVER_REPLY_LOGGED_IN_PROCEED); 249 } 250 } 251 } 252 } 253 } 254 } 255 } 256 257 if (RT_FAILURE(rc)) 258 { 259 int rc2 = rtFTPServerSendReplyRc(pClient, RTFTPSERVER_REPLY_NOT_LOGGED_IN); 260 if (RT_SUCCESS(rc)) 261 rc = rc2; 262 } 263 264 return rc; 265 } 266 267 static int rtFTPServerProcessCommands(PRTFTPSERVERCLIENTSTATE pClient) 268 { 269 int rc; 270 271 for (;;) 272 { 273 size_t cbRead; 274 char szCmd[RTFTPSERVER_MAX_CMD_LEN]; 275 rc = RTTcpRead(pClient->hSocket, szCmd, sizeof(szCmd), &cbRead); 276 if ( RT_SUCCESS(rc) 277 && strlen(szCmd)) 278 { 279 /* A tiny bit of sanitation. */ 280 RTStrStripL(szCmd); 281 282 /* First, terminate string by finding the command end marker (telnet style). */ 283 /** @todo Not sure if this is entirely correct and/or needs tweaking; good enough for now as it seems. */ 284 char *pszCmdEnd = RTStrIStr(szCmd, "\r\n"); 285 if (pszCmdEnd) 286 *pszCmdEnd = '\0'; 287 288 /* Second, determine if there is any parameters following. */ 289 char *pszCmdParms = RTStrIStr(szCmd, " "); 290 /* pszCmdParms can be NULL if command has not parameters. */ 291 RT_NOREF(pszCmdParms); 292 293 unsigned i = 0; 294 for (; i < RT_ELEMENTS(g_aCmdMap); i++) 295 { 296 if (!RTStrICmp(szCmd, g_aCmdMap[i].szCmd)) 297 { 298 rc = g_aCmdMap[i].pfnCmd(pClient); 299 break; 300 } 301 } 302 303 if (i == RT_ELEMENTS(g_aCmdMap)) 304 { 305 int rc2 = rtFTPServerSendReplyRc(pClient, RTFTPSERVER_REPLY_ERROR_CMD_NOT_IMPL); 306 if (RT_SUCCESS(rc)) 307 rc = rc2; 308 } 309 } 310 else 311 { 312 int rc2 = rtFTPServerSendReplyRc(pClient, RTFTPSERVER_REPLY_ERROR_CMD_NOT_RECOGNIZED); 313 if (RT_SUCCESS(rc)) 314 rc = rc2; 315 } 316 } 156 317 157 318 return rc; … … 170 331 171 332 int rc = rtFTPServerDoLogin(&ClientState); 333 if (RT_SUCCESS(rc)) 334 rc = rtFTPServerProcessCommands(&ClientState); 172 335 173 336 return rc; … … 187 350 if (pThis) 188 351 { 352 pThis->u32Magic = RTFTPSERVER_MAGIC; 353 189 354 rc = RTTcpServerCreate(pcszAddress, uPort, RTTHREADTYPE_DEFAULT, "ftpsrv", 190 355 rtFTPServerThread, pThis /* pvUser */, &pThis->pTCPServer);
Note:
See TracChangeset
for help on using the changeset viewer.