Coverage Report

Created: 2025-06-13 06:56

/src/openssl/crypto/cryptlib.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 1998-2023 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 "internal/e_os.h"
12
#include "crypto/cryptlib.h"
13
#include <openssl/safestack.h>
14
15
#if defined(_WIN32) && !defined(OPENSSL_SYS_UEFI)
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
0
{
240
0
#ifndef OPENSSL_NO_STDIO
241
0
    va_list ap;
242
243
0
    va_start(ap, fmta);
244
0
    vfprintf(stderr, fmta, ap);
245
0
    va_end(ap);
246
0
#endif
247
0
}
248
249
int OPENSSL_isservice(void)
250
0
{
251
0
    return 0;
252
0
}
253
#endif
254
255
void OPENSSL_die(const char *message, const char *file, int line)
256
0
{
257
0
    OPENSSL_showfatal("%s:%d: OpenSSL internal error: %s\n",
258
0
                      file, line, message);
259
0
#if !defined(_WIN32) || defined(OPENSSL_SYS_UEFI)
260
0
    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
0
}
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 */