155714Skris/* crypto/bio/bss_log.c */
255714Skris/* ====================================================================
3337982Sjkim * Copyright (c) 1999-2018 The OpenSSL Project.  All rights reserved.
455714Skris *
555714Skris * Redistribution and use in source and binary forms, with or without
655714Skris * modification, are permitted provided that the following conditions
755714Skris * are met:
855714Skris *
955714Skris * 1. Redistributions of source code must retain the above copyright
10280297Sjkim *    notice, this list of conditions and the following disclaimer.
1155714Skris *
1255714Skris * 2. Redistributions in binary form must reproduce the above copyright
1355714Skris *    notice, this list of conditions and the following disclaimer in
1455714Skris *    the documentation and/or other materials provided with the
1555714Skris *    distribution.
1655714Skris *
1755714Skris * 3. All advertising materials mentioning features or use of this
1855714Skris *    software must display the following acknowledgment:
1955714Skris *    "This product includes software developed by the OpenSSL Project
2055714Skris *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
2155714Skris *
2255714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
2355714Skris *    endorse or promote products derived from this software without
2455714Skris *    prior written permission. For written permission, please contact
2555714Skris *    licensing@OpenSSL.org.
2655714Skris *
2755714Skris * 5. Products derived from this software may not be called "OpenSSL"
2855714Skris *    nor may "OpenSSL" appear in their names without prior written
2955714Skris *    permission of the OpenSSL Project.
3055714Skris *
3155714Skris * 6. Redistributions of any form whatsoever must retain the following
3255714Skris *    acknowledgment:
3355714Skris *    "This product includes software developed by the OpenSSL Project
3455714Skris *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
3555714Skris *
3655714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
3755714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3855714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
3955714Skris * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
4055714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
4155714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
4255714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
4355714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4455714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
4555714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
4655714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
4755714Skris * OF THE POSSIBILITY OF SUCH DAMAGE.
4855714Skris * ====================================================================
4955714Skris *
5055714Skris * This product includes cryptographic software written by Eric Young
5155714Skris * (eay@cryptsoft.com).  This product includes software written by Tim
5255714Skris * Hudson (tjh@cryptsoft.com).
5355714Skris *
5455714Skris */
5555714Skris
5655714Skris/*
57280297Sjkim * Why BIO_s_log?
58280297Sjkim *
59280297Sjkim * BIO_s_log is useful for system daemons (or services under NT). It is
60280297Sjkim * one-way BIO, it sends all stuff to syslogd (on system that commonly use
61280297Sjkim * that), or event log (on NT), or OPCOM (on OpenVMS).
62280297Sjkim *
63280297Sjkim */
6455714Skris
6555714Skris#include <stdio.h>
6655714Skris#include <errno.h>
6755714Skris
68109998Smarkm#include "cryptlib.h"
69109998Smarkm
70109998Smarkm#if defined(OPENSSL_SYS_WINCE)
71109998Smarkm#elif defined(OPENSSL_SYS_WIN32)
72109998Smarkm#elif defined(OPENSSL_SYS_VMS)
73280297Sjkim# include <opcdef.h>
74280297Sjkim# include <descrip.h>
75280297Sjkim# include <lib$routines.h>
76280297Sjkim# include <starlet.h>
77238405Sjkim/* Some compiler options may mask the declaration of "_malloc32". */
78280297Sjkim# if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE
79280297Sjkim#  if __INITIAL_POINTER_SIZE == 64
80280297Sjkim#   pragma pointer_size save
81280297Sjkim#   pragma pointer_size 32
82280297Sjkimvoid *_malloc32(__size_t);
83280297Sjkim#   pragma pointer_size restore
84280297Sjkim#  endif                        /* __INITIAL_POINTER_SIZE == 64 */
85280297Sjkim# endif                         /* __INITIAL_POINTER_SIZE && defined
86280297Sjkim                                 * _ANSI_C_SOURCE */
8759191Skris#elif defined(__ultrix)
88280297Sjkim# include <sys/syslog.h>
89160814Ssimon#elif defined(OPENSSL_SYS_NETWARE)
90280297Sjkim# define NO_SYSLOG
91109998Smarkm#elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG)
92280297Sjkim# include <syslog.h>
9355714Skris#endif
9455714Skris
9555714Skris#include <openssl/buffer.h>
9655714Skris#include <openssl/err.h>
9759191Skris
9855714Skris#ifndef NO_SYSLOG
9955714Skris
100280297Sjkim# if defined(OPENSSL_SYS_WIN32)
101280297Sjkim#  define LOG_EMERG       0
102280297Sjkim#  define LOG_ALERT       1
103280297Sjkim#  define LOG_CRIT        2
104280297Sjkim#  define LOG_ERR         3
105280297Sjkim#  define LOG_WARNING     4
106280297Sjkim#  define LOG_NOTICE      5
107280297Sjkim#  define LOG_INFO        6
108280297Sjkim#  define LOG_DEBUG       7
10955714Skris
110280297Sjkim#  define LOG_DAEMON      (3<<3)
111280297Sjkim# elif defined(OPENSSL_SYS_VMS)
11259191Skris/* On VMS, we don't really care about these, but we need them to compile */
113280297Sjkim#  define LOG_EMERG       0
114280297Sjkim#  define LOG_ALERT       1
115280297Sjkim#  define LOG_CRIT        2
116280297Sjkim#  define LOG_ERR         3
117280297Sjkim#  define LOG_WARNING     4
118280297Sjkim#  define LOG_NOTICE      5
119280297Sjkim#  define LOG_INFO        6
120280297Sjkim#  define LOG_DEBUG       7
12159191Skris
122280297Sjkim#  define LOG_DAEMON      OPC$M_NM_NTWORK
123280297Sjkim# endif
12459191Skris
12568651Skrisstatic int MS_CALLBACK slg_write(BIO *h, const char *buf, int num);
12668651Skrisstatic int MS_CALLBACK slg_puts(BIO *h, const char *str);
12768651Skrisstatic long MS_CALLBACK slg_ctrl(BIO *h, int cmd, long arg1, void *arg2);
12855714Skrisstatic int MS_CALLBACK slg_new(BIO *h);
12955714Skrisstatic int MS_CALLBACK slg_free(BIO *data);
130280297Sjkimstatic void xopenlog(BIO *bp, char *name, int level);
131280297Sjkimstatic void xsyslog(BIO *bp, int priority, const char *string);
132280297Sjkimstatic void xcloselog(BIO *bp);
13355714Skris
134280297Sjkimstatic BIO_METHOD methods_slg = {
135280297Sjkim    BIO_TYPE_MEM, "syslog",
136280297Sjkim    slg_write,
137280297Sjkim    NULL,
138280297Sjkim    slg_puts,
139280297Sjkim    NULL,
140280297Sjkim    slg_ctrl,
141280297Sjkim    slg_new,
142280297Sjkim    slg_free,
143280297Sjkim    NULL,
144280297Sjkim};
14555714Skris
14655714SkrisBIO_METHOD *BIO_s_log(void)
147280297Sjkim{
148280297Sjkim    return (&methods_slg);
149280297Sjkim}
15055714Skris
15155714Skrisstatic int MS_CALLBACK slg_new(BIO *bi)
152280297Sjkim{
153280297Sjkim    bi->init = 1;
154280297Sjkim    bi->num = 0;
155280297Sjkim    bi->ptr = NULL;
156280297Sjkim    xopenlog(bi, "application", LOG_DAEMON);
157280297Sjkim    return (1);
158280297Sjkim}
15955714Skris
16055714Skrisstatic int MS_CALLBACK slg_free(BIO *a)
161280297Sjkim{
162280297Sjkim    if (a == NULL)
163280297Sjkim        return (0);
164280297Sjkim    xcloselog(a);
165280297Sjkim    return (1);
166280297Sjkim}
167280297Sjkim
16868651Skrisstatic int MS_CALLBACK slg_write(BIO *b, const char *in, int inl)
169280297Sjkim{
170280297Sjkim    int ret = inl;
171280297Sjkim    char *buf;
172280297Sjkim    char *pp;
173280297Sjkim    int priority, i;
174280297Sjkim    static const struct {
175280297Sjkim        int strl;
176280297Sjkim        char str[10];
177280297Sjkim        int log_level;
178280297Sjkim    } mapping[] = {
179280297Sjkim        {
180280297Sjkim            6, "PANIC ", LOG_EMERG
181280297Sjkim        },
182280297Sjkim        {
183280297Sjkim            6, "EMERG ", LOG_EMERG
184280297Sjkim        },
185280297Sjkim        {
186280297Sjkim            4, "EMR ", LOG_EMERG
187280297Sjkim        },
188280297Sjkim        {
189280297Sjkim            6, "ALERT ", LOG_ALERT
190280297Sjkim        },
191280297Sjkim        {
192280297Sjkim            4, "ALR ", LOG_ALERT
193280297Sjkim        },
194280297Sjkim        {
195280297Sjkim            5, "CRIT ", LOG_CRIT
196280297Sjkim        },
197280297Sjkim        {
198280297Sjkim            4, "CRI ", LOG_CRIT
199280297Sjkim        },
200280297Sjkim        {
201280297Sjkim            6, "ERROR ", LOG_ERR
202280297Sjkim        },
203280297Sjkim        {
204280297Sjkim            4, "ERR ", LOG_ERR
205280297Sjkim        },
206280297Sjkim        {
207280297Sjkim            8, "WARNING ", LOG_WARNING
208280297Sjkim        },
209280297Sjkim        {
210280297Sjkim            5, "WARN ", LOG_WARNING
211280297Sjkim        },
212280297Sjkim        {
213280297Sjkim            4, "WAR ", LOG_WARNING
214280297Sjkim        },
215280297Sjkim        {
216280297Sjkim            7, "NOTICE ", LOG_NOTICE
217280297Sjkim        },
218280297Sjkim        {
219280297Sjkim            5, "NOTE ", LOG_NOTICE
220280297Sjkim        },
221280297Sjkim        {
222280297Sjkim            4, "NOT ", LOG_NOTICE
223280297Sjkim        },
224280297Sjkim        {
225280297Sjkim            5, "INFO ", LOG_INFO
226280297Sjkim        },
227280297Sjkim        {
228280297Sjkim            4, "INF ", LOG_INFO
229280297Sjkim        },
230280297Sjkim        {
231280297Sjkim            6, "DEBUG ", LOG_DEBUG
232280297Sjkim        },
233280297Sjkim        {
234280297Sjkim            4, "DBG ", LOG_DEBUG
235280297Sjkim        },
236280297Sjkim        {
237280297Sjkim            0, "", LOG_ERR
238280297Sjkim        }
239280297Sjkim        /* The default */
240280297Sjkim    };
24155714Skris
242280297Sjkim    if ((buf = (char *)OPENSSL_malloc(inl + 1)) == NULL) {
243280297Sjkim        return (0);
244280297Sjkim    }
245337982Sjkim    memcpy(buf, in, inl);
246280297Sjkim    buf[inl] = '\0';
24755714Skris
248280297Sjkim    i = 0;
249280297Sjkim    while (strncmp(buf, mapping[i].str, mapping[i].strl) != 0)
250280297Sjkim        i++;
251280297Sjkim    priority = mapping[i].log_level;
252280297Sjkim    pp = buf + mapping[i].strl;
25355714Skris
254280297Sjkim    xsyslog(b, priority, pp);
25559191Skris
256280297Sjkim    OPENSSL_free(buf);
257280297Sjkim    return (ret);
258280297Sjkim}
25955714Skris
26068651Skrisstatic long MS_CALLBACK slg_ctrl(BIO *b, int cmd, long num, void *ptr)
261280297Sjkim{
262280297Sjkim    switch (cmd) {
263280297Sjkim    case BIO_CTRL_SET:
264280297Sjkim        xcloselog(b);
265280297Sjkim        xopenlog(b, ptr, num);
266280297Sjkim        break;
267280297Sjkim    default:
268280297Sjkim        break;
269280297Sjkim    }
270280297Sjkim    return (0);
271280297Sjkim}
27255714Skris
27368651Skrisstatic int MS_CALLBACK slg_puts(BIO *bp, const char *str)
274280297Sjkim{
275280297Sjkim    int n, ret;
27655714Skris
277280297Sjkim    n = strlen(str);
278280297Sjkim    ret = slg_write(bp, str, n);
279280297Sjkim    return (ret);
280280297Sjkim}
28155714Skris
282280297Sjkim# if defined(OPENSSL_SYS_WIN32)
28359191Skris
284280297Sjkimstatic void xopenlog(BIO *bp, char *name, int level)
28555714Skris{
286280297Sjkim    if (check_winnt())
287280297Sjkim        bp->ptr = RegisterEventSourceA(NULL, name);
288280297Sjkim    else
289280297Sjkim        bp->ptr = NULL;
29055714Skris}
29155714Skris
29259191Skrisstatic void xsyslog(BIO *bp, int priority, const char *string)
29355714Skris{
294280297Sjkim    LPCSTR lpszStrings[2];
295280297Sjkim    WORD evtype = EVENTLOG_ERROR_TYPE;
296280297Sjkim    char pidbuf[DECIMAL_SIZE(DWORD) + 4];
29759191Skris
298280297Sjkim    if (bp->ptr == NULL)
299280297Sjkim        return;
300238405Sjkim
301280297Sjkim    switch (priority) {
302280297Sjkim    case LOG_EMERG:
303280297Sjkim    case LOG_ALERT:
304280297Sjkim    case LOG_CRIT:
305280297Sjkim    case LOG_ERR:
306280297Sjkim        evtype = EVENTLOG_ERROR_TYPE;
307280297Sjkim        break;
308280297Sjkim    case LOG_WARNING:
309280297Sjkim        evtype = EVENTLOG_WARNING_TYPE;
310280297Sjkim        break;
311280297Sjkim    case LOG_NOTICE:
312280297Sjkim    case LOG_INFO:
313280297Sjkim    case LOG_DEBUG:
314280297Sjkim        evtype = EVENTLOG_INFORMATION_TYPE;
315280297Sjkim        break;
316280297Sjkim    default:
317280297Sjkim        /*
318280297Sjkim         * Should never happen, but set it
319280297Sjkim         * as error anyway.
320280297Sjkim         */
321280297Sjkim        evtype = EVENTLOG_ERROR_TYPE;
322280297Sjkim        break;
323280297Sjkim    }
32459191Skris
325280297Sjkim    sprintf(pidbuf, "[%u] ", GetCurrentProcessId());
326280297Sjkim    lpszStrings[0] = pidbuf;
327280297Sjkim    lpszStrings[1] = string;
32859191Skris
329280297Sjkim    ReportEventA(bp->ptr, evtype, 0, 1024, NULL, 2, 0, lpszStrings, NULL);
33059191Skris}
331280297Sjkim
332280297Sjkimstatic void xcloselog(BIO *bp)
33359191Skris{
334280297Sjkim    if (bp->ptr)
335280297Sjkim        DeregisterEventSource((HANDLE) (bp->ptr));
336280297Sjkim    bp->ptr = NULL;
33759191Skris}
33859191Skris
339280297Sjkim# elif defined(OPENSSL_SYS_VMS)
34059191Skris
34159191Skrisstatic int VMS_OPC_target = LOG_DAEMON;
34259191Skris
343280297Sjkimstatic void xopenlog(BIO *bp, char *name, int level)
34459191Skris{
345280297Sjkim    VMS_OPC_target = level;
34659191Skris}
34759191Skris
34859191Skrisstatic void xsyslog(BIO *bp, int priority, const char *string)
34959191Skris{
350280297Sjkim    struct dsc$descriptor_s opc_dsc;
351238405Sjkim
352238405Sjkim/* Arrange 32-bit pointer to opcdef buffer and malloc(), if needed. */
353280297Sjkim#  if __INITIAL_POINTER_SIZE == 64
354280297Sjkim#   pragma pointer_size save
355280297Sjkim#   pragma pointer_size 32
356280297Sjkim#   define OPCDEF_TYPE __char_ptr32
357280297Sjkim#   define OPCDEF_MALLOC _malloc32
358280297Sjkim#  else                         /* __INITIAL_POINTER_SIZE == 64 */
359280297Sjkim#   define OPCDEF_TYPE char *
360280297Sjkim#   define OPCDEF_MALLOC OPENSSL_malloc
361280297Sjkim#  endif                        /* __INITIAL_POINTER_SIZE == 64 [else] */
362238405Sjkim
363280297Sjkim    struct opcdef *opcdef_p;
364238405Sjkim
365280297Sjkim#  if __INITIAL_POINTER_SIZE == 64
366280297Sjkim#   pragma pointer_size restore
367280297Sjkim#  endif                        /* __INITIAL_POINTER_SIZE == 64 */
368238405Sjkim
369280297Sjkim    char buf[10240];
370280297Sjkim    unsigned int len;
371280297Sjkim    struct dsc$descriptor_s buf_dsc;
372280297Sjkim    $DESCRIPTOR(fao_cmd, "!AZ: !AZ");
373280297Sjkim    char *priority_tag;
37459191Skris
375280297Sjkim    switch (priority) {
376280297Sjkim    case LOG_EMERG:
377280297Sjkim        priority_tag = "Emergency";
378280297Sjkim        break;
379280297Sjkim    case LOG_ALERT:
380280297Sjkim        priority_tag = "Alert";
381280297Sjkim        break;
382280297Sjkim    case LOG_CRIT:
383280297Sjkim        priority_tag = "Critical";
384280297Sjkim        break;
385280297Sjkim    case LOG_ERR:
386280297Sjkim        priority_tag = "Error";
387280297Sjkim        break;
388280297Sjkim    case LOG_WARNING:
389280297Sjkim        priority_tag = "Warning";
390280297Sjkim        break;
391280297Sjkim    case LOG_NOTICE:
392280297Sjkim        priority_tag = "Notice";
393280297Sjkim        break;
394280297Sjkim    case LOG_INFO:
395280297Sjkim        priority_tag = "Info";
396280297Sjkim        break;
397280297Sjkim    case LOG_DEBUG:
398280297Sjkim        priority_tag = "DEBUG";
399280297Sjkim        break;
400280297Sjkim    }
40159191Skris
402280297Sjkim    buf_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
403280297Sjkim    buf_dsc.dsc$b_class = DSC$K_CLASS_S;
404280297Sjkim    buf_dsc.dsc$a_pointer = buf;
405280297Sjkim    buf_dsc.dsc$w_length = sizeof(buf) - 1;
40659191Skris
407280297Sjkim    lib$sys_fao(&fao_cmd, &len, &buf_dsc, priority_tag, string);
40859191Skris
409280297Sjkim    /* We know there's an 8-byte header.  That's documented. */
410280297Sjkim    opcdef_p = OPCDEF_MALLOC(8 + len);
411280297Sjkim    opcdef_p->opc$b_ms_type = OPC$_RQ_RQST;
412280297Sjkim    memcpy(opcdef_p->opc$z_ms_target_classes, &VMS_OPC_target, 3);
413280297Sjkim    opcdef_p->opc$l_ms_rqstid = 0;
414280297Sjkim    memcpy(&opcdef_p->opc$l_ms_text, buf, len);
41559191Skris
416280297Sjkim    opc_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
417280297Sjkim    opc_dsc.dsc$b_class = DSC$K_CLASS_S;
418280297Sjkim    opc_dsc.dsc$a_pointer = (OPCDEF_TYPE) opcdef_p;
419280297Sjkim    opc_dsc.dsc$w_length = len + 8;
42059191Skris
421280297Sjkim    sys$sndopr(opc_dsc, 0);
42259191Skris
423280297Sjkim    OPENSSL_free(opcdef_p);
42459191Skris}
42559191Skris
426280297Sjkimstatic void xcloselog(BIO *bp)
42759191Skris{
42859191Skris}
42959191Skris
430280297Sjkim# else                          /* Unix/Watt32 */
43159191Skris
432280297Sjkimstatic void xopenlog(BIO *bp, char *name, int level)
43359191Skris{
434280297Sjkim#  ifdef WATT32                 /* djgpp/DOS */
435280297Sjkim    openlog(name, LOG_PID | LOG_CONS | LOG_NDELAY, level);
436280297Sjkim#  else
437280297Sjkim    openlog(name, LOG_PID | LOG_CONS, level);
438280297Sjkim#  endif
43959191Skris}
44059191Skris
44159191Skrisstatic void xsyslog(BIO *bp, int priority, const char *string)
44259191Skris{
443280297Sjkim    syslog(priority, "%s", string);
44459191Skris}
44559191Skris
446280297Sjkimstatic void xcloselog(BIO *bp)
44759191Skris{
448280297Sjkim    closelog();
44955714Skris}
45055714Skris
451280297Sjkim# endif                         /* Unix */
45259191Skris
453280297Sjkim#endif                          /* NO_SYSLOG */
454