Проблема с OpenSSL
От: milo  
Дата: 07.06.11 11:28
Оценка:
добрый день. по работе необходимо реализовать ссл-сервер и ссл-клиента на с++ под линукс. пошарив по инету и начитавшись документации набросал тестовые клиент и сервер. сгенерировал серитфикаты, как сказано тут http://codeghar.wordpress.com/2008/03/17/create-a-certificate-authority-and-certificates-with-openssl/ . при подключении клиент выдает ошибку:
error SSL_ERROR_SYSCALL
error: error:00000000:lib(0):func(0):reason(0)
The peer does not have certificate
sending request...
5914:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:188:
-1 bytes sent

текст клиента:
int main() {
    int err;

    SSL_CTX * ctx = init_ctx("client-cert.pem", "client-private.pem", "certs/cacert.pem", "clientpass");
    if (!ctx) {
        fprintf(stderr, "couldn't init ctx\n");
        exit(1);
    }

    int sock = tcp_connect("localhost", 4443);

    /* Connect the SSL socket */
    SSL * ssl = SSL_new(ctx);
    BIO * sbio = BIO_new_socket(sock,BIO_NOCLOSE);
    SSL_set_bio(ssl,sbio,sbio);

    if((err = SSL_connect(ssl)) != 1) {
        switch(SSL_get_error(ssl, err)) {
            case SSL_ERROR_NONE:
            fprintf(stderr, "error SSL_ERROR_NONE\n");
            break;
            case SSL_ERROR_ZERO_RETURN:
            fprintf(stderr, "errorSSL_ERROR_ZERO_RETURN \n");
            break;
            case SSL_ERROR_WANT_READ:
            fprintf(stderr, "error SSL_ERROR_WANT_READ\n");
            break;
            case SSL_ERROR_WANT_WRITE:
            fprintf(stderr, "error SSL_ERROR_WANT_WRITE\n");
            break;
            case SSL_ERROR_WANT_CONNECT:
            fprintf(stderr, "error SSL_ERROR_WANT_CONNECT\n");
            break;
            case SSL_ERROR_WANT_X509_LOOKUP:
            fprintf(stderr, "error SSL_ERROR_WANT_X509_LOOKUP\n");
            break;
            case SSL_ERROR_SYSCALL:
            fprintf(stderr, "error SSL_ERROR_SYSCALL\n");
            break;
            case SSL_ERROR_SSL:
            fprintf(stderr, "error SSL_ERROR_SSL\n");
            break;
            default:
            fprintf(stderr, "error f****** s***!!!\n");
            break;
        }
        fprintf(stderr, "%s\n", ERR_error_string(ERR_get_error(), NULL));
        ERR_print_errors_fp(stderr);
        //exit(1);
    }

    check_cert(ssl, "host.com");
    fprintf(stderr, "%d bytes sent\n", send_request(ssl, "come with me, we'll go dreaming"));   

    /* shutdown ssl connection */
    err = SSL_shutdown(ssl);
    if (err < 0) {
        ERR_print_errors_fp(stderr);
        exit(1);
    }

    close(sock);
    SSL_free(ssl);
    SSL_CTX_free(ctx);

    return 0;
}

ssize_t send_request(SSL * ssl, const char * req) {
    fprintf(stderr, "sending request...\n");
    ssize_t size = SSL_write(ssl, req, strlen(req));

    if (size < 0) {
        ERR_print_errors_fp(stderr);
    }

    return size;
}
int pem_passwd_cb(char *buf, int size, int rwflag, void *password) {
    strncpy(buf, (char *)(password), size);
    buf[size - 1] = '\0';
    return(strlen(buf));
}

typedef int (*pem_passwd_func) (char *, int , int , void *);

SSL_CTX * init_ctx(const char * cert, const char * key, const char * ca_cert, char * password) {
    SSL_library_init();
    SSL_load_error_strings();
    pem_passwd_func passwd_func = &pem_passwd_cb;

    SSL_CTX * ctx = SSL_CTX_new(SSLv23_method());
    if (!ctx) {
        ERR_print_errors_fp(stderr);
        return NULL;
    }

    /* Load the server certificate into the SSL_CTX structure */
    if (SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stderr);
        return NULL;
    }
               
    SSL_CTX_set_default_passwd_cb(ctx, passwd_func);
    SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *)password);

    /* Load the private-key corresponding to the server certificate */
    if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stderr);
        return NULL;
    }

    /* Check if the server certificate and private-key matches */
    if (!SSL_CTX_check_private_key(ctx)) {
        fprintf(stderr,"Private key does not match the certificate public key\n");
        return NULL;
    }

    /* verify client */
    /* Load the RSA CA certificate into the SSL_CTX structure */
    if (!SSL_CTX_load_verify_locations(ctx, ca_cert, NULL)) {
        ERR_print_errors_fp(stderr);
        return NULL;
    }

    return ctx;
}


Функция tcp_connect() отрабатывает верно, т.к. сервер сообщает по поступившем соединении. Приватный ключ защищен паролем. тут проблема либо в коде (не очень вероятно), либо в сертификатов (мне нужна двусторонняя авторизация — как сервера, так и клиента). Пробовал тестировать при помощи s_client:

milo@milonote:~/src/tests/ssl$ openssl s_client -connect localhost:4443 -cert client-cert.pem -key client-private.pem -verify 1 -CAfile cacert.pem -prexit -msg -pass password
verify depth is 1
Invalid password argument "password"
Error getting password

говорит, пароль неверный, хотя он точно верный, потому как уже пару раз перегенеривал сертификат и ключ. И да, может быть это неправильно, но я генерировал сертификат и ключ для клиента от серверного CA сертификата.

Прошу помочь, потому как уже сутки пытаюсь выяснить причину. Спасибо.
c linux openssl
Re: Проблема с OpenSSL
От: MTimur  
Дата: 07.06.11 17:21
Оценка:
Здравствуйте, milo, Вы писали:

M>Invalid password argument "password"

M>Error getting password

http://www.mail-archive.com/openssl-users@openssl.org/msg48820.html
Re[2]: Проблема с OpenSSL
От: milo  
Дата: 08.06.11 03:50
Оценка:
Здравствуйте, MTimur, Вы писали:

MT>Здравствуйте, milo, Вы писали:


M>>Invalid password argument "password"

M>>Error getting password

MT>http://www.mail-archive.com/openssl-users@openssl.org/msg48820.html


ошибка та же
Re[3]: Проблема с OpenSSL
От: milo  
Дата: 08.06.11 04:26
Оценка:
Здравствуйте, milo, Вы писали:

M>Здравствуйте, MTimur, Вы писали:


MT>>Здравствуйте, milo, Вы писали:


M>>>Invalid password argument "password"

M>>>Error getting password

MT>>http://www.mail-archive.com/openssl-users@openssl.org/msg48820.html


M>ошибка та же


вобщем openssl s_client и openssl s_server начали работать ошибка была в том, что надо пароль писать "pass:пароль", а не "пароль:пароль", как по ссылке указано. остается проблема с моими клиентам. че делать?
Re[4]: Проблема с OpenSSL
От: MTimur  
Дата: 08.06.11 12:12
Оценка:
Здравствуйте, milo, Вы писали:

M>вобщем openssl s_client и openssl s_server начали работать ошибка была в том, что надо пароль писать "pass:пароль", а не "пароль:пароль", как по ссылке указано. остается проблема с моими клиентам. че делать?


Apache? Что в логах ssl на сервере?

server ~ # cat /var/log/apache2/ssl_access_log
server ~ # cat /var/log/apache2/ssl_error_log


На сервере сертификат самоподписанный? — возможно в этом причина.
Re[5]: Проблема с OpenSSL
От: milo  
Дата: 08.06.11 13:27
Оценка:
Здравствуйте, MTimur, Вы писали:

MT>Здравствуйте, milo, Вы писали:


M>>вобщем openssl s_client и openssl s_server начали работать ошибка была в том, что надо пароль писать "pass:пароль", а не "пароль:пароль", как по ссылке указано. остается проблема с моими клиентам. че делать?


MT>Apache? Что в логах ssl на сервере?


MT>
server ~ # cat /var/log/apache2/ssl_access_log
MT>server ~ # cat /var/log/apache2/ssl_error_log


MT>На сервере сертификат самоподписанный? — возможно в этом причина.


Спасибо, проблему решил. Апач не использовал — надо было своего демона писать. Проблема была не в клиенте, а в сервере, в SSL_set_fd передавал по ошибки серверный сокет вместо клиентского.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.