Add password system analysis document
This commit is contained in:
@@ -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; // 驗證成功
|
||||||
|
}
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user