1/* 2 * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved 4 * 5 * Licensed under the Apache License 2.0 (the "License"). You may not use 6 * this file except in compliance with the License. You can obtain a copy 7 * in the file LICENSE in the source distribution or at 8 * https://www.openssl.org/source/license.html 9 */ 10 11#include "e_os.h" 12#include "crypto/cryptlib.h" 13#include <openssl/safestack.h> 14 15#if defined(_WIN32) 16# include <tchar.h> 17# include <signal.h> 18# ifdef __WATCOMC__ 19# if defined(_UNICODE) || defined(__UNICODE__) 20# define _vsntprintf _vsnwprintf 21# else 22# define _vsntprintf _vsnprintf 23# endif 24# endif 25# ifdef _MSC_VER 26# define alloca _alloca 27# endif 28 29# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 30# ifdef OPENSSL_SYS_WIN_CORE 31 32int OPENSSL_isservice(void) 33{ 34 /* OneCore API cannot interact with GUI */ 35 return 1; 36} 37# else 38int OPENSSL_isservice(void) 39{ 40 HWINSTA h; 41 DWORD len; 42 WCHAR *name; 43 static union { 44 void *p; 45 FARPROC f; 46 } _OPENSSL_isservice = { 47 NULL 48 }; 49 50 if (_OPENSSL_isservice.p == NULL) { 51 HANDLE mod = GetModuleHandle(NULL); 52 FARPROC f = NULL; 53 54 if (mod != NULL) 55 f = GetProcAddress(mod, "_OPENSSL_isservice"); 56 if (f == NULL) 57 _OPENSSL_isservice.p = (void *)-1; 58 else 59 _OPENSSL_isservice.f = f; 60 } 61 62 if (_OPENSSL_isservice.p != (void *)-1) 63 return (*_OPENSSL_isservice.f) (); 64 65 h = GetProcessWindowStation(); 66 if (h == NULL) 67 return -1; 68 69 if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) || 70 GetLastError() != ERROR_INSUFFICIENT_BUFFER) 71 return -1; 72 73 if (len > 512) 74 return -1; /* paranoia */ 75 len++, len &= ~1; /* paranoia */ 76 name = (WCHAR *)alloca(len + sizeof(WCHAR)); 77 if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len)) 78 return -1; 79 80 len++, len &= ~1; /* paranoia */ 81 name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */ 82# if 1 83 /* 84 * This doesn't cover "interactive" services [working with real 85 * WinSta0's] nor programs started non-interactively by Task Scheduler 86 * [those are working with SAWinSta]. 87 */ 88 if (wcsstr(name, L"Service-0x")) 89 return 1; 90# else 91 /* This covers all non-interactive programs such as services. */ 92 if (!wcsstr(name, L"WinSta0")) 93 return 1; 94# endif 95 else 96 return 0; 97} 98# endif 99# else 100int OPENSSL_isservice(void) 101{ 102 return 0; 103} 104# endif 105 106void OPENSSL_showfatal(const char *fmta, ...) 107{ 108 va_list ap; 109 TCHAR buf[256]; 110 const TCHAR *fmt; 111 /* 112 * First check if it's a console application, in which case the 113 * error message would be printed to standard error. 114 * Windows CE does not have a concept of a console application, 115 * so we need to guard the check. 116 */ 117# ifdef STD_ERROR_HANDLE 118 HANDLE h; 119 120 if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL && 121 GetFileType(h) != FILE_TYPE_UNKNOWN) { 122 /* must be console application */ 123 int len; 124 DWORD out; 125 126 va_start(ap, fmta); 127 len = _vsnprintf((char *)buf, sizeof(buf), fmta, ap); 128 WriteFile(h, buf, len < 0 ? sizeof(buf) : (DWORD) len, &out, NULL); 129 va_end(ap); 130 return; 131 } 132# endif 133 134 if (sizeof(TCHAR) == sizeof(char)) 135 fmt = (const TCHAR *)fmta; 136 else 137 do { 138 int keepgoing; 139 size_t len_0 = strlen(fmta) + 1, i; 140 WCHAR *fmtw; 141 142 fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR)); 143 if (fmtw == NULL) { 144 fmt = (const TCHAR *)L"no stack?"; 145 break; 146 } 147 if (!MultiByteToWideChar(CP_ACP, 0, fmta, len_0, fmtw, len_0)) 148 for (i = 0; i < len_0; i++) 149 fmtw[i] = (WCHAR)fmta[i]; 150 for (i = 0; i < len_0; i++) { 151 if (fmtw[i] == L'%') 152 do { 153 keepgoing = 0; 154 switch (fmtw[i + 1]) { 155 case L'0': 156 case L'1': 157 case L'2': 158 case L'3': 159 case L'4': 160 case L'5': 161 case L'6': 162 case L'7': 163 case L'8': 164 case L'9': 165 case L'.': 166 case L'*': 167 case L'-': 168 i++; 169 keepgoing = 1; 170 break; 171 case L's': 172 fmtw[i + 1] = L'S'; 173 break; 174 case L'S': 175 fmtw[i + 1] = L's'; 176 break; 177 case L'c': 178 fmtw[i + 1] = L'C'; 179 break; 180 case L'C': 181 fmtw[i + 1] = L'c'; 182 break; 183 } 184 } while (keepgoing); 185 } 186 fmt = (const TCHAR *)fmtw; 187 } while (0); 188 189 va_start(ap, fmta); 190 _vsntprintf(buf, OSSL_NELEM(buf) - 1, fmt, ap); 191 buf[OSSL_NELEM(buf) - 1] = _T('\0'); 192 va_end(ap); 193 194# if defined(_WIN32_WINNT) && _WIN32_WINNT>=0x0333 195# ifdef OPENSSL_SYS_WIN_CORE 196 /* ONECORE is always NONGUI and NT >= 0x0601 */ 197# if !defined(NDEBUG) 198 /* 199 * We are in a situation where we tried to report a critical 200 * error and this failed for some reason. As a last resort, 201 * in debug builds, send output to the debugger or any other 202 * tool like DebugView which can monitor the output. 203 */ 204 OutputDebugString(buf); 205# endif 206# else 207 /* this -------------v--- guards NT-specific calls */ 208 if (check_winnt() && OPENSSL_isservice() > 0) { 209 HANDLE hEventLog = RegisterEventSource(NULL, _T("OpenSSL")); 210 211 if (hEventLog != NULL) { 212 const TCHAR *pmsg = buf; 213 214 if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL, 215 1, 0, &pmsg, NULL)) { 216# if !defined(NDEBUG) 217 /* 218 * We are in a situation where we tried to report a critical 219 * error and this failed for some reason. As a last resort, 220 * in debug builds, send output to the debugger or any other 221 * tool like DebugView which can monitor the output. 222 */ 223 OutputDebugString(pmsg); 224# endif 225 } 226 227 (void)DeregisterEventSource(hEventLog); 228 } 229 } else { 230 MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR); 231 } 232# endif 233# else 234 MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR); 235# endif 236} 237#else 238void OPENSSL_showfatal(const char *fmta, ...) 239{ 240#ifndef OPENSSL_NO_STDIO 241 va_list ap; 242 243 va_start(ap, fmta); 244 vfprintf(stderr, fmta, ap); 245 va_end(ap); 246#endif 247} 248 249int OPENSSL_isservice(void) 250{ 251 return 0; 252} 253#endif 254 255void OPENSSL_die(const char *message, const char *file, int line) 256{ 257 OPENSSL_showfatal("%s:%d: OpenSSL internal error: %s\n", 258 file, line, message); 259#if !defined(_WIN32) 260 abort(); 261#else 262 /* 263 * Win32 abort() customarily shows a dialog, but we just did that... 264 */ 265# if !defined(_WIN32_WCE) 266 raise(SIGABRT); 267# endif 268 _exit(3); 269#endif 270} 271 272#if defined(__TANDEM) && defined(OPENSSL_VPROC) 273/* 274 * Define a VPROC function for HP NonStop build crypto library. 275 * This is used by platform version identification tools. 276 * Do not inline this procedure or make it static. 277 */ 278# define OPENSSL_VPROC_STRING_(x) x##_CRYPTO 279# define OPENSSL_VPROC_STRING(x) OPENSSL_VPROC_STRING_(x) 280# define OPENSSL_VPROC_FUNC OPENSSL_VPROC_STRING(OPENSSL_VPROC) 281void OPENSSL_VPROC_FUNC(void) {} 282#endif /* __TANDEM */ 283