155714Skris/* crypto/bio/bss_log.c */
255714Skris/* ====================================================================
355714Skris * Copyright (c) 1999 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
10296341Sdelphij *    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/*
57296341Sdelphij * Why BIO_s_log?
58296341Sdelphij *
59296341Sdelphij * BIO_s_log is useful for system daemons (or services under NT). It is
60296341Sdelphij * one-way BIO, it sends all stuff to syslogd (on system that commonly use
61296341Sdelphij * that), or event log (on NT), or OPCOM (on OpenVMS).
62296341Sdelphij *
63296341Sdelphij */
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)
73296341Sdelphij# include <opcdef.h>
74296341Sdelphij# include <descrip.h>
75296341Sdelphij# include <lib$routines.h>
76296341Sdelphij# include <starlet.h>
77238405Sjkim/* Some compiler options may mask the declaration of "_malloc32". */
78296341Sdelphij# if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE
79296341Sdelphij#  if __INITIAL_POINTER_SIZE == 64
80296341Sdelphij#   pragma pointer_size save
81296341Sdelphij#   pragma pointer_size 32
82296341Sdelphijvoid *_malloc32(__size_t);
83296341Sdelphij#   pragma pointer_size restore
84296341Sdelphij#  endif                        /* __INITIAL_POINTER_SIZE == 64 */
85296341Sdelphij# endif                         /* __INITIAL_POINTER_SIZE && defined
86296341Sdelphij                                 * _ANSI_C_SOURCE */
8759191Skris#elif defined(__ultrix)
88296341Sdelphij# include <sys/syslog.h>
89160814Ssimon#elif defined(OPENSSL_SYS_NETWARE)
90296341Sdelphij# define NO_SYSLOG
91109998Smarkm#elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG)
92296341Sdelphij# include <syslog.h>
9355714Skris#endif
9455714Skris
9555714Skris#include <openssl/buffer.h>
9655714Skris#include <openssl/err.h>
9759191Skris
9855714Skris#ifndef NO_SYSLOG
9955714Skris
100296341Sdelphij# if defined(OPENSSL_SYS_WIN32)
101296341Sdelphij#  define LOG_EMERG       0
102296341Sdelphij#  define LOG_ALERT       1
103296341Sdelphij#  define LOG_CRIT        2
104296341Sdelphij#  define LOG_ERR         3
105296341Sdelphij#  define LOG_WARNING     4
106296341Sdelphij#  define LOG_NOTICE      5
107296341Sdelphij#  define LOG_INFO        6
108296341Sdelphij#  define LOG_DEBUG       7
10955714Skris
110296341Sdelphij#  define LOG_DAEMON      (3<<3)
111296341Sdelphij# elif defined(OPENSSL_SYS_VMS)
11259191Skris/* On VMS, we don't really care about these, but we need them to compile */
113296341Sdelphij#  define LOG_EMERG       0
114296341Sdelphij#  define LOG_ALERT       1
115296341Sdelphij#  define LOG_CRIT        2
116296341Sdelphij#  define LOG_ERR         3
117296341Sdelphij#  define LOG_WARNING     4
118296341Sdelphij#  define LOG_NOTICE      5
119296341Sdelphij#  define LOG_INFO        6
120296341Sdelphij#  define LOG_DEBUG       7
12159191Skris
122296341Sdelphij#  define LOG_DAEMON      OPC$M_NM_NTWORK
123296341Sdelphij# 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);
130296341Sdelphijstatic void xopenlog(BIO *bp, char *name, int level);
131296341Sdelphijstatic void xsyslog(BIO *bp, int priority, const char *string);
132296341Sdelphijstatic void xcloselog(BIO *bp);
13355714Skris
134296341Sdelphijstatic BIO_METHOD methods_slg = {
135296341Sdelphij    BIO_TYPE_MEM, "syslog",
136296341Sdelphij    slg_write,
137296341Sdelphij    NULL,
138296341Sdelphij    slg_puts,
139296341Sdelphij    NULL,
140296341Sdelphij    slg_ctrl,
141296341Sdelphij    slg_new,
142296341Sdelphij    slg_free,
143296341Sdelphij    NULL,
144296341Sdelphij};
14555714Skris
14655714SkrisBIO_METHOD *BIO_s_log(void)
147296341Sdelphij{
148296341Sdelphij    return (&methods_slg);
149296341Sdelphij}
15055714Skris
15155714Skrisstatic int MS_CALLBACK slg_new(BIO *bi)
152296341Sdelphij{
153296341Sdelphij    bi->init = 1;
154296341Sdelphij    bi->num = 0;
155296341Sdelphij    bi->ptr = NULL;
156296341Sdelphij    xopenlog(bi, "application", LOG_DAEMON);
157296341Sdelphij    return (1);
158296341Sdelphij}
15955714Skris
16055714Skrisstatic int MS_CALLBACK slg_free(BIO *a)
161296341Sdelphij{
162296341Sdelphij    if (a == NULL)
163296341Sdelphij        return (0);
164296341Sdelphij    xcloselog(a);
165296341Sdelphij    return (1);
166296341Sdelphij}
167296341Sdelphij
16868651Skrisstatic int MS_CALLBACK slg_write(BIO *b, const char *in, int inl)
169296341Sdelphij{
170296341Sdelphij    int ret = inl;
171296341Sdelphij    char *buf;
172296341Sdelphij    char *pp;
173296341Sdelphij    int priority, i;
174296341Sdelphij    static const struct {
175296341Sdelphij        int strl;
176296341Sdelphij        char str[10];
177296341Sdelphij        int log_level;
178296341Sdelphij    } mapping[] = {
179296341Sdelphij        {
180296341Sdelphij            6, "PANIC ", LOG_EMERG
181296341Sdelphij        },
182296341Sdelphij        {
183296341Sdelphij            6, "EMERG ", LOG_EMERG
184296341Sdelphij        },
185296341Sdelphij        {
186296341Sdelphij            4, "EMR ", LOG_EMERG
187296341Sdelphij        },
188296341Sdelphij        {
189296341Sdelphij            6, "ALERT ", LOG_ALERT
190296341Sdelphij        },
191296341Sdelphij        {
192296341Sdelphij            4, "ALR ", LOG_ALERT
193296341Sdelphij        },
194296341Sdelphij        {
195296341Sdelphij            5, "CRIT ", LOG_CRIT
196296341Sdelphij        },
197296341Sdelphij        {
198296341Sdelphij            4, "CRI ", LOG_CRIT
199296341Sdelphij        },
200296341Sdelphij        {
201296341Sdelphij            6, "ERROR ", LOG_ERR
202296341Sdelphij        },
203296341Sdelphij        {
204296341Sdelphij            4, "ERR ", LOG_ERR
205296341Sdelphij        },
206296341Sdelphij        {
207296341Sdelphij            8, "WARNING ", LOG_WARNING
208296341Sdelphij        },
209296341Sdelphij        {
210296341Sdelphij            5, "WARN ", LOG_WARNING
211296341Sdelphij        },
212296341Sdelphij        {
213296341Sdelphij            4, "WAR ", LOG_WARNING
214296341Sdelphij        },
215296341Sdelphij        {
216296341Sdelphij            7, "NOTICE ", LOG_NOTICE
217296341Sdelphij        },
218296341Sdelphij        {
219296341Sdelphij            5, "NOTE ", LOG_NOTICE
220296341Sdelphij        },
221296341Sdelphij        {
222296341Sdelphij            4, "NOT ", LOG_NOTICE
223296341Sdelphij        },
224296341Sdelphij        {
225296341Sdelphij            5, "INFO ", LOG_INFO
226296341Sdelphij        },
227296341Sdelphij        {
228296341Sdelphij            4, "INF ", LOG_INFO
229296341Sdelphij        },
230296341Sdelphij        {
231296341Sdelphij            6, "DEBUG ", LOG_DEBUG
232296341Sdelphij        },
233296341Sdelphij        {
234296341Sdelphij            4, "DBG ", LOG_DEBUG
235296341Sdelphij        },
236296341Sdelphij        {
237296341Sdelphij            0, "", LOG_ERR
238296341Sdelphij        }
239296341Sdelphij        /* The default */
240296341Sdelphij    };
24155714Skris
242296341Sdelphij    if ((buf = (char *)OPENSSL_malloc(inl + 1)) == NULL) {
243296341Sdelphij        return (0);
244296341Sdelphij    }
245296341Sdelphij    strncpy(buf, in, inl);
246296341Sdelphij    buf[inl] = '\0';
24755714Skris
248296341Sdelphij    i = 0;
249296341Sdelphij    while (strncmp(buf, mapping[i].str, mapping[i].strl) != 0)
250296341Sdelphij        i++;
251296341Sdelphij    priority = mapping[i].log_level;
252296341Sdelphij    pp = buf + mapping[i].strl;
25355714Skris
254296341Sdelphij    xsyslog(b, priority, pp);
25559191Skris
256296341Sdelphij    OPENSSL_free(buf);
257296341Sdelphij    return (ret);
258296341Sdelphij}
25955714Skris
26068651Skrisstatic long MS_CALLBACK slg_ctrl(BIO *b, int cmd, long num, void *ptr)
261296341Sdelphij{
262296341Sdelphij    switch (cmd) {
263296341Sdelphij    case BIO_CTRL_SET:
264296341Sdelphij        xcloselog(b);
265296341Sdelphij        xopenlog(b, ptr, num);
266296341Sdelphij        break;
267296341Sdelphij    default:
268296341Sdelphij        break;
269296341Sdelphij    }
270296341Sdelphij    return (0);
271296341Sdelphij}
27255714Skris
27368651Skrisstatic int MS_CALLBACK slg_puts(BIO *bp, const char *str)
274296341Sdelphij{
275296341Sdelphij    int n, ret;
27655714Skris
277296341Sdelphij    n = strlen(str);
278296341Sdelphij    ret = slg_write(bp, str, n);
279296341Sdelphij    return (ret);
280296341Sdelphij}
28155714Skris
282296341Sdelphij# if defined(OPENSSL_SYS_WIN32)
28359191Skris
284296341Sdelphijstatic void xopenlog(BIO *bp, char *name, int level)
28555714Skris{
286296341Sdelphij    if (check_winnt())
287296341Sdelphij        bp->ptr = RegisterEventSourceA(NULL, name);
288296341Sdelphij    else
289296341Sdelphij        bp->ptr = NULL;
29055714Skris}
29155714Skris
29259191Skrisstatic void xsyslog(BIO *bp, int priority, const char *string)
29355714Skris{
294296341Sdelphij    LPCSTR lpszStrings[2];
295296341Sdelphij    WORD evtype = EVENTLOG_ERROR_TYPE;
296296341Sdelphij    char pidbuf[DECIMAL_SIZE(DWORD) + 4];
29759191Skris
298296341Sdelphij    if (bp->ptr == NULL)
299296341Sdelphij        return;
300238405Sjkim
301296341Sdelphij    switch (priority) {
302296341Sdelphij    case LOG_EMERG:
303296341Sdelphij    case LOG_ALERT:
304296341Sdelphij    case LOG_CRIT:
305296341Sdelphij    case LOG_ERR:
306296341Sdelphij        evtype = EVENTLOG_ERROR_TYPE;
307296341Sdelphij        break;
308296341Sdelphij    case LOG_WARNING:
309296341Sdelphij        evtype = EVENTLOG_WARNING_TYPE;
310296341Sdelphij        break;
311296341Sdelphij    case LOG_NOTICE:
312296341Sdelphij    case LOG_INFO:
313296341Sdelphij    case LOG_DEBUG:
314296341Sdelphij        evtype = EVENTLOG_INFORMATION_TYPE;
315296341Sdelphij        break;
316296341Sdelphij    default:
317296341Sdelphij        /*
318296341Sdelphij         * Should never happen, but set it
319296341Sdelphij         * as error anyway.
320296341Sdelphij         */
321296341Sdelphij        evtype = EVENTLOG_ERROR_TYPE;
322296341Sdelphij        break;
323296341Sdelphij    }
32459191Skris
325296341Sdelphij    sprintf(pidbuf, "[%u] ", GetCurrentProcessId());
326296341Sdelphij    lpszStrings[0] = pidbuf;
327296341Sdelphij    lpszStrings[1] = string;
32859191Skris
329296341Sdelphij    ReportEventA(bp->ptr, evtype, 0, 1024, NULL, 2, 0, lpszStrings, NULL);
33059191Skris}
331296341Sdelphij
332296341Sdelphijstatic void xcloselog(BIO *bp)
33359191Skris{
334296341Sdelphij    if (bp->ptr)
335296341Sdelphij        DeregisterEventSource((HANDLE) (bp->ptr));
336296341Sdelphij    bp->ptr = NULL;
33759191Skris}
33859191Skris
339296341Sdelphij# elif defined(OPENSSL_SYS_VMS)
34059191Skris
34159191Skrisstatic int VMS_OPC_target = LOG_DAEMON;
34259191Skris
343296341Sdelphijstatic void xopenlog(BIO *bp, char *name, int level)
34459191Skris{
345296341Sdelphij    VMS_OPC_target = level;
34659191Skris}
34759191Skris
34859191Skrisstatic void xsyslog(BIO *bp, int priority, const char *string)
34959191Skris{
350296341Sdelphij    struct dsc$descriptor_s opc_dsc;
351238405Sjkim
352238405Sjkim/* Arrange 32-bit pointer to opcdef buffer and malloc(), if needed. */
353296341Sdelphij#  if __INITIAL_POINTER_SIZE == 64
354296341Sdelphij#   pragma pointer_size save
355296341Sdelphij#   pragma pointer_size 32
356296341Sdelphij#   define OPCDEF_TYPE __char_ptr32
357296341Sdelphij#   define OPCDEF_MALLOC _malloc32
358296341Sdelphij#  else                         /* __INITIAL_POINTER_SIZE == 64 */
359296341Sdelphij#   define OPCDEF_TYPE char *
360296341Sdelphij#   define OPCDEF_MALLOC OPENSSL_malloc
361296341Sdelphij#  endif                        /* __INITIAL_POINTER_SIZE == 64 [else] */
362238405Sjkim
363296341Sdelphij    struct opcdef *opcdef_p;
364238405Sjkim
365296341Sdelphij#  if __INITIAL_POINTER_SIZE == 64
366296341Sdelphij#   pragma pointer_size restore
367296341Sdelphij#  endif                        /* __INITIAL_POINTER_SIZE == 64 */
368238405Sjkim
369296341Sdelphij    char buf[10240];
370296341Sdelphij    unsigned int len;
371296341Sdelphij    struct dsc$descriptor_s buf_dsc;
372296341Sdelphij    $DESCRIPTOR(fao_cmd, "!AZ: !AZ");
373296341Sdelphij    char *priority_tag;
37459191Skris
375296341Sdelphij    switch (priority) {
376296341Sdelphij    case LOG_EMERG:
377296341Sdelphij        priority_tag = "Emergency";
378296341Sdelphij        break;
379296341Sdelphij    case LOG_ALERT:
380296341Sdelphij        priority_tag = "Alert";
381296341Sdelphij        break;
382296341Sdelphij    case LOG_CRIT:
383296341Sdelphij        priority_tag = "Critical";
384296341Sdelphij        break;
385296341Sdelphij    case LOG_ERR:
386296341Sdelphij        priority_tag = "Error";
387296341Sdelphij        break;
388296341Sdelphij    case LOG_WARNING:
389296341Sdelphij        priority_tag = "Warning";
390296341Sdelphij        break;
391296341Sdelphij    case LOG_NOTICE:
392296341Sdelphij        priority_tag = "Notice";
393296341Sdelphij        break;
394296341Sdelphij    case LOG_INFO:
395296341Sdelphij        priority_tag = "Info";
396296341Sdelphij        break;
397296341Sdelphij    case LOG_DEBUG:
398296341Sdelphij        priority_tag = "DEBUG";
399296341Sdelphij        break;
400296341Sdelphij    }
40159191Skris
402296341Sdelphij    buf_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
403296341Sdelphij    buf_dsc.dsc$b_class = DSC$K_CLASS_S;
404296341Sdelphij    buf_dsc.dsc$a_pointer = buf;
405296341Sdelphij    buf_dsc.dsc$w_length = sizeof(buf) - 1;
40659191Skris
407296341Sdelphij    lib$sys_fao(&fao_cmd, &len, &buf_dsc, priority_tag, string);
40859191Skris
409296341Sdelphij    /* We know there's an 8-byte header.  That's documented. */
410296341Sdelphij    opcdef_p = OPCDEF_MALLOC(8 + len);
411296341Sdelphij    opcdef_p->opc$b_ms_type = OPC$_RQ_RQST;
412296341Sdelphij    memcpy(opcdef_p->opc$z_ms_target_classes, &VMS_OPC_target, 3);
413296341Sdelphij    opcdef_p->opc$l_ms_rqstid = 0;
414296341Sdelphij    memcpy(&opcdef_p->opc$l_ms_text, buf, len);
41559191Skris
416296341Sdelphij    opc_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
417296341Sdelphij    opc_dsc.dsc$b_class = DSC$K_CLASS_S;
418296341Sdelphij    opc_dsc.dsc$a_pointer = (OPCDEF_TYPE) opcdef_p;
419296341Sdelphij    opc_dsc.dsc$w_length = len + 8;
42059191Skris
421296341Sdelphij    sys$sndopr(opc_dsc, 0);
42259191Skris
423296341Sdelphij    OPENSSL_free(opcdef_p);
42459191Skris}
42559191Skris
426296341Sdelphijstatic void xcloselog(BIO *bp)
42759191Skris{
42859191Skris}
42959191Skris
430296341Sdelphij# else                          /* Unix/Watt32 */
43159191Skris
432296341Sdelphijstatic void xopenlog(BIO *bp, char *name, int level)
43359191Skris{
434296341Sdelphij#  ifdef WATT32                 /* djgpp/DOS */
435296341Sdelphij    openlog(name, LOG_PID | LOG_CONS | LOG_NDELAY, level);
436296341Sdelphij#  else
437296341Sdelphij    openlog(name, LOG_PID | LOG_CONS, level);
438296341Sdelphij#  endif
43959191Skris}
44059191Skris
44159191Skrisstatic void xsyslog(BIO *bp, int priority, const char *string)
44259191Skris{
443296341Sdelphij    syslog(priority, "%s", string);
44459191Skris}
44559191Skris
446296341Sdelphijstatic void xcloselog(BIO *bp)
44759191Skris{
448296341Sdelphij    closelog();
44955714Skris}
45055714Skris
451296341Sdelphij# endif                         /* Unix */
45259191Skris
453296341Sdelphij#endif                          /* NO_SYSLOG */
454