SSLベースselectプログラミングLinuxシステム

11672 ワード

この機能で参考にした記事は、https://www.openssl.org (これはopensslの公式サイトで、多くの関数の使用、英語のサイトを調べることができます)https://www.cnblogs.com/hjbf/p/10248388.html (SSLプロトコルについてかなり詳しく紹介されていますが、十分な時間があればご理解いただけます)https://blog.csdn.net/nyyjs/article/details/72832896 (SSLに関する各種証明書の紹介)https://www.cnblogs.com/LiuYanYGZ/p/10438861.html (この文章で複数の証明書と鍵を使用したのは双方向認証を使用しているため、本プログラムは1つのdemoで比較的簡単で、一方向認証方式を使用している)https://www.jianshu.com/p/fb5fe0165ef2 (SSLの一方向認証と双方向認証についての紹介)https://www.cnblogs.com/AloneSword/p/3809002.html (OpenSSLを使って証明書を生成するのは、基本的にコマンドですが、流れを大まかに理解できます.以下、明確な命令を出して証明書を生成します)https://blog.csdn.net/xs574924427/article/details/17240793 (この文章は私のコードの原型で、この文章の始まりはSSLプログラミングの流れを詳しく紹介して、見る価値がありますが、コードを実現する部分は少し乱れています)
Serverエンドプログラム
  • 必ずCA証明書と鍵を持っていなければならない.SSLプロトコルを作るには迂回してはいけない.私はこのステップを省略しようとした.ここの検証過程はかなり複雑でこまごましているので、私は良い理解の方法でまとめた.https://www.cnblogs.com/y-c-y/p/12124685.html】しかし、CSの両端は通信に成功しなかった.SSL握手の過程で構造体SSLにいくつかの付与が行われるため、証明書と鍵がなければ、いくつかの流れは進まない.
  • 上記cacert.pemとprivkey.pemファイルを次の2つのコマンドで生成します.cdからコードディレクトリに生成すれば
  • です.
    openssl genrsa -out privkey.pem 2048
    openssl req -new -x509 -key privkey.pem -out cacert.pem -days 1095

    Cacert.pemが生成されると、省や会社名など、勝手に入力できるものを入力させます.
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include "utils.h"
    #define MAXBUF 1024
    #define PORT 7838
    #define CAR "cacert.pem"
    #define PRIVA_KEY "privkey.pem"
    
    int main()
    {
        int sockfd, new_fd;
        FILE *fp
        socklen_t len;
        struct sockaddr_in my_addr, their_addr;
        char buf[MAXBUF + 1];
        SSL_METHOD *meth;
        SSL_CTX *ctx;
        fd_set readFdSet;
    
        /*    OpenSSL */
        SSL_library_init();
        /*      */
        OpenSSL_add_all_algorithms();
        /*         */
        SSL_load_error_strings();
        /*                  */
        meth = (SSL_METHOD *)SSLv23_server_method();
        /*        */
        ctx = SSL_CTX_new(meth);
        /*          */
        SSL_CTX_set_security_level(ctx, 0);
        
        if (ctx == NULL) 
        {
            ERR_print_errors_fp(stdout);
            exit(1);
        }
        /*  SSL    CA   */
        if (SSL_CTX_use_certificate_file(ctx, CAR, SSL_FILETYPE_PEM) <= 0) 
        {
            ERR_print_errors_fp(stdout);
            exit(1);
        }
        /*  SSL       */
        if (SSL_CTX_use_PrivateKey_file(ctx, PRIVA_KEY, SSL_FILETYPE_PEM) <= 0) 
        {
            ERR_print_errors_fp(stdout);
            exit(1);
        }
        /*        (            )     */
        if (!SSL_CTX_check_private_key(ctx)) 
        {
            ERR_print_errors_fp(stdout);
            exit(1);
        }
        
        /*   TCP socket */
        if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) 
        {
            perror("socket");
            exit(1);
        } 
        else
            printf("socket created
    "); bzero(&my_addr, sizeof(my_addr)); my_addr.sin_family = PF_INET; my_addr.sin_port = htons(PORT); my_addr.sin_addr.s_addr = INADDR_ANY; /* TCP socket */ if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr))== -1) { perror("bind"); exit(1); } else printf("binded
    "); /* TCP socket */ if (listen(sockfd, 5) == -1) { perror("listen"); exit(1); } else printf("begin listen
    "); FD_ZERO(&readFdSet); FD_SET(fileno(fp),&readFdSet); FD_SET(sockfd,&readFdSet); while (1) { FD_SET(fileno(fp),&readFdSet); FD_SET(sockfd,&readFdSet); /* select */ if(select(sockfd+1,&readFdSet,NULL,NULL,NULL)>0) { if(FD_ISSET(sockfd,&readFdSet)) { SSL *ssl; ssl = SSL_new(ctx); /* socket ssl */ SSL_set_fd(ssl, sockfd); /* SSL socket socket */ if (SSL_accept(ssl) == -1) { perror("accept"); close(new_fd); break; } bzero(buf, MAXBUF + 1); scanf("%s",buf); len = SSL_write(ssl, buf, strlen(buf)); if (len <= 0) { printf(" '%s' ! %d, '%s'
    ",buf, errno, strerror(errno)); SSL_shutdown(ssl); SSL_free(ssl); close(new_fd); SSL_CTX_free(ctx); return 0; } else printf(" '%s' , %d !
    ",buf, len); bzero(buffer, MAXBUF + 1); /* SSL read recevfrom */ len = SSL_read(ssl, buffer, MAXBUF); if (len > 0) printf(" :'%s', %d
    ",buffer, len); else { printf(" ! %d, '%s'
    ",errno, strerror(errno)); /* */ SSL_shutdown(ssl); SSL_free(ssl); close(sockfd); SSL_CTX_free(ctx); return 0; } } else if(FD_ISSET(fileno(fp),&readFdSet)) { memset(buf,0,sizeof(buf)); if((n = readline(fileno(fp),buf,MAXLINE)) == 0) { shutdown(sockfd,SHUT_WR); FD_CLR(fileno(fp),&rset); INFO_PRINT("nothing input!"); continue; } else if(n >0) { SSL_writen(sockfd,buf,n); } else { ERR_EXIT("some error occurred "); } printf("FD_ISSET(fileno(fp),&rset)----%d--%s
    ",n,buf); SSL_writen(sockfd,buf,n); } else { printf(" ! %d, '%s'
    ",errno, strerror(errno)); } } else { printf(" ! %d, '%s'
    ",errno, strerror(errno)); } } SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ctx); close(new_fd); return ; }

    Clientエンドプログラム
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include "utils.h"
    #define MAXBUF 1024
    #define PORT 7838
    #define IP "127.0.0.1"
     
    void ShowCerts(SSL * ssl)
    {
        X509 *cert;
        char *line;
         
        cert = SSL_get_peer_certificate(ssl);
        if (cert != NULL) 
        {
            printf("      :
    "); line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); printf(" : %s
    ", line); free(line); line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); printf(" : %s
    ", line); free(line); X509_free(cert); } else printf(" !
    "); } int main() { int sockfd, len; FILE *fp struct sockaddr_in dest; char buffer[MAXBUF + 1]; SSL_CTX *ctx; SSL *ssl; fd_set readFdSet; /* OpenSSL */ SSL_library_init(); /* */ OpenSSL_add_all_algorithms(); /* */ SSL_load_error_strings(); /* */ meth = (SSL_METHOD *) SSLv23_client_method (); /* */ ctx = SSL_CTX_new(meth); if (ctx == NULL) { ERR_print_errors_fp(stdout); exit(1); } /* TCP socket */ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("Socket"); exit(errno); } printf("socket created
    "); bzero(&dest, sizeof(dest)); dest.sin_family = AF_INET; dest.sin_port = htons(PORT); if (inet_aton(IP, (struct in_addr *) &dest.sin_addr.s_addr) == 0) { perror(IP); exit(errno); } printf("address created
    "); /* TCP */ if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != 0) { perror("Connect "); exit(errno); } printf("server connected
    "); ssl = SSL_new(ctx); /* socket ssl */ SSL_set_fd(ssl, sockfd); /* SSL */ if (SSL_connect(ssl) == -1) ERR_print_errors_fp(stderr); else { printf("Connected with %s encryption
    ", SSL_get_cipher(ssl)); /* SSL Client , */ ShowCerts(ssl); } /* readFdSet select */ FD_ZERO(&readFdSet); while(1) { FD_SET(fileno(fp),&readFdSet); FD_SET(sockfd,&readFdSet); /* select */ if(select(sockfd+1,&readFdSet,NULL,NULL,NULL)>0) { if(FD_ISSET(sockfd,&readFdSet)) { bzero(buffer, MAXBUF + 1); /* SSL read recevfrom */ len = SSL_read(ssl, buffer, MAXBUF); if (len > 0) printf(" :'%s', %d
    ",buffer, len); else { printf(" ! %d, '%s'
    ",errno, strerror(errno)); /* */ SSL_shutdown(ssl); SSL_free(ssl); close(sockfd); SSL_CTX_free(ctx); return 0; } } else if(FD_ISSET(fileno(fp),&readFdSet)) { memset(buf,0,sizeof(buf)); if((n = readline(fileno(fp),buf,MAXLINE)) == 0) { shutdown(sockfd,SHUT_WR); FD_CLR(fileno(fp),&rset); INFO_PRINT("nothing input!"); continue; } else if(n >0) { /* do nothing */ } else { ERR_EXIT("some error occurred "); } printf("FD_ISSET(fileno(fp),&rset)----%d--%s
    ",n,buf); SSL_writen(ssl,buf,n); } else { printf(" ! %d, '%s'
    ",errno, strerror(errno)); } } else { printf(" ! %d, '%s'
    ",errno, strerror(errno)); } } /* */ SSL_shutdown(ssl); SSL_free(ssl); close(sockfd); SSL_CTX_free(ctx); return 1; }

    makefile
    all:ss
        @echo ""
        @echo "This is Client compile......."
        @echo ""
    ss:client.c 
        gcc -g -o Client client.c -lssl -lcrypto
        gcc -g -o Server server.c -lssl -lcrypto
    clean :
        -rm Client Server