TrickDiary このページをアンテナに追加 RSSフィード

2008-08-01

wraith132008-08-01

[][] マスターパスワードに基づく各種目的別パスワード生成ツール

http://www.trickpalace.net/tools/password.htm

スターパスワードから目的別のパスワードを生成するツールです。 このツールは乱数を用いるパスワード生成ツールとは異なり、同じ指定でパスワード生成を行えば毎回同じパスワードが生成されます。

このパスワード生成ツールを利用すると、ひとつのマスターパスワードさえ覚えておけば各種目的別パスワードを管理する手間から解放されます。 このツールは一方向性関数(SHA-256)を利用してパスワードを作成します。 このツールで作成されたパスワードを元に、マスターパスワードを復元したり、同じマスターパスワードから作成される他のパスワードを算出することはできません。

...というもの作成してみました。

アイデア的にも特に真新しいものではないでしょうし、既に個人的にこのような方法でパスワードを管理している方も居られるかと思います。ただ、このページのようにお手軽に利用できるものが見あたらなかったんで自作してみました。

追記

このツールに関しては例外的に IE だけでなく Opera 及び Safari でも動作することを確認しました。あと、ウィジェットの類への移植を考慮してたところなんだけど、... Mac(というか Safari with Dashboard)だと、このページのフォームの部分だけ切り抜いてそのままウィジェットとして仕立て上げてしまうなんて荒技がプログラマではない一般的なユーザーであっても超簡単にできるんだね。初めて良い意味で Apple スゲー!って思った。

追記2

つい先日 GIGAZINE で同様のツール SuperGenPass が紹介されてたんですね。orz

ちなみに SuperGenPass との主な差は...

...といったところです。あと、SuperGenPass のほうがドメイン等の付帯条件の入力の手間が省ける分、使い勝手がいいと思います。

追記3

パスワードに使用する文字種を記号文字だけでなく数字、英大文字、英小文字もそれぞれ個別に選択できるようにしました。

2008-01-20

msgbox

[][][] メッセージボックス表示コマンド ver 2.0

前回のものに以下の修正を加えました。

画面サンプル1

msgbox -t3000 -cサンプル 1行目 2行目 " " 4行目

f:id:wraith13:20080120133444p:image

画面サンプル2

whoami |msgbox -c"whoami"

f:id:wraith13:20080120133520p:image

戻り値(環境変数 %ERRORLEVEL% に設定される値)

IDWINVER
IDOK1-
IDCANCEL2-
IDABORT3-
IDRETRY4-
IDIGNORE5-
IDYES6-
IDNO7-
IDCLOSE80x0400以上
IDHELP90x0400以上
IDTRYAGAIN100x0500以上
IDCONTINUE110x0500以上
IDTIMEOUT320000x0501以上

注意事項1

MessageBoxTimeout() は Windows XP から user32.dll に搭載されている Undocumented API です。 Windows XP 以降に対応している winuser.h にはこの API で使う為の IDTIMEOUT が定義されているし、 user32.lib には MessageBoxTimeoutA() 及び MessageBoxTimeoutW() の定義があるから関数宣言するだけで使えるかとも思ったのですが、どうもうまくいかず GetProcAddress() で API の呼び出しアドレスを取得しています。

注意事項2

リダイレクトやパイプの機能でメッセージを渡す場合は問題ないけど、コンソールでキーボードを叩いて標準入力へメッセージを渡した場合はメッセージボックスにフォーカスが当たらないので注意。この現象が再現するのはこのコマンドの動作確認やってる時だけで実用上は問題がないんで、特に原因を追及して直すつもりもありません。恐らくは親コンソールのGUIスレッドにアタッチすれば解決するんじゃなかろうかと思ってはいるんだけど、相手が通常のウィンドウ制御の及ばないコンソールウィンドウなのでちとやっかいかも。

ソースコード

//////////////////////////////////////////////////////////////////////////////
//
//  includes
//

#if !defined(WINVER)
#define WINVER 0x0501
#endif

#if !defined(_WIN32_WINNT)
#define _WIN32_WINNT WINVER
#endif

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <wincon.h>
#include <string>
#include <iostream>
#include <iterator>

#if defined(_MSC_VER)
#pragma comment(lib, "USER32.lib")
#pragma comment(lib, "SHELL32.lib")
#endif


///////////////////////////////////////////////////////////////////////////////
//
//  main
//

int main(int, char *[])
{
    HWND parent =
#if 0x0500 <= WINVER
        GetConsoleWindow();
#else
        NULL;
#endif
    std::wstring title = L"msgbox";
    std::wstring message;
    DWORD icon = MB_ICONINFORMATION;
    DWORD button = MB_OK;
#if 0x0501 <= WINVER
    DWORD timeout = 0;
    typedef int (*MessageBoxTimeoutW_type)(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, WORD wLanguageId, DWORD dwTimeout);
    MessageBoxTimeoutW_type MessageBoxTimeoutW = NULL;
#endif
    
    int argc;
    LPWSTR *args = CommandLineToArgvW(GetCommandLineW(), &argc);
    
    try
    {
        int i = 1;
        while(i < argc)
        {
            if (L'-' == args[i][0])
            {
                switch(args[i][1])
                {
                
                case L'I': case L'i':
                    switch(args[i][2])
                    {
                    case L'I': case L'i': icon = MB_ICONINFORMATION;    break;
                    case L'E': case L'e': icon = MB_ICONEXCLAMATION;    break;
                    case L'S': case L's': icon = MB_ICONSTOP;           break;
                    case L'Q': case L'q': icon = MB_ICONQUESTION;       break;
                    default: throw L"不明なオプションが指定されました。";
                    }
                    break;
                
                case L'B': case L'b':
                    switch(args[i][2])
                    {
                    case L'A': case L'a': button = MB_ABORTRETRYIGNORE; break;
                    case L'C': case L'c': button = MB_OKCANCEL;         break;
                    case L'Y': case L'y': button = MB_YESNO;            break;
                    case L'N': case L'n': button = MB_YESNOCANCEL;      break;
                    case L'O': case L'o': button = MB_OK;               break;
                    case L'R': case L'r': button = MB_RETRYCANCEL;      break;
#if 0x0500 <= WINVER
                    case L'T': case L't': button = MB_CANCELTRYCONTINUE;break;
#endif
                    default: throw L"不明なオプションが指定されました。";
                    }
                    break;
                    
#if 0x0501 <= WINVER
                case L'T': case L't':
                    timeout = _wtol(args[i] +2);
                    if (timeout)
                    {
                        HMODULE user32_lib = LoadLibraryA("user32.dll");
                        MessageBoxTimeoutW = (MessageBoxTimeoutW_type)GetProcAddress(user32_lib, "MessageBoxTimeoutW");
                        FreeLibrary(user32_lib);
                        //  ↑DLLは参照カウンタを持っており、C++ランタイムライブラリによる 
                        //  LoadLibrary() 呼び出し分のカウントがあるので少なくとも main() 
                        //  を抜けるまでは user32.dll はアンロードされない。
                    }
                    break;
#endif

                case L'C': case L'c':
                    title = args[i] +2;
                    break;
                
                default:
                    throw L"不明なオプションが指定されました。";
                    
                }
            }
            else
            {
                break;
            }
            ++i;
        }
        if (argc <= i)
        {
            //  コマンドライン引数でメッセージが指定されていないので標準入力からメッセージを取得
#if defined(_MSC_VER) && 1300 <= _MSC_VER
            std::wcin.imbue(std::locale(""));
            message.assign(std::istreambuf_iterator<wchar_t>(std::wcin), std::istreambuf_iterator<wchar_t>());
#else
            std::string buffer;
#if defined(__BORLANDC__)
            buffer.assign(std::istreambuf_iterator<char>(std::cin), std::istreambuf_iterator<char>());
#else
            std::istreambuf_iterator<char> cin_i(std::cin), cin_end;
            while(cin_i != cin_end)
            {
                buffer += (*cin_i);
                ++cin_i;
            }
#endif
            if (2 <= buffer.size() && '\xFF' == buffer[0] && '\xFE' == buffer[1])
            {
                message.assign(((LPCWSTR)buffer.data()) +1, (buffer.size() /sizeof(WCHAR)) -1);
            }
            else
            {
                size_t wbuffer_size = buffer.size() +16;
                WCHAR *wbuffer = new WCHAR[wbuffer_size];
                MultiByteToWideChar(CP_ACP, 0, buffer.c_str(), -1, wbuffer, wbuffer_size);
                message.assign(wbuffer);
            }
#endif
        }
        else
        {
            //  コマンドライン引数で指定されているメッセージを取得
            while(i < argc)
            {
                message += args[i];
                message += L"\n";
                ++i;
            }
        }
    }
    catch(const wchar_t *a_message)
    {
        title = GetCommandLineW();
        message = a_message;
        message += L"\n";
        message += L"\n";
#if 0x0501 <= WINVER
        message += L"msgbox [-ii|-ie|-is-|-iq] [-ba|-bc|-by|-bn|-bo|-br|-bt] [-tタイムアウトまでの時間(ミリ秒)] [-cキャプション] [メッセージ1 [メッセージ2...]]";
#elif 0x0500 <= WINVER
        message += L"msgbox [-ii|-ie|-is-|-iq] [-ba|-bc|-by|-bn|-bo|-br|-bt] [-cキャプション] [メッセージ1 [メッセージ2...]]";
#else
        message += L"msgbox [-ii|-ie|-is-|-iq] [-ba|-bc|-by|-bn|-bo|-br] [-cキャプション] [メッセージ1 [メッセージ2...]]";
#endif
        icon = MB_ICONSTOP;
        button = MB_OK;
    }
    
    LocalFree(args);
    
    return
#if 0x0501 <= WINVER
        (MessageBoxTimeoutW) ?
            MessageBoxTimeoutW(parent, message.c_str(), title.c_str(), icon |button, 0, timeout):
#endif
            MessageBoxW(parent, message.c_str(), title.c_str(), icon |button);
}

2008-01-08

[f:id:wraith13:20080108204644p:image

[][][] メッセージボックス表示コマンド

前々から作ろうと思ってたメッセージボックスを表示するだけのプログラムです。バッチファイルの御供にどうぞ。silentとも相性がいいです。

//////////////////////////////////////////////////////////////////////////////
//
//  includes
//

#if !defined(WINVER)
#define WINVER 0x0500
#endif

#if !defined(_WIN32_WINNT)
#define _WIN32_WINNT WINVER
#endif

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <windows.h>
#include <wincon.h>

#pragma comment(lib, "USER32.lib")
#pragma comment(lib, "SHELL32.lib")


///////////////////////////////////////////////////////////////////////////////
//
//  main
//

int main(int, char *[])
{
    std::wstring title = L"msgbox";
    std::wstring message;
    DWORD icon = MB_ICONINFORMATION;
    DWORD button = MB_OK;
    
    int argc;
    LPWSTR *args = CommandLineToArgvW(GetCommandLineW(), &argc);
    
    try
    {
        if (argc <= 1)
        {
            throw L"引数が指定されていません。";
        }
        
        int i = 1;
        while(i < argc)
        {
            if (L'-' == args[i][0])
            {
                switch(args[i][1])
                {
                
                case L'I':
                case L'i':
                    switch(args[i][2])
                    {
                    
                    case L'I':
                    case L'i':
                        icon = MB_ICONINFORMATION;
                        break;
                        
                    case L'E':
                    case L'e':
                        icon = MB_ICONEXCLAMATION;
                        break;
                        
                    case L'S':
                    case L's':
                        icon = MB_ICONSTOP;
                        break;
                        
                    case L'Q':
                    case L'q':
                        icon = MB_ICONQUESTION;
                        break;
                        
                    default:
                        throw L"不明なオプションが指定されました。";
                        
                    }
                    break;
                
                case L'B':
                case L'b':
                    switch(args[i][2])
                    {
                    
                    case L'A':
                    case L'a':
                        button = MB_ABORTRETRYIGNORE;
                        break;
                    
                    case L'C':
                    case L'c':
                        button = MB_OKCANCEL;
                        break;
                        
                    case L'Y':
                    case L'y':
                        button = MB_YESNO;
                        break;
                        
                    case L'N':
                    case L'n':
                        button = MB_YESNOCANCEL;
                        break;
                        
                    case L'O':
                    case L'o':
                        button = MB_OK;
                        break;
                        
                    case L'R':
                    case L'r':
                        button = MB_RETRYCANCEL;
                        break;
                        
#if 0x0500 <= WINVER
                    case L'T':
                    case L't':
                        button = MB_CANCELTRYCONTINUE;
                        break;
#endif
                        
                    default:
                        throw L"不明なオプションが指定されました。";
                        
                    }
                    break;
                    
                case L't':
                    title = args[i] +2;
                    break;
                
                default:
                    throw L"不明なオプションが指定されました。";
                    
                }
            }
            else
            {
                break;
            }
            ++i;
        }
        if (argc <= i)
        {
            throw L"メッセージが指定されていません。";
        }
        while(i < argc)
        {
            message += args[i];
            message += L"\n";
            ++i;
        }
    
    }
    catch(const wchar_t *a_message)
    {
        title = GetCommandLineW();
        message = a_message;
        message += L"\n";
        message += L"\n";
#if 0x0500 <= WINVER
        message += L"msgbox [-ii|-ie|-is-|-iq] [-ba|-bc|-by|-bn|-bo|-br|-bt] [-tタイトル] メッセージ1 [メッセージ2...]";
#else
        message += L"msgbox [-ii|-ie|-is-|-iq] [-ba|-bc|-by|-bn|-bo|-br] [-tタイトル] メッセージ1 [メッセージ2...]";
#endif
        icon = MB_ICONSTOP;
        button = MB_OK;
    }
    
    LocalFree(args);
    
#if 0x0500 <= WINVER
    return MessageBoxW(GetConsoleWindow(), message.c_str(), title.c_str(), icon |button);
#else
    return MessageBoxW(NULL, message.c_str(), title.c_str(), icon |button);
#endif
}

↓こんな感じで呼び出すと

msgbox -ii -bo -t"サンプル メッセージ" "msgbox の使用例" " " "こんな感じでメッセージボックスを表示できます。"

↓こんな風に表示されます。(真ん中の空行は↑のダブルクォーテーションで括った半角のスペースで指定しています。)

f:id:wraith13:20080108204644p:image

メッセージボックスのどのボタンが押下されたのかの判断は環境変数 %ERRORLEVEL% が以下の表(winuser.h で #define されてる定数で関係ないものも含んでいます)からどの値になったかで判断してください。

IDWINVER
IDOK1-
IDCANCEL2-
IDABORT3-
IDRETRY4-
IDIGNORE5-
IDYES6-
IDNO7-
IDCLOSE80x0400以上
IDHELP90x0400以上
IDTRYAGAIN100x0500以上
IDCONTINUE110x0500以上
IDTIMEOUT320000x0501以上

2008-01-06

[][][] neticon を更新しました。

http://tricklib.com/cxx/ex/neticon/

2008-01-06 ポートチェックのみ IPv6 に対応しました。( PING チェックはまだ IPv6 に対応してません )


IPv6 の API が既存の IPv4 ベースのアプリケーションを IPv6 へ対応し易いように考慮してくれてはいるみたいなのですが、その実、少なくともこの neticon のケースでは通信まわりのコードをかなり作り直すはめになりました。ただ、普通に TCP ベースの通信やってる分にはそんなには IPv6 への対応は厳しくないと思います。が、ICMP(というかPING)とかはなかなか一筋縄ではうまくいってくれません。

実のところ PING に関しても IPv6 対応のコードは記述済みでちゃんと動作確認もとれたりはするのですが、うまく動作する環境と全然うまく動作しない環境があってとりあえず今回は PING の IPv6 対応コードは殺してます。特に Icmp6SendEcho2() まわりの情報がまだ少なくネット上で探せば Icmp6CreateFile(), Icmp6SendEcho2() を使った PING のサンプルコード等があるにはあるのですが、それらの情報をもってしても現在の問題解決にはまだ至ってません。恐らくは getaddrinfo() で自分のアドレスの取得の仕方あたりに問題があるじゃないかとはふんでいるのですが、いまんとこハッキリしません。また後日、この問題を追跡していきたいと思います。

ちなみに TCP ベースの通信は Windows XP SP2 の IPv6 プロトコルがインストールされていない環境でも IPv6 対応コードで正常に動作してくれました。

2007-10-15

[][][] svcicon と neticon を更新しました。

http://tricklib.com/cxx/ex/svcicon/

http://tricklib.com/cxx/ex/neticon/

2007-10-15 Windows Vista で通知アイコンの登録失敗する問題を解決。


前回の処置を施しても Windows Vista では稀に通知アイコンの登録に失敗することがあったので追跡してみたのですが、Windows Vista では Shell_NotifyIcon() の戻り値が FALSE なのに GetLastError() は ERROR_SUCCESS を返すことがあるというトホホな内容でした。仕方がないんで、GetLastError() の値はチェックしないようにしました。

この問題は Windows Vista 固有の問題だろうと考えていますが、元々発生頻度が低い問題なのでひょっとしたらその他の Windows でも再現するかもしれません。

2007-10-02

[][][] svcicon と neticon を更新しました。

http://tricklib.com/cxx/ex/svcicon/

2007-10-02 次の二つの修正を行いました。

  • 通知アイコン登録のリトライ回数の増加、及び、リトライループに1秒のWaitを追加。
  • 表記の修正("トレイアイコン"→"通知アイコン", "システムトレイ"→"通知領域")。

http://tricklib.com/cxx/ex/neticon/

2007-10-02 次の四つの修正を行いました。

  • 通知アイコン登録のリトライ回数の増加、及び、リトライループに1秒のWaitを追加。
  • 表記の修正("トレイアイコン"→"通知アイコン", "システムトレイ"→"通知領域")。
  • "OK"オーバーレイアイコンの変更(再生マーク→チェックマーク)。
  • ソケットをクローズする前に接続をシャットダウンする処理を追加。

通知アイコン登録のリトライについては、KB418138 に対するいままでの対策では不十分だったようで、かなりスペックのいいマシンでも Windows のスタートアップ時では通知アイコンの登録にそれでもまだ失敗することがあったので処理を強化しました。


表記の修正に関しては「Windowsプログラミングの極意」(Raymond Chen著、原題:THE OLD NEW THING)によると"トレイアイコン"だの"システムトレイ"だのと言った名前は明確な間違いで、正しくはそれぞれ"通知アイコン"および"通知領域"(追記:本文中では"通知エリア"となっていますが、WindowsGUI上での表現は"通知領域"となっているのでそれに倣いました。)とのことなので修正しました。


ソケットのシャットダウンに関しては、neticon による生存確認が IDS によっては SYNフラッド攻撃(DoS攻撃のひとつ) と見做されるようなので本来必要ないハズなのですがダメ元で接続をシャットダウンする処理を追加しました。SYNフラッド攻撃と見做されるということはクライアント(neticon)がACKを返していないということになるのですが、connect()関数から呼び出し元に制御が返ってきている時点で本来なら接続が確立されていて且つそれはクライアントがACKを返していること意味するわけでどうにも腑に落ちません。

2007-09-07

[][][] neticon を更新しました。

http://tricklib.com/cxx/ex/neticon/

2007-09-07 次の三つの修正を行いました。

  • ポート番号を指定した場合に接続先が必ず localhost になるバグの修正
  • [OutputDebugString(Log)] によるログ出力にタイムスタンプを追加
  • トレイアイコンのTIP表示でステータスをリモートホスト名の後ろではなく前へ移動

...いささか詰めが甘かった。ちと反省。

最初のバグに関しては gethostbyname() の仕様( ホスト名の文字列の代わりに誤って NULL を渡していたのに localhost のアドレスを"正常に"返していた )に振り回され見つけ損ねてました。

最後の修正に関してはログの出力時にも同じテキストを使用している関係上、複数のログ出力が行われた際に表示位置が揃うようにという意味と、リモートホスト名がアホみたいに長い場合にTIP表示の末尾が切断されてステータスが表示されなくなるという問題を避ける意味でやってます。

2007-09-06

neticon

[][][] neticon を公開しました。

http://tricklib.com/cxx/ex/neticon/

このツールはネットワーク上のサーバやその上で動作するサービスの稼働状態をタスクバーのシステムトレイ上のアイコンで監視する為のツールです。

ポート番号を指定しなかった場合は PING を行いその結果をトレイアイコンに反映し、ポート番号が指定されていればそのポートに接続確認を行いその結果をトレイアイコンに反映します。

2007-08-30

[][][] svcicon を更新しました。

http://tricklib.com/cxx/ex/svcicon/

Windows XP でアルファ付きのアイコンを指定すると半透明部分が黒ずむ問題を仮対策。

Windows Vista では再現しない問題であることから、どうも Windows XP の ImageList 固有の問題だと思われます。

これを解決するには自前の処理でアイコンのビットマップバイナリを合成する必要があると思われ、そこまでやる気は Nothing なんで仮対策とかいいつつたぶんずっとこのままほったらかしにしちゃうと思います。

2007-08-26

[][][] svcicon を更新しました。

http://tricklib.com/cxx/ex/svcicon/

一時停止が可能なサービスであっても権限要求のフラグが足りていなかった為に一時停止ができなかったバグを修正。