/*****************************************************************************\
* Copyright (c) 2002 Pelle Johansson. *
* All rights reserved. *
* *
* This file is part of the moftpd package. Use and distribution of *
* this software is governed by the terms in the file LICENCE, which *
* should have come with this package. *
\*****************************************************************************/
/* $moftpd: com_misc.c 1251 2005-03-06 22:24:29Z morth $ */
#include "system.h"
#include "commands.h"
#include "connection.h"
#include "utf8fs/memory.h"
#include "accounter.h"
extern command_t siteCommands[];
/* Miscellaneous commands */
int command_abor(connection_t *conn, const char *arg, int expected)
{
switch (close_data_connection (conn))
{
case -1:
return 1;
case 0:
reply (conn, "226 Abort successful.");
return 0;
default:
reply (conn, "426 Data connection closed.");
reply (conn, "226 Abort successful.");
return 0;
}
}
int command_site (connection_t *conn, const char *arg, int expected)
{
const char *narg, *cname;
command_t *cmd;
narg = strchr (arg, ' ');
if (narg)
{
cname = talloc (narg - arg + 1);
if (!cname)
{
reply (conn, "500 %s", strerror (errno));
return 0;
}
strncpy ((char*)cname, arg, narg++ - arg);
}
else
{
cname = arg;
narg = "";
}
if (!strlen (cname))
{
reply (conn, "500 Need a command name.");
return 0;
}
for (cmd = siteCommands; cmd->name; cmd++)
{
if (!strcasecmp(cmd->name, cname))
{
if (conn->working && !cmd->whileWorking)
reply (conn, "500 Please wait until the server is ready.");
else if (!conn->authed && !cmd->unauthed)
reply(conn, "503 Please login.");
else if (cmd->handler (conn, narg, expected))
return 1;
break;
}
}
if (!cmd->name)
reply(conn, "500 No such command SITE %s.", cname);
return 0;
}
int command_noop(connection_t *conn, const char *arg, int expected)
{
reply(conn, "200 No action taken.");
return 0;
}
int command_host (connection_t *conn, const char *arg, int expected)
{
struct sockaddr_storage lAddr, rAddr;
server_t *serv;
int l;
if (conn->inLookUp || conn->authed
#ifdef USE_TLS
|| conn->tlsControl
#endif
)
{
reply (conn, "503 Too late to switch host, please connect again.");
return 0;
}
l = sizeof(lAddr);
getsockname(conn->sock, (struct sockaddr*)&lAddr, &l);
l = sizeof(rAddr);
getpeername(conn->sock, (struct sockaddr*)&rAddr, &l);
if (!arg[0])
{
reply (conn, "200-You can connect to these hosts (* = current):");
serv = NULL;
while ((serv = find_server ((struct sockaddr*)&lAddr, (struct sockaddr*)&rAddr, serv)))
{
if (serv == conn->server)
reply (conn, " %s*", serv->name);
else
reply (conn, " %s", serv->name);
}
reply (conn, "200 End of hosts.");
return 0;
}
serv = find_named_server (arg, 0, (struct sockaddr*)&rAddr, NULL);
if (serv)
{
int i, port = -1;
if (serv == conn->server)
{
reply (conn, "220 Already at %s.", serv->name);
return 0;
}
switch(lAddr.ss_family)
{
case AF_INET:
port = ntohs (((struct sockaddr_in*)&lAddr)->sin_port);
break;
case AF_INET6:
port = ntohs (((struct sockaddr_in6*)&lAddr)->sin6_port);
break;
}
for(i = 0; i < serv->numPorts; i++)
if(serv->ports[i] == port)
break;
if (i < serv->numPorts)
{
char rhost[NI_MAXHOST];
if (getnameinfo ((struct sockaddr*)&rAddr, l, rhost, sizeof (rhost), NULL,
0, NI_NUMERICHOST))
strcpy (rhost, "unknown");
if (accounter (conn->accSock, "CONNECT %s %s\n", rhost, serv->name))
{
syslog (LOG_ERR, "%d: Error in acocunter: %m", conn->id);
reply (conn, "500 Error: %s.", strerror (errno));
}
else
{
conn->oldserver = conn->server;
conn->server = pattach (serv, conn);
syslog (LOG_INFO, "%d: Switching to %s.", conn->id, conn->server->name);
conn->accWait = acWelcome;
}
return 0;
}
}
reply (conn, "500 No such host.");
return 0;
}
int sitecommand_admin (connection_t *conn, const char *arg, int expected)
{
char buf[4097];
int i;
buf[0] = i = 0;
if (!strcasecmp (arg, "LIST"))
{
if (conn->user->adminPrivs & admList)
{
if (accounter (conn->accSock, "LIST\n"))
reply (conn, "500 %s.", strerror (errno));
else
{
reply (conn, "200-Connections (id: pid ip server user account email action):");
conn->accWait = acList;
}
return 0;
}
}
else if (!strncasecmp (arg, "MSG ", 4))
{
if (conn->user->adminPrivs & admMsg)
{
if (sscanf (arg + 4, "%d %[^\n]", &i, buf) < 2)
reply (conn, "501 Not enough arguments.");
else if (accounter (conn->accSock, "MSG %d %s\n", i, buf))
reply (conn, "500 %s.", strerror (errno));
else
conn->accWait = acMsg;
return 0;
}
}
else if (!strncasecmp (arg, "MSGALL ", 7))
{
if (conn->user->adminPrivs & admMsg)
{
if (sscanf (arg + 7, "%[^\n]", buf) < 1)
reply (conn, "501 Not enough arguments.");
else if (accounter (conn->accSock, "MSGALL %s\n", buf))
reply (conn, "500 %s.", strerror (errno));
else
conn->accWait = acMsg;
return 0;
}
}
else if (!strncasecmp (arg, "ABORT ", 6))
{
if (conn->user->adminPrivs & admAbort)
{
if (sscanf (arg + 6, "%d %[^\n]", &i, buf) < 1)
reply (conn, "501 Not enough arguments.");
else if (accounter (conn->accSock, "ABORT %d %s\n", i, buf))
reply (conn, "500 %s.", strerror (errno));
else
conn->accWait = acAbort;
return 0;
}
}
else if (!strncasecmp (arg, "DISCONNECT ", 11))
{
if (conn->user->adminPrivs & admDisconnect)
{
if (sscanf (arg + 11, "%d %[^\n]", &i, buf) < 1)
reply (conn, "501 Not enough arguments.");
else if (accounter (conn->accSock, "DISCONNECT %d %s\n", i, buf))
reply (conn, "500 %s.", strerror (errno));
else
conn->accWait = acDisconnect;
return 0;
}
}
else if (!strncasecmp (arg, "DISCABORT ", 10))
{
if ((conn->user->adminPrivs & (admDisconnect | admAbort)) == (admDisconnect | admAbort))
{
if (sscanf (arg + 10, "%d %[^\n]", &i, buf) < 1)
reply (conn, "501 Not enough arguments.");
else if (accounter (conn->accSock, "DISCABORT %d %s\n", i, buf))
reply (conn, "500 %s.", strerror (errno));
else
conn->accWait = acDisconnect;
return 0;
}
}
else if (!strcasecmp (arg, "RELOAD"))
{
if (conn->user->adminPrivs & admReload)
{
if (accounter (conn->accSock, "RELOAD\n"))
reply (conn, "500 %s.", strerror (errno));
else
reply (conn, "200 Reloading configuration file.");
return 0;
}
}
else
{
reply (conn, "500 Unknown admin command %s.", arg);
return 0;
}
reply (conn, "500 Access denied.");
syslog (LOG_NOTICE, "%d: No access to SITE ADMIN %s", conn->id, arg);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1