luajitos

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

USAGE_EXAMPLE.md (10646B)


      1 # Password Prompt Usage Examples
      2 
      3 ## Quick Start
      4 
      5 ### 1. First-Time Setup
      6 
      7 Before using the password prompt system, you need to create a password hash:
      8 
      9 ```lua
     10 -- Boot into LuajitOS and run this code (requires crypto permission):
     11 
     12 local password = "admin"  -- Your chosen password
     13 local salt = "LuajitOS-AdminSalt-v1"
     14 
     15 -- Generate Argon2id hash
     16 local hash = crypto.Argon2id(password, salt)
     17 
     18 -- Base64 encode function
     19 local b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
     20 local function base64_encode(data)
     21     if not data or #data == 0 then return "" end
     22     local result = {}
     23     for i = 1, #data, 3 do
     24         local b1 = string.byte(data, i)
     25         local b2 = string.byte(data, i + 1) or 0
     26         local b3 = string.byte(data, i + 2) or 0
     27         local n = b1 * 65536 + b2 * 256 + b3
     28         local c1 = bit.band(bit.rshift(n, 18), 63) + 1
     29         local c2 = bit.band(bit.rshift(n, 12), 63) + 1
     30         local c3 = bit.band(bit.rshift(n, 6), 63) + 1
     31         local c4 = bit.band(n, 63) + 1
     32         table.insert(result, b64chars:sub(c1, c1))
     33         table.insert(result, b64chars:sub(c2, c2))
     34         if i + 1 <= #data then table.insert(result, b64chars:sub(c3, c3)) else table.insert(result, '=') end
     35         if i + 2 <= #data then table.insert(result, b64chars:sub(c4, c4)) else table.insert(result, '=') end
     36     end
     37     return table.concat(result)
     38 end
     39 
     40 -- Print the hash
     41 print("Password hash (base64):")
     42 print(base64_encode(hash))
     43 print("")
     44 print("Save this to /os/password.hash and rebuild the ISO")
     45 ```
     46 
     47 ### 2. Start the Password Prompt Service
     48 
     49 ```lua
     50 -- Run the password prompt app (stays in background)
     51 run("com.luajitos.passprompt")
     52 ```
     53 
     54 The app will export two functions:
     55 - `admin.requestPermission(pid, permission, callback)`
     56 - `admin.requestPath(pid, path, callback)`
     57 
     58 ## Example 1: Request Network Permission
     59 
     60 ```lua
     61 -- In your app manifest.lua, add:
     62 permissions = {
     63     "draw",
     64     "import"  -- Required to import from other apps
     65 }
     66 
     67 -- In your app code:
     68 local function enableNetworking()
     69     -- Get the passprompt app
     70     local passprompt = apps["com.luajitos.passprompt"]
     71 
     72     if not passprompt then
     73         print("ERROR: Password prompt app not running")
     74         print("Run: run('com.luajitos.passprompt')")
     75         return
     76     end
     77 
     78     -- Get the exported function
     79     local requestPerm = passprompt.exports["admin.requestPermission"]
     80     if not requestPerm then
     81         print("ERROR: admin.requestPermission not found")
     82         return
     83     end
     84 
     85     -- Request permission
     86     print("Requesting network permission...")
     87     requestPerm.func(app.pid, "network", function(granted)
     88         if granted then
     89             print("SUCCESS! Network permission granted")
     90             -- Now you can use network APIs
     91             -- local SafeHTTP = require("SafeHTTP")
     92             -- local response = SafeHTTP.get("http://example.com")
     93         else
     94             print("Permission denied or cancelled")
     95         end
     96     end)
     97 end
     98 
     99 -- Call when user clicks a "Connect" button
    100 window.onClick = function(mx, my)
    101     if clickedConnectButton(mx, my) then
    102         enableNetworking()
    103     end
    104 end
    105 ```
    106 
    107 ## Example 2: Request Filesystem Path Access
    108 
    109 ```lua
    110 -- Request access to system logs
    111 local function requestLogAccess()
    112     local passprompt = apps["com.luajitos.passprompt"]
    113 
    114     if not passprompt or not passprompt.exports["admin.requestPath"] then
    115         print("ERROR: Password prompt not available")
    116         return
    117     end
    118 
    119     local requestPath = passprompt.exports["admin.requestPath"]
    120 
    121     print("Requesting /var/log/* access...")
    122     requestPath.func(app.pid, "/var/log/*", function(granted)
    123         if granted then
    124             print("Path access granted!")
    125             -- Now you can read/write to /var/log/*
    126             local logs = fs:read("/var/log/system.log")
    127             if logs then
    128                 print("Log file contents:")
    129                 print(logs)
    130             end
    131         else
    132             print("Path access denied")
    133         end
    134     end)
    135 end
    136 ```
    137 
    138 ## Example 3: Request Multiple Permissions
    139 
    140 ```lua
    141 local function requestAllPermissions()
    142     local passprompt = apps["com.luajitos.passprompt"]
    143 
    144     if not passprompt then
    145         print("Password prompt app not running")
    146         return
    147     end
    148 
    149     local requestPerm = passprompt.exports["admin.requestPermission"].func
    150     local permissions = {"network", "ramdisk", "scheduling"}
    151     local currentIndex = 1
    152 
    153     local function requestNext()
    154         if currentIndex > #permissions then
    155             print("All permissions processed!")
    156             return
    157         end
    158 
    159         local perm = permissions[currentIndex]
    160         print("Requesting: " .. perm)
    161 
    162         requestPerm(app.pid, perm, function(granted)
    163             if granted then
    164                 print("Granted: " .. perm)
    165             else
    166                 print("Denied: " .. perm)
    167             end
    168 
    169             currentIndex = currentIndex + 1
    170             requestNext()  -- Request next permission
    171         end)
    172     end
    173 
    174     requestNext()
    175 end
    176 ```
    177 
    178 ## Example 4: Safe Permission Request with Retry
    179 
    180 ```lua
    181 local function safeRequestPermission(permission, maxRetries)
    182     maxRetries = maxRetries or 3
    183     local attempts = 0
    184 
    185     local function tryRequest()
    186         attempts = attempts + 1
    187 
    188         local passprompt = apps["com.luajitos.passprompt"]
    189         if not passprompt or not passprompt.exports["admin.requestPermission"] then
    190             print("ERROR: Password prompt not available")
    191             return
    192         end
    193 
    194         local requestPerm = passprompt.exports["admin.requestPermission"].func
    195 
    196         requestPerm(app.pid, permission, function(granted)
    197             if granted then
    198                 print("Permission granted: " .. permission)
    199                 -- Continue with your app logic
    200             elseif attempts < maxRetries then
    201                 print("Attempt " .. attempts .. " failed. " .. (maxRetries - attempts) .. " retries remaining")
    202                 -- Let user try again
    203             else
    204                 print("Failed to obtain permission after " .. maxRetries .. " attempts")
    205                 -- Gracefully degrade or exit
    206             end
    207         end)
    208     end
    209 
    210     tryRequest()
    211 end
    212 
    213 -- Usage:
    214 safeRequestPermission("network", 3)
    215 ```
    216 
    217 ## Example 5: Conditional Permission Request
    218 
    219 ```lua
    220 -- Only request permission if not already granted
    221 local function ensurePermission(permission, callback)
    222     -- Check if we already have the permission
    223     local hasPermission = false
    224     if app.permissions then
    225         for _, perm in ipairs(app.permissions) do
    226             if perm == permission then
    227                 hasPermission = true
    228                 break
    229             end
    230         end
    231     end
    232 
    233     if hasPermission then
    234         print("Already have permission: " .. permission)
    235         if callback then callback(true) end
    236         return
    237     end
    238 
    239     -- Don't have it, request it
    240     print("Requesting permission: " .. permission)
    241     local passprompt = apps["com.luajitos.passprompt"]
    242 
    243     if not passprompt or not passprompt.exports["admin.requestPermission"] then
    244         print("ERROR: Cannot request permission")
    245         if callback then callback(false) end
    246         return
    247     end
    248 
    249     local requestPerm = passprompt.exports["admin.requestPermission"].func
    250     requestPerm(app.pid, permission, callback)
    251 end
    252 
    253 -- Usage:
    254 ensurePermission("network", function(granted)
    255     if granted then
    256         -- Use network
    257     else
    258         -- Show error to user
    259     end
    260 end)
    261 ```
    262 
    263 ## Testing the Password Prompt
    264 
    265 Run the included test application:
    266 
    267 ```lua
    268 run("com.luajitos.passprompttest")
    269 ```
    270 
    271 This will create a window with two buttons:
    272 1. **Request Network Permission** - Tests `admin.requestPermission`
    273 2. **Request /var/log/* Path** - Tests `admin.requestPath`
    274 
    275 Click either button to see the password prompt appear on top of all windows.
    276 
    277 ## Password Prompt UI
    278 
    279 When the prompt appears:
    280 
    281 ### Keyboard Controls
    282 - **Type**: Enter your password (displayed as asterisks)
    283 - **Backspace**: Delete last character
    284 - **Enter**: Submit password
    285 - **Escape**: Cancel request
    286 
    287 ### Mouse Controls
    288 - **OK Button**: Submit password
    289 - **Cancel Button**: Cancel request
    290 - **Close (X)**: Cancel request
    291 
    292 ### Visual Feedback
    293 - **Blue text**: Shows PID and requested permission/path
    294 - **Red text**: Shows error messages (wrong password, etc.)
    295 - **Cursor blink**: Indicates input field is active
    296 
    297 ## Security Best Practices
    298 
    299 ### For App Developers
    300 
    301 1. **Only request what you need**: Don't request permissions unnecessarily
    302 2. **Explain to users**: Show why you need the permission before prompting
    303 3. **Handle denials gracefully**: Don't crash if permission is denied
    304 4. **Don't spam requests**: Only request once per user action
    305 5. **Clear sensitive data**: Don't store passwords or responses
    306 
    307 ### For System Administrators
    308 
    309 1. **Use strong passwords**: Minimum 12 characters, mix of types
    310 2. **Change default password**: Don't use "admin" in production
    311 3. **Monitor requests**: Check serial console logs for suspicious activity
    312 4. **Limit app access**: Only install trusted apps with "import" permission
    313 5. **Regular audits**: Review which apps have which permissions
    314 
    315 ## Troubleshooting
    316 
    317 ### "Password prompt app not running"
    318 ```lua
    319 run("com.luajitos.passprompt")
    320 ```
    321 
    322 ### "admin.requestPermission not found"
    323 The passprompt app may not have exported the function. Check logs:
    324 ```
    325 osprint("Passprompt exports: ", app.listExports())
    326 ```
    327 
    328 ### Password prompt doesn't appear
    329 - Check that passprompt has "draw" and "system-all" permissions
    330 - Verify window is set to `alwaysOnTop = true`
    331 - Check serial console for errors
    332 
    333 ### "Password file not found"
    334 Generate and save password hash to `/os/password.hash` (see First-Time Setup)
    335 
    336 ### "Incorrect password" even with correct password
    337 - Verify hash was generated with same salt: "LuajitOS-AdminSalt-v1"
    338 - Check for whitespace in password.hash file
    339 - Ensure base64 encoding is correct
    340 
    341 ## Advanced Usage
    342 
    343 ### Custom Salt (Not Recommended)
    344 
    345 If you need a different salt for security reasons:
    346 
    347 1. Modify `iso_includes/apps/com.luajitos.passprompt/src/init.lua`
    348 2. Change line: `local salt = "LuajitOS-AdminSalt-v1"`
    349 3. Regenerate password hash with new salt
    350 4. Rebuild ISO
    351 
    352 **Warning**: This breaks compatibility with existing password hashes.
    353 
    354 ### Integration with External Auth
    355 
    356 You can modify the `verifyPassword` function to check against:
    357 - LDAP servers
    358 - OAuth tokens
    359 - Hardware keys (via custom crypto hooks)
    360 
    361 This requires modifying the passprompt app source code.
    362 
    363 ## See Also
    364 
    365 - `README.md` - Full documentation
    366 - `/os/SETUP_PASSWORD.md` - Password setup instructions
    367 - `manifest.lua` - Permission requirements
    368 - `com.luajitos.passprompttest` - Test application source