From 55b6fd73b8cea7dcec4b204417cbb0f7cd9d7540 Mon Sep 17 00:00:00 2001 From: Ivan Godwin Date: Wed, 8 Jul 2026 00:20:29 -0700 Subject: [PATCH] Add od-cfg-persist runbook + od-cfg-acl script Persist Open Dental's 'Do not show this window on startup' by making FreeDentalConfig.xml writable: - Option A: one-time elevated save - Option B (preferred): grant Users Modify via well-known SID S-1-5-32-545 - od-cfg-acl.ps1 auto-resolves 64/32-bit install path, iex-safe conventions - Security note on reversible MySQL password in the config; limited user / Middle Tier - Cites OD manual freedentalconfig.html / choosedatabase.html Co-Authored-By: Claude Opus 4.8 --- README.md | 2 ++ od-cfg-persist.md | 78 ++++++++++++++++++++++++++++++++++++++++++ scripts/od-cfg-acl.ps1 | 64 ++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 od-cfg-persist.md create mode 100644 scripts/od-cfg-acl.ps1 diff --git a/README.md b/README.md index 01ca866..771c9fc 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,9 @@ run time — never commit filled-in values. | File | Purpose | |---|---| | [`od-smb-cred.md`](od-smb-cred.md) | Open Dental SMB share — stored-credential fix | +| [`od-cfg-persist.md`](od-cfg-persist.md) | Open Dental — persist "Do not show this window on startup" (writable FreeDentalConfig.xml) | | [`scripts/cg-disable.ps1`](scripts/cg-disable.ps1) | Disable Credential Guard, then reboot (prompts to confirm) | +| [`scripts/od-cfg-acl.ps1`](scripts/od-cfg-acl.ps1) | Grant Users Modify on FreeDentalConfig.xml (Option B of od-cfg-persist) | ## Tiers diff --git a/od-cfg-persist.md b/od-cfg-persist.md new file mode 100644 index 0000000..e746f58 --- /dev/null +++ b/od-cfg-persist.md @@ -0,0 +1,78 @@ +# Runbook: Open Dental — Persist "Do not show this window on startup" + +**Applies to:** Windows workstation where Open Dental is run by a standard (non-admin) user. +**Symptom:** The **Choose Database** window appears on every launch even though **"Do not show this window on startup (this computer only)"** is checked. The checkbox appears to take but does not survive a restart. +**Root cause:** The setting is stored in `FreeDentalConfig.xml` in the Open Dental install directory. Standard users lack write permission to that directory, so the change is never saved. Per Open Dental's docs, saving this window's settings requires the process to write that file. + +**Placeholders:** + +| Placeholder | Meaning | +|---|---| +| `` | Open Dental install directory (holds `FreeDentalConfig.xml`) — commonly under `Program Files` or `Program Files (x86)`; varies by version/architecture | + +--- + +## 1. Confirm the symptom + +Launch Open Dental **as the standard user who normally runs it**. Check **"Do not show this window on startup (this computer only)"**, click **OK**, then fully close and relaunch. + +- Window returns → the config file isn't being saved → continue. +- Window gone → nothing to do. + +## 2. Choose the fix + +| Situation | Use | +|---|---| +| One-off machine, or the daily user is already a local admin | **Option A** — one-time elevated save | +| Shared workstation, or the daily user is a standard (non-admin) user | **Option B** — persistent ACL grant *(preferred)* | + +Option A saves the setting once under an elevated context. Option B makes the file writable under the normal user context so Open Dental can rewrite it itself, now and after future changes — the durable fix for standard-user machines. + +## 3. Option A — One-time elevated save + +1. Right-click the Open Dental shortcut → **Run as administrator**. +2. Re-check **"Do not show this window on startup (this computer only)."** +3. Click **OK**, then close Open Dental. +4. Relaunch **as the standard user** and confirm the window no longer appears. + +> Because the elevated process could write the install directory, the setting saves. If the standard user later triggers another change to this window, it won't persist — for shared/standard-user machines prefer Option B. + +## 4. Option B — Persistent ACL grant (preferred) + +Grant the built-in **Users** group **Modify** on `FreeDentalConfig.xml` so Open Dental can rewrite it under the normal user context without elevation. + +Fastest, from an **elevated** PowerShell: + +``` +irm https://gitea.ivangodwin.com/ops/rb/raw/branch/main/scripts/od-cfg-acl.ps1 | iex +``` + +It resolves the install path (64-bit / 32-bit Program Files), confirms, and grants the permission. + +Offline / manual equivalent (elevated PowerShell or Command Prompt) — grant Modify to Users via the well-known SID, not the localized name "Users": + +``` +icacls "\FreeDentalConfig.xml" /grant *S-1-5-32-545:M +``` + +> `S-1-5-32-545` is the built-in **Users** group on every Windows install regardless of OS language — safer in scripts than the display name "Users," which is localized. `:M` = Modify. + +## 5. Verify + +Relaunch Open Dental **as the standard user**. Confirm the **Choose Database** window no longer appears on startup. + +If it still appears: confirm the ACL landed with `icacls "\FreeDentalConfig.xml"` (look for a `Users:(M)`-style entry), and confirm you edited the copy in the directory Open Dental actually launches from. + +--- + +## Security note + +On **direct-connection** setups, `FreeDentalConfig.xml` stores the MySQL password **obfuscated but reversible**. Granting the Users group write access does not change that exposure — but widening read/write on a file that holds DB credentials is worth calling out. + +- Use a **limited MySQL user** (scoped to the Open Dental database) for workstation connections rather than `root`. +- Longer-term, move to **Middle Tier**, which removes per-workstation DB credentials entirely (workstations talk to a service, not the database directly). + +## References + +- Open Dental manual — FreeDentalConfig.xml: +- Open Dental manual — Choose Database window: diff --git a/scripts/od-cfg-acl.ps1 b/scripts/od-cfg-acl.ps1 new file mode 100644 index 0000000..a158e9a --- /dev/null +++ b/scripts/od-cfg-acl.ps1 @@ -0,0 +1,64 @@ +<# +.SYNOPSIS + Grant the built-in Users group Modify on Open Dental's FreeDentalConfig.xml + so the "Do not show this window on startup" setting persists for standard + users. + +.DESCRIPTION + Open Dental stores the Choose Database window's "do not show on startup" + setting in FreeDentalConfig.xml in the install directory. Standard (non-admin) + users lack write permission there, so the checkbox never saves and the window + returns on every launch. This grants the built-in Users group Modify on that + one file, using the well-known SID (locale-independent). + + Auto-resolves the install directory across 64-bit / 32-bit Program Files; + fails clearly if FreeDentalConfig.xml isn't found in either. + +.NOTES + Run via: irm https://gitea.ivangodwin.com/ops/rb/raw/branch/main/scripts/od-cfg-acl.ps1 | iex + Referenced by od-cfg-persist.md, Option B. + + SECURITY: on direct-connection setups FreeDentalConfig.xml also holds the + MySQL password (obfuscated but reversible). Widening write access here does + not change that exposure, but prefer a limited MySQL user over root for + workstation connections, and Middle Tier as the long-term fix that removes + per-workstation DB credentials entirely. See the runbook's security note. +#> + +$ErrorActionPreference = 'Stop' + +# --- Admin check (do not rely on #Requires under iex) --- +$isAdmin = ([Security.Principal.WindowsPrincipal] ` + [Security.Principal.WindowsIdentity]::GetCurrent() + ).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) +if (-not $isAdmin) { + Write-Warning 'This script needs an elevated PowerShell session. Re-run as Administrator.' + return +} + +Write-Host '== Open Dental: make FreeDentalConfig.xml writable by Users ==' -ForegroundColor Cyan + +# --- Resolve install path across 64-bit / 32-bit Program Files --- +$bases = @(${env:ProgramFiles(x86)}, $env:ProgramFiles) | Where-Object { $_ } +$candidates = $bases | ForEach-Object { Join-Path $_ 'Open Dental\FreeDentalConfig.xml' } +$configPath = $candidates | Where-Object { Test-Path $_ } | Select-Object -First 1 +if (-not $configPath) { + Write-Warning "FreeDentalConfig.xml not found. Checked:`n $($candidates -join "`n ")" + Write-Warning 'If Open Dental is installed elsewhere, grant Users Modify on that copy manually.' + return +} + +Write-Host "Found: $configPath" -ForegroundColor Green +Write-Host 'About to grant the built-in Users group (S-1-5-32-545) Modify on this file.' -ForegroundColor Yellow +if ((Read-Host 'Proceed? (y/N)') -ne 'y') { + Write-Host 'Aborted. No changes made.' + return +} + +# --- Grant Modify to Users via well-known SID (not the localized name "Users") --- +icacls "$configPath" /grant '*S-1-5-32-545:M' +if ($LASTEXITCODE -ne 0) { + Write-Warning "icacls returned exit code $LASTEXITCODE — permission not changed." + return +} +Write-Host 'Done. Relaunch Open Dental as the standard user to confirm the window is gone.' -ForegroundColor Green