1
1
// -*- mode: cpp; mode: fold -*-
2
2
// Description /*{{{*/
3
// $Id: ftp.cc,v 1.28 2001/05/22 04:02:00 jgg Exp $
3
// $Id: ftp.cc,v 1.31.2.1 2004/01/16 18:58:50 mdz Exp $
4
4
/* ######################################################################
6
6
FTP Aquire Method - This is the FTP aquire method for APT.
160
161
// Login must be before getpeername otherwise dante won't work.
161
Owner->Status("Logging in");
162
Owner->Status(_("Logging in"));
162
163
bool Res = Login();
164
165
// Get the remote server's address
165
166
PeerAddrLen = sizeof(PeerAddr);
166
167
if (getpeername(ServerFd,(sockaddr *)&PeerAddr,&PeerAddrLen) != 0)
167
return _error->Errno("getpeername","Unable to determine the peer name");
168
return _error->Errno("getpeername",_("Unable to determine the peer name"));
169
170
// Get the local machine's address
170
171
ServerAddrLen = sizeof(ServerAddr);
171
172
if (getsockname(ServerFd,(sockaddr *)&ServerAddr,&ServerAddrLen) != 0)
172
return _error->Errno("getsockname","Unable to determine the local name");
173
return _error->Errno("getsockname",_("Unable to determine the local name"));
200
201
if (ReadResp(Tag,Msg) == false)
203
return _error->Error("Server refused our connection and said: %s",Msg.c_str());
204
return _error->Error(_("The server refused the connection and said: %s"),Msg.c_str());
206
207
if (WriteMsg(Tag,Msg,"USER %s",User.c_str()) == false)
209
return _error->Error("USER failed, server said: %s",Msg.c_str());
210
return _error->Error(_("USER failed, server said: %s"),Msg.c_str());
212
if (WriteMsg(Tag,Msg,"PASS %s",Pass.c_str()) == false)
215
return _error->Error("PASS failed, server said: %s",Msg.c_str());
212
if (Tag == 331) { // 331 User name okay, need password.
214
if (WriteMsg(Tag,Msg,"PASS %s",Pass.c_str()) == false)
217
return _error->Error(_("PASS failed, server said: %s"),Msg.c_str());
217
220
// Enter passive mode
218
221
if (_config->Exists("Acquire::FTP::Passive::" + ServerName.Host) == true)
226
229
if (ReadResp(Tag,Msg) == false)
229
return _error->Error("Server refused our connection and said: %s",Msg.c_str());
232
return _error->Error(_("The server refused the connection and said: %s"),Msg.c_str());
231
234
// Perform proxy script execution
232
235
Configuration::Item const *Opts = _config->Tree("Acquire::ftp::ProxyLogin");
233
236
if (Opts == 0 || Opts->Child == 0)
234
return _error->Error("A proxy server was specified but no login "
235
"script, Acquire::ftp::ProxyLogin is empty.");
237
return _error->Error(_("A proxy server was specified but no login "
238
"script, Acquire::ftp::ProxyLogin is empty."));
236
239
Opts = Opts->Child;
238
241
// Iterate over the entire login script
259
262
if (WriteMsg(Tag,Msg,"%s",Tmp.c_str()) == false)
262
return _error->Error("Login script command '%s' failed, server said: %s",Tmp.c_str(),Msg.c_str());
265
return _error->Error(_("Login script command '%s' failed, server said: %s"),Tmp.c_str(),Msg.c_str());
265
268
// Enter passive mode
285
288
if (WriteMsg(Tag,Msg,"TYPE I") == false)
288
return _error->Error("TYPE failed, server said: %s",Msg.c_str());
291
return _error->Error(_("TYPE failed, server said: %s"),Msg.c_str());
323
326
if (WaitFd(ServerFd,false,TimeOut) == false)
326
return _error->Error("Connection timeout");
329
return _error->Error(_("Connection timeout"));
330
333
int Res = read(ServerFd,Buffer + Len,sizeof(Buffer) - Len);
332
_error->Error("Server closed the connection");
335
_error->Error(_("Server closed the connection"));
335
_error->Errno("read","Read error");
338
_error->Errno("read",_("Read error"));
342
return _error->Error("A response overflowed the buffer.");
345
return _error->Error(_("A response overflowed the buffer."));
345
348
// FTPConn::ReadResp - Read a full response from the server /*{{{*/
357
360
Ret = strtol(Msg.c_str(),&End,10);
358
361
if (End - Msg.c_str() != 3)
359
return _error->Error("Protocol corruption");
362
return _error->Error(_("Protocol corruption"));
362
365
Text = Msg.c_str()+4;
371
return _error->Error("Protocol corruption");
374
return _error->Error(_("Protocol corruption"));
373
376
/* Okay, here we do the continued message trick. This is foolish, but
374
377
proftpd follows the protocol as specified and wu-ftpd doesn't, so
434
437
if (WaitFd(ServerFd,true,TimeOut) == false)
437
return _error->Error("Connection timeout");
440
return _error->Error(_("Connection timeout"));
440
443
int Res = write(ServerFd,S + Start,Len);
443
_error->Errno("write","Write Error");
446
_error->Errno("write",_("Write error"));
682
685
if ((DataFd = socket(PasvAddr->ai_family,PasvAddr->ai_socktype,
683
686
PasvAddr->ai_protocol)) < 0)
684
return _error->Errno("socket","Could not create a socket");
687
return _error->Errno("socket",_("Could not create a socket"));
686
689
// Connect to the server
687
690
SetNonBlock(DataFd,true);
688
691
if (connect(DataFd,PasvAddr->ai_addr,PasvAddr->ai_addrlen) < 0 &&
689
692
errno != EINPROGRESS)
690
return _error->Errno("socket","Could not create a socket");
693
return _error->Errno("socket",_("Could not create a socket"));
692
695
/* This implements a timeout for connect by opening the connection
694
697
if (WaitFd(DataFd,true,TimeOut) == false)
695
return _error->Error("Could not connect data socket, connection timed out");
698
return _error->Error(_("Could not connect data socket, connection timed out"));
696
699
unsigned int Err;
697
700
unsigned int Len = sizeof(Err);
698
701
if (getsockopt(DataFd,SOL_SOCKET,SO_ERROR,&Err,&Len) != 0)
699
return _error->Errno("getsockopt","Failed");
702
return _error->Errno("getsockopt",_("Failed"));
701
return _error->Error("Could not connect passive socket.");
704
return _error->Error(_("Could not connect passive socket."));
716
719
Hints.ai_family = ((struct sockaddr *)&ServerAddr)->sa_family;
718
721
if ((Res = getaddrinfo(0,"0",&Hints,&BindAddr)) != 0)
719
return _error->Error("getaddrinfo was unable to get a listening socket");
722
return _error->Error(_("getaddrinfo was unable to get a listening socket"));
721
724
// Construct the socket
722
725
if ((DataListenFd = socket(BindAddr->ai_family,BindAddr->ai_socktype,
723
726
BindAddr->ai_protocol)) < 0)
725
728
freeaddrinfo(BindAddr);
726
return _error->Errno("socket","Could not create a socket");
729
return _error->Errno("socket",_("Could not create a socket"));
729
732
// Bind and listen
730
733
if (bind(DataListenFd,BindAddr->ai_addr,BindAddr->ai_addrlen) < 0)
732
735
freeaddrinfo(BindAddr);
733
return _error->Errno("bind","Could not bind a socket");
736
return _error->Errno("bind",_("Could not bind a socket"));
735
738
freeaddrinfo(BindAddr);
736
739
if (listen(DataListenFd,1) < 0)
737
return _error->Errno("listen","Could not listen on the socket");
740
return _error->Errno("listen",_("Could not listen on the socket"));
738
741
SetNonBlock(DataListenFd,true);
740
743
// Determine the name to send to the remote
741
744
struct sockaddr_storage Addr;
742
745
socklen_t AddrLen = sizeof(Addr);
743
746
if (getsockname(DataListenFd,(sockaddr *)&Addr,&AddrLen) < 0)
744
return _error->Errno("getsockname","Could not determine the socket's name");
747
return _error->Errno("getsockname",_("Could not determine the socket's name"));
746
750
// Reverse the address. We need the server address and the data port.
747
751
char Name[NI_MAXHOST];
782
786
if (AFMap[J].Family == ((struct sockaddr *)&Addr)->sa_family)
783
787
Proto = AFMap[J].IETFFamily;
785
return _error->Error("Unkonwn address family %u (AF_*)",
789
return _error->Error(_("Unknown address family %u (AF_*)"),
786
790
((struct sockaddr *)&Addr)->sa_family);
788
792
// Send the EPRT command
791
795
if (WriteMsg(Tag,Msg,"EPRT |%u|%s|%s|",Proto,Name,Service) == false)
794
return _error->Error("EPRT failed, server said: %s",Msg.c_str());
798
return _error->Error(_("EPRT failed, server said: %s"),Msg.c_str());
812
816
// Wait for someone to connect..
813
817
if (WaitFd(DataListenFd,false,TimeOut) == false)
814
return _error->Error("Data socket connect timed out");
818
return _error->Error(_("Data socket connect timed out"));
816
820
// Accept the connection
817
821
struct sockaddr_in Addr;
818
822
socklen_t Len = sizeof(Addr);
819
823
DataFd = accept(DataListenFd,(struct sockaddr *)&Addr,&Len);
821
return _error->Errno("accept","Unable to accept connection");
825
return _error->Errno("accept",_("Unable to accept connection"));
823
827
close(DataListenFd);
824
828
DataListenFd = -1;
858
862
if (Hash.AddFD(To.Fd(),Resume) == false)
860
_error->Errno("read","Problem hashing file");
864
_error->Errno("read",_("Problem hashing file"));
873
return _error->Error("Unable to fetch file, server said '%s'",Msg.c_str());
877
return _error->Error(_("Unable to fetch file, server said '%s'"),Msg.c_str());
876
880
// Finish off the data connection
915
919
if (ReadResp(Tag,Msg) == false)
918
return _error->Error("Data transfer failed, server said '%s'",Msg.c_str());
922
return _error->Error(_("Data transfer failed, server said '%s'"),Msg.c_str());
1095
1101
putenv("no_proxy=");
1097
1103
// Run the http method
1098
string Path = flNotFile(argv[0]) + "/http";
1104
string Path = flNotFile(argv[0]) + "http";
1099
1105
execl(Path.c_str(),Path.c_str(),0);
1100
cerr << "Unable to invoke " << Path << endl;
1106
cerr << _("Unable to invoke ") << Path << endl;