VirtualBox

source: vbox/trunk/src/VBox/Runtime/generic/ftp-server.cpp@ 82665

Last change on this file since 82665 was 82665, checked in by vboxsync, 5 years ago

IPRT: First commit of FTP server code, along with a tool to run a standalone server. Work in progress. bugref:9437

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.3 KB
Line 
1/* $Id: ftp-server.cpp 82665 2020-01-08 09:32:19Z vboxsync $ */
2/** @file
3 * Generic FTP server (RFC 959) implementation.
4 */
5
6/*
7 * Copyright (C) 2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/**
28 * Known limitations so far:
29 * - UTF-8 support only.
30 * - No support for writing / modifying ("DELE", "MKD", "RMD", "STOR", ++).
31 * - No FTPS / SFTP support.
32 * - No passive mode ("PASV") support.
33 * - No proxy support.
34 * - No FXP support.
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_FTP
42#include <iprt/assert.h>
43#include <iprt/errcore.h>
44#include <iprt/ftp.h>
45#include <iprt/mem.h>
46#include <iprt/poll.h>
47#include <iprt/socket.h>
48#include <iprt/string.h>
49#include <iprt/tcp.h>
50
51#include "internal/magics.h"
52
53
54/*********************************************************************************************************************************
55* Structures and Typedefs *
56*********************************************************************************************************************************/
57/**
58 * Internal FTP server instance.
59 */
60typedef struct RTFTPSERVERINTERNAL
61{
62 /** Magic value. */
63 uint32_t u32Magic;
64 /** Pointer to TCP server instance. */
65 PRTTCPSERVER pTCPServer;
66} RTFTPSERVERINTERNAL;
67/** Pointer to an internal FTP server instance. */
68typedef RTFTPSERVERINTERNAL *PRTFTPSERVERINTERNAL;
69
70
71/*********************************************************************************************************************************
72* Defined Constants And Macros *
73*********************************************************************************************************************************/
74/** Validates a handle and returns VERR_INVALID_HANDLE if not valid. */
75#define RTFTPSERVER_VALID_RETURN_RC(hFTPServer, a_rc) \
76 do { \
77 AssertPtrReturn((hFTPServer), (a_rc)); \
78 AssertReturn((hFTPServer)->u32Magic == RTFTPSERVER_MAGIC, (a_rc)); \
79 } while (0)
80
81/** Validates a handle and returns VERR_INVALID_HANDLE if not valid. */
82#define RTFTPSERVER_VALID_RETURN(hFTPServer) RTFTPSERVER_VALID_RETURN_RC((hFTPServer), VERR_INVALID_HANDLE)
83
84/** Validates a handle and returns (void) if not valid. */
85#define RTFTPSERVER_VALID_RETURN_VOID(hFTPServer) \
86 do { \
87 AssertPtrReturnVoid(hFTPServer); \
88 AssertReturnVoid((hFTPServer)->u32Magic == RTFTPSERVER_MAGIC); \
89 } while (0)
90
91/** Supported FTP server command IDs.
92 * Alphabetically, named after their official command names. */
93typedef enum RTFTPSERVER_CMD
94{
95 /** Invalid command, do not use. Always must come first. */
96 RTFTPSERVER_CMD_INVALID = 0,
97 /** Aborts the current command on the server. */
98 RTFTPSERVER_CMD_ABOR,
99 /** Changes the current working directory. */
100 RTFTPSERVER_CMD_CDUP,
101 /** Changes the current working directory. */
102 RTFTPSERVER_CMD_CWD,
103 /** Lists a directory. */
104 RTFTPSERVER_CMD_LS,
105 /** Sends a nop ("no operation") to the server. */
106 RTFTPSERVER_CMD_NOOP,
107 /** Sets the password for authentication. */
108 RTFTPSERVER_CMD_PASS,
109 /** Gets the current working directory. */
110 RTFTPSERVER_CMD_PWD,
111 /** Terminates the session (connection). */
112 RTFTPSERVER_CMD_QUIT,
113 /** Retrieves a specific file. */
114 RTFTPSERVER_CMD_RETR,
115 /** Recursively gets a directory (and its contents). */
116 RTFTPSERVER_CMD_RGET,
117 /** Retrieves the current status of a transfer. */
118 RTFTPSERVER_CMD_STAT,
119 /** Sets the (data) representation type. */
120 RTFTPSERVER_CMD_TYPE,
121 /** Sets the user name for authentication. */
122 RTFTPSERVER_CMD_USER,
123 /** The usual 32-bit hack. */
124 RTFTPSERVER_CMD_32BIT_HACK = 0x7fffffff
125} RTFTPSERVER_CMD;
126
127/**
128 * Structure for maintaining an internal FTP server client state.
129 */
130typedef struct RTFTPSERVERCLIENTSTATE
131{
132 /** Pointer to internal server state. */
133 PRTFTPSERVERINTERNAL pServer;
134 /** Socket handle the client is bound to. */
135 RTSOCKET hSocket;
136} RTFTPSERVERCLIENTSTATE;
137/** Pointer to an internal FTP server client state. */
138typedef RTFTPSERVERCLIENTSTATE *PRTFTPSERVERCLIENTSTATE;
139
140
141static 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);
149
150 return rc;
151}
152
153static int rtFTPServerDoLogin(PRTFTPSERVERCLIENTSTATE pClient)
154{
155 int rc = rtFTPServerSendReply(pClient, RTFTPSERVER_REPLY_READY_FOR_NEW_USER);
156
157 return rc;
158}
159
160static DECLCALLBACK(int) rtFTPServerThread(RTSOCKET hSocket, void *pvUser)
161{
162 PRTFTPSERVERINTERNAL pThis = (PRTFTPSERVERINTERNAL)pvUser;
163 RTFTPSERVER_VALID_RETURN(pThis);
164
165 RTFTPSERVERCLIENTSTATE ClientState;
166 RT_ZERO(ClientState);
167
168 ClientState.pServer = pThis;
169 ClientState.hSocket = hSocket;
170
171 int rc = rtFTPServerDoLogin(&ClientState);
172
173 return rc;
174}
175
176RTR3DECL(int) RTFTPServerCreate(PRTFTPSERVER phFTPServer, const char *pcszAddress, uint16_t uPort,
177 const char *pcszPathRoot)
178{
179 AssertPtrReturn(phFTPServer, VERR_INVALID_POINTER);
180 AssertPtrReturn(pcszAddress, VERR_INVALID_POINTER);
181 AssertPtrReturn(pcszPathRoot, VERR_INVALID_POINTER);
182 AssertReturn (uPort, VERR_INVALID_PARAMETER);
183
184 int rc;
185
186 PRTFTPSERVERINTERNAL pThis = (PRTFTPSERVERINTERNAL)RTMemAllocZ(sizeof(RTFTPSERVERINTERNAL));
187 if (pThis)
188 {
189 rc = RTTcpServerCreate(pcszAddress, uPort, RTTHREADTYPE_DEFAULT, "ftpsrv",
190 rtFTPServerThread, pThis /* pvUser */, &pThis->pTCPServer);
191 }
192 else
193 rc = VERR_NO_MEMORY;
194
195 return rc;
196}
197
198RTR3DECL(int) RTFTPServerDestroy(RTFTPSERVER hFTPServer)
199{
200 if (hFTPServer == NIL_RTFTPSERVER)
201 return VINF_SUCCESS;
202
203 PRTFTPSERVERINTERNAL pThis = hFTPServer;
204 RTFTPSERVER_VALID_RETURN(pThis);
205
206 AssertPtr(pThis->pTCPServer);
207
208 int rc = RTTcpServerDestroy(pThis->pTCPServer);
209 if (RT_SUCCESS(rc))
210 {
211 pThis->u32Magic = RTFTPSERVER_MAGIC_DEAD;
212
213 RTMemFree(pThis);
214 }
215
216 return rc;
217}
218
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette