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 32 int OPENSSL_isservice(void) 33 { 34 /* OneCore API cannot interact with GUI */ 35 return 1; 36 } 37 # else 38 int 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 100 int OPENSSL_isservice(void) 101 { 102 return 0; 103 } 104 # endif 105 106 void 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 238 void 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 249 int OPENSSL_isservice(void) 250 { 251 return 0; 252 } 253 #endif 254 255 void 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) 281 void OPENSSL_VPROC_FUNC(void) {} 282 #endif /* __TANDEM */ 283