git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@4843 e7ae566f-a301-0410-adde-c780ea21d3b5
| ... | ... |
@@ -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, |