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