1#include "config.h"
2#include <stdio.h>
3#ifdef HAVE_CRYPT_H
4# include <crypt.h>
5#endif
6#include <string.h>
7#include <errno.h>
8#include <signal.h>
9#include <unistd.h>
10#ifdef HAVE_SYS_TIME_H
11# include <sys/time.h>
12#endif
13#include <time.h>
14#include <stdlib.h>
15
16#include "mystring.h"
17#include "options.h"
18#include "commands.h"
19#include "logging.h"
20#include "bftpdutmp.h"
21#include "login.h"
22
23FILE *mystatuslog;
24
25void loginfailed()
26{
27    control_printf(SL_FAILURE, "421 Login incorrect.");
28    bftpd_log("Administrative login FAILED\n");
29    /* Foxconn added start by Jenny Zhao, 06/10/2011 @USB log */
30    write_usb_fail_log();
31    /* Foxconn added end by Jenny Zhao, 06/10/2011 */
32    exit(1);
33}
34
35void command_adminlogin(char *params)
36{
37    char adminpass[31];
38    char rootpass[31];
39    char buffer[256];
40    char *realadminpass = config_getoption("ADMIN_PASS");
41    if (sscanf(params, "%30s %30s", adminpass, rootpass) < 2)
42        loginfailed();
43    if (!realadminpass[0])
44        loginfailed();
45    if (strcmp(crypt(adminpass, realadminpass), realadminpass))
46        loginfailed();
47    /* Admin password is right */
48    strcpy(user, "root");
49    init_userinfo();
50    if (checkpass(rootpass))
51        loginfailed();
52    /* Root password is right as well */
53    signal(SIGALRM, SIG_IGN);
54    control_printf(SL_SUCCESS, "230 Administrative login successful.");
55    bftpd_log("Administrative login SUCCESSFUL\n");
56    while (fgets(buffer, sizeof(buffer), stdin)) {
57        admin_parsecmd(buffer);
58    }
59    exit(0);
60}
61
62void command_admingetconf(char *params)
63{
64    control_printf(SL_FAILURE, "500 Not implemented yet.");
65}
66
67void command_adminlog(char *params)
68{
69    fd_set rfds;
70    struct timeval tv;
71    char buffer[256];
72    control_printf(SL_SUCCESS, "200 Starting logfile transmission.");
73    mystatuslog = statuslogforreading;
74    fseek(mystatuslog, 0, SEEK_END);
75    while (mystatuslog) {
76        while (fgets(buffer, sizeof(buffer), mystatuslog))
77            /* Don't use control_printf here, as it would generate an infinite loop */
78            fprintf(stderr, "%s", buffer);
79        FD_ZERO(&rfds);
80        FD_SET(0, &rfds);
81        tv.tv_sec = 1;
82        tv.tv_usec = 0;
83        if (select(1, &rfds, NULL, NULL, &tv) > 0) {
84            if (!fgets(buffer, sizeof(buffer), stdin))
85                exit(0);
86            admin_parsecmd(buffer);
87        }
88    }
89    control_printf(SL_SUCCESS, "202 Logfile transmission stopped.");
90}
91
92void command_adminstoplog(char *params)
93{
94    mystatuslog = NULL;
95    control_printf(SL_SUCCESS, "201 Stopping logfile transmission.");
96}
97
98void command_adminwho(char *params)
99{
100    struct bftpdutmp tmp;
101    fprintf(stderr, "200-User listing follows.\n");
102    fprintf(stderr, "200-PID       User           Host                Login time\n");
103    rewind(bftpdutmp);
104    while (fread((void *) &tmp, sizeof(tmp), 1, bftpdutmp)) {
105        if (!tmp.bu_type)
106            continue;
107        fprintf(stderr, "200-%-10i%-15s%-20s%s", tmp.bu_pid, tmp.bu_name, tmp.bu_host,
108                 ctime(&(tmp.bu_time)));
109    }
110    fprintf(stderr, "200 User listing finished.\n");
111}
112
113void command_adminkick(char *strpid)
114{
115    int pid = strtoul(strpid, NULL, 10);
116    if (!pid)
117        control_printf(SL_FAILURE, "500 Error: Given PID is not valid.");
118    else if (bftpdutmp_pidexists(pid)) {
119        if (kill(pid, SIGTERM))
120            control_printf(SL_FAILURE, "500 Error: %s.", strerror(errno));
121        else
122            control_printf(SL_FAILURE, "200 OK");
123    } else
124        control_printf(SL_FAILURE, "500 Error: The given PID does not belong to bftpd.");
125}
126
127void command_adminquit(char *params)
128{
129    control_printf(SL_SUCCESS, "221 See you later...");
130    exit(0);
131}
132
133const struct admin_command admin_commands[] = {
134    {"ADMIN_GETCONF", command_admingetconf},
135    {"ADMIN_LOG", command_adminlog},
136    {"ADMIN_STOPLOG", command_adminstoplog},
137    {"ADMIN_WHO", command_adminwho},
138    {"ADMIN_KICK", command_adminkick},
139    {"ADMIN_QUIT", command_adminquit},
140	{NULL, NULL}
141};
142
143int admin_parsecmd(char *str)
144{
145	int i;
146	char *p, *pp;
147	str[strlen(str) - 2] = '\0';	/* Remove \r\n */
148	p = pp = str;			/* Remove garbage in the string */
149	while (*p)
150		if ((unsigned char) *p < 32)
151			p++;
152		else
153			*pp++ = *p++;
154	*pp++ = 0;
155	for (i = 0; admin_commands[i].name; i++) {	/* Parse command */
156		if (!strncasecmp(str, admin_commands[i].name, strlen(admin_commands[i].name))) {
157			cutto(str, strlen(admin_commands[i].name));
158			p = str;
159			while ((*p) && ((*p == ' ') || (*p == '\t')))
160				p++;
161			memmove(str, p, strlen(str) - (p - str) + 1);
162			admin_commands[i].function(str);
163			return 0;
164		}
165	}
166	control_printf(SL_FAILURE, "500 Unknown command: \"%s\"", str);
167	return 1;
168}
169