Skip to content

Commit 1658131

Browse files
committed
fix: pre-initialize mTLS flag from cert SAN/CN to handle TLS session resumption in Wear OS onboarding
When setting up a Wear OS device the mTLS certificate-selection screen was silently skipped if TLS session resumption occurred, causing the watch to register without a client certificate and the server to return HTTP 400. Root cause: isTLSClientAuthNeeded in TLSWebViewClient is only set inside onReceivedClientCertRequest. When the onboarding WebView reuses the main app's existing TLS session (abbreviated handshake), the server never issues a new CertificateRequest so the callback never fires — even with ssl_session_tickets disabled on the server, because Android's Chromium network stack maintains its own in-process TLS session cache. Fix: add TLSWebViewClient.preInitializeTLSClientAuthState(targetHost) which inspects the in-memory certificate chain (if any) and checks whether it covers targetHost by matching the server hostname against the certificate's Subject Alternative Names (SANs) — both DNS names with wildcard support (RFC 2818 §3.1) and IP addresses — falling back to the Common Name (CN) for legacy certificates without SANs. Matching against the certificate rather than mere private-key presence eliminates the false positive raised in review: a user with multiple servers where only Server A requires mTLS will no longer see the cert- selection screen when onboarding a watch for Server B, because the loaded certificate will not match Server B's hostname. ConnectionViewModel.init extracts the hostname from rawUrl and passes it to preInitializeTLSClientAuthState() before emitting the auth URL so the navigation layer sees the correct value. Also updates ConnectionViewModelTest: the two existing private-key- presence tests are replaced with five cert-host matching tests covering exact DNS SANs, wildcard DNS SANs, a cert for a different host, no certificate chain present, and CN-only fallback. Made-with: Cursor
0 parents  commit 1658131

1,867 files changed

Lines changed: 182648 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.editorconfig

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
indent_size = 4
6+
indent_style = space
7+
insert_final_newline = true
8+
end_of_line = lf
9+
trim_trailing_whitespace = true
10+
11+
[*.{yml,yaml}]
12+
indent_size = 2
13+
ij_yaml_spaces_within_braces = false
14+
ij_yaml_spaces_within_brackets = false
15+
16+
[*.{kt,kts}]
17+
ktlint_code_style = android_studio
18+
# Disable wildcard imports
19+
ij_kotlin_name_count_to_use_star_import = 9999
20+
ij_kotlin_name_count_to_use_star_import_for_members = 9999
21+
# ktlint overrides
22+
ktlint_function_naming_ignore_when_annotated_with=Composable
23+
ij_kotlin_allow_trailing_comma_on_call_site = true
24+
ij_kotlin_allow_trailing_comma = true
25+
# Disable converting functions to expression bodies
26+
ktlint_standard_function-expression-body = disabled
27+
max_line_length = 120
28+
29+
[**/test/**.kt]
30+
max_line_length = off

.git-blame-ignore-revs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Enforce trailing comma
2+
93871a5e078ffaf6d7809e298592703f89e78530
3+
4+
# Update dependency org.jlleitschuh.gradle.ktlint to v13 (max line length 120)
5+
a2eb66ee40bf1d8e4b0624502d1e2668bd7cc447
6+
7+
# Replace android.util.Log with timber.log.Timber
8+
5c6c6e149fea2c2e406d4d7a53434ff932c40c56

.gitattributes

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Set default behavior to automatically normalize line endings
2+
* text=auto
3+
4+
# Explicitly declare text files you want to always be normalized and converted to native line endings on checkout.
5+
*.kt text
6+
*.kts text
7+
*.xml text
8+
*.gradle text
9+
*.md text
10+
*.json text
11+
*.yml text
12+
*.yaml text
13+
*.toml text
14+
*.properties text
15+
*.pro text
16+
*.txt text
17+
*.bash text eol=lf
18+
*.css text diff=css
19+
*.sh text eol=lf
20+
21+
# Declare binary files to be preserved as-is
22+
*.png binary
23+
*.jpg binary
24+
*.jar binary
25+
26+
# Custom merge driver for Gradle lock files
27+
gradle.lockfile merge=union
28+
29+
# Ensure shell scripts have UNIX line endings
30+
*.sh text eol=lf
31+
32+
# Ensure Windows batch files have CRLF line endings
33+
*.bat text eol=crlf
34+
35+
# Handle Android Studio specific files
36+
*.iml text
37+
*.idea/** text
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
name: Bug report
3+
about: Create a report to help us improve
4+
title: ''
5+
labels: bug
6+
assignees: ''
7+
8+
---
9+
10+
<!-- READ THIS FIRST:
11+
- Make sure you run the latest version of the Android app
12+
- Make sure you run the latest version of Home Assistant
13+
- Make sure to check the Companion docs for troubleshooting and configuration: https://companion.home-assistant.io/
14+
- Make sure the bug you found is not already reported, we love to put work in bugfixes instead of closing duplicate bug reports
15+
DO NOT DELETE ANY TEXT from this template! All requested information is important.
16+
-->
17+
18+
<!-- If you are reporting an issue for Wear OS please list both devices for the below 3 fields -->
19+
**Home Assistant Android app version(s):**
20+
21+
**Android version(s):**
22+
23+
**Device model(s):**
24+
25+
**Home Assistant version:**
26+
27+
**Last working Home Assistant release (if known):**
28+
29+
**Description of problem, include YAML if issue is related to notifications:**
30+
31+
<!--
32+
- For Wear OS devices we will need the LogCat logs from the device.
33+
- For Android Auto the logs can be retrieved from the connected device.
34+
- Logs from the device can be taken from Settings > Companion App Troubleshooting > Show and Share Logs
35+
-->
36+
**Companion App Logs:**
37+
38+
```
39+
40+
```
41+
42+
**Screenshot or video of problem:**
43+
44+
**Additional information:**

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
blank_issues_enabled: false
2+
contact_links:
3+
- name: Issue or suggestion for the app documentation
4+
url: https://github.com/home-assistant/companion.home-assistant/issues
5+
about: Please report any errors, missing information, or suggestions for the companion app documentation here.
6+
- name: Issue or suggestion for the developer documentation
7+
url: https://github.com/home-assistant/developers.home-assistant/issues
8+
about: Please report any errors, missing information, or suggestions for the developer documentation here.
9+
- name: Request a feature for the Android application
10+
url: https://github.com/orgs/home-assistant/discussions/new?category=android
11+
about: Request a new feature for the Android application.
12+
- name: Problem with your dashboard
13+
url: https://github.com/home-assistant/frontend/issues
14+
about: Most of the app's interface is provided by the Home Assistant frontend (WebView). Please report dashboard issues here.
15+
- name: I have a question or need support
16+
url: https://www.home-assistant.io/help
17+
about: GitHub is for tracking bugs and feature requests. For help and support, please visit our help page.
18+
- name: I'm not sure where to go
19+
url: https://www.home-assistant.io/join-chat
20+
about: If you're unsure where to report your issue or ask your question, join our chat and we'll help

.github/ISSUE_TEMPLATE/task.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: Task
2+
description: For staff only - Create a task
3+
type: Task
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
## ⚠️ RESTRICTED ACCESS
9+
10+
**This form is restricted to Open Home Foundation staff and authorized contributors only.**
11+
12+
If you are a community member wanting to contribute, please:
13+
- For bug reports: Use the [bug report form](https://github.com/home-assistant/android/issues/new?template=Bug_report.md)
14+
- For feature requests: Submit to [Feature Requests](https://github.com/orgs/home-assistant/discussions)
15+
16+
---
17+
18+
### For authorized contributors
19+
20+
Use this form to create tasks for development work, improvements, or other actionable items that need to be tracked.
21+
- type: textarea
22+
id: description
23+
attributes:
24+
label: Description
25+
description: |
26+
Provide a clear and detailed description of the task that needs to be accomplished.
27+
28+
Be specific about what needs to be done, why it's important, and any constraints or requirements.
29+
placeholder: |
30+
Describe the task, including:
31+
- What needs to be done
32+
- Why this task is needed
33+
- Expected outcome
34+
- Any constraints or requirements
35+
validations:
36+
required: true
37+
- type: textarea
38+
id: additional_context
39+
attributes:
40+
label: Additional context
41+
description: |
42+
Any additional information, links, research, or context that would be helpful.
43+
44+
Include links to related issues, research, prototypes, roadmap opportunities etc.
45+
placeholder: |
46+
- Roadmap opportunity: [link]
47+
- Epic: [link]
48+
- Feature request: [link]
49+
- Technical design documents: [link]
50+
- Prototype/mockup: [link]
51+
- Dependencies: [links]
52+
validations:
53+
required: false
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: "Create Release Notes"
2+
description: "Creates the current releases release notes"
3+
inputs:
4+
tag-name:
5+
description: "Name of the tag that will be used for this release"
6+
required: true
7+
gh-token:
8+
description: "The GitHub token used to get details from the API"
9+
required: true
10+
runs:
11+
using: "composite"
12+
steps:
13+
- name: Get Previous Release Tag
14+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
15+
id: latest-release-tag
16+
with:
17+
github-token: ${{ inputs.gh-token }}
18+
result-encoding: string
19+
script: |
20+
const { data } = await github.rest.repos.getLatestRelease({
21+
owner: context.repo.owner,
22+
repo: context.repo.repo,
23+
})
24+
return data.tag_name
25+
- name: Get Generated Release Notes
26+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
27+
id: generate-notes
28+
env:
29+
TAG_NAME: ${{ inputs.tag-name }}
30+
PREVIOUS_TAG: ${{ steps.latest-release-tag.outputs.result }}
31+
with:
32+
github-token: ${{ inputs.gh-token }}
33+
result-encoding: string
34+
script: |
35+
const { data } = await github.rest.repos.generateReleaseNotes({
36+
owner: context.repo.owner,
37+
repo: context.repo.repo,
38+
tag_name: process.env.TAG_NAME,
39+
target_commitish: 'main',
40+
previous_tag_name: process.env.PREVIOUS_TAG,
41+
})
42+
return data.body.replaceAll('`', '\'').replaceAll('"', '\'')
43+
- name: Generate Release Notes
44+
id: version-generator
45+
shell: bash
46+
env:
47+
PREVIOUS_TAG: ${{ steps.latest-release-tag.outputs.result }}
48+
CHANGELOG: ${{ steps.generate-notes.outputs.result }}
49+
run: |
50+
mkdir -p ./app/build/outputs/
51+
52+
echo "Previous Release Tag:"
53+
echo "$PREVIOUS_TAG"
54+
55+
echo "Full Changelog:"
56+
echo -e "$CHANGELOG"
57+
printf "%s" "$CHANGELOG" > ./app/build/outputs/changelogGithub
58+
59+
echo "Beta Changelog:"
60+
git log --format="* %s" HEAD^..HEAD
61+
git log --format="* %s" HEAD^..HEAD > ./app/build/outputs/changelogBeta
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: "Create Release Numbers"
2+
description: "Creates the current release number based on checked out code"
3+
outputs:
4+
version-code:
5+
description: "The numeric app version"
6+
value: ${{ steps.version-generator.outputs.version-code }}
7+
version:
8+
description: "The app version"
9+
value: ${{ steps.version-generator.outputs.version }}
10+
runs:
11+
using: "composite"
12+
steps:
13+
- name: Set Build Number
14+
id: version-generator
15+
shell: bash
16+
run: |
17+
./gradlew versionFile
18+
COMMITS=`git rev-list --count HEAD`
19+
TAGS=`git tag | grep -v beta | wc -l`
20+
VC=$((((COMMITS+TAGS) * 3) << 1))
21+
echo Number Commits $COMMITS
22+
echo Number Tags $TAGS
23+
echo Version Code $VC
24+
echo "version-code=$VC" >> $GITHUB_OUTPUT
25+
VERSION=`cat version.txt`
26+
echo Version $VERSION
27+
echo "version=$VERSION" >> $GITHUB_OUTPUT
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: "Download Translations"
2+
description: "Reaches out to Lokalise to download the latest translations."
3+
inputs:
4+
lokalise-project:
5+
description: "The project id in lokalise"
6+
required: true
7+
lokalise-token:
8+
description: "An API token that has read access to the desired project"
9+
required: true
10+
runs:
11+
using: "composite"
12+
steps:
13+
- name: Get Translations
14+
id: translations
15+
shell: bash
16+
env:
17+
LOKALISE_PROJECT: ${{ inputs.lokalise-project }}
18+
LOKALISE_TOKEN: ${{ inputs.lokalise-token }}
19+
run: |
20+
ZIP=`\
21+
curl --location --request POST "https://api.lokalise.com/api2/projects/${LOKALISE_PROJECT}/files/download" \
22+
--header "X-Api-Token: ${LOKALISE_TOKEN}" \
23+
--header 'Content-Type: application/json' \
24+
--data-raw '{
25+
"format": "xml",
26+
"original_filenames": false,
27+
"bundle_structure": "common/src/main/res/values-%LANG_ISO%/strings.%FORMAT%",
28+
"add_newline_eof": true,
29+
"replace_breaks": true,
30+
"export_empty_as": "skip"
31+
}' \
32+
| jq -r '.bundle_url' \
33+
`
34+
35+
echo "Download Ready: $ZIP"
36+
37+
curl "$ZIP" --output strings.zip
38+
39+
echo "Download Complete, unzipping"
40+
unzip -n strings.zip
41+
echo "Unzipped strings, generating locales_config.xml"
42+
43+
XML_START='<?xml version="1.0" encoding="utf-8"?>\n<locale-config xmlns:android="http://schemas.android.com/apk/res/android">\n'
44+
XML_LOCALES=''
45+
XML_END='</locale-config>'
46+
for i in common/src/main/res/values*/strings.xml; do
47+
FOLDER="$(basename $(dirname $i))"
48+
CODE="${FOLDER#*-}" # remove "values-"
49+
CODE="${CODE/-r/-}" # replace region "-rXX" with "-XX"
50+
if [ "$CODE" == "values" ]; then CODE="en"; fi
51+
XML_LOCALES="$XML_LOCALES <locale android:name=\"$CODE\"/>\n"
52+
done
53+
printf "$XML_START$XML_LOCALES$XML_END" > app/src/main/res/xml/locales_config.xml
54+
printf "$XML_START$XML_LOCALES$XML_END" > wear/src/main/res/xml/locales_config.xml
55+
56+
echo "Complete"

0 commit comments

Comments
 (0)