예제 #1
0
END_TEST

START_TEST (listen_test) {
  conn_t *res;
  const pr_netaddr_t *bind_addr = NULL;

  res = proxy_ftp_conn_listen(NULL, NULL, FALSE);
  fail_unless(res == NULL, "Failed to handle null pool");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL,
    strerror(errno), errno);

  res = proxy_ftp_conn_listen(p, NULL, FALSE);
  fail_unless(res == NULL, "Failed to handle null bind address");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL,
    strerror(errno), errno);

  bind_addr = pr_netaddr_get_addr(p, "127.0.0.1", NULL);
  fail_unless(bind_addr != NULL, "Failed to address for 127.0.0.1: %s",
    strerror(errno));
  pr_netaddr_set_port((pr_netaddr_t *) bind_addr, htons(0));

  mark_point();
  res = proxy_ftp_conn_listen(p, bind_addr, FALSE);
  fail_unless(res != NULL, "Failed to listen: %s", strerror(errno));
  pr_inet_close(p, res);

  mark_point();
  res = proxy_ftp_conn_listen(p, bind_addr, TRUE);
  fail_unless(res != NULL, "Failed to listen: %s", strerror(errno));
  pr_inet_close(p, res);
}
예제 #2
0
파일: inet.c 프로젝트: proftpd/proftpd
END_TEST

START_TEST (inet_create_conn_test) {
  int sockfd = -2, port = INPORT_ANY;
  conn_t *conn, *conn2;

  conn = pr_inet_create_conn(NULL, sockfd, NULL, port, FALSE);
  fail_unless(conn == NULL, "Failed to handle null arguments");
  fail_unless(errno == EINVAL,
    "Failed to set errno to EINVAL (%d), got '%s' (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));
  fail_unless(conn->listen_fd == sockfd, "Expected listen_fd %d, got %d",
    sockfd, conn->listen_fd);
  pr_inet_close(p, conn);

  sockfd = -1;
  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));
  fail_unless(conn->listen_fd != sockfd,
    "Expected listen_fd other than %d, got %d",
    sockfd, conn->listen_fd);

  /* Create another conn, with the same port, make sure it fails. */
  conn2 = pr_inet_create_conn(p, sockfd, NULL, conn->local_port, FALSE);
  if (conn2 == NULL) {
    fail_unless(errno == EADDRINUSE, "Expected EADDRINUSE (%d), got %s (%d)",
      EADDRINUSE, strerror(errno), errno);
    pr_inet_close(p, conn2);
  }

  pr_inet_close(p, conn);
}
예제 #3
0
int proxy_session_free(pool *p, struct proxy_session *proxy_sess) {
  conn_t *conn;

  if (proxy_sess == NULL) {
    errno = EINVAL;
    return -1;
  }

  /* Close any open connections. */

  conn = proxy_sess->frontend_data_conn;
  if (conn != NULL) {
    pr_inet_close(p, conn);
    proxy_sess->frontend_data_conn = session.d = NULL;
  }

  conn = proxy_sess->backend_ctrl_conn;
  if (conn != NULL) {
    pr_inet_close(p, conn);
    proxy_sess->backend_ctrl_conn = NULL;
  }

  conn = proxy_sess->backend_data_conn;
  if (conn != NULL) {
    pr_inet_close(p, conn);
    proxy_sess->backend_data_conn = NULL;
  }

  destroy_pool(proxy_sess->pool);
  return 0;
}
예제 #4
0
파일: inet.c 프로젝트: Nakor78/proftpd
END_TEST

START_TEST (inet_create_conn_test) {
  int sockfd = -2, port = INPORT_ANY;
  conn_t *conn;

  conn = pr_inet_create_conn(NULL, sockfd, NULL, port, FALSE);
  fail_unless(conn == NULL, "Failed to handle null arguments");
  fail_unless(errno == EINVAL,
    "Failed to set errno to EINVAL (%d), got '%s' (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));
  fail_unless(conn->listen_fd == sockfd, "Expected listen_fd %d, got %d",
    sockfd, conn->listen_fd);
  pr_inet_close(p, conn);

  sockfd = -1;
  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));
  fail_unless(conn->listen_fd != sockfd,
    "Expected listen_fd other than %d, got %d",
    sockfd, conn->listen_fd);
  pr_inet_close(p, conn);
}
예제 #5
0
파일: inet.c 프로젝트: proftpd/proftpd
END_TEST

START_TEST (inet_connect_ipv4_test) {
  int sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;
  const pr_netaddr_t *addr;

  res = pr_inet_connect(NULL, NULL, NULL, port);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_connect(p, conn, NULL, 80);
  fail_unless(res < 0, "Failed to handle null address");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  addr = pr_netaddr_get_addr(p, "127.0.0.1", NULL);
  fail_unless(addr != NULL, "Failed to resolve '127.0.0.1': %s",
    strerror(errno));

  res = pr_inet_connect(p, conn, addr, 80);
  fail_unless(res < 0, "Connected to 127.0.0.1#80 unexpectedly");
  fail_unless(errno == ECONNREFUSED, "Expected ECONNREFUSED (%d), got %s (%d)",
    ECONNREFUSED, strerror(errno), errno);

  /* Try connecting to Google's DNS server. */

  addr = pr_netaddr_get_addr(p, "8.8.8.8", NULL);
  fail_unless(addr != NULL, "Failed to resolve '8.8.8.8': %s",
    strerror(errno));

  res = pr_inet_connect(p, conn, addr, 53);
  if (res < 0) {
    /* Note: We get EINVAL here because the socket already tried (and failed)
     * to connect to a different address.  Interestingly, trying to connect(2)
     * using that same fd to a different address yields EINVAL.
     */
    fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
      strerror(errno), errno);
  }
  pr_inet_close(p, conn);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_connect(p, conn, addr, 53);
  fail_if(res < 0, "Failed to connect to 8.8.8.8#53: %s", strerror(errno));

  res = pr_inet_connect(p, conn, addr, 53);
  fail_unless(res < 0, "Failed to connect to 8.8.8.8#53: %s",
    strerror(errno));
  fail_unless(errno == EISCONN, "Expected EISCONN (%d), got %s (%d)",
    EISCONN, strerror(errno), errno);
  pr_inet_close(p, conn);
}
예제 #6
0
파일: inet.c 프로젝트: Nakor78/proftpd
END_TEST

START_TEST (inet_openrw_test) {
  int sockfd = -1, port = INPORT_ANY;
  conn_t *conn, *res;
  pr_netaddr_t *addr;

  res = pr_inet_openrw(NULL, NULL, NULL, PR_NETIO_STRM_CTRL, -1, -1, -1, FALSE);
  fail_unless(res == NULL, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_openrw(p, conn, NULL, PR_NETIO_STRM_CTRL, -1, -1, -1, FALSE);
  fail_unless(res == NULL, "Opened rw conn unexpectedly");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  addr = pr_netaddr_get_addr(p, "127.0.0.1", NULL);
  fail_unless(addr != NULL, "Failed to resolve 127.0.0.1: %s", strerror(errno));

  res = pr_inet_openrw(p, conn, addr, PR_NETIO_STRM_CTRL, -1, -1, -1, FALSE);
  fail_unless(res != NULL, "Failed to open rw conn: %s", strerror(errno));
  (void) pr_inet_close(p, res);

  res = pr_inet_openrw(p, conn, addr, PR_NETIO_STRM_CTRL, -1, -1, -1, TRUE);
  fail_unless(res != NULL, "Failed to open rw conn: %s", strerror(errno));
}
예제 #7
0
파일: inet.c 프로젝트: Nakor78/proftpd
END_TEST

START_TEST (inet_set_block_test) {
  int sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn; 

  res = pr_inet_set_block(NULL, NULL);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected errno EINVAL (%d), got '%s' (%d)",
    EINVAL, strerror(errno), errno);

  res = pr_inet_set_nonblock(NULL, NULL);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected errno EINVAL (%d), got '%s' (%d)",
    EINVAL, strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_set_nonblock(p, conn);
  fail_unless(res < 0, "Failed to handle bad socket");
  fail_unless(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
    strerror(errno), errno);

  res = pr_inet_set_block(p, conn);
  fail_unless(res < 0, "Failed to handle bad socket");
  fail_unless(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
    strerror(errno), errno);

  pr_inet_close(p, conn);
}
예제 #8
0
파일: inet.c 프로젝트: Nakor78/proftpd
END_TEST

START_TEST (inet_connect_nowait_test) {
  int sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;
  pr_netaddr_t *addr;

  res = pr_inet_connect_nowait(NULL, NULL, NULL, port);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_connect_nowait(p, conn, NULL, 80);
  fail_unless(res < 0, "Failed to handle null connection");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  addr = pr_netaddr_get_addr(p, "127.0.0.1", NULL);
  fail_unless(addr != NULL, "Failed to resolve '127.0.0.1': %s",
    strerror(errno));

  res = pr_inet_connect_nowait(p, conn, addr, 80);
  fail_unless(res < 0, "Connected to 127.0.0.1#80 unexpectedly");

  pr_inet_close(p, conn);
}
예제 #9
0
파일: inet.c 프로젝트: proftpd/proftpd
END_TEST

START_TEST (inet_set_socket_opts_test) {
  int sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;
  struct tcp_keepalive keepalive;

  res = pr_inet_set_socket_opts(NULL, NULL, 1, 2, NULL);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_set_socket_opts(p, conn, 1, 2, NULL);
  fail_unless(res == 0, "Failed to set socket opts: %s", strerror(errno));

  res = pr_inet_set_socket_opts(p, conn, INT_MAX, INT_MAX, NULL);
  fail_unless(res == 0, "Failed to set socket opts: %s", strerror(errno));

  keepalive.keepalive_enabled = 1;
  keepalive.keepalive_idle = 1;
  keepalive.keepalive_count = 2;
  keepalive.keepalive_intvl = 3;
  res = pr_inet_set_socket_opts(p, conn, 1, 2, &keepalive);
  fail_unless(res == 0, "Failed to set socket opts: %s", strerror(errno));

  pr_inet_close(p, conn);
}
예제 #10
0
파일: inet.c 프로젝트: Nakor78/proftpd
END_TEST

START_TEST (inet_conn_info_test) {
  int sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;

  res = pr_inet_get_conn_info(NULL, -1);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_get_conn_info(conn, -1);
  fail_unless(res < 0, "Failed to handle bad file descriptor");
  fail_unless(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
    strerror(errno), errno);

  res = pr_inet_get_conn_info(conn, 1);
  fail_unless(res < 0, "Failed to handle bad file descriptor");
  fail_unless(errno == ENOTSOCK, "Expected ENOTSOCK (%d), got %s (%d)",
    ENOTSOCK, strerror(errno), errno);

  pr_inet_close(p, conn);
}
예제 #11
0
파일: inet.c 프로젝트: proftpd/proftpd
END_TEST

START_TEST (inet_set_proto_opts_ipv6_test) {
#ifdef PR_USE_IPV6
  int fd, sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;
  unsigned char use_ipv6;

  use_ipv6 = pr_netaddr_use_ipv6();

  pr_netaddr_enable_ipv6();
  pr_inet_set_default_family(p, AF_INET6);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  mark_point();
  res = pr_inet_set_proto_opts(p, conn, 1, 1, 1, 1);
  fail_unless(res == 0, "Failed to set proto opts: %s", strerror(errno));

  mark_point();
  fd = conn->rfd;
  conn->rfd = 8;
  res = pr_inet_set_proto_opts(p, conn, 1, 1, 1, 1);
  fail_unless(res == 0, "Failed to set proto opts: %s", strerror(errno));
  conn->rfd = fd;

  mark_point();
  fd = conn->wfd;
  conn->wfd = 9;
  res = pr_inet_set_proto_opts(p, conn, 1, 1, 1, 1);
  fail_unless(res == 0, "Failed to set proto opts: %s", strerror(errno));
  conn->wfd = fd;

  mark_point();
  fd = conn->listen_fd;
  conn->listen_fd = 10;
  res = pr_inet_set_proto_opts(p, conn, 1, 1, 1, 1);
  fail_unless(res == 0, "Failed to set proto opts: %s", strerror(errno));
  conn->listen_fd = fd;

  pr_inet_close(p, conn);

  pr_inet_set_default_family(p, AF_INET);
  if (use_ipv6 == FALSE) {
    pr_netaddr_disable_ipv6();
  }
#endif /* PR_USE_IPV6 */
}
예제 #12
0
파일: inet.c 프로젝트: proftpd/proftpd
END_TEST

START_TEST (inet_listen_test) {
  int fd, mode, sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;

  res = pr_inet_listen(NULL, NULL, 5, 0);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  res = pr_inet_resetlisten(NULL, NULL);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  fd = conn->listen_fd;
  conn->listen_fd = 777;
  res = pr_inet_listen(p, conn, 5, 0);
  fail_unless(res < 0, "Succeeded in listening on conn unexpectedly");
  fail_unless(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
    strerror(errno), errno);

  mode = conn->mode;
  res = pr_inet_resetlisten(p, conn);
  fail_unless(res < 0, "Succeeded in resetting listening on conn unexpectedly");
  fail_unless(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
    strerror(errno), errno);

  conn->listen_fd = fd;
  conn->mode = mode;

  res = pr_inet_listen(p, conn, 5, 0);
  fail_unless(res == 0, "Failed to listen on conn: %s", strerror(errno));

  res = pr_inet_resetlisten(p, conn);
  fail_unless(res == 0, "Failed to reset listen mode: %s", strerror(errno));

  res = pr_inet_listen(p, conn, 5, 0);
  fail_unless(res < 0, "Failed to handle already-listening socket");
  fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
    strerror(errno), errno);

  pr_inet_close(p, conn);
}
예제 #13
0
파일: trace.c 프로젝트: proftpd/proftpd
END_TEST

START_TEST (trace_msg_test) {
  int res;
  char *channel, msg[16384];

  res = pr_trace_msg(NULL, -1, NULL);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  channel = "testsuite";

  res = pr_trace_msg(channel, -1, NULL);
  fail_unless(res < 0, "Failed to handle bad level");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  res = pr_trace_msg(channel, 1, NULL);
  fail_unless(res < 0, "Failed to handle null message");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  pr_trace_set_levels(channel, 1, 10);

  memset(msg, 'A', sizeof(msg)-1);
  msg[sizeof(msg)-1] = '\0';
  pr_trace_msg(channel, 5, "%s", msg);

  session.c = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE);
  fail_unless(session.c != NULL, "Failed to create conn: %s", strerror(errno));
  session.c->local_addr = session.c->remote_addr =
    pr_netaddr_get_addr(p, "127.0.0.1", NULL);

  res = pr_trace_set_options(PR_TRACE_OPT_LOG_CONN_IPS|PR_TRACE_OPT_USE_TIMESTAMP_MILLIS);
  fail_unless(res == 0, "Failed to set options: %s", strerror(errno));
  pr_trace_msg(channel, 5, "%s", "alef bet vet?");

  res = pr_trace_set_options(0);
  fail_unless(res == 0, "Failed to set options: %s", strerror(errno));
  pr_trace_msg(channel, 5, "%s", "alef bet vet?");

  pr_inet_close(p, session.c);
  session.c = NULL;

  pr_trace_set_levels(channel, 0, 0);
}
예제 #14
0
파일: inet.c 프로젝트: Nakor78/proftpd
END_TEST

START_TEST (inet_set_proto_nodelay_test) {
  int fd, sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;

  res = pr_inet_set_proto_nodelay(NULL, NULL, 1);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_set_proto_nodelay(p, conn, 1);
  fail_unless(res == 0, "Failed to enable nodelay: %s", strerror(errno));

  res = pr_inet_set_proto_nodelay(p, conn, 0);
  fail_unless(res == 0, "Failed to disable nodelay: %s", strerror(errno));

  fd = conn->rfd;
  conn->rfd = 8;
  res = pr_inet_set_proto_nodelay(p, conn, 0);
  fail_unless(res == 0, "Failed to disable nodelay: %s", strerror(errno));
  conn->rfd = fd;

  fd = conn->rfd;
  conn->rfd = -2;
  res = pr_inet_set_proto_nodelay(p, conn, 0);
  fail_unless(res == 0, "Failed to disable nodelay: %s", strerror(errno));
  conn->rfd = fd;

  fd = conn->wfd;
  conn->rfd = 9;
  res = pr_inet_set_proto_nodelay(p, conn, 0);
  fail_unless(res == 0, "Failed to disable nodelay: %s", strerror(errno));
  conn->wfd = fd;

  fd = conn->wfd;
  conn->rfd = -3;
  res = pr_inet_set_proto_nodelay(p, conn, 0);
  fail_unless(res == 0, "Failed to disable nodelay: %s", strerror(errno));
  conn->wfd = fd;

  pr_inet_close(p, conn);
}
예제 #15
0
파일: inet.c 프로젝트: proftpd/proftpd
END_TEST

START_TEST (inet_connect_nowait_test) {
  int sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;
  const pr_netaddr_t *addr;

  res = pr_inet_connect_nowait(NULL, NULL, NULL, port);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_connect_nowait(p, conn, NULL, 80);
  fail_unless(res < 0, "Failed to handle null address");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  addr = pr_netaddr_get_addr(p, "127.0.0.1", NULL);
  fail_unless(addr != NULL, "Failed to resolve '127.0.0.1': %s",
    strerror(errno));

  res = pr_inet_connect_nowait(p, conn, addr, 80);
  fail_unless(res != -1, "Connected to 127.0.0.1#80 unexpectedly");

  /* Try connecting to Google's DNS server. */

  addr = pr_netaddr_get_addr(p, "8.8.8.8", NULL);
  fail_unless(addr != NULL, "Failed to resolve '8.8.8.8': %s",
    strerror(errno));

  res = pr_inet_connect_nowait(p, conn, addr, 53);
  if (res < 0 &&
      errno != ECONNREFUSED) {
    fail_unless(res != -1, "Failed to connect to 8.8.8.8#53: %s",
      strerror(errno));
  }

  pr_inet_close(p, conn);

  /* Restore the default family to AF_INET, for other tests. */
  pr_inet_set_default_family(p, AF_INET);
}
예제 #16
0
파일: inet.c 프로젝트: Nakor78/proftpd
END_TEST

START_TEST (inet_set_socket_opts_test) {
  int sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;

  res = pr_inet_set_socket_opts(NULL, NULL, 1, 2, NULL);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_set_socket_opts(p, conn, 1, 2, NULL);
  fail_unless(res == 0, "Failed to set socket opts: %s", strerror(errno));

  pr_inet_close(p, conn);
}
예제 #17
0
파일: inet.c 프로젝트: Nakor78/proftpd
END_TEST

START_TEST (inet_set_proto_opts_test) {
  int fd, sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;

  mark_point();
  res = pr_inet_set_proto_opts(NULL, NULL, 1, 1, 1, 1);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  mark_point();
  res = pr_inet_set_proto_opts(p, conn, 1, 1, 1, 1);
  fail_unless(res == 0, "Failed to set proto opts: %s", strerror(errno));

  mark_point();
  fd = conn->rfd;
  conn->rfd = 8;
  res = pr_inet_set_proto_opts(p, conn, 1, 1, 1, 1);
  fail_unless(res == 0, "Failed to set proto opts: %s", strerror(errno));
  conn->rfd = fd;

  mark_point();
  fd = conn->wfd;
  conn->wfd = 9;
  res = pr_inet_set_proto_opts(p, conn, 1, 1, 1, 1);
  fail_unless(res == 0, "Failed to set proto opts: %s", strerror(errno));
  conn->wfd = fd;

  mark_point();
  fd = conn->listen_fd;
  conn->listen_fd = 10;
  res = pr_inet_set_proto_opts(p, conn, 1, 1, 1, 1);
  fail_unless(res == 0, "Failed to set proto opts: %s", strerror(errno));
  conn->listen_fd = fd;

  pr_inet_close(p, conn);
}
예제 #18
0
파일: inet.c 프로젝트: Nakor78/proftpd
END_TEST

START_TEST (inet_set_async_test) {
  int fd, sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;

  res = pr_inet_set_async(NULL, NULL);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected errno EINVAL (%d), got '%s' (%d)",
    EINVAL, strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_set_async(p, conn);
  fail_unless(res == 0, "Failed to set conn %p async: %s", conn,
    strerror(errno));

  fd = conn->rfd;
  conn->rfd = 77;
  res = pr_inet_set_async(p, conn);
  fail_unless(res == 0, "Failed to set conn %p async: %s", conn,
    strerror(errno));
  conn->rfd = fd;

  fd = conn->wfd;
  conn->wfd = 78;
  res = pr_inet_set_async(p, conn);
  fail_unless(res == 0, "Failed to set conn %p async: %s", conn,
    strerror(errno));
  conn->wfd = fd;

  fd = conn->listen_fd;
  conn->listen_fd = 79;
  res = pr_inet_set_async(p, conn);
  fail_unless(res == 0, "Failed to set conn %p async: %s", conn,
    strerror(errno));
  conn->listen_fd = fd;

  pr_inet_close(p, conn);
}
예제 #19
0
파일: inet.c 프로젝트: Nakor78/proftpd
END_TEST

START_TEST (inet_accept_nowait_test) {
  int sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;

  res = pr_inet_accept_nowait(NULL, NULL);
  fail_unless(res < 0, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_accept_nowait(p, conn);
  fail_unless(res < 0, "Accepted connection unexpectedly");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  pr_inet_close(p, conn);
}
예제 #20
0
파일: display.c 프로젝트: Nakor78/proftpd
static void tear_down(void) {
  pr_response_register_handler(NULL);

  if (session.c != NULL) {
    pr_inet_close(p, session.c);
    session.c = NULL;
  }

  pr_unregister_netio(PR_NETIO_STRM_CTRL);

  if (getenv("TEST_VERBOSE") != NULL) {
    pr_trace_set_levels("netio", 0, 0);
    pr_trace_set_levels("response", 0, 0);
  }

  (void) unlink(display_test_file);

  if (p) {
    destroy_pool(p);
    p = session.pool = permanent_pool = NULL;
  }
}
예제 #21
0
파일: data.c 프로젝트: 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;
}
예제 #22
0
static int forward_connect(pool *p, struct proxy_session *proxy_sess,
    pr_response_t **resp, unsigned int *resp_nlines) {
  conn_t *server_conn = NULL;
  int banner_ok = TRUE, use_tls, xerrno = 0;
  pr_netaddr_t *dst_addr;
  array_header *other_addrs = NULL;

  dst_addr = proxy_sess->dst_addr;
  other_addrs = proxy_sess->other_addrs;

  server_conn = proxy_conn_get_server_conn(p, proxy_sess, dst_addr);
  if (server_conn == NULL) {
    xerrno = errno;

    if (other_addrs != NULL) {
      register unsigned int i;

      /* Try the other IP addresses for the requested name (if any) as well. */
      for (i = 0; i < other_addrs->nelts; i++) {
        dst_addr = ((pr_netaddr_t **) other_addrs->elts)[i];

        pr_trace_msg(trace_channel, 8,
          "attempting to connect to other address #%u (%s) for requested "
          "URI '%.100s'", i+1, pr_netaddr_get_ipstr(dst_addr),
          proxy_conn_get_uri(proxy_sess->dst_pconn));
        server_conn = proxy_conn_get_server_conn(p, proxy_sess, dst_addr);
        if (server_conn != NULL) {
          proxy_sess->dst_addr = dst_addr;
          break;
        }
      }
    }

    if (server_conn == NULL) {
      xerrno = errno;

      /* EINVALs lead to strange-looking error responses; change them to
       * EPERM.
       */
      if (xerrno == EINVAL) {
        xerrno = EPERM;
      }
    }

    errno = xerrno;
    return -1;
  }

  /* XXX Support/send a CLNT command of our own?  Configurable via e.g.
   * "UserAgent" string?
   */

  proxy_sess->frontend_ctrl_conn = session.c;
  proxy_sess->backend_ctrl_conn = server_conn;

  /* Read the response from the backend server. */
  *resp = proxy_ftp_ctrl_recv_resp(p, proxy_sess->backend_ctrl_conn,
    resp_nlines);
  if (*resp == NULL) {
    xerrno = errno;

    pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
      "unable to read banner from server %s:%u: %s",
      pr_netaddr_get_ipstr(proxy_sess->backend_ctrl_conn->remote_addr),
      ntohs(pr_netaddr_get_port(proxy_sess->backend_ctrl_conn->remote_addr)),
      strerror(xerrno));

    errno = EPERM;
    return -1;
  }

  if ((*resp)->num[0] != '2') {
    banner_ok = FALSE;
  }

  (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
    "received banner from backend %s:%u%s: %s %s",
    pr_netaddr_get_ipstr(proxy_sess->backend_ctrl_conn->remote_addr),
    ntohs(pr_netaddr_get_port(proxy_sess->backend_ctrl_conn->remote_addr)),
    banner_ok ? "" : ", DISCONNECTING", (*resp)->num, (*resp)->msg);

  if (banner_ok == FALSE) {
    pr_inet_close(p, proxy_sess->backend_ctrl_conn);
    proxy_sess->backend_ctrl_conn = NULL;

    errno = EPERM;
    return -1;
  }

  /* Get the features supported by the backend server */
  if (proxy_ftp_sess_get_feat(p, proxy_sess) < 0) {
    if (errno != EPERM) {
      (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
        "unable to determine features of backend server: %s", strerror(errno));
    }
  }

  use_tls = proxy_tls_use_tls();
  if (use_tls != PROXY_TLS_ENGINE_OFF) {
    if (proxy_ftp_sess_send_auth_tls(p, proxy_sess) < 0) {
      xerrno = errno;

      (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
        "error enabling TLS on control connection to backend server: %s",
        strerror(xerrno));
      pr_inet_close(p, proxy_sess->backend_ctrl_conn);
      proxy_sess->backend_ctrl_conn = NULL;

      *resp = NULL;
      errno = xerrno;
      return -1;
    }
  }

  if (proxy_netio_postopen(server_conn->instrm) < 0) {
    xerrno = errno;

    (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
      "postopen error for backend control connection input stream: %s",
      strerror(xerrno));
    proxy_inet_close(session.pool, server_conn);
    proxy_sess->backend_ctrl_conn = NULL;

    *resp = NULL;
    errno = xerrno;
    return -1;
  }

  if (proxy_netio_postopen(server_conn->outstrm) < 0) {
    xerrno = errno;

    (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
      "postopen error for backend control connection output stream: %s",
      strerror(xerrno));
    proxy_inet_close(session.pool, server_conn);
    proxy_sess->backend_ctrl_conn = NULL;

    *resp = NULL;
    errno = xerrno;
    return -1;
  }

  if (use_tls != PROXY_TLS_ENGINE_OFF) {
    if (proxy_sess_state & PROXY_SESS_STATE_BACKEND_HAS_CTRL_TLS) {
      /* NOTE: should this be a fatal error? */
      (void) proxy_ftp_sess_send_pbsz_prot(p, proxy_sess);
    }
  }

  (void) proxy_ftp_sess_send_host(p, proxy_sess);

  proxy_sess_state |= PROXY_SESS_STATE_CONNECTED;
  return 0;
}
예제 #23
0
파일: ident.c 프로젝트: proftpd/proftpd
char *pr_ident_lookup(pool *p, conn_t *c) {
  char *ret = "UNKNOWN";
  pool *tmp_pool = NULL;
  conn_t *ident_conn = NULL, *ident_io = NULL;
  char buf[256] = {'\0'}, *tok = NULL, *tmp = NULL;
  int timerno, i = 0;
  int ident_port = pr_inet_getservport(p, "ident", "tcp");

  tmp_pool = make_sub_pool(p);
  ident_timeout = 0;
  nstrm = NULL;

  if (ident_port == -1) {
    destroy_pool(tmp_pool);
    return pstrdup(p, ret);
  }

  /* Set up our timer before going any further. */
  timerno = pr_timer_add(PR_TUNABLE_TIMEOUTIDENT, -1, NULL,
    (callback_t) ident_timeout_cb, "ident lookup");
  if (timerno <= 0) {
    destroy_pool(tmp_pool);
    return pstrdup(p, ret);
  }

  ident_conn = pr_inet_create_connection(tmp_pool, NULL, -1, c->local_addr,
    INPORT_ANY, FALSE);
  pr_inet_set_nonblock(tmp_pool, ident_conn);

  i = pr_inet_connect_nowait(tmp_pool, ident_conn, c->remote_addr, ident_port);
  if (i < 0) {
    int xerrno = errno;

    pr_timer_remove(timerno, ANY_MODULE);
    pr_inet_close(tmp_pool, ident_conn);
    pr_trace_msg(trace_channel, 5, "connection to %s, port %d failed: %s",
      pr_netaddr_get_ipstr(c->remote_addr), ident_port, strerror(xerrno));

    destroy_pool(tmp_pool);

    errno = xerrno;
    return pstrdup(p, ret);
  }

  if (!i) {
    /* Not yet connected. */
    nstrm = pr_netio_open(p, PR_NETIO_STRM_OTHR, ident_conn->listen_fd,
      PR_NETIO_IO_RD);
    pr_netio_set_poll_interval(nstrm, 1);

    switch (pr_netio_poll(nstrm)) {

      /* Aborted, timed out */
      case 1: {
        if (ident_timeout) {
          pr_timer_remove(timerno, ANY_MODULE);
          pr_netio_close(nstrm);
          pr_inet_close(tmp_pool, ident_conn);

          pr_trace_msg(trace_channel, 5, "lookup timed out, returning '%s'",
            ret);
          destroy_pool(tmp_pool);
          return pstrdup(p, ret);
        }
        break;
      }

      /* Error. */
      case -1: {
        int xerrno = errno;

        pr_timer_remove(timerno, ANY_MODULE);
        pr_netio_close(nstrm);
        pr_inet_close(tmp_pool, ident_conn);

        pr_trace_msg(trace_channel, 6, "lookup failed (%s), returning '%s'",
          strerror(xerrno), ret);
        destroy_pool(tmp_pool);

        errno = xerrno;
        return pstrdup(p, ret);
      }

      /* Connected. */
      default: {
        ident_conn->mode = CM_OPEN;

        if (pr_inet_get_conn_info(ident_conn, ident_conn->listen_fd) < 0) {
          int xerrno = errno;

          pr_timer_remove(timerno, ANY_MODULE);
          pr_netio_close(nstrm);
          pr_inet_close(tmp_pool, ident_conn);

          pr_trace_msg(trace_channel, 2,
            "lookup timed out (%s), returning '%s'", strerror(xerrno), ret);
          destroy_pool(tmp_pool);

          errno = xerrno;
          return pstrdup(p, ret);
        }
        break;
      }
    }
  }

  ident_io = pr_inet_openrw(tmp_pool, ident_conn, NULL, PR_NETIO_STRM_OTHR,
    -1, -1, -1, FALSE);
  if (ident_io == NULL) {
    int xerrno = errno;

    pr_timer_remove(timerno, ANY_MODULE);
    pr_inet_close(tmp_pool, ident_conn);

    pr_trace_msg(trace_channel, 3, "failed opening read/write connection: %s",
      strerror(xerrno));
    destroy_pool(tmp_pool);

    errno = xerrno;
    return pstrdup(p, ret);
  }

  nstrm = ident_io->instrm;

  pr_inet_set_nonblock(tmp_pool, ident_io);
  pr_netio_set_poll_interval(ident_io->instrm, 1);
  pr_netio_set_poll_interval(ident_io->outstrm, 1);

  pr_netio_printf(ident_io->outstrm, "%d, %d\r\n", c->remote_port,
    c->local_port);

  /* If the timer fires while in netio_gets(), netio_gets() will simply return
   * either a partial string, or NULL.  This works because ident_timeout_cb
   * aborts the stream from which we are reading.  netio_set_poll_interval() is
   * used to make sure significant delays don't occur on systems that
   * automatically restart syscalls after the SIGALRM signal.
   */

  pr_trace_msg(trace_channel, 4, "reading response from remote ident server");

  if (pr_netio_gets(buf, sizeof(buf), ident_io->instrm)) {
    strip_end(buf, "\r\n");

    pr_trace_msg(trace_channel, 6, "received '%s' from remote ident server",
      buf);

    tmp = buf;
    tok = get_token(&tmp, ":");
    if (tok && (tok = get_token(&tmp, ":"))) {
      while (*tok && isspace((int) *tok)) {
        pr_signals_handle();
        tok++;
      }
      strip_end(tok, " \t");

      if (strcasecmp(tok, "ERROR") == 0) {
        if (tmp) {
          while (*tmp && isspace((int) *tmp)) {
            pr_signals_handle();
            tmp++;
          }
	  strip_end(tmp, " \t");
          if (strcasecmp(tmp, "HIDDEN-USER") == 0)
            ret = "HIDDEN-USER";
        }

      } else if (strcasecmp(tok, "USERID") == 0) {
        if (tmp && (tok = get_token(&tmp, ":"))) {
          if (tmp) {
            while (*tmp && isspace((int) *tmp)) {
              pr_signals_handle();
              tmp++;
            }
            strip_end(tmp, " \t");
            ret = tmp;
          }
        }
      }
    }
  }

  pr_timer_remove(timerno, ANY_MODULE);
  pr_inet_close(tmp_pool, ident_io);
  pr_inet_close(tmp_pool, ident_conn);
  destroy_pool(tmp_pool);

  return pstrdup(p, ret);
}
예제 #24
0
파일: inet.c 프로젝트: proftpd/proftpd
END_TEST

START_TEST (inet_connect_ipv6_test) {
#ifdef PR_USE_IPV6
  int sockfd = -1, port = INPORT_ANY, res;
  conn_t *conn;
  const pr_netaddr_t *addr;
  unsigned char use_ipv6;

  use_ipv6 = pr_netaddr_use_ipv6();

  pr_netaddr_enable_ipv6();
  pr_inet_set_default_family(p, AF_INET6);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  addr = pr_netaddr_get_addr(p, "::1", NULL);
  fail_unless(addr != NULL, "Failed to resolve '::1': %s",
    strerror(errno));

  res = pr_inet_connect(p, conn, addr, 80);
  fail_unless(res < 0, "Connected to ::1#80 unexpectedly");
  fail_unless(errno == ECONNREFUSED || errno == ENETUNREACH,
    "Expected ECONNREFUSED (%d) or ENETUNREACH (%d), got %s (%d)",
    ECONNREFUSED, ENETUNREACH, strerror(errno), errno);

  /* Try connecting to Google's DNS server. */

  addr = pr_netaddr_get_addr(p, "2001:4860:4860::8888", NULL);
  fail_unless(addr != NULL, "Failed to resolve '2001:4860:4860::8888': %s",
    strerror(errno));

  res = pr_inet_connect(p, conn, addr, 53);
  if (res < 0) {
    /* Note: We get EINVAL here because the socket already tried (and failed)
     * to connect to a different address.  Interestingly, trying to connect(2)
     * using that same fd to a different address yields EINVAL.
     */
    fail_unless(errno == EINVAL || errno == ENETUNREACH,
      "Expected EINVAL (%d) or ENETUNREACH (%d), got %s (%d)",
      EINVAL, ENETUNREACH, strerror(errno), errno);
  }
  pr_inet_close(p, conn);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  res = pr_inet_connect(p, conn, addr, 53);
  if (res < 0) {
    /* This could be expected, e.g. if there's no route. */
    fail_unless(errno == EHOSTUNREACH || errno == ENETUNREACH,
      "Expected EHOSTUNREACH (%d) or ENETUNREACH (%d), got %s (%d)",
      EHOSTUNREACH, ENETUNREACH, strerror(errno), errno);
  }

  res = pr_inet_connect(p, conn, addr, 53);
  fail_unless(res < 0, "Failed to connect to 2001:4860:4860::8888#53: %s",
    strerror(errno));
  fail_unless(errno == EISCONN || errno == EHOSTUNREACH || errno == ENETUNREACH,
    "Expected EISCONN (%d) or EHOSTUNREACH (%d) or ENETUNREACH (%d), "
    "got %s (%d)", EISCONN, EHOSTUNREACH, ENETUNREACH, strerror(errno), errno);
  pr_inet_close(p, conn);

  pr_inet_set_default_family(p, AF_INET);

  if (use_ipv6 == FALSE) {
    pr_netaddr_disable_ipv6();
  }
#endif /* PR_USE_IPV6 */
}
예제 #25
0
파일: session.c 프로젝트: Nubisa/JXPanel
static void sess_cleanup(int flags) {

  /* Clear the scoreboard entry. */
  if (ServerType == SERVER_STANDALONE) {

    /* For standalone daemons, we only clear the scoreboard slot if we are
     * an exiting child process.
     */

    if (!is_master) {
      if (pr_scoreboard_entry_del(TRUE) < 0 &&
          errno != EINVAL &&
          errno != ENOENT) {
        pr_log_debug(DEBUG1, "error deleting scoreboard entry: %s",
          strerror(errno));
      }
    }

  } else if (ServerType == SERVER_INETD) {
    /* For inetd-spawned daemons, we always clear the scoreboard slot. */
    if (pr_scoreboard_entry_del(TRUE) < 0 &&
        errno != EINVAL &&
        errno != ENOENT) {
      pr_log_debug(DEBUG1, "error deleting scoreboard entry: %s",
        strerror(errno));
    }
  }

  /* If session.user is set, we have a valid login. */
  if (session.user &&
      session.wtmp_log) {
    const char *sess_ttyname;

    sess_ttyname = pr_session_get_ttyname(session.pool);
    log_wtmp(sess_ttyname, "", pr_netaddr_get_sess_remote_name(),
      pr_netaddr_get_sess_remote_addr());
  }

  /* These are necessary in order that cleanups associated with these pools
   * (and their subpools) are properly run.
   */
  if (session.d) {
    pr_inet_close(session.pool, session.d);
    session.d = NULL;
  }

  if (session.c) {
    pr_inet_close(session.pool, session.c);
    session.c = NULL;
  }

  /* Run all the exit handlers */
  pr_event_generate("core.exit", NULL);

  if (!is_master ||
      (ServerType == SERVER_INETD &&
      !(flags & PR_SESS_END_FL_SYNTAX_CHECK))) {
    pr_log_pri(PR_LOG_INFO, "%s session closed.",
      pr_session_get_protocol(PR_SESS_PROTO_FL_LOGOUT));
  }

  log_closesyslog();
}
예제 #26
0
파일: bindings.c 프로젝트: dbarba74/proftpd
int pr_ipbind_close(pr_netaddr_t *addr, unsigned int port,
    unsigned char close_namebinds) {
  int res = 0;
  register unsigned int i = 0;

  if (addr) {
    pr_ipbind_t *ipbind = NULL;
    unsigned char have_ipbind = FALSE;

    i = ipbind_hash_addr(addr);

    if (ipbind_table[i] == NULL) {
      pr_log_pri(PR_LOG_NOTICE, "notice: no ipbind found for %s:%d",
        pr_netaddr_get_ipstr(addr), port);
      errno = ENOENT;
      return -1;
    }

    for (ipbind = ipbind_table[i]; ipbind; ipbind = ipbind->ib_next) {
      if (pr_netaddr_cmp(ipbind->ib_addr, addr) == 0 &&
          (!ipbind->ib_port || ipbind->ib_port == port)) {
        have_ipbind = TRUE;
        break;
      }
    }

    if (!have_ipbind) {
      pr_log_pri(PR_LOG_NOTICE, "notice: no ipbind found for %s:%d",
        pr_netaddr_get_ipstr(addr), port);
      errno = ENOENT;
      return -1;
    }

    /* If already closed, exit now. */
    if (!ipbind->ib_isactive) {
      errno = EPERM;
      return -1;
    }

    /* Close the ipbinding's listen connection, if present.  The trick
     * here is determining whether this binding's listen member is
     * _the_ listening socket for the master daemon, or whether it's
     * been created for SocketBindTight, and can be closed.
     *
     * Actually, it's not that hard.  It's only _the_ listening socket
     * for the master daemon in inetd mode, in which case virtual servers
     * can't be shutdown via ftpdctl, anyway.
     */
    if (SocketBindTight && ipbind->ib_listener != NULL) {
      pr_inet_close(ipbind->ib_server->pool, ipbind->ib_listener);
      ipbind->ib_listener = ipbind->ib_server->listen = NULL;
    }

    /* Mark this ipbind as inactive.  For SocketBindTight sockets, the
     * closing of the listening connection will suffice, from the clients'
     * point of view.  However, this covers the non-SocketBindTight case,
     * and will prevent this binding from returning its server_rec pointer
     * on future lookup requests via pr_ipbind_get_server().
     */
    ipbind->ib_isactive = FALSE;

    if (close_namebinds && ipbind->ib_namebinds) {
      register unsigned int j = 0;
      pr_namebind_t **namebinds = NULL;

      namebinds = (pr_namebind_t **) ipbind->ib_namebinds->elts;
      for (j = 0; j < ipbind->ib_namebinds->nelts; j++) {
        pr_namebind_t *nb = namebinds[j];

        PR_CLOSE_NAMEBIND(nb->nb_name, nb->nb_server->addr,
          nb->nb_server->ServerPort);
      }
    }

  } else {

    /* A NULL addr has a special meaning: close _all_ ipbinds in the
     * list.
     */

    for (i = 0; i < PR_BINDINGS_TABLE_SIZE; i++) {
      pr_ipbind_t *ipbind = NULL;
      for (ipbind = ipbind_table[i]; ipbind; ipbind = ipbind->ib_next) {

        if (SocketBindTight && ipbind->ib_listener != NULL) {
          pr_inet_close(main_server->pool, ipbind->ib_listener);
          ipbind->ib_listener = ipbind->ib_server->listen = NULL;
        }

        /* Note: do not need to check if this ipbind was previously closed,
         * for the NULL addr is a request to shut down all ipbinds,
         * regardless of their current state.
         */
        ipbind->ib_isactive = FALSE;

        if (close_namebinds && ipbind->ib_namebinds) {
          register unsigned int j = 0;
          pr_namebind_t **namebinds = NULL;

          namebinds = (pr_namebind_t **) ipbind->ib_namebinds->elts;
          for (j = 0; j < ipbind->ib_namebinds->nelts; j++) {
            pr_namebind_t *nb = namebinds[j];

            PR_CLOSE_NAMEBIND(nb->nb_name, nb->nb_server->addr,
              nb->nb_server->ServerPort);
          }
        }
      }
    }
  }

  return 0;
}
예제 #27
0
파일: data.c 프로젝트: 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;
}
예제 #28
0
파일: inet.c 프로젝트: Nakor78/proftpd
END_TEST

START_TEST (inet_copy_conn_test) {
  int fd = -1, sockfd = -1, port = INPORT_ANY;
  conn_t *conn, *conn2;
  const char *name;

  conn = pr_inet_copy_conn(NULL, NULL);
  fail_unless(conn == NULL, "Failed to handle null arguments");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_copy_conn(p, NULL);
  fail_unless(conn == NULL, "Failed to handle null conn argument");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  conn2 = pr_inet_copy_conn(p, conn);
  fail_unless(conn2 != NULL, "Failed to copy conn: %s", strerror(errno));

  pr_inet_close(p, conn);
  pr_inet_close(p, conn2);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  name = "127.0.0.1";
  conn->remote_addr = pr_netaddr_get_addr(p, name, NULL);
  fail_unless(conn->remote_addr != NULL, "Failed to resolve '%s': %s",
    name, strerror(errno));
  conn->remote_name = pstrdup(p, name);
  conn->instrm = pr_netio_open(p, PR_NETIO_STRM_CTRL, fd, PR_NETIO_IO_RD);
  fail_unless(conn->instrm != NULL, "Failed to open ctrl reading stream: %s",
    strerror(errno));
  conn->outstrm = pr_netio_open(p, PR_NETIO_STRM_CTRL, fd, PR_NETIO_IO_WR);
  fail_unless(conn->instrm != NULL, "Failed to open ctrl writing stream: %s",
    strerror(errno));

  conn2 = pr_inet_copy_conn(p, conn);
  fail_unless(conn2 != NULL, "Failed to copy conn: %s", strerror(errno));

  mark_point();
  pr_inet_lingering_close(NULL, NULL, 0L);

  pr_inet_lingering_close(p, conn, 0L);
  pr_inet_close(p, conn2);

  conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE);
  fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno));

  conn->instrm = pr_netio_open(p, PR_NETIO_STRM_CTRL, fd, PR_NETIO_IO_RD);
  fail_unless(conn->instrm != NULL, "Failed to open ctrl reading stream: %s",
    strerror(errno));
  conn->outstrm = pr_netio_open(p, PR_NETIO_STRM_CTRL, fd, PR_NETIO_IO_WR);
  fail_unless(conn->instrm != NULL, "Failed to open ctrl writing stream: %s",
    strerror(errno));

  mark_point();
  pr_inet_lingering_abort(NULL, NULL, 0L);

  pr_inet_lingering_abort(p, conn, 0L);
}
예제 #29
0
int main(int argc, char *argv[]) {
  pool *p;
  const char *remote_name;
  pr_netaddr_t *remote_addr;
  conn_t *client_conn, *ctrl_conn, *data_conn;
  unsigned int connect_timeout, remote_port;
  struct proxy_ftp_client *ftp;
  int res, timerno;
  char buf[1024];

  /* Seed the random number generator. */
  /* XXX Use random(3) in the future? */
  srand((unsigned int) (time(NULL) * getpid()));

  init_pools();
  init_privs();
  init_log();
  init_regexp();
  init_inet();
  init_netio();
  init_netaddr();
  init_fs();
  init_class();
  init_config();
  init_stash();

  pr_log_setdebuglevel(10);
  log_stderr(TRUE);
  pr_trace_use_stderr(TRUE);
  pr_trace_set_levels("DEFAULT", 1, 20);

  p = make_sub_pool(permanent_pool);
  pr_pool_tag(p, "FTP Client Pool");

  remote_name = "ftp.proftpd.org";

  remote_addr = pr_netaddr_get_addr(p, remote_name, NULL);
  if (remote_addr == NULL) {
    fprintf(stderr, "Failed to get addr for '%s': %s\n", remote_name,
      strerror(errno));
    destroy_pool(p);
    return 1;
  } 

  fprintf(stdout, "Resolved name '%s' to IP address '%s'\n", remote_name,
    pr_netaddr_get_ipstr(remote_addr));

  remote_port = 21;
  connect_timeout = 5;
  ftp = proxy_ftp_connect(p, remote_addr, remote_port, connect_timeout, NULL);
  if (ftp == NULL) {
    fprintf(stderr, "Error connecting to FTP server: %s\n", strerror(errno));
    destroy_pool(p);
    return 1;
  }

  fprintf(stdout, "Successfully connected to %s:%d from %s:%d\n", remote_name,
    remote_port, pr_netaddr_get_ipstr(client_conn->local_addr),
    ntohs(pr_netaddr_get_port(client_conn->local_addr)));

  res = proxy_ftp_disconnect(ftp);
  if (res < 0) {
    fprintf(stderr, "Error disconnecting from FTP server: %s\n",
      strerror(errno));
    destroy_pool(p);
    return 1;
  }

  ctrl_conn = pr_inet_openrw(p, client_conn, NULL, PR_NETIO_STRM_OTHR,
    -1, -1, -1, FALSE);
  if (ctrl_conn == NULL) {
    fprintf(stderr, "Error opening control connection: %s\n", strerror(errno));

    pr_inet_close(p, client_conn);
    destroy_pool(p);
    return 1;
  }

  fprintf(stdout, "Reading response from %s:%d\n", remote_name, remote_port);

  /* Read the response */
  memset(buf, '\0', sizeof(buf));

  /* XXX We need to write our own version of netio_telnet_gets(), with
   * the buffering to handle reassembly of a full FTP response out of
   * multiple TCP packets.  Not sure why the existing netio_telnet_gets()
   * is not sufficient.  But we don't need the handling of Telnet codes
   * in our reading.  But DO generate the 'core.ctrl-read' event, so that
   * any event listeners get a chance to process the data we've received.
   * (Or maybe use 'mod_proxy.server-read', and differentiate between
   * client and server reads/writes?)
   */
  if (pr_netio_read(ctrl_conn->instrm, buf, sizeof(buf)-1, 5) < 0) {
    fprintf(stderr, "Error reading response from server: %s\n",
      strerror(errno));

  } else {
    fprintf(stdout, "Response: \"%s\"\n", buf);
  }

  /* Disconnect */
  res = pr_netio_printf(ctrl_conn->outstrm, "%s\r\n", C_QUIT);
  if (res < 0) {
    fprintf(stderr, "Error writing command to server: %s", strerror(errno));
  }

  pr_inet_close(p, ctrl_conn);
  pr_inet_close(p, client_conn);
  destroy_pool(p);
  return 0;
}
예제 #30
0
END_TEST

START_TEST (connect_test) {
  conn_t *res;
  const pr_netaddr_t *remote_addr = NULL;

  res = proxy_ftp_conn_connect(NULL, NULL, NULL, FALSE);
  fail_unless(res == NULL, "Failed to handle null pool");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL,
    strerror(errno), errno);

  res = proxy_ftp_conn_connect(p, NULL, NULL, FALSE);
  fail_unless(res == NULL, "Failed to handle null remote addr");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL,
    strerror(errno), errno);

  remote_addr = pr_netaddr_get_addr(p, "127.0.0.1", NULL);
  fail_unless(remote_addr != NULL, "Failed to address for 127.0.0.1: %s",
    strerror(errno));
  pr_netaddr_set_port((pr_netaddr_t *) remote_addr, htons(6555));

  session.xfer.direction = PR_NETIO_IO_RD;

  mark_point();
  res = proxy_ftp_conn_connect(p, NULL, remote_addr, FALSE);
  fail_unless(res == NULL, "Failed to handle bad address family");
  fail_unless(errno == ECONNREFUSED, "Expected ECONNREFUSED (%d), got %s (%d)",
    ECONNREFUSED, strerror(errno), errno);

  mark_point();
  res = proxy_ftp_conn_connect(p, NULL, remote_addr, TRUE);
  fail_unless(res == NULL, "Failed to handle bad address family");
  fail_unless(errno == ECONNREFUSED, "Expected ECONNREFUSED (%d), got %s (%d)",
    ECONNREFUSED, strerror(errno), errno);

  session.xfer.direction = PR_NETIO_IO_WR;

  mark_point();
  res = proxy_ftp_conn_connect(p, NULL, remote_addr, FALSE);
  fail_unless(res == NULL, "Failed to handle bad address family");
  fail_unless(errno == ECONNREFUSED, "Expected ECONNREFUSED (%d), got %s (%d)",
    ECONNREFUSED, strerror(errno), errno);

  mark_point();
  res = proxy_ftp_conn_connect(p, NULL, remote_addr, TRUE);
  fail_unless(res == NULL, "Failed to handle bad address family");
  fail_unless(errno == ECONNREFUSED, "Expected ECONNREFUSED (%d), got %s (%d)",
    ECONNREFUSED, strerror(errno), errno);

  /* Try connecting to Google's DNS server. */

  remote_addr = pr_netaddr_get_addr(p, "8.8.8.8", NULL);
  fail_unless(remote_addr != NULL, "Failed to resolve '8.8.8.8': %s",
    strerror(errno));
  pr_netaddr_set_port((pr_netaddr_t *) remote_addr, htons(53));

  mark_point();
  res = proxy_ftp_conn_connect(p, NULL, remote_addr, FALSE);
  fail_unless(res != NULL, "Failed to connect: %s", strerror(errno));
  pr_inet_close(p, res);

  mark_point();
  res = proxy_ftp_conn_connect(p, NULL, remote_addr, TRUE);
  fail_unless(res != NULL, "Failed to connect: %s", strerror(errno));
  pr_inet_close(p, res);
}