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