Add password system analysis document

This commit is contained in:
accusys
2026-03-29 00:54:38 +08:00
parent c74f5a7001
commit 482be9db5f
+256
View File
@@ -0,0 +1,256 @@
# 密碼系統分析
## 概述
RAIDGuard X 使用密碼系統來控制對 RAID 控制器的訪問權限。以下是密碼相關的功能:
## 密碼類型
| 密碼類型 | 說明 | 預設值 |
|-----------|------|--------|
| 控制器密碼 | 連線到控制器時驗證 | `00000000` |
| 進階功能密碼 | 用於進階功能 (如 Update Firmware) | `WANGWANG``=AU4@A83` |
## 密碼驗證流程
### 1. 密碼檢查 (PwdCheck)
```
使用者操作進階功能
→ PwdCheck(loc)
→ 檢查 sPwd[SN] 是否為空
→ 若為空,彈出密碼輸入對話框 (dlgPasswordCheck)
→ 驗證密碼正確性
→ 成功後才允許執行
```
### 2. 密碼輸入對話框 (dlgPasswordCheck)
```java
// dlgPasswordCheck.java
public void jbOk_actionPerformed() {
// 取得使用者輸入的密碼 (8 字元)
String inputPwd = jpPwd.getSelectedText();
// 儲存到 PageDataDB.sPwd[]
PageDataDB.sPwd[SNToNo(sSN)] = inputPwd + " ";
// 發送密碼到控制器驗證
// OpCode: 0x1D
// SubOp: 0x08
// 密碼: raw char values (無轉換)
bCmds[3] = 0x1D; // OpCode
bCmds[4] = 0x08; // Length
bCmds[5-12] = password bytes (charAt(i))
}
```
## 密碼發送機制
### OpCode: 0x1D - SEND_PASSWORD
**CDB 結構:**
| Offset | 值 | 說明 |
|--------|-----|------|
| 0 | 0x00 | Phase Code |
| 1 | 0x00 | Request Code |
| 2 | 0x00 | Controller No |
| 3 | 0x1D | OpCode - SEND_PASSWORD |
| 4 | 0x08 | Length (8 bytes) |
| 5-12 | password | 8 bytes password |
### 密碼位元組轉換
**有兩種不同的轉換方式:**
#### 方式 1: dlgPasswordCheck (直接發送)
```java
// 密碼直接作為 char 發送
bCmds[5] = (byte) password.charAt(0);
bCmds[6] = (byte) password.charAt(1);
// ...
```
#### 方式 2: SendCmd.sendPassword (減法轉換)
```java
// 密碼字元減去 0x30
pwdBytes[i] = (byte) (password.charAt(i) - 0x30);
// Example:
// '0' (0x30) → 0x00
// '1' (0x31) → 0x01
// '9' (0x39) → 0x09
// 'A' (0x41) → 0x11
```
## 密碼儲存
### PageDataDB.sPwd[]
```java
// 全域密碼儲存陣列
public static String sPwd[] = new String[iMaxHosts];
// 根據序號查詢密碼索引
public static int SNToNo(String sSN) {
// 查詢 sSNToNo[][] 對應表
// 回傳該 SN 的密碼陣列索引
}
// 儲存密碼
PageDataDB.sPwd[SNToNo(sSN)] = "00000000";
```
### 密碼對應表
```
sSNToNo[i][0] = 控制器序號 (String)
sSNToNo[i][1] = 密碼索引 (String "0"-"15")
```
## 預設密碼
### 預設控制器密碼
```
預設值: "00000000" (8 個零)
```
### 進階功能密碼
`PageDataDB.GetPlayMenu()` 中檢查:
```java
if (sPwd[SNToNo(sSN)].trim().equals("=AU4@A83") ||
sPwd[SNToNo(sSN)].trim().equals("WANGWANG")) {
// 啟用進階功能 (Play Menu)
}
```
| 密碼 | 用途 |
|------|------|
| `00000000` | 預設控制器連線密碼 |
| `WANGWANG` | 啟用 Play Menu 進階功能 |
| `=AU4@A83` | 啟用 Play Menu 進階功能 (另一組) |
## 需要密碼的功能
以下功能需要密碼驗證:
| 功能 | 密碼類型 |
|------|----------|
| Update System Code (Firmware) | 控制器密碼 |
| Update Boot Code | 控制器密碼 |
| Update BIOS/EFI | 控制器密碼 |
| Update Expander Code | 控制器密碼 |
| Dump Controller Log | 控制器密碼 |
| Shutdown Controller | 控制器密碼 |
| Play Menu | 進階密碼 (`WANGWANG``=AU4@A83`) |
## 密碼對話框
### dlgPasswordCheck
```
┌────────────────────────────────────────┐
│ Password Check │
│ │
│ [________________] │
│ (Default Password: 00000000) │
│ │
│ [OK] [Cancel] │
└────────────────────────────────────────┘
```
### 密碼欄位設定
```java
// 固定長度 8 字元
jpPwd.setDocument(new FixedSizePlainDocument(8));
jpPwd.setSelectionEnd(8);
// 密碼可視 (不遮蔽)
// jpPwd.setEchoChar('*');
```
## Code Flow
### 密碼驗證流程
```
1. 使用者點擊功能 (如 Update Firmware)
2. frmMain.jmXXX_actionPerformed()
3. PageDataDB.PwdCheck(loc)
4.
a. 若 sPwd[SN] 已有密碼 → 自動使用
b. 若 sPwd[SN] 為空 → 彈出 dlgPasswordCheck
5.
a. 驗證成功 → bPwdCheckPass = true → 執行功能
b. 驗證失敗 → bPwdCheckPass = false → 拒絕執行
```
### 密碼發送流程
```
1. dlgPasswordCheck.jbOk_actionPerformed()
2. 取得輸入密碼 → 儲存到 sPwd[SN]
3. 建立 CmdQueue 命令
4.
a. dlgPasswordCheck: 使用 raw char (無轉換)
b. SendCmd.sendPassword: 使用 char - 0x30 轉換
5. 發送到控制器 (OpCode 0x1D)
6. 等待回應
7. 驗證成功 → 刷新頁面資料
```
## 關鍵類
| 類別 | 檔案 | 功能 |
|------|------|------|
| `PageDataDB` | PageDataDB.java | 密碼儲存與驗證 |
| `dlgPasswordCheck` | dlgPasswordCheck.java | 密碼輸入對話框 |
| `SendCmd` | InBandAPI/SendCmd.java | 密碼發送通訊 |
## 參考程式碼
### SendCmd.sendPassword()
```java
public void sendPassword(String sIP, String sSN) {
// 取得密碼
String rawPwdStr = PageDataDB.sPwd[SNToNo(sSN)];
// 密碼轉換: char - 0x30
byte[] pwdBytes = new byte[8];
for (int i = 0; i < 8; i++) {
pwdBytes[i] = (byte) (rawPwdStr.charAt(i) - 0x30);
}
// 發送
// OpCode: 0x1D
// Length: 0x08
// Data: pwdBytes[0..7]
this.send(sIP, sSN, (byte) 0x1D, (byte) 0x08,
pwdBytes[0], pwdBytes[1], pwdBytes[2], pwdBytes[3],
pwdBytes[4], pwdBytes[5], pwdBytes[6], pwdBytes[7]);
}
```
### PageDataDB.PwdCheck()
```java
public static int PwdCheck(Point loc) {
if (sSN.trim().equals("")) {
return 0x00; // 無控制器
}
if (sPwd[SNToNo(sSN)].equals("")) {
// 彈出密碼輸入對話框
dlgPasswordCheck dlgPwdCheck = new dlgPasswordCheck();
dlgPwdCheck.setVisible(true);
if (dlgPwdCheck.bPwdCheckPass == false) {
return 0x00; // 驗證失敗
}
}
return 0x01; // 驗證成功
}
```