2 * Unit tests for security functions
4 * Copyright (c) 2004 Mike McCormack
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "wine/test.h"
30 typedef BOOL (WINAPI
*fnBuildTrusteeWithSidA
)( TRUSTEE
*trustee
, PSID psid
);
31 typedef BOOL (WINAPI
*fnBuildTrusteeWithNameA
)( TRUSTEE
*trustee
, LPSTR str
);
32 typedef BOOL (WINAPI
*fnConvertSidToStringSidA
)( PSID pSid
, LPSTR
*str
);
33 typedef BOOL (WINAPI
*fnConvertStringSidToSidA
)( LPCSTR str
, PSID pSid
);
34 typedef BOOL (WINAPI
*fnGetFileSecurityA
)(LPCSTR
, SECURITY_INFORMATION
,
35 PSECURITY_DESCRIPTOR
, DWORD
, LPDWORD
);
39 fnBuildTrusteeWithSidA pBuildTrusteeWithSidA
;
40 fnBuildTrusteeWithNameA pBuildTrusteeWithNameA
;
41 fnConvertSidToStringSidA pConvertSidToStringSidA
;
42 fnConvertStringSidToSidA pConvertStringSidToSidA
;
43 fnGetFileSecurityA pGetFileSecurityA
;
47 SID_IDENTIFIER_AUTHORITY auth
;
51 static void init(void)
53 hmod
= GetModuleHandle("advapi32.dll");
58 struct sidRef refs
[] = {
59 { { {0x00,0x00,0x33,0x44,0x55,0x66} }, "S-1-860116326-1" },
60 { { {0x00,0x00,0x01,0x02,0x03,0x04} }, "S-1-16909060-1" },
61 { { {0x00,0x00,0x00,0x01,0x02,0x03} }, "S-1-66051-1" },
62 { { {0x00,0x00,0x00,0x00,0x01,0x02} }, "S-1-258-1" },
63 { { {0x00,0x00,0x00,0x00,0x00,0x02} }, "S-1-2-1" },
64 { { {0x00,0x00,0x00,0x00,0x00,0x0c} }, "S-1-12-1" },
66 const char noSubAuthStr
[] = "S-1-5";
72 pConvertSidToStringSidA
= (fnConvertSidToStringSidA
)
73 GetProcAddress( hmod
, "ConvertSidToStringSidA" );
74 if( !pConvertSidToStringSidA
)
76 pConvertStringSidToSidA
= (fnConvertStringSidToSidA
)
77 GetProcAddress( hmod
, "ConvertStringSidToSidA" );
78 if( !pConvertStringSidToSidA
)
81 r
= pConvertStringSidToSidA( NULL
, NULL
);
82 ok( !r
, "expected failure with NULL parameters\n" );
83 if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
85 ok( GetLastError() == ERROR_INVALID_PARAMETER
,
86 "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
89 r
= pConvertStringSidToSidA( refs
[0].refStr
, NULL
);
90 ok( !r
&& GetLastError() == ERROR_INVALID_PARAMETER
,
91 "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
94 r
= pConvertStringSidToSidA( NULL
, &str
);
95 ok( !r
&& GetLastError() == ERROR_INVALID_PARAMETER
,
96 "expected GetLastError() is ERROR_INVALID_PARAMETER, got %ld\n",
99 r
= pConvertStringSidToSidA( noSubAuthStr
, &psid
);
101 "expected failure with no sub authorities\n" );
102 ok( GetLastError() == ERROR_INVALID_SID
,
103 "expected GetLastError() is ERROR_INVALID_SID, got %ld\n",
106 for( i
= 0; i
< sizeof(refs
) / sizeof(refs
[0]); i
++ )
110 r
= AllocateAndInitializeSid( &refs
[i
].auth
, 1,1,0,0,0,0,0,0,0,
112 ok( r
, "failed to allocate sid\n" );
113 r
= pConvertSidToStringSidA( psid
, &str
);
114 ok( r
, "failed to convert sid\n" );
117 ok( !strcmp( str
, refs
[i
].refStr
),
118 "incorrect sid, expected %s, got %s\n", refs
[i
].refStr
, str
);
124 r
= pConvertStringSidToSidA( refs
[i
].refStr
, &psid
);
125 ok( r
, "failed to parse sid string\n" );
128 !memcmp( pisid
->IdentifierAuthority
.Value
, refs
[i
].auth
.Value
,
129 sizeof(refs
[i
].auth
) ),
130 "string sid %s didn't parse to expected value\n"
131 "(got 0x%04x%08lx, expected 0x%04x%08lx)\n",
133 MAKEWORD( pisid
->IdentifierAuthority
.Value
[1],
134 pisid
->IdentifierAuthority
.Value
[0] ),
135 MAKELONG( MAKEWORD( pisid
->IdentifierAuthority
.Value
[5],
136 pisid
->IdentifierAuthority
.Value
[4] ),
137 MAKEWORD( pisid
->IdentifierAuthority
.Value
[3],
138 pisid
->IdentifierAuthority
.Value
[2] ) ),
139 MAKEWORD( refs
[i
].auth
.Value
[1], refs
[i
].auth
.Value
[0] ),
140 MAKELONG( MAKEWORD( refs
[i
].auth
.Value
[5], refs
[i
].auth
.Value
[4] ),
141 MAKEWORD( refs
[i
].auth
.Value
[3], refs
[i
].auth
.Value
[2] ) ) );
153 SID_IDENTIFIER_AUTHORITY auth
= { {0x11,0x22,0,0,0, 0} };
155 pBuildTrusteeWithSidA
= (fnBuildTrusteeWithSidA
)
156 GetProcAddress( hmod
, "BuildTrusteeWithSidA" );
157 pBuildTrusteeWithNameA
= (fnBuildTrusteeWithNameA
)
158 GetProcAddress( hmod
, "BuildTrusteeWithNameA" );
159 if( !pBuildTrusteeWithSidA
|| !pBuildTrusteeWithNameA
)
162 if ( ! AllocateAndInitializeSid( &auth
, 1, 42, 0,0,0,0,0,0,0,&psid
) )
164 trace( "failed to init SID\n" );
168 memset( &trustee
, 0xff, sizeof trustee
);
169 pBuildTrusteeWithSidA( &trustee
, psid
);
171 ok( trustee
.pMultipleTrustee
== NULL
, "pMultipleTrustee wrong\n");
172 ok( trustee
.MultipleTrusteeOperation
== NO_MULTIPLE_TRUSTEE
,
173 "MultipleTrusteeOperation wrong\n");
174 ok( trustee
.TrusteeForm
== TRUSTEE_IS_SID
, "TrusteeForm wrong\n");
175 ok( trustee
.TrusteeType
== TRUSTEE_IS_UNKNOWN
, "TrusteeType wrong\n");
176 ok( trustee
.ptstrName
== (LPSTR
) psid
, "ptstrName wrong\n" );
179 /* test BuildTrusteeWithNameA */
180 memset( &trustee
, 0xff, sizeof trustee
);
181 pBuildTrusteeWithNameA( &trustee
, str
);
183 ok( trustee
.pMultipleTrustee
== NULL
, "pMultipleTrustee wrong\n");
184 ok( trustee
.MultipleTrusteeOperation
== NO_MULTIPLE_TRUSTEE
,
185 "MultipleTrusteeOperation wrong\n");
186 ok( trustee
.TrusteeForm
== TRUSTEE_IS_NAME
, "TrusteeForm wrong\n");
187 ok( trustee
.TrusteeType
== TRUSTEE_IS_UNKNOWN
, "TrusteeType wrong\n");
188 ok( trustee
.ptstrName
== str
, "ptstrName wrong\n" );
191 /* If the first isn't defined, assume none is */
192 #ifndef SE_MIN_WELL_KNOWN_PRIVILEGE
193 #define SE_MIN_WELL_KNOWN_PRIVILEGE 2L
194 #define SE_CREATE_TOKEN_PRIVILEGE 2L
195 #define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE 3L
196 #define SE_LOCK_MEMORY_PRIVILEGE 4L
197 #define SE_INCREASE_QUOTA_PRIVILEGE 5L
198 #define SE_MACHINE_ACCOUNT_PRIVILEGE 6L
199 #define SE_TCB_PRIVILEGE 7L
200 #define SE_SECURITY_PRIVILEGE 8L
201 #define SE_TAKE_OWNERSHIP_PRIVILEGE 9L
202 #define SE_LOAD_DRIVER_PRIVILEGE 10L
203 #define SE_SYSTEM_PROFILE_PRIVILEGE 11L
204 #define SE_SYSTEMTIME_PRIVILEGE 12L
205 #define SE_PROF_SINGLE_PROCESS_PRIVILEGE 13L
206 #define SE_INC_BASE_PRIORITY_PRIVILEGE 14L
207 #define SE_CREATE_PAGEFILE_PRIVILEGE 15L
208 #define SE_CREATE_PERMANENT_PRIVILEGE 16L
209 #define SE_BACKUP_PRIVILEGE 17L
210 #define SE_RESTORE_PRIVILEGE 18L
211 #define SE_SHUTDOWN_PRIVILEGE 19L
212 #define SE_DEBUG_PRIVILEGE 20L
213 #define SE_AUDIT_PRIVILEGE 21L
214 #define SE_SYSTEM_ENVIRONMENT_PRIVILEGE 22L
215 #define SE_CHANGE_NOTIFY_PRIVILLEGE 23L
216 #define SE_REMOTE_SHUTDOWN_PRIVILEGE 24L
217 #define SE_UNDOCK_PRIVILEGE 25L
218 #define SE_SYNC_AGENT_PRIVILEGE 26L
219 #define SE_ENABLE_DELEGATION_PRIVILEGE 27L
220 #define SE_MANAGE_VOLUME_PRIVILEGE 28L
221 #define SE_IMPERSONATE_PRIVILEGE 29L
222 #define SE_CREATE_GLOBAL_PRIVILEGE 30L
223 #define SE_MAX_WELL_KNOWN_PRIVILEGE SE_CREATE_GLOBAL_PRIVILEGE
224 #endif /* ndef SE_MIN_WELL_KNOWN_PRIVILEGE */
226 static void test_allocateLuid(void)
228 BOOL (WINAPI
*pAllocateLocallyUniqueId
)(PLUID
);
232 pAllocateLocallyUniqueId
= (void*)GetProcAddress(hmod
, "AllocateLocallyUniqueId");
233 if (!pAllocateLocallyUniqueId
) return;
235 ret
= pAllocateLocallyUniqueId(&luid1
);
236 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
240 "AllocateLocallyUniqueId failed: %ld\n", GetLastError());
241 ret
= pAllocateLocallyUniqueId(&luid2
);
243 "AllocateLocallyUniqueId failed: %ld\n", GetLastError());
244 ok(luid1
.LowPart
> SE_MAX_WELL_KNOWN_PRIVILEGE
|| luid1
.HighPart
!= 0,
245 "AllocateLocallyUniqueId returned a well-known LUID\n");
246 ok(luid1
.LowPart
!= luid2
.LowPart
|| luid1
.HighPart
!= luid2
.HighPart
,
247 "AllocateLocallyUniqueId returned non-unique LUIDs\n");
248 ret
= pAllocateLocallyUniqueId(NULL
);
249 ok( !ret
&& GetLastError() == ERROR_NOACCESS
,
250 "AllocateLocallyUniqueId(NULL) didn't return ERROR_NOACCESS: %ld\n",
254 static void test_lookupPrivilegeName(void)
256 BOOL (WINAPI
*pLookupPrivilegeNameA
)(LPSTR
, PLUID
, LPSTR
, LPDWORD
);
257 char buf
[MAX_PATH
]; /* arbitrary, seems long enough */
258 DWORD cchName
= sizeof(buf
);
259 LUID luid
= { 0, 0 };
263 /* check whether it's available first */
264 pLookupPrivilegeNameA
= (void*)GetProcAddress(hmod
, "LookupPrivilegeNameA");
265 if (!pLookupPrivilegeNameA
) return;
266 luid
.LowPart
= SE_CREATE_TOKEN_PRIVILEGE
;
267 ret
= pLookupPrivilegeNameA(NULL
, &luid
, buf
, &cchName
);
268 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
271 /* check with a short buffer */
273 luid
.LowPart
= SE_CREATE_TOKEN_PRIVILEGE
;
274 ret
= pLookupPrivilegeNameA(NULL
, &luid
, NULL
, &cchName
);
275 ok( !ret
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
,
276 "LookupPrivilegeNameA didn't fail with ERROR_INSUFFICIENT_BUFFER: %ld\n",
278 ok(cchName
== strlen("SeCreateTokenPrivilege") + 1,
279 "LookupPrivilegeNameA returned an incorrect required length for\n"
280 "SeCreateTokenPrivilege (got %ld, expected %d)\n", cchName
,
281 strlen("SeCreateTokenPrivilege") + 1);
282 /* check a known value and its returned length on success */
283 cchName
= sizeof(buf
);
284 ok(pLookupPrivilegeNameA(NULL
, &luid
, buf
, &cchName
) &&
285 cchName
== strlen("SeCreateTokenPrivilege"),
286 "LookupPrivilegeNameA returned an incorrect output length for\n"
287 "SeCreateTokenPrivilege (got %ld, expected %d)\n", cchName
,
288 (int)strlen("SeCreateTokenPrivilege"));
289 /* check known values */
290 for (i
= SE_MIN_WELL_KNOWN_PRIVILEGE
; i
< SE_MAX_WELL_KNOWN_PRIVILEGE
; i
++)
293 cchName
= sizeof(buf
);
294 ret
= pLookupPrivilegeNameA(NULL
, &luid
, buf
, &cchName
);
295 ok( ret
|| GetLastError() == ERROR_NO_SUCH_PRIVILEGE
,
296 "LookupPrivilegeNameA(0.%ld) failed: %ld\n", i
, GetLastError());
298 /* check a bogus LUID */
299 luid
.LowPart
= 0xdeadbeef;
300 cchName
= sizeof(buf
);
301 ret
= pLookupPrivilegeNameA(NULL
, &luid
, buf
, &cchName
);
302 ok( !ret
&& GetLastError() == ERROR_NO_SUCH_PRIVILEGE
,
303 "LookupPrivilegeNameA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
305 /* check on a bogus system */
306 luid
.LowPart
= SE_CREATE_TOKEN_PRIVILEGE
;
307 cchName
= sizeof(buf
);
308 ret
= pLookupPrivilegeNameA("b0gu5.Nam3", &luid
, buf
, &cchName
);
309 ok( !ret
&& GetLastError() == RPC_S_SERVER_UNAVAILABLE
,
310 "LookupPrivilegeNameA didn't fail with RPC_S_SERVER_UNAVAILABLE: %ld\n",
320 static void test_lookupPrivilegeValue(void)
322 static const struct NameToLUID privs
[] = {
323 { "SeCreateTokenPrivilege", SE_CREATE_TOKEN_PRIVILEGE
},
324 { "SeAssignPrimaryTokenPrivilege", SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
},
325 { "SeLockMemoryPrivilege", SE_LOCK_MEMORY_PRIVILEGE
},
326 { "SeIncreaseQuotaPrivilege", SE_INCREASE_QUOTA_PRIVILEGE
},
327 { "SeMachineAccountPrivilege", SE_MACHINE_ACCOUNT_PRIVILEGE
},
328 { "SeTcbPrivilege", SE_TCB_PRIVILEGE
},
329 { "SeSecurityPrivilege", SE_SECURITY_PRIVILEGE
},
330 { "SeTakeOwnershipPrivilege", SE_TAKE_OWNERSHIP_PRIVILEGE
},
331 { "SeLoadDriverPrivilege", SE_LOAD_DRIVER_PRIVILEGE
},
332 { "SeSystemProfilePrivilege", SE_SYSTEM_PROFILE_PRIVILEGE
},
333 { "SeSystemtimePrivilege", SE_SYSTEMTIME_PRIVILEGE
},
334 { "SeProfileSingleProcessPrivilege", SE_PROF_SINGLE_PROCESS_PRIVILEGE
},
335 { "SeIncreaseBasePriorityPrivilege", SE_INC_BASE_PRIORITY_PRIVILEGE
},
336 { "SeCreatePagefilePrivilege", SE_CREATE_PAGEFILE_PRIVILEGE
},
337 { "SeCreatePermanentPrivilege", SE_CREATE_PERMANENT_PRIVILEGE
},
338 { "SeBackupPrivilege", SE_BACKUP_PRIVILEGE
},
339 { "SeRestorePrivilege", SE_RESTORE_PRIVILEGE
},
340 { "SeShutdownPrivilege", SE_SHUTDOWN_PRIVILEGE
},
341 { "SeDebugPrivilege", SE_DEBUG_PRIVILEGE
},
342 { "SeAuditPrivilege", SE_AUDIT_PRIVILEGE
},
343 { "SeSystemEnvironmentPrivilege", SE_SYSTEM_ENVIRONMENT_PRIVILEGE
},
344 { "SeChangeNotifyPrivilege", SE_CHANGE_NOTIFY_PRIVILLEGE
},
345 { "SeRemoteShutdownPrivilege", SE_REMOTE_SHUTDOWN_PRIVILEGE
},
346 { "SeUndockPrivilege", SE_UNDOCK_PRIVILEGE
},
347 { "SeSyncAgentPrivilege", SE_SYNC_AGENT_PRIVILEGE
},
348 { "SeEnableDelegationPrivilege", SE_ENABLE_DELEGATION_PRIVILEGE
},
349 { "SeManageVolumePrivilege", SE_MANAGE_VOLUME_PRIVILEGE
},
350 { "SeImpersonatePrivilege", SE_IMPERSONATE_PRIVILEGE
},
351 { "SeCreateGlobalPrivilege", SE_CREATE_GLOBAL_PRIVILEGE
},
353 BOOL (WINAPI
*pLookupPrivilegeValueA
)(LPCSTR
, LPCSTR
, PLUID
);
358 /* check whether it's available first */
359 pLookupPrivilegeValueA
= (void*)GetProcAddress(hmod
, "LookupPrivilegeValueA");
360 if (!pLookupPrivilegeValueA
) return;
361 ret
= pLookupPrivilegeValueA(NULL
, "SeCreateTokenPrivilege", &luid
);
362 if (!ret
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
365 /* check a bogus system name */
366 ret
= pLookupPrivilegeValueA("b0gu5.Nam3", "SeCreateTokenPrivilege", &luid
);
367 ok( !ret
&& GetLastError() == RPC_S_SERVER_UNAVAILABLE
,
368 "LookupPrivilegeValueA didn't fail with RPC_S_SERVER_UNAVAILABLE: %ld\n",
370 /* check a NULL string */
371 ret
= pLookupPrivilegeValueA(NULL
, 0, &luid
);
372 ok( !ret
&& GetLastError() == ERROR_NO_SUCH_PRIVILEGE
,
373 "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
375 /* check a bogus privilege name */
376 ret
= pLookupPrivilegeValueA(NULL
, "SeBogusPrivilege", &luid
);
377 ok( !ret
&& GetLastError() == ERROR_NO_SUCH_PRIVILEGE
,
378 "LookupPrivilegeValueA didn't fail with ERROR_NO_SUCH_PRIVILEGE: %ld\n",
380 /* check case insensitive */
381 ret
= pLookupPrivilegeValueA(NULL
, "sEcREATEtOKENpRIVILEGE", &luid
);
383 "LookupPrivilegeValueA(NULL, sEcREATEtOKENpRIVILEGE, &luid) failed: %ld\n",
385 for (i
= 0; i
< sizeof(privs
) / sizeof(privs
[0]); i
++)
387 /* Not all privileges are implemented on all Windows versions, so
388 * don't worry if the call fails
390 if (pLookupPrivilegeValueA(NULL
, privs
[i
].name
, &luid
))
392 ok(luid
.LowPart
== privs
[i
].lowPart
,
393 "LookupPrivilegeValueA returned an invalid LUID for %s\n",
399 static void test_luid(void)
402 test_lookupPrivilegeName();
403 test_lookupPrivilegeValue();
406 static void test_FileSecurity(void)
408 char directory
[MAX_PATH
];
409 DWORD retval
, outSize
;
413 pGetFileSecurityA
= (fnGetFileSecurityA
)
414 GetProcAddress( hmod
, "GetFileSecurityA" );
415 if( !pGetFileSecurityA
)
418 retval
= GetTempPathA(sizeof(directory
), directory
);
420 trace("GetTempPathA failed\n");
424 strcpy(directory
, "\\Should not exist");
426 SetLastError(NO_ERROR
);
427 result
= pGetFileSecurityA( directory
,OWNER_SECURITY_INFORMATION
,buffer
,0x40,&outSize
);
428 ok(!result
, "GetFileSecurityA should fail for not existing directories/files\n");
429 ok( (GetLastError() == ERROR_FILE_NOT_FOUND
) ||
430 (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) ,
431 "last error ERROR_FILE_NOT_FOUND / ERROR_CALL_NOT_IMPLEMENTED (98) "
432 "expected, got %ld\n", GetLastError());