bss_log.c revision 109998
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
1055714Skris *    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/*
5755714Skris	Why BIO_s_log?
5855714Skris
5955714Skris	BIO_s_log is useful for system daemons (or services under NT).
6059191Skris	It is one-way BIO, it sends all stuff to syslogd (on system that
6159191Skris	commonly use that), or event log (on NT), or OPCOM (on OpenVMS).
6255714Skris
6355714Skris*/
6455714Skris
6555714Skris
6655714Skris#include <stdio.h>
6755714Skris#include <errno.h>
6855714Skris
69109998Smarkm#include "cryptlib.h"
70109998Smarkm
71109998Smarkm#if defined(OPENSSL_SYS_WINCE)
72109998Smarkm#elif defined(OPENSSL_SYS_WIN32)
7359191Skris#  include <process.h>
74109998Smarkm#elif defined(OPENSSL_SYS_VMS)
7559191Skris#  include <opcdef.h>
7659191Skris#  include <descrip.h>
7759191Skris#  include <lib$routines.h>
7859191Skris#  include <starlet.h>
7959191Skris#elif defined(__ultrix)
8059191Skris#  include <sys/syslog.h>
81109998Smarkm#elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG)
8259191Skris#  include <syslog.h>
8355714Skris#endif
8455714Skris
8555714Skris#include <openssl/buffer.h>
8655714Skris#include <openssl/err.h>
8759191Skris
8855714Skris#ifndef NO_SYSLOG
8955714Skris
90109998Smarkm#if defined(OPENSSL_SYS_WIN32)
9159191Skris#define LOG_EMERG	0
9259191Skris#define LOG_ALERT	1
9359191Skris#define LOG_CRIT	2
9459191Skris#define LOG_ERR		3
9559191Skris#define LOG_WARNING	4
9659191Skris#define LOG_NOTICE	5
9759191Skris#define LOG_INFO	6
9859191Skris#define LOG_DEBUG	7
9955714Skris
10059191Skris#define LOG_DAEMON	(3<<3)
101109998Smarkm#elif defined(OPENSSL_SYS_VMS)
10259191Skris/* On VMS, we don't really care about these, but we need them to compile */
10359191Skris#define LOG_EMERG	0
10459191Skris#define LOG_ALERT	1
10559191Skris#define LOG_CRIT	2
10659191Skris#define LOG_ERR		3
10759191Skris#define LOG_WARNING	4
10859191Skris#define LOG_NOTICE	5
10959191Skris#define LOG_INFO	6
11059191Skris#define LOG_DEBUG	7
11159191Skris
11259191Skris#define LOG_DAEMON	OPC$M_NM_NTWORK
11359191Skris#endif
11459191Skris
11568651Skrisstatic int MS_CALLBACK slg_write(BIO *h, const char *buf, int num);
11668651Skrisstatic int MS_CALLBACK slg_puts(BIO *h, const char *str);
11768651Skrisstatic long MS_CALLBACK slg_ctrl(BIO *h, int cmd, long arg1, void *arg2);
11855714Skrisstatic int MS_CALLBACK slg_new(BIO *h);
11955714Skrisstatic int MS_CALLBACK slg_free(BIO *data);
12068651Skrisstatic void xopenlog(BIO* bp, char* name, int level);
12159191Skrisstatic void xsyslog(BIO* bp, int priority, const char* string);
12259191Skrisstatic void xcloselog(BIO* bp);
123109998Smarkm#ifdef OPENSSL_SYS_WIN32
12468651SkrisLONG	(WINAPI *go_for_advapi)()	= RegOpenKeyEx;
12568651SkrisHANDLE	(WINAPI *register_event_source)()	= NULL;
12668651SkrisBOOL	(WINAPI *deregister_event_source)()	= NULL;
12768651SkrisBOOL	(WINAPI *report_event)()	= NULL;
12868651Skris#define DL_PROC(m,f)	(GetProcAddress( m, f ))
12968651Skris#ifdef UNICODE
13068651Skris#define DL_PROC_X(m,f) DL_PROC( m, f "W" )
13168651Skris#else
13268651Skris#define DL_PROC_X(m,f) DL_PROC( m, f "A" )
13368651Skris#endif
13468651Skris#endif
13555714Skris
13655714Skrisstatic BIO_METHOD methods_slg=
13755714Skris	{
13855714Skris	BIO_TYPE_MEM,"syslog",
13955714Skris	slg_write,
14055714Skris	NULL,
14155714Skris	slg_puts,
14255714Skris	NULL,
14355714Skris	slg_ctrl,
14455714Skris	slg_new,
14555714Skris	slg_free,
14659191Skris	NULL,
14755714Skris	};
14855714Skris
14955714SkrisBIO_METHOD *BIO_s_log(void)
15055714Skris	{
15155714Skris	return(&methods_slg);
15255714Skris	}
15355714Skris
15455714Skrisstatic int MS_CALLBACK slg_new(BIO *bi)
15555714Skris	{
15655714Skris	bi->init=1;
15755714Skris	bi->num=0;
15855714Skris	bi->ptr=NULL;
15955714Skris	xopenlog(bi, "application", LOG_DAEMON);
16055714Skris	return(1);
16155714Skris	}
16255714Skris
16355714Skrisstatic int MS_CALLBACK slg_free(BIO *a)
16455714Skris	{
16555714Skris	if (a == NULL) return(0);
16655714Skris	xcloselog(a);
16755714Skris	return(1);
16855714Skris	}
16955714Skris
17068651Skrisstatic int MS_CALLBACK slg_write(BIO *b, const char *in, int inl)
17155714Skris	{
17255714Skris	int ret= inl;
17368651Skris	char* buf;
17455714Skris	char* pp;
17568651Skris	int priority, i;
17668651Skris	static struct
17768651Skris		{
17868651Skris		int strl;
17968651Skris		char str[10];
18068651Skris		int log_level;
18168651Skris		}
18268651Skris	mapping[] =
18368651Skris		{
18468651Skris		{ 6, "PANIC ", LOG_EMERG },
18568651Skris		{ 6, "EMERG ", LOG_EMERG },
18668651Skris		{ 4, "EMR ", LOG_EMERG },
18768651Skris		{ 6, "ALERT ", LOG_ALERT },
18868651Skris		{ 4, "ALR ", LOG_ALERT },
18968651Skris		{ 5, "CRIT ", LOG_CRIT },
19068651Skris		{ 4, "CRI ", LOG_CRIT },
19168651Skris		{ 6, "ERROR ", LOG_ERR },
19268651Skris		{ 4, "ERR ", LOG_ERR },
19368651Skris		{ 8, "WARNING ", LOG_WARNING },
19468651Skris		{ 5, "WARN ", LOG_WARNING },
19568651Skris		{ 4, "WAR ", LOG_WARNING },
19668651Skris		{ 7, "NOTICE ", LOG_NOTICE },
19768651Skris		{ 5, "NOTE ", LOG_NOTICE },
19868651Skris		{ 4, "NOT ", LOG_NOTICE },
19968651Skris		{ 5, "INFO ", LOG_INFO },
20068651Skris		{ 4, "INF ", LOG_INFO },
20168651Skris		{ 6, "DEBUG ", LOG_DEBUG },
20268651Skris		{ 4, "DBG ", LOG_DEBUG },
20368651Skris		{ 0, "", LOG_ERR } /* The default */
20468651Skris		};
20555714Skris
20668651Skris	if((buf= (char *)OPENSSL_malloc(inl+ 1)) == NULL){
20755714Skris		return(0);
20855714Skris	}
20955714Skris	strncpy(buf, in, inl);
21055714Skris	buf[inl]= '\0';
21155714Skris
21268651Skris	i = 0;
21368651Skris	while(strncmp(buf, mapping[i].str, mapping[i].strl) != 0) i++;
21468651Skris	priority = mapping[i].log_level;
21568651Skris	pp = buf + mapping[i].strl;
21655714Skris
21759191Skris	xsyslog(b, priority, pp);
21859191Skris
21968651Skris	OPENSSL_free(buf);
22055714Skris	return(ret);
22155714Skris	}
22255714Skris
22368651Skrisstatic long MS_CALLBACK slg_ctrl(BIO *b, int cmd, long num, void *ptr)
22455714Skris	{
22555714Skris	switch (cmd)
22655714Skris		{
22755714Skris	case BIO_CTRL_SET:
22855714Skris		xcloselog(b);
22955714Skris		xopenlog(b, ptr, num);
23055714Skris		break;
23155714Skris	default:
23255714Skris		break;
23355714Skris		}
23455714Skris	return(0);
23555714Skris	}
23655714Skris
23768651Skrisstatic int MS_CALLBACK slg_puts(BIO *bp, const char *str)
23855714Skris	{
23955714Skris	int n,ret;
24055714Skris
24155714Skris	n=strlen(str);
24255714Skris	ret=slg_write(bp,str,n);
24355714Skris	return(ret);
24455714Skris	}
24555714Skris
246109998Smarkm#if defined(OPENSSL_SYS_WIN32)
24759191Skris
24868651Skrisstatic void xopenlog(BIO* bp, char* name, int level)
24955714Skris{
25068651Skris	if ( !register_event_source )
25168651Skris		{
25268651Skris		HANDLE	advapi;
25368651Skris		if ( !(advapi = GetModuleHandle("advapi32")) )
25468651Skris			return;
25568651Skris		register_event_source = (HANDLE (WINAPI *)())DL_PROC_X(advapi,
25668651Skris			"RegisterEventSource" );
25768651Skris		deregister_event_source = (BOOL (WINAPI *)())DL_PROC(advapi,
25868651Skris			"DeregisterEventSource");
25968651Skris		report_event = (BOOL (WINAPI *)())DL_PROC_X(advapi,
26068651Skris			"ReportEvent" );
26168651Skris		if ( !(register_event_source && deregister_event_source &&
26268651Skris				report_event) )
26368651Skris			{
26468651Skris			register_event_source = NULL;
26568651Skris			deregister_event_source = NULL;
26668651Skris			report_event = NULL;
26768651Skris			return;
26868651Skris			}
26968651Skris		}
27068651Skris	bp->ptr= (char *)register_event_source(NULL, name);
27155714Skris}
27255714Skris
27359191Skrisstatic void xsyslog(BIO *bp, int priority, const char *string)
27455714Skris{
27559191Skris	LPCSTR lpszStrings[2];
27659191Skris	WORD evtype= EVENTLOG_ERROR_TYPE;
27759191Skris	int pid = _getpid();
278109998Smarkm	char pidbuf[DECIMAL_SIZE(pid)+4];
27959191Skris
28059191Skris	switch (priority)
28159191Skris		{
28268651Skris	case LOG_EMERG:
28368651Skris	case LOG_ALERT:
28468651Skris	case LOG_CRIT:
28559191Skris	case LOG_ERR:
28659191Skris		evtype = EVENTLOG_ERROR_TYPE;
28759191Skris		break;
28859191Skris	case LOG_WARNING:
28959191Skris		evtype = EVENTLOG_WARNING_TYPE;
29059191Skris		break;
29168651Skris	case LOG_NOTICE:
29259191Skris	case LOG_INFO:
29368651Skris	case LOG_DEBUG:
29459191Skris		evtype = EVENTLOG_INFORMATION_TYPE;
29559191Skris		break;
29668651Skris	default:		/* Should never happen, but set it
29768651Skris				   as error anyway. */
29859191Skris		evtype = EVENTLOG_ERROR_TYPE;
29959191Skris		break;
30059191Skris		}
30159191Skris
30259191Skris	sprintf(pidbuf, "[%d] ", pid);
30359191Skris	lpszStrings[0] = pidbuf;
30459191Skris	lpszStrings[1] = string;
30559191Skris
30668651Skris	if(report_event && bp->ptr)
30768651Skris		report_event(bp->ptr, evtype, 0, 1024, NULL, 2, 0,
30859191Skris				lpszStrings, NULL);
30959191Skris}
31059191Skris
31159191Skrisstatic void xcloselog(BIO* bp)
31259191Skris{
31368651Skris	if(deregister_event_source && bp->ptr)
31468651Skris		deregister_event_source((HANDLE)(bp->ptr));
31555714Skris	bp->ptr= NULL;
31659191Skris}
31759191Skris
318109998Smarkm#elif defined(OPENSSL_SYS_VMS)
31959191Skris
32059191Skrisstatic int VMS_OPC_target = LOG_DAEMON;
32159191Skris
32268651Skrisstatic void xopenlog(BIO* bp, char* name, int level)
32359191Skris{
32459191Skris	VMS_OPC_target = level;
32559191Skris}
32659191Skris
32759191Skrisstatic void xsyslog(BIO *bp, int priority, const char *string)
32859191Skris{
32959191Skris	struct dsc$descriptor_s opc_dsc;
33059191Skris	struct opcdef *opcdef_p;
33159191Skris	char buf[10240];
33259191Skris	unsigned int len;
33359191Skris        struct dsc$descriptor_s buf_dsc;
33459191Skris	$DESCRIPTOR(fao_cmd, "!AZ: !AZ");
33559191Skris	char *priority_tag;
33659191Skris
33759191Skris	switch (priority)
33859191Skris	  {
33959191Skris	  case LOG_EMERG: priority_tag = "Emergency"; break;
34059191Skris	  case LOG_ALERT: priority_tag = "Alert"; break;
34159191Skris	  case LOG_CRIT: priority_tag = "Critical"; break;
34259191Skris	  case LOG_ERR: priority_tag = "Error"; break;
34359191Skris	  case LOG_WARNING: priority_tag = "Warning"; break;
34459191Skris	  case LOG_NOTICE: priority_tag = "Notice"; break;
34559191Skris	  case LOG_INFO: priority_tag = "Info"; break;
34659191Skris	  case LOG_DEBUG: priority_tag = "DEBUG"; break;
34759191Skris	  }
34859191Skris
34959191Skris	buf_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
35059191Skris	buf_dsc.dsc$b_class = DSC$K_CLASS_S;
35159191Skris	buf_dsc.dsc$a_pointer = buf;
35259191Skris	buf_dsc.dsc$w_length = sizeof(buf) - 1;
35359191Skris
35459191Skris	lib$sys_fao(&fao_cmd, &len, &buf_dsc, priority_tag, string);
35559191Skris
35659191Skris	/* we know there's an 8 byte header.  That's documented */
35768651Skris	opcdef_p = (struct opcdef *) OPENSSL_malloc(8 + len);
35859191Skris	opcdef_p->opc$b_ms_type = OPC$_RQ_RQST;
35959191Skris	memcpy(opcdef_p->opc$z_ms_target_classes, &VMS_OPC_target, 3);
36059191Skris	opcdef_p->opc$l_ms_rqstid = 0;
36159191Skris	memcpy(&opcdef_p->opc$l_ms_text, buf, len);
36259191Skris
36359191Skris	opc_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
36459191Skris	opc_dsc.dsc$b_class = DSC$K_CLASS_S;
36559191Skris	opc_dsc.dsc$a_pointer = (char *)opcdef_p;
36659191Skris	opc_dsc.dsc$w_length = len + 8;
36759191Skris
36859191Skris	sys$sndopr(opc_dsc, 0);
36959191Skris
37068651Skris	OPENSSL_free(opcdef_p);
37159191Skris}
37259191Skris
37359191Skrisstatic void xcloselog(BIO* bp)
37459191Skris{
37559191Skris}
37659191Skris
377109998Smarkm#else /* Unix/Watt32 */
37859191Skris
37968651Skrisstatic void xopenlog(BIO* bp, char* name, int level)
38059191Skris{
381109998Smarkm#ifdef WATT32   /* djgpp/DOS */
382109998Smarkm	openlog(name, LOG_PID|LOG_CONS|LOG_NDELAY, level);
383109998Smarkm#else
38459191Skris	openlog(name, LOG_PID|LOG_CONS, level);
385109998Smarkm#endif
38659191Skris}
38759191Skris
38859191Skrisstatic void xsyslog(BIO *bp, int priority, const char *string)
38959191Skris{
39059191Skris	syslog(priority, "%s", string);
39159191Skris}
39259191Skris
39359191Skrisstatic void xcloselog(BIO* bp)
39459191Skris{
39555714Skris	closelog();
39655714Skris}
39755714Skris
39859191Skris#endif /* Unix */
39959191Skris
40059191Skris#endif /* NO_SYSLOG */
401