GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: main.c Lines: 85 86 98.8 %
Date: 2026-02-24 22:34:55 Branches: 25 50 50.0 %

Line Branch Exec Source
1
/*
2
* main.c
3
*
4
*  Created on: Aug 20, 2016
5
*
6
*  Modified on: Jun 06, 2018
7
*
8
*      Author: lightftp
9
*/
10
11
#include "ftpserv.h"
12
#include "cfgparse.h"
13
#include "x_malloc.h"
14
#include <signal.h>
15
#include <unistd.h>
16
17
FTP_CONFIG	g_cfg;
18
int			g_log = -1;
19
20
gnutls_dh_params_t					dh_params = NULL;
21
gnutls_certificate_credentials_t	x509_cred = NULL;
22
gnutls_priority_t					priority_cache = NULL;
23
24
static	char	CAFILE[PATH_MAX],
25
				CERTFILE[PATH_MAX],
26
				KEYFILE[PATH_MAX],
27
				KEYFILE_PASS[256];
28
29
80
void sig_handler(int signo)
30
{
31
80
  if (signo == SIGUSR1)
32
80
    exit(0);
33
}
34
35
670
void TLSInit()
36
{
37
670
	while (gnutls_global_init() >= 0)
38
	{
39
670
		if (gnutls_certificate_allocate_credentials(&x509_cred) < 0)
40
    		break;
41
42
670
    	if (gnutls_certificate_set_x509_trust_file(x509_cred, CAFILE,
43
    			GNUTLS_X509_FMT_PEM) < 0)
44
    		break;
45
46
670
    	if (gnutls_certificate_set_x509_key_file2(x509_cred, CERTFILE,
47
    			KEYFILE, GNUTLS_X509_FMT_PEM, KEYFILE_PASS, 0) < 0)
48
    		break;
49
50
670
    	if (gnutls_priority_init(&priority_cache, NULL, NULL) < 0)
51
    		break;
52
53
#if GNUTLS_VERSION_NUMBER >= 0x030506
54
670
    	gnutls_certificate_set_known_dh_params(x509_cred, GNUTLS_SEC_PARAM_HIGH);
55
#else
56
    	gnutls_dh_params_init(&dh_params);
57
    	gnutls_dh_params_generate2(dh_params,
58
    			gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_HIGH));
59
    	gnutls_certificate_set_dh_params(x509_cred, dh_params);
60
#endif
61
670
    	break;
62
    }
63
670
}
64
65
590
void TLSCleanup()
66
{
67
#if GNUTLS_VERSION_NUMBER < 0x030506
68
	if ( dh_params != NULL)
69
		gnutls_dh_params_deinit(dh_params);
70
#endif
71
72
590
	if ( x509_cred != NULL )
73
590
		gnutls_certificate_free_credentials(x509_cred);
74
75
590
	if ( priority_cache != NULL )
76
590
		gnutls_priority_deinit(priority_cache);
77
78
590
	gnutls_global_deinit();
79
590
}
80
81
670
int main(int argc, char *argv[])
82
{
83
	char		*cfg = NULL, *textbuf = NULL;
84
	int			c;
85
	uint32_t	bufsize = 65536;
86
	pthread_t	thid;
87
670
        signal(SIGUSR1, sig_handler);
88
	if (sizeof (off_t) != 8)
89
	{
90
		printf("off_t is not 64 bits long");
91
		return 0;
92
	}
93
94
670
	if (argc > 1)
95
670
		cfg = InitConfig(argv[1]);
96
	else
97
		cfg = InitConfig(CONFIG_FILE_NAME);
98
99
670
	while (cfg != NULL)
100
	{
101
670
		textbuf = x_malloc(bufsize);
102
103
670
		g_cfg.ConfigFile = cfg;
104
105
670
		g_cfg.BindToInterface = inet_addr("127.0.0.1");
106
670
		if (ParseConfig(cfg, CONFIG_SECTION_NAME, "interface", textbuf, bufsize))
107
670
			g_cfg.BindToInterface = inet_addr(textbuf);
108
109
670
		g_cfg.ExternalInterface = inet_addr("0.0.0.0");
110
670
		if (ParseConfig(cfg, CONFIG_SECTION_NAME, "external_ip", textbuf, bufsize))
111
670
			g_cfg.ExternalInterface = inet_addr(textbuf);
112
113
670
		g_cfg.LocalIPMask = inet_addr("255.255.255.0");
114
670
		if (ParseConfig(cfg, CONFIG_SECTION_NAME, "local_mask", textbuf, bufsize))
115
670
			g_cfg.LocalIPMask = inet_addr(textbuf);
116
117
		//g_cfg.Port = DEFAULT_FTP_PORT;
118
		//if (ParseConfig(cfg, CONFIG_SECTION_NAME, "port", textbuf, bufsize))
119
		//	g_cfg.Port = strtoul(textbuf, NULL, 10);
120
670
    g_cfg.Port = strtoul(argv[2], NULL, 10);
121
122
670
		g_cfg.MaxUsers = 1;
123
670
		if (ParseConfig(cfg, CONFIG_SECTION_NAME, "maxusers", textbuf, bufsize))
124
670
			g_cfg.MaxUsers = strtoul(textbuf, NULL, 10);
125
126
670
		g_cfg.PasvPortBase = 1024;
127
670
		if (ParseConfig(cfg, CONFIG_SECTION_NAME, "minport", textbuf, bufsize))
128
670
			g_cfg.PasvPortBase = strtoul(textbuf, NULL, 10);
129
130
670
		g_cfg.PasvPortMax = 65535;
131
670
		if (ParseConfig(cfg, CONFIG_SECTION_NAME, "maxport", textbuf, bufsize))
132
670
			g_cfg.PasvPortMax = strtoul(textbuf, NULL, 10);
133
134
670
		ParseConfig(cfg, CONFIG_SECTION_NAME, "CATrustFile", CAFILE, sizeof(CAFILE));
135
670
		ParseConfig(cfg, CONFIG_SECTION_NAME, "ServerCertificate", CERTFILE, sizeof(CERTFILE));
136
670
		ParseConfig(cfg, CONFIG_SECTION_NAME, "Keyfile", KEYFILE, sizeof(KEYFILE));
137
670
		ParseConfig(cfg, CONFIG_SECTION_NAME, "KeyfilePassword", KEYFILE_PASS, sizeof(KEYFILE_PASS));
138
139
		memset(textbuf, 0, bufsize);
140
670
		if (ParseConfig(cfg, CONFIG_SECTION_NAME, "logfilepath", textbuf, bufsize))
141
		{
142
670
			g_log = open(textbuf, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR);
143
670
			if (g_log == -1)
144
			{
145
				printf("Error: Failed to open/create log file. Please check logfilepath: %s\r\n", textbuf);
146
				printf("Possible errors: 1) path is invalid; 2) file is read only; 3) file is directory; 4) insufficient permissions\r\n");
147
				break;
148
			}
149
150
		} else
151
			printf("WARNING: logfilepath section is not found in configuration. Logging to file disabled.\r\n");
152
153
670
        if (g_log != -1)
154
670
            lseek(g_log, 0L, SEEK_END);
155
156
		printf("\r\n    [ LightFTP server v2.0 ]\r\n\r\n");
157
		printf("Log file        : %s\r\n", textbuf);
158
159
		getcwd(textbuf, bufsize);
160
		printf("Working dir     : %s\r\n", textbuf);
161
162
670
		if (argc > 1)
163
670
			printf("Config file     : %s\r\n", argv[1]);
164
		else
165
			printf("Config file     : %s/%s\r\n", textbuf, CONFIG_FILE_NAME);
166
167
670
		printf("Interface ipv4  : %u.%u.%u.%u\r\n",
168
				g_cfg.BindToInterface & 0xff,
169
670
				(g_cfg.BindToInterface >> 8) & 0xff,
170
670
				(g_cfg.BindToInterface >> 16) & 0xff,
171
670
				(g_cfg.BindToInterface >> 24) & 0xff);
172
173
670
		printf("Interface mask  : %u.%u.%u.%u\r\n",
174
				g_cfg.LocalIPMask & 0xff,
175
670
				(g_cfg.LocalIPMask >> 8) & 0xff,
176
670
				(g_cfg.LocalIPMask >> 16) & 0xff,
177
670
				(g_cfg.LocalIPMask >> 24) & 0xff);
178
179
670
		printf("External ipv4   : %u.%u.%u.%u\r\n",
180
				g_cfg.ExternalInterface & 0xff,
181
670
				(g_cfg.ExternalInterface >> 8) & 0xff,
182
670
				(g_cfg.ExternalInterface >> 16) & 0xff,
183
670
				(g_cfg.ExternalInterface >> 24) & 0xff);
184
185
670
		printf("Port            : %u\r\n", g_cfg.Port);
186
670
		printf("Max users       : %u\r\n", g_cfg.MaxUsers);
187
670
		printf("PASV port range : %u..%u\r\n", g_cfg.PasvPortBase, g_cfg.PasvPortMax);
188
189
		printf("\r\n TYPE q or Ctrl+C to terminate >\r\n");
190
191
670
		TLSInit();
192
193
670
		thid = (pthread_t)0;
194
670
		if (pthread_create(&thid, NULL, &ftpmain, NULL) != 0)
195
		{
196
			printf("Error: Failed to create main server thread\r\n");
197
			break;
198
		}
199
200
    //Terminate the server when the main thread terminates
201
670
		pthread_join(thid, NULL);
202
203
590
		break;
204
	}
205
206
590
    if (cfg == NULL)
207
		printf("Could not find configuration file\r\n\r\n Usage: fftp [CONFIGFILE]\r\n\r\n");
208
209
590
	if (g_log != -1)
210
590
        close(g_log);
211
212
590
	if (cfg != NULL)
213
590
		free(cfg);
214
215
590
	if (textbuf != NULL)
216
590
		free(textbuf);
217
218
590
	TLSCleanup();
219
220
590
	exit(2);
221
}