1 --- a/mod_gss.c.in |
|
2 +++ b/mod_gss.c.in |
|
3 @@ -1412,6 +1412,87 @@ MODRET gss_auth(cmd_rec *cmd) { |
|
4 return HANDLED(cmd); |
|
5 } |
|
6 |
|
7 +#ifdef USE_IPV6 /* { */ |
|
8 +#define IPV6_STR_SIZE 128 |
|
9 + |
|
10 +static int ip6_to_str(struct in6_addr* addr, char* buf, int size) { |
|
11 + |
|
12 + const char *err; |
|
13 + |
|
14 + if(size<IPV6_STR_SIZE) |
|
15 + return 0; |
|
16 + |
|
17 + memset(buf, 0, size); |
|
18 + err=inet_ntop(AF_INET6, addr, buf, size-1); |
|
19 + if(err!=buf) |
|
20 + return 0; |
|
21 + |
|
22 + return 1; |
|
23 +} |
|
24 + |
|
25 +static int ip6_to_ip4(struct in6_addr *ip6, struct in_addr *ip4) { |
|
26 + |
|
27 + char buf[IPV6_STR_SIZE]; |
|
28 + |
|
29 + if (!ip6_to_str(ip6, buf, IPV6_STR_SIZE)) |
|
30 + return 0; |
|
31 + |
|
32 + const char *ip4_str=strrchr(buf, ':'); |
|
33 + if (ip4_str == 0) |
|
34 + return 0; |
|
35 + |
|
36 + ip4_str++; |
|
37 + if (!inet_aton(ip4_str, ip4)) |
|
38 + return 0; |
|
39 + |
|
40 + return 1; |
|
41 +} |
|
42 + |
|
43 +static int set_chan_v4mapped( |
|
44 + gss_channel_bindings_t chan, struct in_addr *ia, struct in_addr *aa) { |
|
45 + |
|
46 + if (!ip6_to_ip4(&(session.c->remote_addr->na_addr.v6.sin6_addr), ia)) |
|
47 + return 0; |
|
48 + |
|
49 + if (!ip6_to_ip4(&(session.c->local_addr->na_addr.v6.sin6_addr), aa)) |
|
50 + return 0; |
|
51 + |
|
52 + chan->initiator_addrtype = GSS_C_AF_INET; |
|
53 + chan->initiator_address.length = sizeof(struct in_addr); |
|
54 + chan->initiator_address.value = ia; |
|
55 + |
|
56 + chan->acceptor_addrtype = GSS_C_AF_INET; |
|
57 + chan->acceptor_address.length = sizeof(struct in_addr); |
|
58 + chan->acceptor_address.value = aa; |
|
59 + |
|
60 + chan->application_data.length = 0; |
|
61 + chan->application_data.value = 0; |
|
62 + |
|
63 + return 1; |
|
64 +} |
|
65 + |
|
66 +static int try_v4mapped() { |
|
67 + |
|
68 + struct in6_addr* addr; |
|
69 + |
|
70 + if (pr_netaddr_get_family(session.c->remote_addr) != AF_INET6) |
|
71 + return 0; |
|
72 + |
|
73 + if (pr_netaddr_get_family(session.c->local_addr) != AF_INET6) |
|
74 + return 0; |
|
75 + |
|
76 + addr = (struct in6_addr*)pr_netaddr_get_inaddr(session.c->remote_addr); |
|
77 + if (!IN6_IS_ADDR_V4MAPPED(addr)) |
|
78 + return 0; |
|
79 + |
|
80 + addr = (struct in6_addr*)pr_netaddr_get_inaddr(session.c->local_addr); |
|
81 + if (!IN6_IS_ADDR_V4MAPPED(addr)) |
|
82 + return 0; |
|
83 + |
|
84 + return 1; |
|
85 +} |
|
86 +#endif /* } */ |
|
87 + |
|
88 /* |
|
89 AUTHENTICATION/SECURITY DATA (ADAT) |
|
90 |
|
91 @@ -1527,6 +1608,12 @@ MODRET gss_adat(cmd_rec *cmd) { |
|
92 char *gbuf ; |
|
93 |
|
94 gss_channel_bindings_t chan=GSS_C_NO_CHANNEL_BINDINGS; |
|
95 + gss_channel_bindings_t chan_sl=GSS_C_NO_CHANNEL_BINDINGS; |
|
96 +#ifdef USE_IPV6 |
|
97 + gss_channel_bindings_t chan_v4m=GSS_C_NO_CHANNEL_BINDINGS; |
|
98 + struct in_addr ia; |
|
99 + struct in_addr aa; |
|
100 +#endif |
|
101 |
|
102 if (!gss_engine) |
|
103 return DECLINED(cmd); |
|
104 @@ -1631,13 +1718,22 @@ MODRET gss_adat(cmd_rec *cmd) { |
|
105 continue; |
|
106 } |
|
107 |
|
108 + chan_sl = chan; |
|
109 +#ifdef USE_IPV6 |
|
110 + if (try_v4mapped()) { |
|
111 + chan_v4m = pcalloc(cmd->tmp_pool,sizeof(*chan_v4m)); |
|
112 + if (set_chan_v4mapped(chan_v4m, &ia, &aa)) |
|
113 + chan_sl = chan_v4m; |
|
114 + } |
|
115 +#endif |
|
116 + |
|
117 found++; |
|
118 gcontext = GSS_C_NO_CONTEXT; |
|
119 accept_maj = gss_accept_sec_context(&accept_min, |
|
120 &gcontext, /* context_handle */ |
|
121 server_creds, /* verifier_cred_handle */ |
|
122 &tok, /* input_token */ |
|
123 - chan, /* channel bindings */ |
|
124 + chan_sl, /* channel bindings */ |
|
125 &client, /* src_name */ |
|
126 &mechid, /* mech_type */ |
|
127 &out_tok, /* output_token */ |
|
128 |
|