Coverage Report

Created: 2025-07-01 06:46

/src/FreeRDP/winpr/libwinpr/sspicli/sspicli.c
Line
Count
Source (jump to first uncovered line)
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
  free(token->Domain);
103
0
  free(token);
104
0
  return TRUE;
105
0
}
106
107
static HANDLE_OPS ops = { LogonUserIsHandled,
108
                        LogonUserCloseHandle,
109
                        LogonUserGetFd,
110
                        NULL, /* CleanupHandle */
111
                        NULL,
112
                        NULL,
113
                        NULL,
114
                        NULL,
115
                        NULL,
116
                        NULL,
117
                        NULL,
118
                        NULL,
119
                        NULL,
120
                        NULL,
121
                        NULL,
122
                        NULL,
123
                        NULL,
124
                        NULL,
125
                        NULL,
126
                        NULL,
127
                        NULL };
128
129
BOOL LogonUserA(LPCSTR lpszUsername, LPCSTR lpszDomain, WINPR_ATTR_UNUSED LPCSTR lpszPassword,
130
                WINPR_ATTR_UNUSED DWORD dwLogonType, WINPR_ATTR_UNUSED DWORD dwLogonProvider,
131
                PHANDLE phToken)
132
0
{
133
0
  if (!lpszUsername)
134
0
    return FALSE;
135
136
0
  WINPR_ACCESS_TOKEN* token = (WINPR_ACCESS_TOKEN*)calloc(1, sizeof(WINPR_ACCESS_TOKEN));
137
138
0
  if (!token)
139
0
    return FALSE;
140
141
0
  WINPR_HANDLE_SET_TYPE_AND_MODE(token, HANDLE_TYPE_ACCESS_TOKEN, WINPR_FD_READ);
142
0
  token->common.ops = &ops;
143
0
  token->Username = _strdup(lpszUsername);
144
145
0
  if (!token->Username)
146
0
    goto fail;
147
148
0
  if (lpszDomain)
149
0
  {
150
0
    token->Domain = _strdup(lpszDomain);
151
152
0
    if (!token->Domain)
153
0
      goto fail;
154
0
  }
155
156
0
  long buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
157
0
  if (buflen < 0)
158
0
    buflen = 8196;
159
160
0
  const size_t s = 1ULL + (size_t)buflen;
161
0
  char* buf = (char*)calloc(s, sizeof(char));
162
0
  if (!buf)
163
0
    goto fail;
164
165
0
  struct passwd pwd = { 0 };
166
0
  struct passwd* pw = NULL;
167
0
  const int rc =
168
0
      getpwnam_r(lpszUsername, &pwd, buf, WINPR_ASSERTING_INT_CAST(size_t, buflen), &pw);
169
0
  free(buf);
170
0
  if ((rc == 0) && pw)
171
0
  {
172
0
    token->UserId = (DWORD)pw->pw_uid;
173
0
    token->GroupId = (DWORD)pw->pw_gid;
174
0
  }
175
176
0
  *((ULONG_PTR*)phToken) = (ULONG_PTR)token;
177
0
  return TRUE;
178
179
0
fail:
180
0
  free(token->Username);
181
0
  free(token->Domain);
182
0
  free(token);
183
0
  return FALSE;
184
0
}
185
186
BOOL LogonUserW(WINPR_ATTR_UNUSED LPCWSTR lpszUsername, WINPR_ATTR_UNUSED LPCWSTR lpszDomain,
187
                WINPR_ATTR_UNUSED LPCWSTR lpszPassword, WINPR_ATTR_UNUSED DWORD dwLogonType,
188
                WINPR_ATTR_UNUSED DWORD dwLogonProvider, WINPR_ATTR_UNUSED PHANDLE phToken)
189
0
{
190
0
  WLog_ERR("TODO", "TODO: implement");
191
0
  return TRUE;
192
0
}
193
194
BOOL LogonUserExA(WINPR_ATTR_UNUSED LPCSTR lpszUsername, WINPR_ATTR_UNUSED LPCSTR lpszDomain,
195
                  WINPR_ATTR_UNUSED LPCSTR lpszPassword, WINPR_ATTR_UNUSED DWORD dwLogonType,
196
                  WINPR_ATTR_UNUSED DWORD dwLogonProvider, WINPR_ATTR_UNUSED PHANDLE phToken,
197
                  WINPR_ATTR_UNUSED PSID* ppLogonSid, WINPR_ATTR_UNUSED PVOID* ppProfileBuffer,
198
                  WINPR_ATTR_UNUSED LPDWORD pdwProfileLength,
199
                  WINPR_ATTR_UNUSED PQUOTA_LIMITS pQuotaLimits)
200
0
{
201
0
  WLog_ERR("TODO", "TODO: implement");
202
0
  return TRUE;
203
0
}
204
205
BOOL LogonUserExW(WINPR_ATTR_UNUSED LPCWSTR lpszUsername, WINPR_ATTR_UNUSED LPCWSTR lpszDomain,
206
                  WINPR_ATTR_UNUSED LPCWSTR lpszPassword, WINPR_ATTR_UNUSED DWORD dwLogonType,
207
                  WINPR_ATTR_UNUSED DWORD dwLogonProvider, WINPR_ATTR_UNUSED PHANDLE phToken,
208
                  WINPR_ATTR_UNUSED PSID* ppLogonSid, WINPR_ATTR_UNUSED PVOID* ppProfileBuffer,
209
                  WINPR_ATTR_UNUSED LPDWORD pdwProfileLength,
210
                  WINPR_ATTR_UNUSED PQUOTA_LIMITS pQuotaLimits)
211
0
{
212
0
  WLog_ERR("TODO", "TODO: implement");
213
0
  return TRUE;
214
0
}
215
216
BOOL GetUserNameExA(EXTENDED_NAME_FORMAT NameFormat, LPSTR lpNameBuffer, PULONG nSize)
217
0
{
218
0
  WINPR_ASSERT(lpNameBuffer);
219
0
  WINPR_ASSERT(nSize);
220
221
0
  switch (NameFormat)
222
0
  {
223
0
    case NameSamCompatible:
224
0
#if defined(WINPR_HAVE_GETPWUID_R)
225
0
    {
226
0
      int rc = 0;
227
0
      struct passwd pwd = { 0 };
228
0
      struct passwd* result = NULL;
229
0
      uid_t uid = getuid();
230
231
0
      rc = getpwuid_r(uid, &pwd, lpNameBuffer, *nSize, &result);
232
0
      if (rc != 0)
233
0
        return FALSE;
234
0
      if (result == NULL)
235
0
        return FALSE;
236
0
    }
237
#elif defined(WINPR_HAVE_GETLOGIN_R)
238
      if (getlogin_r(lpNameBuffer, *nSize) != 0)
239
        return FALSE;
240
#else
241
    {
242
      const char* name = getlogin();
243
      if (!name)
244
        return FALSE;
245
      strncpy(lpNameBuffer, name, strnlen(name, *nSize));
246
    }
247
#endif
248
0
      const size_t len = strnlen(lpNameBuffer, *nSize);
249
0
      if (len > UINT32_MAX)
250
0
        return FALSE;
251
0
      *nSize = (ULONG)len;
252
0
      return TRUE;
253
254
0
    case NameFullyQualifiedDN:
255
0
    case NameDisplay:
256
0
    case NameUniqueId:
257
0
    case NameCanonical:
258
0
    case NameUserPrincipal:
259
0
    case NameCanonicalEx:
260
0
    case NameServicePrincipal:
261
0
    case NameDnsDomain:
262
0
      break;
263
264
0
    default:
265
0
      break;
266
0
  }
267
268
0
  return FALSE;
269
0
}
270
271
BOOL GetUserNameExW(EXTENDED_NAME_FORMAT NameFormat, LPWSTR lpNameBuffer, PULONG nSize)
272
0
{
273
0
  BOOL rc = FALSE;
274
0
  char* name = NULL;
275
276
0
  WINPR_ASSERT(nSize);
277
0
  WINPR_ASSERT(lpNameBuffer);
278
279
0
  name = calloc(1, *nSize + 1);
280
0
  if (!name)
281
0
    goto fail;
282
283
0
  if (!GetUserNameExA(NameFormat, name, nSize))
284
0
    goto fail;
285
286
0
  const SSIZE_T res = ConvertUtf8ToWChar(name, lpNameBuffer, *nSize);
287
0
  if ((res < 0) || (res >= UINT32_MAX))
288
0
    goto fail;
289
290
0
  *nSize = (UINT32)res + 1;
291
0
  rc = TRUE;
292
0
fail:
293
0
  free(name);
294
0
  return rc;
295
0
}
296
297
#endif