OSSECソースコードリーディング

# はじめに
OSSECのソースコードリーディングを始めました。この記事では、ざっくりとした処理フローをテキストエディタで作成しています。なお、概要として、[OSSECの各デーモンのソースコードリーディング](https://qiita.com/Diavolo/items/6e6b39c655ff91641890)を記事にしていますので、興味のある方は、[こちらの記事](https://qiita.com/Diavolo/items/6e6b39c655ff91641890)もご参照ください。

[OSSECの各デーモンのソースコードリーディング](https://qiita.com/Diavolo/items/6e6b39c655ff91641890)

## analysisd
#### main()
```/ossec-hids-master/src/analysisd/analysisd.c
main()
|--- OS_SetName() プログラム名をセットする
|--- getopt() 起動オプションによる処理実行
|--- getDefine_Int() デバッグレベル取得
|--- Privsep_GetUser() 指定されたユーザーが有効かどうかを確認する
|--- Privsep_GetGroup() 指定されたグループが有効かどうかを確認する
|--- AR_Init() アクティブレスポンスを初期化する
|--- AR_ReadConfig() コンフィグファイルを読み込む
|--- Privsep_SetGroup() グループをセットする
|--- Privsep_Chroot() ルートディレクトリをセットする
|--- nowChroot()
|--- OS_CreateOSDecoderList() デコードリストを初期化する
|--- ReadDecodeXML() デコードを読み込む
|--- SetDecodeXML() デコードをセットする
|    リスト検索を必要とするすべてのルールを見つけ、そのルールをアタッチします。
|    正しいリスト構造体をルールに追加します。これにより、ルールが正しいファイルを探すために、リストのリストを検索します。
|    ルールの評価を行います。
|--- Lists_OP_CreateLists() リストを初期化する
|--- Lists_OP_LoadList() リストをロードする
|--- Rules_OP_CreateRules() ルールリストを作成する
|--- Rules_OP_ReadRules() ルールを読み込む
|--- OS_ListLoadRules() ルールをロードする
|    レベル/精度を修正します。
|--- OS_GetFirstRule() 一個目のルールを取得します。
|--- _setlevels() レベルをセットします。
|    ルールハッシュの作成（他のサーバーからのアラート読み込み用）
|--- OS_GetFirstRule()
|--- OSHash_Create()
|--- StartSIG() シグナルを操作します
|--- Privsep_SetUser() ユーザーを設定します
|--- CreatePID() PIDファイルを作成します
|--- StartMQ() キューをセットします
|--- OS_ReadMSG() メインループ処理を実行します。
END
```
#### OS_ReadMSG()
メイン処理です。メッセージ(イベント)を受信し、それらをすべて分析します。
```/ossec-hids-master/src/analysisd/analysisd.c
OS_ReadMSG()
|--- OS_InitLog()
|--- SyscheckInit()
|--- RootcheckInit()
|--- HostinfoInit()
|--- OS_CreateEventList()
|--- FTS_Init()
|--- Accumulate_Init()
|--- StartMQ(ARQUEUE, WRITE) アクティブレスポンスキューを開始する ← リモートでアクティブレスポンスを受ける(Serverインストールの場合)
|--- StartMQ(EXECQUEUE, WRITE) 実行キューを開始する 
|--- 1時間ごと/1週間ごとの統計データを開始する
|--- ログを初期化する
|--- sqlite3_open() SQLITE DBをオープンする（SQLITEが有効な場合）
ここまで、analysisdのスタートアップが完了です
|--- while(1) デーモンの無限ループ
|      |--- OS_RecvUnix(m_queue, OS_MAXSTR, msg) キューからメッセージを受信する
|      |--- イベント受信回数をインクリメント
|      |--- デコーダーの実行
|      |--- msg[0]にて、イベント種別を判断している SYSCHECK_MQ/ROOTCHECK_MQ/HOSTINFO_MQ/OTHER
|      |      |--- DecodeSyscheck() 
|      |      |--- DecodeRootcheck()
|      |      |--- DecodeHostinfo()
|      |      |--- DecodeEvent()
|      |--- Accumulate() アキュームレーター実行
|      |    lf->decoder_info->typeでイベント種別を判断している
|      |--- ファイアウォールイベントの場合、firewall回数インクリメント、FW_Log()
|      |--- SYSLOGイベントの場合、メッセージ重複のチェック処理を実行
|      |--- 統計情報のチェック処理
|      |--- ルールのチェック処理
|      |    OS_GetFirstRule() で一個目のルールをポインタにセットして、全ルールをループしてチェックしている
|      |    rulenode_pt->ruleinfo->categoryとlf->decoder_info->typeを比較（ルールのカテゴリ比較）
|      |    OS_CheckIfRuleMatch() ルールにマッチしているかを比較する。 ※ルールマッチング処理【重要】
|      |    currently_rule->ignore_time ルールマッチングを無視するタイムをチェック ※指定時間内のルールマッチ回数の処理実現【重要】
|      |--- currently_rule->alert_opts & DO_LOGALERT でログアラート有効の場合、ログファイルにアラート書き込み
|      |--- JSONアウトプット有効の場合、jsonout_output_event()
|      |--- アクティブレスポンス有効（currently_rule->ar）の場合、OS_Exec()
|      |--- if_matched_sid のステートメモリに構造体をコピーする　OSList_AddData()
|      |--- OSList_AddData() グループマッチ情報（currently_rule->group_prev_matched）をセットする
|    while ((rulenode_pt = rulenode_pt->next) != NULL) ※最終ルールに到達するまで、最初に戻ってループしている
|--- Free_Eventinfo(lf)
|--- free(lf)
END
```
#### OS_CheckIfRuleMatch()
current_rule がイベント情報と一致するかどうかを確認する。
【チェック項目】
- decoded_as
- fts
- word match (fast regex)
- regex
- url
- id
- user
- maxsize
- protocol
- srcip
- dstip
- srcport
- stport
- time
- weekday
- status

# おわりに
地道に記事を更新していきます。では、また。