Esempio n. 1
0
int proxy_ftp_sess_send_auth_tls(pool *p, struct proxy_session *proxy_sess) {
    int uri_tls, use_tls, xerrno;
    char *auth_feat;
    array_header *auth_feats = NULL;
    pool *tmp_pool;
    cmd_rec *cmd;
    pr_response_t *resp;
    unsigned int resp_nlines = 0;

    use_tls = proxy_tls_use_tls();
    if (use_tls == PROXY_TLS_ENGINE_OFF) {
        pr_trace_msg(trace_channel, 19,
                     "TLS support not enabled/desired, skipping");
        return 0;
    }

    /* Check for any per-URI scheme-based TLS requirements. */
    uri_tls = proxy_conn_get_tls(proxy_sess->dst_pconn);

    auth_feat = pr_table_get(proxy_sess->backend_features, C_AUTH, NULL);
    if (auth_feat == NULL) {
        /* Backend server does not indicate that it supports AUTH via FEAT.
         *
         * Even though this is the case, we will still try to send the AUTH
         * command.  A malicious attacker could be modifying the plaintext
         * FEAT listing, to make us think that TLS is not supported, and thus
         * prevent us from encrypting the session (a la "SSL stripping").
         */

        /* If TLS is required, then complain loudly.  */
        if (uri_tls == PROXY_TLS_ENGINE_ON ||
                use_tls == PROXY_TLS_ENGINE_ON) {
            const char *ip_str;

            ip_str = pr_netaddr_get_ipstr(proxy_sess->backend_ctrl_conn->remote_addr);

            if (uri_tls == PROXY_TLS_ENGINE_ON) {
                (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
                                        "backend server %s does not support AUTH TLS (see FEAT response) but "
                                        "URI '%.100s' requires TLS, attempting anyway", ip_str,
                                        proxy_conn_get_uri(proxy_sess->dst_pconn));

            } else if (use_tls == PROXY_TLS_ENGINE_ON) {
                (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
                                        "backend server %s does not support AUTH TLS (see FEAT response) but "
                                        "ProxyTLSEngine requires TLS, attempting anyway", ip_str);
            }
        }

        pr_trace_msg(trace_channel, 9,
                     "backend server does not support AUTH TLS (via FEAT)");
    }

    tmp_pool = make_sub_pool(p);

    /* Note: the FEAT response against IIS servers shows e.g.:
     *
     * 211-Extended features supported:
     *  LANG EN*
     *  UTF8
     *  AUTH TLS;TLS-C;SSL;TLS-P;
     *  PBSZ
     *  PROT C;P;
     *  CCC
     *  HOST
     *  SIZE
     *  MDTM
     *  REST STREAM
     * 211 END
     *
     * Note how the AUTH and PROT values are not exactly as specified
     * in RFC 4217.  This means we'll need to deal with it as is.  There will
     * be other servers with other FEAT response formats, too.
     */
    if (parse_feat(tmp_pool, auth_feat, &auth_feats) > 0) {
        register unsigned int i;

        pr_trace_msg(trace_channel, 9, "parsed FEAT value '%s' into %d values",
                     auth_feat, auth_feats->nelts);
        for (i = 0; i < auth_feats->nelts; i++) {
            char *val;

            val = ((char **) auth_feats->elts)[i];
            pr_trace_msg(trace_channel, 9, " %s", val);
        }
    }

    /* XXX How should we interoperate with servers that support/want the
     * older formats, e.g.:
     *
     *  AUTH SSL (which automatically assumes PBSZ 0, PROT P)
     *  AUTH TLS-P (synonym for AUTH SSL)
     *  AUTH TLS-C (synonym for AUTH TLS)
     */

    cmd = pr_cmd_alloc(tmp_pool, 2, C_AUTH, "TLS");
    cmd->arg = pstrdup(tmp_pool, "TLS");

    resp = send_recv(tmp_pool, proxy_sess->backend_ctrl_conn, cmd, &resp_nlines);
    if (resp == NULL) {
        xerrno = errno;

        proxy_netio_use(PR_NETIO_STRM_CTRL, NULL);
        destroy_pool(tmp_pool);
        errno = xerrno;
        return -1;
    }

    if (resp->num[0] != '2') {
        /* XXX Some older servers might respond with a 334 response code, per
         * RFC 2228.  See, for example:
         *   http://serverfault.com/questions/640978/ftp-alter-server-response-in-transit
         */
        pr_trace_msg(trace_channel, 4,
                     "received unexpected %s response code %s from backend",
                     (char *) cmd->argv[0], resp->num);

        proxy_netio_use(PR_NETIO_STRM_CTRL, NULL);
        destroy_pool(tmp_pool);
        errno = EPERM;
        return -1;
    }

    destroy_pool(tmp_pool);
    return 0;
}
Esempio n. 2
0
int proxy_ftp_sess_send_auth_tls(pool *p, struct proxy_session *proxy_sess) {
  int uri_tls, use_tls, xerrno;
  char *auth_feat;
  array_header *auth_feats = NULL;
  pool *tmp_pool;
  cmd_rec *cmd;
  pr_response_t *resp;
  unsigned int resp_nlines = 0;

  use_tls = proxy_tls_use_tls();
  if (use_tls == PROXY_TLS_ENGINE_OFF) {
    pr_trace_msg(trace_channel, 19,
      "TLS support not enabled/desired, skipping");
    return 0;
  }

  /* Check for any per-URI scheme-based TLS requirements. */
  uri_tls = proxy_conn_get_tls(proxy_sess->dst_pconn);

  auth_feat = pr_table_get(proxy_sess->backend_features, C_AUTH, NULL);
  if (auth_feat == NULL) {
    /* Backend server does not indicate that it supports AUTH via FEAT. */

    /* If TLS is required, then fail now. */
    if (uri_tls == PROXY_TLS_ENGINE_ON ||
        use_tls == PROXY_TLS_ENGINE_ON) {
      const char *ip_str;

      ip_str = pr_netaddr_get_ipstr(proxy_sess->backend_ctrl_conn->remote_addr);

      if (uri_tls == PROXY_TLS_ENGINE_ON) {
        (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
          "backend server %s does not support AUTH TLS (see FEAT response) but "
          "URI '%.100s' requires TLS, failing connection", ip_str,
          proxy_conn_get_uri(proxy_sess->dst_pconn));

      } else if (use_tls == PROXY_TLS_ENGINE_ON) {
        (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
          "backend server %s does not support AUTH TLS (see FEAT response) but "
          "ProxyTLSEngine requires TLS, failing connection", ip_str);
      }

      errno = EPERM;
      return -1;
    }

    /* Tell the Proxy NetIO API to NOT try to use our TLS NetIO. */
    proxy_netio_use(PR_NETIO_STRM_CTRL, NULL);

    pr_trace_msg(trace_channel, 9,
      "backend server does not support AUTH TLS (via FEAT), skipping");
    return 0;
  }

  tmp_pool = make_sub_pool(p);

  /* Note: the FEAT response against IIS servers shows e.g.:
   *
   * 211-Extended features supported:
   *  LANG EN*
   *  UTF8
   *  AUTH TLS;TLS-C;SSL;TLS-P;
   *  PBSZ
   *  PROT C;P;
   *  CCC
   *  HOST
   *  SIZE
   *  MDTM
   *  REST STREAM
   * 211 END
   *
   * Note how the AUTH and PROT values are not exactly as specified
   * in RFC 4217.  This means we'll need to deal with as is.  There will
   * be other servers with other FEAT response formats, too.
   */
  if (parse_feat(tmp_pool, auth_feat, &auth_feats) > 0) {
    register unsigned int i;

    pr_trace_msg(trace_channel, 9, "parsed FEAT value '%s' into %d values",
      auth_feat, auth_feats->nelts);
    for (i = 0; i < auth_feats->nelts; i++) {
      char *val;

      val = ((char **) auth_feats->elts)[i];
      pr_trace_msg(trace_channel, 9, " %s", val);
    }
  }

  cmd = pr_cmd_alloc(tmp_pool, 2, C_AUTH, "TLS");
  cmd->arg = pstrdup(tmp_pool, "TLS");

  resp = send_recv(tmp_pool, proxy_sess->backend_ctrl_conn, cmd, &resp_nlines);
  if (resp == NULL) {
    xerrno = errno;

    proxy_netio_use(PR_NETIO_STRM_CTRL, NULL);
    destroy_pool(tmp_pool);
    errno = xerrno;
    return -1;
  }

  if (resp->num[0] != '2') {
    pr_trace_msg(trace_channel, 4,
      "received unexpected %s response code %s from backend",
      (char *) cmd->argv[0], resp->num);

    proxy_netio_use(PR_NETIO_STRM_CTRL, NULL);
    destroy_pool(tmp_pool);
    errno = EPERM;
    return -1;
  }

  destroy_pool(tmp_pool);
  return 0;
}