1*1dcdf01fSchristos /*
2*1dcdf01fSchristos  * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
360662d10Schristos  *
4*1dcdf01fSchristos  * Licensed under the OpenSSL license (the "License").  You may not use
5*1dcdf01fSchristos  * this file except in compliance with the License.  You can obtain a copy
6*1dcdf01fSchristos  * in the file LICENSE in the source distribution or at
7*1dcdf01fSchristos  * https://www.openssl.org/source/license.html
860662d10Schristos  */
960662d10Schristos 
1060662d10Schristos /*
1160662d10Schristos  * Why BIO_s_log?
1260662d10Schristos  *
1360662d10Schristos  * BIO_s_log is useful for system daemons (or services under NT). It is
1460662d10Schristos  * one-way BIO, it sends all stuff to syslogd (on system that commonly use
1560662d10Schristos  * that), or event log (on NT), or OPCOM (on OpenVMS).
1660662d10Schristos  *
1760662d10Schristos  */
1860662d10Schristos 
1960662d10Schristos #include <stdio.h>
2060662d10Schristos #include <errno.h>
2160662d10Schristos 
22*1dcdf01fSchristos #include "bio_local.h"
23*1dcdf01fSchristos #include "internal/cryptlib.h"
2460662d10Schristos 
2560662d10Schristos #if defined(OPENSSL_SYS_WINCE)
2660662d10Schristos #elif defined(OPENSSL_SYS_WIN32)
2760662d10Schristos #elif defined(OPENSSL_SYS_VMS)
2860662d10Schristos # include <opcdef.h>
2960662d10Schristos # include <descrip.h>
3060662d10Schristos # include <lib$routines.h>
3160662d10Schristos # include <starlet.h>
3260662d10Schristos /* Some compiler options may mask the declaration of "_malloc32". */
3360662d10Schristos # if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE
3460662d10Schristos #  if __INITIAL_POINTER_SIZE == 64
3560662d10Schristos #   pragma pointer_size save
3660662d10Schristos #   pragma pointer_size 32
3760662d10Schristos void *_malloc32(__size_t);
3860662d10Schristos #   pragma pointer_size restore
3960662d10Schristos #  endif                        /* __INITIAL_POINTER_SIZE == 64 */
4060662d10Schristos # endif                         /* __INITIAL_POINTER_SIZE && defined
4160662d10Schristos                                  * _ANSI_C_SOURCE */
42*1dcdf01fSchristos #elif defined(__DJGPP__) && defined(OPENSSL_NO_SOCK)
4360662d10Schristos # define NO_SYSLOG
4460662d10Schristos #elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG)
4560662d10Schristos # include <syslog.h>
4660662d10Schristos #endif
4760662d10Schristos 
4860662d10Schristos #include <openssl/buffer.h>
4960662d10Schristos #include <openssl/err.h>
5060662d10Schristos 
5160662d10Schristos #ifndef NO_SYSLOG
5260662d10Schristos 
5360662d10Schristos # if defined(OPENSSL_SYS_WIN32)
5460662d10Schristos #  define LOG_EMERG       0
5560662d10Schristos #  define LOG_ALERT       1
5660662d10Schristos #  define LOG_CRIT        2
5760662d10Schristos #  define LOG_ERR         3
5860662d10Schristos #  define LOG_WARNING     4
5960662d10Schristos #  define LOG_NOTICE      5
6060662d10Schristos #  define LOG_INFO        6
6160662d10Schristos #  define LOG_DEBUG       7
6260662d10Schristos 
6360662d10Schristos #  define LOG_DAEMON      (3<<3)
6460662d10Schristos # elif defined(OPENSSL_SYS_VMS)
6560662d10Schristos /* On VMS, we don't really care about these, but we need them to compile */
6660662d10Schristos #  define LOG_EMERG       0
6760662d10Schristos #  define LOG_ALERT       1
6860662d10Schristos #  define LOG_CRIT        2
6960662d10Schristos #  define LOG_ERR         3
7060662d10Schristos #  define LOG_WARNING     4
7160662d10Schristos #  define LOG_NOTICE      5
7260662d10Schristos #  define LOG_INFO        6
7360662d10Schristos #  define LOG_DEBUG       7
7460662d10Schristos 
7560662d10Schristos #  define LOG_DAEMON      OPC$M_NM_NTWORK
7660662d10Schristos # endif
7760662d10Schristos 
78*1dcdf01fSchristos static int slg_write(BIO *h, const char *buf, int num);
79*1dcdf01fSchristos static int slg_puts(BIO *h, const char *str);
80*1dcdf01fSchristos static long slg_ctrl(BIO *h, int cmd, long arg1, void *arg2);
81*1dcdf01fSchristos static int slg_new(BIO *h);
82*1dcdf01fSchristos static int slg_free(BIO *data);
8360662d10Schristos static void xopenlog(BIO *bp, char *name, int level);
8460662d10Schristos static void xsyslog(BIO *bp, int priority, const char *string);
8560662d10Schristos static void xcloselog(BIO *bp);
8660662d10Schristos 
87*1dcdf01fSchristos static const BIO_METHOD methods_slg = {
88*1dcdf01fSchristos     BIO_TYPE_MEM,
89*1dcdf01fSchristos     "syslog",
90*1dcdf01fSchristos     /* TODO: Convert to new style write function */
91*1dcdf01fSchristos     bwrite_conv,
9260662d10Schristos     slg_write,
93*1dcdf01fSchristos     NULL,                      /* slg_write_old,    */
94*1dcdf01fSchristos     NULL,                      /* slg_read,         */
9560662d10Schristos     slg_puts,
9660662d10Schristos     NULL,
9760662d10Schristos     slg_ctrl,
9860662d10Schristos     slg_new,
9960662d10Schristos     slg_free,
100*1dcdf01fSchristos     NULL,                      /* slg_callback_ctrl */
10160662d10Schristos };
10260662d10Schristos 
BIO_s_log(void)103*1dcdf01fSchristos const BIO_METHOD *BIO_s_log(void)
10460662d10Schristos {
105*1dcdf01fSchristos     return &methods_slg;
10660662d10Schristos }
10760662d10Schristos 
slg_new(BIO * bi)108*1dcdf01fSchristos static int slg_new(BIO *bi)
10960662d10Schristos {
11060662d10Schristos     bi->init = 1;
11160662d10Schristos     bi->num = 0;
11260662d10Schristos     bi->ptr = NULL;
11360662d10Schristos     xopenlog(bi, "application", LOG_DAEMON);
114*1dcdf01fSchristos     return 1;
11560662d10Schristos }
11660662d10Schristos 
slg_free(BIO * a)117*1dcdf01fSchristos static int slg_free(BIO *a)
11860662d10Schristos {
11960662d10Schristos     if (a == NULL)
120*1dcdf01fSchristos         return 0;
12160662d10Schristos     xcloselog(a);
122*1dcdf01fSchristos     return 1;
12360662d10Schristos }
12460662d10Schristos 
slg_write(BIO * b,const char * in,int inl)125*1dcdf01fSchristos static int slg_write(BIO *b, const char *in, int inl)
12660662d10Schristos {
12760662d10Schristos     int ret = inl;
12860662d10Schristos     char *buf;
12960662d10Schristos     char *pp;
13060662d10Schristos     int priority, i;
13160662d10Schristos     static const struct {
13260662d10Schristos         int strl;
13360662d10Schristos         char str[10];
13460662d10Schristos         int log_level;
13560662d10Schristos     } mapping[] = {
13660662d10Schristos         {
13760662d10Schristos             6, "PANIC ", LOG_EMERG
13860662d10Schristos         },
13960662d10Schristos         {
14060662d10Schristos             6, "EMERG ", LOG_EMERG
14160662d10Schristos         },
14260662d10Schristos         {
14360662d10Schristos             4, "EMR ", LOG_EMERG
14460662d10Schristos         },
14560662d10Schristos         {
14660662d10Schristos             6, "ALERT ", LOG_ALERT
14760662d10Schristos         },
14860662d10Schristos         {
14960662d10Schristos             4, "ALR ", LOG_ALERT
15060662d10Schristos         },
15160662d10Schristos         {
15260662d10Schristos             5, "CRIT ", LOG_CRIT
15360662d10Schristos         },
15460662d10Schristos         {
15560662d10Schristos             4, "CRI ", LOG_CRIT
15660662d10Schristos         },
15760662d10Schristos         {
15860662d10Schristos             6, "ERROR ", LOG_ERR
15960662d10Schristos         },
16060662d10Schristos         {
16160662d10Schristos             4, "ERR ", LOG_ERR
16260662d10Schristos         },
16360662d10Schristos         {
16460662d10Schristos             8, "WARNING ", LOG_WARNING
16560662d10Schristos         },
16660662d10Schristos         {
16760662d10Schristos             5, "WARN ", LOG_WARNING
16860662d10Schristos         },
16960662d10Schristos         {
17060662d10Schristos             4, "WAR ", LOG_WARNING
17160662d10Schristos         },
17260662d10Schristos         {
17360662d10Schristos             7, "NOTICE ", LOG_NOTICE
17460662d10Schristos         },
17560662d10Schristos         {
17660662d10Schristos             5, "NOTE ", LOG_NOTICE
17760662d10Schristos         },
17860662d10Schristos         {
17960662d10Schristos             4, "NOT ", LOG_NOTICE
18060662d10Schristos         },
18160662d10Schristos         {
18260662d10Schristos             5, "INFO ", LOG_INFO
18360662d10Schristos         },
18460662d10Schristos         {
18560662d10Schristos             4, "INF ", LOG_INFO
18660662d10Schristos         },
18760662d10Schristos         {
18860662d10Schristos             6, "DEBUG ", LOG_DEBUG
18960662d10Schristos         },
19060662d10Schristos         {
19160662d10Schristos             4, "DBG ", LOG_DEBUG
19260662d10Schristos         },
19360662d10Schristos         {
19460662d10Schristos             0, "", LOG_ERR
19560662d10Schristos         }
19660662d10Schristos         /* The default */
19760662d10Schristos     };
19860662d10Schristos 
199*1dcdf01fSchristos     if ((buf = OPENSSL_malloc(inl + 1)) == NULL) {
200*1dcdf01fSchristos         BIOerr(BIO_F_SLG_WRITE, ERR_R_MALLOC_FAILURE);
201*1dcdf01fSchristos         return 0;
20260662d10Schristos     }
203*1dcdf01fSchristos     memcpy(buf, in, inl);
20460662d10Schristos     buf[inl] = '\0';
20560662d10Schristos 
20660662d10Schristos     i = 0;
20760662d10Schristos     while (strncmp(buf, mapping[i].str, mapping[i].strl) != 0)
20860662d10Schristos         i++;
20960662d10Schristos     priority = mapping[i].log_level;
21060662d10Schristos     pp = buf + mapping[i].strl;
21160662d10Schristos 
21260662d10Schristos     xsyslog(b, priority, pp);
21360662d10Schristos 
21460662d10Schristos     OPENSSL_free(buf);
215*1dcdf01fSchristos     return ret;
21660662d10Schristos }
21760662d10Schristos 
slg_ctrl(BIO * b,int cmd,long num,void * ptr)218*1dcdf01fSchristos static long slg_ctrl(BIO *b, int cmd, long num, void *ptr)
21960662d10Schristos {
22060662d10Schristos     switch (cmd) {
22160662d10Schristos     case BIO_CTRL_SET:
22260662d10Schristos         xcloselog(b);
22360662d10Schristos         xopenlog(b, ptr, num);
22460662d10Schristos         break;
22560662d10Schristos     default:
22660662d10Schristos         break;
22760662d10Schristos     }
228*1dcdf01fSchristos     return 0;
22960662d10Schristos }
23060662d10Schristos 
slg_puts(BIO * bp,const char * str)231*1dcdf01fSchristos static int slg_puts(BIO *bp, const char *str)
23260662d10Schristos {
23360662d10Schristos     int n, ret;
23460662d10Schristos 
23560662d10Schristos     n = strlen(str);
23660662d10Schristos     ret = slg_write(bp, str, n);
237*1dcdf01fSchristos     return ret;
23860662d10Schristos }
23960662d10Schristos 
24060662d10Schristos # if defined(OPENSSL_SYS_WIN32)
24160662d10Schristos 
xopenlog(BIO * bp,char * name,int level)24260662d10Schristos static void xopenlog(BIO *bp, char *name, int level)
24360662d10Schristos {
24460662d10Schristos     if (check_winnt())
24560662d10Schristos         bp->ptr = RegisterEventSourceA(NULL, name);
24660662d10Schristos     else
24760662d10Schristos         bp->ptr = NULL;
24860662d10Schristos }
24960662d10Schristos 
xsyslog(BIO * bp,int priority,const char * string)25060662d10Schristos static void xsyslog(BIO *bp, int priority, const char *string)
25160662d10Schristos {
25260662d10Schristos     LPCSTR lpszStrings[2];
25360662d10Schristos     WORD evtype = EVENTLOG_ERROR_TYPE;
25460662d10Schristos     char pidbuf[DECIMAL_SIZE(DWORD) + 4];
25560662d10Schristos 
25660662d10Schristos     if (bp->ptr == NULL)
25760662d10Schristos         return;
25860662d10Schristos 
25960662d10Schristos     switch (priority) {
26060662d10Schristos     case LOG_EMERG:
26160662d10Schristos     case LOG_ALERT:
26260662d10Schristos     case LOG_CRIT:
26360662d10Schristos     case LOG_ERR:
26460662d10Schristos         evtype = EVENTLOG_ERROR_TYPE;
26560662d10Schristos         break;
26660662d10Schristos     case LOG_WARNING:
26760662d10Schristos         evtype = EVENTLOG_WARNING_TYPE;
26860662d10Schristos         break;
26960662d10Schristos     case LOG_NOTICE:
27060662d10Schristos     case LOG_INFO:
27160662d10Schristos     case LOG_DEBUG:
27260662d10Schristos         evtype = EVENTLOG_INFORMATION_TYPE;
27360662d10Schristos         break;
27460662d10Schristos     default:
27560662d10Schristos         /*
27660662d10Schristos          * Should never happen, but set it
27760662d10Schristos          * as error anyway.
27860662d10Schristos          */
27960662d10Schristos         evtype = EVENTLOG_ERROR_TYPE;
28060662d10Schristos         break;
28160662d10Schristos     }
28260662d10Schristos 
283*1dcdf01fSchristos     sprintf(pidbuf, "[%u] ", GetCurrentProcessId());
28460662d10Schristos     lpszStrings[0] = pidbuf;
28560662d10Schristos     lpszStrings[1] = string;
28660662d10Schristos 
28760662d10Schristos     ReportEventA(bp->ptr, evtype, 0, 1024, NULL, 2, 0, lpszStrings, NULL);
28860662d10Schristos }
28960662d10Schristos 
xcloselog(BIO * bp)29060662d10Schristos static void xcloselog(BIO *bp)
29160662d10Schristos {
29260662d10Schristos     if (bp->ptr)
29360662d10Schristos         DeregisterEventSource((HANDLE) (bp->ptr));
29460662d10Schristos     bp->ptr = NULL;
29560662d10Schristos }
29660662d10Schristos 
29760662d10Schristos # elif defined(OPENSSL_SYS_VMS)
29860662d10Schristos 
29960662d10Schristos static int VMS_OPC_target = LOG_DAEMON;
30060662d10Schristos 
xopenlog(BIO * bp,char * name,int level)30160662d10Schristos static void xopenlog(BIO *bp, char *name, int level)
30260662d10Schristos {
30360662d10Schristos     VMS_OPC_target = level;
30460662d10Schristos }
30560662d10Schristos 
xsyslog(BIO * bp,int priority,const char * string)30660662d10Schristos static void xsyslog(BIO *bp, int priority, const char *string)
30760662d10Schristos {
30860662d10Schristos     struct dsc$descriptor_s opc_dsc;
30960662d10Schristos 
31060662d10Schristos /* Arrange 32-bit pointer to opcdef buffer and malloc(), if needed. */
31160662d10Schristos #  if __INITIAL_POINTER_SIZE == 64
31260662d10Schristos #   pragma pointer_size save
31360662d10Schristos #   pragma pointer_size 32
31460662d10Schristos #   define OPCDEF_TYPE __char_ptr32
31560662d10Schristos #   define OPCDEF_MALLOC _malloc32
31660662d10Schristos #  else                         /* __INITIAL_POINTER_SIZE == 64 */
31760662d10Schristos #   define OPCDEF_TYPE char *
31860662d10Schristos #   define OPCDEF_MALLOC OPENSSL_malloc
31960662d10Schristos #  endif                        /* __INITIAL_POINTER_SIZE == 64 [else] */
32060662d10Schristos 
32160662d10Schristos     struct opcdef *opcdef_p;
32260662d10Schristos 
32360662d10Schristos #  if __INITIAL_POINTER_SIZE == 64
32460662d10Schristos #   pragma pointer_size restore
32560662d10Schristos #  endif                        /* __INITIAL_POINTER_SIZE == 64 */
32660662d10Schristos 
32760662d10Schristos     char buf[10240];
32860662d10Schristos     unsigned int len;
32960662d10Schristos     struct dsc$descriptor_s buf_dsc;
33060662d10Schristos     $DESCRIPTOR(fao_cmd, "!AZ: !AZ");
33160662d10Schristos     char *priority_tag;
33260662d10Schristos 
33360662d10Schristos     switch (priority) {
33460662d10Schristos     case LOG_EMERG:
33560662d10Schristos         priority_tag = "Emergency";
33660662d10Schristos         break;
33760662d10Schristos     case LOG_ALERT:
33860662d10Schristos         priority_tag = "Alert";
33960662d10Schristos         break;
34060662d10Schristos     case LOG_CRIT:
34160662d10Schristos         priority_tag = "Critical";
34260662d10Schristos         break;
34360662d10Schristos     case LOG_ERR:
34460662d10Schristos         priority_tag = "Error";
34560662d10Schristos         break;
34660662d10Schristos     case LOG_WARNING:
34760662d10Schristos         priority_tag = "Warning";
34860662d10Schristos         break;
34960662d10Schristos     case LOG_NOTICE:
35060662d10Schristos         priority_tag = "Notice";
35160662d10Schristos         break;
35260662d10Schristos     case LOG_INFO:
35360662d10Schristos         priority_tag = "Info";
35460662d10Schristos         break;
35560662d10Schristos     case LOG_DEBUG:
35660662d10Schristos         priority_tag = "DEBUG";
35760662d10Schristos         break;
35860662d10Schristos     }
35960662d10Schristos 
36060662d10Schristos     buf_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
36160662d10Schristos     buf_dsc.dsc$b_class = DSC$K_CLASS_S;
36260662d10Schristos     buf_dsc.dsc$a_pointer = buf;
36360662d10Schristos     buf_dsc.dsc$w_length = sizeof(buf) - 1;
36460662d10Schristos 
36560662d10Schristos     lib$sys_fao(&fao_cmd, &len, &buf_dsc, priority_tag, string);
36660662d10Schristos 
36760662d10Schristos     /* We know there's an 8-byte header.  That's documented. */
36860662d10Schristos     opcdef_p = OPCDEF_MALLOC(8 + len);
36960662d10Schristos     opcdef_p->opc$b_ms_type = OPC$_RQ_RQST;
37060662d10Schristos     memcpy(opcdef_p->opc$z_ms_target_classes, &VMS_OPC_target, 3);
37160662d10Schristos     opcdef_p->opc$l_ms_rqstid = 0;
37260662d10Schristos     memcpy(&opcdef_p->opc$l_ms_text, buf, len);
37360662d10Schristos 
37460662d10Schristos     opc_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
37560662d10Schristos     opc_dsc.dsc$b_class = DSC$K_CLASS_S;
37660662d10Schristos     opc_dsc.dsc$a_pointer = (OPCDEF_TYPE) opcdef_p;
37760662d10Schristos     opc_dsc.dsc$w_length = len + 8;
37860662d10Schristos 
37960662d10Schristos     sys$sndopr(opc_dsc, 0);
38060662d10Schristos 
38160662d10Schristos     OPENSSL_free(opcdef_p);
38260662d10Schristos }
38360662d10Schristos 
xcloselog(BIO * bp)38460662d10Schristos static void xcloselog(BIO *bp)
38560662d10Schristos {
38660662d10Schristos }
38760662d10Schristos 
38860662d10Schristos # else                          /* Unix/Watt32 */
38960662d10Schristos 
xopenlog(BIO * bp,char * name,int level)39060662d10Schristos static void xopenlog(BIO *bp, char *name, int level)
39160662d10Schristos {
39260662d10Schristos #  ifdef WATT32                 /* djgpp/DOS */
39360662d10Schristos     openlog(name, LOG_PID | LOG_CONS | LOG_NDELAY, level);
39460662d10Schristos #  else
39560662d10Schristos     openlog(name, LOG_PID | LOG_CONS, level);
39660662d10Schristos #  endif
39760662d10Schristos }
39860662d10Schristos 
xsyslog(BIO * bp,int priority,const char * string)39960662d10Schristos static void xsyslog(BIO *bp, int priority, const char *string)
40060662d10Schristos {
40160662d10Schristos     syslog(priority, "%s", string);
40260662d10Schristos }
40360662d10Schristos 
xcloselog(BIO * bp)40460662d10Schristos static void xcloselog(BIO *bp)
40560662d10Schristos {
40660662d10Schristos     closelog();
40760662d10Schristos }
40860662d10Schristos 
40960662d10Schristos # endif                         /* Unix */
41060662d10Schristos 
411*1dcdf01fSchristos #else                           /* NO_SYSLOG */
BIO_s_log(void)412*1dcdf01fSchristos const BIO_METHOD *BIO_s_log(void)
413*1dcdf01fSchristos {
414*1dcdf01fSchristos     return NULL;
415*1dcdf01fSchristos }
41660662d10Schristos #endif                          /* NO_SYSLOG */
417