xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/roken/syslogc.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
1 /*	$NetBSD: syslogc.c,v 1.2 2017/01/28 21:31:50 christos Exp $	*/
2 
3 /***********************************************************************
4  * Copyright (c) 2009, Secure Endpoints Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * - Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  *
14  * - Redistributions in binary form must reproduce the above copyright
15  *   notice, this list of conditions and the following disclaimer in
16  *   the documentation and/or other materials provided with the
17  *   distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30  * OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  **********************************************************************/
33 
34 /*
35  * Based on code by Alexander Yaworsky
36  */
37 
38 #include <config.h>
39 
40 #include <krb5/roken.h>
41 
42 #define SYSLOG_DGRAM_SIZE 1024
43 
44 static BOOL        syslog_opened = FALSE;
45 
46 static int         syslog_mask = 0xFF;
47 static char        syslog_ident[ 128 ] = "";
48 static int         syslog_facility = LOG_USER;
49 static char        syslog_procid_str[ 20 ];
50 
51 static SOCKADDR_IN syslog_hostaddr;
52 static SOCKET      syslog_socket = INVALID_SOCKET;
53 static char        local_hostname[ MAX_COMPUTERNAME_LENGTH + 1 ];
54 
55 static char        syslog_hostname[ MAX_COMPUTERNAME_LENGTH + 1 ] = "localhost";
56 static unsigned short syslog_port = SYSLOG_PORT;
57 
58 static int   datagramm_size;
59 
60 volatile BOOL initialized = FALSE;
61 BOOL wsa_initialized = FALSE;
62 CRITICAL_SECTION cs_syslog;
63 
64 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
init_syslog(const char * hostname)65 init_syslog(const char * hostname)
66 {
67     WSADATA wsd;
68     char * service;
69 
70     if ( initialized )
71         return;
72 
73     if( WSAStartup( MAKEWORD( 2, 2 ), &wsd ) ) {
74         fprintf(stderr, "Can't initialize WinSock\n");
75         /* we let the rest of the initialization code go through,
76            although none of the syslog calls would succeed. */
77     } else {
78         wsa_initialized = TRUE;
79     }
80 
81     if (hostname)
82         strcpy_s(syslog_hostname, sizeof(syslog_hostname), hostname);
83     else
84         strcpy_s(syslog_hostname, sizeof(syslog_hostname), "");
85 
86     service = strchr(syslog_hostname, ':');
87 
88     if (service) {
89         int tp;
90 
91         *service++ = '\0';
92 
93         if ((tp = atoi(service)) <= 0) {
94             struct servent * se;
95 
96             se = getservbyname(service, "udp");
97 
98             syslog_port = (se == NULL)? SYSLOG_PORT: se->s_port;
99         } else {
100             syslog_port = (unsigned short) tp;
101         }
102     } else {
103         syslog_port = SYSLOG_PORT;
104     }
105 
106     InitializeCriticalSection(&cs_syslog);
107     initialized = TRUE;
108 
109     atexit(exit_syslog);
110 }
111 
112 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
exit_syslog(void)113 exit_syslog(void)
114 {
115     if ( !initialized )
116         return;
117 
118     closelog();
119 
120     if ( wsa_initialized )
121         WSACleanup();
122 
123     DeleteCriticalSection(&cs_syslog);
124     initialized = FALSE;
125 }
126 
init_logger_addr()127 static void init_logger_addr()
128 {
129     struct hostent * phe = NULL;
130 
131     memset( &syslog_hostaddr, 0, sizeof(SOCKADDR_IN) );
132     syslog_hostaddr.sin_family = AF_INET;
133 
134     if (syslog_hostname[0] == '\0')
135         goto use_default;
136 
137     phe = gethostbyname( syslog_hostname );
138     if( !phe )
139         goto use_default;
140 
141     memcpy( &syslog_hostaddr.sin_addr.s_addr, phe->h_addr, phe->h_length );
142 
143     syslog_hostaddr.sin_port = htons( syslog_port );
144     return;
145 
146 use_default:
147     syslog_hostaddr.sin_addr.S_un.S_addr = htonl( 0x7F000001 );
148     syslog_hostaddr.sin_port = htons( SYSLOG_PORT );
149 }
150 
151 /******************************************************************************
152  * closelog
153  *
154  * Close desriptor used to write to system logger.
155  */
156 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
closelog()157 closelog()
158 {
159     if ( !initialized )
160         return;
161 
162     EnterCriticalSection(&cs_syslog);
163     if( syslog_opened ) {
164         closesocket( syslog_socket );
165         syslog_socket = INVALID_SOCKET;
166         syslog_opened = FALSE;
167     }
168     LeaveCriticalSection(&cs_syslog);
169 }
170 
171 /******************************************************************************
172  * openlog
173  *
174  * Open connection to system logger.
175  */
176 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
openlog(char * ident,int option,int facility)177 openlog( char* ident, int option, int facility )
178 {
179     BOOL failed = FALSE;
180     SOCKADDR_IN sa_local;
181     DWORD n;
182     int size;
183 
184     if ( !initialized )
185         return;
186 
187     EnterCriticalSection(&cs_syslog);
188 
189     if( syslog_opened )
190         goto done;
191 
192     failed = TRUE;
193 
194     syslog_facility = facility? facility : LOG_USER;
195 
196     if( option & LOG_PID )
197         sprintf_s( syslog_procid_str, sizeof(syslog_procid_str), "[%lu]", GetCurrentProcessId() );
198     else
199         syslog_procid_str[0] = '\0';
200 
201     /* FIXME: handle other options */
202 
203     n = sizeof(local_hostname);
204     if( !GetComputerName( local_hostname, &n ) )
205         goto done;
206 
207     syslog_socket = INVALID_SOCKET;
208 
209     init_logger_addr();
210 
211     for( n = 0;; n++ )
212     {
213         syslog_socket = socket( AF_INET, SOCK_DGRAM, 0 );
214         if( INVALID_SOCKET == syslog_socket )
215             goto done;
216 
217         memset( &sa_local, 0, sizeof(SOCKADDR_IN) );
218         sa_local.sin_family = AF_INET;
219         if( bind( syslog_socket, (SOCKADDR*) &sa_local, sizeof(SOCKADDR_IN) ) == 0 )
220             break;
221         rk_closesocket( syslog_socket );
222         syslog_socket = INVALID_SOCKET;
223         if( n == 100 )
224             goto done;
225         Sleep(0);
226     }
227 
228     /* get size of datagramm */
229     size = sizeof(datagramm_size);
230     if( getsockopt( syslog_socket, SOL_SOCKET, SO_MAX_MSG_SIZE, (char*) &datagramm_size, &size ) )
231         goto done;
232     if( datagramm_size - strlen(local_hostname) - (ident? strlen(ident) : 0) < 64 )
233         goto done;
234     if( datagramm_size > SYSLOG_DGRAM_SIZE )
235         datagramm_size = SYSLOG_DGRAM_SIZE;
236 
237     if (ident)
238         strcpy_s(syslog_ident, sizeof(syslog_ident), ident);
239 
240     syslog_facility = (facility ? facility : LOG_USER);
241     failed = FALSE;
242 
243  done:
244     if( failed ) {
245         if( syslog_socket != INVALID_SOCKET )
246             rk_closesocket( syslog_socket );
247     }
248     syslog_opened = !failed;
249 
250     LeaveCriticalSection(&cs_syslog);
251 }
252 
253 /******************************************************************************
254  * setlogmask
255  *
256  * Set the log mask level.
257  */
258 ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
setlogmask(int mask)259 setlogmask( int mask )
260 {
261     int ret;
262 
263     if ( !initialized )
264         return 0;
265 
266     EnterCriticalSection(&cs_syslog);
267 
268     ret = syslog_mask;
269     if( mask )
270         syslog_mask = mask;
271 
272     LeaveCriticalSection(&cs_syslog);
273 
274     return ret;
275 }
276 
277 /******************************************************************************
278  * syslog
279  *
280  * Generate a log message using FMT string and option arguments.
281  */
282 ROKEN_LIB_FUNCTION void
syslog(int pri,char * fmt,...)283 syslog( int pri, char* fmt, ... )
284 {
285     va_list ap;
286 
287     va_start( ap, fmt );
288     vsyslog( pri, fmt, ap );
289     va_end( ap );
290 }
291 
292 /******************************************************************************
293  * vsyslog
294  *
295  * Generate a log message using FMT and using arguments pointed to by AP.
296  */
297 ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
vsyslog(int pri,char * fmt,va_list ap)298 vsyslog( int pri, char* fmt, va_list ap )
299 {
300     static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
301                             "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
302     char  datagramm[ SYSLOG_DGRAM_SIZE ];
303     SYSTEMTIME stm;
304     int len;
305     char *p;
306 
307     if ( !initialized )
308         return;
309 
310     EnterCriticalSection(&cs_syslog);
311 
312     if( !(LOG_MASK( LOG_PRI( pri )) & syslog_mask) )
313         goto done;
314 
315     openlog( NULL, 0, pri & LOG_FACMASK );
316     if( !syslog_opened )
317         goto done;
318 
319     if( !(pri & LOG_FACMASK) )
320         pri |= syslog_facility;
321 
322     GetLocalTime( &stm );
323     len = sprintf_s( datagramm, sizeof(datagramm),
324                      "<%d>%s %2d %02d:%02d:%02d %s %s%s: ",
325                      pri,
326                      month[ stm.wMonth - 1 ], stm.wDay, stm.wHour, stm.wMinute, stm.wSecond,
327                      local_hostname, syslog_ident, syslog_procid_str );
328     vsprintf_s( datagramm + len, datagramm_size - len, fmt, ap );
329     p = strchr( datagramm, '\n' );
330     if( p )
331         *p = 0;
332     p = strchr( datagramm, '\r' );
333     if( p )
334         *p = 0;
335 
336     sendto( syslog_socket, datagramm, strlen(datagramm), 0, (SOCKADDR*) &syslog_hostaddr, sizeof(SOCKADDR_IN) );
337 
338  done:
339     LeaveCriticalSection(&cs_syslog);
340 }
341 
342