1/* 2 * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10/* 11 * Why BIO_s_log? 12 * 13 * BIO_s_log is useful for system daemons (or services under NT). It is 14 * one-way BIO, it sends all stuff to syslogd (on system that commonly use 15 * that), or event log (on NT), or OPCOM (on OpenVMS). 16 * 17 */ 18 19#include <stdio.h> 20#include <errno.h> 21 22#include "bio_local.h" 23#include "internal/cryptlib.h" 24 25#if defined(OPENSSL_SYS_WINCE) 26#elif defined(OPENSSL_SYS_WIN32) 27#elif defined(OPENSSL_SYS_VMS) 28# include <opcdef.h> 29# include <descrip.h> 30# include <lib$routines.h> 31# include <starlet.h> 32/* Some compiler options may mask the declaration of "_malloc32". */ 33# if __INITIAL_POINTER_SIZE && defined _ANSI_C_SOURCE 34# if __INITIAL_POINTER_SIZE == 64 35# pragma pointer_size save 36# pragma pointer_size 32 37void *_malloc32(__size_t); 38# pragma pointer_size restore 39# endif /* __INITIAL_POINTER_SIZE == 64 */ 40# endif /* __INITIAL_POINTER_SIZE && defined 41 * _ANSI_C_SOURCE */ 42#elif defined(__DJGPP__) && defined(OPENSSL_NO_SOCK) 43# define NO_SYSLOG 44#elif (!defined(MSDOS) || defined(WATT32)) && !defined(OPENSSL_SYS_VXWORKS) && !defined(NO_SYSLOG) 45# include <syslog.h> 46#endif 47 48#include <openssl/buffer.h> 49#include <openssl/err.h> 50 51#ifndef NO_SYSLOG 52 53# if defined(OPENSSL_SYS_WIN32) 54# define LOG_EMERG 0 55# define LOG_ALERT 1 56# define LOG_CRIT 2 57# define LOG_ERR 3 58# define LOG_WARNING 4 59# define LOG_NOTICE 5 60# define LOG_INFO 6 61# define LOG_DEBUG 7 62 63# define LOG_DAEMON (3<<3) 64# elif defined(OPENSSL_SYS_VMS) 65/* On VMS, we don't really care about these, but we need them to compile */ 66# define LOG_EMERG 0 67# define LOG_ALERT 1 68# define LOG_CRIT 2 69# define LOG_ERR 3 70# define LOG_WARNING 4 71# define LOG_NOTICE 5 72# define LOG_INFO 6 73# define LOG_DEBUG 7 74 75# define LOG_DAEMON OPC$M_NM_NTWORK 76# endif 77 78static int slg_write(BIO *h, const char *buf, int num); 79static int slg_puts(BIO *h, const char *str); 80static long slg_ctrl(BIO *h, int cmd, long arg1, void *arg2); 81static int slg_new(BIO *h); 82static int slg_free(BIO *data); 83static void xopenlog(BIO *bp, char *name, int level); 84static void xsyslog(BIO *bp, int priority, const char *string); 85static void xcloselog(BIO *bp); 86 87static const BIO_METHOD methods_slg = { 88 BIO_TYPE_MEM, 89 "syslog", 90 bwrite_conv, 91 slg_write, 92 NULL, /* slg_write_old, */ 93 NULL, /* slg_read, */ 94 slg_puts, 95 NULL, 96 slg_ctrl, 97 slg_new, 98 slg_free, 99 NULL, /* slg_callback_ctrl */ 100}; 101 102const BIO_METHOD *BIO_s_log(void) 103{ 104 return &methods_slg; 105} 106 107static int slg_new(BIO *bi) 108{ 109 bi->init = 1; 110 bi->num = 0; 111 bi->ptr = NULL; 112 xopenlog(bi, "application", LOG_DAEMON); 113 return 1; 114} 115 116static int slg_free(BIO *a) 117{ 118 if (a == NULL) 119 return 0; 120 xcloselog(a); 121 return 1; 122} 123 124static int slg_write(BIO *b, const char *in, int inl) 125{ 126 int ret = inl; 127 char *buf; 128 char *pp; 129 int priority, i; 130 static const struct { 131 int strl; 132 char str[10]; 133 int log_level; 134 } mapping[] = { 135 { 136 6, "PANIC ", LOG_EMERG 137 }, 138 { 139 6, "EMERG ", LOG_EMERG 140 }, 141 { 142 4, "EMR ", LOG_EMERG 143 }, 144 { 145 6, "ALERT ", LOG_ALERT 146 }, 147 { 148 4, "ALR ", LOG_ALERT 149 }, 150 { 151 5, "CRIT ", LOG_CRIT 152 }, 153 { 154 4, "CRI ", LOG_CRIT 155 }, 156 { 157 6, "ERROR ", LOG_ERR 158 }, 159 { 160 4, "ERR ", LOG_ERR 161 }, 162 { 163 8, "WARNING ", LOG_WARNING 164 }, 165 { 166 5, "WARN ", LOG_WARNING 167 }, 168 { 169 4, "WAR ", LOG_WARNING 170 }, 171 { 172 7, "NOTICE ", LOG_NOTICE 173 }, 174 { 175 5, "NOTE ", LOG_NOTICE 176 }, 177 { 178 4, "NOT ", LOG_NOTICE 179 }, 180 { 181 5, "INFO ", LOG_INFO 182 }, 183 { 184 4, "INF ", LOG_INFO 185 }, 186 { 187 6, "DEBUG ", LOG_DEBUG 188 }, 189 { 190 4, "DBG ", LOG_DEBUG 191 }, 192 { 193 0, "", LOG_ERR 194 } 195 /* The default */ 196 }; 197 198 if (inl < 0) 199 return 0; 200 if ((buf = OPENSSL_malloc(inl + 1)) == NULL) { 201 ERR_raise(ERR_LIB_BIO, ERR_R_MALLOC_FAILURE); 202 return 0; 203 } 204 memcpy(buf, in, inl); 205 buf[inl] = '\0'; 206 207 i = 0; 208 while (strncmp(buf, mapping[i].str, mapping[i].strl) != 0) 209 i++; 210 priority = mapping[i].log_level; 211 pp = buf + mapping[i].strl; 212 213 xsyslog(b, priority, pp); 214 215 OPENSSL_free(buf); 216 return ret; 217} 218 219static long slg_ctrl(BIO *b, int cmd, long num, void *ptr) 220{ 221 switch (cmd) { 222 case BIO_CTRL_SET: 223 xcloselog(b); 224 xopenlog(b, ptr, num); 225 break; 226 default: 227 break; 228 } 229 return 0; 230} 231 232static int slg_puts(BIO *bp, const char *str) 233{ 234 int n, ret; 235 236 n = strlen(str); 237 ret = slg_write(bp, str, n); 238 return ret; 239} 240 241# if defined(OPENSSL_SYS_WIN32) 242 243static void xopenlog(BIO *bp, char *name, int level) 244{ 245 if (check_winnt()) 246 bp->ptr = RegisterEventSourceA(NULL, name); 247 else 248 bp->ptr = NULL; 249} 250 251static void xsyslog(BIO *bp, int priority, const char *string) 252{ 253 LPCSTR lpszStrings[2]; 254 WORD evtype = EVENTLOG_ERROR_TYPE; 255 char pidbuf[DECIMAL_SIZE(DWORD) + 4]; 256 257 if (bp->ptr == NULL) 258 return; 259 260 switch (priority) { 261 case LOG_EMERG: 262 case LOG_ALERT: 263 case LOG_CRIT: 264 case LOG_ERR: 265 evtype = EVENTLOG_ERROR_TYPE; 266 break; 267 case LOG_WARNING: 268 evtype = EVENTLOG_WARNING_TYPE; 269 break; 270 case LOG_NOTICE: 271 case LOG_INFO: 272 case LOG_DEBUG: 273 evtype = EVENTLOG_INFORMATION_TYPE; 274 break; 275 default: 276 /* 277 * Should never happen, but set it 278 * as error anyway. 279 */ 280 evtype = EVENTLOG_ERROR_TYPE; 281 break; 282 } 283 284 sprintf(pidbuf, "[%lu] ", GetCurrentProcessId()); 285 lpszStrings[0] = pidbuf; 286 lpszStrings[1] = string; 287 288 ReportEventA(bp->ptr, evtype, 0, 1024, NULL, 2, 0, lpszStrings, NULL); 289} 290 291static void xcloselog(BIO *bp) 292{ 293 if (bp->ptr) 294 DeregisterEventSource((HANDLE) (bp->ptr)); 295 bp->ptr = NULL; 296} 297 298# elif defined(OPENSSL_SYS_VMS) 299 300static int VMS_OPC_target = LOG_DAEMON; 301 302static void xopenlog(BIO *bp, char *name, int level) 303{ 304 VMS_OPC_target = level; 305} 306 307static void xsyslog(BIO *bp, int priority, const char *string) 308{ 309 struct dsc$descriptor_s opc_dsc; 310 311/* Arrange 32-bit pointer to opcdef buffer and malloc(), if needed. */ 312# if __INITIAL_POINTER_SIZE == 64 313# pragma pointer_size save 314# pragma pointer_size 32 315# define OPCDEF_TYPE __char_ptr32 316# define OPCDEF_MALLOC _malloc32 317# else /* __INITIAL_POINTER_SIZE == 64 */ 318# define OPCDEF_TYPE char * 319# define OPCDEF_MALLOC OPENSSL_malloc 320# endif /* __INITIAL_POINTER_SIZE == 64 [else] */ 321 322 struct opcdef *opcdef_p; 323 324# if __INITIAL_POINTER_SIZE == 64 325# pragma pointer_size restore 326# endif /* __INITIAL_POINTER_SIZE == 64 */ 327 328 char buf[10240]; 329 unsigned int len; 330 struct dsc$descriptor_s buf_dsc; 331 $DESCRIPTOR(fao_cmd, "!AZ: !AZ"); 332 char *priority_tag; 333 334 switch (priority) { 335 case LOG_EMERG: 336 priority_tag = "Emergency"; 337 break; 338 case LOG_ALERT: 339 priority_tag = "Alert"; 340 break; 341 case LOG_CRIT: 342 priority_tag = "Critical"; 343 break; 344 case LOG_ERR: 345 priority_tag = "Error"; 346 break; 347 case LOG_WARNING: 348 priority_tag = "Warning"; 349 break; 350 case LOG_NOTICE: 351 priority_tag = "Notice"; 352 break; 353 case LOG_INFO: 354 priority_tag = "Info"; 355 break; 356 case LOG_DEBUG: 357 priority_tag = "DEBUG"; 358 break; 359 } 360 361 buf_dsc.dsc$b_dtype = DSC$K_DTYPE_T; 362 buf_dsc.dsc$b_class = DSC$K_CLASS_S; 363 buf_dsc.dsc$a_pointer = buf; 364 buf_dsc.dsc$w_length = sizeof(buf) - 1; 365 366 lib$sys_fao(&fao_cmd, &len, &buf_dsc, priority_tag, string); 367 368 /* We know there's an 8-byte header. That's documented. */ 369 opcdef_p = OPCDEF_MALLOC(8 + len); 370 opcdef_p->opc$b_ms_type = OPC$_RQ_RQST; 371 memcpy(opcdef_p->opc$z_ms_target_classes, &VMS_OPC_target, 3); 372 opcdef_p->opc$l_ms_rqstid = 0; 373 memcpy(&opcdef_p->opc$l_ms_text, buf, len); 374 375 opc_dsc.dsc$b_dtype = DSC$K_DTYPE_T; 376 opc_dsc.dsc$b_class = DSC$K_CLASS_S; 377 opc_dsc.dsc$a_pointer = (OPCDEF_TYPE) opcdef_p; 378 opc_dsc.dsc$w_length = len + 8; 379 380 sys$sndopr(opc_dsc, 0); 381 382 OPENSSL_free(opcdef_p); 383} 384 385static void xcloselog(BIO *bp) 386{ 387} 388 389# else /* Unix/Watt32 */ 390 391static void xopenlog(BIO *bp, char *name, int level) 392{ 393# ifdef WATT32 /* djgpp/DOS */ 394 openlog(name, LOG_PID | LOG_CONS | LOG_NDELAY, level); 395# else 396 openlog(name, LOG_PID | LOG_CONS, level); 397# endif 398} 399 400static void xsyslog(BIO *bp, int priority, const char *string) 401{ 402 syslog(priority, "%s", string); 403} 404 405static void xcloselog(BIO *bp) 406{ 407 closelog(); 408} 409 410# endif /* Unix */ 411 412#else /* NO_SYSLOG */ 413const BIO_METHOD *BIO_s_log(void) 414{ 415 return NULL; 416} 417#endif /* NO_SYSLOG */ 418