Version 2.1.1i
git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@5668 e7ae566f-a301-0410-adde-c780ea21d3b5
... | ... |
@@ -76,8 +76,15 @@ typedef unsigned long ptr_type; |
76 | 76 |
/* |
77 | 77 |
* This parameter controls the TLS channel buffer size and the |
78 | 78 |
* maximum size of a single TLS message (cleartext). |
79 |
+ * This parameter must be >= PUSH_BUNDLE_SIZE |
|
79 | 80 |
*/ |
80 |
-#define TLS_CHANNEL_BUF_SIZE 1024 |
|
81 |
+#define TLS_CHANNEL_BUF_SIZE 2048 |
|
82 |
+ |
|
83 |
+/* |
|
84 |
+ * This parameter controls the maximum size of a bundle |
|
85 |
+ * of pushed options. |
|
86 |
+ */ |
|
87 |
+#define PUSH_BUNDLE_SIZE 1024 |
|
81 | 88 |
|
82 | 89 |
/* |
83 | 90 |
* A sort of pseudo-filename for data provided inline within |
... | ... |
@@ -2007,6 +2007,9 @@ do_init_crypto_tls (struct context *c, const unsigned int flags) |
2007 | 2007 |
to.renegotiate_packets = options->renegotiate_packets; |
2008 | 2008 |
to.renegotiate_seconds = options->renegotiate_seconds; |
2009 | 2009 |
to.single_session = options->single_session; |
2010 |
+#ifdef ENABLE_PUSH_PEER_INFO |
|
2011 |
+ to.push_peer_info = options->push_peer_info; |
|
2012 |
+#endif |
|
2010 | 2013 |
|
2011 | 2014 |
/* should we not xmit any packets until we get an initial |
2012 | 2015 |
response from client? */ |
... | ... |
@@ -2275,6 +2275,58 @@ man_output_extra_env (struct management *man) |
2275 | 2275 |
gc_free (&gc); |
2276 | 2276 |
} |
2277 | 2277 |
|
2278 |
+static bool |
|
2279 |
+validate_peer_info_line(const char *line) |
|
2280 |
+{ |
|
2281 |
+ uint8_t c; |
|
2282 |
+ int state = 0; |
|
2283 |
+ while ((c=*line++)) |
|
2284 |
+ { |
|
2285 |
+ switch (state) |
|
2286 |
+ { |
|
2287 |
+ case 0: |
|
2288 |
+ case 1: |
|
2289 |
+ if (c == '=' && state == 1) |
|
2290 |
+ state = 2; |
|
2291 |
+ else if (isalnum(c) || c == '_') |
|
2292 |
+ state = 1; |
|
2293 |
+ else |
|
2294 |
+ return false; |
|
2295 |
+ case 2: |
|
2296 |
+ if (isprint(c)) |
|
2297 |
+ ; |
|
2298 |
+ else |
|
2299 |
+ return false; |
|
2300 |
+ } |
|
2301 |
+ } |
|
2302 |
+ return (state == 2); |
|
2303 |
+} |
|
2304 |
+ |
|
2305 |
+static void |
|
2306 |
+man_output_peer_info_env (struct management *man, struct man_def_auth_context *mdac) |
|
2307 |
+{ |
|
2308 |
+ char line[256]; |
|
2309 |
+ if (man->persist.callback.get_peer_info) |
|
2310 |
+ { |
|
2311 |
+ const char *peer_info = (*man->persist.callback.get_peer_info) (man->persist.callback.arg, mdac->cid); |
|
2312 |
+ if (peer_info) |
|
2313 |
+ { |
|
2314 |
+ struct buffer buf; |
|
2315 |
+ buf_set_read (&buf, (const uint8_t *) peer_info, strlen(peer_info)); |
|
2316 |
+ while (buf_parse (&buf, '\n', line, sizeof (line))) |
|
2317 |
+ { |
|
2318 |
+ chomp (line); |
|
2319 |
+ if (validate_peer_info_line(line)) |
|
2320 |
+ { |
|
2321 |
+ msg (M_CLIENT, ">CLIENT:ENV,%s", line); |
|
2322 |
+ } |
|
2323 |
+ else |
|
2324 |
+ msg (D_MANAGEMENT, "validation failed on peer_info line received from client"); |
|
2325 |
+ } |
|
2326 |
+ } |
|
2327 |
+ } |
|
2328 |
+} |
|
2329 |
+ |
|
2278 | 2330 |
void |
2279 | 2331 |
management_notify_client_needing_auth (struct management *management, |
2280 | 2332 |
const unsigned int mda_key_id, |
... | ... |
@@ -2288,6 +2340,7 @@ management_notify_client_needing_auth (struct management *management, |
2288 | 2288 |
mode = "REAUTH"; |
2289 | 2289 |
msg (M_CLIENT, ">CLIENT:%s,%lu,%u", mode, mdac->cid, mda_key_id); |
2290 | 2290 |
man_output_extra_env (management); |
2291 |
+ man_output_peer_info_env(management, mdac); |
|
2291 | 2292 |
man_output_env (es, true, management->connection.env_filter_level); |
2292 | 2293 |
mdac->flags |= DAF_INITIAL_AUTH; |
2293 | 2294 |
} |
... | ... |
@@ -164,6 +164,7 @@ struct management_callback |
164 | 164 |
const char *reason, |
165 | 165 |
const char *client_reason, |
166 | 166 |
struct buffer_list *cc_config); /* ownership transferred */ |
167 |
+ char *(*get_peer_info) (void *arg, const unsigned long cid); |
|
167 | 168 |
#endif |
168 | 169 |
#ifdef MANAGEMENT_PF |
169 | 170 |
bool (*client_pf) (void *arg, |
... | ... |
@@ -2597,6 +2597,20 @@ management_client_auth (void *arg, |
2597 | 2597 |
buffer_list_free (cc_config); |
2598 | 2598 |
return ret; |
2599 | 2599 |
} |
2600 |
+ |
|
2601 |
+static char * |
|
2602 |
+management_get_peer_info (void *arg, const unsigned long cid) |
|
2603 |
+{ |
|
2604 |
+ struct multi_context *m = (struct multi_context *) arg; |
|
2605 |
+ struct multi_instance *mi = lookup_by_cid (m, cid); |
|
2606 |
+ char *ret = NULL; |
|
2607 |
+ |
|
2608 |
+ if (mi) |
|
2609 |
+ ret = tls_get_peer_info (mi->context.c2.tls_multi); |
|
2610 |
+ |
|
2611 |
+ return ret; |
|
2612 |
+} |
|
2613 |
+ |
|
2600 | 2614 |
#endif |
2601 | 2615 |
|
2602 | 2616 |
#ifdef MANAGEMENT_PF |
... | ... |
@@ -2637,6 +2651,7 @@ init_management_callback_multi (struct multi_context *m) |
2637 | 2637 |
#ifdef MANAGEMENT_DEF_AUTH |
2638 | 2638 |
cb.kill_by_cid = management_kill_by_cid; |
2639 | 2639 |
cb.client_auth = management_client_auth; |
2640 |
+ cb.get_peer_info = management_get_peer_info; |
|
2640 | 2641 |
#endif |
2641 | 2642 |
#ifdef MANAGEMENT_PF |
2642 | 2643 |
cb.client_pf = management_client_pf; |
... | ... |
@@ -196,6 +196,9 @@ static const char usage_message[] = |
196 | 196 |
" Add 'bypass-dns' flag to similarly bypass tunnel for DNS.\n" |
197 | 197 |
"--redirect-private [flags]: Like --redirect-gateway, but omit actually changing\n" |
198 | 198 |
" the default gateway. Useful when pushing private subnets.\n" |
199 |
+#ifdef ENABLE_PUSH_PEER_INFO |
|
200 |
+ "--push-peer-info : (client only) push client info to server.\n" |
|
201 |
+#endif |
|
199 | 202 |
"--setenv name value : Set a custom environmental variable to pass to script.\n" |
200 | 203 |
"--setenv FORWARD_COMPATIBLE 1 : Relax config file syntax checking to allow\n" |
201 | 204 |
" directives for future OpenVPN versions to be ignored.\n" |
... | ... |
@@ -1348,6 +1351,9 @@ show_settings (const struct options *o) |
1348 | 1348 |
SHOW_INT (transition_window); |
1349 | 1349 |
|
1350 | 1350 |
SHOW_BOOL (single_session); |
1351 |
+#ifdef ENABLE_PUSH_PEER_INFO |
|
1352 |
+ SHOW_BOOL (push_peer_info); |
|
1353 |
+#endif |
|
1351 | 1354 |
SHOW_BOOL (tls_exit); |
1352 | 1355 |
|
1353 | 1356 |
SHOW_STR (tls_auth_file); |
... | ... |
@@ -2057,6 +2063,9 @@ options_postprocess_verify_ce (const struct options *options, const struct conne |
2057 | 2057 |
MUST_BE_UNDEF (transition_window); |
2058 | 2058 |
MUST_BE_UNDEF (tls_auth_file); |
2059 | 2059 |
MUST_BE_UNDEF (single_session); |
2060 |
+#ifdef ENABLE_PUSH_PEER_INFO |
|
2061 |
+ MUST_BE_UNDEF (push_peer_info); |
|
2062 |
+#endif |
|
2060 | 2063 |
MUST_BE_UNDEF (tls_exit); |
2061 | 2064 |
MUST_BE_UNDEF (crl_file); |
2062 | 2065 |
MUST_BE_UNDEF (key_method); |
... | ... |
@@ -5672,6 +5681,13 @@ add_option (struct options *options, |
5672 | 5672 |
VERIFY_PERMISSION (OPT_P_GENERAL); |
5673 | 5673 |
options->single_session = true; |
5674 | 5674 |
} |
5675 |
+#ifdef ENABLE_PUSH_PEER_INFO |
|
5676 |
+ else if (streq (p[0], "push-peer-info")) |
|
5677 |
+ { |
|
5678 |
+ VERIFY_PERMISSION (OPT_P_GENERAL); |
|
5679 |
+ options->push_peer_info = true; |
|
5680 |
+ } |
|
5681 |
+#endif |
|
5675 | 5682 |
else if (streq (p[0], "tls-exit")) |
5676 | 5683 |
{ |
5677 | 5684 |
VERIFY_PERMISSION (OPT_P_GENERAL); |
... | ... |
@@ -102,8 +102,8 @@ send_auth_failed (struct context *c, const char *client_reason) |
102 | 102 |
schedule_exit (c, c->options.scheduled_exit_interval, SIGTERM); |
103 | 103 |
|
104 | 104 |
len = (client_reason ? strlen(client_reason)+1 : 0) + sizeof(auth_failed); |
105 |
- if (len > TLS_CHANNEL_BUF_SIZE) |
|
106 |
- len = TLS_CHANNEL_BUF_SIZE; |
|
105 |
+ if (len > PUSH_BUNDLE_SIZE) |
|
106 |
+ len = PUSH_BUNDLE_SIZE; |
|
107 | 107 |
|
108 | 108 |
{ |
109 | 109 |
struct buffer buf = alloc_buf_gc (len, &gc); |
... | ... |
@@ -171,7 +171,7 @@ bool |
171 | 171 |
send_push_reply (struct context *c) |
172 | 172 |
{ |
173 | 173 |
struct gc_arena gc = gc_new (); |
174 |
- struct buffer buf = alloc_buf_gc (TLS_CHANNEL_BUF_SIZE, &gc); |
|
174 |
+ struct buffer buf = alloc_buf_gc (PUSH_BUNDLE_SIZE, &gc); |
|
175 | 175 |
struct push_entry *e = c->options.push_list.head; |
176 | 176 |
bool multi_push = false; |
177 | 177 |
static char cmd[] = "PUSH_REPLY"; |
... | ... |
@@ -174,7 +174,7 @@ bool get_default_gateway (in_addr_t *ip, in_addr_t *netmask); |
174 | 174 |
#define TLA_LOCAL 2 |
175 | 175 |
int test_local_addr (const in_addr_t addr); |
176 | 176 |
|
177 |
-#if AUTO_USERID |
|
177 |
+#if AUTO_USERID || defined(ENABLE_PUSH_PEER_INFO) |
|
178 | 178 |
bool get_default_gateway_mac_addr (unsigned char *macaddr); |
179 | 179 |
#endif |
180 | 180 |
|
... | ... |
@@ -2558,6 +2558,8 @@ tls_multi_free (struct tls_multi *multi, bool clear) |
2558 | 2558 |
|
2559 | 2559 |
#ifdef MANAGEMENT_DEF_AUTH |
2560 | 2560 |
man_def_auth_set_client_reason(multi, NULL); |
2561 |
+ |
|
2562 |
+ free (multi->peer_info); |
|
2561 | 2563 |
#endif |
2562 | 2564 |
|
2563 | 2565 |
if (multi->locked_cn) |
... | ... |
@@ -3106,6 +3108,14 @@ write_string (struct buffer *buf, const char *str, const int maxlen) |
3106 | 3106 |
} |
3107 | 3107 |
|
3108 | 3108 |
static bool |
3109 |
+write_empty_string (struct buffer *buf) |
|
3110 |
+{ |
|
3111 |
+ if (!buf_write_u16 (buf, 0)) |
|
3112 |
+ return false; |
|
3113 |
+ return true; |
|
3114 |
+} |
|
3115 |
+ |
|
3116 |
+static bool |
|
3109 | 3117 |
read_string (struct buffer *buf, char *str, const unsigned int capacity) |
3110 | 3118 |
{ |
3111 | 3119 |
const int len = buf_read_u16 (buf); |
... | ... |
@@ -3117,6 +3127,33 @@ read_string (struct buffer *buf, char *str, const unsigned int capacity) |
3117 | 3117 |
return true; |
3118 | 3118 |
} |
3119 | 3119 |
|
3120 |
+static char * |
|
3121 |
+read_string_alloc (struct buffer *buf) |
|
3122 |
+{ |
|
3123 |
+ const int len = buf_read_u16 (buf); |
|
3124 |
+ char *str; |
|
3125 |
+ |
|
3126 |
+ if (len < 1) |
|
3127 |
+ return NULL; |
|
3128 |
+ str = (char *) malloc(len); |
|
3129 |
+ check_malloc_return(str); |
|
3130 |
+ if (!buf_read (buf, str, len)) |
|
3131 |
+ { |
|
3132 |
+ free (str); |
|
3133 |
+ return NULL; |
|
3134 |
+ } |
|
3135 |
+ str[len-1] = '\0'; |
|
3136 |
+ return str; |
|
3137 |
+} |
|
3138 |
+ |
|
3139 |
+void |
|
3140 |
+read_string_discard (struct buffer *buf) |
|
3141 |
+{ |
|
3142 |
+ char *data = read_string_alloc(buf); |
|
3143 |
+ if (data) |
|
3144 |
+ free (data); |
|
3145 |
+} |
|
3146 |
+ |
|
3120 | 3147 |
/* |
3121 | 3148 |
* Authenticate a client using username/password. |
3122 | 3149 |
* Runs on server. |
... | ... |
@@ -3328,6 +3365,73 @@ key_method_1_write (struct buffer *buf, struct tls_session *session) |
3328 | 3328 |
} |
3329 | 3329 |
|
3330 | 3330 |
static bool |
3331 |
+push_peer_info(struct buffer *buf, struct tls_session *session) |
|
3332 |
+{ |
|
3333 |
+ struct gc_arena gc = gc_new (); |
|
3334 |
+ bool ret = false; |
|
3335 |
+ |
|
3336 |
+#ifdef ENABLE_PUSH_PEER_INFO |
|
3337 |
+ if (session->opt->push_peer_info) /* write peer info */ |
|
3338 |
+ { |
|
3339 |
+ struct env_set *es = session->opt->es; |
|
3340 |
+ struct env_item *e; |
|
3341 |
+ struct buffer out = alloc_buf_gc (512*3, &gc); |
|
3342 |
+ |
|
3343 |
+ /* push version */ |
|
3344 |
+ buf_printf (&out, "IV_VER=%s\n", PACKAGE_VERSION); |
|
3345 |
+ |
|
3346 |
+ /* push platform */ |
|
3347 |
+#if defined(TARGET_LINUX) |
|
3348 |
+ buf_printf (&out, "IV_PLAT=linux\n"); |
|
3349 |
+#elif defined(TARGET_SOLARIS) |
|
3350 |
+ buf_printf (&out, "IV_PLAT=solaris\n"); |
|
3351 |
+#elif defined(TARGET_OPENBSD) |
|
3352 |
+ buf_printf (&out, "IV_PLAT=openbsd\n"); |
|
3353 |
+#elif defined(TARGET_DARWIN) |
|
3354 |
+ buf_printf (&out, "IV_PLAT=mac\n"); |
|
3355 |
+#elif defined(TARGET_NETBSD) |
|
3356 |
+ buf_printf (&out, "IV_PLAT=netbsd\n"); |
|
3357 |
+#elif defined(TARGET_FREEBSD) |
|
3358 |
+ buf_printf (&out, "IV_PLAT=freebsd\n"); |
|
3359 |
+#elif defined(WIN32) |
|
3360 |
+ buf_printf (&out, "IV_PLAT=win\n"); |
|
3361 |
+#endif |
|
3362 |
+ |
|
3363 |
+ /* push mac addr */ |
|
3364 |
+ { |
|
3365 |
+ bool get_default_gateway_mac_addr (unsigned char *macaddr); |
|
3366 |
+ uint8_t macaddr[6]; |
|
3367 |
+ get_default_gateway_mac_addr (macaddr); |
|
3368 |
+ buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (macaddr, 6, 0, 1, ":", &gc)); |
|
3369 |
+ } |
|
3370 |
+ |
|
3371 |
+ /* push env vars that begin with UV_ */ |
|
3372 |
+ for (e=es->list; e != NULL; e=e->next) |
|
3373 |
+ { |
|
3374 |
+ if (e->string) |
|
3375 |
+ { |
|
3376 |
+ if (!strncmp(e->string, "UV_", 3) && buf_safe(&out, strlen(e->string)+1)) |
|
3377 |
+ buf_printf (&out, "%s\n", e->string); |
|
3378 |
+ } |
|
3379 |
+ } |
|
3380 |
+ |
|
3381 |
+ if (!write_string(buf, BSTR(&out), -1)) |
|
3382 |
+ goto error; |
|
3383 |
+ } |
|
3384 |
+ else |
|
3385 |
+#endif |
|
3386 |
+ { |
|
3387 |
+ if (!write_empty_string (buf)) /* no peer info */ |
|
3388 |
+ goto error; |
|
3389 |
+ } |
|
3390 |
+ ret = true; |
|
3391 |
+ |
|
3392 |
+ error: |
|
3393 |
+ gc_free (&gc); |
|
3394 |
+ return ret; |
|
3395 |
+} |
|
3396 |
+ |
|
3397 |
+static bool |
|
3331 | 3398 |
key_method_2_write (struct buffer *buf, struct tls_session *session) |
3332 | 3399 |
{ |
3333 | 3400 |
ASSERT (session->opt->key_method == 2); |
... | ... |
@@ -3361,6 +3465,16 @@ key_method_2_write (struct buffer *buf, struct tls_session *session) |
3361 | 3361 |
goto error; |
3362 | 3362 |
purge_user_pass (&auth_user_pass, false); |
3363 | 3363 |
} |
3364 |
+ else |
|
3365 |
+ { |
|
3366 |
+ if (!write_empty_string (buf)) /* no username */ |
|
3367 |
+ goto error; |
|
3368 |
+ if (!write_empty_string (buf)) /* no password */ |
|
3369 |
+ goto error; |
|
3370 |
+ } |
|
3371 |
+ |
|
3372 |
+ if (!push_peer_info (buf, session)) |
|
3373 |
+ goto error; |
|
3364 | 3374 |
|
3365 | 3375 |
/* |
3366 | 3376 |
* generate tunnel keys if server |
... | ... |
@@ -3507,11 +3621,13 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi |
3507 | 3507 |
int s1 = OPENVPN_PLUGIN_FUNC_SUCCESS; |
3508 | 3508 |
bool s2 = true; |
3509 | 3509 |
char *raw_username; |
3510 |
+ bool username_status, password_status; |
|
3510 | 3511 |
|
3511 | 3512 |
/* get username/password from plaintext buffer */ |
3512 | 3513 |
ALLOC_OBJ_CLEAR_GC (up, struct user_pass, &gc); |
3513 |
- if (!read_string (buf, up->username, USER_PASS_LEN) |
|
3514 |
- || !read_string (buf, up->password, USER_PASS_LEN)) |
|
3514 |
+ username_status = read_string (buf, up->username, USER_PASS_LEN); |
|
3515 |
+ password_status = read_string (buf, up->password, USER_PASS_LEN); |
|
3516 |
+ if (!username_status || !password_status) |
|
3515 | 3517 |
{ |
3516 | 3518 |
CLEAR (*up); |
3517 | 3519 |
if (!(session->opt->ssl_flags & SSLF_AUTH_USER_PASS_OPTIONAL)) |
... | ... |
@@ -3532,6 +3648,10 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi |
3532 | 3532 |
|
3533 | 3533 |
/* call plugin(s) and/or script */ |
3534 | 3534 |
#ifdef MANAGEMENT_DEF_AUTH |
3535 |
+ /* get peer info from control channel */ |
|
3536 |
+ free (multi->peer_info); |
|
3537 |
+ multi->peer_info = read_string_alloc (buf); |
|
3538 |
+ |
|
3535 | 3539 |
if (man_def_auth == KMDA_DEF) |
3536 | 3540 |
man_def_auth = verify_user_pass_management (session, up, raw_username); |
3537 | 3541 |
#endif |
... | ... |
@@ -432,6 +432,9 @@ struct tls_options |
432 | 432 |
#ifdef ENABLE_OCC |
433 | 433 |
bool disable_occ; |
434 | 434 |
#endif |
435 |
+#ifdef ENABLE_PUSH_PEER_INFO |
|
436 |
+ bool push_peer_info; |
|
437 |
+#endif |
|
435 | 438 |
int transition_window; |
436 | 439 |
int handshake_window; |
437 | 440 |
interval_t packet_timeout; |
... | ... |
@@ -618,6 +621,12 @@ struct tls_multi |
618 | 618 |
*/ |
619 | 619 |
char *client_reason; |
620 | 620 |
|
621 |
+ /* |
|
622 |
+ * A multi-line string of general-purpose info received from peer |
|
623 |
+ * over control channel. |
|
624 |
+ */ |
|
625 |
+ char *peer_info; |
|
626 |
+ |
|
621 | 627 |
/* Time of last call to tls_authentication_status */ |
622 | 628 |
time_t tas_last; |
623 | 629 |
#endif |
... | ... |
@@ -721,6 +730,12 @@ void tls_deauthenticate (struct tls_multi *multi); |
721 | 721 |
|
722 | 722 |
#ifdef MANAGEMENT_DEF_AUTH |
723 | 723 |
bool tls_authenticate_key (struct tls_multi *multi, const unsigned int mda_key_id, const bool auth, const char *client_reason); |
724 |
+ |
|
725 |
+static inline char * |
|
726 |
+tls_get_peer_info(const struct tls_multi *multi) |
|
727 |
+{ |
|
728 |
+ return multi->peer_info; |
|
729 |
+} |
|
724 | 730 |
#endif |
725 | 731 |
|
726 | 732 |
/* |