Edit

IABSD.fr/src/usr.bin/ssh/log.h

Branch :

  • Show log

    Commit

  • Author : djm
    Date : 2024-12-07 10:05:36
    Hash : cc7fda5d
    Message : add infrastructure for ratelimited logging; feedback/ok dtucker

  • usr.bin/ssh/log.h
  • /* $OpenBSD: log.h,v 1.35 2024/12/07 10:05:37 djm Exp $ */
    
    /*
     * Author: Tatu Ylonen <ylo@cs.hut.fi>
     * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
     *                    All rights reserved
     *
     * As far as I am concerned, the code I have written for this software
     * can be used freely for any purpose.  Any derived versions of this
     * software must be clearly marked as such, and if the derived work is
     * incompatible with the protocol description in the RFC file, it must be
     * called by a name other than "ssh" or "Secure Shell".
     */
    
    #ifndef SSH_LOG_H
    #define SSH_LOG_H
    
    #include <stdarg.h> /* va_list */
    #include "ssherr.h" /* ssh_err() */
    
    /* Supported syslog facilities and levels. */
    typedef enum {
    	SYSLOG_FACILITY_DAEMON,
    	SYSLOG_FACILITY_USER,
    	SYSLOG_FACILITY_AUTH,
    	SYSLOG_FACILITY_LOCAL0,
    	SYSLOG_FACILITY_LOCAL1,
    	SYSLOG_FACILITY_LOCAL2,
    	SYSLOG_FACILITY_LOCAL3,
    	SYSLOG_FACILITY_LOCAL4,
    	SYSLOG_FACILITY_LOCAL5,
    	SYSLOG_FACILITY_LOCAL6,
    	SYSLOG_FACILITY_LOCAL7,
    	SYSLOG_FACILITY_NOT_SET = -1
    }       SyslogFacility;
    
    typedef enum {
    	SYSLOG_LEVEL_QUIET,
    	SYSLOG_LEVEL_FATAL,
    	SYSLOG_LEVEL_ERROR,
    	SYSLOG_LEVEL_INFO,
    	SYSLOG_LEVEL_VERBOSE,
    	SYSLOG_LEVEL_DEBUG1,
    	SYSLOG_LEVEL_DEBUG2,
    	SYSLOG_LEVEL_DEBUG3,
    	SYSLOG_LEVEL_NOT_SET = -1
    }       LogLevel;
    
    typedef void (log_handler_fn)(LogLevel, int, const char *, void *);
    
    void     log_init(const char *, LogLevel, SyslogFacility, int);
    LogLevel log_level_get(void);
    int      log_change_level(LogLevel);
    int      log_is_on_stderr(void);
    void     log_redirect_stderr_to(const char *);
    void	 log_verbose_add(const char *);
    void	 log_verbose_reset(void);
    
    SyslogFacility	log_facility_number(char *);
    const char *	log_facility_name(SyslogFacility);
    LogLevel	log_level_number(char *);
    const char *	log_level_name(LogLevel);
    
    void	 set_log_handler(log_handler_fn *, void *);
    void	 cleanup_exit(int) __attribute__((noreturn));
    
    void	 sshlog(const char *, const char *, int, int,
        LogLevel, const char *, const char *, ...)
        __attribute__((format(printf, 7, 8)));
    void	 sshlogv(const char *, const char *, int, int,
        LogLevel, const char *, const char *, va_list);
    void	 sshlogdie(const char *, const char *, int, int,
        LogLevel, const char *, const char *, ...) __attribute__((noreturn))
        __attribute__((format(printf, 7, 8)));
    void	 sshfatal(const char *, const char *, int, int,
        LogLevel, const char *, const char *, ...) __attribute__((noreturn))
        __attribute__((format(printf, 7, 8)));
    void	 sshlogdirect(LogLevel, int, const char *, ...)
        __attribute__((format(printf, 3, 4)));
    
    struct log_ratelimit_ctx {
    	/* configuration */
    	u_int threshold;	/* events per second */
    	u_int max_accum;	/* max events to accumulate */
    	u_int hysteresis;	/* seconds */
    	u_int log_every;	/* seconds */
    
    	/* state */
    	time_t last_event;
    	u_int accumulated_events; /* used for threshold comparisons */
    
    	/* state while actively rate-limiting */
    	int ratelimit_active;
    	time_t ratelimit_start;
    	time_t last_log;
    	time_t hysteresis_start;
    	u_int ratelimited_events;
    };
    
    void log_ratelimit_init(struct log_ratelimit_ctx *rl, u_int threshold,
        u_int max_accum, u_int hysteresis, u_int log_every);
    int log_ratelimit(struct log_ratelimit_ctx *rl, time_t now, int *active,
        u_int *events_dropped);
    
    #define do_log2(level, ...)	sshlog(__FILE__, __func__, __LINE__, 0, level, NULL, __VA_ARGS__)
    #define debug3(...)		sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG3, NULL, __VA_ARGS__)
    #define debug2(...)		sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG2, NULL, __VA_ARGS__)
    #define debug(...)		sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG1, NULL, __VA_ARGS__)
    #define verbose(...)		sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_VERBOSE, NULL, __VA_ARGS__)
    #define logit(...)		sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_INFO, NULL, __VA_ARGS__)
    #define error(...)		sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__)
    #define fatal(...)		sshfatal(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_FATAL, NULL, __VA_ARGS__)
    #define logdie(...)		sshlogdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__)
    
    /* Variants that prepend the caller's function */
    #define do_log2_f(level, ...)	sshlog(__FILE__, __func__, __LINE__, 1, level, NULL, __VA_ARGS__)
    #define debug3_f(...)		sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG3, NULL, __VA_ARGS__)
    #define debug2_f(...)		sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG2, NULL, __VA_ARGS__)
    #define debug_f(...)		sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG1, NULL, __VA_ARGS__)
    #define verbose_f(...)		sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_VERBOSE, NULL, __VA_ARGS__)
    #define logit_f(...)		sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_INFO, NULL, __VA_ARGS__)
    #define error_f(...)		sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__)
    #define fatal_f(...)		sshfatal(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_FATAL, NULL, __VA_ARGS__)
    #define logdie_f(...)		sshlogdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__)
    
    /* Variants that appends a ssh_err message */
    #define do_log2_r(r, level, ...) sshlog(__FILE__, __func__, __LINE__, 0, level, ssh_err(r), __VA_ARGS__)
    #define debug3_r(r, ...)	sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG3, ssh_err(r), __VA_ARGS__)
    #define debug2_r(r, ...)	sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG2, ssh_err(r), __VA_ARGS__)
    #define debug_r(r, ...)		sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG1, ssh_err(r), __VA_ARGS__)
    #define verbose_r(r, ...)	sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_VERBOSE, ssh_err(r), __VA_ARGS__)
    #define logit_r(r, ...)		sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_INFO, ssh_err(r), __VA_ARGS__)
    #define error_r(r, ...)		sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__)
    #define fatal_r(r, ...)		sshfatal(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), __VA_ARGS__)
    #define logdie_r(r, ...)	sshlogdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__)
    #define do_log2_fr(r, level, ...) sshlog(__FILE__, __func__, __LINE__, 1, level, ssh_err(r), __VA_ARGS__)
    #define debug3_fr(r, ...)	sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG3, ssh_err(r), __VA_ARGS__)
    #define debug2_fr(r, ...)	sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG2, ssh_err(r), __VA_ARGS__)
    #define debug_fr(r, ...)	sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG1, ssh_err(r), __VA_ARGS__)
    #define verbose_fr(r, ...)	sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_VERBOSE, ssh_err(r), __VA_ARGS__)
    #define logit_fr(r, ...)	sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_INFO, ssh_err(r), __VA_ARGS__)
    #define error_fr(r, ...)	sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__)
    #define fatal_fr(r, ...)	sshfatal(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), __VA_ARGS__)
    #define logdie_fr(r, ...)	sshlogdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__)
    
    #endif