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