📄 open.c
字号:
/* open.c
*
* Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft.
* All rights reserved.
*
*/
#include "syshdrs.h"
static void
FTPDeallocateHost(const FTPCIPtr cip)
{
/* Requires the cip->bufSize field set,
* and the cip->buf set if the
* buffer is allocated.
*/
if (cip->buf != NULL) {
(void) memset(cip->buf, 0, cip->bufSize);
free(cip->buf);
cip->buf = NULL;
}
if (cip->startingWorkingDirectory != NULL) {
free(cip->startingWorkingDirectory);
cip->startingWorkingDirectory = NULL;
}
#if USE_SIO
DisposeSReadlineInfo(&cip->ctrlSrl);
#endif
DisposeLineListContents(&cip->lastFTPCmdResultLL);
} /* FTPDeallocateHost */
static int
FTPAllocateHost(const FTPCIPtr cip)
{
char *buf;
/* Requires the cip->bufSize field set,
* and the cip->buf cleared if the
* buffer is not allocated.
*/
if (cip->buf == NULL) {
buf = (char *) calloc((size_t) 1, cip->bufSize);
if (buf == NULL) {
Error(cip, kDontPerror, "Malloc failed.\n");
cip->errNo = kErrMallocFailed;
return (kErrMallocFailed);
}
cip->buf = buf;
}
return (kNoErr);
} /* FTPAllocateHost */
void
FTPInitializeOurHostName(const FTPLIPtr lip)
{
if (lip == NULL)
return;
if (strcmp(lip->magic, kLibraryMagic))
return;
if (lip->htried == 0) {
(void) memset(lip->ourHostName, 0, sizeof(lip->ourHostName));
lip->hresult = GetOurHostName(lip->ourHostName, sizeof(lip->ourHostName));
}
lip->htried++;
} /* FTPInitializeOurHostName */
void
FTPInitializeAnonPassword(const FTPLIPtr lip)
{
if (lip == NULL)
return;
if (strcmp(lip->magic, kLibraryMagic))
return;
FTPInitializeOurHostName(lip);
if (lip->defaultAnonPassword[0] == '\0') {
#ifdef SPAM_PROBLEM_HAS_BEEN_SOLVED_FOREVER
GetUsrName(lip->defaultAnonPassword, sizeof(lip->defaultAnonPassword));
(void) STRNCAT(lip->defaultAnonPassword, "@");
/* Default to the "user@" notation
* supported by NcFTPd and wu-ftpd.
*/
if (lip->htried > 0)
(void) STRNCAT(lip->defaultAnonPassword, lip->ourHostName);
#else
(void) STRNCPY(lip->defaultAnonPassword, "NcFTP@");
#endif
}
} /* FTPInitializeAnonPassword */
int
FTPLoginHost(const FTPCIPtr cip)
{
ResponsePtr rp;
int result = kErrLoginFailed;
int anonLogin;
int sentpass = 0;
int fwloggedin;
int firstTime;
char cwd[512];
if (cip == NULL)
return (kErrBadParameter);
if ((cip->firewallType < kFirewallNotInUse) || (cip->firewallType > kFirewallLastType))
return (kErrBadParameter);
if (strcmp(cip->magic, kLibraryMagic))
return (kErrBadMagic);
anonLogin = 0;
if (cip->user[0] == '\0')
(void) STRNCPY(cip->user, "anonymous");
if ((strcmp(cip->user, "anonymous") == 0) || (strcmp(cip->user, "ftp") == 0)) {
anonLogin = 1;
/* Try to get the email address if you didn't specify
* a password when the user is anonymous.
*/
if (cip->pass[0] == '\0') {
FTPInitializeAnonPassword(cip->lip);
(void) STRNCPY(cip->pass, cip->lip->defaultAnonPassword);
}
}
rp = InitResponse();
if (rp == NULL) {
result = kErrMallocFailed;
cip->errNo = kErrMallocFailed;
goto done2;
}
for (firstTime = 1, fwloggedin = 0; ; ) {
/* Here's a mini finite-automaton for the login process.
*
* Originally, the FTP protocol was designed to be entirely
* implementable from a FA. It could be done, but I don't think
* it's something an interactive process could be the most
* effective with.
*/
if (firstTime != 0) {
rp->code = 220;
firstTime = 0;
} else if (result < 0) {
goto done;
}
switch (rp->code) {
case 220: /* Welcome, ready for new user. */
if ((cip->firewallType == kFirewallNotInUse) || (fwloggedin != 0)) {
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "USER %s", cip->user);
} else if (cip->firewallType == kFirewallUserAtSite) {
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "USER %s@%s", cip->user, cip->host);
} else if (cip->firewallType == kFirewallUserAtUserPassAtPass) {
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "USER %s@%s@%s", cip->user, cip->firewallUser, cip->host);
} else if (cip->firewallType == kFirewallUserAtSiteFwuPassFwp) {
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "USER %s@%s %s", cip->user, cip->host, cip->firewallUser);
} else if (cip->firewallType == kFirewallFwuAtSiteFwpUserPass) {
/* only reached when !fwloggedin */
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "USER %s@%s", cip->firewallUser, cip->host);
} else if (cip->firewallType > kFirewallNotInUse) {
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "USER %s", cip->firewallUser);
} else {
goto unknown;
}
break;
case 230: /* 230 User logged in, proceed. */
case 231: /* User name accepted. */
case 202: /* Command not implemented, superfluous at this site. */
if ((cip->firewallType == kFirewallNotInUse) || (fwloggedin != 0))
goto okay;
/* Now logged in to the firewall. */
fwloggedin++;
if (cip->firewallType == kFirewallLoginThenUserAtSite) {
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "USER %s@%s", cip->user, cip->host);
} else if (cip->firewallType == kFirewallUserAtUserPassAtPass) {
goto okay;
} else if (cip->firewallType == kFirewallOpenSite) {
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "OPEN %s", cip->host);
} else if (cip->firewallType == kFirewallSiteSite) {
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "SITE %s", cip->host);
} else if (cip->firewallType == kFirewallFwuAtSiteFwpUserPass) {
/* only reached when !fwloggedin */
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "USER %s", cip->user);
} else /* kFirewallUserAtSite */ {
goto okay;
}
break;
case 421: /* 421 Service not available, closing control connection. */
result = kErrHostDisconnectedDuringLogin;
goto done;
case 331: /* 331 User name okay, need password. */
if ((cip->firewallType == kFirewallNotInUse) || (fwloggedin != 0)) {
if ((cip->pass[0] == '\0') && (cip->passphraseProc != NoGetPassphraseProc))
(*cip->passphraseProc)(cip, &rp->msg, cip->pass, sizeof(cip->pass));
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "PASS %s", cip->pass);
} else if (cip->firewallType == kFirewallUserAtSite) {
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "PASS %s", cip->pass);
} else if (cip->firewallType == kFirewallUserAtUserPassAtPass) {
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "PASS %s@%s", cip->pass, cip->firewallPass);
} else if (cip->firewallType == kFirewallUserAtSiteFwuPassFwp) {
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "PASS %s", cip->pass);
} else if (cip->firewallType == kFirewallFwuAtSiteFwpUserPass) {
/* only reached when !fwloggedin */
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "PASS %s", cip->firewallPass);
} else if (cip->firewallType > kFirewallNotInUse) {
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "PASS %s", cip->firewallPass);
} else {
goto unknown;
}
sentpass++;
break;
case 332: /* 332 Need account for login. */
case 532: /* 532 Need account for storing files. */
if ((cip->firewallType == kFirewallNotInUse) || (fwloggedin != 0)) {
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "ACCT %s", cip->acct);
} else if (cip->firewallType == kFirewallUserAtSiteFwuPassFwp) {
ReInitResponse(cip, rp);
result = RCmd(cip, rp, "ACCT %s", cip->firewallPass);
} else {
/* ACCT not supported on firewall. */
goto unknown;
}
break;
case 530: /* Not logged in. */
result = (sentpass != 0) ? kErrBadRemoteUserOrPassword : kErrBadRemoteUser;
goto done;
case 501: /* Syntax error in parameters or arguments. */
case 503: /* Bad sequence of commands. */
case 550: /* Can't set guest privileges. */
goto done;
default:
unknown:
if (rp->msg.first == NULL) {
Error(cip, kDontPerror, "Lost connection during login.\n");
} else {
Error(cip, kDontPerror, "Unexpected response: %s\n",
rp->msg.first->line
);
}
goto done;
}
}
okay:
/* Do the application's connect message callback, if present. */
if (cip->onLoginMsgProc != 0)
(*cip->onLoginMsgProc)(cip, rp);
DoneWithResponse(cip, rp);
result = 0;
cip->loggedIn = 1;
/* Make a note of what our root directory is.
* This is often different from "/" when not
* logged in anonymously.
*/
if (cip->startingWorkingDirectory != NULL) {
free(cip->startingWorkingDirectory);
cip->startingWorkingDirectory = NULL;
}
if ((cip->doNotGetStartingWorkingDirectory == 0) &&
(FTPGetCWD(cip, cwd, sizeof(cwd)) == kNoErr))
{
cip->startingWorkingDirectory = StrDup(cwd);
}
/* When a new site is opened, ASCII mode is assumed (by protocol). */
cip->curTransferType = 'A';
PrintF(cip, "Logged in to %s as %s.\n", cip->host, cip->user);
/* Don't leave cleartext password in memory. */
if ((anonLogin == 0) && (cip->leavePass == 0))
(void) memset(cip->pass, '*', strlen(cip->pass));
if (result < 0)
cip->errNo = result;
return result;
done:
DoneWithResponse(cip, rp);
done2:
/* Don't leave cleartext password in memory. */
if ((anonLogin == 0) && (cip->leavePass == 0))
(void) memset(cip->pass, '*', strlen(cip->pass));
if (result < 0)
cip->errNo = result;
return result;
} /* FTPLoginHost */
static void
FTPExamineMlstFeatures(const FTPCIPtr cip, const char *features)
{
char buf[256], *feat;
int flags;
flags = 0;
STRNCPY(buf, features);
feat = strtok(buf, ";*");
while (feat != NULL) {
if (ISTRNEQ(feat, "OS.", 3))
feat += 3;
if (ISTREQ(feat, "type")) {
flags |= kMlsOptType;
} else if (ISTREQ(feat, "size")) {
flags |= kMlsOptSize;
} else if (ISTREQ(feat, "modify")) {
flags |= kMlsOptModify;
} else if (ISTREQ(feat, "UNIX.mode")) {
flags |= kMlsOptUNIXmode;
} else if (ISTREQ(feat, "UNIX.owner")) {
flags |= kMlsOptUNIXowner;
} else if (ISTREQ(feat, "UNIX.group")) {
flags |= kMlsOptUNIXgroup;
} else if (ISTREQ(feat, "perm")) {
flags |= kMlsOptPerm;
} else if (ISTREQ(feat, "UNIX.uid")) {
flags |= kMlsOptUNIXuid;
} else if (ISTREQ(feat, "UNIX.gid")) {
flags |= kMlsOptUNIXgid;
} else if (ISTREQ(feat, "UNIX.gid")) {
flags |= kMlsOptUnique;
}
feat = strtok(NULL, ";*");
}
cip->mlsFeatures = flags;
} /* FTPExamineMlstFeatures */
int
FTPQueryFeatures(const FTPCIPtr cip)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -