Screensaver preferences askForPassword, askForPasswordDelay disappear in 10.13

Hi,

I need to read a couple of preferences for screen savers: ‘askForPassword’ and ‘askForPasswordDelay’

Up to macOS 10.12 I could retrieve them using

defaults read com.apple.screensaver

See plists below.

I crawled the web, Apple forums, MBS plugins … but couldn’t find anything. They just vanished…

Does someone know how to read these 2 values ?

plist on 10.12

<dict> <key>askForPassword</key> <integer>1</integer> <key>askForPasswordDelay</key> <real>5</real> <key>tokenRemovalAction</key> <integer>0</integer>

plist starting from 10.13

<dict> <key>tokenRemovalAction</key> <integer>0</integer>

Yes but I’m on mobile at the moment so I don’t have code handy. See https://iscreensaver.com/help/notes/high_sierra/high_sierra.shtml for related discussion. I’ll follow up when im back at desk.

Hi Michael,

Thanks. I already looked at this post but AFAIK they just confirm what I found, they don’t provide solutions.
iScreenSaver is an app, they don’t provide source code. I’ll have a better look.

But if you have a solution to read these 2 values, I’m interested !

This is a super ugly hack, but it worked for me. Use with caution, etc.

Private Function GetLockScreenTimeoutFromKB() as integer
  #if TargetCocoa
    ' hack for finding the value which we used to be able to get from
    ' defaults read com.apple.screensaver askForPasswordDelay
    
    'Notes 
    ' The file where the data was stored was deteremined with these terminal commands
    ' see http://www.westwind.com/reference/OS-X/finding-settings.html
    ' sudo -s # get a root shell
    ' touch timestamp
    ' find -x / -newer ~/timestamp >~/changedfiles.txt
    ' bbedit changedfiles.txt
    
    ' then, the actual byte data was found by making changes in System Preferences 
    ' and comparing before vs. after using HexFiend.app
    
    ' Notes on return values:
    ' - 2 means an error
    '  -1 means the lock screen timeout is disabled
    '  0  means 'immediately'
    '  1+ all other positive values are the timeout in seconds
    
    #Pragma DisableBackgroundTasks
    
    dim root as FolderItem = SpecialFolder.UserLibrary
    root = root.child("Keychains")
    dim matches() as FolderItem
    dim dates() as double
    // we are looking for user.kb which is in a folder with a giant hex name
    for i as integer = 1 to root.Count
      dim g as FolderItem = root.item(i)
      if g <> nil and g.exists then
        dim f as FolderItem = g.child("user.kb")
        if f <> nil and f.exists then
          matches.append f
          dates.append f.ModificationDate.TotalSeconds
          system.debugLog(f.ModificationDate.SQLDateTime + " " + f.NativePath)
        end if
      end if
    next
    
    if matches.Ubound = -1 then
      system.debugLog(CurrentMethodName + " unable to find user.kb file")
      return -2
    end if
    
    
    dates.sortWith(matches) ' sort by modification date
    dim f as FolderItem = matches.pop ' get the most recent one
    
    dim timeout as int32 = GetLockScreenParseKeybag(f)
    
    return timeout
    
    
  #endif
End Function

Private Function GetLockScreenParseKeybag(f as FolderItem) as integer
  #if TargetCocoa
    #Pragma DisableBackgroundTasks
    
    
    ' hack for finding the value which we used to be able to get from
    ' defaults read com.apple.screensaver askForPasswordDelay
    
    ' this parses the keybag file to return the value
    
    
    ' see https://github.com/n0fate/iChainbreaker/blob/master/keybag.py
    
    'KEYBAG_DATA = '>4sI'
    'KEYBAG_DATA_SIZE = 8
    'KEYBAG_HEADER = '>4sII4sII4sI16s4sI40s4sII4sI20s4sII'
    'KEYBAG_HEADER_SIZE = 148
    
    
    dim mb as MemoryBlock = ReadFileIntoMemoryBlock(f)
    
    system.debugLog "Keybag size " + str(mb.size)
    
    // quick & dirty method of parsing: find the tag 'GRCE' and then grab the next 4 bytes
    // absence of the GRCE atom seems to indicate that 'immediately' is the setting.
    
    dim data as string = mb
    ' note: when using strings, positions are 1-based
    dim x1 as integer = data.InStrb("GRCE")
    if x1 = 0 then
      system.debugLog CurrentMethodName + " failed to find GRCE tag, will use 'immediately' as result"
      return 0
    else
      x1 = x1 -1 // zero-based
      system.debugLog CurrentMethodName + " found GRCE tag at " + str(x1)
    end if
    
    // it's actually bigendian so just use the MemoryBlock
    mb.LittleEndian = false
    
    dim tagLength as integer = mb.Int32Value(x1+4)
    system.debugLog CurrentMethodName + " GRCE tagLength = " + str(tagLength)
    
    dim location as integer = x1 + 8 + tagLength - 4
    dim timeout as integer = mb.Int32Value(location)
    
    select case timeout
    case 2147483647
      timeout = -1  // special value of MAXINT-1 means "Disabled"
    case -2102302411
      timeout = 0 // immediately
    end select
    
    dim msg as string = "Keybag Values = "
    for i as integer = x1 to x1 + tagLength + 4 -1
      msg = msg + hex(mb.byte(i)) + " "
    next
    system.debugLog msg
    
    
    return timeout
    
    
  #endif
  
  
End Function

Thanks Michael !

It works on my dev machine, and on another test system (both Catalina).

But … when signed/notarized using AppWrapper3 I get a sandbox violation.

Sandbox: testScreenSaverP(1886) deny(1) file-read-data /Users/olivier/Library/Keychains Violation: deny(1) file-read-data /Users/olivier/Library/Keychains

Do you use it sandboxed ?
Do you use special entitlements ?

Thanks !

I suspect this will not work on Catalina (and perhaps not Mojave) due to increased security restrictions. Can you say more about what you are trying to accomplish? Why do you want that setting?

I have a custom software that was only used in office premises and the macs controlled by policies.
With covid-19 confinement rules, more and more users are working from home, no more policies, it’s a customer concern.

I need to restrict access to some windows when there’s no password requested after screensaver started and have a maximal delay for asking the password.
They don’t want to enforce these settings, they just want to check them and to inform the user.

This was fine up until 10.12 Sierra, using ‘read defaults’.

I know I can get System Idle time and close windows or even lock the screen but it requires more changes to the software than just relying on system settings.

you can read the display sleep time using

/usr/bin/pmset -g | /usr/bin/grep displaysleep | /usr/bin/awk '{ print $2 }'

but that’s not the same as the lock time.

Thanks.
For ‘askForPassword’ I could use appleScript:

require password to wake (boolean) : Is a password required to wake the computer from sleep or screen saver?
--> tell application "System Events" to tell security preferences to get require password to wake

For ‘aksForPasswordDelay’ I can’t find the correct system event, there is

‘log out when inactive interval (integer) : The interval of inactivity after which the computer will log out’
but it always return 60 which doesn’t correspond to anything in my settings