Avoid negative array index in BIO_debug_callback()
[openssl.git] / crypto / bio / bss_log.c
1 /* ====================================================================
2  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * 3. All advertising materials mentioning features or use of this
17  *    software must display the following acknowledgment:
18  *    "This product includes software developed by the OpenSSL Project
19  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
20  *
21  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22  *    endorse or promote products derived from this software without
23  *    prior written permission. For written permission, please contact
24  *    licensing@OpenSSL.org.
25  *
26  * 5. Products derived from this software may not be called "OpenSSL"
27  *    nor may "OpenSSL" appear in their names without prior written
28  *    permission of the OpenSSL Project.
29  *
30  * 6. Redistributions of any form whatsoever must retain the following
31  *    acknowledgment:
32  *    "This product includes software developed by the OpenSSL Project
33  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46  * OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This product includes cryptographic software written by Eric Young
50  * (eay@cryptsoft.com).  This product includes software written by Tim
51  * Hudson (tjh@cryptsoft.com).
52  *
53  */
54
55 /*
56  * Why BIO_s_log?
57  *
58  * BIO_s_log is useful for system daemons (or services under NT). It is
59  * one-way BIO, it sends all stuff to syslogd (on system that commonly use
60  * that), or event log (on NT), or OPCOM (on OpenVMS).
61  *
62  */
63
64 #include <stdio.h>
65 #include <errno.h>
66
67 #include "internal/cryptlib.h"
68
69 #if defined(OPENSSL_SYS_WINCE)
70 #elif defined(OPENSSL_SYS_WIN32)
71 #elif defined(OPENSSL_SYS_VMS)
72 # include <opcdef.h>
73 # include <descrip.h>
74 # include <lib$routines.h>
75 # include <starlet.h>
76 /* Some compiler options may mask the declaration of "_malloc32". */
77 # if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE
78 #  if __INITIAL_POINTER_SIZE == 64
79 #   pragma pointer_size save
80 #   pragma pointer_size 32
81 void *_malloc32(__size_t);
82 #   pragma pointer_size restore
83 #  endif                        /* __INITIAL_POINTER_SIZE == 64 */
84 # endif                         /* __INITIAL_POINTER_SIZE && defined
85                                  * _ANSI_C_SOURCE */
86 #elif defined(__ultrix)
87 # include <sys/syslog.h>
88 #elif defined(OPENSSL_SYS_NETWARE)
89 # define NO_SYSLOG
90 #elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG)
91 # include <syslog.h>
92 #endif
93
94 #include <openssl/buffer.h>
95 #include <openssl/err.h>
96
97 #ifndef NO_SYSLOG
98
99 # if defined(OPENSSL_SYS_WIN32)
100 #  define LOG_EMERG       0
101 #  define LOG_ALERT       1
102 #  define LOG_CRIT        2
103 #  define LOG_ERR         3
104 #  define LOG_WARNING     4
105 #  define LOG_NOTICE      5
106 #  define LOG_INFO        6
107 #  define LOG_DEBUG       7
108
109 #  define LOG_DAEMON      (3<<3)
110 # elif defined(OPENSSL_SYS_VMS)
111 /* On VMS, we don't really care about these, but we need them to compile */
112 #  define LOG_EMERG       0
113 #  define LOG_ALERT       1
114 #  define LOG_CRIT        2
115 #  define LOG_ERR         3
116 #  define LOG_WARNING     4
117 #  define LOG_NOTICE      5
118 #  define LOG_INFO        6
119 #  define LOG_DEBUG       7
120
121 #  define LOG_DAEMON      OPC$M_NM_NTWORK
122 # endif
123
124 static int slg_write(BIO *h, const char *buf, int num);
125 static int slg_puts(BIO *h, const char *str);
126 static long slg_ctrl(BIO *h, int cmd, long arg1, void *arg2);
127 static int slg_new(BIO *h);
128 static int slg_free(BIO *data);
129 static void xopenlog(BIO *bp, char *name, int level);
130 static void xsyslog(BIO *bp, int priority, const char *string);
131 static void xcloselog(BIO *bp);
132
133 static BIO_METHOD methods_slg = {
134     BIO_TYPE_MEM, "syslog",
135     slg_write,
136     NULL,
137     slg_puts,
138     NULL,
139     slg_ctrl,
140     slg_new,
141     slg_free,
142     NULL,
143 };
144
145 BIO_METHOD *BIO_s_log(void)
146 {
147     return (&methods_slg);
148 }
149
150 static int slg_new(BIO *bi)
151 {
152     bi->init = 1;
153     bi->num = 0;
154     bi->ptr = NULL;
155     xopenlog(bi, "application", LOG_DAEMON);
156     return (1);
157 }
158
159 static int slg_free(BIO *a)
160 {
161     if (a == NULL)
162         return (0);
163     xcloselog(a);
164     return (1);
165 }
166
167 static int slg_write(BIO *b, const char *in, int inl)
168 {
169     int ret = inl;
170     char *buf;
171     char *pp;
172     int priority, i;
173     static const struct {
174         int strl;
175         char str[10];
176         int log_level;
177     } mapping[] = {
178         {
179             6, "PANIC ", LOG_EMERG
180         },
181         {
182             6, "EMERG ", LOG_EMERG
183         },
184         {
185             4, "EMR ", LOG_EMERG
186         },
187         {
188             6, "ALERT ", LOG_ALERT
189         },
190         {
191             4, "ALR ", LOG_ALERT
192         },
193         {
194             5, "CRIT ", LOG_CRIT
195         },
196         {
197             4, "CRI ", LOG_CRIT
198         },
199         {
200             6, "ERROR ", LOG_ERR
201         },
202         {
203             4, "ERR ", LOG_ERR
204         },
205         {
206             8, "WARNING ", LOG_WARNING
207         },
208         {
209             5, "WARN ", LOG_WARNING
210         },
211         {
212             4, "WAR ", LOG_WARNING
213         },
214         {
215             7, "NOTICE ", LOG_NOTICE
216         },
217         {
218             5, "NOTE ", LOG_NOTICE
219         },
220         {
221             4, "NOT ", LOG_NOTICE
222         },
223         {
224             5, "INFO ", LOG_INFO
225         },
226         {
227             4, "INF ", LOG_INFO
228         },
229         {
230             6, "DEBUG ", LOG_DEBUG
231         },
232         {
233             4, "DBG ", LOG_DEBUG
234         },
235         {
236             0, "", LOG_ERR
237         }
238         /* The default */
239     };
240
241     if ((buf = OPENSSL_malloc(inl + 1)) == NULL) {
242         return (0);
243     }
244     strncpy(buf, in, inl);
245     buf[inl] = '\0';
246
247     i = 0;
248     while (strncmp(buf, mapping[i].str, mapping[i].strl) != 0)
249         i++;
250     priority = mapping[i].log_level;
251     pp = buf + mapping[i].strl;
252
253     xsyslog(b, priority, pp);
254
255     OPENSSL_free(buf);
256     return (ret);
257 }
258
259 static long slg_ctrl(BIO *b, int cmd, long num, void *ptr)
260 {
261     switch (cmd) {
262     case BIO_CTRL_SET:
263         xcloselog(b);
264         xopenlog(b, ptr, num);
265         break;
266     default:
267         break;
268     }
269     return (0);
270 }
271
272 static int slg_puts(BIO *bp, const char *str)
273 {
274     int n, ret;
275
276     n = strlen(str);
277     ret = slg_write(bp, str, n);
278     return (ret);
279 }
280
281 # if defined(OPENSSL_SYS_WIN32)
282
283 static void xopenlog(BIO *bp, char *name, int level)
284 {
285     if (check_winnt())
286         bp->ptr = RegisterEventSourceA(NULL, name);
287     else
288         bp->ptr = NULL;
289 }
290
291 static void xsyslog(BIO *bp, int priority, const char *string)
292 {
293     LPCSTR lpszStrings[2];
294     WORD evtype = EVENTLOG_ERROR_TYPE;
295     char pidbuf[DECIMAL_SIZE(DWORD) + 4];
296
297     if (bp->ptr == NULL)
298         return;
299
300     switch (priority) {
301     case LOG_EMERG:
302     case LOG_ALERT:
303     case LOG_CRIT:
304     case LOG_ERR:
305         evtype = EVENTLOG_ERROR_TYPE;
306         break;
307     case LOG_WARNING:
308         evtype = EVENTLOG_WARNING_TYPE;
309         break;
310     case LOG_NOTICE:
311     case LOG_INFO:
312     case LOG_DEBUG:
313         evtype = EVENTLOG_INFORMATION_TYPE;
314         break;
315     default:
316         /*
317          * Should never happen, but set it
318          * as error anyway.
319          */
320         evtype = EVENTLOG_ERROR_TYPE;
321         break;
322     }
323
324     sprintf(pidbuf, "[%lu] ", GetCurrentProcessId());
325     lpszStrings[0] = pidbuf;
326     lpszStrings[1] = string;
327
328     ReportEventA(bp->ptr, evtype, 0, 1024, NULL, 2, 0, lpszStrings, NULL);
329 }
330
331 static void xcloselog(BIO *bp)
332 {
333     if (bp->ptr)
334         DeregisterEventSource((HANDLE) (bp->ptr));
335     bp->ptr = NULL;
336 }
337
338 # elif defined(OPENSSL_SYS_VMS)
339
340 static int VMS_OPC_target = LOG_DAEMON;
341
342 static void xopenlog(BIO *bp, char *name, int level)
343 {
344     VMS_OPC_target = level;
345 }
346
347 static void xsyslog(BIO *bp, int priority, const char *string)
348 {
349     struct dsc$descriptor_s opc_dsc;
350
351 /* Arrange 32-bit pointer to opcdef buffer and malloc(), if needed. */
352 #  if __INITIAL_POINTER_SIZE == 64
353 #   pragma pointer_size save
354 #   pragma pointer_size 32
355 #   define OPCDEF_TYPE __char_ptr32
356 #   define OPCDEF_MALLOC _malloc32
357 #  else                         /* __INITIAL_POINTER_SIZE == 64 */
358 #   define OPCDEF_TYPE char *
359 #   define OPCDEF_MALLOC OPENSSL_malloc
360 #  endif                        /* __INITIAL_POINTER_SIZE == 64 [else] */
361
362     struct opcdef *opcdef_p;
363
364 #  if __INITIAL_POINTER_SIZE == 64
365 #   pragma pointer_size restore
366 #  endif                        /* __INITIAL_POINTER_SIZE == 64 */
367
368     char buf[10240];
369     unsigned int len;
370     struct dsc$descriptor_s buf_dsc;
371     $DESCRIPTOR(fao_cmd, "!AZ: !AZ");
372     char *priority_tag;
373
374     switch (priority) {
375     case LOG_EMERG:
376         priority_tag = "Emergency";
377         break;
378     case LOG_ALERT:
379         priority_tag = "Alert";
380         break;
381     case LOG_CRIT:
382         priority_tag = "Critical";
383         break;
384     case LOG_ERR:
385         priority_tag = "Error";
386         break;
387     case LOG_WARNING:
388         priority_tag = "Warning";
389         break;
390     case LOG_NOTICE:
391         priority_tag = "Notice";
392         break;
393     case LOG_INFO:
394         priority_tag = "Info";
395         break;
396     case LOG_DEBUG:
397         priority_tag = "DEBUG";
398         break;
399     }
400
401     buf_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
402     buf_dsc.dsc$b_class = DSC$K_CLASS_S;
403     buf_dsc.dsc$a_pointer = buf;
404     buf_dsc.dsc$w_length = sizeof(buf) - 1;
405
406     lib$sys_fao(&fao_cmd, &len, &buf_dsc, priority_tag, string);
407
408     /* We know there's an 8-byte header.  That's documented. */
409     opcdef_p = OPCDEF_MALLOC(8 + len);
410     opcdef_p->opc$b_ms_type = OPC$_RQ_RQST;
411     memcpy(opcdef_p->opc$z_ms_target_classes, &VMS_OPC_target, 3);
412     opcdef_p->opc$l_ms_rqstid = 0;
413     memcpy(&opcdef_p->opc$l_ms_text, buf, len);
414
415     opc_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
416     opc_dsc.dsc$b_class = DSC$K_CLASS_S;
417     opc_dsc.dsc$a_pointer = (OPCDEF_TYPE) opcdef_p;
418     opc_dsc.dsc$w_length = len + 8;
419
420     sys$sndopr(opc_dsc, 0);
421
422     OPENSSL_free(opcdef_p);
423 }
424
425 static void xcloselog(BIO *bp)
426 {
427 }
428
429 # else                          /* Unix/Watt32 */
430
431 static void xopenlog(BIO *bp, char *name, int level)
432 {
433 #  ifdef WATT32                 /* djgpp/DOS */
434     openlog(name, LOG_PID | LOG_CONS | LOG_NDELAY, level);
435 #  else
436     openlog(name, LOG_PID | LOG_CONS, level);
437 #  endif
438 }
439
440 static void xsyslog(BIO *bp, int priority, const char *string)
441 {
442     syslog(priority, "%s", string);
443 }
444
445 static void xcloselog(BIO *bp)
446 {
447     closelog();
448 }
449
450 # endif                         /* Unix */
451
452 #endif                          /* NO_SYSLOG */