GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: main.c Lines: 85 86 98.8 %
Date: 2026-02-24 22:33:50 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
58
void sig_handler(int signo)
30
{
31
58
  if (signo == SIGUSR1)
32
58
    exit(0);
33
}
34
35
641
void TLSInit()
36
{
37
641
	while (gnutls_global_init() >= 0)
38
	{
39
641
		if (gnutls_certificate_allocate_credentials(&x509_cred) < 0)
40
    		break;
41
42
641
    	if (gnutls_certificate_set_x509_trust_file(x509_cred, CAFILE,
43
    			GNUTLS_X509_FMT_PEM) < 0)
44
    		break;
45
46
641
    	if (gnutls_certificate_set_x509_key_file2(x509_cred, CERTFILE,
47
    			KEYFILE, GNUTLS_X509_FMT_PEM, KEYFILE_PASS, 0) < 0)
48
    		break;
49
50
641
    	if (gnutls_priority_init(&priority_cache, NULL, NULL) < 0)
51
    		break;
52
53
#if GNUTLS_VERSION_NUMBER >= 0x030506
54
641
    	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
641
    	break;
62
    }
63
641
}
64
65
583
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
583
	if ( x509_cred != NULL )
73
583
		gnutls_certificate_free_credentials(x509_cred);
74
75
583
	if ( priority_cache != NULL )
76
583
		gnutls_priority_deinit(priority_cache);
77
78
583
	gnutls_global_deinit();
79
583
}
80
81
641
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
641
        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
641
	if (argc > 1)
95
641
		cfg = InitConfig(argv[1]);
96
	else
97
		cfg = InitConfig(CONFIG_FILE_NAME);
98
99
641
	while (cfg != NULL)
100
	{
101
641
		textbuf = x_malloc(bufsize);
102
103
641
		g_cfg.ConfigFile = cfg;
104
105
641
		g_cfg.BindToInterface = inet_addr("127.0.0.1");
106
641
		if (ParseConfig(cfg, CONFIG_SECTION_NAME, "interface", textbuf, bufsize))
107
641
			g_cfg.BindToInterface = inet_addr(textbuf);
108
109
641
		g_cfg.ExternalInterface = inet_addr("0.0.0.0");
110
641
		if (ParseConfig(cfg, CONFIG_SECTION_NAME, "external_ip", textbuf, bufsize))
111
641
			g_cfg.ExternalInterface = inet_addr(textbuf);
112
113
641
		g_cfg.LocalIPMask = inet_addr("255.255.255.0");
114
641
		if (ParseConfig(cfg, CONFIG_SECTION_NAME, "local_mask", textbuf, bufsize))
115
641
			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
641
    g_cfg.Port = strtoul(argv[2], NULL, 10);
121
122
641
		g_cfg.MaxUsers = 1;
123
641
		if (ParseConfig(cfg, CONFIG_SECTION_NAME, "maxusers", textbuf, bufsize))
124
641
			g_cfg.MaxUsers = strtoul(textbuf, NULL, 10);
125
126
641
		g_cfg.PasvPortBase = 1024;
127
641
		if (ParseConfig(cfg, CONFIG_SECTION_NAME, "minport", textbuf, bufsize))
128
641
			g_cfg.PasvPortBase = strtoul(textbuf, NULL, 10);
129
130
641
		g_cfg.PasvPortMax = 65535;
131
641
		if (ParseConfig(cfg, CONFIG_SECTION_NAME, "maxport", textbuf, bufsize))
132
641
			g_cfg.PasvPortMax = strtoul(textbuf, NULL, 10);
133
134
641
		ParseConfig(cfg, CONFIG_SECTION_NAME, "CATrustFile", CAFILE, sizeof(CAFILE));
135
641
		ParseConfig(cfg, CONFIG_SECTION_NAME, "ServerCertificate", CERTFILE, sizeof(CERTFILE));
136
641
		ParseConfig(cfg, CONFIG_SECTION_NAME, "Keyfile", KEYFILE, sizeof(KEYFILE));
137
641
		ParseConfig(cfg, CONFIG_SECTION_NAME, "KeyfilePassword", KEYFILE_PASS, sizeof(KEYFILE_PASS));
138
139
		memset(textbuf, 0, bufsize);
140
641
		if (ParseConfig(cfg, CONFIG_SECTION_NAME, "logfilepath", textbuf, bufsize))
141
		{
142
641
			g_log = open(textbuf, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR);
143
641
			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
641
        if (g_log != -1)
154
641
            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
641
		if (argc > 1)
163
641
			printf("Config file     : %s\r\n", argv[1]);
164
		else
165
			printf("Config file     : %s/%s\r\n", textbuf, CONFIG_FILE_NAME);
166
167
641
		printf("Interface ipv4  : %u.%u.%u.%u\r\n",
168
				g_cfg.BindToInterface & 0xff,
169
641
				(g_cfg.BindToInterface >> 8) & 0xff,
170
641
				(g_cfg.BindToInterface >> 16) & 0xff,
171
641
				(g_cfg.BindToInterface >> 24) & 0xff);
172
173
641
		printf("Interface mask  : %u.%u.%u.%u\r\n",
174
				g_cfg.LocalIPMask & 0xff,
175
641
				(g_cfg.LocalIPMask >> 8) & 0xff,
176
641
				(g_cfg.LocalIPMask >> 16) & 0xff,
177
641
				(g_cfg.LocalIPMask >> 24) & 0xff);
178
179
641
		printf("External ipv4   : %u.%u.%u.%u\r\n",
180
				g_cfg.ExternalInterface & 0xff,
181
641
				(g_cfg.ExternalInterface >> 8) & 0xff,
182
641
				(g_cfg.ExternalInterface >> 16) & 0xff,
183
641
				(g_cfg.ExternalInterface >> 24) & 0xff);
184
185
641
		printf("Port            : %u\r\n", g_cfg.Port);
186
641
		printf("Max users       : %u\r\n", g_cfg.MaxUsers);
187
641
		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
641
		TLSInit();
192
193
641
		thid = (pthread_t)0;
194
641
		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
641
		pthread_join(thid, NULL);
202
203
583
		break;
204
	}
205
206
583
    if (cfg == NULL)
207
		printf("Could not find configuration file\r\n\r\n Usage: fftp [CONFIGFILE]\r\n\r\n");
208
209
583
	if (g_log != -1)
210
583
        close(g_log);
211
212
583
	if (cfg != NULL)
213
583
		free(cfg);
214
215
583
	if (textbuf != NULL)
216
583
		free(textbuf);
217
218
583
	TLSCleanup();
219
220
583
	exit(2);
221
}