14ec2eca9Schristos /*
2*5b10f583Schristos  * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
3a89c9211Schristos  *
4*5b10f583Schristos  * Licensed under the Apache License 2.0 (the "License").  You may not use
54ec2eca9Schristos  * this file except in compliance with the License.  You can obtain a copy
64ec2eca9Schristos  * in the file LICENSE in the source distribution or at
74ec2eca9Schristos  * https://www.openssl.org/source/license.html
8a89c9211Schristos  */
9a89c9211Schristos 
10a89c9211Schristos /*
11d572d25fSspz  * Why BIO_s_log?
12d572d25fSspz  *
13d572d25fSspz  * BIO_s_log is useful for system daemons (or services under NT). It is
14d572d25fSspz  * one-way BIO, it sends all stuff to syslogd (on system that commonly use
15d572d25fSspz  * that), or event log (on NT), or OPCOM (on OpenVMS).
16d572d25fSspz  *
17a89c9211Schristos  */
18a89c9211Schristos 
19a89c9211Schristos #include <stdio.h>
20a89c9211Schristos #include <errno.h>
21a89c9211Schristos 
22cb006352Schristos #include "bio_local.h"
234ec2eca9Schristos #include "internal/cryptlib.h"
24a89c9211Schristos 
25a89c9211Schristos #if defined(OPENSSL_SYS_WINCE)
26a89c9211Schristos #elif defined(OPENSSL_SYS_WIN32)
27a89c9211Schristos #elif defined(OPENSSL_SYS_VMS)
28a89c9211Schristos # include <opcdef.h>
29a89c9211Schristos # include <descrip.h>
30a89c9211Schristos # include <lib$routines.h>
31a89c9211Schristos # include <starlet.h>
321e09c865Sspz /* Some compiler options may mask the declaration of "_malloc32". */
331e09c865Sspz # if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE
341e09c865Sspz #  if __INITIAL_POINTER_SIZE == 64
351e09c865Sspz #   pragma pointer_size save
361e09c865Sspz #   pragma pointer_size 32
371e09c865Sspz void *_malloc32(__size_t);
381e09c865Sspz #   pragma pointer_size restore
391e09c865Sspz #  endif                        /* __INITIAL_POINTER_SIZE == 64 */
40d572d25fSspz # endif                         /* __INITIAL_POINTER_SIZE && defined
41d572d25fSspz                                  * _ANSI_C_SOURCE */
42e7ccb6d1Schristos #elif defined(__DJGPP__) && defined(OPENSSL_NO_SOCK)
43a89c9211Schristos # define NO_SYSLOG
44a89c9211Schristos #elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG)
45a89c9211Schristos # include <syslog.h>
46a89c9211Schristos #endif
47a89c9211Schristos 
48a89c9211Schristos #include <openssl/buffer.h>
49a89c9211Schristos #include <openssl/err.h>
50a89c9211Schristos 
51a89c9211Schristos #ifndef NO_SYSLOG
52a89c9211Schristos 
53a89c9211Schristos # if defined(OPENSSL_SYS_WIN32)
54a89c9211Schristos #  define LOG_EMERG       0
55a89c9211Schristos #  define LOG_ALERT       1
56a89c9211Schristos #  define LOG_CRIT        2
57a89c9211Schristos #  define LOG_ERR         3
58a89c9211Schristos #  define LOG_WARNING     4
59a89c9211Schristos #  define LOG_NOTICE      5
60a89c9211Schristos #  define LOG_INFO        6
61a89c9211Schristos #  define LOG_DEBUG       7
62a89c9211Schristos 
63a89c9211Schristos #  define LOG_DAEMON      (3<<3)
64a89c9211Schristos # elif defined(OPENSSL_SYS_VMS)
65a89c9211Schristos /* On VMS, we don't really care about these, but we need them to compile */
66a89c9211Schristos #  define LOG_EMERG       0
67a89c9211Schristos #  define LOG_ALERT       1
68a89c9211Schristos #  define LOG_CRIT        2
69a89c9211Schristos #  define LOG_ERR         3
70a89c9211Schristos #  define LOG_WARNING     4
71a89c9211Schristos #  define LOG_NOTICE      5
72a89c9211Schristos #  define LOG_INFO        6
73a89c9211Schristos #  define LOG_DEBUG       7
74a89c9211Schristos 
75a89c9211Schristos #  define LOG_DAEMON      OPC$M_NM_NTWORK
76a89c9211Schristos # endif
77a89c9211Schristos 
784ec2eca9Schristos static int slg_write(BIO *h, const char *buf, int num);
794ec2eca9Schristos static int slg_puts(BIO *h, const char *str);
804ec2eca9Schristos static long slg_ctrl(BIO *h, int cmd, long arg1, void *arg2);
814ec2eca9Schristos static int slg_new(BIO *h);
824ec2eca9Schristos static int slg_free(BIO *data);
83a89c9211Schristos static void xopenlog(BIO *bp, char *name, int level);
84a89c9211Schristos static void xsyslog(BIO *bp, int priority, const char *string);
85a89c9211Schristos static void xcloselog(BIO *bp);
86a89c9211Schristos 
874ec2eca9Schristos static const BIO_METHOD methods_slg = {
883afa6631Schristos     BIO_TYPE_MEM,
893afa6631Schristos     "syslog",
90e7ccb6d1Schristos     bwrite_conv,
91a89c9211Schristos     slg_write,
92e7ccb6d1Schristos     NULL,                      /* slg_write_old,    */
933afa6631Schristos     NULL,                      /* slg_read,         */
94a89c9211Schristos     slg_puts,
95e7ccb6d1Schristos     NULL,
96a89c9211Schristos     slg_ctrl,
97a89c9211Schristos     slg_new,
98a89c9211Schristos     slg_free,
99062790c0Schristos     NULL,                      /* slg_callback_ctrl */
100a89c9211Schristos };
101a89c9211Schristos 
BIO_s_log(void)1024ec2eca9Schristos const BIO_METHOD *BIO_s_log(void)
103a89c9211Schristos {
104e7ccb6d1Schristos     return &methods_slg;
105a89c9211Schristos }
106a89c9211Schristos 
slg_new(BIO * bi)1074ec2eca9Schristos static int slg_new(BIO *bi)
108a89c9211Schristos {
109a89c9211Schristos     bi->init = 1;
110a89c9211Schristos     bi->num = 0;
111a89c9211Schristos     bi->ptr = NULL;
112a89c9211Schristos     xopenlog(bi, "application", LOG_DAEMON);
113e7ccb6d1Schristos     return 1;
114a89c9211Schristos }
115a89c9211Schristos 
slg_free(BIO * a)1164ec2eca9Schristos static int slg_free(BIO *a)
117a89c9211Schristos {
118d572d25fSspz     if (a == NULL)
119e7ccb6d1Schristos         return 0;
120a89c9211Schristos     xcloselog(a);
121e7ccb6d1Schristos     return 1;
122a89c9211Schristos }
123a89c9211Schristos 
slg_write(BIO * b,const char * in,int inl)1244ec2eca9Schristos static int slg_write(BIO *b, const char *in, int inl)
125a89c9211Schristos {
126a89c9211Schristos     int ret = inl;
127a89c9211Schristos     char *buf;
128a89c9211Schristos     char *pp;
129a89c9211Schristos     int priority, i;
130d572d25fSspz     static const struct {
131a89c9211Schristos         int strl;
132a89c9211Schristos         char str[10];
133a89c9211Schristos         int log_level;
134d572d25fSspz     } mapping[] = {
135a89c9211Schristos         {
136d572d25fSspz             6, "PANIC ", LOG_EMERG
137d572d25fSspz         },
138d572d25fSspz         {
139d572d25fSspz             6, "EMERG ", LOG_EMERG
140d572d25fSspz         },
141d572d25fSspz         {
142d572d25fSspz             4, "EMR ", LOG_EMERG
143d572d25fSspz         },
144d572d25fSspz         {
145d572d25fSspz             6, "ALERT ", LOG_ALERT
146d572d25fSspz         },
147d572d25fSspz         {
148d572d25fSspz             4, "ALR ", LOG_ALERT
149d572d25fSspz         },
150d572d25fSspz         {
151d572d25fSspz             5, "CRIT ", LOG_CRIT
152d572d25fSspz         },
153d572d25fSspz         {
154d572d25fSspz             4, "CRI ", LOG_CRIT
155d572d25fSspz         },
156d572d25fSspz         {
157d572d25fSspz             6, "ERROR ", LOG_ERR
158d572d25fSspz         },
159d572d25fSspz         {
160d572d25fSspz             4, "ERR ", LOG_ERR
161d572d25fSspz         },
162d572d25fSspz         {
163d572d25fSspz             8, "WARNING ", LOG_WARNING
164d572d25fSspz         },
165d572d25fSspz         {
166d572d25fSspz             5, "WARN ", LOG_WARNING
167d572d25fSspz         },
168d572d25fSspz         {
169d572d25fSspz             4, "WAR ", LOG_WARNING
170d572d25fSspz         },
171d572d25fSspz         {
172d572d25fSspz             7, "NOTICE ", LOG_NOTICE
173d572d25fSspz         },
174d572d25fSspz         {
175d572d25fSspz             5, "NOTE ", LOG_NOTICE
176d572d25fSspz         },
177d572d25fSspz         {
178d572d25fSspz             4, "NOT ", LOG_NOTICE
179d572d25fSspz         },
180d572d25fSspz         {
181d572d25fSspz             5, "INFO ", LOG_INFO
182d572d25fSspz         },
183d572d25fSspz         {
184d572d25fSspz             4, "INF ", LOG_INFO
185d572d25fSspz         },
186d572d25fSspz         {
187d572d25fSspz             6, "DEBUG ", LOG_DEBUG
188d572d25fSspz         },
189d572d25fSspz         {
190d572d25fSspz             4, "DBG ", LOG_DEBUG
191d572d25fSspz         },
192d572d25fSspz         {
193d572d25fSspz             0, "", LOG_ERR
194d572d25fSspz         }
195d572d25fSspz         /* The default */
196a89c9211Schristos     };
197a89c9211Schristos 
198*5b10f583Schristos     if (inl < 0)
199*5b10f583Schristos         return 0;
2004ec2eca9Schristos     if ((buf = OPENSSL_malloc(inl + 1)) == NULL) {
201*5b10f583Schristos         ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE);
202e7ccb6d1Schristos         return 0;
203a89c9211Schristos     }
20495661423Schristos     memcpy(buf, in, inl);
205a89c9211Schristos     buf[inl] = '\0';
206a89c9211Schristos 
207a89c9211Schristos     i = 0;
208d572d25fSspz     while (strncmp(buf, mapping[i].str, mapping[i].strl) != 0)
209d572d25fSspz         i++;
210a89c9211Schristos     priority = mapping[i].log_level;
211a89c9211Schristos     pp = buf + mapping[i].strl;
212a89c9211Schristos 
213a89c9211Schristos     xsyslog(b, priority, pp);
214a89c9211Schristos 
215a89c9211Schristos     OPENSSL_free(buf);
216e7ccb6d1Schristos     return ret;
217a89c9211Schristos }
218a89c9211Schristos 
slg_ctrl(BIO * b,int cmd,long num,void * ptr)2194ec2eca9Schristos static long slg_ctrl(BIO *b, int cmd, long num, void *ptr)
220a89c9211Schristos {
221d572d25fSspz     switch (cmd) {
222a89c9211Schristos     case BIO_CTRL_SET:
223a89c9211Schristos         xcloselog(b);
224a89c9211Schristos         xopenlog(b, ptr, num);
225a89c9211Schristos         break;
226a89c9211Schristos     default:
227a89c9211Schristos         break;
228a89c9211Schristos     }
229e7ccb6d1Schristos     return 0;
230a89c9211Schristos }
231a89c9211Schristos 
slg_puts(BIO * bp,const char * str)2324ec2eca9Schristos static int slg_puts(BIO *bp, const char *str)
233a89c9211Schristos {
234a89c9211Schristos     int n, ret;
235a89c9211Schristos 
236a89c9211Schristos     n = strlen(str);
237a89c9211Schristos     ret = slg_write(bp, str, n);
238e7ccb6d1Schristos     return ret;
239a89c9211Schristos }
240a89c9211Schristos 
241a89c9211Schristos # if defined(OPENSSL_SYS_WIN32)
242a89c9211Schristos 
xopenlog(BIO * bp,char * name,int level)243a89c9211Schristos static void xopenlog(BIO *bp, char *name, int level)
244a89c9211Schristos {
245a79d450bSchristos     if (check_winnt())
246a89c9211Schristos         bp->ptr = RegisterEventSourceA(NULL, name);
247a89c9211Schristos     else
248a89c9211Schristos         bp->ptr = NULL;
249a89c9211Schristos }
250a89c9211Schristos 
xsyslog(BIO * bp,int priority,const char * string)251a89c9211Schristos static void xsyslog(BIO *bp, int priority, const char *string)
252a89c9211Schristos {
253a89c9211Schristos     LPCSTR lpszStrings[2];
254a89c9211Schristos     WORD evtype = EVENTLOG_ERROR_TYPE;
255a89c9211Schristos     char pidbuf[DECIMAL_SIZE(DWORD) + 4];
256a89c9211Schristos 
257a89c9211Schristos     if (bp->ptr == NULL)
258a89c9211Schristos         return;
259a89c9211Schristos 
260d572d25fSspz     switch (priority) {
261a89c9211Schristos     case LOG_EMERG:
262a89c9211Schristos     case LOG_ALERT:
263a89c9211Schristos     case LOG_CRIT:
264a89c9211Schristos     case LOG_ERR:
265a89c9211Schristos         evtype = EVENTLOG_ERROR_TYPE;
266a89c9211Schristos         break;
267a89c9211Schristos     case LOG_WARNING:
268a89c9211Schristos         evtype = EVENTLOG_WARNING_TYPE;
269a89c9211Schristos         break;
270a89c9211Schristos     case LOG_NOTICE:
271a89c9211Schristos     case LOG_INFO:
272a89c9211Schristos     case LOG_DEBUG:
273a89c9211Schristos         evtype = EVENTLOG_INFORMATION_TYPE;
274a89c9211Schristos         break;
275d572d25fSspz     default:
276d572d25fSspz         /*
277d572d25fSspz          * Should never happen, but set it
278d572d25fSspz          * as error anyway.
279d572d25fSspz          */
280a89c9211Schristos         evtype = EVENTLOG_ERROR_TYPE;
281a89c9211Schristos         break;
282a89c9211Schristos     }
283a89c9211Schristos 
2842593478dSriastradh     sprintf(pidbuf, "[%u] ", GetCurrentProcessId());
285a89c9211Schristos     lpszStrings[0] = pidbuf;
286a89c9211Schristos     lpszStrings[1] = string;
287a89c9211Schristos 
288d572d25fSspz     ReportEventA(bp->ptr, evtype, 0, 1024, NULL, 2, 0, lpszStrings, NULL);
289a89c9211Schristos }
290a89c9211Schristos 
xcloselog(BIO * bp)291a89c9211Schristos static void xcloselog(BIO *bp)
292a89c9211Schristos {
293a89c9211Schristos     if (bp->ptr)
294a89c9211Schristos         DeregisterEventSource((HANDLE) (bp->ptr));
295a89c9211Schristos     bp->ptr = NULL;
296a89c9211Schristos }
297a89c9211Schristos 
298a89c9211Schristos # elif defined(OPENSSL_SYS_VMS)
299a89c9211Schristos 
300a89c9211Schristos static int VMS_OPC_target = LOG_DAEMON;
301a89c9211Schristos 
xopenlog(BIO * bp,char * name,int level)302a89c9211Schristos static void xopenlog(BIO *bp, char *name, int level)
303a89c9211Schristos {
304a89c9211Schristos     VMS_OPC_target = level;
305a89c9211Schristos }
306a89c9211Schristos 
xsyslog(BIO * bp,int priority,const char * string)307a89c9211Schristos static void xsyslog(BIO *bp, int priority, const char *string)
308a89c9211Schristos {
309a89c9211Schristos     struct dsc$descriptor_s opc_dsc;
3101e09c865Sspz 
3111e09c865Sspz /* Arrange 32-bit pointer to opcdef buffer and malloc(), if needed. */
3121e09c865Sspz #  if __INITIAL_POINTER_SIZE == 64
3131e09c865Sspz #   pragma pointer_size save
3141e09c865Sspz #   pragma pointer_size 32
3151e09c865Sspz #   define OPCDEF_TYPE __char_ptr32
3161e09c865Sspz #   define OPCDEF_MALLOC _malloc32
3171e09c865Sspz #  else                         /* __INITIAL_POINTER_SIZE == 64 */
3181e09c865Sspz #   define OPCDEF_TYPE char *
3191e09c865Sspz #   define OPCDEF_MALLOC OPENSSL_malloc
3201e09c865Sspz #  endif                        /* __INITIAL_POINTER_SIZE == 64 [else] */
3211e09c865Sspz 
322a89c9211Schristos     struct opcdef *opcdef_p;
3231e09c865Sspz 
3241e09c865Sspz #  if __INITIAL_POINTER_SIZE == 64
3251e09c865Sspz #   pragma pointer_size restore
3261e09c865Sspz #  endif                        /* __INITIAL_POINTER_SIZE == 64 */
3271e09c865Sspz 
328a89c9211Schristos     char buf[10240];
329a89c9211Schristos     unsigned int len;
330a89c9211Schristos     struct dsc$descriptor_s buf_dsc;
331a89c9211Schristos     $DESCRIPTOR(fao_cmd, "!AZ: !AZ");
332a89c9211Schristos     char *priority_tag;
333a89c9211Schristos 
334d572d25fSspz     switch (priority) {
335d572d25fSspz     case LOG_EMERG:
336d572d25fSspz         priority_tag = "Emergency";
337d572d25fSspz         break;
338d572d25fSspz     case LOG_ALERT:
339d572d25fSspz         priority_tag = "Alert";
340d572d25fSspz         break;
341d572d25fSspz     case LOG_CRIT:
342d572d25fSspz         priority_tag = "Critical";
343d572d25fSspz         break;
344d572d25fSspz     case LOG_ERR:
345d572d25fSspz         priority_tag = "Error";
346d572d25fSspz         break;
347d572d25fSspz     case LOG_WARNING:
348d572d25fSspz         priority_tag = "Warning";
349d572d25fSspz         break;
350d572d25fSspz     case LOG_NOTICE:
351d572d25fSspz         priority_tag = "Notice";
352d572d25fSspz         break;
353d572d25fSspz     case LOG_INFO:
354d572d25fSspz         priority_tag = "Info";
355d572d25fSspz         break;
356d572d25fSspz     case LOG_DEBUG:
357d572d25fSspz         priority_tag = "DEBUG";
358d572d25fSspz         break;
359a89c9211Schristos     }
360a89c9211Schristos 
361a89c9211Schristos     buf_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
362a89c9211Schristos     buf_dsc.dsc$b_class = DSC$K_CLASS_S;
363a89c9211Schristos     buf_dsc.dsc$a_pointer = buf;
364a89c9211Schristos     buf_dsc.dsc$w_length = sizeof(buf) - 1;
365a89c9211Schristos 
366a89c9211Schristos     lib$sys_fao(&fao_cmd, &len, &buf_dsc, priority_tag, string);
367a89c9211Schristos 
3681e09c865Sspz     /* We know there's an 8-byte header.  That's documented. */
3691e09c865Sspz     opcdef_p = OPCDEF_MALLOC(8 + len);
370a89c9211Schristos     opcdef_p->opc$b_ms_type = OPC$_RQ_RQST;
371a89c9211Schristos     memcpy(opcdef_p->opc$z_ms_target_classes, &VMS_OPC_target, 3);
372a89c9211Schristos     opcdef_p->opc$l_ms_rqstid = 0;
373a89c9211Schristos     memcpy(&opcdef_p->opc$l_ms_text, buf, len);
374a89c9211Schristos 
375a89c9211Schristos     opc_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
376a89c9211Schristos     opc_dsc.dsc$b_class = DSC$K_CLASS_S;
3771e09c865Sspz     opc_dsc.dsc$a_pointer = (OPCDEF_TYPE) opcdef_p;
378a89c9211Schristos     opc_dsc.dsc$w_length = len + 8;
379a89c9211Schristos 
380a89c9211Schristos     sys$sndopr(opc_dsc, 0);
381a89c9211Schristos 
382a89c9211Schristos     OPENSSL_free(opcdef_p);
383a89c9211Schristos }
384a89c9211Schristos 
xcloselog(BIO * bp)385a89c9211Schristos static void xcloselog(BIO *bp)
386a89c9211Schristos {
387a89c9211Schristos }
388a89c9211Schristos 
389a89c9211Schristos # else                          /* Unix/Watt32 */
390a89c9211Schristos 
xopenlog(BIO * bp,char * name,int level)391a89c9211Schristos static void xopenlog(BIO *bp, char *name, int level)
392a89c9211Schristos {
393a89c9211Schristos #  ifdef WATT32                 /* djgpp/DOS */
394a89c9211Schristos     openlog(name, LOG_PID | LOG_CONS | LOG_NDELAY, level);
395a89c9211Schristos #  else
396a89c9211Schristos     openlog(name, LOG_PID | LOG_CONS, level);
397a89c9211Schristos #  endif
398a89c9211Schristos }
399a89c9211Schristos 
xsyslog(BIO * bp,int priority,const char * string)400a89c9211Schristos static void xsyslog(BIO *bp, int priority, const char *string)
401a89c9211Schristos {
402a89c9211Schristos     syslog(priority, "%s", string);
403a89c9211Schristos }
404a89c9211Schristos 
xcloselog(BIO * bp)405a89c9211Schristos static void xcloselog(BIO *bp)
406a89c9211Schristos {
407a89c9211Schristos     closelog();
408a89c9211Schristos }
409a89c9211Schristos 
410a89c9211Schristos # endif                         /* Unix */
411a89c9211Schristos 
412f9c27609Schristos #else                           /* NO_SYSLOG */
BIO_s_log(void)413f9c27609Schristos const BIO_METHOD *BIO_s_log(void)
414f9c27609Schristos {
415f9c27609Schristos     return NULL;
416f9c27609Schristos }
417a89c9211Schristos #endif                          /* NO_SYSLOG */
418