日常業務の都合上、当部隊ではServ-Uを利用してFTPサーバーを構築していましたが、引き継ぎ後にこのFTPサーバーが公開されており、多くのユーザーが利用していたことが判明しました。パスワードを設定しませんでした。全員がパスワードを設定することが必須であり、それがサーバー上で設定されなければならない場合、結局のところ、多くの人が同じパスワードを使用することに慣れているため、全員が自分のパスワードを管理者に通知しなければならないことを意味するのではないでしょうか?何をするか?もちろん、最善の方法は、パスワード変更機能を提供する Web ページを提供することです。
オンラインで確認してみてください。Serv-U 自体が提供する ODBC 機能を使用し、データベースを使用してパスワードを保存し、データベースを直接操作してパスワード変更機能を実現する方法があります。実現可能。この FTP サーバーは 1 年間稼働しており、ユーザーが 60 人近くいるため、これらのユーザーを INI ファイルからデータベースに移植する際にエラーが発生する可能性は依然として比較的高く、INI ファイルを直接操作する方が簡単です。
まず、Serv-U のユーザー情報がどのように INI ファイルに保存され、パスワードがどのように暗号化されるかを理解する必要があります。 INI ファイルの構造は比較的単純で、パスワードを変更するには、[User=@UserID|1] で始まるセクションを見つけて、その下のパスワード キーの値を変更するだけです。 @UserID はユーザーのログイン ID を指します。
1[グローバル]
2バージョン=6.1.0.5
3パケットタイムアウト=300
4
5
6
7[ドメイン1]
8ユーザー1=
9ユーザー2=
10ユーザー3=
11
12
13
14[ユーザー=abc|1]
15パスワード=niE383DC3710266ECAE04A6B3A18A2966D
16ホームディレクトリ=D:
17常にログインを許可=1
18パスワード変更=1
19タイムアウト=600
20注1="ウィザードによって生成されたアカウント"
21アクセス1=D:
22
23
ユーザーパスワードの暗号化方法は、Ser-U公式Webサイトのナレッジベースで確認できます。
http://rhinosoft.com/KBArticle.asp?RefNo=1177&prod=su
ServUDaemon.ini ファイルへの暗号化されたパスワードの手動入力
暗号化されたパスワードを生成するには、最初の 2 つのランダムな文字 (a..z、A..Z の範囲の「ソルト」) がクリアテキスト パスワードの先頭に追加され、これが MD5 を使用してハッシュされ、結果として生成されます。ハッシュは 16 進数でエンコードされ、2 つのソルト文字で始まり、その後に 16 進数でエンコードされたハッシュが続くプレーンテキストとして
.ini ファイルに書き込まれます。
Password=cb644FB1F31184F8D3D169B54B3D46AB1A
ソルト
。は文字列「cb」、MD5 ハッシュは「644FB1F31184F8D3D169B54B3D46AB1A」です。
ユーザーのパスワードを検証するとき、Serv-U はユーザーの保存されたパスワード (つまり、この場合は「cb」) からソルトを解析し、先頭に付加します。これはユーザーがクライアントから送信したパスワードであり、MD5 はそれをハッシュし、その結果を保存されているハッシュと比較します。値が等しい場合、入力されたパスワードは正しいことになります。
暗号化方法は、2 つの文字をランダムに生成し、その文字とパスワードを結合して、その MD5 値を見つけます。最後に、ランダムな文字を MD5 値の前に置き、暗号化されたパスワードを取得します。
次に、上記の分析に基づいてプログラムを作成し、オンライン変更を実装できます。
1 /**//// <概要>
2 /// 指定された文字列の MD5 値を取得します
3 /// </まとめ>
4 /// <param name="strContent"></param>
5 /// <リターン></リターン>
6 パブリック String MD5(String strContent)
7 {
8 System.Security.Cryptography.MD5 md5 = 新しい System.Security.Cryptography.MD5CryptoServiceProvider();
9 byte[] バイト = System.Text.Encoding.UTF8.GetBytes( strContent );
10 バイト = md5.ComputeHash( バイト );
11 md5.Clear();
12 文字列 ret = "";
13 for(int i=0; i<bytes.Length; i++)
14 {
15 ret += Convert.ToString(bytes[i],16).PadLeft(2,'0');
16}
17 return ret.PadLeft(32,'0').ToUpper();
18}
19
20
21 /**//// <概要>
22 /// ランダムな文字列を生成します。文字列の長さは 2 です。
23 /// </まとめ>
24 /// <リターン></リターン>
25 パブリック文字列 GetRandomString()
26 {
27 文字列 strReturn = "";
28 ランダム ran = new Random();
29 strReturn += Convert.ToChar( ran.Next( 26 ) + 'a' ).ToString();
30 strReturn += Convert.ToChar( ran.Next( 26 ) + 'a' ).ToString();
31 戻り strReturn;
32}
33
34 //指定されたランダムな文字とログインパスワードから暗号化されたパスワードを生成します
35 パブリック文字列 CreateCryPassword( string strFrontChars, string strPassword)
36 {
37 return strFrontChars + MD5( strFrontChars + strPassword ).ToUpper().Trim();
38 }
39
40 /**//// <概要>
41 /// パスワードを変更する「パスワード変更」のクリックイベント。
42 /// </まとめ>
43 /// <param name="送信者"></param>
44 /// <param name="e"></param>
45 private void btnModifyPwd_Click(オブジェクト送信者、System.EventArgs e)
46 {
47 文字列strUserID = txtLoginID.Text;
48 if(strUserID == String.Empty)
49 {
50 controlMessage.InnerHtml = "ユーザー名を空にすることはできません";
51 戻ります。
52 }
53
54 //2 つのパスワード入力が同じかどうかを判断します
55 if( txtNewPassword.Text != txtconfirmPassword.Text )
56 {
57 controlMessage.InnerHtml = "2 回入力したパスワードは一致しません。再入力してください。";
58 戻ります。
59 }
60
61 IniFile ini = new IniFile( _strServUDaemonPath );
62 文字列 strSectionValue = "USER=" + strUserID.Trim() + "|1";
63
64 //指定されたユーザーの HomeDir を読み取り、ユーザーが存在するかどうかを判断します
65 if(ini.ReadString(strSectionValue, "HomeDir", "" ) == "" )
66 {
67 controlMessage.InnerHtml = "指定されたユーザーは存在しません";
68 戻ります。
69 }
70
71 //パスワードが正しいかどうかの判定を開始します
72 文字列 strPassword = ini.ReadString( strSectionValue, "パスワード", "" );
73
74 文字列 strPasswordFrontTwoChars;
75 bool bPasswordRight = false;
76 if(strPassword.Length > 2)
77 {
78 //パスワードに含まれるランダムな文字を読み取ります
79 strPasswordFrontTwoChars = strPassword.Substring(0, 2);
80 if( CreateCryPassword( strPasswordFrontTwoChars, txtOldPassword.Text ) == strPassword )
81 {//パスワード一致
82 bPasswordRight = true;
83}
84 その他
85 {//パスワードが一致しません
86 bPasswordRight = false;
87 }
88}
89 else if( strPassword == txtOldPassword.Text) //元のパスワードは空です
90 {
91 bPasswordRight = true;
92 }
93 その他
94 {
95 bPasswordRight = false;
96 }
97
98 if( bPasswordRight )
99 {
100 //パスワードは正しいので、新しいパスワードを書き込み、次回変更されたときにも有効になるように、新しい設定を自動的にロードするように設定します。
101 ini.WriteString( strSectionValue, "パスワード", CreateCryPassword( GetRandomString(), txtNewPassword.Text ) );
102 controlMessage.InnerHtml = "パスワードの変更が完了しました";
103}
104 その他
105 {
106 controlMessage.InnerHtml = "元のパスワードが間違っています";
107 }
108
109 }
上記のコードの _strServUDaemonPath 変数は、ServUDaemon.ini ファイルが配置されているパスを保存するために使用されます。この値は、PageLoad イベントの Web.Config 設定を通じて取得できます。
しかし、それで終わりではありませんでした。テストの結果、重大な問題があることが判明しました。パスワードを変更した後、Serv-U を再起動しないと変更されたパスワードが有効になりません。それは、管理者がパスワードの変更を有効にするために常にサーバーを再起動できるわけではないということではないでしょうか?
再びServ-Uの公式ナレッジベースに戻ると、次のような内容が見つかりました。
ServUDaemon.ini ファイルの手動更新
ServUDaemon.ini ファイルに直接変更を加える場合は、INI ファイルの Global 領域に次の行を追加します。ReloadSettings
=True
Serv-U は、INI ファイルにこの設定があるかどうかを定期的にチェックします。存在する場合、Serv-U は更新します。これにより、Serv-U は再起動しなくても変更を認識できるようになり
、「ReloadSettings=True」エントリが削除され、再度入力できるようになります。次回変更が行われたとき。
つまり、INI ファイルの GLOBAL セクションに ReloadSettings キーを追加し、その値を True に設定していれば、パスワードの変更後に自動的にパスワードを更新できます。したがって、元のコードを変更して、101 行目と 102 行目の間に次のコードを挿入するだけです。
ini.WriteString( "GLOBAL", "ReloadSettings", "True" );
この時点で、Serv-U パスワードをオンラインで変更するための Web ページが完成します。
プログラム内の IniFile は、INI ファイルに対する API の操作をカプセル化するクラスであり、文字列の読み取りと書き込みのみを実装する必要があります。