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