Ejemplo n.º 1
0
/**
 * 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;
}
Ejemplo n.º 2
0
/**
 * 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;
}