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
10296465Sdelphij *    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/*
57296465Sdelphij * Why BIO_s_log?
58296465Sdelphij *
59296465Sdelphij * BIO_s_log is useful for system daemons (or services under NT). It is
60296465Sdelphij * one-way BIO, it sends all stuff to syslogd (on system that commonly use
61296465Sdelphij * that), or event log (on NT), or OPCOM (on OpenVMS).
62296465Sdelphij *
63296465Sdelphij */
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)
72296465Sdelphij# include <process.h>
73109998Smarkm#elif defined(OPENSSL_SYS_VMS)
74296465Sdelphij# include <opcdef.h>
75296465Sdelphij# include <descrip.h>
76296465Sdelphij# include <lib$routines.h>
77296465Sdelphij# include <starlet.h>
7859191Skris#elif defined(__ultrix)
79296465Sdelphij# include <sys/syslog.h>
80160814Ssimon#elif defined(OPENSSL_SYS_NETWARE)
81296465Sdelphij# define NO_SYSLOG
82109998Smarkm#elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG)
83296465Sdelphij# include <syslog.h>
8455714Skris#endif
8555714Skris
8655714Skris#include <openssl/buffer.h>
8755714Skris#include <openssl/err.h>
8859191Skris
8955714Skris#ifndef NO_SYSLOG
9055714Skris
91296465Sdelphij# if defined(OPENSSL_SYS_WIN32)
92296465Sdelphij#  define LOG_EMERG       0
93296465Sdelphij#  define LOG_ALERT       1
94296465Sdelphij#  define LOG_CRIT        2
95296465Sdelphij#  define LOG_ERR         3
96296465Sdelphij#  define LOG_WARNING     4
97296465Sdelphij#  define LOG_NOTICE      5
98296465Sdelphij#  define LOG_INFO        6
99296465Sdelphij#  define LOG_DEBUG       7
10055714Skris
101296465Sdelphij#  define LOG_DAEMON      (3<<3)
102296465Sdelphij# elif defined(OPENSSL_SYS_VMS)
10359191Skris/* On VMS, we don't really care about these, but we need them to compile */
104296465Sdelphij#  define LOG_EMERG       0
105296465Sdelphij#  define LOG_ALERT       1
106296465Sdelphij#  define LOG_CRIT        2
107296465Sdelphij#  define LOG_ERR         3
108296465Sdelphij#  define LOG_WARNING     4
109296465Sdelphij#  define LOG_NOTICE      5
110296465Sdelphij#  define LOG_INFO        6
111296465Sdelphij#  define LOG_DEBUG       7
11259191Skris
113296465Sdelphij#  define LOG_DAEMON      OPC$M_NM_NTWORK
114296465Sdelphij# endif
11559191Skris
11668651Skrisstatic int MS_CALLBACK slg_write(BIO *h, const char *buf, int num);
11768651Skrisstatic int MS_CALLBACK slg_puts(BIO *h, const char *str);
11868651Skrisstatic long MS_CALLBACK slg_ctrl(BIO *h, int cmd, long arg1, void *arg2);
11955714Skrisstatic int MS_CALLBACK slg_new(BIO *h);
12055714Skrisstatic int MS_CALLBACK slg_free(BIO *data);
121296465Sdelphijstatic void xopenlog(BIO *bp, char *name, int level);
122296465Sdelphijstatic void xsyslog(BIO *bp, int priority, const char *string);
123296465Sdelphijstatic void xcloselog(BIO *bp);
124296465Sdelphij# ifdef OPENSSL_SYS_WIN32
125296465SdelphijLONG(WINAPI *go_for_advapi) () = RegOpenKeyEx;
126296465SdelphijHANDLE(WINAPI *register_event_source) () = NULL;
127296465SdelphijBOOL(WINAPI *deregister_event_source) () = NULL;
128296465SdelphijBOOL(WINAPI *report_event) () = NULL;
129296465Sdelphij#  define DL_PROC(m,f)    (GetProcAddress( m, f ))
130296465Sdelphij#  ifdef UNICODE
131296465Sdelphij#   define DL_PROC_X(m,f) DL_PROC( m, f "W" )
132296465Sdelphij#  else
133296465Sdelphij#   define DL_PROC_X(m,f) DL_PROC( m, f "A" )
134296465Sdelphij#  endif
135296465Sdelphij# endif
13655714Skris
137296465Sdelphijstatic BIO_METHOD methods_slg = {
138296465Sdelphij    BIO_TYPE_MEM, "syslog",
139296465Sdelphij    slg_write,
140296465Sdelphij    NULL,
141296465Sdelphij    slg_puts,
142296465Sdelphij    NULL,
143296465Sdelphij    slg_ctrl,
144296465Sdelphij    slg_new,
145296465Sdelphij    slg_free,
146296465Sdelphij    NULL,
147296465Sdelphij};
14855714Skris
14955714SkrisBIO_METHOD *BIO_s_log(void)
150296465Sdelphij{
151296465Sdelphij    return (&methods_slg);
152296465Sdelphij}
15355714Skris
15455714Skrisstatic int MS_CALLBACK slg_new(BIO *bi)
155296465Sdelphij{
156296465Sdelphij    bi->init = 1;
157296465Sdelphij    bi->num = 0;
158296465Sdelphij    bi->ptr = NULL;
159296465Sdelphij    xopenlog(bi, "application", LOG_DAEMON);
160296465Sdelphij    return (1);
161296465Sdelphij}
16255714Skris
16355714Skrisstatic int MS_CALLBACK slg_free(BIO *a)
164296465Sdelphij{
165296465Sdelphij    if (a == NULL)
166296465Sdelphij        return (0);
167296465Sdelphij    xcloselog(a);
168296465Sdelphij    return (1);
169296465Sdelphij}
170296465Sdelphij
17168651Skrisstatic int MS_CALLBACK slg_write(BIO *b, const char *in, int inl)
172296465Sdelphij{
173296465Sdelphij    int ret = inl;
174296465Sdelphij    char *buf;
175296465Sdelphij    char *pp;
176296465Sdelphij    int priority, i;
177296465Sdelphij    static struct {
178296465Sdelphij        int strl;
179296465Sdelphij        char str[10];
180296465Sdelphij        int log_level;
181296465Sdelphij    } mapping[] = {
182296465Sdelphij        {
183296465Sdelphij            6, "PANIC ", LOG_EMERG
184296465Sdelphij        },
185296465Sdelphij        {
186296465Sdelphij            6, "EMERG ", LOG_EMERG
187296465Sdelphij        },
188296465Sdelphij        {
189296465Sdelphij            4, "EMR ", LOG_EMERG
190296465Sdelphij        },
191296465Sdelphij        {
192296465Sdelphij            6, "ALERT ", LOG_ALERT
193296465Sdelphij        },
194296465Sdelphij        {
195296465Sdelphij            4, "ALR ", LOG_ALERT
196296465Sdelphij        },
197296465Sdelphij        {
198296465Sdelphij            5, "CRIT ", LOG_CRIT
199296465Sdelphij        },
200296465Sdelphij        {
201296465Sdelphij            4, "CRI ", LOG_CRIT
202296465Sdelphij        },
203296465Sdelphij        {
204296465Sdelphij            6, "ERROR ", LOG_ERR
205296465Sdelphij        },
206296465Sdelphij        {
207296465Sdelphij            4, "ERR ", LOG_ERR
208296465Sdelphij        },
209296465Sdelphij        {
210296465Sdelphij            8, "WARNING ", LOG_WARNING
211296465Sdelphij        },
212296465Sdelphij        {
213296465Sdelphij            5, "WARN ", LOG_WARNING
214296465Sdelphij        },
215296465Sdelphij        {
216296465Sdelphij            4, "WAR ", LOG_WARNING
217296465Sdelphij        },
218296465Sdelphij        {
219296465Sdelphij            7, "NOTICE ", LOG_NOTICE
220296465Sdelphij        },
221296465Sdelphij        {
222296465Sdelphij            5, "NOTE ", LOG_NOTICE
223296465Sdelphij        },
224296465Sdelphij        {
225296465Sdelphij            4, "NOT ", LOG_NOTICE
226296465Sdelphij        },
227296465Sdelphij        {
228296465Sdelphij            5, "INFO ", LOG_INFO
229296465Sdelphij        },
230296465Sdelphij        {
231296465Sdelphij            4, "INF ", LOG_INFO
232296465Sdelphij        },
233296465Sdelphij        {
234296465Sdelphij            6, "DEBUG ", LOG_DEBUG
235296465Sdelphij        },
236296465Sdelphij        {
237296465Sdelphij            4, "DBG ", LOG_DEBUG
238296465Sdelphij        },
239296465Sdelphij        {
240296465Sdelphij            0, "", LOG_ERR
241296465Sdelphij        }
242296465Sdelphij        /* The default */
243296465Sdelphij    };
24455714Skris
245296465Sdelphij    if ((buf = (char *)OPENSSL_malloc(inl + 1)) == NULL) {
246296465Sdelphij        return (0);
247296465Sdelphij    }
248296465Sdelphij    strncpy(buf, in, inl);
249296465Sdelphij    buf[inl] = '\0';
25055714Skris
251296465Sdelphij    i = 0;
252296465Sdelphij    while (strncmp(buf, mapping[i].str, mapping[i].strl) != 0)
253296465Sdelphij        i++;
254296465Sdelphij    priority = mapping[i].log_level;
255296465Sdelphij    pp = buf + mapping[i].strl;
25655714Skris
257296465Sdelphij    xsyslog(b, priority, pp);
25859191Skris
259296465Sdelphij    OPENSSL_free(buf);
260296465Sdelphij    return (ret);
261296465Sdelphij}
26255714Skris
26368651Skrisstatic long MS_CALLBACK slg_ctrl(BIO *b, int cmd, long num, void *ptr)
264296465Sdelphij{
265296465Sdelphij    switch (cmd) {
266296465Sdelphij    case BIO_CTRL_SET:
267296465Sdelphij        xcloselog(b);
268296465Sdelphij        xopenlog(b, ptr, num);
269296465Sdelphij        break;
270296465Sdelphij    default:
271296465Sdelphij        break;
272296465Sdelphij    }
273296465Sdelphij    return (0);
274296465Sdelphij}
27555714Skris
27668651Skrisstatic int MS_CALLBACK slg_puts(BIO *bp, const char *str)
277296465Sdelphij{
278296465Sdelphij    int n, ret;
27955714Skris
280296465Sdelphij    n = strlen(str);
281296465Sdelphij    ret = slg_write(bp, str, n);
282296465Sdelphij    return (ret);
283296465Sdelphij}
28455714Skris
285296465Sdelphij# if defined(OPENSSL_SYS_WIN32)
28659191Skris
287296465Sdelphijstatic void xopenlog(BIO *bp, char *name, int level)
28855714Skris{
289296465Sdelphij    if (!register_event_source) {
290296465Sdelphij        HANDLE advapi;
291296465Sdelphij        if (!(advapi = GetModuleHandle("advapi32")))
292296465Sdelphij            return;
293296465Sdelphij        register_event_source = (HANDLE(WINAPI *)())DL_PROC_X(advapi,
294296465Sdelphij                                                              "RegisterEventSource");
295296465Sdelphij        deregister_event_source = (BOOL(WINAPI *)()) DL_PROC(advapi,
296296465Sdelphij                                                             "DeregisterEventSource");
297296465Sdelphij        report_event = (BOOL(WINAPI *)()) DL_PROC_X(advapi, "ReportEvent");
298296465Sdelphij        if (!(register_event_source && deregister_event_source &&
299296465Sdelphij              report_event)) {
300296465Sdelphij            register_event_source = NULL;
301296465Sdelphij            deregister_event_source = NULL;
302296465Sdelphij            report_event = NULL;
303296465Sdelphij            return;
304296465Sdelphij        }
305296465Sdelphij    }
306296465Sdelphij    bp->ptr = (char *)register_event_source(NULL, name);
30755714Skris}
30855714Skris
30959191Skrisstatic void xsyslog(BIO *bp, int priority, const char *string)
31055714Skris{
311296465Sdelphij    LPCSTR lpszStrings[2];
312296465Sdelphij    WORD evtype = EVENTLOG_ERROR_TYPE;
313296465Sdelphij    int pid = _getpid();
314296465Sdelphij    char pidbuf[DECIMAL_SIZE(pid) + 4];
31559191Skris
316296465Sdelphij    switch (priority) {
317296465Sdelphij    case LOG_EMERG:
318296465Sdelphij    case LOG_ALERT:
319296465Sdelphij    case LOG_CRIT:
320296465Sdelphij    case LOG_ERR:
321296465Sdelphij        evtype = EVENTLOG_ERROR_TYPE;
322296465Sdelphij        break;
323296465Sdelphij    case LOG_WARNING:
324296465Sdelphij        evtype = EVENTLOG_WARNING_TYPE;
325296465Sdelphij        break;
326296465Sdelphij    case LOG_NOTICE:
327296465Sdelphij    case LOG_INFO:
328296465Sdelphij    case LOG_DEBUG:
329296465Sdelphij        evtype = EVENTLOG_INFORMATION_TYPE;
330296465Sdelphij        break;
331296465Sdelphij    default:
332296465Sdelphij        /*
333296465Sdelphij         * Should never happen, but set it
334296465Sdelphij         * as error anyway.
335296465Sdelphij         */
336296465Sdelphij        evtype = EVENTLOG_ERROR_TYPE;
337296465Sdelphij        break;
338296465Sdelphij    }
33959191Skris
340296465Sdelphij    sprintf(pidbuf, "[%d] ", pid);
341296465Sdelphij    lpszStrings[0] = pidbuf;
342296465Sdelphij    lpszStrings[1] = string;
34359191Skris
344296465Sdelphij    if (report_event && bp->ptr)
345296465Sdelphij        report_event(bp->ptr, evtype, 0, 1024, NULL, 2, 0, lpszStrings, NULL);
34659191Skris}
347296465Sdelphij
348296465Sdelphijstatic void xcloselog(BIO *bp)
34959191Skris{
350296465Sdelphij    if (deregister_event_source && bp->ptr)
351296465Sdelphij        deregister_event_source((HANDLE) (bp->ptr));
352296465Sdelphij    bp->ptr = NULL;
35359191Skris}
35459191Skris
355296465Sdelphij# elif defined(OPENSSL_SYS_VMS)
35659191Skris
35759191Skrisstatic int VMS_OPC_target = LOG_DAEMON;
35859191Skris
359296465Sdelphijstatic void xopenlog(BIO *bp, char *name, int level)
36059191Skris{
361296465Sdelphij    VMS_OPC_target = level;
36259191Skris}
36359191Skris
36459191Skrisstatic void xsyslog(BIO *bp, int priority, const char *string)
36559191Skris{
366296465Sdelphij    struct dsc$descriptor_s opc_dsc;
367296465Sdelphij    struct opcdef *opcdef_p;
368296465Sdelphij    char buf[10240];
369296465Sdelphij    unsigned int len;
370296465Sdelphij    struct dsc$descriptor_s buf_dsc;
371296465Sdelphij    $DESCRIPTOR(fao_cmd, "!AZ: !AZ");
372296465Sdelphij    char *priority_tag;
37359191Skris
374296465Sdelphij    switch (priority) {
375296465Sdelphij    case LOG_EMERG:
376296465Sdelphij        priority_tag = "Emergency";
377296465Sdelphij        break;
378296465Sdelphij    case LOG_ALERT:
379296465Sdelphij        priority_tag = "Alert";
380296465Sdelphij        break;
381296465Sdelphij    case LOG_CRIT:
382296465Sdelphij        priority_tag = "Critical";
383296465Sdelphij        break;
384296465Sdelphij    case LOG_ERR:
385296465Sdelphij        priority_tag = "Error";
386296465Sdelphij        break;
387296465Sdelphij    case LOG_WARNING:
388296465Sdelphij        priority_tag = "Warning";
389296465Sdelphij        break;
390296465Sdelphij    case LOG_NOTICE:
391296465Sdelphij        priority_tag = "Notice";
392296465Sdelphij        break;
393296465Sdelphij    case LOG_INFO:
394296465Sdelphij        priority_tag = "Info";
395296465Sdelphij        break;
396296465Sdelphij    case LOG_DEBUG:
397296465Sdelphij        priority_tag = "DEBUG";
398296465Sdelphij        break;
399296465Sdelphij    }
40059191Skris
401296465Sdelphij    buf_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
402296465Sdelphij    buf_dsc.dsc$b_class = DSC$K_CLASS_S;
403296465Sdelphij    buf_dsc.dsc$a_pointer = buf;
404296465Sdelphij    buf_dsc.dsc$w_length = sizeof(buf) - 1;
40559191Skris
406296465Sdelphij    lib$sys_fao(&fao_cmd, &len, &buf_dsc, priority_tag, string);
40759191Skris
408296465Sdelphij    /* we know there's an 8 byte header.  That's documented */
409296465Sdelphij    opcdef_p = (struct opcdef *)OPENSSL_malloc(8 + len);
410296465Sdelphij    opcdef_p->opc$b_ms_type = OPC$_RQ_RQST;
411296465Sdelphij    memcpy(opcdef_p->opc$z_ms_target_classes, &VMS_OPC_target, 3);
412296465Sdelphij    opcdef_p->opc$l_ms_rqstid = 0;
413296465Sdelphij    memcpy(&opcdef_p->opc$l_ms_text, buf, len);
41459191Skris
415296465Sdelphij    opc_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
416296465Sdelphij    opc_dsc.dsc$b_class = DSC$K_CLASS_S;
417296465Sdelphij    opc_dsc.dsc$a_pointer = (char *)opcdef_p;
418296465Sdelphij    opc_dsc.dsc$w_length = len + 8;
41959191Skris
420296465Sdelphij    sys$sndopr(opc_dsc, 0);
42159191Skris
422296465Sdelphij    OPENSSL_free(opcdef_p);
42359191Skris}
42459191Skris
425296465Sdelphijstatic void xcloselog(BIO *bp)
42659191Skris{
42759191Skris}
42859191Skris
429296465Sdelphij# else                          /* Unix/Watt32 */
43059191Skris
431296465Sdelphijstatic void xopenlog(BIO *bp, char *name, int level)
43259191Skris{
433296465Sdelphij#  ifdef WATT32                 /* djgpp/DOS */
434296465Sdelphij    openlog(name, LOG_PID | LOG_CONS | LOG_NDELAY, level);
435296465Sdelphij#  else
436296465Sdelphij    openlog(name, LOG_PID | LOG_CONS, level);
437296465Sdelphij#  endif
43859191Skris}
43959191Skris
44059191Skrisstatic void xsyslog(BIO *bp, int priority, const char *string)
44159191Skris{
442296465Sdelphij    syslog(priority, "%s", string);
44359191Skris}
44459191Skris
445296465Sdelphijstatic void xcloselog(BIO *bp)
44659191Skris{
447296465Sdelphij    closelog();
44855714Skris}
44955714Skris
450296465Sdelphij# endif                         /* Unix */
45159191Skris
452296465Sdelphij#endif                          /* NO_SYSLOG */
453