Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > boost::asio::ssl, авторизация на сервере по ключу


Автор: bsa 9.9.2009, 16:15
Задача: нужно написать сервер, каждый клиент которого должен иметь свой собственный сертификат шифрования (т.е. авторизация по сертификату, как в ssh). Желательно сделать это через boost::asio.
На данный момент (поковыряв этот asio) я решил, что проще всего сделать так: при подключении клиента получить у него некий идентификатор (логин), по этому идентификатору загрузить с диска необходимый публичный ключ (приватный хранится на стороне клиента) и после этого начать процедуру SSL:handshake...

Возможно ли это? И как это сделать (меня интересуют процедуры авторизации по публичному ключу и преобразования обычного сокета в защищенный)?

Автор: andrew_121 9.9.2009, 16:57
Цитата(bsa @  9.9.2009,  16:15 Найти цитируемый пост)
Возможно ли это?

да

asio/examples/ssl/client.cpp
тут отличный пример.

Добавлено через 6 минут и 57 секунд
дополню.
В примерах, не используются загружаемые ключи. Нет надобности. Но если нужно, то можно.

Автор: andrew_121 9.9.2009, 17:20
еще дополню.
в asio::ssl::context(могу ошибаться), есть методы с постфиксом file. они это реализуют. нужно в доках уточнить...

Автор: bsa 9.9.2009, 19:44
это я все видел. доки, если честно, просто жгут. Имхо, исходник был бы более информативным.
Единственное, что спасает - примеры. Но опять же, хоть бы подсветку синтаксиса сделали...

Автор: andrew_121 9.9.2009, 21:05
Цитата(bsa @  9.9.2009,  19:44 Найти цитируемый пост)
это я все видел. доки, если честно, просто жгут

да уж.

Цитата(bsa @  9.9.2009,  19:44 Найти цитируемый пост)
Имхо, исходник был бы более информативным.

так вот же:
examples/ssl/server.cpp
examples/ssl/client.cpp

или что не так?

Автор: andrew_121 9.9.2009, 21:23
Если использовать это: http://getunderstand.com/latest/understand/understand-b489-win32.exe можно получить такую картинку.
http://ipicture.ru/Gallery/Viewfull/23495633.html

имхо, намного облегчает понимание. учитывая что она динамическая.

Автор: bsa 9.9.2009, 21:55
Цитата(andrew_121 @ 9.9.2009,  21:05)
Цитата(bsa @  9.9.2009,  19:44 Найти цитируемый пост)
Имхо, исходник был бы более информативным.

так вот же:
examples/ssl/server.cpp
examples/ssl/client.cpp

или что не так?

Я имел в виду, исходник библиотеки, а не примера.

Автор: andrew_121 9.9.2009, 22:02
Цитата(bsa @  9.9.2009,  21:55 Найти цитируемый пост)
Я имел в виду, исходник библиотеки, а не примера. 

Ну тогда ваще не понял smile  Она же opensource, в чем проблема?

Автор: bsa 9.9.2009, 22:20
Цитата(andrew_121 @ 9.9.2009,  22:02)
Ну тогда ваще не понял smile  Она же opensource, в чем проблема?

Проблема в доке, которая хуже, чем исходник. Я только это и хотел сказать.

Автор: Lazin 9.9.2009, 22:30
я никогда не использовал ssl, но могу что-нибудь подсказать по архитектуре smile 
Цитата(bsa @  9.9.2009,  22:20 Найти цитируемый пост)
Проблема в доке, которая хуже, чем исходник. Я только это и хотел сказать. 
там на самом деле все не сложно, как и все удачные библиотеки, asio очень просто и понятно организована

Автор: bsa 9.9.2009, 23:18
Мне очень интересно, можно ли один и тот же SSL контекст использовать для разных подключений (об этом в доке я ничего не нашел). Например, коннектится к серверу клиент, для него используется некий контекст, затем второй коннектится... Можно ли для него использовать тот же контекст? Ведь все методы получают неконстантный контекст! А вот в примере я увидел, что именно так и делается - контекст для всех один:
Код
  void handle_accept(session* new_session,
      const boost::system::error_code& error)
  {
    if (!error)
    {
      new_session->start();
      new_session = new session(io_service_, context_);
      acceptor_.async_accept(new_session->socket(),
          boost::bind(&server::handle_accept, this, new_session,
            boost::asio::placeholders::error));
    }
    else
    {
      delete new_session;
    }
  }

Автор: andrew_121 10.9.2009, 06:46
Цитата(bsa @  9.9.2009,  23:18 Найти цитируемый пост)
можно ли один и тот же SSL контекст использовать для разных подключений

да. а вот наоборот, не уверен.

Автор: bsa 27.11.2009, 11:35
Цитата(bsa @  9.9.2009,  23:18 Найти цитируемый пост)
можно ли один и тот же SSL контекст использовать для разных подключений
можно. несмотря на сигнатуру, ssl::socket копирует контекст.

Цитата(bsa @  9.9.2009,  16:15 Найти цитируемый пост)
Возможно ли это? И как это сделать (меня интересуют процедуры авторизации по публичному ключу и преобразования обычного сокета в защищенный)?
Можно, но средств asio для этого недостаточно. Я сделал так:
1. клиент хранит у себя сертификат цифровой подписи ("открытый ключ"), которой подписаны сертификаты серверов
2. после установления соединения и успешного прохождения операции квитирования (handshake) (значит цифровая подпись верна, так как установлен режим проверки verify_peer), берется поле subject полученного сертификата и из него извлекается нужное поле.
Делаю это так:
Код
template<typename ImplType>
std::string getCertIssuer(ImplType impl, const std::string &field)
{
    std::string data;
    {
        ::X509 *crt = ::SSL_get_peer_certificate(impl->ssl);
        char buf[256];
        ::X509_NAME_oneline(::X509_get_subject_name(crt), buf, sizeof(buf));
        ::X509_free(crt);
        buf[sizeof(buf)-1] = '\0';
        data = buf;
    }
    std::string::size_type begin = data.find("/" + field + "=");
    begin = data.find('=', begin);
    const std::string::size_type end = data.find('/', begin);
    if (end == std::string::npos)
        return std::string();
    ++begin;
    return data.substr(begin, end - begin);
}
...
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket(io_service, ctx);
...
std::string organization = getCertIssuer(socket.impl(), "O")


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)