Devido às necessidades do trabalho diário, a unidade utilizou o Serv-U para configurar um servidor FTP, porém, após assumir, descobriu-se que havia um problema gravíssimo. Este servidor FTP estava aberto ao público e a muitos usuários. não definiu senhas. Se é obrigatório que todos definam uma senha e ela deve ser definida no servidor, não significa que todos devem informar sua senha ao administrador? Afinal, muitas pessoas estão acostumadas a usar a mesma senha. O que fazer? A melhor maneira é, obviamente, fornecer uma página da Web para fornecer a função de modificação de senha.
Basta ir em frente e verificar online. Um método é usar a função ODBC fornecida pelo próprio Serv-U, usar o banco de dados para armazenar senhas e operar diretamente o banco de dados para realizar a função de modificação de senha. viável. Como este servidor FTP está em execução há um ano e possui quase 60 usuários, a probabilidade de erros ao transplantar esses usuários do arquivo INI para o banco de dados ainda é relativamente alta.
A primeira coisa é descobrir como as informações do usuário do Serv-U são salvas no arquivo INI e como a senha é criptografada. A estrutura do arquivo INI é relativamente simples. Para modificar a senha, basta encontrar a seção que começa com [User=@UserID|1] e modificar o valor da chave Password abaixo dela. @UserID refere-se ao ID de login do usuário.
1[GLOBAL]
2Versão=6.1.0.5
3PacketTimeOut=300
4
5
6
7[Domínio1]
8Usuário1=
9Usuário2=
10Usuário3=
11
12
13
14[USUÁRIO=abc|1]
15Senha=niE383DC3710266ECAE04A6B3A18A2966D
16HomeDir=D:
17AlwaysAllowLogin=1
18Alterar senha=1
19TimeOut=600
20Note1="Conta gerada pelo assistente"
21Acesso1=D:
vinte e dois
vinte e três
O método de criptografia da senha do usuário pode ser encontrado na base de conhecimento do site oficial da Ser-U
http://rhinosoft.com/KBArticle.asp?RefNo=1177&prod=su
Inserindo manualmente senhas criptografadas no arquivo ServUDaemon.ini
Para gerar uma senha criptografada, os primeiros dois caracteres aleatórios (o 'salt' - no intervalo a..z, A..Z) são adicionados ao início da senha em texto não criptografado. hash é codificado em hexadecimal. O resultado disso é escrito como texto simples começando com os 2 caracteres salt seguidos pelo hash codificado em hexadecimal.
Para uma conta de usuário no arquivo .ini, será semelhante a:
Password=cb644FB1F31184F8D3D169B54B3D46AB1A
O salt. é a string "cb", o hash MD5 é "644FB1F31184F8D3D169B54B3D46AB1A".
Ao verificar a senha de um usuário, o Serv-U fará o mesmo. Ele analisa o salt da senha armazenada do usuário (ou seja, "cb" neste caso), acrescenta. é a senha que o usuário enviou a ele pelo cliente, MD5 faz o hash e compara o resultado com o hash armazenado. Se os valores forem iguais, a senha inserida está correta.
O método de criptografia consiste em gerar duas letras aleatoriamente, em seguida, unir as letras e a senha e, em seguida, encontrar seus valores MD5. Por fim, coloque as letras aleatórias na frente do valor MD5 para obter a senha criptografada.
A seguir, você pode escrever um programa baseado na análise acima para implementar a modificação online.
1 /**//// <resumo>
2 /// Obtém o valor MD5 da string especificada
3 /// </summary>
4 /// <param name="strContent"></param>
5 /// <retorna></retorna>
6 String pública MD5 (String strContent)
7 {
8 System.Security.Cryptography.MD5 md5 = novo System.Security.Cryptography.MD5CryptoServiceProvider();
9 bytes[] bytes = System.Text.Encoding.UTF8.GetBytes(strContent);
10 bytes = md5.ComputeHash(bytes);
11md5.Limpar();
12 strings ret = "";
13 for(int i=0; i<bytes.Comprimento; i++)
14 {
15 ret += Convert.ToString(bytes[i],16).PadLeft(2,'0');
16}
17 return ret.PadLeft(32,'0').ToUpper();
18}
19
20
21 /**//// <resumo>
22 /// Gera uma string aleatória, o comprimento da string é 2
23 /// </summary>
24 /// <retorna></retorna>
25 string pública GetRandomString()
26 {
27 string strReturn = "";
28 Corrida aleatória = new Random();
29 strReturn += Convert.ToChar( ran.Next( 26 ) + 'a' ).ToString();
30 strReturn += Convert.ToChar( ran.Next( 26 ) + 'a' ).ToString();
31 return strReturn;
32}
33
34 //Gera uma senha criptografada a partir das letras aleatórias especificadas e da senha de login
35 string pública CreateCryPassword(string strFrontChars, string strPassword)
36 {
37 retornar strFrontChars + MD5( strFrontChars + strPassword ).ToUpper().Trim();
38}
39
40 /**//// <resumo>
41 /// Evento de clique de “Alterar Senha”, no qual a senha é modificada.
42 /// </summary>
43 /// <param name="sender"></param>
44 /// <param name="e"></param>
45 privado void btnModifyPwd_Click(objeto remetente, System.EventArgs e)
46 {
47 string strUserID = txtLoginID.Text;
48 if(strUserID == String.Empty)
49 {
50 controlMessage.InnerHtml = "Nome de usuário não pode ficar vazio";
51 retorno;
52}
53
54 //Determina se as duas entradas de senha são iguais
55 if(txtNewPassword.Text!=txtConfirmPassword.Text)
56 {
57 controlMessage.InnerHtml = "As senhas digitadas duas vezes são inconsistentes, digite novamente";
58 retorno;
59}
60
61 IniFile ini = new IniFile( _strServUDaemonPath );
62 string strSectionValue = "USER=" + strUserID.Trim() + "|1";
63
64 //Determina se o usuário existe lendo o HomeDir do usuário especificado
65 if(ini.ReadString(strSectionValue, "HomeDir", "" ) == "" )
66 {
67 controlMessage.InnerHtml = "O usuário especificado não existe";
68 retorno;
69}
70
71 //Começa a determinar se a senha está correta
72 string strPassword = ini.ReadString(strSectionValue, "Senha", "" );
73
74 string strPasswordFrontTwoChars;
75 bool bPasswordRight = falso;
76 if(strPassword.Comprimento > 2)
77 {
78 //Lê as letras aleatórias contidas na senha
79 strPasswordFrontTwoChars = strPassword.Substring(0, 2);
80 if(CreateCryPassword(strPasswordFrontTwoChars, txtOldPassword.Text) == strPassword)
81 {//Correspondências de senha
82 bPasswordRight = verdadeiro;
83}
84 mais
85 {//A senha não corresponde
86 bPasswordRight = falso;
87}
88}
89 else if( strPassword == txtOldPassword.Text) //A senha original está vazia
90 {
91 bPasswordRight = verdadeiro;
92}
93 mais
94 {
95 bPasswordRight = falso;
96}
97
98 if(bPasswordRight)
99 {
100 //A senha está correta, escreva uma nova senha e configure para carregar automaticamente novas configurações para que ainda sejam válidas na próxima vez que forem alteradas.
101 ini.WriteString( strSectionValue, "Senha", CreateCryPassword( GetRandomString(), txtNewPassword.Text ) );
102 controlMessage.InnerHtml = "Alteração de senha concluída";
103}
104 mais
105 {
106 controlMessage.InnerHtml = "A senha original está errada";
107}
108
109}
A variável _strServUDaemonPath no código acima é usada para salvar o caminho onde o arquivo ServUDaemon.ini está localizado. Este valor pode ser obtido através da configuração Web.Config no evento PageLoad.
Mas não terminou aí. Após testes, constatou-se que há um problema sério: após a alteração da senha, somente reiniciando o Serv-U a senha alterada poderá ter efeito. Isso não significa que é inútil? O administrador nem sempre pode reiniciar o servidor para que a alteração da senha tenha efeito.
Voltando novamente à base de conhecimento oficial do Serv-U, encontrei o seguinte conteúdo:
Atualizando manualmente o arquivo ServUDaemon.ini
Sempre que alterações forem feitas diretamente no arquivo ServUDaemon.ini, adicione a seguinte linha na área Global no arquivo INI
ReloadSettings=True
O Serv-U verifica regularmente o arquivo INI para esta configuração. Se estiver presente, o Serv-U será atualizado. todas as configurações armazenadas para cada domínio no servidor Isso permite que o Serv-U reconheça as alterações sem precisar ser reiniciado.
Depois que o Serv-U carrega as alterações, ele remove a entrada "ReloadSettings=True". próxima vez que qualquer alteração for feita.
Em outras palavras, contanto que você adicione a chave ReloadSettings na seção GLOBAL do arquivo INI e defina seu valor como True, você poderá atualizar automaticamente a senha após alterá-la. Então basta modificar o código original e inserir o seguinte código entre as linhas 101 e 102:
ini.WriteString("GLOBAL", "ReloadSettings", "True");
Neste ponto, uma página da web para alteração da senha do Serv-U online está concluída.
IniFile no programa é uma classe que encapsula a operação da API em arquivos INI. Ele só precisa implementar a leitura e escrita de strings.