Gmailにつなぐための実証コード - 最終的に作ったコード [プログラミング]
元々のC言語のソースのインデントが、スペースがふたつになっていてRubyみたい。Linux的に言うと、インデントのtabは8とかなんだろうけど、私はインデントのタブを、普通に4にしている人間です。やっぱり、いろいろな状況で見ると、普通は4tabぐらいが妥当なのかな、と思っています。というか、8タブって空白が多過ぎて、気持ち悪いんですが。C言語のインデントが2というのも悪くはないけど、見るの慣れてないので気になる。気になる程度で気持ち悪くはない。結局、Windowsから入った人間だからなぁ。
ええと、Gmailにつなぐために、OpenSSLのライブラリをC言語で使ってみた。なるべくミニマム設定でやったつもり。
ファイルはこっち。
http://www010.upp.so-net.ne.jp/mihumi/source/pop3s-client_minimum.c
説明内容はコメントで大丈夫かな。コメントをたくさん盛る癖があるので、自分のソースを見るときは、設計書とか読む必要がないのが良いんだよね。TODOとか、不具合とか、別ファイルにしても、そんなの見るかどうかわかんないから、自分が恥ずかしい結果になるとしても、がっつりコメントを盛る。
Macでのコンパイル方法は
gcc -L/opt/local/lib -I/opt/local/include -lssl -lcrypto -arch x86_64 -o https-client https-client.c
みたいな感じで。細かいうんぬんは下のリンクにあるはず。
http://miff.blog.so-net.ne.jp/2010-12-12
結局、証明書関係は使わなかったので、すっぱり削りました。それでも、ミニマム設定にはなってないかな(乱数の発生とか)。でも、辛うじて動く状態にはなっているはずです。
ええと、Gmailにつなぐために、OpenSSLのライブラリをC言語で使ってみた。なるべくミニマム設定でやったつもり。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/types.h> #include <sys/uio.h> #include <unistd.h> #include <openssl/crypto.h> #include <openssl/ssl.h> #include <openssl/err.h> #include <openssl/rand.h> #define BUF_LEN 1024 SSL *ssl; SSL_CTX *ctx; void sendByTLS(char* request); void recieveFromGmail(); void readOneLine(); int main(argc, argv) int argc; char *argv[]; { int ret; int s; struct hostent *servhost; struct sockaddr_in server; char *host = "pop.gmail.com"; char *port = "995"; if ( argc == 2 ) { //URLとポート番号を引数から得る host = argv[1]; port = argv[2]; } servhost = gethostbyname(host); if ( servhost == NULL ){ fprintf(stderr, "[%s] から IP アドレスへの変換に失敗しました。\n", host); exit(1); } bzero((char *)&server, sizeof(server)); server.sin_family = AF_INET; bcopy(servhost->h_addr, (char *)&server.sin_addr, servhost->h_length); server.sin_port = htons(atoi(port)); s = socket(AF_INET, SOCK_STREAM, 0); if ( s < 0 ){ fprintf(stderr, "ソケットの生成に失敗しました。\n"); exit(1); } if ( connect(s, (struct sockaddr*) &server, sizeof(server)) == -1 ){ fprintf(stderr, "connect に失敗しました。\n"); exit(1); } /* ------------------ ここからが SSL(それまで普通のソケット)------------------ */ SSL_load_error_strings(); //エラーメッセージを文字列で SSL_library_init(); //SSL/TLSの初期化 ctx = SSL_CTX_new(TLSv1_client_method()); //プロトコル選択。GmailはTLS if ( ctx == NULL ) { ERR_print_errors_fp(stderr); exit(1); } ssl = SSL_new(ctx); //SSL_CTX構造体を生成 if ( ssl == NULL ) { ERR_print_errors_fp(stderr); exit(1); } ret = SSL_set_fd(ssl, s); //ソケットとSSLの構造体を結びつけ if ( ret == 0 ) { ERR_print_errors_fp(stderr); exit(1); } /* PRNG 初期化 (新しめのOSには要らないかもな、コレ)*/ RAND_poll(); //乱数の種生成 while ( RAND_status() == 0 ){ //乱数の種の過不足チェック unsigned short rand_ret = rand() % 65536; RAND_seed(&rand_ret, sizeof(rand_ret)); //乱数の大きさが小さい場合追加 } /* SSL で接続 */ ret = SSL_connect(ssl); //サーバとハンドシェイク if ( ret != 1 ) { ERR_print_errors_fp(stderr); exit(1); } // readOneLine(); recieveFromGmail(); /* ------------------- リクエスト送信 ------------------- */ // POP3的なメッセージ sendByTLS("USER ユーザー名\r\n"); recieveFromGmail(); sendByTLS("PASS パスワード名\r\n"); recieveFromGmail(); sendByTLS("STAT\r\n"); recieveFromGmail(); sendByTLS("LIST\r\n"); recieveFromGmail(); // sendByTLS("RETR 1\r\n"); // recieveFromGmail(); //RETR途中の1230文字くらいで、下のQUITが入ってきちゃう。なぜ? sendByTLS("QUIT\r\n"); // readOneLine(); recieveFromGmail(); ret = SSL_shutdown(ssl); //TLSのコネクションを切る if ( ret != 1 ){ ERR_print_errors_fp(stderr); exit(1); } close(s); //普通のソケットを閉じる SSL_free(ssl); //SSL_new()で確保した領域解放 SSL_CTX_free(ctx); //SSL_CTX_new()で確保した領域解放 ERR_free_strings(); //SSL_load_error_strings()で確保した領域解放 exit(0); } void sendByTLS(char* request) { printf("----- クライアントからのリクエスト -----\n"); printf(request); int ret = SSL_write(ssl, request, strlen(request)); //リクエスト送信 if ( ret < 1 ){ ERR_print_errors_fp(stderr); exit(1); } } // バッファが小さいので、全部読まずに捨ててる // 必要なのがはじめの十数バイトだからいいんだけど… void readOneLine() { printf("----- サーバからのレスポンス -----\n"); char buf[BUF_LEN]; int read_size = SSL_read(ssl, buf, sizeof(buf)-1); //サーバから受信 printf(buf); } // 不具合があるので直さんと。バッファが小さすぎる(32bytes以下?)と切れたりすることも void recieveFromGmail() { printf("----- サーバからのレスポンス -----\n"); char buf[BUF_LEN]; while (1) { memset(buf, '\0', sizeof(buf)); int read_size = SSL_read(ssl, buf, sizeof(buf)-1); //サーバから受信 printf(buf); if ( read_size < sizeof(buf)-1) break; } }
ファイルはこっち。
http://www010.upp.so-net.ne.jp/mihumi/source/pop3s-client_minimum.c
説明内容はコメントで大丈夫かな。コメントをたくさん盛る癖があるので、自分のソースを見るときは、設計書とか読む必要がないのが良いんだよね。TODOとか、不具合とか、別ファイルにしても、そんなの見るかどうかわかんないから、自分が恥ずかしい結果になるとしても、がっつりコメントを盛る。
Macでのコンパイル方法は
gcc -L/opt/local/lib -I/opt/local/include -lssl -lcrypto -arch x86_64 -o https-client https-client.c
みたいな感じで。細かいうんぬんは下のリンクにあるはず。
http://miff.blog.so-net.ne.jp/2010-12-12
結局、証明書関係は使わなかったので、すっぱり削りました。それでも、ミニマム設定にはなってないかな(乱数の発生とか)。でも、辛うじて動く状態にはなっているはずです。
コメント 0