Acked-by: Lev Stipakov <lstipa...@gmail.com>

ke 3. maalisk. 2021 klo 14.39 Arne Schwabe (a...@rfc2549.org) kirjoitti:
>
> Patch V2: eliminate parse_kid function, fix style
> Patch V3: adding missing parameter in function, this was added
>           by a later patch in the original series
>
> Signed-off-by: Arne Schwabe <a...@rfc2549.org>
> ---
>  src/openvpn/manage.c     | 23 +++++++++--------
>  src/openvpn/manage.h     |  3 ++-
>  src/openvpn/multi.c      | 27 +++-----------------
>  src/openvpn/push.c       | 55 +++++++++++++++++++++++++++++++++++++---
>  src/openvpn/push.h       | 14 +++++++++-
>  src/openvpn/ssl.c        |  1 +
>  src/openvpn/ssl_common.h |  1 +
>  7 files changed, 84 insertions(+), 40 deletions(-)
>
> diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c
> index 169e645f..df987f53 100644
> --- a/src/openvpn/manage.c
> +++ b/src/openvpn/manage.c
> @@ -975,15 +975,15 @@ parse_cid(const char *str, unsigned long *cid)
>  }
>
>  static bool
> -parse_kid(const char *str, unsigned int *kid)
> +parse_uint(const char *str, const char* what, unsigned int *uint)
>  {
> -    if (sscanf(str, "%u", kid) == 1)
> +    if (sscanf(str, "%u", uint) == 1)
>      {
>          return true;
>      }
>      else
>      {
> -        msg(M_CLIENT, "ERROR: cannot parse KID");
> +        msg(M_CLIENT, "ERROR: cannot parse %s", what);
>          return false;
>      }
>  }
> @@ -998,15 +998,18 @@ parse_kid(const char *str, unsigned int *kid)
>   *                      the information of the additional steps
>   */
>  static void
> -man_client_pending_auth(struct management *man, const char *cid_str, const 
> char *extra)
> +man_client_pending_auth(struct management *man, const char *cid_str,
> +                        const char *extra, const char *timeout_str)
>  {
>      unsigned long cid = 0;
> -    if (parse_cid(cid_str, &cid))
> +    unsigned int timeout = 0;
> +    if (parse_cid(cid_str, &cid)
> +        && parse_uint(timeout_str, "TIMEOUT", &timeout))
>      {
>          if (man->persist.callback.client_pending_auth)
>          {
>              bool ret = (*man->persist.callback.client_pending_auth)
> -                           (man->persist.callback.arg, cid, extra);
> +                           (man->persist.callback.arg, cid, extra, timeout);
>
>              if (ret)
>              {
> @@ -1032,7 +1035,7 @@ man_client_auth(struct management *man, const char 
> *cid_str, const char *kid_str
>      mc->in_extra_cid = 0;
>      mc->in_extra_kid = 0;
>      if (parse_cid(cid_str, &mc->in_extra_cid)
> -        && parse_kid(kid_str, &mc->in_extra_kid))
> +        && parse_uint(kid_str, "KID", &mc->in_extra_kid))
>      {
>          mc->in_extra_cmd = IEC_CLIENT_AUTH;
>          in_extra_reset(mc, IER_NEW);
> @@ -1048,7 +1051,7 @@ man_client_deny(struct management *man, const char 
> *cid_str, const char *kid_str
>  {
>      unsigned long cid = 0;
>      unsigned int kid = 0;
> -    if (parse_cid(cid_str, &cid) && parse_kid(kid_str, &kid))
> +    if (parse_cid(cid_str, &cid) && parse_uint(kid_str, "KID", &kid))
>      {
>          if (man->persist.callback.client_auth)
>          {
> @@ -1563,9 +1566,9 @@ man_dispatch_command(struct management *man, struct 
> status_output *so, const cha
>      }
>      else if (streq(p[0], "client-pending-auth"))
>      {
> -        if (man_need(man, p, 2, 0))
> +        if (man_need(man, p, 3, 0))
>          {
> -            man_client_pending_auth(man, p[1], p[2]);
> +            man_client_pending_auth(man, p[1], p[2], p[3]);
>          }
>      }
>  #ifdef MANAGEMENT_PF
> diff --git a/src/openvpn/manage.h b/src/openvpn/manage.h
> index 9797842b..41eacc02 100644
> --- a/src/openvpn/manage.h
> +++ b/src/openvpn/manage.h
> @@ -173,7 +173,8 @@ struct management_callback
>                           struct buffer_list *cc_config); /* ownership 
> transferred */
>      bool (*client_pending_auth) (void *arg,
>                                   const unsigned long cid,
> -                                 const char *url);
> +                                 const char *extra,
> +                                 unsigned int timeout);
>      char *(*get_peer_info) (void *arg, const unsigned long cid);
>  #ifdef MANAGEMENT_PF
>      bool (*client_pf)(void *arg,
> diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c
> index dd713049..ac5d3f5b 100644
> --- a/src/openvpn/multi.c
> +++ b/src/openvpn/multi.c
> @@ -1768,28 +1768,6 @@ multi_client_connect_setenv(struct multi_context *m,
>      gc_free(&gc);
>  }
>
> -/**
> - * Extracts the IV_PROTO variable and returns its value or 0
> - * if it cannot be extracted.
> - *
> - */
> -static unsigned int
> -extract_iv_proto(const char *peer_info)
> -{
> -
> -    const char *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 > 0)
> -        {
> -            return proto;
> -        }
> -    }
> -    return 0;
> -}
> -
>  /**
>   * Calculates the options that depend on the client capabilities
>   * based on local options and available peer info
> @@ -3918,14 +3896,15 @@ management_kill_by_cid(void *arg, const unsigned long 
> cid, const char *kill_msg)
>  static bool
>  management_client_pending_auth(void *arg,
>                                 const unsigned long cid,
> -                               const char *extra)
> +                               const char *extra,
> +                               unsigned int timeout)
>  {
>      struct multi_context *m = (struct multi_context *) arg;
>      struct multi_instance *mi = lookup_by_cid(m, cid);
>      if (mi)
>      {
>          /* sends INFO_PRE and AUTH_PENDING messages to client */
> -        bool ret = send_auth_pending_messages(&mi->context, extra);
> +        bool ret = send_auth_pending_messages(&mi->context, extra, timeout);
>          multi_schedule_context_wakeup(m, mi);
>          return ret;
>      }
> diff --git a/src/openvpn/push.c b/src/openvpn/push.c
> index 9a67e036..46267835 100644
> --- a/src/openvpn/push.c
> +++ b/src/openvpn/push.c
> @@ -361,26 +361,57 @@ send_auth_failed(struct context *c, const char 
> *client_reason)
>      gc_free(&gc);
>  }
>
> +
>  bool
> -send_auth_pending_messages(struct context *c, const char *extra)
> +send_auth_pending_messages(struct context *c, const char *extra,
> +                           unsigned int timeout)
>  {
> -    send_control_channel_string(c, "AUTH_PENDING", D_PUSH);
> +    struct tls_multi *tls_multi = c->c2.tls_multi;
> +    struct key_state *ks = &tls_multi->session[TM_ACTIVE].key[KS_PRIMARY];
>
>      static const char info_pre[] = "INFO_PRE,";
>
> +    const char *const peer_info = tls_multi->peer_info;
> +    unsigned int proto = extract_iv_proto(peer_info);
> +
>
> -    size_t len = strlen(extra)+1 + sizeof(info_pre);
> +    /* Calculate the maximum timeout and subtract the time we already waited 
> */
> +    unsigned int max_timeout = max_uint(tls_multi->opt.renegotiate_seconds/2,
> +                                        tls_multi->opt.handshake_window);
> +    max_timeout = max_timeout - (now - ks->initial);
> +    timeout = min_uint(max_timeout, timeout);
> +
> +    struct gc_arena gc = gc_new();
> +    if ((proto & IV_PROTO_AUTH_PENDING_KW) == 0)
> +    {
> +        send_control_channel_string(c, "AUTH_PENDING", D_PUSH);
> +    }
> +    else
> +    {
> +        static const char auth_pre[] = "AUTH_PENDING,timeout ";
> +        // Assume a worst case of 8 byte uint64 in decimal which
> +        // needs 20 bytes
> +        size_t len = 20 + 1 + sizeof(auth_pre);
> +        struct buffer buf = alloc_buf_gc(len, &gc);
> +        buf_printf(&buf, auth_pre);
> +        buf_printf(&buf, "%u", timeout);
> +        send_control_channel_string(c, BSTR(&buf), D_PUSH);
> +    }
> +
> +    size_t len = strlen(extra) + 1 + sizeof(info_pre);
>      if (len > PUSH_BUNDLE_SIZE)
>      {
> +        gc_free(&gc);
>          return false;
>      }
> -    struct gc_arena gc = gc_new();
>
>      struct buffer buf = alloc_buf_gc(len, &gc);
>      buf_printf(&buf, info_pre);
>      buf_printf(&buf, "%s", extra);
>      send_control_channel_string(c, BSTR(&buf), D_PUSH);
>
> +    ks->auth_deferred_expire = now + timeout;
> +
>      gc_free(&gc);
>      return true;
>  }
> @@ -1028,4 +1059,20 @@ remove_iroutes_from_push_route_list(struct options *o)
>      }
>  }
>
> +unsigned int
> +extract_iv_proto(const char *peer_info)
> +{
> +    const char *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 > 0)
> +        {
> +            return proto;
> +        }
> +    }
> +    return 0;
> +}
> +
>  #endif /* if P2MP */
> diff --git a/src/openvpn/push.h b/src/openvpn/push.h
> index 01847671..e7271de2 100644
> --- a/src/openvpn/push.h
> +++ b/src/openvpn/push.h
> @@ -77,7 +77,9 @@ void send_auth_failed(struct context *c, const char 
> *client_reason);
>   * doc/management-notes.txt under client-pending-auth for
>   * more details on message format
>   */
> -bool send_auth_pending_messages(struct context *c, const char *extra);
> +bool
> +send_auth_pending_messages(struct context *c, const char *extra,
> +                           unsigned int timeout);
>
>  void send_restart(struct context *c, const char *kill_msg);
>
> @@ -89,6 +91,16 @@ void send_restart(struct context *c, const char *kill_msg);
>   */
>  void send_push_reply_auth_token(struct tls_multi *multi);
>
> +
> +/**
> + * Extracts the IV_PROTO variable and returns its value or 0
> + * if it cannot be extracted.
> + *
> + * @param peer_info     peer info string to search for IV_PROTO
> + */
> +unsigned int
> +extract_iv_proto(const char *peer_info);
> +
>  /**
>   * Parses an AUTH_PENDING message and if in pull mode extends the timeout
>   *
> diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
> index 56cd4c60..1389322e 100644
> --- a/src/openvpn/ssl.c
> +++ b/src/openvpn/ssl.c
> @@ -2659,6 +2659,7 @@ tls_process(struct tls_multi *multi,
>              buf = reliable_get_buf_output_sequenced(ks->send_reliable);
>              if (buf)
>              {
> +                ks->initial = now;
>                  ks->must_negotiate = now + session->opt->handshake_window;
>                  ks->auth_deferred_expire = now + 
> auth_deferred_expire_window(session->opt);
>
> diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
> index bbb8135d..bf7f9ba3 100644
> --- a/src/openvpn/ssl_common.h
> +++ b/src/openvpn/ssl_common.h
> @@ -175,6 +175,7 @@ struct key_state
>
>      struct key_state_ssl ks_ssl; /* contains SSL object and BIOs for the 
> control channel */
>
> +    time_t initial;             /* when we created this session */
>      time_t established;         /* when our state went S_ACTIVE */
>      time_t must_negotiate;      /* key negotiation times out if not finished 
> before this time */
>      time_t must_die;            /* this object is destroyed at this time */
> --
> 2.30.1
>
>
>
> _______________________________________________
> Openvpn-devel mailing list
> Openvpn-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/openvpn-devel



-- 
-Lev


_______________________________________________
Openvpn-devel mailing list
Openvpn-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openvpn-devel

Reply via email to