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