Coverage Report

Created: 2026-08-31 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/winpr/libwinpr/sspicli/sspicli.c
Line
Count
Source
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * Security Support Provider Interface
4
 *
5
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
20
#include <winpr/config.h>
21
22
#include <winpr/assert.h>
23
#include <winpr/sspicli.h>
24
25
/**
26
 * sspicli.dll:
27
 *
28
 * EnumerateSecurityPackagesA
29
 * EnumerateSecurityPackagesW
30
 * GetUserNameExW
31
 * ImportSecurityContextA
32
 * LogonUser
33
 * LogonUserEx
34
 * LogonUserExExW
35
 * SspiCompareAuthIdentities
36
 * SspiCopyAuthIdentity
37
 * SspiDecryptAuthIdentity
38
 * SspiEncodeAuthIdentityAsStrings
39
 * SspiEncodeStringsAsAuthIdentity
40
 * SspiEncryptAuthIdentity
41
 * SspiExcludePackage
42
 * SspiFreeAuthIdentity
43
 * SspiGetTargetHostName
44
 * SspiIsAuthIdentityEncrypted
45
 * SspiLocalFree
46
 * SspiMarshalAuthIdentity
47
 * SspiPrepareForCredRead
48
 * SspiPrepareForCredWrite
49
 * SspiUnmarshalAuthIdentity
50
 * SspiValidateAuthIdentity
51
 * SspiZeroAuthIdentity
52
 */
53
54
#ifndef _WIN32
55
56
#include <winpr/crt.h>
57
58
#ifdef WINPR_HAVE_UNISTD_H
59
#include <unistd.h>
60
#endif
61
62
#if defined(WINPR_HAVE_GETPWUID_R)
63
#include <sys/types.h>
64
#endif
65
66
#include <pthread.h>
67
68
#include <pwd.h>
69
#include <grp.h>
70
71
#include "../handle/handle.h"
72
73
#include "../security/security.h"
74
75
static BOOL LogonUserCloseHandle(HANDLE handle);
76
77
static BOOL LogonUserIsHandled(HANDLE handle)
78
0
{
79
0
  return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_ACCESS_TOKEN, FALSE);
80
0
}
81
82
static int LogonUserGetFd(HANDLE handle)
83
0
{
84
0
  WINPR_ACCESS_TOKEN* pLogonUser = (WINPR_ACCESS_TOKEN*)handle;
85
86
0
  if (!LogonUserIsHandled(handle))
87
0
    return -1;
88
89
  /* TODO: File fd not supported */
90
0
  (void)pLogonUser;
91
0
  return -1;
92
0
}
93
94
BOOL LogonUserCloseHandle(HANDLE handle)
95
0
{
96
0
  WINPR_ACCESS_TOKEN* token = (WINPR_ACCESS_TOKEN*)handle;
97
98
0
  if (!handle || !LogonUserIsHandled(handle))
99
0
    return FALSE;
100
101
0
  free(token->Username);
102
0
  token->Username = nullptr;
103
0
  free(token->Domain);
104
0
  token->Domain = nullptr;
105
0
  return TRUE;
106
0
}
107
108
static HANDLE_OPS ops = { LogonUserIsHandled,
109
                        LogonUserCloseHandle,
110
                        LogonUserGetFd,
111
                        nullptr, /* CleanupHandle */
112
                        nullptr,
113
                        nullptr,
114
                        nullptr,
115
                        nullptr,
116
                        nullptr,
117
                        nullptr,
118
                        nullptr,
119
                        nullptr,
120
                        nullptr,
121
                        nullptr,
122
                        nullptr,
123
                        nullptr,
124
                        nullptr,
125
                        nullptr,
126
                        nullptr,
127
                        nullptr,
128
                        nullptr };
129
130
BOOL LogonUserA(LPCSTR lpszUsername, LPCSTR lpszDomain, WINPR_ATTR_UNUSED LPCSTR lpszPassword,
131
                WINPR_ATTR_UNUSED DWORD dwLogonType, WINPR_ATTR_UNUSED DWORD dwLogonProvider,
132
                PHANDLE phToken)
133
0
{
134
0
  if (!lpszUsername)
135
0
    return FALSE;
136
137
0
  WINPR_ACCESS_TOKEN* token = (WINPR_ACCESS_TOKEN*)calloc(1, sizeof(WINPR_ACCESS_TOKEN));
138
139
0
  if (!token)
140
0
    return FALSE;
141
142
0
  WINPR_HANDLE_SET_TYPE_AND_MODE(token, HANDLE_TYPE_ACCESS_TOKEN, WINPR_FD_READ);
143
0
  token->common.ops = &ops;
144
0
  token->Username = _strdup(lpszUsername);
145
146
0
  if (!token->Username)
147
0
    goto fail;
148
149
0
  if (lpszDomain)
150
0
  {
151
0
    token->Domain = _strdup(lpszDomain);
152
153
0
    if (!token->Domain)
154
0
      goto fail;
155
0
  }
156
157
0
  {
158
0
    long buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
159
0
    if (buflen < 0)
160
0
      buflen = 8196;
161
162
0
    {
163
0
      const size_t s = 1ULL + (size_t)buflen;
164
0
      char* buf = (char*)calloc(s, sizeof(char));
165
0
      if (!buf)
166
0
        goto fail;
167
168
0
      {
169
0
        struct passwd pwd = WINPR_C_ARRAY_INIT;
170
0
        struct passwd* pw = nullptr;
171
0
        const int rc = getpwnam_r(lpszUsername, &pwd, buf,
172
0
                                  WINPR_ASSERTING_INT_CAST(size_t, buflen), &pw);
173
0
        free(buf);
174
0
        if ((rc == 0) && pw)
175
0
        {
176
0
          token->UserId = (DWORD)pw->pw_uid;
177
0
          token->GroupId = (DWORD)pw->pw_gid;
178
0
        }
179
180
0
        *((ULONG_PTR*)phToken) = (ULONG_PTR)token;
181
0
        return TRUE;
182
0
      }
183
0
    }
184
0
  }
185
0
fail:
186
0
  free(token->Username);
187
0
  free(token->Domain);
188
0
  free(token);
189
0
  return FALSE;
190
0
}
191
192
BOOL LogonUserW(WINPR_ATTR_UNUSED LPCWSTR lpszUsername, WINPR_ATTR_UNUSED LPCWSTR lpszDomain,
193
                WINPR_ATTR_UNUSED LPCWSTR lpszPassword, WINPR_ATTR_UNUSED DWORD dwLogonType,
194
                WINPR_ATTR_UNUSED DWORD dwLogonProvider, WINPR_ATTR_UNUSED PHANDLE phToken)
195
0
{
196
0
  WLog_ERR("TODO", "TODO: implement");
197
0
  return TRUE;
198
0
}
199
200
BOOL LogonUserExA(WINPR_ATTR_UNUSED LPCSTR lpszUsername, WINPR_ATTR_UNUSED LPCSTR lpszDomain,
201
                  WINPR_ATTR_UNUSED LPCSTR lpszPassword, WINPR_ATTR_UNUSED DWORD dwLogonType,
202
                  WINPR_ATTR_UNUSED DWORD dwLogonProvider, WINPR_ATTR_UNUSED PHANDLE phToken,
203
                  WINPR_ATTR_UNUSED PSID* ppLogonSid, WINPR_ATTR_UNUSED PVOID* ppProfileBuffer,
204
                  WINPR_ATTR_UNUSED LPDWORD pdwProfileLength,
205
                  WINPR_ATTR_UNUSED PQUOTA_LIMITS pQuotaLimits)
206
0
{
207
0
  WLog_ERR("TODO", "TODO: implement");
208
0
  return TRUE;
209
0
}
210
211
BOOL LogonUserExW(WINPR_ATTR_UNUSED LPCWSTR lpszUsername, WINPR_ATTR_UNUSED LPCWSTR lpszDomain,
212
                  WINPR_ATTR_UNUSED LPCWSTR lpszPassword, WINPR_ATTR_UNUSED DWORD dwLogonType,
213
                  WINPR_ATTR_UNUSED DWORD dwLogonProvider, WINPR_ATTR_UNUSED PHANDLE phToken,
214
                  WINPR_ATTR_UNUSED PSID* ppLogonSid, WINPR_ATTR_UNUSED PVOID* ppProfileBuffer,
215
                  WINPR_ATTR_UNUSED LPDWORD pdwProfileLength,
216
                  WINPR_ATTR_UNUSED PQUOTA_LIMITS pQuotaLimits)
217
0
{
218
0
  WLog_ERR("TODO", "TODO: implement");
219
0
  return TRUE;
220
0
}
221
222
BOOL GetUserNameExA(EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
223
0
{
224
0
  WINPR_ASSERT(lpNameBuffer);
225
0
  WINPR_ASSERT(nSize);
226
227
0
  switch (NameFormat)
228
0
  {
229
0
    case NameSamCompatible:
230
0
#if defined(WINPR_HAVE_GETPWUID_R)
231
0
    {
232
0
      int rc = 0;
233
0
      struct passwd pwd = WINPR_C_ARRAY_INIT;
234
0
      struct passwd* result = nullptr;
235
0
      uid_t uid = getuid();
236
237
0
      rc = getpwuid_r(uid, &pwd, lpNameBuffer, *nSize, &result);
238
0
      if (rc != 0)
239
0
        return FALSE;
240
0
      if (result == nullptr)
241
0
        return FALSE;
242
0
    }
243
#elif defined(WINPR_HAVE_GETLOGIN_R)
244
      if (getlogin_r(lpNameBuffer, *nSize) != 0)
245
        return FALSE;
246
#else
247
    {
248
      const char* name = getlogin();
249
      if (!name)
250
        return FALSE;
251
      strncpy(lpNameBuffer, name, strnlen(name, *nSize));
252
    }
253
#endif
254
0
      {
255
0
        const size_t len = strnlen(lpNameBuffer, *nSize);
256
0
        if (len > UINT32_MAX)
257
0
          return FALSE;
258
0
        *nSize = (ULONG)len;
259
0
      }
260
0
      return TRUE;
261
262
0
    case NameFullyQualifiedDN:
263
0
    case NameDisplay:
264
0
    case NameUniqueId:
265
0
    case NameCanonical:
266
0
    case NameUserPrincipal:
267
0
    case NameCanonicalEx:
268
0
    case NameServicePrincipal:
269
0
    case NameDnsDomain:
270
0
      break;
271
272
0
    default:
273
0
      break;
274
0
  }
275
276
0
  return FALSE;
277
0
}
278
279
BOOL GetUserNameExW(EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
280
0
{
281
0
  BOOL rc = FALSE;
282
0
  char* name = nullptr;
283
284
0
  WINPR_ASSERT(nSize);
285
0
  WINPR_ASSERT(lpNameBuffer);
286
287
0
  name = calloc(1, *nSize + 1);
288
0
  if (!name)
289
0
    goto fail;
290
291
0
  if (!GetUserNameExA(NameFormat, name, nSize))
292
0
    goto fail;
293
294
0
  {
295
0
    const SSIZE_T res = ConvertUtf8ToWChar(name, lpNameBuffer, *nSize);
296
0
    if ((res < 0) || (res >= UINT32_MAX))
297
0
      goto fail;
298
299
0
    *nSize = (UINT32)res + 1;
300
0
  }
301
0
  rc = TRUE;
302
0
fail:
303
0
  free(name);
304
0
  return rc;
305
0
}
306
307
#endif