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