sl@0: /* crypto/bio/bss_log.c */ sl@0: /* ==================================================================== sl@0: * Copyright (c) 1999 The OpenSSL Project. All rights reserved. sl@0: * sl@0: * Redistribution and use in source and binary forms, with or without sl@0: * modification, are permitted provided that the following conditions sl@0: * are met: sl@0: * sl@0: * 1. Redistributions of source code must retain the above copyright sl@0: * notice, this list of conditions and the following disclaimer. sl@0: * sl@0: * 2. Redistributions in binary form must reproduce the above copyright sl@0: * notice, this list of conditions and the following disclaimer in sl@0: * the documentation and/or other materials provided with the sl@0: * distribution. sl@0: * sl@0: * 3. All advertising materials mentioning features or use of this sl@0: * software must display the following acknowledgment: sl@0: * "This product includes software developed by the OpenSSL Project sl@0: * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" sl@0: * sl@0: * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to sl@0: * endorse or promote products derived from this software without sl@0: * prior written permission. For written permission, please contact sl@0: * licensing@OpenSSL.org. sl@0: * sl@0: * 5. Products derived from this software may not be called "OpenSSL" sl@0: * nor may "OpenSSL" appear in their names without prior written sl@0: * permission of the OpenSSL Project. sl@0: * sl@0: * 6. Redistributions of any form whatsoever must retain the following sl@0: * acknowledgment: sl@0: * "This product includes software developed by the OpenSSL Project sl@0: * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" sl@0: * sl@0: * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY sl@0: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE sl@0: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR sl@0: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR sl@0: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, sl@0: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT sl@0: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; sl@0: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) sl@0: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, sl@0: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) sl@0: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED sl@0: * OF THE POSSIBILITY OF SUCH DAMAGE. sl@0: * ==================================================================== sl@0: * sl@0: * This product includes cryptographic software written by Eric Young sl@0: * (eay@cryptsoft.com). This product includes software written by Tim sl@0: * Hudson (tjh@cryptsoft.com). sl@0: * sl@0: */ sl@0: /* sl@0: © Portions copyright (c) 2006 Nokia Corporation. All rights reserved. sl@0: */ sl@0: /* sl@0: Why BIO_s_log? sl@0: sl@0: BIO_s_log is useful for system daemons (or services under NT). sl@0: It is one-way BIO, it sends all stuff to syslogd (on system that sl@0: commonly use that), or event log (on NT), or OPCOM (on OpenVMS). sl@0: sl@0: */ sl@0: sl@0: sl@0: #include sl@0: #include sl@0: sl@0: #include "cryptlib.h" sl@0: sl@0: #if defined(OPENSSL_SYS_WINCE) sl@0: #elif defined(OPENSSL_SYS_WIN32) sl@0: # include sl@0: #elif defined(OPENSSL_SYS_VMS) sl@0: # include sl@0: # include sl@0: # include sl@0: # include sl@0: #elif defined(__ultrix) sl@0: # include sl@0: #elif defined(OPENSSL_SYS_NETWARE) sl@0: # define NO_SYSLOG sl@0: #elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG) sl@0: # include sl@0: #endif sl@0: sl@0: #include sl@0: #include sl@0: #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__))) sl@0: #include "libcrypto_wsd_macros.h" sl@0: #include "libcrypto_wsd.h" sl@0: #endif sl@0: sl@0: sl@0: #ifndef NO_SYSLOG sl@0: sl@0: #if defined(OPENSSL_SYS_WIN32) sl@0: #define LOG_EMERG 0 sl@0: #define LOG_ALERT 1 sl@0: #define LOG_CRIT 2 sl@0: #define LOG_ERR 3 sl@0: #define LOG_WARNING 4 sl@0: #define LOG_NOTICE 5 sl@0: #define LOG_INFO 6 sl@0: #define LOG_DEBUG 7 sl@0: sl@0: #define LOG_DAEMON (3<<3) sl@0: #elif defined(OPENSSL_SYS_VMS) sl@0: /* On VMS, we don't really care about these, but we need them to compile */ sl@0: #define LOG_EMERG 0 sl@0: #define LOG_ALERT 1 sl@0: #define LOG_CRIT 2 sl@0: #define LOG_ERR 3 sl@0: #define LOG_WARNING 4 sl@0: #define LOG_NOTICE 5 sl@0: #define LOG_INFO 6 sl@0: #define LOG_DEBUG 7 sl@0: sl@0: #define LOG_DAEMON OPC$M_NM_NTWORK sl@0: #endif sl@0: sl@0: static int MS_CALLBACK slg_write(BIO *h, const char *buf, int num); sl@0: static int MS_CALLBACK slg_puts(BIO *h, const char *str); sl@0: static long MS_CALLBACK slg_ctrl(BIO *h, int cmd, long arg1, void *arg2); sl@0: static int MS_CALLBACK slg_new(BIO *h); sl@0: static int MS_CALLBACK slg_free(BIO *data); sl@0: static void xopenlog(BIO* bp, char* name, int level); sl@0: static void xsyslog(BIO* bp, int priority, const char* string); sl@0: static void xcloselog(BIO* bp); sl@0: #ifdef OPENSSL_SYS_WIN32 sl@0: LONG (WINAPI *go_for_advapi)() = RegOpenKeyEx; sl@0: HANDLE (WINAPI *register_event_source)() = NULL; sl@0: BOOL (WINAPI *deregister_event_source)() = NULL; sl@0: BOOL (WINAPI *report_event)() = NULL; sl@0: #define DL_PROC(m,f) (GetProcAddress( m, f )) sl@0: #ifdef UNICODE sl@0: #define DL_PROC_X(m,f) DL_PROC( m, f "W" ) sl@0: #else sl@0: #define DL_PROC_X(m,f) DL_PROC( m, f "A" ) sl@0: #endif sl@0: #endif sl@0: sl@0: #ifndef EMULATOR sl@0: static BIO_METHOD methods_slg= sl@0: { sl@0: BIO_TYPE_MEM,"syslog", sl@0: slg_write, sl@0: NULL, sl@0: slg_puts, sl@0: NULL, sl@0: slg_ctrl, sl@0: slg_new, sl@0: slg_free, sl@0: NULL, sl@0: }; sl@0: #else sl@0: sl@0: GET_STATIC_VAR_FROM_TLS(methods_slg,bss_log,BIO_METHOD) sl@0: #define methods_slg (*GET_WSD_VAR_NAME(methods_slg,bss_log,s)()) sl@0: const BIO_METHOD temp_s_methods_slg= sl@0: { sl@0: BIO_TYPE_MEM,"syslog", sl@0: slg_write, sl@0: NULL, sl@0: slg_puts, sl@0: NULL, sl@0: slg_ctrl, sl@0: slg_new, sl@0: slg_free, sl@0: NULL, sl@0: }; sl@0: sl@0: #endif sl@0: sl@0: EXPORT_C BIO_METHOD *BIO_s_log(void) sl@0: { sl@0: return(&methods_slg); sl@0: } sl@0: sl@0: static int MS_CALLBACK slg_new(BIO *bi) sl@0: { sl@0: bi->init=1; sl@0: bi->num=0; sl@0: bi->ptr=NULL; sl@0: xopenlog(bi, "application", LOG_DAEMON); sl@0: return(1); sl@0: } sl@0: sl@0: static int MS_CALLBACK slg_free(BIO *a) sl@0: { sl@0: if (a == NULL) return(0); sl@0: xcloselog(a); sl@0: return(1); sl@0: } sl@0: sl@0: static int MS_CALLBACK slg_write(BIO *b, const char *in, int inl) sl@0: { sl@0: int ret= inl; sl@0: char* buf; sl@0: char* pp; sl@0: int priority, i; sl@0: static struct sl@0: { sl@0: int strl; sl@0: char str[10]; sl@0: int log_level; sl@0: } sl@0: mapping[] = sl@0: { sl@0: { 6, "PANIC ", LOG_EMERG }, sl@0: { 6, "EMERG ", LOG_EMERG }, sl@0: { 4, "EMR ", LOG_EMERG }, sl@0: { 6, "ALERT ", LOG_ALERT }, sl@0: { 4, "ALR ", LOG_ALERT }, sl@0: { 5, "CRIT ", LOG_CRIT }, sl@0: { 4, "CRI ", LOG_CRIT }, sl@0: { 6, "ERROR ", LOG_ERR }, sl@0: { 4, "ERR ", LOG_ERR }, sl@0: { 8, "WARNING ", LOG_WARNING }, sl@0: { 5, "WARN ", LOG_WARNING }, sl@0: { 4, "WAR ", LOG_WARNING }, sl@0: { 7, "NOTICE ", LOG_NOTICE }, sl@0: { 5, "NOTE ", LOG_NOTICE }, sl@0: { 4, "NOT ", LOG_NOTICE }, sl@0: { 5, "INFO ", LOG_INFO }, sl@0: { 4, "INF ", LOG_INFO }, sl@0: { 6, "DEBUG ", LOG_DEBUG }, sl@0: { 4, "DBG ", LOG_DEBUG }, sl@0: { 0, "", LOG_ERR } /* The default */ sl@0: }; sl@0: sl@0: if((buf= (char *)OPENSSL_malloc(inl+ 1)) == NULL){ sl@0: return(0); sl@0: } sl@0: strncpy(buf, in, inl); sl@0: buf[inl]= '\0'; sl@0: sl@0: i = 0; sl@0: while(strncmp(buf, mapping[i].str, mapping[i].strl) != 0) i++; sl@0: priority = mapping[i].log_level; sl@0: pp = buf + mapping[i].strl; sl@0: sl@0: xsyslog(b, priority, pp); sl@0: sl@0: OPENSSL_free(buf); sl@0: return(ret); sl@0: } sl@0: sl@0: static long MS_CALLBACK slg_ctrl(BIO *b, int cmd, long num, void *ptr) sl@0: { sl@0: switch (cmd) sl@0: { sl@0: case BIO_CTRL_SET: sl@0: xcloselog(b); sl@0: xopenlog(b, ptr, num); sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: return(0); sl@0: } sl@0: sl@0: static int MS_CALLBACK slg_puts(BIO *bp, const char *str) sl@0: { sl@0: int n,ret; sl@0: sl@0: n=strlen(str); sl@0: ret=slg_write(bp,str,n); sl@0: return(ret); sl@0: } sl@0: sl@0: #if defined(OPENSSL_SYS_WIN32) sl@0: sl@0: static void xopenlog(BIO* bp, char* name, int level) sl@0: { sl@0: if ( !register_event_source ) sl@0: { sl@0: HANDLE advapi; sl@0: if ( !(advapi = GetModuleHandle("advapi32")) ) sl@0: return; sl@0: register_event_source = (HANDLE (WINAPI *)())DL_PROC_X(advapi, sl@0: "RegisterEventSource" ); sl@0: deregister_event_source = (BOOL (WINAPI *)())DL_PROC(advapi, sl@0: "DeregisterEventSource"); sl@0: report_event = (BOOL (WINAPI *)())DL_PROC_X(advapi, sl@0: "ReportEvent" ); sl@0: if ( !(register_event_source && deregister_event_source && sl@0: report_event) ) sl@0: { sl@0: register_event_source = NULL; sl@0: deregister_event_source = NULL; sl@0: report_event = NULL; sl@0: return; sl@0: } sl@0: } sl@0: bp->ptr= (char *)register_event_source(NULL, name); sl@0: } sl@0: sl@0: static void xsyslog(BIO *bp, int priority, const char *string) sl@0: { sl@0: LPCSTR lpszStrings[2]; sl@0: WORD evtype= EVENTLOG_ERROR_TYPE; sl@0: int pid = _getpid(); sl@0: char pidbuf[DECIMAL_SIZE(pid)+4]; sl@0: sl@0: switch (priority) sl@0: { sl@0: case LOG_EMERG: sl@0: case LOG_ALERT: sl@0: case LOG_CRIT: sl@0: case LOG_ERR: sl@0: evtype = EVENTLOG_ERROR_TYPE; sl@0: break; sl@0: case LOG_WARNING: sl@0: evtype = EVENTLOG_WARNING_TYPE; sl@0: break; sl@0: case LOG_NOTICE: sl@0: case LOG_INFO: sl@0: case LOG_DEBUG: sl@0: evtype = EVENTLOG_INFORMATION_TYPE; sl@0: break; sl@0: default: /* Should never happen, but set it sl@0: as error anyway. */ sl@0: evtype = EVENTLOG_ERROR_TYPE; sl@0: break; sl@0: } sl@0: sl@0: sprintf(pidbuf, "[%d] ", pid); sl@0: lpszStrings[0] = pidbuf; sl@0: lpszStrings[1] = string; sl@0: sl@0: if(report_event && bp->ptr) sl@0: report_event(bp->ptr, evtype, 0, 1024, NULL, 2, 0, sl@0: lpszStrings, NULL); sl@0: } sl@0: sl@0: static void xcloselog(BIO* bp) sl@0: { sl@0: if(deregister_event_source && bp->ptr) sl@0: deregister_event_source((HANDLE)(bp->ptr)); sl@0: bp->ptr= NULL; sl@0: } sl@0: sl@0: #elif defined(OPENSSL_SYS_VMS) sl@0: sl@0: static int VMS_OPC_target = LOG_DAEMON; sl@0: sl@0: static void xopenlog(BIO* bp, char* name, int level) sl@0: { sl@0: VMS_OPC_target = level; sl@0: } sl@0: sl@0: static void xsyslog(BIO *bp, int priority, const char *string) sl@0: { sl@0: struct dsc$descriptor_s opc_dsc; sl@0: struct opcdef *opcdef_p; sl@0: #ifndef SYMBAIN sl@0: char buf[10240]; sl@0: #else sl@0: char buf[100]; sl@0: #endif sl@0: unsigned int len; sl@0: struct dsc$descriptor_s buf_dsc; sl@0: $DESCRIPTOR(fao_cmd, "!AZ: !AZ"); sl@0: char *priority_tag; sl@0: sl@0: switch (priority) sl@0: { sl@0: case LOG_EMERG: priority_tag = "Emergency"; break; sl@0: case LOG_ALERT: priority_tag = "Alert"; break; sl@0: case LOG_CRIT: priority_tag = "Critical"; break; sl@0: case LOG_ERR: priority_tag = "Error"; break; sl@0: case LOG_WARNING: priority_tag = "Warning"; break; sl@0: case LOG_NOTICE: priority_tag = "Notice"; break; sl@0: case LOG_INFO: priority_tag = "Info"; break; sl@0: case LOG_DEBUG: priority_tag = "DEBUG"; break; sl@0: } sl@0: sl@0: buf_dsc.dsc$b_dtype = DSC$K_DTYPE_T; sl@0: buf_dsc.dsc$b_class = DSC$K_CLASS_S; sl@0: buf_dsc.dsc$a_pointer = buf; sl@0: buf_dsc.dsc$w_length = sizeof(buf) - 1; sl@0: sl@0: lib$sys_fao(&fao_cmd, &len, &buf_dsc, priority_tag, string); sl@0: sl@0: /* we know there's an 8 byte header. That's documented */ sl@0: opcdef_p = (struct opcdef *) OPENSSL_malloc(8 + len); sl@0: opcdef_p->opc$b_ms_type = OPC$_RQ_RQST; sl@0: memcpy(opcdef_p->opc$z_ms_target_classes, &VMS_OPC_target, 3); sl@0: opcdef_p->opc$l_ms_rqstid = 0; sl@0: memcpy(&opcdef_p->opc$l_ms_text, buf, len); sl@0: sl@0: opc_dsc.dsc$b_dtype = DSC$K_DTYPE_T; sl@0: opc_dsc.dsc$b_class = DSC$K_CLASS_S; sl@0: opc_dsc.dsc$a_pointer = (char *)opcdef_p; sl@0: opc_dsc.dsc$w_length = len + 8; sl@0: sl@0: sys$sndopr(opc_dsc, 0); sl@0: sl@0: OPENSSL_free(opcdef_p); sl@0: } sl@0: sl@0: static void xcloselog(BIO* bp) sl@0: { sl@0: } sl@0: sl@0: #else /* Unix/Watt32 */ sl@0: sl@0: static void xopenlog(BIO* bp, char* name, int level) sl@0: { sl@0: #ifdef WATT32 /* djgpp/DOS */ sl@0: openlog(name, LOG_PID|LOG_CONS|LOG_NDELAY, level); sl@0: #else sl@0: openlog(name, LOG_PID|LOG_CONS, level); sl@0: #endif sl@0: } sl@0: sl@0: static void xsyslog(BIO *bp, int priority, const char *string) sl@0: { sl@0: syslog(priority, "%s", string); sl@0: } sl@0: sl@0: static void xcloselog(BIO* bp) sl@0: { sl@0: closelog(); sl@0: } sl@0: sl@0: #endif /* Unix */ sl@0: sl@0: #endif /* NO_SYSLOG */