22:36今回はただの愚痴ですが・・・。SMB/CIFSの仕様をみると、データの途中にいきなり可変長データが入っていたりします。paddingがいたるところに出てきます。変数は存在するものの、実際のところどういう値にしていいのか、定数としてどんなものがあるのかわからないことが多々あります。そんなときはプロトコルアナライザです。WindowsServer系ならばリソースキットで利用できますが、WireSharkなんかも便利です。絶対あったほうが良いもの・・。それはポートミラーリング、またはポートモニタリング機能がついたスイッチングハブです。完全なリピータハブがあればそれでもいいですが、おそらく10BASE-Tの時代のものしか無いと思うので・・・。数年前までは何万円もしましたが、今では1万円を切る商品もあるみたいです。00:56Windowsで使われる、NetBIOSまわりを頑張ってみます。やりたいことは、Windowsコンピュータ名(NETBIOS名)からIPアドレスを取得することです。NetBIOSはとにかく不可解です。本当に不可解なんですが、歴史的背景があるので仕方がありません。どのくらい古いかというと1980年代くらいなので仕様書もイマイチ読みづらく、後の改変も多数あるので本当にわかりづりです。NetBIOSはTCP/IPとは別物です。現在ではプロトコル部分をNetBEUI、インターフェイス部分をNetBIOSと呼ぶようですが、元はインターフェイス(API)からプロトコルまですべてひっくるめた規格でした。NetBEUIは現在では使われることは無くなりましたが、NetBIOSのインターフェイスだけは利用され続けているというわけです。(TCP/IPとか言いながらUDP/IPも多用します)これ時代もWindows3.x時代のものなので何かと理解しづらいです。Extensions[MS-NBTE]をまず見てみると名前解決についてはRFC1002を見るように書いてあります。RFC1002の内容は「NetBIOS-over-TCP」となっています。読んでみると・・・なんか意味不明・・ですががんばって読む。+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Bはブロードキャストフラグなので、1で固定みたいです。フラグ部分は0x0110。これがまだ何故??というやり方で頭に???浮かびっぱなしです。NETBIOS名は15文字です。本来は16文字でしたが、最後の1バイトを別の用途に割り当てたため15文字。15文字に満たない場合はスペース(0x20)で埋めます。Managerの仕様ではなくMicrosoftの拡張仕様です。0x00はクライアント、0x20がサーバサービスを示すようなのでここでは0x20が正解だと思われます。(実際にはどちらも名前登録されていて、反応もしてくれるので良いのですが)で、肝心のNETBIOS名の格納方法です。最初の1バイトは0x20を指定します。0x20=長さが32byteの意味で、NETBIOS名の場合は32byte固定と書いてあるので必ず0x20を指定。NEBIOS名+サフィックスの16byteを以下の手順で符号化して32Byteにします。最後にNULL(0x00)くっつけるので、長さを表す先頭の0x20と合わせて34byteになります。これがQUESTION_NAMEになります。NETBIOS名の符号化は、まず文字コードを4バイト単位にわけます。空白文字(0x20)であれば0x2と0x0です。0x0をA、0x1をB、0x2をC・・・という感じで文字を割り当てます。0x20であれば「CA」になります。NETBIOS名が「FRED」であれば「EGFCEFEECACACACACACACACACACACACA」になります。これをUDPでブロードキャストすれば該当ホストがレスポンスを返してくれます。iOSで1024番以下のポートをbindできるのか?とちょっと不安でしたが、やってみたら大丈夫でした。+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+TTLより前はリクエストと同じ。ARRAYにIPアドレスが入ります。(複数ある場合は複数入ります。パケットの送信アドレスを見るか、自分のネットワークマスクと較べてどれを利用するか決めます)実際には名前の解放パケットとかも飛んでくるようですが(それを見てキャッシュから削除する)、iOSでそれを監視し続けるのは非現実的なので無視します。Resolution)を使う必要があります。今回はIPv4だけでいいのでそっちはやりません。(そのくらいの知識がある人はIPアドレスでわかるでしょうし・・・)さて、これでコンピュータ名(NETBIOS名)を解決できるようになりました。なったところでどう使うかは悩ましいところなんですけどね。02:23Windows関連情報は運用を目的にしたものが多く、コーディング例はあんまり聞かないのでメモ的に書いておきます。SMBの認証にはLM認証、NTLMv1認証、NTLMv2認証、Kerberos認証のいずれかを使います。Kerberos認証は鍵交換でActiveDirectly環境想定のものなので除外。LM認証はNTLMv1認証はだいぶ古いにもかかわらずつい最近まで使われていましたがWindows7からはデフォルト無効になっているようなのでこちらも使わない方針で行きます。ようするに面倒なのでNTLMv2だけ対応します。あと、まず非対応ということはあり得ないので、Unicodeだけ対応します。Protocol」のことらしいです。Microsoftの仕様書名は[MS-NLMP]です。基本的には認証情報をバイト列に並べているだけなので仕様書を読みながら実装すればなんとか出来ます。SMB/CIFSがアライメントやら謎のpaddingやらとても実装しにくいのに比べると可変長データをpayloadにまとめているので少しだけ気楽です。クライアント側で生成する必要があるのは、NEGOTIATE_MESSAGEとAUTHENTICATE_MESSAGEです。前者は本当に必要な情報を連結してバイト列にしているだけなので楽勝。それでも実際実装してみると一発ではなかなか思い通りにならないのですが・・・。後者のAUTHENTICATE_MESSAGEもほとんど同じですが、NEGOTIATE_MESSAGEに対してサーバから返されたCHALLENGE_MESSAGEに含まれる情報を使ってチャレンジレスポンスを計算する必要があります。それがNTLMv2なわけですね。Responseというフィールドです。いっても、使うのはmd4とmd5だけなんですね。試行錯誤の結果正しい結果を出せるようになったのでメモ。challengeと4を連結する6.5に対して、3を鍵として、hmac_md5を計算する7.6と4を連結する7で出来たものがNTLMv2レスポンスになります。2104に規定されています。それぞれC言語コードが附属しています。計算量も無いので最適化も不要でしょうから、そのまま使ってもOKかと思います。ライセンス表記が必要です。探せばそのあたりをクリアしたコードも見つかります。(僕はmd4はそのまま使いました。md5は以前準備したコードがあったのでそっちを利用)基本的に、SMBと同じく全てリトルエンディアンが使われます。普通ネットワークバイトオーダーと言えばビッグエンディアンなんですけどね。最初はエンディアン気にしてコード書いてましたが、どうせiPhoneもリトルエンディアンだし途中から面倒になってリトルエンディアン環境想定で作りました。これでSMBサーバと認証ができるようになりました。TCP/IPを使って名前解決(IPアドレスを取得する)をやってみたいと思います。IPアドレスでアクセスすれば良いので不要な気もしますが。欲を言えばBROWSERプロトコルを使ってネットワーク上のNETBIOSホスト名を自動収集したいところですが、、まぁNASとかはBonjourに対応してるから不要な気もします。challengeのスペルが違うというお恥ずかしいミスがありましたのでこっそり修正。00:36昔実践していたことがあるのが、ひとりサマータイムもどき。自分だけ時計を1時間か2時間ずらして生活します。(時計を進めます)そうすると時計が午前2時とか3時とかになるまで起きていても平気です。(気分ですよ気分)実際には午前0時頃なわけですが、さすがに(表示が)1時、2時になると寝ようかなーという気分になるわけです。これはこれでよいのですが、昼間は他の人と時間がずれていて何かと不便です。といわけで、帳尻合わせて夜だけ時計を進める歪みタイムゾーンを考えてみました。・午前6時から午後6時までは普通の時計と同じです。・午後6時からちょっと加速して、午後10時になるころに表示は24時(0時)になります。・午後10時から午前2時までは表示は2時間進んだまま、通常と同じ速度で表示が進みます。・午前2時から午前6時の間に2時間の進みを帳尻合わせします。<図解>とりあえずみんな笑顔でハッピーということで「スマイルタイム」と名づけました。<スマイルタイム>↑思いついたらすぐになんかしてみたくなるので、説明のためのサイト作りました。全てパブリックドメイン的に扱って構わないので是非お試しください。普及活動します(弱々しく)寝る時間だけではなく、仕事もはやく終えるようになったらいいですよね。iPhone時計アプリとかもそのうち作ってみる。00:29何故か全くライブラリが見つからないSMB/CIFS。ググってみても、「SMBのiOSライブラリないの?(そもそもObj-cに限定しなくても無い)」「sambaがGPL、ぐぬぬぬ・・・」という記事しか見当たらない。組込み向けの製品はいくつか見つかりましたが、たぶん個人で買えるようなものじゃない。実装は厄介なんだろうなと見る気もしてなかったですが、風邪でダウンしていたので、その時に一度気合を入れてテストしてみました。tangoというOSSがあるようですが、うまく動かない。認証関連が古いせいで最近のWindowsでは動かないぽい。flagが立っていると即座にエラー返すようなのできっとダメだろう、ってことでtangoは諦める。SMBはSMB1とSMB2があって、SMB2は大きなバッファが扱えて高速LANで効率がいいようですが、NASとかで対応していないものもあるかもしれないし、iPhoneのWifiからではほとんど速度は変わらない(と思う)のでまずSMB1にトライ。みたいな実装があって苦しむと噂には聞いております。仕様書読むと案外単純な通信です。(ワイルドカード*でFindFileする。ルートディレクトリだと失敗するのでちょっと変える必要ある)・データの転送(実は簡単な命令っぽい)という感じで、バイナリデータなのでC言語では扱いやすい(はず・・)しかしセッションリクエストで早速ハマる。Manager1.0のときの(方言で?)定義された。このコマンドが最初に定義されてから、リクエストと応答メッセージのフォーマットが変わったよ。