@@ -359,6 +359,168 @@ func TestBuildSecurityDescriptor(t *testing.T) {
359
359
}
360
360
}
361
361
362
+ // getEntriesFromACL returns a list of explicit access control entries associated with the given ACL.
363
+ func getEntriesFromACL (acl * windows.ACL ) (aces []* windows.ACCESS_ALLOWED_ACE , err error ) {
364
+ aces = make ([]* windows.ACCESS_ALLOWED_ACE , acl .AceCount )
365
+
366
+ for i := uint16 (0 ); i < acl .AceCount ; i ++ {
367
+ err = windows .GetAce (acl , uint32 (i ), & aces [i ])
368
+ if err != nil {
369
+ return nil , err
370
+ }
371
+ }
372
+
373
+ return aces , nil
374
+ }
375
+
376
+ func TestGetACEsFromACL (t * testing.T ) {
377
+ // Create a temporary file to set ACLs on and test getting the ACEs from the ACL.
378
+ f , err := os .CreateTemp ("" , "foo.lish" )
379
+ defer os .Remove (f .Name ())
380
+
381
+ if err = f .Close (); err != nil {
382
+ t .Fatal (err )
383
+ }
384
+
385
+ // Well-known SID Strings:
386
+ // https://support.microsoft.com/en-us/help/243330/well-known-security-identifiers-in-windows-operating-systems
387
+ ownerSid , err := windows .StringToSid ("S-1-3-2" )
388
+ if err != nil {
389
+ t .Fatal (err )
390
+ }
391
+ groupSid , err := windows .StringToSid ("S-1-3-3" )
392
+ if err != nil {
393
+ t .Fatal (err )
394
+ }
395
+ worldSid , err := windows .StringToSid ("S-1-1-0" )
396
+ if err != nil {
397
+ t .Fatal (err )
398
+ }
399
+
400
+ ownerPermissions := windows .ACCESS_MASK (windows .GENERIC_ALL )
401
+ groupPermissions := windows .ACCESS_MASK (windows .GENERIC_READ | windows .GENERIC_EXECUTE )
402
+ worldPermissions := windows .ACCESS_MASK (windows .GENERIC_READ )
403
+
404
+ access := []windows.EXPLICIT_ACCESS {
405
+ {
406
+ AccessPermissions : ownerPermissions ,
407
+ AccessMode : windows .GRANT_ACCESS ,
408
+ Trustee : windows.TRUSTEE {
409
+ TrusteeForm : windows .TRUSTEE_IS_SID ,
410
+ TrusteeValue : windows .TrusteeValueFromSID (ownerSid ),
411
+ },
412
+ },
413
+ {
414
+ AccessPermissions : groupPermissions ,
415
+ AccessMode : windows .GRANT_ACCESS ,
416
+ Trustee : windows.TRUSTEE {
417
+ TrusteeForm : windows .TRUSTEE_IS_SID ,
418
+ TrusteeType : windows .TRUSTEE_IS_GROUP ,
419
+ TrusteeValue : windows .TrusteeValueFromSID (groupSid ),
420
+ },
421
+ },
422
+ {
423
+ AccessPermissions : worldPermissions ,
424
+ AccessMode : windows .GRANT_ACCESS ,
425
+ Trustee : windows.TRUSTEE {
426
+ TrusteeForm : windows .TRUSTEE_IS_SID ,
427
+ TrusteeType : windows .TRUSTEE_IS_GROUP ,
428
+ TrusteeValue : windows .TrusteeValueFromSID (worldSid ),
429
+ },
430
+ },
431
+ }
432
+
433
+ acl , err := windows .ACLFromEntries (access , nil )
434
+ if err != nil {
435
+ t .Fatal (err )
436
+ }
437
+
438
+ // Set new ACL.
439
+ err = windows .SetNamedSecurityInfo (
440
+ f .Name (),
441
+ windows .SE_FILE_OBJECT ,
442
+ windows .DACL_SECURITY_INFORMATION | windows .PROTECTED_DACL_SECURITY_INFORMATION ,
443
+ nil ,
444
+ nil ,
445
+ acl ,
446
+ nil ,
447
+ )
448
+ if err != nil {
449
+ t .Fatal (err )
450
+ }
451
+
452
+ descriptor , err := windows .GetNamedSecurityInfo (
453
+ f .Name (),
454
+ windows .SE_FILE_OBJECT ,
455
+ windows .DACL_SECURITY_INFORMATION | windows .PROTECTED_DACL_SECURITY_INFORMATION | windows .OWNER_SECURITY_INFORMATION | windows .GROUP_SECURITY_INFORMATION ,
456
+ )
457
+ if err != nil {
458
+ t .Fatal (err )
459
+ }
460
+
461
+ dacl , _ , err := descriptor .DACL ()
462
+ if err != nil {
463
+ t .Fatal (err )
464
+ }
465
+
466
+ owner , _ , err := descriptor .Owner ()
467
+ if err != nil {
468
+ t .Fatal (err )
469
+ }
470
+
471
+ group , _ , err := descriptor .Group ()
472
+ if err != nil {
473
+ t .Fatal (err )
474
+ }
475
+
476
+ entries , err := getEntriesFromACL (dacl )
477
+ if err != nil {
478
+ t .Fatal (err )
479
+ }
480
+
481
+ if len (entries ) != 3 {
482
+ t .Fatalf ("Expected newly set ACL to only have 3 entries." )
483
+ }
484
+
485
+ // https://docs.microsoft.com/en-us/windows/win32/fileio/file-access-rights-constants
486
+ read := uint32 (windows .FILE_READ_DATA | windows .FILE_READ_ATTRIBUTES )
487
+ write := uint32 (windows .FILE_WRITE_DATA | windows .FILE_APPEND_DATA | windows .FILE_WRITE_ATTRIBUTES | windows .FILE_WRITE_EA )
488
+ execute := uint32 (windows .FILE_READ_DATA | windows .FILE_EXECUTE )
489
+
490
+ // Check the set ACEs. We should have the equivalent of 754.
491
+ for _ , entry := range entries {
492
+ mask := uint32 (entry .Mask )
493
+ actual := 0
494
+
495
+ if mask & read == read {
496
+ actual |= 4
497
+ }
498
+ if mask & write == write {
499
+ actual |= 2
500
+ }
501
+ if mask & execute == execute {
502
+ actual |= 1
503
+ }
504
+
505
+ entrySid := (* windows .SID )(unsafe .Pointer (& entry .SidStart ))
506
+ if owner .Equals (entrySid ) {
507
+ if actual != 7 {
508
+ t .Fatalf ("Expected owner to have FullAccess permissions." )
509
+ }
510
+ } else if group .Equals (entrySid ) {
511
+ if actual != 5 {
512
+ t .Fatalf ("Expected group to have only Read and Execute permissions." )
513
+ }
514
+ } else if worldSid .Equals (entrySid ) {
515
+ if actual != 4 {
516
+ t .Fatalf ("Expected the World to have only Read permissions." )
517
+ }
518
+ } else {
519
+ t .Fatalf ("Unexpected SID in ACEs: %s" , entrySid .String ())
520
+ }
521
+ }
522
+ }
523
+
362
524
func TestGetDiskFreeSpaceEx (t * testing.T ) {
363
525
cwd , err := windows .UTF16PtrFromString ("." )
364
526
if err != nil {
0 commit comments