Exemple #1
0
const char *pr_strtime2(time_t t, int use_gmtime) {
  static char buf[64];
  static char *mons[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
    "Aug", "Sep", "Oct", "Nov", "Dec" };
  static char *days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
  struct tm *tr;

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

  if (use_gmtime) {
    tr = pr_gmtime(NULL, &t);

  } else {
    tr = pr_localtime(NULL, &t);
  }

  if (tr != NULL) {
    snprintf(buf, sizeof(buf), "%s %s %02d %02d:%02d:%02d %d",
      days[tr->tm_wday], mons[tr->tm_mon], tr->tm_mday, tr->tm_hour,
      tr->tm_min, tr->tm_sec, tr->tm_year + 1900);

  } else {
    buf[0] = '\0';
  }

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

  return buf;
}
Exemple #2
0
END_TEST

START_TEST (localtime_test) {
  struct tm *res;
  time_t now;

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

  time(&now);

  mark_point();
  res = pr_localtime(NULL, &now);
  fail_unless(res != NULL, "Failed to handle %lu: %s", (unsigned long) now,
    strerror(errno));

  mark_point();
  res = pr_localtime(p, &now);
  fail_unless(res != NULL, "Failed to handle %lu: %s", (unsigned long) now,
    strerror(errno));
}
Exemple #3
0
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);
  }
}
Exemple #4
0
int pr_log_vwritefile(int logfd, const char *ident, const char *fmt,
    va_list msg) {
  char buf[PR_TUNABLE_BUFFER_SIZE] = {'\0'};
  struct timeval now;
  struct tm *tm = NULL;
  size_t buflen, len;
  unsigned long millis;

  if (logfd < 0) {
    errno = EINVAL;
    return -1;
  }

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

  /* Prepend the timestamp */
  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;

  /* Prepend a small header */
  len = snprintf(buf + buflen, sizeof(buf) - buflen, "%s[%u]: ", ident,
    (unsigned int) (session.pid ? session.pid : getpid()));
  buflen += len;
  buf[sizeof(buf)-1] = '\0';

  /* Affix the message */
  len = vsnprintf(buf + buflen, sizeof(buf) - buflen - 1, fmt, msg);
  buflen += len;
  buf[sizeof(buf)-1] = '\0';

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

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

  pr_log_event_generate(PR_LOG_TYPE_UNSPEC, logfd, -1, buf, buflen);

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

    return -1;
  }

  return 0;
}
Exemple #5
0
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);
}
Exemple #6
0
const char *sftp_display_fh_get_msg(pool *p, pr_fh_t *fh) {
  struct stat st;
  char buf[PR_TUNABLE_BUFFER_SIZE], *msg = "";
  int len, res;
  unsigned int *current_clients = NULL;
  unsigned int *max_clients = NULL;
  off_t fs_size = 0;
  void *v;
  const char *serverfqdn = main_server->ServerFQDN;
  char *outs, mg_size[12] = {'\0'}, mg_size_units[12] = {'\0'},
    mg_max[12] = "unlimited";
  char mg_class_limit[12] = {'\0'}, mg_cur[12] = {'\0'},
    mg_cur_class[12] = {'\0'};
  const char *mg_time;
  char *rfc1413_ident = NULL, *user = NULL;

  /* Stat the opened file to determine the optimal buffer size for IO. */
  memset(&st, 0, sizeof(st));
  if (pr_fsio_fstat(fh, &st) == 0) {
    fh->fh_iosz = st.st_blksize;
  }

  res = pr_fs_fgetsize(fh->fh_fd, &fs_size);
  if (res < 0 &&
      errno != ENOSYS) {
    (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
      "error getting filesystem size for '%s': %s", fh->fh_path,
      strerror(errno));
    fs_size = 0;
  }

  snprintf(mg_size, sizeof(mg_size), "%" PR_LU, (pr_off_t) fs_size);
  format_size_str(mg_size_units, sizeof(mg_size_units), fs_size);

  mg_time = pr_strtime(time(NULL));

  max_clients = get_param_ptr(main_server->conf, "MaxClients", FALSE);

  v = pr_table_get(session.notes, "client-count", NULL);
  if (v) {
    current_clients = v;
  }

  snprintf(mg_cur, sizeof(mg_cur), "%u", current_clients ? *current_clients: 1);

  if (session.conn_class != NULL &&
      session.conn_class->cls_name) {
    unsigned int *class_clients = NULL;
    config_rec *maxc = NULL;
    unsigned int maxclients = 0;

    v = pr_table_get(session.notes, "class-client-count", NULL);
    if (v) {
      class_clients = v;
    }

    snprintf(mg_cur_class, sizeof(mg_cur_class), "%u",
      class_clients ? *class_clients : 0);

    /* For the %z variable, first we scan through the MaxClientsPerClass,
     * and use the first applicable one.  If none are found, look for
     * any MaxClients set.
     */

    maxc = find_config(main_server->conf, CONF_PARAM, "MaxClientsPerClass",
      FALSE);

    while (maxc) {
      pr_signals_handle();

      if (strcmp(maxc->argv[0], session.conn_class->cls_name) != 0) {
        maxc = find_config_next(maxc, maxc->next, CONF_PARAM,
          "MaxClientsPerClass", FALSE);
        continue;
      }

      maxclients = *((unsigned int *) maxc->argv[1]);
      break;
    }

    if (maxclients == 0) {
      maxc = find_config(main_server->conf, CONF_PARAM, "MaxClients", FALSE);

      if (maxc)
        maxclients = *((unsigned int *) maxc->argv[0]);
    }

    snprintf(mg_class_limit, sizeof(mg_class_limit), "%u", maxclients);

  } else {
    snprintf(mg_class_limit, sizeof(mg_class_limit), "%u",
      max_clients ? *max_clients : 0);
    snprintf(mg_cur_class, sizeof(mg_cur_class), "%u", 0);
  }

  snprintf(mg_max, sizeof(mg_max), "%u", max_clients ? *max_clients : 0);

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

  rfc1413_ident = pr_table_get(session.notes, "mod_ident.rfc1413-ident", NULL);
  if (rfc1413_ident == NULL) {
    rfc1413_ident = "UNKNOWN";
  }

  memset(buf, '\0', sizeof(buf));
  while (pr_fsio_gets(buf, sizeof(buf), fh) != NULL) {
    char *tmp;

    pr_signals_handle();

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

    while (len > 0 &&
           (buf[len-1] == '\r' || buf[len-1] == '\n')) {
      pr_signals_handle();

      buf[len-1] = '\0';
      len--;
    }

    /* Check for any Variable-type strings. */
    tmp = strstr(buf, "%{");
    while (tmp) {
      char *key, *tmp2;
      const char *val;

      pr_signals_handle();

      tmp2 = strchr(tmp, '}');
      if (tmp2 == NULL) {
        /* No closing '}' found in this string, so no need to look for any
         * aother '%{' opening sequence.  Just move on.
         */
        tmp = NULL;
        break;
      }

      key = pstrndup(p, tmp, tmp2 - tmp + 1);

      /* There are a couple of special-case keys to watch for:
       *
       *   env:$var
       *   time:$fmt
       *
       * The Var API does not easily support returning values for keys
       * where part of the value depends on part of the key.  That's why
       * these keys are handled here, instead of in pr_var_get().
       */

      if (strncmp(key, "%{time:", 7) == 0) {
        char time_str[128], *fmt;
        time_t now;
        struct tm *time_info;

        fmt = pstrndup(p, key + 7, strlen(key) - 8);

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

        memset(time_str, 0, sizeof(time_str));
        strftime(time_str, sizeof(time_str), fmt, time_info);

        val = pstrdup(p, time_str);

      } else if (strncmp(key, "%{env:", 6) == 0) {
        char *env_var;

        env_var = pstrndup(p, key + 6, strlen(key) - 7);
        val = pr_env_get(p, env_var);
        if (val == NULL) {
          pr_trace_msg("var", 4,
            "no value set for environment variable '%s', using \"(none)\"",
            env_var);
          val = "(none)";
        }

      } else {
        val = pr_var_get(key);
        if (val == NULL) {
          pr_trace_msg("var", 4,
            "no value set for name '%s', using \"(none)\"", key);
          val = "(none)";
        }
      }

      outs = sreplace(p, buf, key, val, NULL);
      sstrncpy(buf, outs, sizeof(buf));

      tmp = strstr(outs, "%{");
    }

    outs = sreplace(p, buf,
      "%C", (session.cwd[0] ? session.cwd : "(none)"),
      "%E", main_server->ServerAdmin,
      "%F", mg_size,
      "%f", mg_size_units,
      "%i", "0",
      "%K", "0",
      "%k", "0B",
      "%L", serverfqdn,
      "%M", mg_max,
      "%N", mg_cur,
      "%o", "0",
      "%R", (session.c && session.c->remote_name ?
        session.c->remote_name : "(unknown)"),
      "%T", mg_time,
      "%t", "0",
      "%U", user,
      "%u", rfc1413_ident,
      "%V", main_server->ServerName,
      "%x", session.conn_class ? session.conn_class->cls_name : "(unknown)",
      "%y", mg_cur_class,
      "%z", mg_class_limit,
      NULL);

    /* Always make sure that the lines we send are CRLF-terminated. */
    msg = pstrcat(p, msg, outs, "\r\n", NULL);

    /* Clear the buffer for the next read. */
    memset(buf, '\0', sizeof(buf));
  }

  return msg;
}
Exemple #7
0
/* Checks for the existence of PR_SHUTMSG_PATH.  deny and disc are
 * filled with the times to deny new connections and disconnect
 * existing ones.
 */
int check_shutmsg(const char *path, time_t *shut, time_t *deny, time_t *disc,
    char *msg, size_t msg_size) {
  FILE *fp;
  char *deny_str, *disc_str, *cp, buf[PR_TUNABLE_BUFFER_SIZE+1] = {'\0'};
  char hr[3] = {'\0'}, mn[3] = {'\0'};
  time_t now, shuttime = (time_t) 0;
  struct tm *tm;

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

  fp = fopen(path, "r");
  if (fp != NULL) {
    struct stat st;

    if (fstat(fileno(fp), &st) == 0) {
      if (S_ISDIR(st.st_mode)) {
        fclose(fp);
        errno = EISDIR;
        return -1;
      }
    }

    cp = fgets(buf, sizeof(buf), fp);
    if (cp != NULL) {
      buf[sizeof(buf)-1] = '\0'; CHOP(cp);

      /* We use this to fill in dst, timezone, etc */
      time(&now);
      tm = pr_localtime(NULL, &now);
      if (tm == NULL) {
        fclose(fp);
        return 0;
      }

      tm->tm_year = atoi(safe_token(&cp)) - 1900;
      tm->tm_mon = atoi(safe_token(&cp)) - 1;
      tm->tm_mday = atoi(safe_token(&cp));
      tm->tm_hour = atoi(safe_token(&cp));
      tm->tm_min = atoi(safe_token(&cp));
      tm->tm_sec = atoi(safe_token(&cp));

      deny_str = safe_token(&cp);
      disc_str = safe_token(&cp);

      shuttime = mktime(tm);
      if (shuttime == (time_t) -1) {
        fclose(fp);
        return 0;
      }

      if (deny != NULL) {
        if (strlen(deny_str) == 4) {
          sstrncpy(hr, deny_str, sizeof(hr)); hr[2] = '\0'; deny_str += 2;
          sstrncpy(mn, deny_str, sizeof(mn)); mn[2] = '\0';

          *deny = shuttime - ((atoi(hr) * 3600) + (atoi(mn) * 60));

        } else {
          *deny = shuttime;
        }
      }

      if (disc != NULL) {
        if (strlen(disc_str) == 4) {
          sstrncpy(hr, disc_str, sizeof(hr)); hr[2] = '\0'; disc_str += 2;
          sstrncpy(mn, disc_str, sizeof(mn)); mn[2] = '\0';

          *disc = shuttime - ((atoi(hr) * 3600) + (atoi(mn) * 60));

        } else {
          *disc = shuttime;
        }
      }

      if (fgets(buf, sizeof(buf), fp) && msg) {
        buf[sizeof(buf)-1] = '\0';
	CHOP(buf);
        sstrncpy(msg, buf, msg_size-1);
      }
    }

    fclose(fp);
    if (shut != NULL) {
      *shut = shuttime;
    }

    return 1;
  }

  return -1;
}