/** * Prepare push options, based on local options and available peer info. * * @param options Connection options * @param tls_multi TLS state structure for the current tunnel * * @return true on success, false on failure. */ static bool prepare_push_reply (struct options *o, struct tls_multi *tls_multi) { const char *optstr = NULL; const char * const peer_info = tls_multi->peer_info; /* Send peer-id if client supports it */ optstr = peer_info ? strstr(peer_info, "IV_PROTO=") : NULL; if (optstr) { int proto = 0; int r = sscanf(optstr, "IV_PROTO=%d", &proto); if ((r == 1) && (proto >= 2)) { push_option_fmt(o, M_USAGE, "peer-id %d", tls_multi->peer_id); } } /* Push cipher if client supports Negotiable Crypto Parameters */ if (tls_peer_info_ncp_ver (peer_info) >= 2 && o->ncp_enabled) { /* Push the first cipher from --ncp-ciphers to the client. * TODO: actual negotiation, instead of server dictatorship. */ char *push_cipher = string_alloc(o->ncp_ciphers, &o->gc); o->ciphername = strtok (push_cipher, ":"); push_option_fmt(o, M_USAGE, "cipher %s", o->ciphername); } return true; }
/** * Prepare push options, based on local options and available peer info. * * @param options Connection options * @param tls_multi TLS state structure for the current tunnel * * @return true on success, false on failure. */ static bool prepare_push_reply (struct options *o, struct tls_multi *tls_multi) { const char *optstr = NULL; const char * const peer_info = tls_multi->peer_info; /* Send peer-id if client supports it */ optstr = peer_info ? strstr(peer_info, "IV_PROTO=") : NULL; if (optstr) { int proto = 0; int r = sscanf(optstr, "IV_PROTO=%d", &proto); if ((r == 1) && (proto >= 2)) { push_option_fmt(o, M_USAGE, "peer-id %d", tls_multi->peer_id); } } /* Push cipher if client supports Negotiable Crypto Parameters */ optstr = peer_info ? strstr(peer_info, "IV_NCP=") : NULL; if (optstr) { int ncp = 0; int r = sscanf(optstr, "IV_NCP=%d", &ncp); if ((r == 1) && (ncp == 2)) { push_option_fmt(o, M_USAGE, "cipher %s", o->ciphername); } } return true; }
/** * Prepare push options, based on local options and available peer info. * * @param context context structure storing data for VPN tunnel * @param gc gc arena for allocating push options * @param push_list push list to where options are added * * @return true on success, false on failure. */ static bool prepare_push_reply(struct context *c, struct gc_arena *gc, struct push_list *push_list) { const char *optstr = NULL; struct tls_multi *tls_multi = c->c2.tls_multi; const char *const peer_info = tls_multi->peer_info; struct options *o = &c->options; /* ipv6 */ if (c->c2.push_ifconfig_ipv6_defined && !o->push_ifconfig_ipv6_blocked) { push_option_fmt(gc, push_list, M_USAGE, "ifconfig-ipv6 %s/%d %s", print_in6_addr(c->c2.push_ifconfig_ipv6_local, 0, gc), c->c2.push_ifconfig_ipv6_netbits, print_in6_addr(c->c2.push_ifconfig_ipv6_remote, 0, gc)); } /* ipv4 */ if (c->c2.push_ifconfig_defined && c->c2.push_ifconfig_local && c->c2.push_ifconfig_remote_netmask && !o->push_ifconfig_ipv4_blocked) { in_addr_t ifconfig_local = c->c2.push_ifconfig_local; if (c->c2.push_ifconfig_local_alias) { ifconfig_local = c->c2.push_ifconfig_local_alias; } push_option_fmt(gc, push_list, M_USAGE, "ifconfig %s %s", print_in_addr_t(ifconfig_local, 0, gc), print_in_addr_t(c->c2.push_ifconfig_remote_netmask, 0, gc)); } /* Send peer-id if client supports it */ optstr = peer_info ? strstr(peer_info, "IV_PROTO=") : NULL; if (optstr) { int proto = 0; int r = sscanf(optstr, "IV_PROTO=%d", &proto); if ((r == 1) && (proto >= 2)) { push_option_fmt(gc, push_list, M_USAGE, "peer-id %d", tls_multi->peer_id); tls_multi->use_peer_id = true; } } /* Push cipher if client supports Negotiable Crypto Parameters */ if (tls_peer_info_ncp_ver(peer_info) >= 2 && o->ncp_enabled) { /* if we have already created our key, we cannot *change* our own * cipher -> so log the fact and push the "what we have now" cipher * (so the client is always told what we expect it to use) */ const struct tls_session *session = &tls_multi->session[TM_ACTIVE]; if (session->key[KS_PRIMARY].crypto_options.key_ctx_bi.initialized) { msg( M_INFO, "PUSH: client wants to negotiate cipher (NCP), but " "server has already generated data channel keys, " "re-sending previously negotiated cipher '%s'", o->ciphername ); } else { /* Push the first cipher from --ncp-ciphers to the client. * TODO: actual negotiation, instead of server dictatorship. */ char *push_cipher = string_alloc(o->ncp_ciphers, &o->gc); o->ciphername = strtok(push_cipher, ":"); } push_option_fmt(gc, push_list, M_USAGE, "cipher %s", o->ciphername); } else if (o->ncp_enabled) { tls_poor_mans_ncp(o, tls_multi->remote_ciphername); } /* If server uses --auth-gen-token and we have an auth token * to send to the client */ if (false == tls_multi->auth_token_sent && NULL != tls_multi->auth_token) { push_option_fmt(gc, push_list, M_USAGE, "auth-token %s", tls_multi->auth_token); tls_multi->auth_token_sent = true; } return true; }