aboutsummaryrefslogtreecommitdiffstats
path: root/ftp/tnftpd/files/patch-src-ftpd.c
blob: 2b968a6d06ca61150dea882795c8e9cf127b2068 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

Add -C user@host support instead of just -C user and add support for
IPv6 in ftpusers.

FreeBSD does not have _PASSWORD_CHGNOW defined, so use direct constant
instead.

We are sure, that we have good LOGIN_NAME_MAX from tnftpd.h, so use it
instead of unnecessarily conservative _POSIX_LOGIN_NAME_MAX.

--- src/ftpd.c.orig 2008-06-08 20:52:33.000000000 -0400
+++ src/ftpd.c  2008-06-08 20:52:33.000000000 -0400
@@ -368,6 +368,24 @@
            break;
 
        case 'C':
+           if ((p = strchr(optarg, '@')) != NULL) {
+               *p++ = '\0';
+               strlcpy(remotehost, p, MAXHOSTNAMELEN + 1);
+               if (inet_pton(AF_INET, p,
+                   &his_addr.su_addr) == 1) {
+                   his_addr.su_family = AF_INET;
+                   his_addr.su_len =
+                       sizeof(his_addr.si_su.su_sin);
+#ifdef INET6
+               } else if (inet_pton(AF_INET6, p,
+                   &his_addr.su_6addr) == 1) {
+                   his_addr.su_family = AF_INET6;
+                   his_addr.su_len =
+                       sizeof(his_addr.si_su.su_sin6);
+#endif
+               } else
+                   his_addr.su_family = AF_UNSPEC;
+           }
            pw = sgetpwnam(optarg);
            exit(checkaccess(optarg) ? 0 : 1);
            /* NOTREACHED */
@@ -497,12 +515,12 @@
        exit(1);
    } else if (l <= 0) {
        syslog(LOG_WARNING, "using conservative LOGIN_NAME_MAX value");
-       curname_len = _POSIX_LOGIN_NAME_MAX;
+       curname_len = LOGIN_NAME_MAX;
    } else 
        curname_len = (size_t)l;
 #else
    /* using conservative LOGIN_NAME_MAX value */
-   curname_len = _POSIX_LOGIN_NAME_MAX;
+   curname_len = LOGIN_NAME_MAX;
 #endif
    curname = malloc(curname_len);
    if (curname == NULL) {
@@ -1179,18 +1197,38 @@
 
                    /* have a host specifier */
        if ((p = strchr(word, '@')) != NULL) {
-           unsigned long   net, mask, addr;
-           int     bits;
+           char        net[16], mask[16], *addr;
+           int     addrlen, bits, bytes, a;
 
            *p++ = '\0';
                    /* check against network or CIDR */
-           if (isdigit((unsigned char)*p) &&
-               (bits = inet_net_pton(AF_INET, p,
-               &net, sizeof(net))) != -1) {
-               net = ntohl(net);
-               mask = 0xffffffffU << (32 - bits);
-               addr = ntohl(his_addr.su_addr.s_addr);
-               if ((addr & mask) != net)
+           memset(net, 0x00, sizeof(net));
+           if ((bits = inet_net_pton(his_addr.su_family, p, net,
+               sizeof(net))) != -1) {
+#ifdef INET6
+               if (his_addr.su_family == AF_INET) {
+#endif
+                   addrlen = 4;
+                   addr = (char *)&his_addr.su_addr;
+#ifdef INET6
+               } else {
+                   addrlen = 16;
+                   addr = (char *)&his_addr.su_6addr;
+               }
+#endif
+               bytes = bits / 8;
+               bits = bits % 8;
+               if (bytes > 0)
+                   memset(mask, 0xFF, bytes);
+               if (bytes < addrlen)
+                   mask[bytes] = 0xFF << (8 - bits);
+               if (bytes + 1 < addrlen)
+                   memset(mask + bytes + 1, 0x00,
+                       addrlen - bytes - 1);
+               for (a = 0; a < addrlen; a++)
+                   if ((addr[a] & mask[a]) != net[a])
+                       break;
+               if (a < addrlen)
                    continue;
 
                    /* check against hostname glob */
@@ -3776,7 +3814,7 @@
    expire = pwent->pw_expire;
 #endif
 #if defined(HAVE_STRUCT_PASSWD_PW_CHANGE)
-   change = (pwent->pw_change == _PASSWORD_CHGNOW)? now : pwent->pw_change;
+   change = (pwent->pw_change == -1)? now : pwent->pw_change;
 #endif
 #endif