git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@4843 e7ae566f-a301-0410-adde-c780ea21d3b5
james authored on 2009/08/23 03:29:20... | ... |
@@ -1186,6 +1186,44 @@ create_temp_filename (const char *directory, const char *prefix, struct gc_arena |
1186 | 1186 |
return gen_path (directory, BSTR (&fname), gc); |
1187 | 1187 |
} |
1188 | 1188 |
|
1189 |
+/* |
|
1190 |
+ * Add a random string to first DNS label of hostname to prevent DNS caching. |
|
1191 |
+ * For example, foo.bar.gov would be modified to <random-chars>.foo.bar.gov. |
|
1192 |
+ * Of course, this requires explicit support in the DNS server. |
|
1193 |
+ */ |
|
1194 |
+const char * |
|
1195 |
+hostname_randomize(const char *hostname, struct gc_arena *gc) |
|
1196 |
+{ |
|
1197 |
+ const int n_rnd_bytes = 6; |
|
1198 |
+ |
|
1199 |
+ char *hst = string_alloc(hostname, gc); |
|
1200 |
+ char *dot = strchr(hst, '.'); |
|
1201 |
+ |
|
1202 |
+ if (dot) |
|
1203 |
+ { |
|
1204 |
+ uint8_t rnd_bytes[n_rnd_bytes]; |
|
1205 |
+ const char *rnd_str; |
|
1206 |
+ struct buffer hname = alloc_buf_gc (strlen(hostname)+sizeof(rnd_bytes)*2+4, gc); |
|
1207 |
+ |
|
1208 |
+ *dot++ = '\0'; |
|
1209 |
+ prng_bytes (rnd_bytes, sizeof (rnd_bytes)); |
|
1210 |
+ rnd_str = format_hex_ex (rnd_bytes, sizeof (rnd_bytes), 40, 0, NULL, gc); |
|
1211 |
+ buf_printf(&hname, "%s-0x%s.%s", hst, rnd_str, dot); |
|
1212 |
+ return BSTR(&hname); |
|
1213 |
+ } |
|
1214 |
+ else |
|
1215 |
+ return hostname; |
|
1216 |
+} |
|
1217 |
+ |
|
1218 |
+#else |
|
1219 |
+ |
|
1220 |
+const char * |
|
1221 |
+hostname_randomize(const char *hostname, struct gc_arena *gc) |
|
1222 |
+{ |
|
1223 |
+ msg (M_WARN, "WARNING: hostname randomization disabled when crypto support is not compiled"); |
|
1224 |
+ return hostname; |
|
1225 |
+} |
|
1226 |
+ |
|
1189 | 1227 |
#endif |
1190 | 1228 |
|
1191 | 1229 |
/* |
... | ... |
@@ -230,6 +230,9 @@ bool delete_file (const char *filename); |
230 | 230 |
/* return true if pathname is absolute */ |
231 | 231 |
bool absolute_pathname (const char *pathname); |
232 | 232 |
|
233 |
+/* prepend a random prefix to hostname (need USE_CRYPTO) */ |
|
234 |
+const char *hostname_randomize(const char *hostname, struct gc_arena *gc); |
|
235 |
+ |
|
233 | 236 |
/* |
234 | 237 |
* Get and store a username/password |
235 | 238 |
*/ |
... | ... |
@@ -90,6 +90,7 @@ static const char usage_message[] = |
90 | 90 |
"--local host : Local host name or ip address. Implies --bind.\n" |
91 | 91 |
"--remote host [port] : Remote host name or ip address.\n" |
92 | 92 |
"--remote-random : If multiple --remote options specified, choose one randomly.\n" |
93 |
+ "--remote-random-hostname : Add a random string to remote DNS name.\n" |
|
93 | 94 |
"--mode m : Major mode, m = 'p2p' (default, point-to-point) or 'server'.\n" |
94 | 95 |
"--proto p : Use protocol p for communicating with peer.\n" |
95 | 96 |
" p = udp (default), tcp-server, or tcp-client\n" |
... | ... |
@@ -4420,15 +4421,27 @@ add_option (struct options *options, |
4420 | 4420 |
} |
4421 | 4421 |
options->routes->flags |= RG_ENABLE; |
4422 | 4422 |
} |
4423 |
+ else if (streq (p[0], "remote-random-hostname")) |
|
4424 |
+ { |
|
4425 |
+ VERIFY_PERMISSION (OPT_P_GENERAL); |
|
4426 |
+ options->sockflags |= SF_HOST_RANDOMIZE; |
|
4427 |
+ } |
|
4423 | 4428 |
else if (streq (p[0], "setenv") && p[1]) |
4424 | 4429 |
{ |
4425 | 4430 |
VERIFY_PERMISSION (OPT_P_GENERAL); |
4426 |
- if (streq (p[1], "FORWARD_COMPATIBLE") && p[2] && streq (p[2], "1")) |
|
4431 |
+ if (streq (p[1], "REMOTE_RANDOM_HOSTNAME")) |
|
4432 |
+ { |
|
4433 |
+ options->sockflags |= SF_HOST_RANDOMIZE; |
|
4434 |
+ } |
|
4435 |
+ else |
|
4427 | 4436 |
{ |
4428 |
- options->forward_compatible = true; |
|
4429 |
- msglevel_fc = msglevel_forward_compatible (options, msglevel); |
|
4437 |
+ if (streq (p[1], "FORWARD_COMPATIBLE") && p[2] && streq (p[2], "1")) |
|
4438 |
+ { |
|
4439 |
+ options->forward_compatible = true; |
|
4440 |
+ msglevel_fc = msglevel_forward_compatible (options, msglevel); |
|
4441 |
+ } |
|
4442 |
+ setenv_str (es, p[1], p[2] ? p[2] : ""); |
|
4430 | 4443 |
} |
4431 |
- setenv_str (es, p[1], p[2] ? p[2] : ""); |
|
4432 | 4444 |
} |
4433 | 4445 |
else if (streq (p[0], "setenv-safe") && p[1]) |
4434 | 4446 |
{ |
... | ... |
@@ -32,6 +32,7 @@ |
32 | 32 |
#include "plugin.h" |
33 | 33 |
#include "ps.h" |
34 | 34 |
#include "manage.h" |
35 |
+#include "misc.h" |
|
35 | 36 |
|
36 | 37 |
#include "memdbg.h" |
37 | 38 |
|
... | ... |
@@ -43,6 +44,19 @@ const int proto_overhead[] = { /* indexed by PROTO_x */ |
43 | 43 |
}; |
44 | 44 |
|
45 | 45 |
/* |
46 |
+ * Convert sockflags/getaddr_flags into getaddr_flags |
|
47 |
+ */ |
|
48 |
+static unsigned int |
|
49 |
+sf2gaf(const unsigned int getaddr_flags, |
|
50 |
+ const unsigned int sockflags) |
|
51 |
+{ |
|
52 |
+ if (sockflags & SF_HOST_RANDOMIZE) |
|
53 |
+ return getaddr_flags | GETADDR_RANDOMIZE; |
|
54 |
+ else |
|
55 |
+ return getaddr_flags; |
|
56 |
+} |
|
57 |
+ |
|
58 |
+/* |
|
46 | 59 |
* Functions related to the translation of DNS names to IP addresses. |
47 | 60 |
*/ |
48 | 61 |
|
... | ... |
@@ -79,6 +93,10 @@ getaddr (unsigned int flags, |
79 | 79 |
int status; |
80 | 80 |
int sigrec = 0; |
81 | 81 |
int msglevel = (flags & GETADDR_FATAL) ? M_FATAL : D_RESOLVE_ERRORS; |
82 |
+ struct gc_arena gc = gc_new (); |
|
83 |
+ |
|
84 |
+ if (flags & GETADDR_RANDOMIZE) |
|
85 |
+ hostname = hostname_randomize(hostname, &gc); |
|
82 | 86 |
|
83 | 87 |
if (flags & GETADDR_MSG_VIRT_OUT) |
84 | 88 |
msglevel |= M_MSG_VIRT_OUT; |
... | ... |
@@ -225,6 +243,7 @@ getaddr (unsigned int flags, |
225 | 225 |
msg (level, "RESOLVE: signal received during DNS resolution attempt"); |
226 | 226 |
} |
227 | 227 |
|
228 |
+ gc_free (&gc); |
|
228 | 229 |
return (flags & GETADDR_HOST_ORDER) ? ntohl (ia.s_addr) : ia.s_addr; |
229 | 230 |
} |
230 | 231 |
|
... | ... |
@@ -359,12 +378,13 @@ mac_addr_safe (const char *mac_addr) |
359 | 359 |
static void |
360 | 360 |
update_remote (const char* host, |
361 | 361 |
struct openvpn_sockaddr *addr, |
362 |
- bool *changed) |
|
362 |
+ bool *changed, |
|
363 |
+ const unsigned int sockflags) |
|
363 | 364 |
{ |
364 | 365 |
if (host && addr) |
365 | 366 |
{ |
366 | 367 |
const in_addr_t new_addr = getaddr ( |
367 |
- GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, |
|
368 |
+ sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sockflags), |
|
368 | 369 |
host, |
369 | 370 |
1, |
370 | 371 |
NULL, |
... | ... |
@@ -728,7 +748,7 @@ socket_listen_accept (socket_descriptor_t sd, |
728 | 728 |
|
729 | 729 |
if (socket_defined (new_sd)) |
730 | 730 |
{ |
731 |
- update_remote (remote_dynamic, &remote_verify, remote_changed); |
|
731 |
+ update_remote (remote_dynamic, &remote_verify, remote_changed, 0); |
|
732 | 732 |
if (addr_defined (&remote_verify) |
733 | 733 |
&& !addr_match (&remote_verify, &act->dest)) |
734 | 734 |
{ |
... | ... |
@@ -858,6 +878,7 @@ socket_connect (socket_descriptor_t *sd, |
858 | 858 |
const int connect_retry_seconds, |
859 | 859 |
const int connect_timeout, |
860 | 860 |
const int connect_retry_max, |
861 |
+ const unsigned int sockflags, |
|
861 | 862 |
volatile int *signal_received) |
862 | 863 |
{ |
863 | 864 |
struct gc_arena gc = gc_new (); |
... | ... |
@@ -919,7 +940,7 @@ socket_connect (socket_descriptor_t *sd, |
919 | 919 |
*sd = create_socket_tcp (); |
920 | 920 |
if (bind_local) |
921 | 921 |
socket_bind (*sd, local, "TCP Client"); |
922 |
- update_remote (remote_dynamic, remote, remote_changed); |
|
922 |
+ update_remote (remote_dynamic, remote, remote_changed, sockflags); |
|
923 | 923 |
} |
924 | 924 |
|
925 | 925 |
msg (M_INFO, "TCP connection established with %s", |
... | ... |
@@ -1023,7 +1044,7 @@ resolve_remote (struct link_socket *sock, |
1023 | 1023 |
|
1024 | 1024 |
if (sock->remote_host) |
1025 | 1025 |
{ |
1026 |
- unsigned int flags = GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE; |
|
1026 |
+ unsigned int flags = sf2gaf(GETADDR_RESOLVE|GETADDR_UPDATE_MANAGEMENT_STATE, sock->sockflags); |
|
1027 | 1027 |
int retry = 0; |
1028 | 1028 |
bool status = false; |
1029 | 1029 |
|
... | ... |
@@ -1384,6 +1405,7 @@ link_socket_init_phase2 (struct link_socket *sock, |
1384 | 1384 |
sock->connect_retry_seconds, |
1385 | 1385 |
sock->connect_timeout, |
1386 | 1386 |
sock->connect_retry_max, |
1387 |
+ sock->sockflags, |
|
1387 | 1388 |
signal_received); |
1388 | 1389 |
|
1389 | 1390 |
if (*signal_received) |
... | ... |
@@ -1432,6 +1454,7 @@ link_socket_init_phase2 (struct link_socket *sock, |
1432 | 1432 |
sock->connect_retry_seconds, |
1433 | 1433 |
sock->connect_timeout, |
1434 | 1434 |
sock->connect_retry_max, |
1435 |
+ sock->sockflags, |
|
1435 | 1436 |
signal_received); |
1436 | 1437 |
|
1437 | 1438 |
if (*signal_received) |
... | ... |
@@ -198,6 +198,7 @@ struct link_socket |
198 | 198 |
# define SF_USE_IP_PKTINFO (1<<0) |
199 | 199 |
# define SF_TCP_NODELAY (1<<1) |
200 | 200 |
# define SF_PORT_SHARE (1<<2) |
201 |
+# define SF_HOST_RANDOMIZE (1<<3) |
|
201 | 202 |
unsigned int sockflags; |
202 | 203 |
|
203 | 204 |
/* for stream sockets */ |
... | ... |
@@ -447,6 +448,7 @@ bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int * |
447 | 447 |
#define GETADDR_MSG_VIRT_OUT (1<<6) |
448 | 448 |
#define GETADDR_TRY_ONCE (1<<7) |
449 | 449 |
#define GETADDR_UPDATE_MANAGEMENT_STATE (1<<8) |
450 |
+#define GETADDR_RANDOMIZE (1<<9) |
|
450 | 451 |
|
451 | 452 |
in_addr_t getaddr (unsigned int flags, |
452 | 453 |
const char *hostname, |