Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

syslog.c

Go to the documentation of this file.
00001 /* $Id$ */
00002 /* -/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/-/
00003  . Copyright (c) 2001 Michael Davis <mike@datanerds.net>
00004  . All rights reserved.
00005  .
00006  . Redistribution and use in source and binary forms, with or without
00007  . modification, are permitted provided that the following conditions
00008  . are met:
00009  .
00010  . 1. Redistributions of source code must retain the above copyright
00011  .    notice, this list of conditions and the following disclaimer.
00012  .
00013  . 2. Redistributions in binary form must reproduce the above copyright
00014  .    notice, this list of conditions and the following disclaimer in the
00015  .    documentation and/or other materials provided with the distribution.
00016  .
00017  . 3. The name of author may not be used to endorse or promote products
00018  .    derived from this software without specific prior written permission.
00019  .
00020  . THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
00021  . INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00022  . AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
00023  . THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00024  . EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00025  . PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00026  . OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00027  . WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00028  . OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00029  . ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030  . -\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\ */
00031 
00032 #define _WINSOCKAPI_   /* Prevent inclusion of winsock.h in windows.h */
00033 #include <windows.h>
00034 #include <stdio.h>
00035 #include <time.h>
00036 #include "name.h"
00037 #include "syslog.h"
00038 
00039 #include "snort.h"
00040 #include "util.h"
00041 
00042 #define TBUF_LEN        2048
00043 #define FMT_LEN         1024
00044 #define INTERNALLOG     LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
00045 
00046 static int      LogFile = -1;           /* fd for log */
00047 static int      opened;                 /* have done openlog() */
00048 static int      LogStat = 0;            /* status bits, set by openlog() */
00049 static char *LogTag = NULL;       /* string to tag the entry with */
00050 static int      LogFacility = LOG_USER; /* default facility code */
00051 static int      LogMask = 0xff;         /* mask of priorities to be logged */
00052 
00053 void syslog(int pri, char *fmt, ...)
00054 {
00055         va_list ap;
00056         va_start(ap, fmt);
00057         vsyslog(pri, fmt, ap);
00058         va_end(ap);
00059 }
00060 
00061 void vsyslog(int pri, char *fmt, va_list ap){
00062         char ch, *p, *t;
00063         register int cnt;
00064         int tbuf_left, fmt_left, prlen, saved_errno;
00065         char *stdp, tbuf[TBUF_LEN], fmt_cpy[FMT_LEN];
00066     time_t now;
00067         SOCKET sockfd;
00068         struct sockaddr_in sin;
00069         HANDLE  hEventLog;                              /* handle to the Event Log. */
00070 
00071         if(!pv.syslog_remote_flag) { /* Log to Event Log. */
00072             p = tbuf;
00073             tbuf_left = TBUF_LEN;
00074 
00075             saved_errno = errno;
00076 
00077             /*
00078              * We wouldn't need this mess if printf handled %m, or if
00079              * strerror() had been invented before syslog().
00080              */
00081             for (t = fmt_cpy, fmt_left = FMT_LEN;
00082                  (ch = *fmt);
00083                  ++fmt)
00084             {
00085                     if (ch == '%' && fmt[1] == 'm') {
00086                             ++fmt;
00087                             prlen = _snprintf(t, fmt_left, "%s",
00088                                 strerror(saved_errno));
00089                             if (prlen >= fmt_left)
00090                                     prlen = fmt_left - 1;
00091                             t += prlen;
00092                             fmt_left -= prlen;
00093                     } else {
00094                             if (fmt_left > 1) {
00095                                     *t++ = ch;
00096                                     fmt_left--;
00097                             }
00098                     }
00099             }
00100             *t = '\0';
00101 
00102             _vsnprintf(p, tbuf_left, fmt_cpy, ap);
00103             
00104             /* Get connected, output the message to the local logger. */
00105             if (!opened)
00106                     openlog(LogTag, LogStat, 0);
00107 
00108         
00109                 hEventLog = RegisterEventSource(NULL, LogTag);
00110                 if (hEventLog == NULL)
00111                         return;
00112 
00113                 /* Now, actually report it. */
00114                 ReportEvent( hEventLog
00115                    , EVENTLOG_INFORMATION_TYPE
00116                    , 0
00117                    , EVMSG_SIMPLE
00118                    , NULL
00119                    , 1
00120                    , 0
00121                    , (char **)&p
00122                    , NULL);
00123                 DeregisterEventSource(hEventLog);
00124 
00125                 return;
00126         }
00127         
00128     /* Check for invalid bits. */
00129     if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
00130             syslog(INTERNALLOG,
00131                 "syslog: unknown facility/priority: %x", pri);
00132             pri &= LOG_PRIMASK|LOG_FACMASK;
00133     }
00134 
00135     /* Check priority against setlogmask values. */
00136     if (!(LOG_MASK(LOG_PRI(pri)) & LogMask))
00137             return;
00138 
00139     saved_errno = errno;
00140 
00141     /* Set default facility if none specified. */
00142     if ((pri & LOG_FACMASK) == 0)
00143             pri |= LogFacility;
00144 
00145     /* Build the message. */
00146 
00147     /*
00148      * Although it's tempting, we can't ignore the possibility of
00149      * overflowing the buffer when assembling the "fixed" portion
00150      * of the message.  Strftime's "%h" directive expands to the
00151      * locale's abbreviated month name, but if the user has the
00152      * ability to construct to his own locale files, it may be
00153      * arbitrarily long.
00154      */
00155     (void)time(&now);
00156 
00157     p = tbuf;
00158     tbuf_left = TBUF_LEN;
00159 
00160 #define DEC()   \
00161         do {                                    \
00162                 if (prlen >= tbuf_left)         \
00163                         prlen = tbuf_left - 1;  \
00164                 p += prlen;                     \
00165                 tbuf_left -= prlen;             \
00166         } while (0)
00167 
00168     prlen = snprintf(p, tbuf_left, "<%d>", pri);
00169     DEC();
00170 
00171     prlen = strftime(p, tbuf_left, "%h %e %T ", localtime(&now));
00172     DEC();
00173 
00174     if (LogStat & LOG_PERROR)
00175             stdp = p;
00176     if (LogTag == NULL)
00177             LogTag = VERSION;
00178     if (LogTag != NULL) {
00179             prlen = snprintf(p, tbuf_left, "%s", LogTag);
00180             DEC();
00181     }
00182     if (LogStat & LOG_PID) {
00183             prlen = snprintf(p, tbuf_left, "[%d]", getpid());
00184             DEC();
00185     }
00186     if (LogTag != NULL) {
00187             if (tbuf_left > 1) {
00188                     *p++ = ':';
00189                     tbuf_left--;
00190             }
00191             if (tbuf_left > 1) {
00192                     *p++ = ' ';
00193                     tbuf_left--;
00194             }
00195     }
00196 
00197     /*
00198      * We wouldn't need this mess if printf handled %m, or if
00199      * strerror() had been invented before syslog().
00200      */
00201     for (t = fmt_cpy, fmt_left = FMT_LEN; (ch = *fmt); ++fmt) {
00202             if (ch == '%' && fmt[1] == 'm') {
00203                     ++fmt;
00204                     prlen = snprintf(t, fmt_left, "%s",
00205                         strerror(saved_errno));
00206                     if (prlen >= fmt_left)
00207                             prlen = fmt_left - 1;
00208                     t += prlen;
00209                     fmt_left -= prlen;
00210             } else {
00211                     if (fmt_left > 1) {
00212                             *t++ = ch;
00213                             fmt_left--;
00214                     }
00215             }
00216     }
00217     *t = '\0';
00218 
00219     prlen = vsnprintf(p, tbuf_left, fmt_cpy, ap);
00220     DEC();
00221     cnt = p - tbuf;
00222 
00223         /* Connect to Target server. */
00224         if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == SOCKET_ERROR){
00225                 ErrorMessage("[!] ERROR: Could not create the socket to send the syslog alert. Error Number: %d.\n", WSAGetLastError());        
00226                 return;
00227         }
00228 
00229         sin.sin_port = htons((u_short)pv.syslog_server_port);
00230         sin.sin_family = AF_INET;
00231 
00232         if (!(sin.sin_addr.s_addr = resolve_host(pv.syslog_server))){
00233                 ErrorMessage("[!] ERROR: Could not resolve syslog server's hostname. Error Number: %d.\n", WSAGetLastError());          
00234                 closesocket(sockfd);
00235                 return;
00236         }
00237 
00238         if(sendto(sockfd,tbuf,cnt,(int)NULL, (SOCKADDR *)&sin, sizeof(SOCKADDR_IN)) == SOCKET_ERROR) {
00239                 ErrorMessage("[!] ERROR: Could not send the alert to the syslog server. Error Number: %d.\n", WSAGetLastError());               
00240                 closesocket(sockfd);
00241                 return;
00242         }
00243 
00244         closesocket(sockfd);
00245 }
00246 
00247 void openlog(char *ident, int logstat, int logfac){
00248 
00249         if(ident != NULL){
00250                 LogTag = ident;
00251         LogStat = logstat;
00252                 if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
00253                 LogFacility = logfac;
00254 
00255             /* Add the registry key each time openlog is called. */
00256             AddEventSource(ident);
00257         }
00258         opened = 1;
00259 }
00260 
00261 /* Taken from MSDN. */
00262 void AddEventSource(char *ident)
00263 {
00264     HKEY hk; 
00265     DWORD dwData; 
00266     char szFilePath[_MAX_PATH];
00267         char key[_MAX_PATH];
00268         
00269     // Add your source name as a subkey under the Application 
00270     // key in the EventLog registry key. 
00271     _snprintf(key, sizeof(key), "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s", ident);
00272 
00273     if (RegCreateKey(HKEY_LOCAL_MACHINE, key, &hk)) {
00274                 printf("Could not create the registry key."); 
00275                 exit(-1);
00276         }
00277  
00278     // Set the name of the message file. 
00279         GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
00280     // Add the name to the EventMessageFile subkey. 
00281  
00282     if (RegSetValueEx(hk,             // subkey handle 
00283             "EventMessageFile",       // value name 
00284             0,                        // must be zero 
00285             REG_EXPAND_SZ,            // value type 
00286             (LPBYTE) szFilePath,           // pointer to value data 
00287             strlen(szFilePath) + 1)) {       // length of value data 
00288         printf("Could not set the event message file."); 
00289                 exit(-1);
00290         }
00291  
00292     // Set the supported event types in the TypesSupported subkey. 
00293  
00294     dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | 
00295         EVENTLOG_INFORMATION_TYPE | EVENTLOG_AUDIT_SUCCESS | EVENTLOG_AUDIT_FAILURE; 
00296  
00297     if (RegSetValueEx(hk,      // subkey handle 
00298             "TypesSupported",  // value name 
00299             0,                 // must be zero 
00300             REG_DWORD,         // value type 
00301             (LPBYTE) &dwData,  // pointer to value data 
00302             sizeof(DWORD))){    // length of value data 
00303         printf("Could not set the supported types."); 
00304                 exit(-1);
00305         }
00306  
00307     RegCloseKey(hk); 
00308 } 
00309 
00310 unsigned long resolve_host(char *host) {
00311     struct hostent *he;
00312     unsigned long ip;
00313     
00314     if (inet_addr(host) == INADDR_NONE)
00315     {
00316         he = gethostbyname(host);
00317         if (!he)
00318         {
00319             printf("Unable to resolve address: %s", host);
00320             return 0;
00321         }
00322         else
00323         {
00324             /* protecting against malicious DNS servers */
00325             if(he->h_length <= sizeof(unsigned long))
00326             {
00327                 memcpy((char FAR *)&(ip), he->h_addr, he->h_length);
00328             }
00329             else
00330             {
00331                 memcpy((char FAR *)&(ip), he->h_addr, sizeof(unsigned long));
00332             }
00333         }
00334     } else {
00335         ip = inet_addr(host);
00336     }
00337     
00338     return ip;
00339 }

Generated on Sun May 14 14:51:19 2006 by  doxygen 1.4.2