コード例 #1
0
ファイル: netaddr.c プロジェクト: netdna/proftpd
END_TEST
#endif /* PR_USE_IPV6 */

START_TEST (netaddr_get_ipstr_test) {
  pr_netaddr_t *addr;
  const char *res;

  res = pr_netaddr_get_ipstr(NULL);
  fail_unless(res == NULL, "Failed to handle null argument");
  fail_unless(errno == EINVAL, "Failed to set errno to EINVAL");

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

  res = pr_netaddr_get_ipstr(addr);
  fail_unless(res != NULL, "Failed to get IP str for addr: %s",
    strerror(errno));
  fail_unless(strcmp(res, "127.0.0.1") == 0, "Expected '%s', got '%s'",
    "127.0.0.1", res);
  fail_unless(addr->na_have_ipstr == 1, "addr should have cached IP str");

  pr_netaddr_clear(addr);
  res = pr_netaddr_get_ipstr(addr);
  fail_unless(res == NULL, "Expected null, got '%s'", res);

}
コード例 #2
0
int proxy_forward_sess_init(pool *p, const char *tables_dir,
    struct proxy_session *proxy_sess) {
  config_rec *c;
  int allowed = FALSE;
  void *enabled = NULL;

  /* By default, only allow connections from RFC1918 addresses to use
   * forward proxying.  Otherwise, it must be from an explicitly allowed
   * connection class, via the class notes.
   */
  if (session.conn_class != NULL) {
    enabled = pr_table_get(session.conn_class->cls_notes,
      PROXY_FORWARD_ENABLED_NOTE, NULL);
  }

  if (enabled != NULL) {
    allowed = *((int *) enabled);
    if (allowed == FALSE) {
      (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
        "forward proxying not allowed from client address %s in <Class %s> "
        "(see ProxyForwardEnabled)",
        pr_netaddr_get_ipstr(session.c->remote_addr),
        session.conn_class->cls_name);
    }

  } else {
    if (pr_netaddr_is_rfc1918(session.c->remote_addr) == TRUE) {
      allowed = TRUE;

    } else {
      (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
        "forward proxying not allowed from non-RFC1918 client address %s",
        pr_netaddr_get_ipstr(session.c->remote_addr));
    }
  }

  if (allowed == FALSE) {
    errno = EPERM;
    return -1;
  }

  c = find_config(main_server->conf, CONF_PARAM, "ProxyForwardMethod", FALSE);
  if (c != NULL) {
    proxy_method = *((int *) c->argv[0]);
  }

  c = find_config(main_server->conf, CONF_PARAM, "ProxyRetryCount", FALSE);
  if (c != NULL) {
    forward_retry_count = *((int *) c->argv[0]);
  }

  return 0;
}
コード例 #3
0
ファイル: bindings.c プロジェクト: dbarba74/proftpd
int pr_ipbind_create(server_rec *server, pr_netaddr_t *addr,
    unsigned int port) {
  pr_ipbind_t *ipbind = NULL;
  register unsigned int i = 0;

  if (server == NULL||
      addr == NULL) {
    errno = EINVAL;
    return -1;
  }

  i = ipbind_hash_addr(addr);

  /* Make sure the address is not already in use */
  for (ipbind = ipbind_table[i]; ipbind; ipbind = ipbind->ib_next) {
    if (pr_netaddr_cmp(ipbind->ib_addr, addr) == 0 &&
        ipbind->ib_port == port) {

      /* An ipbind already exists for this IP address */
      pr_log_pri(PR_LOG_WARNING, "notice: '%s' (%s:%u) already bound to '%s'",
        server->ServerName, pr_netaddr_get_ipstr(addr), port,
        ipbind->ib_server->ServerName);

      errno = EADDRINUSE;
      return -1;
    }
  }

  if (!binding_pool) {
    binding_pool = make_sub_pool(permanent_pool);
    pr_pool_tag(binding_pool, "Bindings Pool");
  }

  ipbind = pcalloc(server->pool, sizeof(pr_ipbind_t));
  ipbind->ib_server = server;
  ipbind->ib_addr = addr;
  ipbind->ib_port = port;
  ipbind->ib_namebinds = NULL;
  ipbind->ib_isdefault = FALSE;
  ipbind->ib_islocalhost = FALSE;
  ipbind->ib_isactive = FALSE;

  pr_trace_msg(trace_channel, 8, "created IP binding for %s#%u, server %p",
    pr_netaddr_get_ipstr(ipbind->ib_addr), ipbind->ib_port, ipbind->ib_server);

  /* Add the ipbind to the table. */
  if (ipbind_table[i]) {
    ipbind->ib_next = ipbind_table[i];
  }

  ipbind_table[i] = ipbind;
  return 0;
}
コード例 #4
0
ファイル: mod_dynmasq.c プロジェクト: predever/proftpd
static void dynmasq_refresh(void) {
    server_rec *s;

    pr_log_debug(DEBUG2, MOD_DYNMASQ_VERSION
                 ": resolving all MasqueradeAddress directives (could take a little while)");

    for (s = (server_rec *) server_list->xas_list; s; s = s->next) {
        config_rec *c;

        c = find_config(s->conf, CONF_PARAM, "MasqueradeAddress", FALSE);
        if (c != NULL) {
            const char *masq_addr;
            pr_netaddr_t *na;

            masq_addr = c->argv[1];

            pr_netaddr_clear_ipcache(masq_addr);
            na = pr_netaddr_get_addr(s->pool, masq_addr, NULL);
            if (na != NULL) {
                /* Compare the obtained netaddr with the one already present.
                 * Only update the "live" netaddr if they differ.
                 */
                pr_log_debug(DEBUG2, MOD_DYNMASQ_VERSION
                             ": resolved MasqueradeAddress '%s' to IP address %s", masq_addr,
                             pr_netaddr_get_ipstr(na));

                if (pr_netaddr_cmp(c->argv[0], na) != 0) {
                    pr_log_pri(PR_LOG_DEBUG, MOD_DYNMASQ_VERSION
                               ": MasqueradeAddress '%s' updated for new address %s (was %s)",
                               masq_addr, pr_netaddr_get_ipstr(na),
                               pr_netaddr_get_ipstr(c->argv[0]));

                    /* Overwrite the old netaddr pointer.  Note that this constitutes
                     * a minor memory leak, as there currently isn't a way to free
                     * the memory used by a netaddr object.  Hrm.
                     */
                    c->argv[0] = na;

                } else {
                    pr_log_debug(DEBUG2, MOD_DYNMASQ_VERSION
                                 ": MasqueradeAddress '%s' has not changed addresses", masq_addr);
                }

            } else {
                pr_log_pri(PR_LOG_INFO, MOD_DYNMASQ_VERSION
                           ": unable to resolve '%s', keeping previous address", masq_addr);
            }
        }
    }

    return;
}
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);
}
コード例 #6
0
ファイル: netaddr.c プロジェクト: WiseMan787/ralink_sdk
int pr_netaddr_fnmatch(pr_netaddr_t *na, const char *pattern, int flags) {

  /* Note: I'm still not sure why proftpd bundles an fnmatch(3)
   * implementation rather than using the system library's implementation.
   * Needs looking into.
   *
   * The FNM_CASEFOLD flag is a GNU extension; perhaps the bundled
   * implementation was added to make that flag available on other platforms.
   */
  int match_flags = PR_FNM_NOESCAPE|PR_FNM_CASEFOLD;

  if (!na || !pattern) {
    errno = EINVAL;
    return -1;
  }

  if (flags & PR_NETADDR_MATCH_DNS) {
    const char *dnsstr = pr_netaddr_get_dnsstr(na);

    if (pr_fnmatch(pattern, dnsstr, match_flags) == 0) {
      pr_trace_msg(trace_channel, 6, "DNS name '%s' matches pattern '%s'",
        dnsstr, pattern);
      return TRUE;
    }
  }

  if (flags & PR_NETADDR_MATCH_IP) {
    const char *ipstr = pr_netaddr_get_ipstr(na);

    if (pr_fnmatch(pattern, ipstr, match_flags) == 0) {
      pr_trace_msg(trace_channel, 6, "DNS name '%s' matches pattern '%s'",
        ipstr, pattern);
      return TRUE;
    }
  }

  pr_trace_msg(trace_channel, 4, "addr %s does not match pattern '%s'",
    pr_netaddr_get_ipstr(na), pattern);
  return FALSE;
}
コード例 #7
0
ファイル: msg.c プロジェクト: Castaglia/proftpd-mod_proxy
const char *proxy_ftp_msg_fmt_addr(pool *p, const pr_netaddr_t *addr,
    unsigned short port, int use_masqaddr) {
  char *addr_str, *msg, *ptr;
  size_t msglen;

  if (p == NULL ||
      addr == NULL) {
    errno = EINVAL;
    return NULL;
  }

  if (use_masqaddr) {
    config_rec *c;

    /* TODO What about TLSMasqueradeAddress? */

    /* Handle MasqueradeAddress. */
    c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress", FALSE);
    if (c != NULL) {
      addr = c->argv[0];
    }
  }

  addr_str = pstrdup(p, pr_netaddr_get_ipstr(addr));

  /* Fixup the address string for use in PORT commands/PASV responses. */
  ptr = strrchr(addr_str, ':');
  if (ptr != NULL) {
    addr_str = ptr + 1;
  }

  for (ptr = addr_str; *ptr; ptr++) {
    if (*ptr == '.') {
      *ptr = ',';
    }
  }

  /* Allocate enough room for 6 numbers (3 digits max each), 5 separators,
   * and a trailing NUL.
   */
  msglen = (6 * 3) + (5 * 1) + 1;

  msg = pcalloc(p, msglen);
  snprintf(msg, msglen-1, "%s,%u,%u", addr_str, (port >> 8) & 255, port & 255);

  return msg;
}
コード例 #8
0
ファイル: netaddr.c プロジェクト: netdna/proftpd
END_TEST

START_TEST (netaddr_v6tov4_test) {
  pr_netaddr_t *addr, *addr2;
  const char *name, *ipstr;

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

  addr = pr_netaddr_v6tov4(p, NULL);
  fail_unless(addr == NULL, "Failed to handle null address");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

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

  addr = pr_netaddr_v6tov4(p, addr2);
  fail_unless(addr == NULL, "Converted '%s' to IPv4 address unexpectedly",
    name);
  fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
    strerror(errno), errno);

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

  addr = pr_netaddr_v6tov4(p, addr2);
  fail_unless(addr != NULL, "Failed to convert '%s' to IPv4 addres: %s",
    name, strerror(errno));
  fail_unless(pr_netaddr_get_family(addr) == AF_INET,
    "Expected %d, got %d", AF_INET, pr_netaddr_get_family(addr));

  ipstr = pr_netaddr_get_ipstr(addr);
  fail_unless(strcmp(ipstr, "127.0.0.1") == 0,
    "Expected '127.0.0.1', got '%s'", ipstr);
}
コード例 #9
0
ファイル: conn.c プロジェクト: lazy404/proftpd-mod_proxy
int proxy_conn_connect_timeout_cb(CALLBACK_FRAME) {
  struct proxy_session *proxy_sess;
  pr_netaddr_t *server_addr;

  proxy_sess = pr_table_get(session.notes, "mod_proxy.proxy-session", NULL);
  server_addr = pr_table_get(session.notes, "mod_proxy.proxy-connect-address",
    NULL);

  (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION,
    "timed out connecting to %s:%d after %d %s",
    pr_netaddr_get_ipstr(server_addr), ntohs(pr_netaddr_get_port(server_addr)),
    proxy_sess->connect_timeout,
    proxy_sess->connect_timeout != 1 ? "seconds" : "second");

  pr_event_generate("mod_proxy.timeout-connect", NULL);

  pr_log_pri(PR_LOG_NOTICE, "%s", "Connect timed out, disconnected");
  pr_session_disconnect(&proxy_module, PR_SESS_DISCONNECT_TIMEOUT,
    "ProxyTimeoutConnect");

  /* Do not restart the timer (should never be reached). */
  return 0;
}
コード例 #10
0
ファイル: trace.c プロジェクト: dbarba74/proftpd
static int trace_write(const char *channel, int level, const char *msg,
    int discard) {
  char buf[PR_TUNABLE_BUFFER_SIZE];
  size_t buflen, len;
  struct tm *tm;
  int use_conn_ips = FALSE;

  if (trace_logfd < 0)
    return 0;

  memset(buf, '\0', sizeof(buf));

  if (!(trace_opts & PR_TRACE_OPT_USE_TIMESTAMP_MILLIS)) {
    time_t now;

    now = time(NULL);
    tm = pr_localtime(NULL, &now);

    len = strftime(buf, sizeof(buf)-1, "%Y-%m-%d %H:%M:%S", tm);
    buflen = len;

  } else {
    struct timeval now;
    unsigned long millis;

    gettimeofday(&now, NULL);

    tm = pr_localtime(NULL, (const time_t *) &(now.tv_sec));

    len = strftime(buf, sizeof(buf)-1, "%Y-%m-%d %H:%M:%S", tm);
    buflen = len;

    /* Convert microsecs to millisecs. */
    millis = now.tv_usec / 1000;

    len = snprintf(buf + buflen, sizeof(buf) - buflen, ",%03lu", millis);
    buflen += len;
  }

  if ((trace_opts & PR_TRACE_OPT_LOG_CONN_IPS) &&
      session.c != NULL) {
    /* We can only support the "+ConnIPs" TraceOption if there actually
     * is a client connected in this process.  We might be the daemon
     * process, in which there is no client.
     */
    use_conn_ips = TRUE;
  }

  if (use_conn_ips == FALSE) {
    len = snprintf(buf + buflen, sizeof(buf) - buflen, " [%u] <%s:%d>: %s",
      (unsigned int) (session.pid ? session.pid : getpid()), channel, level,
      msg);
    buflen += len;

  } else {
    const char *client_ip, *server_ip;
    int server_port;

    client_ip = pr_netaddr_get_ipstr(session.c->remote_addr);
    server_ip = pr_netaddr_get_ipstr(session.c->local_addr);
    server_port = pr_netaddr_get_port(session.c->local_addr);

    len = snprintf(buf + buflen, sizeof(buf) - buflen,
      " [%u] (client %s, server %s:%d) <%s:%d>: %s",
      (unsigned int) (session.pid ? session.pid : getpid()),
      client_ip != NULL ? client_ip : "none",
      server_ip != NULL ? server_ip : "none", server_port, channel, level, msg);
    buflen += len;
  }

  buf[sizeof(buf)-1] = '\0';

  if (buflen < (sizeof(buf) - 1)) {
    buf[buflen] = '\n';
    buflen++;

  } else {
    buf[sizeof(buf)-2] = '\n';
  }

  pr_log_event_generate(PR_LOG_TYPE_TRACELOG, trace_logfd, level, buf, buflen);

  if (discard) {
    /* This log message would not have been written to disk, so just discard
     * it.  The discard value is TRUE when there's a log listener for
     * TraceLog logging events, and the Trace log level configuration would
     * otherwise have filtered out this log message.
     */
    return 0;
  }

  return write(trace_logfd, buf, buflen);
}
コード例 #11
0
ファイル: log.c プロジェクト: SangramSahuFIS/proftpd
static void log_write(int priority, int f, char *s, int discard) {
  unsigned int max_priority = 0, *ptr = NULL;
  char serverinfo[PR_TUNABLE_BUFFER_SIZE] = {'\0'};

  memset(serverinfo, '\0', sizeof(serverinfo));

  if (main_server &&
      main_server->ServerFQDN) {
    pr_netaddr_t *remote_addr = pr_netaddr_get_sess_remote_addr();
    const char *remote_name = pr_netaddr_get_sess_remote_name();

    snprintf(serverinfo, sizeof(serverinfo)-1, "%s", main_server->ServerFQDN);
    serverinfo[sizeof(serverinfo)-1] = '\0';

    if (remote_addr && remote_name) {
      size_t serverinfo_len;

      serverinfo_len = strlen(serverinfo);

      snprintf(serverinfo + serverinfo_len,
        sizeof(serverinfo) - serverinfo_len, " (%s[%s])",
        remote_name, pr_netaddr_get_ipstr(remote_addr));

      serverinfo[sizeof(serverinfo)-1] = '\0';
    }
  }

  if (!discard &&
      (logstderr || !main_server)) {
    char buf[LOGBUFFER_SIZE] = {'\0'};
    size_t buflen, len;
    struct timeval now;
    struct tm *tm = NULL;
    unsigned long millis;

    gettimeofday(&now, NULL);
    tm = pr_localtime(NULL, (const time_t *) &(now.tv_sec));
    if (tm == NULL) {
      return;
    }

    len = strftime(buf, sizeof(buf)-1, "%Y-%m-%d %H:%M:%S", tm);
    buflen = len;
    buf[sizeof(buf)-1] = '\0';

    /* Convert microsecs to millisecs. */
    millis = now.tv_usec / 1000;

    len = snprintf(buf + buflen, sizeof(buf) - len, ",%03lu ", millis);
    buflen += len;
    buf[sizeof(buf)-1] = '\0';

    if (*serverinfo) {
      len = snprintf(buf + buflen, sizeof(buf) - buflen,
        "%s proftpd[%u] %s: %s\n", systemlog_host,
        (unsigned int) (session.pid ? session.pid : getpid()), serverinfo, s);

    } else {
      len = snprintf(buf + buflen, sizeof(buf) - buflen,
        "%s proftpd[%u]: %s\n", systemlog_host,
        (unsigned int) (session.pid ? session.pid : getpid()), s);
    }

    buflen += len;
    buf[sizeof(buf)-1] = '\0';

    pr_log_event_generate(PR_LOG_TYPE_SYSTEMLOG, STDERR_FILENO, priority,
      buf, buflen);

    fprintf(stderr, "%s", buf);
    return;
  }

  if (syslog_discard) {
    /* Only return now if we don't have any log listeners. */
    if (pr_log_event_listening(PR_LOG_TYPE_SYSLOG) <= 0 &&
        pr_log_event_listening(PR_LOG_TYPE_SYSTEMLOG) <= 0) {
      return;
    }
  }

  ptr = get_param_ptr(main_server->conf, "SyslogLevel", FALSE);
  if (ptr != NULL) {
    max_priority = *ptr;

  } else {
    /* Default SyslogLevel */
    max_priority = default_level;
  }

  if (priority > max_priority) {
    /* Only return now if we don't have any log listeners. */
    if (pr_log_event_listening(PR_LOG_TYPE_SYSLOG) <= 0 &&
        pr_log_event_listening(PR_LOG_TYPE_SYSTEMLOG) <= 0) {
      return;
    }
  }

  if (systemlog_fd != -1) {
    char buf[LOGBUFFER_SIZE] = {'\0'};
    size_t buflen, len;
    struct timeval now;
    struct tm *tm;
    unsigned long millis;

    gettimeofday(&now, NULL);
    tm = pr_localtime(NULL, (const time_t *) &(now.tv_sec));
    if (tm == NULL) {
      return;
    }

    len = strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
    buflen = len;
    buf[sizeof(buf) - 1] = '\0';

    /* Convert microsecs to millisecs. */
    millis = now.tv_usec / 1000;

    len = snprintf(buf + buflen, sizeof(buf) - len, ",%03lu ", millis);
    buflen += len;
    buf[sizeof(buf) - 1] = '\0';

    if (*serverinfo) {
      len = snprintf(buf + buflen, sizeof(buf) - buflen,
        "%s proftpd[%u] %s: %s\n", systemlog_host,
        (unsigned int) (session.pid ? session.pid : getpid()), serverinfo, s);

    } else {
      len = snprintf(buf + buflen, sizeof(buf) - buflen,
        "%s proftpd[%u]: %s\n", systemlog_host,
        (unsigned int) (session.pid ? session.pid : getpid()), s);
    }

    buflen += len;
    buf[sizeof(buf)-1] = '\0';

    pr_log_event_generate(PR_LOG_TYPE_SYSTEMLOG, systemlog_fd, priority,
      buf, buflen);

    /* Now we need to enforce the discard, syslog_discard and SyslogLevel
     * filtering.
     */
    if (discard) {
      return;
    }

    if (syslog_discard) {
      return;
    }

    if (priority > max_priority) {
      return;
    }

    while (write(systemlog_fd, buf, buflen) < 0) {
      if (errno == EINTR) {
        pr_signals_handle();
        continue;
      }

      return;
    }

    return;
  }

  pr_log_event_generate(PR_LOG_TYPE_SYSLOG, syslog_sockfd, priority, s,
    strlen(s));

  if (set_facility != -1)
    f = set_facility;

  if (!syslog_open) {
    syslog_sockfd = pr_openlog("proftpd", LOG_NDELAY|LOG_PID, f);
    if (syslog_sockfd < 0) {
      (void) pr_trace_msg(trace_channel, 1,
        "error opening syslog fd: %s", strerror(errno));
      return;
    }

    syslog_open = TRUE;

  } else if (f != facility) {
    /* If this message is to be sent to a different log facility than a
     * default one (or the facility configured via SyslogFacility), then
     * OR in the facility with the priority value, as per the syslog(3)
     * docs.
     */
    priority |= f;
  }

  if (*serverinfo) {
    pr_syslog(syslog_sockfd, priority, "%s - %s\n", serverinfo, s);

  } else {
    pr_syslog(syslog_sockfd, priority, "%s\n", s);
  }
}
コード例 #12
0
ファイル: main.c プロジェクト: noirey/proftpd-mod_proxy
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;
}
コード例 #13
0
ファイル: auth-password.c プロジェクト: bverschueren/proftpd
int sftp_auth_password(struct ssh2_packet *pkt, cmd_rec *pass_cmd,
                       const char *orig_user, const char *user, const char *service,
                       unsigned char **buf, uint32_t *buflen, int *send_userauth_fail) {
    const char *cipher_algo, *mac_algo;
    char *passwd;
    int have_new_passwd, res;
    struct passwd *pw;

    cipher_algo = sftp_cipher_get_read_algo();
    mac_algo = sftp_mac_get_read_algo();

    if (strncmp(cipher_algo, "none", 5) == 0 ||
            strncmp(mac_algo, "none", 5) == 0) {

        if (sftp_opts & SFTP_OPT_ALLOW_INSECURE_LOGIN) {
            (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
                                    "WARNING: cipher algorithm '%s' or MAC algorithm '%s' INSECURE for "
                                    "password authentication (SFTPOption AllowInsecureLogin in effect)",
                                    cipher_algo, mac_algo);

        } else {
            (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
                                    "cipher algorithm '%s' or MAC algorithm '%s' unacceptable for "
                                    "password authentication, denying password authentication request",
                                    cipher_algo, mac_algo);
            *send_userauth_fail = TRUE;
            errno = EPERM;
            return 0;
        }
    }

    /* XXX We currently don't do anything with this. */
    have_new_passwd = sftp_msg_read_bool(pkt->pool, buf, buflen);
    if (have_new_passwd) {
        (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, "%s",
                                "client says they have provided a new password; this functionality "
                                "is not currently supported");
    }

    passwd = sftp_msg_read_string(pkt->pool, buf, buflen);
    passwd = sftp_utf8_decode_str(pkt->pool, passwd);

    pass_cmd->arg = passwd;

    if (pr_cmd_dispatch_phase(pass_cmd, PRE_CMD, 0) < 0) {
        (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
                                "authentication request for user '%s' blocked by '%s' handler",
                                orig_user, (char *) pass_cmd->argv[0]);

        pr_cmd_dispatch_phase(pass_cmd, POST_CMD_ERR, 0);
        pr_cmd_dispatch_phase(pass_cmd, LOG_CMD_ERR, 0);

        pr_memscrub(passwd, strlen(passwd));

        *send_userauth_fail = TRUE;
        errno = EPERM;
        return 0;
    }

    pw = pr_auth_getpwnam(pkt->pool, user);
    if (pw == NULL) {
        (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
                                "no account for user '%s' found", user);

        pr_log_auth(PR_LOG_NOTICE,
                    "USER %s: no such user found from %s [%s] to %s:%d", user,
                    session.c->remote_name, pr_netaddr_get_ipstr(session.c->remote_addr),
                    pr_netaddr_get_ipstr(session.c->local_addr), session.c->local_port);

        pr_memscrub(passwd, strlen(passwd));

        *send_userauth_fail = TRUE;
        errno = ENOENT;
        return 0;
    }

    res = pr_auth_authenticate(pkt->pool, user, passwd);
    pr_memscrub(passwd, strlen(passwd));

    switch (res) {
    case PR_AUTH_OK:
        break;

    case PR_AUTH_NOPWD:
        (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
                                "password authentication for user '%s' failed: No such user", user);
        pr_log_auth(PR_LOG_NOTICE, "USER %s (Login failed): No such user found",
                    user);
        *send_userauth_fail = TRUE;
        errno = ENOENT;
        return 0;

    case PR_AUTH_BADPWD:
        (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
                                "password authentication for user '%s' failed: Incorrect password",
                                user);
        pr_log_auth(PR_LOG_NOTICE, "USER %s (Login failed): Incorrect password",
                    user);
        *send_userauth_fail = TRUE;
        errno = EINVAL;
        return 0;

    case PR_AUTH_AGEPWD:
        (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
                                "password authentication for user '%s' failed: Password expired",
                                user);
        pr_log_auth(PR_LOG_NOTICE, "USER %s (Login failed): Password expired",
                    user);
        *send_userauth_fail = TRUE;
        errno = EINVAL;
        return 0;

    case PR_AUTH_DISABLEDPWD:
        (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
                                "password authentication for user '%s' failed: Account disabled",
                                user);
        pr_log_auth(PR_LOG_NOTICE, "USER %s (Login failed): Account disabled",
                    user);
        *send_userauth_fail = TRUE;
        errno = EINVAL;
        return 0;

    default:
        (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
                                "unknown authentication value (%d), returning error", res);
        *send_userauth_fail = TRUE;
        errno = EINVAL;
        return 0;
    }

    return 1;
}
コード例 #14
0
ファイル: bindings.c プロジェクト: dbarba74/proftpd
conn_t *pr_ipbind_get_listening_conn(server_rec *server, pr_netaddr_t *addr,
    unsigned int port) {
  conn_t *l;
  pool *p;
  struct listener_rec *lr;

  if (listening_conn_list) {
    for (lr = (struct listener_rec *) listening_conn_list->xas_list; lr;
        lr = lr->next) {
      int use_elt = FALSE;

      pr_signals_handle();

      if (addr != NULL &&
          lr->addr != NULL) {
        const char *lr_ipstr = NULL;

        lr_ipstr = pr_netaddr_get_ipstr(lr->addr);

        /* Note: lr_ipstr should never be null.  If it is, it means that
         * the lr->addr object never had its IP address resolved/stashed,
         * and in attempting to do, getnameinfo(3) failed for some reason.
         *
         * The IP address on which it's listening, if not available via
         * lr->addr, should thus be available via lr->conn->local_addr.
         */

        if (lr_ipstr == NULL &&
            lr->conn != NULL) {
          lr_ipstr = pr_netaddr_get_ipstr(lr->conn->local_addr);
        }

        if (lr_ipstr != NULL) {
          if (strcmp(pr_netaddr_get_ipstr(addr), lr_ipstr) == 0 &&
              port == lr->port) {
            use_elt = TRUE;
          }
        }

      } else if (addr == NULL &&
                 port == lr->port) {
        use_elt = TRUE;
      }

      if (use_elt) { 
        lr->claimed = TRUE;
        return lr->conn;
      }
    }
  }

  if (listening_conn_pool == NULL) {
    listening_conn_pool = make_sub_pool(permanent_pool);
    pr_pool_tag(listening_conn_pool, "Listening Connection Pool");

    listening_conn_list = xaset_create(listening_conn_pool, NULL);
  }

  p = make_sub_pool(listening_conn_pool); 
  pr_pool_tag(p, "Listening conn subpool");

  l = pr_inet_create_conn(p, -1, addr, port, FALSE);
  if (l == NULL) {
    return NULL;
  }

  /* Inform any interested listeners that this socket was opened. */
  pr_inet_generate_socket_event("core.ctrl-listen", server, l->local_addr,
    l->listen_fd);

  lr = pcalloc(p, sizeof(struct listener_rec));
  lr->pool = p;
  lr->conn = l;
  lr->addr = pr_netaddr_dup(p, addr);
  if (lr->addr == NULL &&
      errno != EINVAL) {
    return NULL;
  }
  lr->port = port;
  lr->claimed = TRUE;

  xaset_insert(listening_conn_list, (xasetmember_t *) lr);
  return l;
}
コード例 #15
0
ファイル: log.c プロジェクト: melbcat/InMemoryFuzzing
static void log_write(int priority, int f, char *s) {
  unsigned int *max_priority = NULL;
  char serverinfo[PR_TUNABLE_BUFFER_SIZE] = {'\0'};

  memset(serverinfo, '\0', sizeof(serverinfo));

  if (main_server &&
      main_server->ServerFQDN) {
    pr_netaddr_t *remote_addr = pr_netaddr_get_sess_remote_addr();
    const char *remote_name = pr_netaddr_get_sess_remote_name();

    snprintf(serverinfo, sizeof(serverinfo), "%s", main_server->ServerFQDN);
    serverinfo[sizeof(serverinfo)-1] = '\0';

    if (remote_addr && remote_name) {
      snprintf(serverinfo + strlen(serverinfo),
        sizeof(serverinfo) - strlen(serverinfo), " (%s[%s])",
        remote_name, pr_netaddr_get_ipstr(remote_addr));

      serverinfo[sizeof(serverinfo)-1] = '\0';
    }
  }

  if (logstderr ||
      !main_server) {
    fprintf(stderr, "%s - %s\n", serverinfo, s);
    return;
  }

  if (syslog_discard)
    return;

  if (systemlog_fd != -1) {
    char buf[LOGBUFFER_SIZE] = {'\0'};
    time_t tt = time(NULL);
    struct tm *t;

    t = localtime(&tt);
    strftime(buf, sizeof(buf), "%b %d %H:%M:%S ", t);
    buf[sizeof(buf) - 1] = '\0';

    if (*serverinfo) {
      snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
	       "%s proftpd[%u] %s: %s\n", systemlog_host,
	       (unsigned int) getpid(), serverinfo, s);
    } else {
      snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
	       "%s proftpd[%u]: %s\n", systemlog_host,
	       (unsigned int) getpid(), s);
    }

    buf[sizeof(buf) - 1] = '\0';
    write(systemlog_fd, buf, strlen(buf));
    return;
  }

  if (set_facility != -1)
    f = set_facility;

  if (!syslog_open) {
    syslog_sockfd = pr_openlog("proftpd", LOG_NDELAY|LOG_PID, f);

  } else if (f != facility) {
    (void) pr_setlogfacility(f);
  }

  max_priority = get_param_ptr(main_server->conf, "SyslogLevel", FALSE);
  if (max_priority != NULL &&
      priority > *max_priority)
    return;

  if (*serverinfo)
    pr_syslog(syslog_sockfd, priority, "%s - %s\n", serverinfo, s);
  else
    pr_syslog(syslog_sockfd, priority, "%s\n", s);

  if (!syslog_open) {
    pr_closelog(syslog_sockfd);
    syslog_sockfd = -1;

  } else if (f != facility) {
    (void) pr_setlogfacility(f);
  }
}
コード例 #16
0
ファイル: netaddr.c プロジェクト: WiseMan787/ralink_sdk
int pr_netaddr_ncmp(const pr_netaddr_t *na1, const pr_netaddr_t *na2,
    unsigned int bitlen) {
  pool *tmp_pool = NULL;
  pr_netaddr_t *a, *b;
  unsigned int nbytes, nbits;
  const unsigned char *in1, *in2;

  if (na1 && !na2)
    return 1;

  if (!na1 && na2)
    return -1;

  if (!na1 && !na2)
    return 0;

  if (pr_netaddr_get_family(na1) != pr_netaddr_get_family(na2)) {

    /* Cannot compare addresses from different families, unless one
     * of the netaddrs has an AF_INET family, and the other has an
     * AF_INET6 family AND is an IPv4-mapped IPv6 address.
     */

    if (pr_netaddr_is_v4mappedv6(na1) != TRUE &&
        pr_netaddr_is_v4mappedv6(na2) != TRUE) {
      errno = EINVAL;
      return -1;
    }

    if (pr_netaddr_is_v4mappedv6(na1) == TRUE) {
      tmp_pool = make_sub_pool(permanent_pool);

      /* This case means that na1 is an IPv4-mapped IPv6 address, and
       * na2 is an IPv4 address.
       */
      a = pr_netaddr_alloc(tmp_pool);
      pr_netaddr_set_family(a, AF_INET);
      pr_netaddr_set_port(a, pr_netaddr_get_port(na1));
      memcpy(&a->na_addr.v4.sin_addr, get_v4inaddr(na1),
        sizeof(struct in_addr));

      b = (pr_netaddr_t *) na2;

      pr_trace_msg(trace_channel, 6, "comparing IPv4 address '%s' against "
        "IPv4-mapped IPv6 address '%s'", pr_netaddr_get_ipstr(b),
        pr_netaddr_get_ipstr(a));

    } else if (pr_netaddr_is_v4mappedv6(na2) == TRUE) {
      tmp_pool = make_sub_pool(permanent_pool);

      /* This case means that na is an IPv4 address, and na2 is an
       * IPv4-mapped IPv6 address.
       */
      a = (pr_netaddr_t *) na1;

      b = pr_netaddr_alloc(tmp_pool);
      pr_netaddr_set_family(b, AF_INET);
      pr_netaddr_set_port(b, pr_netaddr_get_port(na2));
      memcpy(&b->na_addr.v4.sin_addr, get_v4inaddr(na2),
        sizeof(struct in_addr));

      pr_trace_msg(trace_channel, 6, "comparing IPv4 address '%s' against "
        "IPv4-mapped IPv6 address '%s'", pr_netaddr_get_ipstr(a),
        pr_netaddr_get_ipstr(b));

    } else {
      a = (pr_netaddr_t *) na1;
      b = (pr_netaddr_t *) na2;
    }

  } else {
    a = (pr_netaddr_t *) na1;
    b = (pr_netaddr_t *) na2;
  }

  switch (pr_netaddr_get_family(a)) {
    case AF_INET: {
      /* Make sure that the given number of bits is not more than supported
       * for IPv4 addresses (32).
       */
      if (bitlen > 32) {
        errno = EINVAL;
        return -1;
      }

      break;
    }

#ifdef PR_USE_IPV6
    case AF_INET6: {
      if (use_ipv6) {
        /* Make sure that the given number of bits is not more than supported
         * for IPv6 addresses (128).
         */
        if (bitlen > 128) {
          errno = EINVAL;
          return -1;
        }

        break;
      }
    }
#endif /* PR_USE_IPV6 */

    default:
      errno = EPERM;
      return -1;
  }

  /* Retrieve pointers to the contained in_addrs. */
  in1 = (const unsigned char *) pr_netaddr_get_inaddr(a);
  in2 = (const unsigned char *) pr_netaddr_get_inaddr(b);

  /* Determine the number of bytes, and leftover bits, in the given
   * bit length.
   */
  nbytes = bitlen / 8;
  nbits = bitlen % 8;

  /* Compare bytes, using memcmp(3), first. */
  if (nbytes > 0) {
    int res = memcmp(in1, in2, nbytes);

    /* No need to continue comparing the addresses if they differ already. */
    if (res != 0) {
      if (tmp_pool)
        destroy_pool(tmp_pool);

      return res;
    }
  }

  /* Next, compare the remaining bits in the addresses. */
  if (nbits > 0) {
    unsigned char mask;

    /* Get the bytes in the addresses that have not yet been compared. */
    unsigned char in1byte = in1[nbytes];
    unsigned char in2byte = in2[nbytes];

    /* Build up a mask covering the bits left to be checked. */
    mask = (0xff << (8 - nbits)) & 0xff;

    if ((in1byte & mask) > (in2byte & mask)) {
      if (tmp_pool)
        destroy_pool(tmp_pool);

      return 1;
    }

    if ((in1byte & mask) < (in2byte & mask)) {
      if (tmp_pool)
        destroy_pool(tmp_pool);

      return -1;
    }
  }

  if (tmp_pool)
    destroy_pool(tmp_pool);

  /* If we've made it this far, the addresses match, for the given bit
   * length.
   */
  return 0;
}
コード例 #17
0
ファイル: bindings.c プロジェクト: dbarba74/proftpd
static int init_standalone_bindings(void) {
  int res = 0;
  server_rec *serv = NULL;
  unsigned char *default_server = NULL, is_default = FALSE;

  /* If a port is set to zero, the address/port is not bound to a socket
   * at all.
   */
  if (main_server->ServerPort) {

    /* If SocketBindTight is off, then pr_inet_create_conn() will
     * create and bind to a wildcard socket.  However, should it be an
     * IPv4 or an IPv6 wildcard socket?
     */
    if (!SocketBindTight) {
#ifdef PR_USE_IPV6
      if (pr_netaddr_use_ipv6()) {
        pr_inet_set_default_family(NULL, AF_INET6);

      } else {
        int default_family;

        default_family = pr_netaddr_get_family(main_server->addr);
        pr_inet_set_default_family(NULL, default_family);
      }
#else
      pr_inet_set_default_family(NULL,
        pr_netaddr_get_family(main_server->addr));
#endif /* PR_USE_IPV6 */
    }

    main_server->listen = pr_ipbind_get_listening_conn(main_server,
      (SocketBindTight ? main_server->addr : NULL), main_server->ServerPort);
    if (main_server->listen == NULL) {
      return -1;
    }

  } else {
    main_server->listen = NULL;
  }

  default_server = get_param_ptr(main_server->conf, "DefaultServer", FALSE);
  if (default_server != NULL &&
      *default_server == TRUE) {
    is_default = TRUE;
  }

  if (main_server->ServerPort ||
      is_default) {
    PR_CREATE_IPBIND(main_server, main_server->addr, main_server->ServerPort);
    PR_OPEN_IPBIND(main_server->addr, main_server->ServerPort,
      main_server->listen, is_default, TRUE, TRUE);
    PR_ADD_IPBINDS(main_server);
  }

  for (serv = main_server->next; serv; serv = serv->next) {
    config_rec *c;
    int is_namebind = FALSE;

    /* See if this server is a namebind, to be part of an existing ipbind. */
    c = find_config(serv->conf, CONF_PARAM, "ServerAlias", FALSE);
    while (c != NULL) {
      pr_signals_handle();

      res = pr_namebind_create(serv, c->argv[0], serv->addr, serv->ServerPort);
      if (res == 0) {
        is_namebind = TRUE;

        res = pr_namebind_open(c->argv[0], serv->addr, serv->ServerPort);
        if (res < 0) {
          pr_log_pri(PR_LOG_NOTICE,
            "%s:%d: notice: unable to open namebind '%s': %s", __FILE__,
            __LINE__, (char *) c->argv[0], strerror(errno));
        }

      } else {
        pr_log_pri(PR_LOG_NOTICE,
          "unable to create namebind for '%s' to %s#%u: %s",
          (char *) c->argv[0], pr_netaddr_get_ipstr(serv->addr),
          serv->ServerPort, strerror(errno));
      }

      c = find_config_next(c, c->next, CONF_PARAM, "ServerAlias", FALSE);
    }

    if (is_namebind == TRUE) {
      continue;
    }

    if (serv->ServerPort != main_server->ServerPort ||
        SocketBindTight ||
        !main_server->listen) {
      is_default = FALSE;

      default_server = get_param_ptr(serv->conf, "DefaultServer", FALSE);
      if (default_server != NULL &&
          *default_server == TRUE) {
        is_default = TRUE;
      }

      if (serv->ServerPort) {
        if (!SocketBindTight) {
#ifdef PR_USE_IPV6
          if (pr_netaddr_use_ipv6()) {
            pr_inet_set_default_family(NULL, AF_INET6);

          } else {
            pr_inet_set_default_family(NULL, pr_netaddr_get_family(serv->addr));
          }
#else
          pr_inet_set_default_family(NULL, pr_netaddr_get_family(serv->addr));
#endif /* PR_USE_IPV6 */
        }

        serv->listen = pr_ipbind_get_listening_conn(serv,
          (SocketBindTight ? serv->addr : NULL), serv->ServerPort);
        if (serv->listen == NULL) {
          return -1;
        }

        PR_CREATE_IPBIND(serv, serv->addr, serv->ServerPort);
        PR_OPEN_IPBIND(serv->addr, serv->ServerPort, serv->listen, is_default,
          FALSE, TRUE);
        PR_ADD_IPBINDS(serv);

      } else if (is_default) {
        serv->listen = NULL;

        PR_CREATE_IPBIND(serv, serv->addr, serv->ServerPort);
        PR_OPEN_IPBIND(serv->addr, serv->ServerPort, serv->listen, is_default,
          FALSE, TRUE);
        PR_ADD_IPBINDS(serv);

      } else {
        serv->listen = NULL;
      }

    } else {
      /* Because this server is sharing the connection with the main server,
       * we need a cleanup handler to remove the server's reference when the
       * original connection's pool is destroyed.
       */

      is_default = FALSE;
      default_server = get_param_ptr(serv->conf, "DefaultServer", FALSE);
      if (default_server != NULL &&
          *default_server == TRUE) {
        is_default = TRUE;
      }

      serv->listen = main_server->listen;
      register_cleanup(serv->listen->pool, &serv->listen, server_cleanup_cb,
        server_cleanup_cb);

      PR_CREATE_IPBIND(serv, serv->addr, serv->ServerPort);
      PR_OPEN_IPBIND(serv->addr, serv->ServerPort, NULL, is_default, FALSE,
        TRUE);
      PR_ADD_IPBINDS(serv);
    }
  }

  /* Any "unclaimed" listening conns can be removed and closed. */
  if (listening_conn_list) {
    struct listener_rec *lr, *lrn;

    for (lr = (struct listener_rec *) listening_conn_list->xas_list; lr; lr = lrn) {
      lrn = lr->next;

      if (!lr->claimed) {
        xaset_remove(listening_conn_list, (xasetmember_t *) lr);
        destroy_pool(lr->pool);
      }
    }
  }

  return 0;
}
コード例 #18
0
ファイル: bindings.c プロジェクト: dbarba74/proftpd
int pr_ipbind_listen(fd_set *readfds) {
  int listen_flags = PR_INET_LISTEN_FL_FATAL_ON_ERROR, maxfd = 0;
  register unsigned int i = 0;

  /* sanity check */
  if (!readfds)
    return -1;

  FD_ZERO(readfds);

  if (!binding_pool) {
    binding_pool = make_sub_pool(permanent_pool);
    pr_pool_tag(binding_pool, "Bindings Pool");
  }

  /* Reset the listener list. */
  if (!listener_list) {
    listener_list = make_array(binding_pool, 1, sizeof(conn_t *));

  } else {
    /* Nasty hack to "clear" the list by making it think it has no
     * elements.
     */
    listener_list->nelts = 0;
  }

  /* Slower than the hash lookup, but...we have to check each and every
   * ipbind in the table.
   */
  for (i = 0; i < PR_BINDINGS_TABLE_SIZE; i++) {
    pr_ipbind_t *ipbind = NULL;

    for (ipbind = ipbind_table[i]; ipbind; ipbind = ipbind->ib_next) {

      /* Skip inactive bindings, but only if SocketBindTight is in effect. */
      if (SocketBindTight &&
          !ipbind->ib_isactive)
        continue;

      if (ipbind->ib_listener) {

        if (ipbind->ib_listener->mode == CM_NONE) {
          pr_inet_listen(ipbind->ib_listener->pool, ipbind->ib_listener,
            tcpBackLog, listen_flags);
        }

        if (ipbind->ib_listener->mode == CM_ACCEPT) {
          if (pr_inet_resetlisten(ipbind->ib_listener->pool,
              ipbind->ib_listener) < 0) {
            pr_trace_msg(trace_channel, 3,
              "error resetting %s#%u for listening: %s",
              pr_netaddr_get_ipstr(ipbind->ib_addr), ipbind->ib_port,
              strerror(errno));
          }
        }

        if (ipbind->ib_listener->mode == CM_LISTEN) {
          FD_SET(ipbind->ib_listener->listen_fd, readfds);
          if (ipbind->ib_listener->listen_fd > maxfd)
            maxfd = ipbind->ib_listener->listen_fd;

          /* Add this to the listener list as well. */
          *((conn_t **) push_array(listener_list)) = ipbind->ib_listener;
        }
      }
    }
  }

  return maxfd;
}
コード例 #19
0
ファイル: bindings.c プロジェクト: dbarba74/proftpd
server_rec *pr_ipbind_get_server(pr_netaddr_t *addr, unsigned int port) {
  pr_ipbind_t *ipbind = NULL;
  pr_netaddr_t wildcard_addr;
  int addr_family;

  /* If we've got a binding configured for this exact address, return it
   * straightaway.
   */
  ipbind = pr_ipbind_find(addr, port, TRUE);
  if (ipbind != NULL)
    return ipbind->ib_server;

  /* Look for a vhost bound to the wildcard address (i.e. INADDR_ANY).
   *
   * This allows for "<VirtualHost 0.0.0.0>" configurations, where the
   * IP address to which the client might connect is not known at
   * configuration time.  (Usually happens when the same config file
   * is deployed to multiple machines.)
   */

  addr_family = pr_netaddr_get_family(addr);

  pr_netaddr_clear(&wildcard_addr);
  pr_netaddr_set_family(&wildcard_addr, addr_family);
  pr_netaddr_set_sockaddr_any(&wildcard_addr);

  ipbind = pr_ipbind_find(&wildcard_addr, port, TRUE);
  if (ipbind != NULL) {
    pr_log_debug(DEBUG7, "no matching vhost found for %s#%u, using "
      "'%s' listening on wildcard address", pr_netaddr_get_ipstr(addr), port,
      ipbind->ib_server->ServerName);
    return ipbind->ib_server;

  } else {
#ifdef PR_USE_IPV6
    if (addr_family == AF_INET6 &&
        pr_netaddr_use_ipv6()) {

      /* The pr_ipbind_find() probably returned NULL because there aren't
       * any <VirtualHost> sections configured explicitly for the wildcard
       * IPv6 address of "::", just the IPv4 wildcard "0.0.0.0" address.
       *
       * So try the pr_ipbind_find() again, this time using the IPv4 wildcard.
       */
      pr_netaddr_clear(&wildcard_addr);
      pr_netaddr_set_family(&wildcard_addr, AF_INET);
      pr_netaddr_set_sockaddr_any(&wildcard_addr);

      ipbind = pr_ipbind_find(&wildcard_addr, port, TRUE);
      if (ipbind != NULL) {
        pr_log_debug(DEBUG7, "no matching vhost found for %s#%u, using "
          "'%s' listening on wildcard address", pr_netaddr_get_ipstr(addr),
          port, ipbind->ib_server->ServerName);
        return ipbind->ib_server;
      }
    }
#endif /* PR_USE_IPV6 */
  }

  /* Use the default server, if set. */
  if (ipbind_default_server &&
      ipbind_default_server->ib_isactive) {
    pr_log_debug(DEBUG7, "no matching vhost found for %s#%u, using "
      "DefaultServer '%s'", pr_netaddr_get_ipstr(addr), port,
      ipbind_default_server->ib_server->ServerName);
    return ipbind_default_server->ib_server;
  }

  /* Not found in binding list, and no DefaultServer, so see if it's the
   * loopback address
   */
  if (ipbind_localhost_server &&
      pr_netaddr_is_loopback(addr)) {
    return ipbind_localhost_server->ib_server;
  }

  return NULL;
}
コード例 #20
0
ファイル: netaddr.c プロジェクト: WiseMan787/ralink_sdk
/* This differs from pr_netaddr_get_ipstr() in that pr_netaddr_get_ipstr()
 * returns a string of the numeric form of the given network address, whereas
 * this function returns a string of the DNS name (if present).
 */
const char *pr_netaddr_get_dnsstr(pr_netaddr_t *na) {
  char *name = NULL;
  char buf[256];

  if (!na) {
    errno = EINVAL;
    return NULL;
  }

  /* If this pr_netaddr_t has already been resolved to an DNS string, return the
   * cached string.
   */
  if (na->na_have_dnsstr)
    return na->na_dnsstr;

  if (reverse_dns) {
    int res = 0;

    pr_trace_msg(trace_channel, 3,
      "verifying DNS name for IP address %s via reverse DNS lookup",
      pr_netaddr_get_ipstr(na));

    memset(buf, '\0', sizeof(buf));
    res = pr_getnameinfo(pr_netaddr_get_sockaddr(na),
      pr_netaddr_get_sockaddr_len(na), buf, sizeof(buf), NULL, 0, NI_NAMEREQD);
    buf[sizeof(buf)-1] = '\0';

    if (res == 0) {
      char **checkaddr;
      struct hostent *hent = NULL;
      unsigned char ok = FALSE;
      int family = pr_netaddr_get_family(na);
      void *inaddr = pr_netaddr_get_inaddr(na);
    
#ifdef HAVE_GETHOSTBYNAME2
      if (pr_netaddr_is_v4mappedv6(na) == TRUE) {
        family = AF_INET;
        inaddr = get_v4inaddr(na);
      }

      hent = gethostbyname2(buf, family);
#else
      hent = gethostbyname(buf);
#endif /* HAVE_GETHOSTBYNAME2 */

      if (hent != NULL) {
        char **alias;

        pr_trace_msg(trace_channel, 10,
          "checking addresses associated with host '%s'",
          hent->h_name ? hent->h_name : "(null)");
        for (alias = hent->h_aliases; *alias; ++alias) {
          pr_trace_msg(trace_channel, 10, "host '%s' has alias '%s'",
            hent->h_name ? hent->h_name : "(null)", *alias);
        }
        
        switch (hent->h_addrtype) {
          case AF_INET:
            if (family == AF_INET) {
              for (checkaddr = hent->h_addr_list; *checkaddr; ++checkaddr) {
                if (memcmp(*checkaddr, inaddr, hent->h_length) == 0) {
                  ok = TRUE;
                  break;
                }
              }
            } 
            break;

#ifdef PR_USE_IPV6
          case AF_INET6:
            if (use_ipv6 && family == AF_INET6) {
              for (checkaddr = hent->h_addr_list; *checkaddr; ++checkaddr) {
                if (memcmp(*checkaddr, inaddr, hent->h_length) == 0) {
                  ok = TRUE;
                  break;
                }
              }
            } 
            break;
#endif /* PR_USE_IPV6 */
        }

        if (ok) {
          name = buf;
          pr_trace_msg(trace_channel, 8,
            "using DNS name '%s' for IP address '%s'", name,
            pr_netaddr_get_ipstr(na));

        } else {
          name = NULL;
          pr_trace_msg(trace_channel, 8,
            "unable to verify any DNS names for IP address '%s'",
            pr_netaddr_get_ipstr(na));
        }

      } else
        pr_log_debug(DEBUG1, "notice: unable to resolve '%s': %s", buf,
          hstrerror(errno));
    }

  } else
    pr_log_debug(DEBUG10,
      "UseReverseDNS off, returning IP address instead of DNS name");

  if (name) {
    name = pr_inet_validate(name);

  } else {
    name = (char *) pr_netaddr_get_ipstr(na);
  }

  /* Copy the string into the pr_netaddr_t cache as well, so we only
   * have to do this once for this pr_netaddr_t.
   */
  memset(na->na_dnsstr, '\0', sizeof(na->na_dnsstr));
  sstrncpy(na->na_dnsstr, name, sizeof(na->na_dnsstr));
  na->na_have_dnsstr = TRUE;

  return na->na_dnsstr;
}
コード例 #21
0
ファイル: auth-publickey.c プロジェクト: Distrotech/proftpd
int sftp_auth_publickey(struct ssh2_packet *pkt, cmd_rec *pass_cmd,
    const char *orig_user, const char *user, const char *service, char **buf,
    uint32_t *buflen, int *send_userauth_fail) {
  int have_signature, pubkey_type;
  char *pubkey_algo = NULL, *pubkey_data;
  const char *fp = NULL;
  uint32_t pubkey_len;
  struct passwd *pw;

  if (pr_cmd_dispatch_phase(pass_cmd, PRE_CMD, 0) < 0) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "authentication request for user '%s' blocked by '%s' handler",
      orig_user, pass_cmd->argv[0]);

    pr_cmd_dispatch_phase(pass_cmd, POST_CMD_ERR, 0);
    pr_cmd_dispatch_phase(pass_cmd, LOG_CMD_ERR, 0);

    *send_userauth_fail = TRUE;
    errno = EPERM;
    return 0;
  }

  have_signature = sftp_msg_read_bool(pkt->pool, buf, buflen);

  if (sftp_interop_supports_feature(SFTP_SSH2_FEAT_HAVE_PUBKEY_ALGO)) {
    pubkey_algo = sftp_msg_read_string(pkt->pool, buf, buflen);
  }
  pubkey_len = sftp_msg_read_int(pkt->pool, buf, buflen);
  pubkey_data = sftp_msg_read_data(pkt->pool, buf, buflen, pubkey_len);

  if (pubkey_algo == NULL) {
    /* The client did not send the string identifying the public key algorithm.
     * Thus we need to extract the algorithm string from the public key data.
     */
    pubkey_algo = sftp_msg_read_string(pkt->pool, &pubkey_data, &pubkey_len);
  }

  pr_trace_msg(trace_channel, 9, "client sent '%s' public key %s",
    pubkey_algo, have_signature ? "with signature" : "without signature");

  if (strncmp(pubkey_algo, "ssh-rsa", 8) == 0) {
    pubkey_type = EVP_PKEY_RSA;

  } else if (strncmp(pubkey_algo, "ssh-dss", 8) == 0) {
    pubkey_type = EVP_PKEY_DSA;

  /* XXX This is where we would add support for X509 public keys, e.g.:
   *
   *  x509v3-ssh-dss
   *  x509v3-ssh-rsa
   *  x509v3-sign (older)
   *
   */

  } else {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "unsupported public key algorithm '%s' requested, rejecting request",
      pubkey_algo);

    *send_userauth_fail = TRUE;
    errno = EINVAL;
    return 0;
  }

  if (sftp_keys_verify_pubkey_type(pkt->pool, pubkey_data, pubkey_len,
      pubkey_type) != TRUE) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "unable to verify that given public key matches given '%s' algorithm",
      pubkey_algo);

    *send_userauth_fail = TRUE;
    errno = EINVAL;
    return 0;
  }

#ifdef OPENSSL_FIPS
  if (FIPS_mode()) {
    fp = sftp_keys_get_fingerprint(pkt->pool, pubkey_data, pubkey_len,
      SFTP_KEYS_FP_DIGEST_SHA1);
    if (fp != NULL) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "public key SHA1 fingerprint: %s", fp);

    } else {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error obtaining public key SHA1 fingerprint: %s", strerror(errno));
    }

  } else {
#endif /* OPENSSL_FIPS */
    fp = sftp_keys_get_fingerprint(pkt->pool, pubkey_data, pubkey_len,
      SFTP_KEYS_FP_DIGEST_MD5);
    if (fp != NULL) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "public key MD5 fingerprint: %s", fp);

    } else {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error obtaining public key MD5 fingerprint: %s", strerror(errno));
    }
#ifdef OPENSSL_FIPS
  }
#endif /* OPENSSL_FIPS */

  pw = pr_auth_getpwnam(pkt->pool, user);
  if (pw == NULL) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "no account for user '%s' found", user);

    pr_log_auth(PR_LOG_NOTICE,
      "USER %s: no such user found from %s [%s] to %s:%d", user,
      session.c->remote_name, pr_netaddr_get_ipstr(session.c->remote_addr),
      pr_netaddr_get_ipstr(session.c->local_addr), session.c->local_port);

    *send_userauth_fail = TRUE;
    errno = ENOENT;
    return 0;
  }

  if (!have_signature) {
    /* We don't perform the actual authentication just yet; we need to
     * let the client know that the pubkey algorithms are acceptable.
     */
    if (send_pubkey_ok(pubkey_algo, pubkey_data, pubkey_len) < 0) {
      return -1;
    }

    return 0;

  } else {
    const unsigned char *id;
    char *buf2, *ptr2, *signature_data;
    uint32_t buflen2, bufsz2, id_len, signature_len;

    /* XXX This should become a more generic "is this key data
     * usable/acceptable?" check (and take the pubkey_type parameter), so that
     * that is where we would check the validity/usability of an X509v3 cert
     * (if a cert), or if the key is on the blacklist (if a key).
     */

    if (sftp_blacklist_reject_key(pkt->pool, pubkey_data, pubkey_len)) {
      *send_userauth_fail = TRUE;
      errno = EPERM;
      return 0;
    }

    signature_len = sftp_msg_read_int(pkt->pool, buf, buflen);
    signature_data = sftp_msg_read_data(pkt->pool, buf, buflen, signature_len);

    /* The client signed the request as well; we need to authenticate the
     * user with the given pubkey now.  If that succeeds, we use the
     * signature to verify the request.  And if that succeeds, then we're
     * done authenticating.
     */

    /* XXX Need to pass the pubkey_type here as well, so that the
     * verification routines can handle different databases of keys/certs.
     * 
     * For X509v3 certs, we will want a way to enforce/restrict which
     * user names can be used with the provided cert.  Perhaps a database
     * mapping cert fingerprints to user names/UIDs?  Configurable callback
     * check (HOOK?), for modules to enforce.
     */

    if (sftp_keystore_verify_user_key(pkt->pool, user, pubkey_data,
        pubkey_len) < 0) {
      *send_userauth_fail = TRUE;
      return 0;
    }

    /* Make sure the signature matches as well. */

    id_len = sftp_session_get_id(&id);

    /* Make sure to allocate a buffer large enough to hold the publickey
     * signature and data we want to send back.
     */
    bufsz2 = buflen2 = pubkey_len + 1024;
    ptr2 = buf2 = sftp_msg_getbuf(pkt->pool, bufsz2);

    sftp_msg_write_data(&buf2, &buflen2, (char *) id, id_len, TRUE);
    sftp_msg_write_byte(&buf2, &buflen2, SFTP_SSH2_MSG_USER_AUTH_REQUEST);
    sftp_msg_write_string(&buf2, &buflen2, orig_user);

    if (sftp_interop_supports_feature(SFTP_SSH2_FEAT_SERVICE_IN_PUBKEY_SIG)) {
      sftp_msg_write_string(&buf2, &buflen2, service);

    } else {
      sftp_msg_write_string(&buf2, &buflen2, "ssh-userauth");
    }

    if (sftp_interop_supports_feature(SFTP_SSH2_FEAT_HAVE_PUBKEY_ALGO)) {
      sftp_msg_write_string(&buf2, &buflen2, "publickey");
      sftp_msg_write_bool(&buf2, &buflen2, TRUE);
      sftp_msg_write_string(&buf2, &buflen2, pubkey_algo);

    } else {
      sftp_msg_write_bool(&buf2, &buflen2, TRUE);
    }

    sftp_msg_write_data(&buf2, &buflen2, pubkey_data, pubkey_len, TRUE);

    if (sftp_keys_verify_signed_data(pkt->pool, pubkey_algo, pubkey_data,
        pubkey_len, signature_data, signature_len, (unsigned char *) ptr2,
        (bufsz2 - buflen2)) < 0) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "failed to verify '%s' signature on public key auth request for "
        "user '%s'", pubkey_algo, orig_user);
      *send_userauth_fail = TRUE;
      return 0;
    }
  }

  /* Make sure the user is authorized to login.  Normally this is checked
   * as part of the password verification process, but in the case of
   * publickey authentication, there is no password to verify.
   */

  if (pr_auth_authorize(pkt->pool, user) != PR_AUTH_OK) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "authentication for user '%s' failed: User not authorized", user);
    pr_log_auth(PR_LOG_NOTICE, "USER %s (Login failed): User not authorized "
      "for login", user);
    *send_userauth_fail = TRUE;
    errno = EACCES;
    return 0;
  }

  return 1;
}
コード例 #22
0
ファイル: disconnect.c プロジェクト: jmaggard10/proftpd
void sftp_disconnect_send(uint32_t reason, const char *explain,
    const char *file, int lineno, const char *func) {
  struct ssh2_packet *pkt;
  const pr_netaddr_t *remote_addr;
  const char *lang = "en-US";
  unsigned char *buf, *ptr;
  uint32_t buflen, bufsz;
  int sockfd;

  /* Send the client a DISCONNECT mesg. */
  pkt = sftp_ssh2_packet_create(sftp_pool);

  remote_addr = pr_netaddr_get_sess_remote_addr();

  buflen = bufsz = 1024;
  ptr = buf = palloc(pkt->pool, bufsz);

  if (explain == NULL) {
    register unsigned int i;

    for (i = 0; explanations[i].explain; i++) {
      if (explanations[i].code == reason) {
        explain = explanations[i].explain;
        lang = explanations[i].lang;
        if (lang == NULL) {
          lang = "en-US";
        }
        break;
      }
    }

    if (explain == NULL) {
      explain = "Unknown reason";
    }

  } else {
    lang = "en-US";
  }

  if (strlen(func) > 0) {
    pr_trace_msg(trace_channel, 9, "disconnecting (%s) [at %s:%d:%s()]",
      explain, file, lineno, func);

  } else {
    pr_trace_msg(trace_channel, 9, "disconnecting (%s) [at %s:%d]", explain,
      file, lineno);
  }

  sftp_msg_write_byte(&buf, &buflen, SFTP_SSH2_MSG_DISCONNECT);
  sftp_msg_write_int(&buf, &buflen, reason);
  sftp_msg_write_string(&buf, &buflen, explain);
  sftp_msg_write_string(&buf, &buflen, lang);

  pkt->payload = ptr;
  pkt->payload_len = (bufsz - buflen);

  (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
    "disconnecting %s (%s)", pr_netaddr_get_ipstr(remote_addr), explain);

  /* If we are called very early in the connection lifetime, then the
   * sftp_conn variable may not have been set yet, thus the conditional here.
   */
  if (sftp_conn != NULL) {
    sockfd = sftp_conn->wfd;

  } else {
    sockfd = session.c->wfd;
  }

  /* Explicitly set a short poll timeout of 5 secs. */
  sftp_ssh2_packet_set_poll_timeout(5);

  if (sftp_ssh2_packet_write(sockfd, pkt) < 0) {
    int xerrno = errno;

    pr_trace_msg(trace_channel, 12,
      "error writing DISCONNECT message: %s", strerror(xerrno));
  }

  destroy_pool(pkt->pool);
}
コード例 #23
0
ファイル: msg.c プロジェクト: Castaglia/proftpd-mod_proxy
END_TEST

START_TEST (parse_addr_test) {
  const pr_netaddr_t *res;
  const char *msg, *expected, *ip_str;

  res = proxy_ftp_msg_parse_addr(NULL, NULL, 0);
  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_msg_parse_addr(p, NULL, 0);
  fail_unless(res == NULL, "Failed to handle null msg");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL,
    strerror(errno), errno);

  msg = "foo";
  res = proxy_ftp_msg_parse_addr(p, msg, 0);
  fail_unless(res == NULL, "Failed to handle invalid format");
  fail_unless(errno == EPERM, "Expected EPERM (%d), got '%s' (%d)", EPERM,
    strerror(errno), errno);

  msg = "(a,b,c,d,e,f)";
  res = proxy_ftp_msg_parse_addr(p, msg, 0);
  fail_unless(res == NULL, "Failed to handle invalid format");
  fail_unless(errno == EPERM, "Expected EPERM (%d), got '%s' (%d)", EPERM,
    strerror(errno), errno);

  msg = "(1000,2000,3000,4000,5000,6000)";
  res = proxy_ftp_msg_parse_addr(p, msg, 0);
  fail_unless(res == NULL, "Failed to handle invalid format");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL,
    strerror(errno), errno);

  msg = "(1,2,3,4,5000,6000)";
  res = proxy_ftp_msg_parse_addr(p, msg, 0);
  fail_unless(res == NULL, "Failed to handle invalid format");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL,
    strerror(errno), errno);

  msg = "(0,0,0,0,1,2)";
  res = proxy_ftp_msg_parse_addr(p, msg, 0);
  fail_unless(res == NULL, "Failed to handle invalid format");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL,
    strerror(errno), errno);

  msg = "(1,2,3,4,0,0)";
  res = proxy_ftp_msg_parse_addr(p, msg, 0);
  fail_unless(res == NULL, "Failed to handle invalid format");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL,
    strerror(errno), errno);

  msg = "(127,0,0,1,8,73)";
  res = proxy_ftp_msg_parse_addr(p, msg, 0);
  fail_unless(res != NULL, "Failed to parse message '%s': %s", msg,
    strerror(errno));
  ip_str = pr_netaddr_get_ipstr(res);
  expected = "127.0.0.1";
  fail_unless(strcmp(ip_str, expected) == 0, "Expected '%s', got '%s'",
    expected, ip_str);
  fail_unless(ntohs(pr_netaddr_get_port(res)) == 2121,
    "Expected 2121, got %u", ntohs(pr_netaddr_get_port(res)));

#ifdef PR_USE_IPV6
  msg = "(127,0,0,1,8,73)";
  res = proxy_ftp_msg_parse_addr(p, msg, AF_INET);
  fail_unless(res != NULL, "Failed to parse message '%s': %s", msg,
    strerror(errno));
  ip_str = pr_netaddr_get_ipstr(res);
  expected = "127.0.0.1";
  fail_unless(strcmp(ip_str, expected) == 0, "Expected '%s', got '%s'",
    expected, ip_str);

  msg = "(127,0,0,1,8,73)";
  res = proxy_ftp_msg_parse_addr(p, msg, AF_INET6);
  fail_unless(res != NULL, "Failed to parse message '%s': %s", msg,
    strerror(errno));
  ip_str = pr_netaddr_get_ipstr(res);
  expected = "::ffff:127.0.0.1";
  fail_unless(strcmp(ip_str, expected) == 0, "Expected '%s', got '%s'",
    expected, ip_str);

  pr_netaddr_disable_ipv6();

  res = proxy_ftp_msg_parse_addr(p, msg, AF_INET6);
  fail_unless(res != NULL, "Failed to parse message '%s': %s", msg,
    strerror(errno));
  ip_str = pr_netaddr_get_ipstr(res);
  expected = "127.0.0.1";
  fail_unless(strcmp(ip_str, expected) == 0, "Expected '%s', got '%s'",
    expected, ip_str);

  pr_netaddr_enable_ipv6();
#endif /* PR_USE_IPV6 */
}
コード例 #24
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;
}
コード例 #25
0
ファイル: msg.c プロジェクト: Castaglia/proftpd-mod_proxy
END_TEST

START_TEST (parse_ext_addr_test) {
  const pr_netaddr_t *addr, *res;
  const char *msg; 

  res = proxy_ftp_msg_parse_ext_addr(NULL, NULL, NULL, 0, NULL);
  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_msg_parse_ext_addr(p, NULL, NULL, 0, NULL);
  fail_unless(res == NULL, "Failed to handle null msg");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL,
    strerror(errno), errno);

  msg = "foo";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, NULL, 0, NULL);
  fail_unless(res == NULL, "Failed to handle null addr");
  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 get address for 127.0.0.1: %s",
    strerror(errno));

  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, 0, NULL);
  fail_unless(res == NULL, "Failed to handle bad network protocol");
  fail_unless(errno == EPROTOTYPE, "Expected EPROTOTYPE (%d), got '%s' (%d)",
    EPROTOTYPE, strerror(errno), errno);

  /* EPSV response formats */

  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle bad EPSV response");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  msg = "(foo";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle bad EPSV response");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  msg = "(foo)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle bad network protocol");
  fail_unless(errno == EPROTOTYPE, "Expected EPROTOTYPE (%d), got '%s' (%d)",
    EPROTOTYPE, strerror(errno), errno);

  msg = "(1)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle bad network protocol");
  fail_unless(errno == EPROTOTYPE, "Expected EPROTOTYPE (%d), got '%s' (%d)",
    EPROTOTYPE, strerror(errno), errno);

  msg = "(|4)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle bad network protocol");
  fail_unless(errno == EPROTOTYPE, "Expected EPROTOTYPE (%d), got '%s' (%d)",
    EPROTOTYPE, strerror(errno), errno);

  msg = "(|0)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle bad network protocol");
  fail_unless(errno == EPROTOTYPE, "Expected EPROTOTYPE (%d), got '%s' (%d)",
    EPROTOTYPE, strerror(errno), errno);

  msg = "(|1)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle bad network protocol");
  fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
    strerror(errno), errno);

  msg = "(|2)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle bad network protocol");
  fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
    strerror(errno), errno);

  /* Where the network protocol matches that of the address... */
  msg = "(|1|)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle badly formatted message");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  msg = "(|1|1.2.3.4)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle badly formatted message");
  fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
    strerror(errno), errno);

  msg = "(|1|1.2.3.4|5)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle badly formatted message");
  fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
    strerror(errno), errno);

  msg = "(|1|1.2.3.4|5|)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res != NULL, "Failed to handle formatted message '%s': %s", msg,
    strerror(errno));

  msg = "(||1.2.3.4|5|)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res != NULL, "Failed to handle formatted message '%s': %s", msg,
    strerror(errno));

  msg = "(||1.2.3.4|5|)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, "all");
  fail_unless(res != NULL, "Failed to handle formatted message '%s': %s", msg,
    strerror(errno));

  msg = "(||1.2.3.4|5|)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, "1");
  fail_unless(res != NULL, "Failed to handle formatted message '%s': %s", msg,
    strerror(errno));

  msg = "(|||5|)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res != NULL, "Failed to handle formatted message '%s': %s", msg,
    strerror(errno));
  fail_unless(
    strcmp(pr_netaddr_get_ipstr(addr), pr_netaddr_get_ipstr(res)) == 0,
    "Expected '%s', got '%s'", pr_netaddr_get_ipstr(addr),
    pr_netaddr_get_ipstr(res));

  /* ...and where the network protocol does not match that of the address. */

  msg = "(||::1|5|)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle network protocol mismatch");
  fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
    strerror(errno), errno);

  msg = "(|2|1.2.3.4|5)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle network protocol mismatch");
  fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
    strerror(errno), errno);

#ifdef PR_USE_IPV6
  addr = pr_netaddr_get_addr(p, "::1", NULL);
  fail_unless(addr != NULL, "Failed to get address for ::1: %s",
    strerror(errno));

  msg = "(|2|1.2.3.4|5)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle network protocol mismatch");
  fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
    strerror(errno), errno);

  msg = "(|1|::1|5)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle network protocol mismatch");
  fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
    strerror(errno), errno);

  msg = "(|2|::1|5)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle network protocol mismatch");
  fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
    strerror(errno), errno);

  msg = "(|2|::1|5|)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res != NULL, "Failed to handle formatted message '%s': %s", msg,
    strerror(errno));

  msg = "(|2|::1|5|)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, "ALL");
  fail_unless(res != NULL, "Failed to handle formatted message '%s': %s", msg,
    strerror(errno));

  msg = "(||::1|5|)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, "2");
  fail_unless(res != NULL, "Failed to handle formatted message '%s': %s", msg,
    strerror(errno));

  msg = "(||::1|5|)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res != NULL, "Failed to handle formatted message '%s': %s", msg,
    strerror(errno));

  msg = "(|||5|)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res != NULL, "Failed to handle formatted message '%s': %s", msg,
    strerror(errno));
  fail_unless(
    strcmp(pr_netaddr_get_ipstr(addr), pr_netaddr_get_ipstr(res)) == 0,
    "Expected '%s', got '%s'", pr_netaddr_get_ipstr(addr),
    pr_netaddr_get_ipstr(res));

  msg = "(||1.2.3.4|5|)";
  res = proxy_ftp_msg_parse_ext_addr(p, msg, addr, PR_CMD_EPSV_ID, NULL);
  fail_unless(res == NULL, "Failed to handle network protocol mismatch");
  fail_unless(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
    strerror(errno), errno);
#endif /* PR_USE_IPV6 */
}
コード例 #26
0
ファイル: auth-hostbased.c プロジェクト: bverschueren/proftpd
int sftp_auth_hostbased(struct ssh2_packet *pkt, cmd_rec *pass_cmd,
    const char *orig_user, const char *user, const char *service,
    unsigned char **buf, uint32_t *buflen, int *send_userauth_fail) {
  struct passwd *pw;
  char *hostkey_algo, *host_fqdn, *host_user, *host_user_utf8;
  const char *fp = NULL;
  unsigned char *hostkey_data, *signature_data;
  unsigned char *buf2, *ptr2;
  const unsigned char *id;
  uint32_t buflen2, bufsz2, hostkey_datalen, id_len, signature_len;
  enum sftp_key_type_e pubkey_type;

  if (pr_cmd_dispatch_phase(pass_cmd, PRE_CMD, 0) < 0) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "authentication request for user '%s' blocked by '%s' handler",
      orig_user, (char *) pass_cmd->argv[0]);

    pr_cmd_dispatch_phase(pass_cmd, POST_CMD_ERR, 0);
    pr_cmd_dispatch_phase(pass_cmd, LOG_CMD_ERR, 0);

    *send_userauth_fail = TRUE;
    errno = EPERM;
    return 0;
  }

  hostkey_algo = sftp_msg_read_string(pkt->pool, buf, buflen);
  if (hostkey_algo == NULL) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "missing required host key algorithm, rejecting request");

    *send_userauth_fail = TRUE;
    errno = EINVAL;
    return 0;
  }

  hostkey_datalen = sftp_msg_read_int(pkt->pool, buf, buflen);
  hostkey_data = sftp_msg_read_data(pkt->pool, buf, buflen, hostkey_datalen);

  host_fqdn = sftp_msg_read_string(pkt->pool, buf, buflen);

  host_user_utf8 = sftp_msg_read_string(pkt->pool, buf, buflen);
  host_user = sftp_utf8_decode_str(pkt->pool, host_user_utf8);

  signature_len = sftp_msg_read_int(pkt->pool, buf, buflen);
  signature_data = sftp_msg_read_data(pkt->pool, buf, buflen, signature_len);

  pr_trace_msg(trace_channel, 9,
    "client sent '%s' host key, FQDN %s, and remote user '%s'",
    hostkey_algo, host_fqdn, host_user);

  if (strncmp(hostkey_algo, "ssh-rsa", 8) == 0) {
    pubkey_type = SFTP_KEY_RSA;

  } else if (strncmp(hostkey_algo, "ssh-dss", 8) == 0) {
    pubkey_type = SFTP_KEY_DSA;

#ifdef PR_USE_OPENSSL_ECC
  } else if (strncmp(hostkey_algo, "ecdsa-sha2-nistp256", 20) == 0) {
    pubkey_type = SFTP_KEY_ECDSA_256;

  } else if (strncmp(hostkey_algo, "ecdsa-sha2-nistp256", 20) == 0) {
    pubkey_type = SFTP_KEY_ECDSA_384;

  } else if (strncmp(hostkey_algo, "ecdsa-sha2-nistp256", 20) == 0) {
    pubkey_type = SFTP_KEY_ECDSA_521;
#endif /* PR_USE_OPENSSL_ECC */

  /* XXX Need to support X509v3 certs here */

  } else {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "unsupported host key algorithm '%s' requested, rejecting request",
      hostkey_algo);

    *send_userauth_fail = TRUE;
    errno = EINVAL;
    return 0;
  }

  if (sftp_keys_verify_pubkey_type(pkt->pool, hostkey_data, hostkey_datalen,
      pubkey_type) != TRUE) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "unable to verify that given host key matches given '%s' algorithm",
      hostkey_algo);

    *send_userauth_fail = TRUE;
    errno = EINVAL;
    return 0;
  }

#ifdef OPENSSL_FIPS
  if (FIPS_mode()) {
    fp = sftp_keys_get_fingerprint(pkt->pool, hostkey_data, hostkey_datalen,
      SFTP_KEYS_FP_DIGEST_SHA1);
    if (fp != NULL) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "public key SHA1 fingerprint: %s", fp);

    } else {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error obtaining public key SHA1 fingerprint: %s", strerror(errno));
    }

  } else {
#endif /* OPENSSL_FIPS */
    fp = sftp_keys_get_fingerprint(pkt->pool, hostkey_data, hostkey_datalen,
      SFTP_KEYS_FP_DIGEST_MD5);
    if (fp != NULL) {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "public key MD5 fingerprint: %s", fp);

    } else {
      (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
        "error obtaining public key MD5 fingerprint: %s", strerror(errno));
    }
#ifdef OPENSSL_FIPS
  }
#endif /* OPENSSL_FIPS */

  pw = pr_auth_getpwnam(pkt->pool, user);
  if (pw == NULL) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "no account for user '%s' found", user);

    pr_log_auth(PR_LOG_NOTICE,
      "USER %s: no such user found from %s [%s] to %s:%d", user,
      session.c->remote_name, pr_netaddr_get_ipstr(session.c->remote_addr),
      pr_netaddr_get_ipstr(session.c->local_addr), session.c->local_port);

    *send_userauth_fail = TRUE;
    errno = ENOENT;
    return 0;
  }

  /* XXX Should we check the given FQDN here against the client's actual
   * DNS name and/or IP address?  Or leave that up to the keystore's
   * verify_host_key() function?
   */

  if (sftp_blacklist_reject_key(pkt->pool, hostkey_data, hostkey_datalen)) {
    *send_userauth_fail = TRUE;
    errno = EACCES;
    return 0;
  }

  /* The client signed the request as well; we need to authenticate the
   * host with the given key now.  If that succeeds, we use the signature to
   * verify the request.  And if that succeeds, then we're done authenticating.
   */

  if (sftp_keystore_verify_host_key(pkt->pool, user, host_fqdn, host_user,
      hostkey_data, hostkey_datalen) < 0) {
    *send_userauth_fail = TRUE;
    errno = EACCES;
    return 0;
  }

  /* Make sure the signature matches as well. */

  id_len = sftp_session_get_id(&id);

  /* XXX Is this buffer large enough?  Too large? */
  bufsz2 = buflen2 = 2048;
  ptr2 = buf2 = sftp_msg_getbuf(pkt->pool, bufsz2);

  sftp_msg_write_data(&buf2, &buflen2, id, id_len, TRUE);
  sftp_msg_write_byte(&buf2, &buflen2, SFTP_SSH2_MSG_USER_AUTH_REQUEST);
  sftp_msg_write_string(&buf2, &buflen2, orig_user);

  if (sftp_interop_supports_feature(SFTP_SSH2_FEAT_SERVICE_IN_HOST_SIG)) {
    sftp_msg_write_string(&buf2, &buflen2, service);

  } else {
    sftp_msg_write_string(&buf2, &buflen2, "ssh-userauth");
  }

  sftp_msg_write_string(&buf2, &buflen2, "hostbased");
  sftp_msg_write_string(&buf2, &buflen2, hostkey_algo);
  sftp_msg_write_data(&buf2, &buflen2, hostkey_data, hostkey_datalen, TRUE);
  sftp_msg_write_string(&buf2, &buflen2, host_fqdn);
  sftp_msg_write_string(&buf2, &buflen2, host_user_utf8);

  if (sftp_keys_verify_signed_data(pkt->pool, hostkey_algo, hostkey_data,
      hostkey_datalen, signature_data, signature_len, (unsigned char *) ptr2,
      (bufsz2 - buflen2)) < 0) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "failed to verify '%s' signature on hostbased auth request for "
      "user '%s', host %s", hostkey_algo, orig_user, host_fqdn);
    *send_userauth_fail = TRUE;
    return 0;
  }

  /* Make sure the user is authorized to login.  Normally this is checked
   * as part of the password verification process, but in the case of
   * hostbased authentication, there is no password to verify.
   */

  if (pr_auth_authorize(pkt->pool, user) != PR_AUTH_OK) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "authentication for user '%s' failed: User not authorized", user);
    pr_log_auth(PR_LOG_NOTICE, "USER %s (Login failed): User not authorized "
      "for login", user);
    *send_userauth_fail = TRUE;
    errno = EACCES;
    return 0;
  }

  return 1;
}
コード例 #27
0
ファイル: netaddr.c プロジェクト: WiseMan787/ralink_sdk
pr_netaddr_t *pr_netaddr_get_addr(pool *p, const char *name,
    array_header **addrs) {

  struct sockaddr_in v4;
  pr_netaddr_t *na = NULL;
  int res;

  if (p == NULL || name == NULL) {
    errno = EINVAL;
    return NULL;
  }

  pr_trace_msg(trace_channel, 10, "resolving name '%s' to IP address",
    name);

  /* Attempt to translate the given name into a pr_netaddr_t using
   * pr_inet_pton() first.
   *
   * First, if IPv6 support is enabled, we try to translate the name using
   * pr_inet_pton(AF_INET6) on the hopes that the given string is a valid
   * representation of an IPv6 address.  If that fails, or if IPv6 support
   * is not enabled, we try with pr_inet_pton(AF_INET).  If that fails, we
   * assume that the given name is a DNS name, and we call pr_getaddrinfo().
   */

  na = (pr_netaddr_t *) pcalloc(p, sizeof(pr_netaddr_t));

#ifdef PR_USE_IPV6
  if (use_ipv6) {
    struct sockaddr_in6 v6;
    memset(&v6, 0, sizeof(v6));
    v6.sin6_family = AF_INET6;

# ifdef SIN6_LEN
    v6.sin6_len = sizeof(struct sockaddr_in6);
# endif /* SIN6_LEN */

    res = pr_inet_pton(AF_INET6, name, &v6.sin6_addr);
    if (res > 0) {
      pr_netaddr_set_family(na, AF_INET6);
      pr_netaddr_set_sockaddr(na, (struct sockaddr *) &v6);
      if (addrs)
        *addrs = NULL;

      pr_trace_msg(trace_channel, 7, "'%s' resolved to IPv6 address %s", name,
        pr_netaddr_get_ipstr(na));
      return na;
    }
  }
#endif /* PR_USE_IPV6 */

  memset(&v4, 0, sizeof(v4));
  v4.sin_family = AF_INET;

# ifdef SIN_LEN
  v4.sin_len = sizeof(struct sockaddr_in);
# endif /* SIN_LEN */

  res = pr_inet_pton(AF_INET, name, &v4.sin_addr);
  if (res > 0) {
    pr_netaddr_set_family(na, AF_INET);
    pr_netaddr_set_sockaddr(na, (struct sockaddr *) &v4);
    if (addrs)
      *addrs = NULL;

    pr_trace_msg(trace_channel, 7, "'%s' resolved to IPv4 address %s", name,
      pr_netaddr_get_ipstr(na));
    return na;

  } else if (res == 0) {

    /* If pr_inet_pton() returns 0, it means that name does not represent a
     * valid network address in the specified address family.  Usually,
     * this means that name is actually a DNS name, not an IP address
     * string.  So we treat it as a DNS name, and use getaddrinfo(3) to
     * resolve that name to its IP address(es).
     */

    struct addrinfo hints, *info = NULL;
    int gai_res = 0;

    memset(&hints, 0, sizeof(hints));

    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;

    pr_trace_msg(trace_channel, 7,
      "attempting to resolve '%s' to IPv4 address via DNS", name);
    gai_res = pr_getaddrinfo(name, NULL, &hints, &info);
    if (gai_res != 0) {
      if (gai_res != EAI_SYSTEM) {
        pr_trace_msg(trace_channel, 1, "IPv4 getaddrinfo '%s' error: %s",
          name, pr_gai_strerror(gai_res));

      } else {
        pr_trace_msg(trace_channel, 1,
          "IPv4 getaddrinfo '%s' system error: [%d] %s", name,
          errno, strerror(errno));
      }

      return NULL;
    }

    if (info) {
      /* Copy the first returned addr into na, as the return value. */
      pr_netaddr_set_family(na, info->ai_family);
      pr_netaddr_set_sockaddr(na, info->ai_addr);

      pr_trace_msg(trace_channel, 7, "resolved '%s' to %s address %s", name,
        info->ai_family == AF_INET ? "IPv4" : "IPv6",
        pr_netaddr_get_ipstr(na));

      pr_freeaddrinfo(info);
    }

#ifdef PR_USE_IPV6
    if (use_ipv6 && addrs) {
      /* Do the call again, this time for IPv6 addresses.
       *
       * We make two separate getaddrinfo(3) calls, rather than one
       * with a hint of AF_UNSPEC, because of certain bugs where the use
       * of AF_UNSPEC does not function as advertised.  (I suspect this
       * bug was caused by proftpd's calling pattern, but as I could
       * not track it down, and as there are reports of AF_UNSPEC not
       * being as fast as AF_INET/AF_INET6, it just seemed easier to
       * do it this way.)
       */

      gai_res = 0;

      memset(&hints, 0, sizeof(hints));

      hints.ai_family = AF_INET6;
      hints.ai_socktype = SOCK_STREAM;

      pr_trace_msg(trace_channel, 7,
        "attempting to resolve '%s' to IPv6 address via DNS", name);
      gai_res = pr_getaddrinfo(name, NULL, &hints, &info);
      if (gai_res != 0) {
        if (gai_res != EAI_SYSTEM) {
          pr_trace_msg(trace_channel, 1, "IPv6 getaddrinfo '%s' error: %s",
            name, pr_gai_strerror(gai_res));

        } else {
          pr_trace_msg(trace_channel, 1, 
            "IPv6 getaddrinfo '%s' system error: [%d] %s", name,
            errno, strerror(errno));
        }

        return na;
      }

      if (info) {
        pr_netaddr_t **elt;

        *addrs = make_array(p, 0, sizeof(pr_netaddr_t *));
        elt = push_array(*addrs);

        *elt = pcalloc(p, sizeof(pr_netaddr_t));
        pr_netaddr_set_family(*elt, info->ai_family);
        pr_netaddr_set_sockaddr(*elt, info->ai_addr);

        pr_trace_msg(trace_channel, 7, "resolved '%s' to %s address %s", name,
          info->ai_family == AF_INET ? "IPv4" : "IPv6",
          pr_netaddr_get_ipstr(*elt));

        pr_freeaddrinfo(info);
      }
    }
#endif /* PR_USE_IPV6 */

    return na;
  }

  pr_trace_msg(trace_channel, 8, "failed to resolve '%s' to an IP address",
    name);
  return NULL;
}
コード例 #28
0
ファイル: bindings.c プロジェクト: dbarba74/proftpd
int pr_namebind_create(server_rec *server, const char *name,
    pr_netaddr_t *addr, unsigned int port) {
  pr_ipbind_t *ipbind = NULL;
  pr_namebind_t *namebind = NULL, **namebinds = NULL;

  if (server == NULL ||
      name == NULL) {
    errno = EINVAL;
    return -1;
  }

  /* First, find the ipbind to hold this namebind. */
  ipbind = pr_ipbind_find(addr, port, FALSE);

  if (ipbind == NULL) {
    pr_netaddr_t wildcard_addr;
    int addr_family;

    /* If not found, look for the wildcard address. */

    addr_family = pr_netaddr_get_family(addr);
    pr_netaddr_clear(&wildcard_addr);
    pr_netaddr_set_family(&wildcard_addr, addr_family);
    pr_netaddr_set_sockaddr_any(&wildcard_addr);

    ipbind = pr_ipbind_find(&wildcard_addr, port, FALSE);
#ifdef PR_USE_IPV6
    if (ipbind == FALSE &&
        addr_family == AF_INET6 &&
        pr_netaddr_use_ipv6()) {

      /* No IPv6 wildcard address found; try the IPv4 wildcard address. */
      pr_netaddr_clear(&wildcard_addr);
      pr_netaddr_set_family(&wildcard_addr, AF_INET);
      pr_netaddr_set_sockaddr_any(&wildcard_addr);

      ipbind = pr_ipbind_find(&wildcard_addr, port, FALSE);
    }
#endif /* PR_USE_IPV6 */
  }

  if (ipbind == NULL) {
    errno = ENOENT;
    return -1;
  }

  /* Make sure we can add this namebind. */
  if (!ipbind->ib_namebinds) {
    ipbind->ib_namebinds = make_array(binding_pool, 0, sizeof(pr_namebind_t *));

  } else {
    register unsigned int i = 0;
    namebinds = (pr_namebind_t **) ipbind->ib_namebinds->elts;

    /* See if there is already a namebind for the given name. */
    for (i = 0; i < ipbind->ib_namebinds->nelts; i++) {
      namebind = namebinds[i];
      if (namebind != NULL &&
          namebind->nb_name != NULL) {

        /* DNS names are case-insensitive, hence the case-insensitive check
         * here.
         *
         * XXX Ideally, we should check whether any existing namebinds which
         * are globs will match the newly added namebind as well.
         */

        if (strcasecmp(namebind->nb_name, name) == 0) {
          errno = EEXIST;
          return -1;
        }
      }
    }
  }

  namebind = (pr_namebind_t *) pcalloc(server->pool, sizeof(pr_namebind_t));
  namebind->nb_name = name;
  namebind->nb_server = server;
  namebind->nb_isactive = FALSE;

  if (pr_str_is_fnmatch(name) == TRUE) {
    namebind->nb_iswildcard = TRUE;
  }

  pr_trace_msg(trace_channel, 8,
    "created named binding '%s' for %s#%u, server %p", name,
    pr_netaddr_get_ipstr(server->addr), server->ServerPort, server->ServerName);

  /* The given server should already have the following populated:
   *
   *  server->ServerName
   *  server->ServerAddress
   *  server->ServerFQDN
   */

  /* These TCP socket tweaks will not apply to the control connection (it will
   * already have been established by the time this named vhost is used),
   * but WILL apply to any data connections established to this named vhost.
   */

#if 0
  namebind->nb_server->tcp_mss_len = (server->tcp_mss_len ?
    server->tcp_mss_len : main_server->tcp_mss_len);
  namebind->nb_server->tcp_rcvbuf_len = (server->tcp_rcvbuf_len ?
    server->tcp_rcvbuf_len : main_server->tcp_rcvbuf_len);
  namebind->nb_server->tcp_rcvbuf_override = (server->tcp_rcvbuf_override ?
    TRUE : main_server->tcp_rcvbuf_override);
  namebind->nb_server->tcp_sndbuf_len = (server->tcp_sndbuf_len ?
    server->tcp_sndbuf_len : main_server->tcp_sndbuf_len);
  namebind->nb_server->tcp_sndbuf_override = (server->tcp_sndbuf_override ?
    TRUE : main_server->tcp_sndbuf_override);

  /* XXX Shouldn't need these; the ipbind container handles all of the
   * connection (listener, port, addr) stuff.
   */

  namebind->nb_server->addr = (server->addr ? server->addr :
    main_server->addr);
  namebind->nb_server->ServerPort = (server->ServerPort ? server->ServerPort :
    main_server->ServerPort);
  namebind->nb_listener = (server->listen ? server->listen :
    main_server->listen);
#endif

  *((pr_namebind_t **) push_array(ipbind->ib_namebinds)) = namebind;
  return 0;
}
コード例 #29
0
ファイル: msg.c プロジェクト: Castaglia/proftpd-mod_proxy
const char *proxy_ftp_msg_fmt_ext_addr(pool *p, const pr_netaddr_t *addr,
    unsigned short port, int cmd_id, int use_masqaddr) {
  const char *addr_str;
  char delim = '|', *msg;
  int family = 0;
  size_t addr_strlen, msglen;

  if (p == NULL ||
      addr == NULL) {
    errno = EINVAL;
    return NULL;
  }

  if (use_masqaddr) {
    config_rec *c;

    /* Handle MasqueradeAddress. */
    c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress", FALSE);
    if (c != NULL) {
      addr = c->argv[0];
    }
  }

  /* Format is <d>proto<d>ip address<d>port<d> (ASCII in network order),
   * where <d> is an arbitrary delimiter character.
   */

  switch (pr_netaddr_get_family(addr)) {
    case AF_INET:
      family = 1;
      break;

#ifdef PR_USE_IPV6
    case AF_INET6:
      family = 2;
      break;
#endif /* PR_USE_IPV6 */

    default:
      /* Unlikely to happen. */
      errno = EINVAL;
      return NULL;
  }

  addr_str = pr_netaddr_get_ipstr(addr);
  addr_strlen = strlen(addr_str);

  /* 4 delimiters, the network protocol, the IP address, the port, and a NUL. */
  msglen = (4 * 1) + addr_strlen + 6 + 1;

  msg = pcalloc(p, msglen);
  switch (cmd_id) {
    case PR_CMD_EPRT_ID:
      snprintf(msg, msglen, "%c%d%c%s%c%hu%c", delim, family, delim,
        addr_str, delim, port, delim);
      break;

    case PR_CMD_EPSV_ID:
      snprintf(msg, msglen-1, "%c%c%c%u%c", delim, delim, delim, port, delim);
      break;

    default:
      pr_trace_msg(trace_channel, 3, "invalid/unsupported command ID: %d",
        cmd_id);
      errno = EINVAL;
      return NULL;
  }

  return msg;
}
コード例 #30
0
ファイル: netaddr.c プロジェクト: WiseMan787/ralink_sdk
int pr_netaddr_cmp(const pr_netaddr_t *na1, const pr_netaddr_t *na2) {
  pool *tmp_pool = NULL;
  pr_netaddr_t *a, *b;
  int res;

  if (na1 && !na2)
    return 1;

  if (!na1 && na2)
    return -1;

  if (!na1 && !na2)
    return 0;

  if (pr_netaddr_get_family(na1) != pr_netaddr_get_family(na2)) {

    /* Cannot compare addresses from different families, unless one
     * of the netaddrs has an AF_INET family, and the other has an
     * AF_INET6 family AND is an IPv4-mapped IPv6 address.
     */

    if (pr_netaddr_is_v4mappedv6(na1) != TRUE &&
        pr_netaddr_is_v4mappedv6(na2) != TRUE) {
      errno = EINVAL;
      return -1;
    }

    if (pr_netaddr_is_v4mappedv6(na1) == TRUE) {
      tmp_pool = make_sub_pool(permanent_pool);

      /* This case means that na1 is an IPv4-mapped IPv6 address, and
       * na2 is an IPv4 address.
       */
      a = pr_netaddr_alloc(tmp_pool);
      pr_netaddr_set_family(a, AF_INET);
      pr_netaddr_set_port(a, pr_netaddr_get_port(na1));
      memcpy(&a->na_addr.v4.sin_addr, get_v4inaddr(na1),
        sizeof(struct in_addr));

      b = (pr_netaddr_t *) na2;

      pr_trace_msg(trace_channel, 6, "comparing IPv4 address '%s' against "
        "IPv4-mapped IPv6 address '%s'", pr_netaddr_get_ipstr(b),
        pr_netaddr_get_ipstr(a));

    } else if (pr_netaddr_is_v4mappedv6(na2) == TRUE) {
      tmp_pool = make_sub_pool(permanent_pool);

      /* This case means that na is an IPv4 address, and na2 is an
       * IPv4-mapped IPv6 address.
       */
      a = (pr_netaddr_t *) na1;

      b = pr_netaddr_alloc(tmp_pool);
      pr_netaddr_set_family(b, AF_INET);
      pr_netaddr_set_port(b, pr_netaddr_get_port(na2));
      memcpy(&b->na_addr.v4.sin_addr, get_v4inaddr(na2),
        sizeof(struct in_addr));

      pr_trace_msg(trace_channel, 6, "comparing IPv4 address '%s' against "
        "IPv4-mapped IPv6 address '%s'", pr_netaddr_get_ipstr(a),
        pr_netaddr_get_ipstr(b));

    } else {
      a = (pr_netaddr_t *) na1;
      b = (pr_netaddr_t *) na2;
    }

  } else {
    a = (pr_netaddr_t *) na1;
    b = (pr_netaddr_t *) na2;
  }

  switch (pr_netaddr_get_family(a)) {
    case AF_INET:
      res = memcmp(&a->na_addr.v4.sin_addr, &b->na_addr.v4.sin_addr,
        sizeof(struct in_addr));
      if (tmp_pool)
        destroy_pool(tmp_pool);
      return res;

#ifdef PR_USE_IPV6
    case AF_INET6:
      if (use_ipv6) {
        res = memcmp(&a->na_addr.v6.sin6_addr, &b->na_addr.v6.sin6_addr,
          sizeof(struct in6_addr));
        if (tmp_pool)
          destroy_pool(tmp_pool);
        return res;
      }
#endif /* PR_USE_IPV6 */
  }

  if (tmp_pool)
    destroy_pool(tmp_pool);

  errno = EPERM;
  return -1;
}