# 課題 作業メモ
## 課題3
今回は難しそうで放置してしまっていたのですが、できるところまではやってみようと思います
- brew install jq
- OpenTitechAppでwsTokenを取得
### 課題3.1
[[macOS][iOS] パケットトレースツール「Charles」を使用してiOSデバイスの生の送受信データを確認する](https://dev.classmethod.jp/articles/getting-packet-trace-with-charles/)
- Port: 8888
- Local IP Address:
- en0: `192.168.1.10`
- en1: `192.168.1.6`
- en1で 
色々動かして出たログを export session → JSON session File (.chlsj)に保存してみたけど...


見えない Decodeができない

これはHTTPS通信の暗号化によるものだった
さっきの[記事](https://dev.classmethod.jp/articles/getting-packet-trace-with-charles/)の「SSL通信の中身を見たい場合は、Charlesの証明書をインストールします。」の部分を飛ばしたのが原因
証明書をインストールしてから諸々の作業をすると

出てくるようになった
iPhoneで動かしたのは
- T2SCHOLAアプリを開く
- 講義資料を見に行く 有機高分子化学→6/17 2回目→"有機高分子化学2 資料"(PDF)
- 自分のプロファイルを見に行く
| アプリ開いた|講義資料みた|
|:---:|:---:|
|||
ということで、MoodleのUserIDを取得しているのは /webservice/rest/server.php の `core_webservice_get_site_info`
講義資料などを取得しているのは同じく/webservice/rest/server.php の `core_course_get_contents`
### 課題3.2
通信の通りにcURLしてみる
```
-d "moodlewssettingfilter=true&moodlewssettingfileurl=true&wsfunction=core_webservice_get_site_info&wstoken=..."
"https://t2schola.titech.ac.jp/webservice/rest/server.php?moodlewsrestformat=json&wsfunction=core_webservice_get_site_info"
```
とJSONで色々帰ってきた パイプでjqに渡すと

良い感じ
まとめると
```shell=
ID=$(
curl -s -X POST -d "wsfunction=core_webservice_get_site_info" \
-d "wstoken=63a2d4cc280d4fc7542e5d906021dcbc" \
-d "moodlewsrestformat=json" \
"https://t2schola.titech.ac.jp/webservice/rest/server.php" \
| jq '.userid'
)
echo "UserID: "$ID
```
### 課題3.3
https://docs.moodle.org/dev/Web_service_API_functions から探す
assignment で検索をかけると`mod_assign_get_assignments`が出てきた
とりあえず`wsfunction`をこれに書き換えて実行させてみると...

それっぽい
`courses`内の各講義の`assignments`の`name`を持ってくれば良さそうなので
```| jq '.courses[].assignments[].name'```
で良い感じ
まとめると
```shell=
curl -s -X POST -d "wsfunction=mod_assign_get_assignments" \
-d "wstoken=63a2d4cc280d4fc7542e5d906021dcbc" \
-d "moodlewsrestformat=json" \
"https://t2schola.titech.ac.jp/webservice/rest/server.php" \
| jq '.courses[].assignments[].name'
```
で

---
## 課題2
https://hackmd.io/@nanashiki/rJFjsqPKY
保存したファイルの中から
```htmlmixed=
<tr>
<th align="left" bgcolor="#6699CC"></th>
<th bgcolor="#6699CC"></th>
<td bgcolor="#6699CC">
<div class="col-sm-7 control-align">115777</div>
</td>
</tr>
<tr>
<th align="left" bgcolor="#6699CC">[A,7]</th>
<th bgcolor="#6699CC"></th>
<td bgcolor="#6699CC">
<div class="col-sm-7"><div class="inner-addon left-addon"> <i class="glyphicon glyphicon-lock"></i> <INPUT TYPE="password" NAME="message3" VALUE="" SIZE="32" MAXLENGTH="200" class="form-control" ng-model="password" placeholder="Password" ></div></div>
</td>
</tr>
<tr>
<th align="left" bgcolor="#6699CC">[B,3]</th>
<th bgcolor="#6699CC"></th>
<td bgcolor="#6699CC">
<div class="col-sm-7"><div class="inner-addon left-addon"> <i class="glyphicon glyphicon-lock"></i> <INPUT TYPE="password" NAME="message4" VALUE="" SIZE="32" MAXLENGTH="200" class="form-control" ng-model="password" placeholder="Password" ></div></div>
</td>
</tr>
<tr>
<th align="left" bgcolor="#6699CC">[I,1]</th>
<th bgcolor="#6699CC"></th>
<td bgcolor="#6699CC">
<div class="col-sm-7"><div class="inner-addon left-addon"> <i class="glyphicon glyphicon-lock"></i> <INPUT TYPE="password" NAME="message5" VALUE="" SIZE="32" MAXLENGTH="200" class="form-control" ng-model="password" placeholder="Password" ></div></div>
</td>
</tr>
```
で正規表現を使って[A,7]、[B,3]、[I,1]を抽出するのが目標。正規表現自体はGASのエゴサで書いたことがあった。[正規表現チートシート](https://murashun.jp/article/programming/regular-expression.html)や[チェッカー](https://weblabo.oscasierra.net/tools/regex/)を見ながら書くと
`\[[A-J],[1-7]\]`
あっさり書けた。あとはファイルを指定して検索する方法。
- `grep`で正規表現が書けそう:`grep -e '\[[A-J],[1-7]\]' $FILEPATH`
- これだけだと行そのまま抽出:
```html
<th align="left" bgcolor="#6699CC">[A,7]</th>
<th align="left" bgcolor="#6699CC">[B,3]</th>
<th align="left" bgcolor="#6699CC">[I,1]</th>
```
なので`awk`を使えば良さそう。`|`で渡した後は`,`で区切り$1の末尾と$2の先頭があれば良いので[調べて](https://atmarkit.itmedia.co.jp/ait/articles/1805/25/news035.html)(出力の区切り文字も変えて)\
`grep -e '\[[A-J],[1-7]\]' $FILEPATH | awk -F'[,]' -v 'OFS=' '{print substr($1, length($1)),substr($2, 1, 1)}'`
とすると望みのものが得られた。
## 課題2の回答
以上の話から、次の2行で現在のマトリクスが出力できる。
```shell=
read FILEPATH
grep -e '\[[A-J],[1-7]\]' $FILEPATH | awk -F'[,]' -v 'OFS=' '{print substr($1, length($1)),substr($2, 1, 1)}'
```
---
## 課題1
https://hackmd.io/@nanashiki/rJ3S10qPY
curlの前提知識:TwitterのAPIの[仕様が書かれたページ](https://developer.twitter.com/en/docs/twitter-api/tweets/search/api-reference/get-tweets-search-recent)で見たことある
試しに`curl "https://api.twitter.com/2/tweets/search/recent?query=from%3Aco_planar" -H "Authorization: Bearer [ここにToken]"`と打つといつも見てるレスポンスが帰ってきた
[Qiitaの記事](https://qiita.com/takayukioda/items/edf371b3566bea64d046)を読んだ。-H は HTTP の Request Header への情報の追加だった
---
ここまでで課題1が分かった。
`curl "https://portal.nap.gsic.titech.ac.jp/GetAccess/Login?Template=userpass_key&AUTHMETHOD=UserPassword"`
でポータルの最初のログインページが帰ってきた。
`curl -o portal.html "https://...` とオプションを残してページを保存した
---
`portal.html`の中でformタグを探すと...
`<FORM NAME="login" METHOD="POST" AUTOCOMPLETE="off" ACTION="https://portal.nap.gsic.titech.ac.jp/GetAccess/Login" onSubmit="javascript:{ return idgisSetRedirectionCookie( this ); }">`
学籍番号やパスワードを打つ部分は
`<INPUT TYPE="text" NAME="usr_name" VALUE="" SIZE="32" MAXLENGTH="255" class="form-control" ng-model="username" placeholder="Account" >`
`<INPUT TYPE="password" NAME="usr_password" VALUE="" SIZE="32" MAXLENGTH="32" class="form-control" ng-model="password" placeholder="Password" >`
HTMLのformの挙動は以前TweetDeckもどきを作った時に見た
ヒントを1つずつ見ていくことにする
HTMLのフォームの挙動は前にも見たことがある、今回のも開発者画面で見ると色々飛んでた
- Request URL: https://portal.nap.gsic.titech.ac.jp/GetAccess/Login
- Request Method: POST
- Status Code: 302 Found
- ...
- usr_name: ***
- usr_password: ***
- CSRFFormToken: ***
最後のCSRF(対策)Tokenについて調べると
- フォーム送信前にワンタイムトークンを生成
- フォーム送信ページにhiddenで生成したトークンを埋め込む
- リクエスト送信先でセッションに格納されたトークンとリクエストとして送られてきたトークンが一致するか確認
だそう
`portal.html`をよく見るとformタグ内の最後の方に`<input type='hidden' name=...>`がたくさんある、最後に`CSRFFormToken`もあるのでこれを使えば良さそう
Cookieの中身が知りたいので`curl -c cookie.txt -o portal.html "https://...` とオプション付けてみると
```
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_portal.nap.gsic.titech.ac.jp FALSE /GetAccess TRUE 0 JSESSIONID ******
```
この`JSESSIONID`は使う必要がありそう
最後にredirectについて。Status Codeが`302 Found`で転送先がlocationにあるらしい。さっきの開発者画面のもので見ると`Location: https://portal.nap.gsic.titech.ac.jp/webap/rt?refurl=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList`に飛んでいるらしい。curlに`-L`を足せば良さそう
---
ここまでを踏まえて課題2。開発者画面で見たものをとりあえず全て入れる。bodyの方は`portal.html`のFORMタグの各inputを網羅する
`curl -X POST -H [Header] -d [data] [URL]`で出来そう
- Header
- Content-Type: application/x-www-form-urlencoded
- Cookie: JSESSIONID=$SESSIONID
- Body
- `"usr_name=$USERNAME&usr_password=$PASSWORD&OK=++++OK++++&AUTHTYPE=&HiddenURI=https%3A%2F%2Fportal.nap.gsic.titech.ac.jp%2FGetAccess%2FResourceList&GARESOURCEID=resourcelistID2&Template=userpass_key&AUTHMETHOD=UserPassword&LOCALE=ja_JP&CSRFFormToken=$TOKEN"`\
開発者画面で見たものそのまま
- pageGenTime だけ消した (入れたらtime limit exceededが出るので)
で
```shell=
read USERNAME
read PASSWORD
read TOKEN
curl -v -L -o response1.html -X POST -b cookie1.txt -d "usr_name=$USERNAME&usr_password=$PASSWORD&OK=++++OK++++&AUTHTYPE=&HiddenURI=https%3A%2F%2Fportal.nap.gsic.titech.ac.jp%2FGetAccess%2FResourceList&GARESOURCEID=resourcelistID2&Template=userpass_key&AUTHMETHOD=UserPassword&LOCALE=ja_JP&CSRFFormToken=$TOKEN" "https://portal.nap.gsic.titech.ac.jp/GetAccess/Login"
```
...
さっきとほぼ同じ(パスワード入力)ページが出た、コードは302でなく200、ページ最上部で
```htmlembedded=
<br>
<center>
<font color=red>ERROR: You can only login from this page.</font>
</center>
<br>
```
と言われてしまった。formタグの場所にちゃんと送ったんだけど
onSubmitの中身の関数も見てみるが分からない(開発者画面の方でもAUTHTYPEは空白のまま)、関数の結果(AUTHTYPEをCertにするなど)を入れても変わらず
---
試したこと
- POST先が違う...? `https://portal.nap.gsic.titech.ac.jp/GetAccess/Login?Template=idg_key&AUTHMETHOD=IG&GASF=CERTIFICATE,IG.GRID,IG.TOKENRO,IG.OTP&LOCALE=ja_JP&GAREASONCODE=13&GAIDENTIFICATIONID=UserPassword&GARESOURCEID=resourcelistID2&GAURI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList&Reason=13&APPID=resourcelistID2&URI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList`に直接
- 確かに302は出る
- < HTTP/1.1 302 Found
- < Date: Sun, 14 Nov 2021 01:02:41 GMT
- < Server: Apache/2.4.37 (Red Hat Enterprise Linux) OpenSSL/1.1.1k
- < Location: https://portal.nap.gsic.titech.ac.jp/GetAccess/Login?GAURI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList&LOCALE=ja_JP&AUTHMETHOD=CERTIFICATE&GARESOURCEID=resourcelistID2&Template=idg_key&pageGenTime=1636851761013&GASF=CERTIFICATE,IG.GRID,IG.TOKENRO,IG.OTP
- ...LibreSSL SSL_read: error:1401E410:SSL routines:CONNECT_CR_FINISHED:sslv3 alert handshake failure, errno 0
- 多分違う
- Chromeの開発者画面を見るに
- https://portal.nap.gsic.titech.ac.jp/GetAccess/Login → 302 Found
- → https://portal.nap.gsic.titech.ac.jp/webap/rt?refurl=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList → 302 Found
- → https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList → 302 Found
- → https://portal.nap.gsic.titech.ac.jp/portal.pl?GASF=CERTIFICATE,IG.GRID,IG.TOKENRO,IG.OTP&LOCALE=ja_JP&GAREASONCODE=13&GAIDENTIFICATIONID=UserPassword&GARESOURCEID=resourcelistID2&GAURI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList&Reason=13&APPID=resourcelistID2&URI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList → 302 Found
- → https://portal.nap.gsic.titech.ac.jp/GetAccess/Login?Template=idg_key&AUTHMETHOD=IG&GASF=CERTIFICATE,IG.GRID,IG.TOKENRO,IG.OTP&LOCALE=ja_JP&GAREASONCODE=13&GAIDENTIFICATIONID=UserPassword&GARESOURCEID=resourcelistID2&GAURI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList&Reason=13&APPID=resourcelistID2&URI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList → 200 OK
- **一向に https://portal.nap.gsic.titech.ac.jp/GetAccess/Login で302 Foundが出ない。**
- ブラウザで打つ時との違い
- Cookieに`AUTH_SESSION_ID`と`STYLEINDEX`が無い でも元々ない
- `pageGenTime`が無い 仕方ないので入力を足す
- 結果は変わらず < HTTP/1.1 200 OK
- -Lは付けてるがそういう問題でなく出ない
- `You can only login from this page.`しか情報がない。わからず
- POSTしてるのはcurl -vから
\> POST /GetAccess/Login HTTP/1.1
\> Host: portal.nap.gsic.titech.ac.jp
\> User-Agent: curl/7.77.0
\> Accept: \*/\*
\> Cookie: JSESSIONID=[ここにID]
\> Content-Length: [ここに長さ]
\> Content-Type: application/x-www-form-urlencoded
\>
\} [\*\* bytes data]
で、ここは想定通り。
- (11/16) 学内でアクセス:変化なし それはそう
---
11/28 試験も終わったので再開
とりあえずSafariが送っているデータを全部入れてみる、User-Agentも変えちゃう(減らすのは後でできる)
```shell=
curl -v -L -o response.html -b cookie1.txt -c cookie1.txt \
-A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15" \
-e "https://portal.nap.gsic.titech.ac.jp/GetAccess/Login?Template=userpass_key&AUTHMETHOD=UserPassword" \
-H "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" \
-H "Accept-Encoding:gzip,deflate,br" \
-H "Accept-Language:ja" \
-H "Connection:keep-alive" \
-H "Origin:https%3A%2F%2Fportal.nap.gsic.titech.ac.jp" \
-d ...
```
すると実行に時間がかかりログも多くなって
```
> POST /GetAccess/Login HTTP/1.1
< HTTP/1.1 302 Found
< Location: https://portal.nap.gsic.titech.ac.jp/webap/rt?refurl=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList
> GET /webap/rt?refurl=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList HTTP/1.1
< HTTP/1.1 302 Found
< Location: https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList
> GET /GetAccess/ResourceList HTTP/1.1
< HTTP/1.1 302 Found
< Location: https://portal.nap.gsic.titech.ac.jp/portal.pl?GASF=CERTIFICATE,IG.GRID,IG.TOKENRO,IG.OTP&LOCALE=ja_JP&GAREASONCODE=13&GAIDENTIFICATIONID=UserPassword&GARESOURCEID=resourcelistID2&GAURI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList&Reason=13&APPID=resourcelistID2&URI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList
> GET /portal.pl?GASF=CERTIFICATE,IG.GRID,IG.TOKENRO,IG.OTP&LOCALE=ja_JP&GAREASONCODE=13&GAIDENTIFICATIONID=UserPassword&GARESOURCEID=resourcelistID2&GAURI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList&Reason=13&APPID=resourcelistID2&URI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList HTTP/1.1
< HTTP/1.1 302 Found
< Location: https://portal.nap.gsic.titech.ac.jp/GetAccess/Login?Template=idg_key&AUTHMETHOD=IG&GASF=CERTIFICATE,IG.GRID,IG.TOKENRO,IG.OTP&LOCALE=ja_JP&GAREASONCODE=13&GAIDENTIFICATIONID=UserPassword&GARESOURCEID=resourcelistID2&GAURI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList&Reason=13&APPID=resourcelistID2&URI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList
> GET /GetAccess/Login?Template=idg_key&AUTHMETHOD=IG&GASF=CERTIFICATE,IG.GRID,IG.TOKENRO,IG.OTP&LOCALE=ja_JP&GAREASONCODE=13&GAIDENTIFICATIONID=UserPassword&GARESOURCEID=resourcelistID2&GAURI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList&Reason=13&APPID=resourcelistID2&URI=https://portal.nap.gsic.titech.ac.jp/GetAccess/ResourceList HTTP/1.1
< HTTP/1.1 200 OK
```
となり、response.htmlにマトリクス認証コードが現れた。随分悩んでたけどなんかできた。ログたくさん出たとき感動した
オプションを減らしていく。
- -A:消せた
- -e "https://portal.nap.gsic.titech.ac.jp/GetAccess/Login?Template=userpass_key&AUTHMETHOD=UserPassword":消したら200 OKすぐ帰ってきた。Refererが大事だったらしい
- 他にも消せるものはあったが不要なものでもないので残しておく
---
## 課題1の回答
以上の話を踏まえて、
課題1
```shell=
curl "https://portal.nap.gsic.titech.ac.jp/GetAccess/Login?Template=userpass_key&AUTHMETHOD=UserPassword"
```
でログインページが標準出力される(長いので-o portal.htmlなどする)
課題2
まず課題1の回答を改変した次のコード
```shell=
curl -c cookie.txt -o portal.html \
"https://portal.nap.gsic.titech.ac.jp/GetAccess/Login?Template=userpass_key&AUTHMETHOD=UserPassword"
```
を実行しCookieを `cookie.txt` に保存、加えてresponseを `portal.html`に保存。`portal.html` の179行目の`pageGenTime`と188行目の`CSRFFormToken`を控えておく。
次に
```shell=
read USERNAME
read PASSWORD
read TIME
read TOKEN
curl -L -b cookie.txt -c cookie.txt \
-e "https://portal.nap.gsic.titech.ac.jp/GetAccess/Login?Template=userpass_key&AUTHMETHOD=UserPassword" \
-H "Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" \
-H "Accept-Encoding:gzip,deflate,br" \
-H "Accept-Language:ja" \
-H "Connection:keep-alive" \
-d "usr_name=$USERNAME&usr_password=$PASSWORD&OK=++++OK++++&AUTHTYPE=&HiddenURI=https%3A%2F%2Fportal.nap.gsic.titech.ac.jp%2FGetAccess%2FResourceList&GARESOURCEID=resourcelistID2&Template=userpass_key&AUTHMETHOD=UserPassword&pageGenTime=$TIME&LOCALE=ja_JP&CSRFFormToken=$TOKEN" \
"https://portal.nap.gsic.titech.ac.jp/GetAccess/Login"
```
を実行。入力は
```
学籍番号
パスワード
pageGenTime
CSRFFormToken
```
これでマトリクスコードの入力ページが標準出力される(長いので-o response.htmlなどする)