2

SMTPサーバーへの単純な接続を行おうとしています(認証が必要です)。SSL(CのOpenSSLライブラリ)を使用して、ポート587でsmtp.live.comに接続しています。

最初にsocket()関数を使用してソケットを初期化し、次にconnect()を使用してサーバーに接続します。次に、SSLチャネルを起動して、ログインを試みます。

これが私のシェルの出力です:

server : 220 BLU0-SMTP261.phx.gbl Microsoft ESMTP MAIL Service, Version: 6.0.3790.4675     ready at  Sat, 9 Mar 2013 07:25:17 -0800 

EHLO [127.0.0.1]
server : 250-BLU0-SMTP261.phx.gbl Hello [163.5.221.45]
250-TURN
250-SIZE 41943040
250-ETRN
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-8bitmime
250-BINARYMIME
250-CHUNKING
250-VRFY
250-TLS
250-STARTTLS
250 OK

STARTTLS
server : 220 2.0.0 SMTP server ready

EHLO [127.0.0.1]
server : 250-BLU0-SMTP261.phx.gbl Hello [163.5.221.45]
250-TURN
250-SIZE 41943040
250-ETRN
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-8bitmime
250-BINARYMIME
250-CHUNKING
250-VRFY
250-AUTH LOGIN PLAIN
250 OK

AUTH LOGIN
server : 334 VXNlcm5hbWU6

Y2hlcmGhvdXXXXXXXXXXXuY29tXHJcbg0K
serveur : 
U2hsYWXXXXXXXXXXXwblxyXG4NCg0K
server : 

ご覧のとおり、ユーザー名とパスワードはどちらもbase64でエンコードされています(\ r \ nなし)。サーバーが何も応答しない理由がわかりません...(ソケットを読み取る前にsleep()を入れようとしましたが、同じ結果が得られました)

サーバーに接続するためのコード:

static int              _connect_IPV4(int socket, struct hostent *host)
{
  struct sockaddr_in    addr;

  addr.sin_port = htons(587);
  addr.sin_family = AF_INET;
  addr.sin_addr = *(struct in_addr *)host->h_addr;
  bzero(&addr.sin_zero, 8);
  if (connect(socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) == -1)
    printf("%s\n", strerror(errno));
  else
    return (socket);
}

SSLを開始するコード:

static void     _launch_ssl(int socket)
{
  read_socket(socket);
  write_socket(socket, "EHLO [127.0.0.1]\r\n");
  read_socket(socket);
  write_socket(socket, "STARTTLS\r\n");
  read_socket(socket);
}

SSLを接続するためのコード:

connection      *ssl_connect()
{
  connection    *c;

  c = malloc(sizeof(connection));
  c->ssl_handle = NULL;
  c->ssl_context = NULL;
  c->socket = connect_TCP_IP();
  _launch_ssl(c->socket);
  if (c->socket != -1)
    {
      SSL_load_error_strings();
      SSL_library_init();

      SSL_CTX_new(SSLv23_client_method());
      SSL_new(c->ssl_context);
      SSL_set_fd(c->ssl_handle, c->socket);
      SSL_connect(c->ssl_handle);
    }
  return (c);
}

主要 :

int             main()
{
  connection    *c;

  c = ssl_connect();
  ssl_write_socket(c, "EHLO [127.0.0.1]\r\n");
  ssl_read_socket(c);
  ssl_write_socket(c, "AUTH LOGIN\r\n");
  ssl_read_socket(c);
  ssl_write_socket(c, "Y2hlcmNoZXN0b3lhQGhvdG1haWwuY29tXHJcbg0K");
  printf("\n");
  ssl_read_socket(c);
  ssl_write_socket(c, "U2hsYWdldHRvUHIwblxyXG4NCg0K");
  printf("\n");
  ssl_read_socket(c);
}
4

1 に答える 1

1

まず、サーバーが送信する内容に実際に反応するように、クライアントを改善するつもりであることを願っています。たとえば、_launch_ssl関数でサーバーの応答を実際にチェックして、サーバーを使用する前にオプションとして提供されているEHLOことを確認していないように見えます。STARTTLSその関数の擬似コードは次のようになります。

  1. EHLOを送信します(できれば[127.0.0.1]のような意味のないものではありません!)
  2. サーバーの応答を確認してください
  3. STARTTLSが提供されるオプションに含まれていない場合は、保釈します
  4. STARTTLSが提供されているオプションの中にある場合は、STARTTLSを送信して続行します。

同様に、では、サーバーが実際に250に応答した後、サーバーが実際に334に応答したことmain()を確認する必要があります。EHLOAUTH

そうでなければ、問題はあなたが\r\nあなたの応答の後にあなたが送らないということであるように思われます。言い換えると:

ssl_write_socket(c, "Y2hlcmNoZXN0b3lhQGhvdG1haWwuY29tXHJcbg0K");

する必要があります:

ssl_write_socket(c, "Y2hlcmNoZXN0b3lhQGhvdG1haWwuY29tXHJcbg0K\r\n");

さらに、base64文字列には、ユーザー名の一部であるかのように、文字列内に\\r\\n\r\n(バックスラッシュ+'r'+バックスラッシュ+'n' + CR + LF)が埋め込まれています。それが間違っていると仮定すると、実際には、コードはおそらく実際に次のようになります。\\r\\n\r\n

ssl_write_socket(c, "Y2hlcmNoZXN0b3lhQGhvdG1haWwuY29t\r\n");
于 2013-03-09T16:17:35.410 に答える