Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 157005 | Differences between
and this patch

Collapse All | Expand All

(-)oftpd-0.3.7.orig/src/Makefile.am (-1 / +1 lines)
Lines 1-2 Link Here
1
bin_PROGRAMS = oftpd
1
bin_PROGRAMS = oftpd
2
oftpd_SOURCES = file_list.c file_list.h ftp_command.c ftp_command.h ftp_listener.c ftp_listener.h ftp_session.c ftp_session.h oftpd.c oftpd.h telnet_session.c telnet_session.h watchdog.c watchdog.h error.c error.h af_portability.h daemon_assert.c daemon_assert.h
2
oftpd_SOURCES = file_list.c file_list.h ftp_command.c ftp_command.h ftp_listener.c ftp_listener.h ftp_session.c ftp_session.h oftpd.c oftpd.h telnet_session.c telnet_session.h watchdog.c watchdog.h error.c error.h af_portability.h af_portability.c daemon_assert.c daemon_assert.h
(-)oftpd-0.3.7.orig/src/af_portability.c (+32 lines)
Line 0 Link Here
1
#include <stdlib.h>
2
#include <netdb.h>
3
#include <netinet/in.h>
4
5
unsigned short int sockaddr_port(const struct sockaddr *sa, socklen_t salen)
6
{
7
#ifdef INET6
8
	char sbuf[NI_MAXSERV];
9
#endif
10
	unsigned short int port = 0; 
11
12
#ifdef INET6
13
	if (getnameinfo(sa, salen, NULL, 0, sbuf, sizeof(sbuf),
14
			NI_NUMERICSERV) == 0)
15
		port = atoi(sbuf);
16
	else
17
#endif
18
	        switch (sa->sa_family) {
19
		case AF_INET:
20
			port = ntohs(((struct sockaddr_in *)sa)->sin_port);
21
			break;
22
#ifdef INET6
23
		case AF_INET6:
24
			port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
25
			break;
26
#endif
27
		default: 
28
			/* everything went wrong :-P */
29
			exit(1);
30
		}
31
	return port;
32
}                                                                                                             
(-)oftpd-0.3.7.orig/src/af_portability.h (-2 / +5 lines)
Lines 2-11 Link Here
2
#define AF_PORTABILITY_H
2
#define AF_PORTABILITY_H
3
3
4
#include <netinet/in.h>
4
#include <netinet/in.h>
5
#include <sys/socket.h>
6
5
7
/* _x_ must be a pointer to a sockaddr structure */
6
/* _x_ must be a pointer to a sockaddr structure */
8
7
/*
9
#define SAFAM(_x_)	(((struct sockaddr *)(_x_))->sa_family)
8
#define SAFAM(_x_)	(((struct sockaddr *)(_x_))->sa_family)
10
9
11
#ifdef HAVE_NEW_SS_FAMILY
10
#ifdef HAVE_NEW_SS_FAMILY
Lines 26-31 Link Here
26
#define SINADDR(_x_)    SIN4ADDR(_x_)
25
#define SINADDR(_x_)    SIN4ADDR(_x_)
27
#define SINPORT(_x_)    SIN4PORT(_x_)
26
#define SINPORT(_x_)    SIN4PORT(_x_)
28
#endif
27
#endif
28
*/
29
29
30
#ifndef INET_ADDRSTRLEN
30
#ifndef INET_ADDRSTRLEN
31
#define INET_ADDRSTRLEN 16
31
#define INET_ADDRSTRLEN 16
Lines 43-52 Link Here
43
#define IP_ADDRSTRLEN INET_ADDRSTRLEN
43
#define IP_ADDRSTRLEN INET_ADDRSTRLEN
44
#endif
44
#endif
45
45
46
unsigned short int sockaddr_port(const struct sockaddr *sa, socklen_t salen);
47
/*
46
#ifdef INET6
48
#ifdef INET6
47
typedef struct sockaddr_storage sockaddr_storage_t;
49
typedef struct sockaddr_storage sockaddr_storage_t;
48
#else
50
#else
49
typedef struct sockaddr_in sockaddr_storage_t;
51
typedef struct sockaddr_in sockaddr_storage_t;
50
#endif 
52
#endif 
53
*/
51
54
52
#endif /* AF_PORTABILITY_H */
55
#endif /* AF_PORTABILITY_H */
(-)oftpd-0.3.7.orig/src/config.h.in (-3 / +3 lines)
Lines 97-111 Link Here
97
/* Define if you have the <limits.h> header file.  */
97
/* Define if you have the <limits.h> header file.  */
98
#undef HAVE_LIMITS_H
98
#undef HAVE_LIMITS_H
99
99
100
/* Define if you have the <syslog.h> header file.  */
101
#undef HAVE_SYSLOG_H
102
100
/* Define if you have the <sys/time.h> header file.  */
103
/* Define if you have the <sys/time.h> header file.  */
101
#undef HAVE_SYS_TIME_H
104
#undef HAVE_SYS_TIME_H
102
105
103
/* Define if you have the <sys/types.h> header file.  */
106
/* Define if you have the <sys/types.h> header file.  */
104
#undef HAVE_SYS_TYPES_H
107
#undef HAVE_SYS_TYPES_H
105
108
106
/* Define if you have the <syslog.h> header file.  */
107
#undef HAVE_SYSLOG_H
108
109
/* Define if you have the <unistd.h> header file.  */
109
/* Define if you have the <unistd.h> header file.  */
110
#undef HAVE_UNISTD_H
110
#undef HAVE_UNISTD_H
111
111
(-)oftpd-0.3.7.orig/src/error.c (+1 lines)
Lines 23-28 Link Here
23
{
23
{
24
    va_list args;
24
    va_list args;
25
25
26
    fprintf(stderr, "error_init: %d %s", error_code, desc_fmt);
26
    daemon_assert(err != NULL);
27
    daemon_assert(err != NULL);
27
    daemon_assert(error_code >= 0);
28
    daemon_assert(error_code >= 0);
28
    daemon_assert(desc_fmt != NULL);
29
    daemon_assert(desc_fmt != NULL);
(-)oftpd-0.3.7.orig/src/ftp_command.c (-21 / +28 lines)
Lines 12-18 Link Here
12
#include <arpa/inet.h>
12
#include <arpa/inet.h>
13
#include <netdb.h>
13
#include <netdb.h>
14
#include "ftp_command.h"
14
#include "ftp_command.h"
15
#include "af_portability.h"
16
#include "daemon_assert.h"
15
#include "daemon_assert.h"
17
16
18
/* argument types */
17
/* argument types */
Lines 67-74 Link Here
67
static const char *parse_host_port(struct sockaddr_in *addr, const char *s);
66
static const char *parse_host_port(struct sockaddr_in *addr, const char *s);
68
static const char *parse_number(int *num, const char *s, int max_num);
67
static const char *parse_number(int *num, const char *s, int max_num);
69
static const char *parse_offset(off_t *ofs, const char *s);
68
static const char *parse_offset(off_t *ofs, const char *s);
70
static const char *parse_host_port_long(sockaddr_storage_t *sa, const char *s);
69
static const char *parse_host_port_long(struct sockaddr *sa, const char *s);
71
static const char *parse_host_port_ext(sockaddr_storage_t *sa, const char *s); 
70
static const char *parse_host_port_ext(struct sockaddr *sa, const char *s); 
72
71
73
int ftp_command_parse(const char *input, ftp_command_t *cmd)
72
int ftp_command_parse(const char *input, ftp_command_t *cmd)
74
{
73
{
Lines 137-143 Link Here
137
	    input++;
136
	    input++;
138
137
139
            /* parse the host & port information (if any) */
138
            /* parse the host & port information (if any) */
140
	    input = parse_host_port(&tmp.arg[0].host_port, input);
139
	    input = parse_host_port((struct sockaddr_in *)&tmp.arg[0].host_port, input);
141
	    if (input == NULL) {
140
	    if (input == NULL) {
142
	        return 0;
141
	        return 0;
143
	    }
142
	    }
Lines 151-157 Link Here
151
            input++;
150
            input++;
152
 
151
 
153
            /* parse the host & port information (if any) */
152
            /* parse the host & port information (if any) */
154
            input = parse_host_port_long(&tmp.arg[0].host_port, input);
153
            input = parse_host_port_long((struct sockaddr *)&tmp.arg[0].host_port, input);
155
            if (input == NULL) {
154
            if (input == NULL) {
156
                return 0;
155
                return 0;
157
            }
156
            }
Lines 165-171 Link Here
165
            input++;
164
            input++;
166
 
165
 
167
            /* parse the host & port information (if any) */
166
            /* parse the host & port information (if any) */
168
            input = parse_host_port_ext(&tmp.arg[0].host_port, input);
167
            input = parse_host_port_ext((struct sockaddr *)&tmp.arg[0].host_port, input);
169
            if (input == NULL) {
168
            if (input == NULL) {
170
                return 0;
169
                return 0;
171
            }
170
            }
Lines 378-384 Link Here
378
377
379
/* note: returns success even for unknown address families */
378
/* note: returns success even for unknown address families */
380
/*       this is okay, as long as subsequent uses VERIFY THE FAMILY first */
379
/*       this is okay, as long as subsequent uses VERIFY THE FAMILY first */
381
static const char *parse_host_port_long(sockaddr_storage_t *sa, const char *s)
380
static const char *parse_host_port_long(struct sockaddr *sa, const char *s)
382
{   
381
{   
383
    int i;
382
    int i;
384
    int family;
383
    int family;
Lines 441-478 Link Here
441
440
442
    /* okay, everything parses, load the address if possible */
441
    /* okay, everything parses, load the address if possible */
443
    if (family == 4) {
442
    if (family == 4) {
444
        SAFAM(sa) = AF_INET;
443
        ((struct sockaddr_in *)sa)->sin_family = AF_INET;
445
	if (addr_len != sizeof(struct in_addr)) {
444
	if (addr_len != sizeof(struct in_addr)) {
446
	    return NULL;
445
	    return NULL;
447
	}
446
	}
448
	if (port_len != 2) {
447
	if (port_len != 2) {
449
	    return NULL;
448
	    return NULL;
450
	}
449
	}	
451
	memcpy(&SINADDR(sa), addr, addr_len);
450
	memcpy(&((struct sockaddr_in *)sa)->sin_addr, addr, addr_len);
452
	SINPORT(sa) = htons((port[0] << 8) + port[1]);
451
	((struct sockaddr_in *)sa)->sin_port = htons((port[0] << 8) + port[1]);
453
    }
452
    }
454
#ifdef INET6
453
#ifdef INET6
455
    else if (family == 6) {
454
    else if (family == 6) {
456
        SAFAM(sa) = AF_INET6;
455
        ((struct sockaddr_in6 *)sa)->sin6_family = AF_INET6;
457
	if (addr_len != sizeof(struct in6_addr)) {
456
	if (addr_len != sizeof(struct in6_addr)) {
458
	    return NULL;
457
	    return NULL;
459
	}
458
	}
460
	if (port_len != 2) {
459
	if (port_len != 2) {
461
	    return NULL;
460
	    return NULL;
462
	}
461
	}
463
	memcpy(&SIN6ADDR(sa), addr, addr_len);
462
	memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr, addr, addr_len);
464
	SINPORT(sa) = htons((port[0] << 8) + port[1]);
463
	((struct sockaddr_in6 *)sa)->sin6_port = htons((port[0] << 8) + port[1]);
465
    }
464
    }
466
#endif
465
#endif
467
    else {
466
    else {
468
        SAFAM(sa) = -1;
467
        sa->sa_family = -1;
469
    }
468
    }
470
469
471
    /* return new pointer */
470
    /* return new pointer */
472
    return s;
471
    return s;
473
}
472
}
474
473
475
static const char *parse_host_port_ext(sockaddr_storage_t *sa, const char *s)
474
static const char *parse_host_port_ext(struct sockaddr *sa, const char *s)
476
{ 
475
{ 
477
    int delimeter;
476
    int delimeter;
478
    int family;
477
    int family;
Lines 545-556 Link Here
545
        }
544
        }
546
#endif /* HAVE_INET_ATON */
545
#endif /* HAVE_INET_ATON */
547
546
548
        SIN4ADDR(sa) = in_addr;
547
        ((struct sockaddr_in *)sa)->sin_addr = in_addr;
549
    }
548
    }
550
#else
549
#else
551
    {
550
    {
552
        struct addrinfo hints;
551
        struct addrinfo hints, *res;
553
	struct *res;
554
552
555
	memset(&hints, 0, sizeof(hints));
553
	memset(&hints, 0, sizeof(hints));
556
	hints.ai_flags = AI_NUMERICHOST;
554
	hints.ai_flags = AI_NUMERICHOST;
Lines 566-573 Link Here
566
    }
564
    }
567
#endif /* INET6 */
565
#endif /* INET6 */
568
566
569
    SAFAM(sa) = family;
567
    sa->sa_family = family;
570
    SINPORT(sa) = htons(port);
568
    if (family == AF_INET) {
569
    	((struct sockaddr_in *)sa)->sin_port = htons(port);
570
#ifdef INET6    
571
    } else if (family == AF_INET6) {
572
    	((struct sockaddr_in6 *)sa)->sin6_port = htons(port);
573
#endif /* INET6 */
574
    } else {
575
	/* we have an error! */
576
	return NULL;
577
    }
571
578
572
    /* return new pointer */
579
    /* return new pointer */
573
    return s;
580
    return s;
(-)oftpd-0.3.7.orig/src/ftp_command.h (-2 / +5 lines)
Lines 34-40 Link Here
34
#include <netinet/in.h>
34
#include <netinet/in.h>
35
#include <limits.h>
35
#include <limits.h>
36
#include <sys/types.h>
36
#include <sys/types.h>
37
#include "af_portability.h"
38
37
39
/* special macro for handling EPSV ALL requests */
38
/* special macro for handling EPSV ALL requests */
40
#define EPSV_ALL (-1)
39
#define EPSV_ALL (-1)
Lines 50-56 Link Here
50
    int num_arg;
49
    int num_arg;
51
    union {
50
    union {
52
        char string[MAX_STRING_LEN+1];
51
        char string[MAX_STRING_LEN+1];
53
        sockaddr_storage_t host_port;
52
#ifdef INET6
53
        struct sockaddr_storage host_port;
54
#else
55
	struct sockaddr_in host_port;
56
#endif
54
        int num;
57
        int num;
55
	off_t offset;
58
	off_t offset;
56
    } arg[MAX_ARG];
59
    } arg[MAX_ARG];
(-)oftpd-0.3.7.orig/src/ftp_listener.c (-73 / +115 lines)
Lines 52-58 Link Here
52
#include "af_portability.h"
52
#include "af_portability.h"
53
53
54
54
55
56
/* maximum number of consecutive errors in accept()
55
/* maximum number of consecutive errors in accept()
57
   before we terminate listener                     */
56
   before we terminate listener                     */
58
#define MAX_ACCEPT_ERROR 10
57
#define MAX_ACCEPT_ERROR 10
Lines 73-79 Link Here
73
/* prototypes */
72
/* prototypes */
74
static int invariant(const ftp_listener_t *f);
73
static int invariant(const ftp_listener_t *f);
75
static void *connection_acceptor(ftp_listener_t *f);
74
static void *connection_acceptor(ftp_listener_t *f);
76
static void addr_to_string(const sockaddr_storage_t *s, char *addr);
75
static void addr_to_string(const struct sockaddr *s, char *addr);
77
static void *connection_handler(connection_info_t *info);
76
static void *connection_handler(connection_info_t *info);
78
static void connection_handler_cleanup(connection_info_t *info);
77
static void connection_handler_cleanup(connection_info_t *info);
79
78
Lines 85-98 Link Here
85
                      int inactivity_timeout,
84
                      int inactivity_timeout,
86
                      error_t *err)
85
                      error_t *err)
87
{
86
{
88
    sockaddr_storage_t sock_addr;
87
#ifdef INET6
88
    struct sockaddr_storage sock_addr;
89
    int gai_err;
90
    struct addrinfo hints;
91
    struct addrinfo *res;
92
    char buf[ADDR_BUF_LEN+1];
93
    int ret;
94
#else 
95
    struct sockaddr_in sock_addr;
96
    char *addr_str;
97
#endif
89
    int fd;
98
    int fd;
90
    int flags;
99
    int flags;
91
    int pipefds[2];
100
    int pipefds[2];
92
    int reuseaddr;
101
    int reuseaddr;
93
    char dir[PATH_MAX+1];
102
    char dir[PATH_MAX+1];
94
    char buf[ADDR_BUF_LEN+1];
95
    const char *inet_ntop_ret;
96
103
97
    daemon_assert(f != NULL);
104
    daemon_assert(f != NULL);
98
    daemon_assert(port >= 0);
105
    daemon_assert(port >= 0);
Lines 108-171 Link Here
108
    }
115
    }
109
116
110
    /* set up our socket address */
117
    /* set up our socket address */
111
    memset(&sock_addr, 0, sizeof(sockaddr_storage_t));
118
    memset(&sock_addr, 0, sizeof(sock_addr));
112
119
113
    if (address == NULL) {
114
#ifdef INET6
120
#ifdef INET6
115
        SAFAM(&sock_addr) = AF_INET6;
121
    memset(&hints, 0, sizeof(hints));
116
        memcpy(&SIN6ADDR(&sock_addr), &in6addr_any, sizeof(struct in6_addr));
122
	 
123
    /* with AF_UNSPEC we can handle even hostnames */
124
    hints.ai_family    = (address == NULL ? AF_INET6 : AF_UNSPEC);
125
    hints.ai_flags     = AI_PASSIVE;
126
    hints.ai_socktype  = SOCK_STREAM;
127
128
    gai_err = getaddrinfo(address, "21", &hints, &res);							        
129
    if (gai_err != 0) {
130
	if (gai_err < 0) gai_err = -gai_err;
131
        error_init(err, gai_err, "error parsing server socket address; %s",
132
		gai_strerror(gai_err));
133
	return 0;
134
    }
135
	
136
    memcpy(&sock_addr, res->ai_addr, res->ai_addrlen);
137
    freeaddrinfo(res);
117
#else
138
#else
118
        SAFAM(&sock_addr) = AF_INET;
139
    if (address == NULL) {
140
        sock_addr.sin_family = AF_INET;
119
        sock_addr.sin_addr.s_addr = INADDR_ANY;
141
        sock_addr.sin_addr.s_addr = INADDR_ANY;
120
#endif
121
    } else {
142
    } else {
122
        int gai_err;
143
	struct hostent *hp;
123
        struct addrinfo hints;
144
		
124
        struct addrinfo *res;
145
	hp = gethostbyname(address);
125
146
	if(hp == NULL) {
126
        memset(&hints, 0, sizeof(hints));
147
		error_init(err, h_errno, "error with gethostbyname");
127
148
		return 0;
128
/* - This code should be able to parse both IPv4 and IPv6 internet
149
	}
129
 * addresses and put them in the sock_addr variable.
150
		
130
 * - Much neater now.
151
	assert(hp->h_length <= sizeof(sock_addr));
131
 * - Bug: Can't handle hostnames, only IP addresses.  Not sure
152
	memcpy(&sock_addr, hp->h_addr, hp->h_length);
132
 * exactly why.  But then again, I'm not sure exactly why
153
    }
133
 * there is a man page for getipnodebyname (which getaddrinfo
154
#endif
134
 * says it uses) but no corresponding function in libc.
135
 * -- Matthew Danish [3/20/2001]
136
 */
137
155
156
    /* setup non-default port */
157
    if (port != 0) {			        
158
	sa_family_t family = ((struct sockaddr *)&sock_addr)->sa_family;
159
	switch (family) {
138
#ifdef INET6
160
#ifdef INET6
139
        hints.ai_family = AF_INET6;
161
	case AF_INET6:
140
#else
162
		((struct sockaddr_in6*)&sock_addr)->sin6_port = port;
141
        hints.ai_family = AF_INET;
163
		break;
142
#endif
164
#endif
143
165
	case AF_INET:
144
        hints.ai_flags  = AI_PASSIVE;
166
		((struct sockaddr_in*)&sock_addr)->sin_port = port;
145
167
		break;
146
        gai_err = getaddrinfo(address, NULL, &hints, &res);
168
	default:
147
        if (gai_err != 0) {
169
		/* handle error */
148
            error_init(err, gai_err, "error parsing server socket address; %s", 
170
		error_init(err, 1, "unknown adderess family");
149
                       gai_strerror(gai_err));
171
		return 0;
150
            return 0;
172
	}
151
        }
152
153
        memcpy(&sock_addr, res->ai_addr, res->ai_addrlen);
154
        freeaddrinfo(res);
155
    } 
156
157
    if (port == 0) {
158
        SINPORT(&sock_addr) = htons(DEFAULT_FTP_PORT);
159
    } else {
160
        SINPORT(&sock_addr) = htons(port);
161
    }
173
    }
162
174
	
163
175
#ifdef INET6
164
    inet_ntop_ret = inet_ntop(SAFAM(&sock_addr), 
176
    ret = getnameinfo((struct sockaddr *)(&sock_addr), sizeof(sock_addr), buf, sizeof(buf), 
165
                              (void *)&SINADDR(&sock_addr), 
177
					NULL, 0, NI_NUMERICHOST);
166
                              buf, 
178
    if (ret != 0) {
167
                              sizeof(buf));
168
    if (inet_ntop_ret == NULL) {
169
        error_init(err, errno, "error converting server address to ASCII; %s", 
179
        error_init(err, errno, "error converting server address to ASCII; %s", 
170
                   strerror(errno));
180
                   strerror(errno));
171
        return 0;
181
        return 0;
Lines 173-183 Link Here
173
    
183
    
174
    /* Put some information in syslog */
184
    /* Put some information in syslog */
175
    syslog(LOG_INFO, "Binding interface '%s', port %d, max clients %d\n", buf, 
185
    syslog(LOG_INFO, "Binding interface '%s', port %d, max clients %d\n", buf, 
176
        ntohs(SINPORT(&sock_addr)), max_connections);    
186
	sockaddr_port((struct sockaddr *)&sock_addr, sizeof(sock_addr)), max_connections);    
187
#else 
188
    /* this should be thread-safe, as glibc texinfo documentation states: 
189
     * 
190
     *     In multi-threaded programs each thread has an own
191
     *     statically-allocated buffer (for inet_ntoa).  But still 
192
     *     subsequent calls of `inet_ntoa' in the same thread will 
193
     *     overwrite the result of the last call.
194
     */
195
    addr_str = inet_ntoa(sock_addr.sin_addr);
196
197
    /* Put some information in syslog */
198
    syslog(LOG_INFO, "Binding interface '%s', port %d, max clients %d\n", 
199
        addr_str,sockaddr_port((struct sockaddr*)&sock_addr,sizeof(sock_addr)),
200
	max_connections);
201
#endif
177
    
202
    
178
203
179
    /* okay, finally do some socket manipulation */
204
    /* okay, finally do some socket manipulation */
180
    fd = socket(AF_INET, SOCK_STREAM, 0);
205
    fd = socket(((struct sockaddr *)&sock_addr)->sa_family, SOCK_STREAM, 0);
181
    if (fd == -1) {
206
    if (fd == -1) {
182
        error_init(err, errno, "error creating socket; %s", strerror(errno));
207
        error_init(err, errno, "error creating socket; %s", strerror(errno));
183
        return 0;
208
        return 0;
Lines 193-200 Link Here
193
        return 0;
218
        return 0;
194
    }
219
    }
195
220
196
    if (bind(fd, (struct sockaddr *)&sock_addr, 
221
    if (bind(fd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) 
197
             sizeof(struct sockaddr_in)) != 0) 
198
    {
222
    {
199
        close(fd);
223
        close(fd);
200
        error_init(err, errno, "error binding address; %s", strerror(errno));
224
        error_init(err, errno, "error binding address; %s", strerror(errno));
Lines 261-266 Link Here
261
    daemon_assert(invariant(f));
285
    daemon_assert(invariant(f));
262
    daemon_assert(err != NULL);
286
    daemon_assert(err != NULL);
263
287
288
    syslog(LOG_WARNING, "in ftp_listener_start\n");
289
264
    error_code = pthread_create(&thread_id, 
290
    error_code = pthread_create(&thread_id, 
265
                                NULL, 
291
                                NULL, 
266
                                (void *(*)())connection_acceptor, 
292
                                (void *(*)())connection_acceptor, 
Lines 320-327 Link Here
320
346
321
    int fd;
347
    int fd;
322
    int tcp_nodelay;
348
    int tcp_nodelay;
323
    sockaddr_storage_t client_addr;
349
#ifdef INET6
324
    sockaddr_storage_t server_addr;
350
    struct sockaddr_storage client_addr;
351
    struct sockaddr_storage server_addr;
352
#else 
353
    struct sockaddr_in client_addr;
354
    struct sockaddr_in server_addr;
355
#endif
325
    unsigned addr_len;
356
    unsigned addr_len;
326
    
357
    
327
    connection_info_t *info;
358
    connection_info_t *info;
Lines 332-337 Link Here
332
363
333
    daemon_assert(invariant(f));
364
    daemon_assert(invariant(f));
334
365
366
    syslog(LOG_WARNING, "in connection_acceptor\n");
367
    
335
    if (!watchdog_init(&f->watchdog, f->inactivity_timeout, &err)) {
368
    if (!watchdog_init(&f->watchdog, f->inactivity_timeout, &err)) {
336
        syslog(LOG_ERR, "Error initializing watchdog thread; %s", 
369
        syslog(LOG_ERR, "Error initializing watchdog thread; %s", 
337
            error_get_desc(&err));
370
            error_get_desc(&err));
Lines 355-364 Link Here
355
         }
388
         }
356
389
357
         /* otherwise accept our pending connection (if any) */
390
         /* otherwise accept our pending connection (if any) */
358
         addr_len = sizeof(sockaddr_storage_t);
391
         addr_len = sizeof(client_addr);
359
         fd = accept(f->fd, (struct sockaddr *)&client_addr, &addr_len);
392
         fd = accept(f->fd, (struct sockaddr *)&client_addr, &addr_len);
360
         if (fd >= 0) {
393
         if (fd >= 0) {
361
             
394
             
395
    	     syslog(LOG_WARNING, "in connection_acceptor loop\n");
396
362
             tcp_nodelay = 1;
397
             tcp_nodelay = 1;
363
             if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&tcp_nodelay,
398
             if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&tcp_nodelay,
364
                 sizeof(int)) != 0)
399
                 sizeof(int)) != 0)
Lines 370-376 Link Here
370
                 continue;
405
                 continue;
371
             }
406
             }
372
407
373
             addr_len = sizeof(sockaddr_storage_t);
408
             addr_len = sizeof(server_addr);
374
             if (getsockname(fd, (struct sockaddr *)&server_addr, 
409
             if (getsockname(fd, (struct sockaddr *)&server_addr, 
375
                 &addr_len) == -1) 
410
                 &addr_len) == -1) 
376
             {
411
             {
Lines 392-400 Link Here
392
427
393
             telnet_session_init(&info->telnet_session, fd, fd);
428
             telnet_session_init(&info->telnet_session, fd, fd);
394
429
430
             syslog(LOG_WARNING, "about to call ftp_session_init\n");
431
395
             if (!ftp_session_init(&info->ftp_session, 
432
             if (!ftp_session_init(&info->ftp_session, 
396
                                   &client_addr, 
433
                                   (struct sockaddr *)&client_addr, 
397
                                   &server_addr, 
434
                                   (struct sockaddr *)&server_addr, 
398
                                   &info->telnet_session,  
435
                                   &info->telnet_session,  
399
                                   f->dir, 
436
                                   f->dir, 
400
                                   &err)) 
437
                                   &err)) 
Lines 444-450 Link Here
444
481
445
/* convert an address to a printable string */
482
/* convert an address to a printable string */
446
/* NOT THREADSAFE - wrap with a mutex before calling! */
483
/* NOT THREADSAFE - wrap with a mutex before calling! */
447
static char *addr2string(const sockaddr_storage_t *s)
484
static char *addr2string(const struct sockaddr *s)
448
{
485
{
449
    static char addr[IP_ADDRSTRLEN+1];
486
    static char addr[IP_ADDRSTRLEN+1];
450
    int error;
487
    int error;
Lines 454-467 Link Here
454
491
455
#ifdef INET6
492
#ifdef INET6
456
    error = getnameinfo((struct sockaddr *)s, 
493
    error = getnameinfo((struct sockaddr *)s, 
457
                         sizeof(sockaddr_storage_t),
494
                         sizeof(struct sockaddr_storage),
458
                         addr, 
495
                         addr, 
459
                         sizeof(addr), 
496
                         sizeof(addr), 
460
                         NULL,
497
                         NULL,
461
                         0, 
498
                         0, 
462
                         NI_NUMERICHOST);
499
                         NI_NUMERICHOST);
463
    if (error != 0) {
500
    if (error != 0) {
464
        syslog(LOG_WARN, "getnameinfo error; %s", gai_strerror(error));
501
        syslog(LOG_WARNING, "getnameinfo error; %s", gai_strerror(error));
465
        ret_val = "Unknown IP";
502
        ret_val = "Unknown IP";
466
    } else {
503
    } else {
467
        ret_val = addr;
504
        ret_val = addr;
Lines 480-485 Link Here
480
    int num_connections;
517
    int num_connections;
481
    char drop_reason[80];
518
    char drop_reason[80];
482
519
520
    syslog(LOG_WARNING, "in connection_handler\n");
483
    /* for ease of use only */
521
    /* for ease of use only */
484
    f = info->ftp_listener;
522
    f = info->ftp_listener;
485
523
Lines 497-509 Link Here
497
    pthread_mutex_lock(&f->mutex);
535
    pthread_mutex_lock(&f->mutex);
498
    num_connections = ++f->num_connections;
536
    num_connections = ++f->num_connections;
499
    syslog(LOG_INFO, "%s port %d connection", 
537
    syslog(LOG_INFO, "%s port %d connection", 
500
        addr2string(&info->ftp_session.client_addr), 
538
        addr2string((struct sockaddr *)&info->ftp_session.client_addr), 
501
        ntohs(SINPORT(&info->ftp_session.client_addr)));
539
        sockaddr_port((struct sockaddr *)&info->ftp_session.client_addr, 
540
	    sizeof(info->ftp_session.client_addr)));
502
    pthread_mutex_unlock(&f->mutex);
541
    pthread_mutex_unlock(&f->mutex);
503
542
504
    /* handle the session */
543
    /* handle the session */
505
    if (num_connections <= f->max_connections) {
544
    if (num_connections <= f->max_connections) {
506
545
546
        syslog(LOG_WARNING, "about to call ftp_session_run\n");
507
        ftp_session_run(&info->ftp_session, &info->watched);
547
        ftp_session_run(&info->ftp_session, &info->watched);
508
548
509
    } else {
549
    } else {
Lines 518-525 Link Here
518
        pthread_mutex_lock(&f->mutex);
558
        pthread_mutex_lock(&f->mutex);
519
        syslog(LOG_WARNING, 
559
        syslog(LOG_WARNING, 
520
          "%s port %d exceeds max users (%d), dropping connection",
560
          "%s port %d exceeds max users (%d), dropping connection",
521
          addr2string(&info->ftp_session.client_addr), 
561
          addr2string((struct sockaddr *)&info->ftp_session.client_addr), 
522
          ntohs(SINPORT(&info->ftp_session.client_addr)),
562
          sockaddr_port((struct sockaddr *)&info->ftp_session.client_addr, 
563
	      sizeof(info->ftp_session.client_addr)),
523
          num_connections);
564
          num_connections);
524
        pthread_mutex_unlock(&f->mutex);
565
        pthread_mutex_unlock(&f->mutex);
525
566
Lines 548-555 Link Here
548
589
549
    syslog(LOG_INFO, 
590
    syslog(LOG_INFO, 
550
      "%s port %d disconnected", 
591
      "%s port %d disconnected", 
551
      addr2string(&info->ftp_session.client_addr),
592
      addr2string((struct sockaddr *)&info->ftp_session.client_addr),
552
      ntohs(SINPORT(&info->ftp_session.client_addr)));
593
      sockaddr_port((struct sockaddr *)&info->ftp_session.client_addr, 
594
          sizeof(info->ftp_session.client_addr)));
553
595
554
    pthread_mutex_unlock(&f->mutex);
596
    pthread_mutex_unlock(&f->mutex);
555
597
(-)oftpd-0.3.7.orig/src/ftp_session.c (-79 / +218 lines)
Lines 52-63 Link Here
52
static void init_passive_port();
52
static void init_passive_port();
53
static int get_passive_port();
53
static int get_passive_port();
54
static int convert_newlines(char *dst, const char *src, int srclen);
54
static int convert_newlines(char *dst, const char *src, int srclen);
55
static void get_addr_str(const sockaddr_storage_t *s, char *buf, int bufsiz);
55
static void get_addr_str(const struct sockaddr *s, char *buf, int bufsiz);
56
static void send_readme(const ftp_session_t *f, int code);
56
static void send_readme(const ftp_session_t *f, int code);
57
static void netscape_hack(int fd);
57
static void netscape_hack(int fd);
58
static void set_port(ftp_session_t *f, const sockaddr_storage_t *host_port);
58
static void set_port(ftp_session_t *f, const struct sockaddr *host_port);
59
static int set_pasv(ftp_session_t *f, sockaddr_storage_t *host_port);
59
static int set_pasv(ftp_session_t *f, struct sockaddr *host_port);
60
static int ip_equal(const sockaddr_storage_t *a, const sockaddr_storage_t *b);
60
static int ip_equal(const struct sockaddr *a, const struct sockaddr *b);
61
static void get_absolute_fname(char *fname, 
61
static void get_absolute_fname(char *fname, 
62
                               int fname_len,
62
                               int fname_len,
63
                               const char *dir,
63
                               const char *dir,
Lines 123-130 Link Here
123
123
124
124
125
int ftp_session_init(ftp_session_t *f, 
125
int ftp_session_init(ftp_session_t *f, 
126
                     const sockaddr_storage_t *client_addr, 
126
                     const struct sockaddr *client_addr, 
127
                     const sockaddr_storage_t *server_addr, 
127
                     const struct sockaddr *server_addr, 
128
                     telnet_session_t *t, 
128
                     telnet_session_t *t, 
129
                     const char *dir,
129
                     const char *dir,
130
  	             error_t *err)
130
  	             error_t *err)
Lines 138-146 Link Here
138
    daemon_assert(err != NULL);
138
    daemon_assert(err != NULL);
139
139
140
#ifdef INET6
140
#ifdef INET6
141
    /* if the control connection is on IPv6, we need to get an IPv4 address */
141
    /* if the control connection is on IPv6, we need to get an IPv4 address 
142
    /* to bind the socket to */
142
     * to bind the socket to */
143
    if (SSFAM(server_addr) == AF_INET6) {
143
    if (server_addr->sa_family == AF_INET6) {
144
	struct addrinfo hints;
144
	struct addrinfo hints;
145
	struct addrinfo *res;
145
	struct addrinfo *res;
146
	int errcode;
146
	int errcode;
Lines 149-156 Link Here
149
        memset(&hints, 0, sizeof(struct addrinfo));
149
        memset(&hints, 0, sizeof(struct addrinfo));
150
        hints.ai_family = AF_INET;
150
        hints.ai_family = AF_INET;
151
	hints.ai_flags = AI_PASSIVE;
151
	hints.ai_flags = AI_PASSIVE;
152
	if (getaddrinfo(NULL, "ftp", &hints, &res) != 0) {
152
	hints.ai_socktype = SOCK_STREAM;
153
	    error_init(err, 0, "unable to determing IPv4 address; %s",
153
	
154
	if ((errcode = getaddrinfo(NULL, "21", &hints, &res)) != 0) {
155
	    error_init(err, 0, "unable to determine IPv4 address; %s",
154
	        gai_strerror(errcode));
156
	        gai_strerror(errcode));
155
	    return 0;
157
	    return 0;
156
	}
158
	}
Lines 158-174 Link Here
158
        /* let's sanity check */
160
        /* let's sanity check */
159
	daemon_assert(res != NULL);
161
	daemon_assert(res != NULL);
160
	daemon_assert(sizeof(f->server_ipv4_addr) >= res->ai_addrlen);
162
	daemon_assert(sizeof(f->server_ipv4_addr) >= res->ai_addrlen);
161
        daemon_assert(SSFAM(host_port) == AF_INET);
163
        daemon_assert(res->ai_addr->sa_family == AF_INET);
162
164
163
        /* copy the result and free memory as necessary */
165
        /* copy the result and free memory as necessary */
164
	memcpy(&f->server_ipv4_addr, res->ai_addr, res->ai_addrlen);
166
	memcpy(&f->server_ipv4_addr, res->ai_addr, res->ai_addrlen);
165
        freeaddrinfo(res);
167
        freeaddrinfo(res);
166
    } else {
168
    } else {
167
        daemon_assert(SSFAM(host_port) == AF_INET);
169
        f->server_ipv4_addr = *((struct sockaddr_in *)server_addr);
168
        f->server_ipv4_addr = *server_addr;
169
    }
170
    }
170
#else
171
    f->server_ipv4_addr = *server_addr;
172
#endif
171
#endif
173
172
174
    f->session_active = 1;
173
    f->session_active = 1;
Lines 182-198 Link Here
182
181
183
    f->epsv_all_set = 0;
182
    f->epsv_all_set = 0;
184
183
185
    f->client_addr = *client_addr;
184
#ifdef INET6
185
    memcpy(&f->client_addr, client_addr, sizeof(struct sockaddr_in6));
186
    memcpy(&f->server_addr, server_addr, sizeof(struct sockaddr_in6));
187
    memcpy(&f->data_port,   client_addr, sizeof(struct sockaddr_in6));
188
#else
189
    memcpy(&f->client_addr, client_addr, sizeof(struct sockaddr_in));
190
    memcpy(&f->server_addr, server_addr, sizeof(struct sockaddr_in));
191
    memcpy(&f->data_port,   client_addr, sizeof(struct sockaddr_in));
192
#endif
186
    get_addr_str(client_addr, f->client_addr_str, sizeof(f->client_addr_str));
193
    get_addr_str(client_addr, f->client_addr_str, sizeof(f->client_addr_str));
187
194
188
    f->server_addr = *server_addr;
189
190
    f->telnet_session = t;
195
    f->telnet_session = t;
191
    daemon_assert(strlen(dir) < sizeof(f->dir));
196
    daemon_assert(strlen(dir) < sizeof(f->dir));
192
    strcpy(f->dir, dir);
197
    strcpy(f->dir, dir);
193
198
194
    f->data_channel = DATA_PORT;
199
    f->data_channel = DATA_PORT;
195
    f->data_port = *client_addr;
196
    f->server_fd = -1;
200
    f->server_fd = -1;
197
201
198
    daemon_assert(invariant(f));
202
    daemon_assert(invariant(f));
Lines 326-332 Link Here
326
            /* If the client specifies a port, verify that it is from the   */
330
            /* If the client specifies a port, verify that it is from the   */
327
	    /* host the client connected from.  This prevents a client from */
331
	    /* host the client connected from.  This prevents a client from */
328
	    /* using the server to open connections to arbritrary hosts.    */
332
	    /* using the server to open connections to arbritrary hosts.    */
329
	    if (!ip_equal(&f->client_addr, &f->data_port)) {
333
	    if (!ip_equal((struct sockaddr *)&f->client_addr, 
334
		    (struct sockaddr *)&f->data_port)) {
330
	        return 0;
335
	        return 0;
331
	    }
336
	    }
332
	    if (f->server_fd != -1) {
337
	    if (f->server_fd != -1) {
Lines 412-418 Link Here
412
}
417
}
413
418
414
#ifdef INET6
419
#ifdef INET6
415
static void get_addr_str(const sockaddr_storage_t *s, char *buf, int bufsiz)
420
static void get_addr_str(const struct sockaddr *s, char *buf, int bufsiz)
416
{
421
{
417
    int port;
422
    int port;
418
    int error;
423
    int error;
Lines 426-442 Link Here
426
     * number (which is 5 chars max), plus the '\0' character. */ 
431
     * number (which is 5 chars max), plus the '\0' character. */ 
427
    daemon_assert(bufsiz >= (INET_ADDRSTRLEN + 12));
432
    daemon_assert(bufsiz >= (INET_ADDRSTRLEN + 12));
428
433
429
    error = getnameinfo(client_addr, sizeof(sockaddr_storage_t), buf, 
434
    error = getnameinfo(s, sizeof(struct sockaddr_storage), buf, 
430
                bufsiz, NULL, 0, NI_NUMERICHOST);
435
                bufsiz, NULL, 0, NI_NUMERICHOST);
431
    /* getnameinfo() should never fail when called with NI_NUMERICHOST */
436
    /* getnameinfo() should never fail when called with NI_NUMERICHOST */
432
    daemon_assert(error == 0);
437
    daemon_assert(error == 0);
433
438
434
    len = strlen(buf);
439
    len = strlen(buf);
435
    daemon_assert(bufsiz >= len+12);
440
    daemon_assert(bufsiz >= len+12);
436
    snprintf(buf+len, bufsiz-len, " port %d", ntohs(SINPORT(&f->client_addr)));
441
    snprintf(buf+len, bufsiz-len, " port %d", sockaddr_port((struct sockaddr *)s, sizeof(s)));
437
}
442
}
438
#else
443
#else
439
static void get_addr_str(const sockaddr_storage_t *s, char *buf, int bufsiz)
444
static void get_addr_str(const struct sockaddr *s, char *buf, int bufsiz)
440
{
445
{
441
    unsigned int addr;
446
    unsigned int addr;
442
    int port;
447
    int port;
Lines 449-456 Link Here
449
     * number (which is 5 chars max), plus the '\0' character. */ 
454
     * number (which is 5 chars max), plus the '\0' character. */ 
450
    daemon_assert(bufsiz >= (INET_ADDRSTRLEN + 12));
455
    daemon_assert(bufsiz >= (INET_ADDRSTRLEN + 12));
451
456
452
    addr = ntohl(s->sin_addr.s_addr);
457
    addr = ntohl(((struct sockaddr_in *)s)->sin_addr.s_addr);
453
    port = ntohs(s->sin_port);
458
    port = ntohs(((struct sockaddr_in *)s)->sin_port);
454
    snprintf(buf, bufsiz, "%d.%d.%d.%d port %d", 
459
    snprintf(buf, bufsiz, "%d.%d.%d.%d port %d", 
455
        (addr >> 24) & 0xff, 
460
        (addr >> 24) & 0xff, 
456
	(addr >> 16) & 0xff,
461
	(addr >> 16) & 0xff,
Lines 626-641 Link Here
626
}
631
}
627
632
628
/* support for the various port setting functions */
633
/* support for the various port setting functions */
629
static void set_port(ftp_session_t *f, const sockaddr_storage_t *host_port)
634
static void set_port(ftp_session_t *f, const struct sockaddr *host_port)
630
{
635
{	
631
    daemon_assert(invariant(f));
636
    daemon_assert(invariant(f));
632
    daemon_assert(host_port != NULL);
637
    daemon_assert(host_port != NULL);
633
638
634
    if (f->epsv_all_set) {
639
    if (f->epsv_all_set) {
635
        reply(f, 500, "After EPSV ALL, only EPSV allowed.");
640
        reply(f, 500, "After EPSV ALL, only EPSV allowed.");
636
    } else if (!ip_equal(&f->client_addr, host_port)) {
641
    } else if (!ip_equal((struct sockaddr *)&f->client_addr, host_port)) {
637
        reply(f, 500, "Port must be on command channel IP.");
642
        reply(f, 500, "Port must be on command channel IP.");
638
    } else if (ntohs(SINPORT(host_port)) < IPPORT_RESERVED) {
643
#ifdef INET6
644
    } else if (sockaddr_port(host_port, sizeof(struct sockaddr_storage))
645
	       < IPPORT_RESERVED) {
646
#else
647
    } else if (sockaddr_port(host_port, sizeof(struct sockaddr_in))
648
	       < IPPORT_RESERVED) {
649
#endif
639
        reply(f, 500, "Port may not be less than 1024, which is reserved.");
650
        reply(f, 500, "Port may not be less than 1024, which is reserved.");
640
    } else {
651
    } else {
641
        /* close any outstanding PASSIVE port */
652
        /* close any outstanding PASSIVE port */
Lines 645-651 Link Here
645
        }
656
        }
646
657
647
        f->data_channel = DATA_PORT;
658
        f->data_channel = DATA_PORT;
648
	f->data_port = *host_port;
659
#ifdef INET6
660
	memcpy(&f->data_port, host_port, sizeof(struct sockaddr_in6));
661
#else
662
	memcpy(&f->data_port, host_port, sizeof(struct sockaddr_in));
663
#endif
649
	reply(f, 200, "Command okay.");
664
	reply(f, 200, "Command okay.");
650
    }
665
    }
651
666
Lines 655-670 Link Here
655
/* set IP and port for client to receive data on */
670
/* set IP and port for client to receive data on */
656
static void do_port(ftp_session_t *f, const ftp_command_t *cmd) 
671
static void do_port(ftp_session_t *f, const ftp_command_t *cmd) 
657
{
672
{
658
    const sockaddr_storage_t *host_port;
673
#ifdef INET6
674
    const struct sockaddr_storage *host_port;
675
#else
676
    const struct sockaddr_in *host_port;
677
#endif
659
678
660
    daemon_assert(invariant(f));
679
    daemon_assert(invariant(f));
661
    daemon_assert(cmd != NULL);
680
    daemon_assert(cmd != NULL);
662
    daemon_assert(cmd->num_arg == 1);
681
    daemon_assert(cmd->num_arg == 1);
663
682
664
    host_port = &cmd->arg[0].host_port;
683
    host_port = &cmd->arg[0].host_port;
665
    daemon_assert(SSFAM(host_port) == AF_INET);
684
    daemon_assert(((struct sockaddr *)host_port)->sa_family == AF_INET);
666
685
667
    set_port(f, host_port);
686
    set_port(f, (struct sockaddr *)host_port);
668
687
669
    daemon_assert(invariant(f));
688
    daemon_assert(invariant(f));
670
}
689
}
Lines 672-678 Link Here
672
/* set IP and port for client to receive data on, transport independent */
691
/* set IP and port for client to receive data on, transport independent */
673
static void do_lprt(ftp_session_t *f, const ftp_command_t *cmd)  
692
static void do_lprt(ftp_session_t *f, const ftp_command_t *cmd)  
674
{
693
{
675
    const sockaddr_storage_t *host_port;
694
#ifdef INET6
695
    const struct sockaddr_storage *host_port;
696
#else
697
    const struct sockaddr_in *host_port;
698
#endif
699
    struct sockaddr_in6 *tmp = (struct sockaddr_in6 *)host_port;
676
700
677
    daemon_assert(invariant(f));
701
    daemon_assert(invariant(f));
678
    daemon_assert(cmd != NULL);
702
    daemon_assert(cmd != NULL);
Lines 681-696 Link Here
681
    host_port = &cmd->arg[0].host_port;
705
    host_port = &cmd->arg[0].host_port;
682
706
683
#ifdef INET6
707
#ifdef INET6
684
    if ((SSFAM(host_port) != AF_INET) && (SSFAM(host_port) != AF_INET6)) {
708
    if ((((struct sockaddr *)host_port)->sa_family != AF_INET) && 
709
        (((struct sockaddr *)host_port)->sa_family != AF_INET6)) {
685
        reply(f, 521, "Only IPv4 and IPv6 supported, address families (4,6)");
710
        reply(f, 521, "Only IPv4 and IPv6 supported, address families (4,6)");
686
    }
711
    }
687
#else
712
#else
688
    if (SSFAM(host_port) != AF_INET) {
713
    if (((struct sockaddr *)host_port)->sa_family != AF_INET) {
689
        reply(f, 521, "Only IPv4 supported, address family (4)");
714
        reply(f, 521, "Only IPv4 supported, address family (4)");
690
    }
715
    }
691
#endif
716
#endif
692
717
693
    set_port(f, host_port);
718
    /*
719
    syslog(LOG_WARNING, "host is %d:%d:%d:%d:%d:%d:%d:%d %d", 
720
	ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[0]),
721
	ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[1]),
722
	ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[2]),
723
	ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[3]),
724
	ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[4]),
725
	ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[5]),
726
	ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[6]),
727
	ntohs(((struct sockaddr_in6 *)host_port)->sin6_addr.s6_addr16[7]),
728
	sockaddr_port(host_port, sizeof(struct sockaddr_storage)));
729
    */
730
731
    set_port(f, (struct sockaddr *)host_port);
694
732
695
    daemon_assert(invariant(f));
733
    daemon_assert(invariant(f));
696
}
734
}
Lines 703-709 Link Here
703
/* requests.                                                         */
741
/* requests.                                                         */
704
static void do_eprt(ftp_session_t *f, const ftp_command_t *cmd)  
742
static void do_eprt(ftp_session_t *f, const ftp_command_t *cmd)  
705
{
743
{
706
    const sockaddr_storage_t *host_port;
744
#ifdef INET6
745
    const struct sockaddr_storage *host_port;
746
#else
747
    const struct sockaddr_in *host_port;
748
#endif
707
749
708
    daemon_assert(invariant(f));
750
    daemon_assert(invariant(f));
709
    daemon_assert(cmd != NULL);
751
    daemon_assert(cmd != NULL);
Lines 717-731 Link Here
717
/* support for the various pasv setting functions */
759
/* support for the various pasv setting functions */
718
/* returns the file descriptor of the bound port, or -1 on error */
760
/* returns the file descriptor of the bound port, or -1 on error */
719
/* note: the "host_port" parameter will be modified, having its port set */
761
/* note: the "host_port" parameter will be modified, having its port set */
720
static int set_pasv(ftp_session_t *f, sockaddr_storage_t *bind_addr)
762
static int set_pasv(ftp_session_t *f, struct sockaddr *bind_addr)
721
{
763
{
722
    int socket_fd;
764
    int socket_fd;
723
    int port;
765
    int port;
766
    sa_family_t family;
724
767
725
    daemon_assert(invariant(f));
768
    daemon_assert(invariant(f));
726
    daemon_assert(bind_addr != NULL);
769
    daemon_assert(bind_addr != NULL);
727
770
728
    socket_fd = socket(SSFAM(bind_addr), SOCK_STREAM, 0);
771
    family = ((struct sockaddr *)bind_addr)->sa_family;
772
    socket_fd = socket(family, SOCK_STREAM, 0);
729
    if (socket_fd == -1) {
773
    if (socket_fd == -1) {
730
        reply(f, 500, "Error creating server socket; %s.", strerror(errno));
774
        reply(f, 500, "Error creating server socket; %s.", strerror(errno));
731
	return -1;
775
	return -1;
Lines 733-741 Link Here
733
777
734
    for (;;) {
778
    for (;;) {
735
        port = get_passive_port();
779
        port = get_passive_port();
736
        SINPORT(bind_addr) = htons(port);
780
#ifdef INET6
781
	if (((struct sockaddr *)bind_addr)->sa_family == AF_INET6) {
782
	    ((struct sockaddr_in6 *)bind_addr)->sin6_port = htons(port);
783
	} else 
784
#endif
785
	    ((struct sockaddr_in *)bind_addr)->sin_port = htons(port);
786
	
737
	if (bind(socket_fd, (struct sockaddr *)bind_addr, 
787
	if (bind(socket_fd, (struct sockaddr *)bind_addr, 
738
	    sizeof(struct sockaddr)) == 0) 
788
#ifdef INET6
789
	    sizeof(struct sockaddr_storage)) == 0) 
790
#else 
791
	    sizeof(struct sockaddr_in)) == 0) 
792
#endif
739
	{
793
	{
740
	    break;
794
	    break;
741
	}
795
	}
Lines 771-784 Link Here
771
        goto exit_pasv;
825
        goto exit_pasv;
772
    }
826
    }
773
827
774
    socket_fd = set_pasv(f, &f->server_ipv4_addr);
828
#ifdef INET6
829
    socket_fd = set_pasv(f, (struct sockaddr *)&f->server_ipv4_addr);
830
#else
831
    socket_fd = set_pasv(f, (struct sockaddr *)&f->server_addr);
832
#endif
775
    if (socket_fd == -1) {
833
    if (socket_fd == -1) {
776
        goto exit_pasv;
834
        goto exit_pasv;
777
    }
835
    }
778
836
779
    /* report port to client */
837
    /* report port to client */
838
#ifdef INET6
780
    addr = ntohl(f->server_ipv4_addr.sin_addr.s_addr);
839
    addr = ntohl(f->server_ipv4_addr.sin_addr.s_addr);
781
    port = ntohs(f->server_ipv4_addr.sin_port);
840
    port = ntohs(f->server_ipv4_addr.sin_port);
841
#else
842
    addr = ntohl(f->server_addr.sin_addr.s_addr);
843
    port = ntohs(f->server_addr.sin_port);
844
#endif
782
    reply(f, 227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d).",
845
    reply(f, 227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d).",
783
        addr >> 24, 
846
        addr >> 24, 
784
	(addr >> 16) & 0xff,
847
	(addr >> 16) & 0xff,
Lines 815-830 Link Here
815
        goto exit_lpsv;
878
        goto exit_lpsv;
816
    }
879
    }
817
880
818
    socket_fd = set_pasv(f, &f->server_addr);
881
    socket_fd = set_pasv(f, (struct sockaddr *)&f->server_addr);
819
    if (socket_fd == -1) {
882
    if (socket_fd == -1) {
820
        goto exit_lpsv;
883
        goto exit_lpsv;
821
    }
884
    }
822
885
823
    /* report address and port to client */
886
    /* report address and port to server */
824
#ifdef INET6
887
#ifdef INET6
825
    if (SSFAM(&f->server_addr) == AF_INET6) {
888
    if (((struct sockaddr *)&f->server_addr)->sa_family == AF_INET6) {
826
        a = (uint8_t *)&SIN6ADDR(&f->server_addr);
889
        a = (uint8_t *)&(((struct sockaddr_in6 *)&f->server_addr)->sin6_addr);
827
        p = (uint8_t *)&SIN6PORT(&f->server_addr);
890
        p = (uint8_t *)&(((struct sockaddr_in6 *)&f->server_addr)->sin6_port);
828
	snprintf(addr, sizeof(addr),
891
	snprintf(addr, sizeof(addr),
829
	    "(6,16,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,2,%d,%d)",
892
	    "(6,16,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,2,%d,%d)",
830
	    a[0],  a[1],  a[2],  a[3],  a[4],  a[5],  a[6],  a[7],  a[8],
893
	    a[0],  a[1],  a[2],  a[3],  a[4],  a[5],  a[6],  a[7],  a[8],
Lines 832-839 Link Here
832
    } else 
895
    } else 
833
#endif
896
#endif
834
    {
897
    {
835
        a = (uint8_t *)&SIN4ADDR(&f->server_addr);
898
        a = (uint8_t *)&(((struct sockaddr_in *)&f->server_addr)->sin_addr);
836
        p = (uint8_t *)&SIN4PORT(&f->server_addr);
899
        p = (uint8_t *)&(((struct sockaddr_in *)&f->server_addr)->sin_port);
837
	snprintf(addr, sizeof(addr), "(4,4,%d,%d,%d,%d,2,%d,%d)",
900
	snprintf(addr, sizeof(addr), "(4,4,%d,%d,%d,%d,2,%d,%d)",
838
	    a[0], a[1], a[2], a[3], p[0], p[1]);    
901
	    a[0], a[1], a[2], a[3], p[0], p[1]);    
839
    }
902
    }
Lines 855-861 Link Here
855
static void do_epsv(ftp_session_t *f, const ftp_command_t *cmd) 
918
static void do_epsv(ftp_session_t *f, const ftp_command_t *cmd) 
856
{
919
{
857
    int socket_fd;
920
    int socket_fd;
858
    sockaddr_storage_t *addr;
921
    struct sockaddr *addr;
859
922
860
    daemon_assert(invariant(f));
923
    daemon_assert(invariant(f));
861
    daemon_assert(cmd != NULL);
924
    daemon_assert(cmd != NULL);
Lines 863-872 Link Here
863
926
864
    /* check our argument, if any,  and use the appropriate address */
927
    /* check our argument, if any,  and use the appropriate address */
865
    if (cmd->num_arg == 0) {
928
    if (cmd->num_arg == 0) {
866
        addr = &f->server_addr;
929
        addr = (struct sockaddr *)&f->server_addr;
867
    } else {
930
    } else {
868
        switch (cmd->arg[0].num) {
931
        switch (cmd->arg[0].num) {
869
	    /* EPSV_ALL is a special number indicating the client sent */
932
	    /* EPSV_ALL is a special number indicating the server sent */
870
	    /* the command "EPSV ALL" - this is not a request to assign */
933
	    /* the command "EPSV ALL" - this is not a request to assign */
871
	    /* a new passive port, but rather to deny all future port */
934
	    /* a new passive port, but rather to deny all future port */
872
	    /* assignment requests other than EPSV */
935
	    /* assignment requests other than EPSV */
Lines 874-890 Link Here
874
                f->epsv_all_set = 1;
937
                f->epsv_all_set = 1;
875
		reply(f, 200, "EPSV ALL command successful.");
938
		reply(f, 200, "EPSV ALL command successful.");
876
		goto exit_epsv;
939
		goto exit_epsv;
940
#ifdef INET6
877
	    case 1:
941
	    case 1:
878
	        addr = (sockaddr_storage_t *)&f->server_ipv4_addr;
942
	        addr = (struct sockaddr *)&f->server_ipv4_addr;
879
		break;
943
		break;
880
#ifdef INET6
881
	    case 2:
944
	    case 2:
882
	        addr = &f->server_addr;
945
	        addr = (struct sockaddr *)&f->server_addr;
883
		break;
946
		break;
884
	    default:
947
	    default:
885
	        reply(f, 522, "Only IPv4 and IPv6 supported, use (1,2)");
948
	        reply(f, 522, "Only IPv4 and IPv6 supported, use (1,2)");
886
	        goto exit_epsv;
949
	        goto exit_epsv;
887
#else
950
#else
951
	    case 1:
952
	        addr = (struct sockaddr *)&f->server_addr;
953
		break;
888
	    default:
954
	    default:
889
	        reply(f, 522, "Only IPv4 supported, use (1)");
955
	        reply(f, 522, "Only IPv4 supported, use (1)");
890
	        goto exit_epsv;
956
	        goto exit_epsv;
Lines 900-906 Link Here
900
966
901
    /* report port to client */
967
    /* report port to client */
902
    reply(f, 229, "Entering Extended Passive Mode (|||%d|)", 
968
    reply(f, 229, "Entering Extended Passive Mode (|||%d|)", 
903
        ntohs(SINPORT(&f->server_addr)));
969
        sockaddr_port((struct sockaddr *)&f->server_addr, 
970
		sizeof(f->server_addr)));
904
971
905
    /* close any outstanding PASSIVE port */
972
    /* close any outstanding PASSIVE port */
906
    if (f->data_channel == DATA_PASSIVE) {
973
    if (f->data_channel == DATA_PASSIVE) {
Lines 1278-1306 Link Here
1278
static int open_connection(ftp_session_t *f)
1345
static int open_connection(ftp_session_t *f)
1279
{
1346
{
1280
    int socket_fd;
1347
    int socket_fd;
1348
#ifdef INET6
1349
    struct sockaddr_storage addr;
1350
#else
1281
    struct sockaddr_in addr;
1351
    struct sockaddr_in addr;
1352
#endif
1282
    unsigned addr_len;
1353
    unsigned addr_len;
1354
    sa_family_t family;
1283
1355
1284
    daemon_assert((f->data_channel == DATA_PORT) || 
1356
    daemon_assert((f->data_channel == DATA_PORT) || 
1285
                  (f->data_channel == DATA_PASSIVE));
1357
                  (f->data_channel == DATA_PASSIVE));
1286
1358
1287
    if (f->data_channel == DATA_PORT) {
1359
    if (f->data_channel == DATA_PORT) {
1288
        socket_fd = socket(SSFAM(&f->data_port), SOCK_STREAM, 0);
1360
    	family = ((struct sockaddr *)&f->data_port)->sa_family;
1361
        socket_fd = socket(family, SOCK_STREAM, 0);
1289
	if (socket_fd == -1) {
1362
	if (socket_fd == -1) {
1290
	    reply(f, 425, "Error creating socket; %s.", strerror(errno));
1363
	    reply(f, 425, "Error creating socket; %s.", strerror(errno));
1291
	    return -1;
1364
	    return -1;
1292
	}
1365
	}
1293
	if (connect(socket_fd, (struct sockaddr *)&f->data_port, 
1366
	if (connect(socket_fd, (struct sockaddr *)&f->data_port, 
1294
	    sizeof(sockaddr_storage_t)) != 0)
1367
	    sizeof(f->data_port)) != 0)
1295
	{
1368
	{
1296
	    reply(f, 425, "Error connecting; %s.", strerror(errno));
1369
	    reply(f, 425, "Error connecting; %s.", strerror(errno));
1297
	    close(socket_fd);
1370
	    close(socket_fd);
1298
	    return -1;
1371
	    return -1;
1299
	}
1372
	}
1300
    } else {
1373
    } else {
1374
	sa_family_t a, b;
1301
        daemon_assert(f->data_channel == DATA_PASSIVE);
1375
        daemon_assert(f->data_channel == DATA_PASSIVE);
1302
1376
1303
        addr_len = sizeof(struct sockaddr_in);
1377
        addr_len = sizeof(addr);
1304
        socket_fd = accept(f->server_fd, (struct sockaddr *)&addr, &addr_len);
1378
        socket_fd = accept(f->server_fd, (struct sockaddr *)&addr, &addr_len);
1305
	if (socket_fd == -1) {
1379
	if (socket_fd == -1) {
1306
	    reply(f, 425, "Error accepting connection; %s.", strerror(errno));
1380
	    reply(f, 425, "Error accepting connection; %s.", strerror(errno));
Lines 1310-1324 Link Here
1310
        /* in IPv6, the client can connect to a channel using a different */
1384
        /* in IPv6, the client can connect to a channel using a different */
1311
	/* protocol - in that case, we'll just blindly let the connection */
1385
	/* protocol - in that case, we'll just blindly let the connection */
1312
	/* through, otherwise verify addresses match */
1386
	/* through, otherwise verify addresses match */
1313
        if (SAFAM(addr) == SSFAM(&f->client_addr)) {
1387
        a = ((struct sockaddr *)&addr)->sa_family;
1314
	    if (memcmp(&SINADDR(&f->client_addr), &SINADDR(&addr), 
1388
	b = ((struct sockaddr *)&f->client_addr)->sa_family;
1315
	               sizeof(SINADDR(&addr))))
1389
1316
	    {
1390
	if (a == b) {
1317
	        reply(f, 425, 
1391
	    if (a == AF_INET6) {
1318
	          "Error accepting connection; connection from invalid IP.");
1392
	        if (memcmp(&(((struct sockaddr_in6 *)&addr)->sin6_addr), 
1319
	        close(socket_fd);
1393
		       &(((struct sockaddr_in6 *)&f->client_addr)->sin6_addr),
1320
	        return -1;
1394
	               sizeof(struct in6_addr)))
1321
            }
1395
	        {
1396
	            reply(f, 425, 
1397
	             "Error accepting connection; connection from invalid IP.");
1398
	            close(socket_fd);
1399
	            return -1;
1400
                }
1401
	    } else {
1402
	        if (memcmp(&(((struct sockaddr_in *)&addr)->sin_addr), 
1403
		       &(((struct sockaddr_in *)&f->client_addr)->sin_addr),
1404
	               sizeof(struct in_addr)))
1405
	        {
1406
	            reply(f, 425, 
1407
	             "Error accepting connection; connection from invalid IP.");
1408
	            close(socket_fd);
1409
	            return -1;
1410
                }
1411
	    }
1322
	}
1412
	}
1323
#else
1413
#else
1324
	if (memcmp(&f->client_addr.sin_addr, 
1414
	if (memcmp(&f->client_addr.sin_addr, 
Lines 1811-1830 Link Here
1811
    }
1901
    }
1812
}
1902
}
1813
1903
1904
#ifdef INET6
1905
1814
/* compare two addresses to see if they contain the same IP address */
1906
/* compare two addresses to see if they contain the same IP address */
1815
static int ip_equal(const sockaddr_storage_t *a, const sockaddr_storage_t *b)
1907
static int ip_equal(const struct sockaddr *a, const struct sockaddr *b)
1816
{
1908
{
1909
    struct sockaddr *aa, *bb;
1910
    
1817
    daemon_assert(a != NULL);
1911
    daemon_assert(a != NULL);
1818
    daemon_assert(b != NULL);
1912
    daemon_assert(b != NULL);
1819
    daemon_assert((SSFAM(a) == AF_INET) || (SSFAM(a) == AF_INET6));
1913
    daemon_assert((a->sa_family == AF_INET) || (a->sa_family == AF_INET6));
1820
    daemon_assert((SSFAM(b) == AF_INET) || (SSFAM(b) == AF_INET6));
1914
    daemon_assert((b->sa_family == AF_INET) || (b->sa_family == AF_INET6));
1821
1915
    
1822
    if (SSFAM(a) != SSFAM(b)) {
1916
    aa = (struct sockaddr *)a;
1823
        return 0;
1917
    bb = (struct sockaddr *)b;
1918
    
1919
    /* we have to handle those --damned-- IPV4MAPPED addresses */
1920
    if (aa->sa_family != bb->sa_family) {	    
1921
    	if (a->sa_family == AF_INET6 && 
1922
            IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)a)->sin6_addr)) {
1923
	        aa = (struct sockaddr *)alloca(sizeof(struct sockaddr_in));
1924
	        memset(aa, 0, sizeof(struct sockaddr_in));
1925
	        ((struct sockaddr_in *)aa)->sin_addr.s_addr = 
1926
	    	    ((struct sockaddr_in6 *)a)->sin6_addr.s6_addr32[3];
1927
	        ((struct sockaddr_in *)aa)->sin_port = 
1928
		    ((struct sockaddr_in6 *)a)->sin6_port;
1929
        } else if (b->sa_family == AF_INET6 && 
1930
            IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)b)->sin6_addr)) {
1931
	        bb = (struct sockaddr *)alloca(sizeof(struct sockaddr_in));
1932
	        memset(bb, 0, sizeof(struct sockaddr_in));
1933
	        ((struct sockaddr_in *)bb)->sin_addr.s_addr = 
1934
	    	    ((struct sockaddr_in6 *)b)->sin6_addr.s6_addr32[3];
1935
	        ((struct sockaddr_in *)bb)->sin_port = 
1936
		    ((struct sockaddr_in6 *)b)->sin6_port;
1937
        } else {
1938
            return 0;
1939
	}
1824
    }
1940
    }
1825
    if (memcmp(&SINADDR(a), &SINADDR(b), sizeof(SINADDR(a))) != 0) {
1941
1826
        return 0;
1942
    if (aa->sa_family == AF_INET6) {
1943
    	if (memcmp(&((struct sockaddr_in6 *)aa)->sin6_addr, 
1944
		   &((struct sockaddr_in6 *)bb)->sin6_addr, 
1945
		   sizeof(struct sockaddr_in6)) != 0) return 0;
1946
    } else { 
1947
    	if (((struct sockaddr_in *)aa)->sin_addr.s_addr != 
1948
	    ((struct sockaddr_in *)bb)->sin_addr.s_addr) return 0;
1827
    }
1949
    }
1950
    
1828
    return 1;
1951
    return 1;
1829
}
1952
}
1830
1953
1954
#else 
1955
1956
static int ip_equal(const struct sockaddr *a, const struct sockaddr *b)
1957
{
1958
    daemon_assert(a != NULL);
1959
    daemon_assert(b != NULL);
1960
    daemon_assert(a->sa_family == AF_INET);
1961
    daemon_assert(b->sa_family == AF_INET);
1962
1963
    if (((struct sockaddr_in *)aa)->sin_addr.s_addr != 
1964
	((struct sockaddr_in *)bb)->sin_addr.s_addr) return 0;
1965
    
1966
    return 1;
1967
}
1968
1969
#endif
(-)oftpd-0.3.7.orig/src/ftp_session.h (-6 / +17 lines)
Lines 12-18 Link Here
12
#include <netinet/in.h>
12
#include <netinet/in.h>
13
#include <sys/types.h>
13
#include <sys/types.h>
14
#include <limits.h>
14
#include <limits.h>
15
#include "af_portability.h"
16
#include "watchdog.h"
15
#include "watchdog.h"
17
#include "error.h"
16
#include "error.h"
18
17
Lines 54-65 Link Here
54
    int epsv_all_set;
53
    int epsv_all_set;
55
54
56
    /* address of client */
55
    /* address of client */
57
    sockaddr_storage_t client_addr;
56
#ifdef INET6
57
    struct sockaddr_storage client_addr;
58
#else
59
    struct sockaddr_in client_addr;
60
#endif
58
    char client_addr_str[ADDRPORT_STRLEN];
61
    char client_addr_str[ADDRPORT_STRLEN];
59
62
60
    /* address of server (including IPv4 version) */
63
    /* address of server (including IPv4 version) */
61
    sockaddr_storage_t server_addr;
64
#ifdef INET6
65
    struct sockaddr_storage server_addr;
62
    struct sockaddr_in server_ipv4_addr;
66
    struct sockaddr_in server_ipv4_addr;
67
#else
68
    struct sockaddr_in server_addr;
69
#endif
63
70
64
    /* telnet session to encapsulate control channel logic */
71
    /* telnet session to encapsulate control channel logic */
65
    telnet_session_t *telnet_session;
72
    telnet_session_t *telnet_session;
Lines 70-76 Link Here
70
    /* data channel information, including type, 
77
    /* data channel information, including type, 
71
      and client address or server port depending on type */
78
      and client address or server port depending on type */
72
    int data_channel;
79
    int data_channel;
73
    sockaddr_storage_t data_port;
80
#ifdef INET6
81
    struct sockaddr_storage data_port;
82
#else
83
    struct sockaddr_in data_port;
84
#endif
74
    int server_fd;
85
    int server_fd;
75
86
76
    /* watchdog to handle timeout */
87
    /* watchdog to handle timeout */
Lines 78-85 Link Here
78
} ftp_session_t;
89
} ftp_session_t;
79
90
80
int ftp_session_init(ftp_session_t *f, 
91
int ftp_session_init(ftp_session_t *f, 
81
                     const sockaddr_storage_t *client_addr, 
92
                     const struct sockaddr *client_addr, 
82
                     const sockaddr_storage_t *server_addr, 
93
                     const struct sockaddr *server_addr, 
83
                     telnet_session_t *t,
94
                     telnet_session_t *t,
84
                     const char *dir,
95
                     const char *dir,
85
                     error_t *err);
96
                     error_t *err);
(-)oftpd-0.3.7.orig/src/oftpd.c (-2 / +2 lines)
Lines 300-306 Link Here
300
300
301
301
302
    fork_ret = fork();
302
    fork_ret = fork();
303
    if (fork_ret == -1) {
303
    if (fork_ret < 0) {
304
        fprintf(stderr, "%s: error forking; %s\n", exe_name, strerror(errno));
304
        fprintf(stderr, "%s: error forking; %s\n", exe_name, strerror(errno));
305
        exit(1);
305
        exit(1);
306
    }
306
    }
Lines 313-319 Link Here
313
        exit(1);
313
        exit(1);
314
    }
314
    }
315
    fork_ret = fork();
315
    fork_ret = fork();
316
    if (fork_ret == -1) {
316
    if (fork_ret < 0) {
317
        fprintf(stderr, "%s: error forking; %s\n", exe_name, strerror(errno));
317
        fprintf(stderr, "%s: error forking; %s\n", exe_name, strerror(errno));
318
        exit(1);
318
        exit(1);
319
    }
319
    }

Return to bug 157005