Повторный запрос аутентификации gss ошибка

What does it mean by saying ‘duplicate’ ? How to troubleshoot this?

guest@www:~$ klist
Ticket cache: FILE:/tmp/krb5cc_1000
Default principal: user/admin@SOHONET

Valid starting       Expires              Service principal
12/11/2015 07:37:08  12/11/2015 17:37:08  krbtgt/SOHONET@SOHONET
        renew until 12/12/2015 07:37:05
12/11/2015 07:37:10  12/11/2015 17:37:08  postgres/pghost.sohonet@
        renew until 12/12/2015 07:37:05
12/11/2015 07:37:10  12/11/2015 17:37:08  postgres/pghost.sohonet@SOHONET
        renew until 12/12/2015 07:37:05
guest@www:~$ VERBOSITY=verbose psql -h pghost -d sqlpocket postgres/pghost.sohonet@SOHONET -l
psql: duplicate GSS authentication request
guest@www:~$


2015-12-11 09:03:22 UTC FATAL:  XX000: accepting GSS security context failed
2015-12-11 09:03:22 UTC DETAIL:  Unspecified GSS failure.  Minor code may provide more information: Permission denied
2015-12-11 09:03:22 UTC LOCATION:  pg_GSS_error, auth.c:988
2015-12-11 09:03:22 UTC FATAL:  28000: GSSAPI authentication failed for user "postgres/pghost.sohonet@SOHONET"
2015-12-11 09:03:22 UTC LOCATION:  auth_failed, auth.c:302

asked Dec 11, 2015 at 9:14

user319773's user avatar

I have seen this error when the server side user does not match the user I am trying to log in as. In your case you are trying to log in as postgres/pghost.sohonet@SOHONET while your TGT is for user/admin@SOHONET.

postgres/pghost.sohonet is the service principal, it is not the user you should authenticate as. Try logging in as user/admin instead, and make sure the user or an appropriate mapping exists on the server side.

answered Jan 24, 2016 at 23:53

chutz's user avatar

chutzchutz

7,7881 gold badge29 silver badges58 bronze badges

Я видел эту ошибку, когда пользователь на стороне сервера не совпадает с пользователем, в которого я пытаюсь войти. В вашем случае вы пытаетесь войти как postgres/[email protected] в то время как ваш TGT для user/[email protected],

postgres/pghost.sohonet является субъектом службы, а не тем пользователем, которого вы должны аутентифицировать. Попробуйте войти как user/admin вместо этого и убедитесь, что пользователь или соответствующее сопоставление существует на стороне сервера.

Clear auth context correctly when re-connecting after failed auth attempt.

If authentication over an SSL connection fails, with sslmode=prefer,
libpq will reconnect without SSL and retry. However, we did not clear
the variables related to GSS, SSPI, and SASL authentication state, when
reconnecting. Because of that, the second authentication attempt would
always fail with a «duplicate GSS/SASL authentication request» error.
pg_SSPI_startup did not check for duplicate authentication requests like
the corresponding GSS and SASL functions, so with SSPI, you would leak
some memory instead.

Another way this could manifest itself, on version 10, is if you list
multiple hostnames in the «host» parameter. If the first server requests
Kerberos or SCRAM authentication, but it fails, the attempts to connect to
the other servers will also fail with «duplicate authentication request»
errors.

To fix, move the clearing of authentication state from closePGconn to
pgDropConnection, so that it is cleared also when re-connecting.

Patch by Michael Paquier, with some kibitzing by me.

Backpatch down to 9.3. 9.2 has the same bug, but the code around closing
the connection is somewhat different, so that this patch doesn’t apply.
To fix this in 9.2, I think we would need to back-port commit 210eb9b743
first, and then apply this patch. However, given that we only bumped into
this in our own testing, we haven’t heard any reports from users about
this, and that 9.2 will be end-of-lifed in a couple of months anyway, it
doesn’t seem worth the risk and trouble.

Discussion: https://www.postgresql.org/message-id/CAB7nPqRuOUm0MyJaUy9L3eXYJU3AKCZ-0-03=-aDTZJGV4GyWw@mail.gmail.com

Branch
——
REL9_6_STABLE

Details
——-
https://git.postgresql.org/pg/commitdiff/f44c609ea014fc642431bb5b0adbb120033f8cb1

Modified Files
—————
src/interfaces/libpq/fe-auth.c | 7 +++-
src/interfaces/libpq/fe-connect.c | 76 +++++++++++++++++++++——————
2 files changed, 47 insertions(+), 36 deletions(-)


1

1

Добрый день!

Написал небольшой сайт на apache2.54 (debian) с аутентификацией в домене на 2012-м с помощью keytab-файла , и все работало штатно, но через месяц что-то с нашем царстве-королевстве произошло, кто что настроил, не знаю, но теперь при обращении к сайту на защищенный контент при вводе корректных учетных данных происходит повторный запрос, после чего страницы открываются (конечно, до закрытия браузера).
В логе апача
gss_accept_sec_context() failed: An unsupported mechanism was requested (, Unknown error)

Выяснилось, что теперь браузер вначале пытается авторизоваться по NTLM, а при повторной попытке, видимо, использует kerberos.
Причем это только на хостах с Windows, они в домене. В линукс-хостах все нормально.

Файл конфига апача стандартный, по-умолчанию

Конфиг sites-enabled

            ErrorLog ${APACHE_LOG_DIR}/error.log
            CustomLog ${APACHE_LOG_DIR}/access.log combined

            SSLEngine on
            SSLCertificateFile      /etc/ssl/certs/_***.crt
            SSLCertificateKeyFile /etc/ssl/private/***.key

            SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt

            <FilesMatch ".(cgi|shtml|phtml|php)$">
                            SSLOptions +StdEnvVars
            </FilesMatch>
            <Directory /usr/lib/cgi-bin>
                            SSLOptions +StdEnvVars
            </Directory>

<Directory /var/www/html/site>
    AuthType Kerberos
    KrbAuthRealms DMZ.LOCAL
    KrbServiceName HTTP/***.dmz.local@DMZ.LOCAL
    Krb5Keytab /etc/apache2/***.keytab
    KrbMethodNegotiate on
    KrbMethodK5Passwd on
    require valid-user
    KrbSaveCredentials on
</Directory>
    </VirtualHost>

При создании кейтаб-файла было указано все тоже стандартно.
Где собака порылась, что можно предпринять со стороны веб-сервера?

# ru.po # LIBPQ Translated Messages into the Russian Language (UTF-8) # # Copyright (c) 2001-2004 Serguei A. Mokhov, mokhov@cs.concordia.ca # Distributed under the same licensing terms as PostgreSQL itself. # # pgtranslation Id: libpq.po,v 1.4 2010/12/07 21:22:21 petere Exp $ # # ChangeLog: # — November, 2010: Updates for PostgreSQL 9 by Andrey Sudnik <sudnikand@yandex.ru> # — January, 2005: Corrections and improvements by Oleg Bartunov <oleg@sai.msu.su> # — March 27 — November 1, 2004: Updates for 8.0; <mokhov@cs.concordia.ca> # — July 24 — October 5, 2003: Updates for 7.4.*; <mokhov@cs.concordia.ca> # — Januray 2, 2002: Completed SSL translation, Serguei A. Mokhov <mokhov@cs.concordia.ca> # — October 12, 2002: Post-7.3beta2 fuzzy translation fixes, Serguei A. Mokhov <mokhov@cs.concordia.ca> # — September 7, 2002: Complete post-7.3beta1 Translation, Serguei A. Mokhov <mokhov@cs.concordia.ca> # — August 2001 — August 2002: Initial translation and maintenance, Serguei A. Mokhov <mokhov@cs.concordia.ca> # msgid «» msgstr «» «Project-Id-Version: PostgreSQL 9 currentn« «Report-Msgid-Bugs-To: pgsql-bugs@postgresql.orgn« «POT-Creation-Date: 2010-11-29 18:43+0000n« «PO-Revision-Date: 2010-11-30 20:14+0600n« «Last-Translator: Andrey Sudnik <sudnikand@yandex.ru>n« «Language-Team: pgsql-rusn« «Language: n« «MIME-Version: 1.0n« «Content-Type: text/plain; charset=utf-8n« «Content-Transfer-Encoding: 8bitn« «X-Poedit-Language: Russiann« «X-Poedit-Country: RUSSIAN FEDERATIONn« «X-Poedit-SourceCharset: utf-8n« #: fe-auth.c:212 #: fe-auth.c:432 #: fe-auth.c:659 msgid «host name must be specifiedn» msgstr «должно быть указано имя хостаn» #: fe-auth.c:242 #, c-format msgid «could not set socket to blocking mode: %sn» msgstr «не удалось установить сокет в блокирующий режим: %sn» #: fe-auth.c:260 #: fe-auth.c:264 #, c-format msgid «Kerberos 5 authentication rejected: %*sn» msgstr «аутентификация Kerberos 5 отклонена: %*sn» #: fe-auth.c:290 #, c-format msgid «could not restore non-blocking mode on socket: %sn» msgstr «не удалось восстановить неблокирующий режим для сокета: %sn» #: fe-auth.c:403 msgid «GSSAPI continuation error» msgstr «GSSAPI ошибка возобновления» #: fe-auth.c:439 msgid «duplicate GSS authentication requestn» msgstr «повторный запрос аутентификации GSSn» #: fe-auth.c:459 msgid «GSSAPI name import error» msgstr «GSSAPI ошибка импорта имени» #: fe-auth.c:545 msgid «SSPI continuation error» msgstr «SSPI ошибка возобновления» #: fe-auth.c:556 #: fe-auth.c:630 #: fe-auth.c:665 #: fe-auth.c:762 #: fe-connect.c:1970 #: fe-connect.c:3369 #: fe-connect.c:3586 #: fe-connect.c:4002 #: fe-connect.c:4011 #: fe-connect.c:4148 #: fe-connect.c:4194 #: fe-connect.c:4212 #: fe-connect.c:4291 #: fe-connect.c:4361 #: fe-connect.c:4407 #: fe-connect.c:4425 #: fe-exec.c:3121 #: fe-exec.c:3286 #: fe-lobj.c:696 #: fe-protocol2.c:1027 #: fe-protocol3.c:1425 msgid «out of memoryn» msgstr «недостаточно памятиn» #: fe-auth.c:645 msgid «could not acquire SSPI credentials» msgstr «не удалось получить SSPI удостоверение» #: fe-auth.c:738 msgid «SCM_CRED authentication method not supportedn» msgstr «аутентификация SCM_CRED не поддерживаетсяn» #: fe-auth.c:812 msgid «Kerberos 4 authentication not supportedn» msgstr «аутентификация Kerberos 4 не поддерживаетсяn» #: fe-auth.c:828 msgid «Kerberos 5 authentication not supportedn» msgstr «аутентификация Kerberos 5 не поддерживаетсяn» #: fe-auth.c:895 msgid «GSSAPI authentication not supportedn» msgstr «аутентификация GSSAPI не поддерживаетсяn» #: fe-auth.c:919 msgid «SSPI authentication not supportedn» msgstr «аутентификация SSPI не поддерживаетсяn» #: fe-auth.c:926 msgid «Crypt authentication not supportedn» msgstr «Шифрованая аутентификация не поддерживаетсяn» #: fe-auth.c:953 #, c-format msgid «authentication method %u not supportedn» msgstr «метод аутентификации %u не поддерживаетсяn» #: fe-connect.c:759 #, c-format msgid «invalid sslmode value: «%s« msgstr «неверное значение sslmode: «%s« #: fe-connect.c:780 #, c-format msgid «sslmode value «%s« invalid when SSL support is not compiled inn» msgstr «значение sslmode «%s« неверно, если поддержка SSL не скомпилированаn» #: fe-connect.c:963 #, c-format msgid «could not set socket to TCP no delay mode: %sn» msgstr «не удалось установить сокет в режим TCP передачи без задержки: %sn» #: fe-connect.c:993 #, c-format msgid «» «could not connect to server: %sn» «tIs the server running locally and acceptingn» «tconnections on Unix domain socket «%s«?n» msgstr «» «не удалось соединиться с сервером: %sn» «tРаботает ли сервер локально и принимаетn» «tсоединения через сокет Unix-домена «%s«?n» #: fe-connect.c:1037 #, c-format msgid «» «could not connect to server: %sn» «tIs the server running on host «%s«%s%s%s and acceptingn» «tTCP/IP connections on port %s?n» msgstr «» «не удалось подсоединиться к серверу: %sn» «tРаботает ли сервер на хосте «%s«%s%s%s и принимает лиn» «tTCP/IP соединения по порту %s?n» #: fe-connect.c:1096 #, c-format msgid «setsockopt(TCP_KEEPIDLE) failed: %sn» msgstr «setsockopt(TCP_KEEPIDLE) не удался: %sn» #: fe-connect.c:1109 #, c-format msgid «setsockopt(TCP_KEEPALIVE) failed: %sn» msgstr «setsockopt(TCP_KEEPALIVE) не удался: %sn» #: fe-connect.c:1141 #, c-format msgid «setsockopt(TCP_KEEPINTVL) failed: %sn» msgstr «setsockopt(TCP_KEEPINTVL) не удался: %sn» #: fe-connect.c:1173 #, c-format msgid «setsockopt(TCP_KEEPCNT) failed: %sn» msgstr «setsockopt(TCP_KEEPCNT) не удался: %sn» #: fe-connect.c:1222 #, c-format msgid «WSAIoctl(SIO_KEEPALIVE_VALS) failed: %uin» msgstr «WSAIoctl(SIO_KEEPALIVE_VALS) потерпел неудачу: %uin» #: fe-connect.c:1274 #, c-format msgid «invalid port number: «%s« msgstr «неверный номер порта: «%s« #: fe-connect.c:1317 #, c-format msgid «could not translate host name «%s« to address: %sn» msgstr «не удалось преобразовать имя хоста «%s« в адрес: %sn» #: fe-connect.c:1321 #, c-format msgid «could not translate Unix-domain socket path «%s« to address: %sn» msgstr «не удалось преобразовать название директории сокетов UNIX-домена «%s« в адрес: %sn» #: fe-connect.c:1531 msgid «invalid connection state, probably indicative of memory corruptionn» msgstr «неверное состояние соединения, возможный указатель на нарушение целостности памятиn» #: fe-connect.c:1572 #, c-format msgid «could not create socket: %sn» msgstr «не удалось создать сокет: %sn» #: fe-connect.c:1595 #, c-format msgid «could not set socket to non-blocking mode: %sn» msgstr «не удалось установить сокет в неблокирующий режим: %sn» #: fe-connect.c:1607 #, c-format msgid «could not set socket to close-on-exec mode: %sn» msgstr «не удалось установить сокет в режим закрытия-на-выполнение (close-on-exec): %sn» #: fe-connect.c:1625 msgid «keepalives parameter must be an integern» msgstr «keepalives параметр должен быть целым числомn» #: fe-connect.c:1638 #, c-format msgid «setsockopt(SO_KEEPALIVE) failed: %sn» msgstr «setsockopt(SO_KEEPALIVE) не удался: %sn» #: fe-connect.c:1779 #, c-format msgid «could not get socket error status: %sn» msgstr «не удалось получить статус ошибки сокета: %sn» #: fe-connect.c:1817 #, c-format msgid «could not get client address from socket: %sn» msgstr «не удалось получить адрес клиента из сокета: %sn» #: fe-connect.c:1849 #: fe-connect.c:1863 #: fe-connect.c:1875 #, c-format msgid «could not get peer credentials: %sn» msgstr «не удалось получить удостоверение peer-a: %sn» #: fe-connect.c:1883 #, c-format msgid «could not get effective UID from peer credentials: %sn» msgstr «не удалось получить эффективный UID из удостоверения peer-а: %sn» #: fe-connect.c:1898 #, c-format msgid «local user with ID %d does not existn» msgstr «локальный пользователь с ID %d не существуетn» #: fe-connect.c:1906 #, c-format msgid «requirepeer specifies «%s«, but actual peer user name is «%s« msgstr «requirepeer задан как «%s«, но настоящее имя пользователя peer-а «%s« #: fe-connect.c:1912 msgid «requirepeer parameter is not supported on this platformn» msgstr «параметр requirepeer не поддерживаются на этой платформеn» #: fe-connect.c:1944 #, c-format msgid «could not send SSL negotiation packet: %sn» msgstr «не удалось отправить пакет согласования SSL: %sn» #: fe-connect.c:1983 #, c-format msgid «could not send startup packet: %sn» msgstr «не удалось отправить начальный пакет: %sn» #: fe-connect.c:2050 #: fe-connect.c:2069 msgid «server does not support SSL, but SSL was requiredn» msgstr «сервер не поддерживает SSL, но наличие SSL было необходимоn» #: fe-connect.c:2085 #, c-format msgid «received invalid response to SSL negotiation: %cn» msgstr «получен неверный ответ на согласование по SSL: %cn» #: fe-connect.c:2161 #: fe-connect.c:2194 #, c-format msgid «expected authentication request from server, but received %cn» msgstr «ожидался запрос аутентификации от сервера, но было получено: %cn» #: fe-connect.c:2367 #, c-format msgid «out of memory allocating GSSAPI buffer (%i)» msgstr «недостаточно памяти для аллоцирования GSSAPI буфера (%i)» #: fe-connect.c:2452 msgid «unexpected message from server during startupn» msgstr «неожиданное сообщение от сервера при запускеn» #: fe-connect.c:2548 #, c-format msgid «invalid connection state %d, probably indicative of memory corruptionn» msgstr «неверное состояние соединения %d, возможно, это признак нарушения целостности памятиn» #: fe-connect.c:2977 #: fe-connect.c:3037 #, c-format msgid «PGEventProc «%s« failed during PGEVT_CONNRESET eventn» msgstr «PGEventProc «%s« потерпел неудачу во время события PGEVT_CONNRESETn» #: fe-connect.c:3382 #, c-format msgid «invalid LDAP URL «%s«: scheme must be ldap://n» msgstr «некорректный LDAP URL «%s«: схема должна быть ldap://n» #: fe-connect.c:3397 #, c-format msgid «invalid LDAP URL «%s«: missing distinguished namen» msgstr «не корректный LDAP URL «%s«: отсутствует уникальное имяn» #: fe-connect.c:3408 #: fe-connect.c:3461 #, c-format msgid «invalid LDAP URL «%s«: must have exactly one attributen» msgstr «не корректный LDAP URL «%s«: должен быть только один аттрибутn» #: fe-connect.c:3418 #: fe-connect.c:3475 #, c-format msgid «invalid LDAP URL «%s«: must have search scope (base/one/sub)n» msgstr «не корректный LDAP URL «%s«: должна быть границы поиска (base/one/sub)n» #: fe-connect.c:3429 #, c-format msgid «invalid LDAP URL «%s«: no filtern» msgstr «не корректный LDAP URL «%s«: нет фильтраn» #: fe-connect.c:3450 #, c-format msgid «invalid LDAP URL «%s«: invalid port numbern» msgstr «не корректный LDAP URL «%s«: неверный номер портаn» #: fe-connect.c:3484 msgid «could not create LDAP structuren» msgstr «не удалось создать LDAP структуруn» #: fe-connect.c:3526 #, c-format msgid «lookup on LDAP server failed: %sn» msgstr «поиск на LDAP сервере закончился неудачно: %sn» #: fe-connect.c:3537 msgid «more than one entry found on LDAP lookupn» msgstr «более одного вхождения обнаружено при LDAP поискеn» #: fe-connect.c:3538 #: fe-connect.c:3550 msgid «no entry found on LDAP lookupn» msgstr «ни одного вхождения не обнаружено при LDAP поискеn» #: fe-connect.c:3561 #: fe-connect.c:3574 msgid «attribute has no values on LDAP lookupn» msgstr «аттрибут не имеет значения при LDAP поискеn» #: fe-connect.c:3625 #: fe-connect.c:3643 #: fe-connect.c:4050 #, c-format msgid «missing «=« after «%s« in connection info stringn» msgstr «отсутствует «=« после «%s« в строке соединенияn» #: fe-connect.c:3706 #: fe-connect.c:4132 #: fe-connect.c:4316 #, c-format msgid «invalid connection option «%s« msgstr «неверный параметр соединения «%s« #: fe-connect.c:3719 #: fe-connect.c:4099 msgid «unterminated quoted string in connection info stringn» msgstr «неоконченная строка (не хватает кавычки) в строке соединенияn» #: fe-connect.c:3758 msgid «could not get home directory to locate service definition file» msgstr «не удалось получить домашнюю директорию, чтобы найти файл со служебными определениями» #: fe-connect.c:3791 #, c-format msgid «definition of service «%s« not foundn» msgstr «определение сервиса «%s« не найденоn» #: fe-connect.c:3814 #, c-format msgid «service file «%s« not foundn» msgstr «служебный файл «%s« не найденn» #: fe-connect.c:3827 #, c-format msgid «line %d too long in service file «%s« msgstr «строка %d слишком длинная в служебном файле «%s« #: fe-connect.c:3898 #: fe-connect.c:3925 #, c-format msgid «syntax error in service file «%s«, line %dn» msgstr «синтаксическая ошибка в служебном файле «%s«, строка %dn» #: fe-connect.c:4592 msgid «connection pointer is NULLn» msgstr «указатель соединения является NULLn» #: fe-connect.c:4865 #, c-format msgid «WARNING: password file «%s« is not a plain filen» msgstr «ВНИМАНИЕ: файл паролей «%s« не обычный текстовый файлn» #: fe-connect.c:4874 #, c-format msgid «WARNING: password file «%s« has group or world access; permissions should be u=rw (0600) or lessn» msgstr «ВНИМАНИЕ: файл с паролями «%s« имеет права на чтение для всех или для группы; права должны быть u=rw (0600) или меньшеn» #: fe-connect.c:4962 #, c-format msgid «password retrieved from file «%s« msgstr «пароль получен из файла «%s« #: fe-exec.c:827 msgid «NOTICE» msgstr «NOTICE» #: fe-exec.c:1014 #: fe-exec.c:1071 #: fe-exec.c:1111 msgid «command string is a null pointern» msgstr «командная строка является нулевым указателемn» #: fe-exec.c:1104 #: fe-exec.c:1199 msgid «statement name is a null pointern» msgstr «имя команды является нулевым указателемn» #: fe-exec.c:1119 #: fe-exec.c:1273 #: fe-exec.c:1928 #: fe-exec.c:2125 msgid «function requires at least protocol version 3.0n» msgstr «функция требует как минимум версию протокола 3.0n» #: fe-exec.c:1230 msgid «no connection to the servern» msgstr «нет соединения с серверомn» #: fe-exec.c:1237 msgid «another command is already in progressn» msgstr «другая команда уже выполняетсяn» #: fe-exec.c:1349 msgid «length must be given for binary parametern» msgstr «для бинарного параметра должа быть указана длинаn» #: fe-exec.c:1596 #, c-format msgid «unexpected asyncStatus: %dn» msgstr «неожиданный asyncStatus: %dn» #: fe-exec.c:1616 #, c-format msgid «PGEventProc «%s« failed during PGEVT_RESULTCREATE eventn» msgstr «PGEventProc «%s« порушился во время события PGEVT_RESULTCREATEn» #: fe-exec.c:1746 msgid «COPY terminated by new PQexec» msgstr «COPY прекращена новой PQexec» #: fe-exec.c:1754 msgid «COPY IN state must be terminated firstn» msgstr «Сначала, состояние COPY IN должно завершитьсяn» #: fe-exec.c:1774 msgid «COPY OUT state must be terminated firstn» msgstr «Сначала, состояние COPY OUT должно завершитьсяn» #: fe-exec.c:2016 #: fe-exec.c:2082 #: fe-exec.c:2167 #: fe-protocol2.c:1172 #: fe-protocol3.c:1561 msgid «no COPY in progressn» msgstr «COPY не выполняетсяn» #: fe-exec.c:2359 msgid «connection in wrong staten» msgstr «соединение в неправильном состоянииn» #: fe-exec.c:2390 msgid «invalid ExecStatusType code» msgstr «неверный код ExecStatusType» #: fe-exec.c:2454 #: fe-exec.c:2477 #, c-format msgid «column number %d is out of range 0..%d» msgstr «номер колонки %d вне диапазона 0..%d» #: fe-exec.c:2470 #, c-format msgid «row number %d is out of range 0..%d» msgstr «номер записи %d вне диапазона 0..%d» #: fe-exec.c:2492 #, c-format msgid «parameter number %d is out of range 0..%d» msgstr «номер параметра %d вне диапазона 0..%d» #: fe-exec.c:2780 #, c-format msgid «could not interpret result from server: %s» msgstr «не в состоянии интерпретировать ответ сервера: %s» #: fe-exec.c:3019 #: fe-exec.c:3103 msgid «incomplete multibyte charactern» msgstr «неполный мультибайтовый символn» #: fe-lobj.c:152 msgid «cannot determine OID of function lo_truncaten» msgstr «не в состоянии определить OID функции lo_truncaten» #: fe-lobj.c:380 msgid «cannot determine OID of function lo_createn» msgstr «не в состоянии определить OID функции lo_createn» #: fe-lobj.c:525 #: fe-lobj.c:624 #, c-format msgid «could not open file «%s«: %sn» msgstr «не в состоянии открыть файл «%s«: %sn» #: fe-lobj.c:575 #, c-format msgid «could not read from file «%s«: %sn» msgstr «не в состоянии произвести чтение из файла «%s«: %sn» #: fe-lobj.c:639 #: fe-lobj.c:663 #, c-format msgid «could not write to file «%s«: %sn» msgstr «не в состоянии призвести запись в файл «%s«: %sn» #: fe-lobj.c:744 msgid «query to initialize large object functions did not return datan» msgstr «запрос об инициализации функций для больших объектов (LOs) не вернул данныхn» #: fe-lobj.c:785 msgid «cannot determine OID of function lo_openn» msgstr «не в состоянии определить OID функции lo_openn» #: fe-lobj.c:792 msgid «cannot determine OID of function lo_closen» msgstr «не в состоянии определить OID функции lo_closen» #: fe-lobj.c:799 msgid «cannot determine OID of function lo_creatn» msgstr «не в состоянии определить OID функции lo_creatn» #: fe-lobj.c:806 msgid «cannot determine OID of function lo_unlinkn» msgstr «не в состоянии определить OID функции lo_unlinkn» #: fe-lobj.c:813 msgid «cannot determine OID of function lo_lseekn» msgstr «не в состоянии определить OID функции lo_lseekn» #: fe-lobj.c:820 msgid «cannot determine OID of function lo_telln» msgstr «не в состоянии определить OID функции lo_telln» #: fe-lobj.c:827 msgid «cannot determine OID of function loreadn» msgstr «не в состоянии определить OID функции loreadn» #: fe-lobj.c:834 msgid «cannot determine OID of function lowriten» msgstr «не в состоянии определить OID функции lowriten» #: fe-misc.c:262 #, c-format msgid «integer of size %lu not supported by pqGetInt» msgstr «тип integer длиной %lu байт не поддерживается функцией pqGetInt» #: fe-misc.c:298 #, c-format msgid «integer of size %lu not supported by pqPutInt» msgstr «тип integer длиной %lu байт не поддерживается функцией pqPutInt» #: fe-misc.c:578 #: fe-misc.c:780 msgid «connection not openn» msgstr «соединение не открытоn» #: fe-misc.c:643 #: fe-misc.c:733 #, c-format msgid «could not receive data from server: %sn» msgstr «ошибка при получении данных с сервера: %sn» #: fe-misc.c:750 #: fe-misc.c:828 msgid «» «server closed the connection unexpectedlyn» «tThis probably means the server terminated abnormallyn» «tbefore or while processing the request.n» msgstr «» «сервер неожиданно закрыл соединениеn» «tСкорее всего это означает, что сервер завершил работу со сбоемn» «tдо или в процессе выполнения запроса.n» #: fe-misc.c:845 #, c-format msgid «could not send data to server: %sn» msgstr «не удалось послать данные серверу: %sn» #: fe-misc.c:964 msgid «timeout expiredn» msgstr «интервал ожидания закончилсяn» #: fe-misc.c:1009 msgid «socket not openn» msgstr «сокет не открытn» #: fe-misc.c:1032 #, c-format msgid «select() failed: %sn» msgstr «select() не удался: %sn» #: fe-protocol2.c:89 #, c-format msgid «invalid setenv state %c, probably indicative of memory corruptionn» msgstr «неверное состояние setenv %c, возможный указатель на нарушение целостности памятиn» #: fe-protocol2.c:330 #, c-format msgid «invalid state %c, probably indicative of memory corruptionn» msgstr «неверное состояние %c, возможный указатель на нарушение целостности памятиn» #: fe-protocol2.c:419 #: fe-protocol3.c:186 #, c-format msgid «message type 0x%02x arrived from server while idle» msgstr «сообщение типа 0x%02x прибыло от сервера во время простоя» #: fe-protocol2.c:462 #, c-format msgid «unexpected character %c following empty query response («I« message)» msgstr «неожиданный символ %c вслед за пустым ответом (сообщение «I« #: fe-protocol2.c:516 msgid «server sent data («D« message) without prior row description («T« message)» msgstr «сервер отправил данные (сообщение «D«) без предварительного строки описания (сообщение «T« #: fe-protocol2.c:532 msgid «server sent binary data («B« message) without prior row description («T« message)» msgstr «сервер отправил двоичные данные (сообщение «B«) без предварительного строки описания (сообщение «T« #: fe-protocol2.c:547 #: fe-protocol3.c:382 #, c-format msgid «unexpected response from server; first received character was «%c« msgstr «неожиданный ответ сервера; первый полученный символ: «%c« #: fe-protocol2.c:768 #: fe-protocol3.c:701 msgid «out of memory for query resultn» msgstr «недостаточно памяти для результата запросаn» #: fe-protocol2.c:1215 #: fe-protocol3.c:1629 #, c-format msgid «%s» msgstr «%s» #: fe-protocol2.c:1227 msgid «lost synchronization with server, resetting connection» msgstr «потеряна синхронизация с сервером; переустановка соединения» #: fe-protocol2.c:1361 #: fe-protocol2.c:1393 #: fe-protocol3.c:1832 #, c-format msgid «protocol error: id=0x%xn» msgstr «ошибка протокола: id=0x%xn» #: fe-protocol3.c:344 msgid «server sent data («D« message) without prior row description («T« message)n» msgstr «сервер отправил данные (сообщение «D«) без предварительного строки описания (сообщение «T«)n» #: fe-protocol3.c:403 #, c-format msgid «message contents do not agree with length in message type «%c« msgstr «содержимое сообщения не согласуется с длиной в сообщении типа «%c« #: fe-protocol3.c:424 #, c-format msgid «lost synchronization with server: got message type «%c«, length %dn» msgstr «потеряна синхронизация с сервером: получено сообщение типа «%c«, длина %dn» #: fe-protocol3.c:646 msgid «unexpected field count in «D« messagen» msgstr «неожиданное число полей в собщении «D« #. translator: %s represents a digit string #: fe-protocol3.c:792 #: fe-protocol3.c:811 #, c-format msgid » at character %s» msgstr » у символа %s» #: fe-protocol3.c:824 #, c-format msgid «DETAIL: %sn» msgstr «ПОДРОБНО: %sn» #: fe-protocol3.c:827 #, c-format msgid «HINT: %sn» msgstr «ПОДСКАЗКА: %sn» #: fe-protocol3.c:830 #, c-format msgid «QUERY: %sn» msgstr «ЗАПРОС: %sn» #: fe-protocol3.c:833 #, c-format msgid «CONTEXT: %sn» msgstr «КОНТЕКСТ: %sn» #: fe-protocol3.c:845 msgid «LOCATION: « msgstr «РАСПОЛОЖЕНИЕ: « #: fe-protocol3.c:847 #, c-format msgid «%s, « msgstr «%s, « #: fe-protocol3.c:849 #, c-format msgid «%s:%s» msgstr «%s:%s» #: fe-protocol3.c:1073 #, c-format msgid «LINE %d: « msgstr «СТРОКА %d:» #: fe-protocol3.c:1457 msgid «PQgetline: not doing text COPY OUTn» msgstr «PQgetline: не производится текстовый COPY OUTn» #: fe-secure.c:265 #, c-format msgid «could not establish SSL connection: %sn» msgstr «не удалось установить SSL-соединение: %sn» #: fe-secure.c:349 #: fe-secure.c:436 #: fe-secure.c:1162 #, c-format msgid «SSL SYSCALL error: %sn» msgstr «ошибка SSL SYSCALL: %sn» #: fe-secure.c:355 #: fe-secure.c:442 #: fe-secure.c:1166 msgid «SSL SYSCALL error: EOF detectedn» msgstr «ошибка SSL SYSCALL: обнаружен конец файла (EOF)n» #: fe-secure.c:367 #: fe-secure.c:453 #: fe-secure.c:1175 #, c-format msgid «SSL error: %sn» msgstr «ошибка SSL: %sn» #: fe-secure.c:377 #: fe-secure.c:463 #: fe-secure.c:1184 #, c-format msgid «unrecognized SSL error code: %dn» msgstr «нераспознанный код ошибки SSL: %dn» #: fe-secure.c:601 msgid «host name must be specified for a verified SSL connectionn» msgstr «для заверенного SSL соединения должно быть указано имя хостаn» #: fe-secure.c:620 #, c-format msgid «server common name «%s« does not match host name «%s« msgstr «общее имя сервера «%s« не совпадает с именем хоста «%s« #: fe-secure.c:752 #, c-format msgid «could not create SSL context: %sn» msgstr «не удалось создать контекст SSL: %sn» #: fe-secure.c:843 msgid «could not get home directory to locate client certificate filesn» msgstr «не удалось получить домашнюю директорию, чтобы найти файлы с клиентскими сертификатамиn» #: fe-secure.c:868 #, c-format msgid «could not open certificate file «%s«: %sn» msgstr «не в состоянии открыть файл сертификата «%s«: %sn» #: fe-secure.c:893 #: fe-secure.c:903 #, c-format msgid «could not read certificate file «%s«: %sn» msgstr «не в состоянии считать файл сертификата «%s«: %sn» #: fe-secure.c:940 #, c-format msgid «could not load SSL engine «%s«: %sn» msgstr «не удаётся загрузить движок SSL «%s«: %sn» #: fe-secure.c:952 #, c-format msgid «could not initialize SSL engine «%s«: %sn» msgstr «не удаётся инициализировать движок SSL «%s«: %sn» #: fe-secure.c:968 #, c-format msgid «could not read private SSL key «%s« from engine «%s«: %sn» msgstr «не удалось прочитать приватный SSL ключ «%s« из движка «%s«: %sn» #: fe-secure.c:982 #, c-format msgid «could not load private SSL key «%s« from engine «%s«: %sn» msgstr «не удалось загрузить приватный SSL ключ «%s« из движка «%s«: %sn» #: fe-secure.c:1017 #, c-format msgid «certificate present, but not private key file «%s« msgstr «сертификат присутствует, но нет файла с личным ключом «%s« #: fe-secure.c:1025 #, c-format msgid «private key file «%s« has group or world access; permissions should be u=rw (0600) or lessn» msgstr «файл приватного ключа «%s« имеет права на чтение для всех или для группы; права должны быть u=rw (0600) или меньшеn» #: fe-secure.c:1036 #, c-format msgid «could not load private key file «%s«: %sn» msgstr «не удалось загрузить файл приватного ключа «%s«: %sn» #: fe-secure.c:1050 #, c-format msgid «certificate does not match private key file «%s«: %sn» msgstr «сертификат не совпадает с файлом личного ключа «%s«: %sn» #: fe-secure.c:1075 #, c-format msgid «could not read root certificate file «%s«: %sn» msgstr «не удалось прочитать файл корневых сертификатов «%s«: %sn» #: fe-secure.c:1099 #, c-format msgid «SSL library does not support CRL certificates (file «%s«)n» msgstr «Библиотека SSL не поддерживает CRL сертификаты (файл «%s«)n» #: fe-secure.c:1120 #, c-format msgid «» «root certificate file «%s« does not existn» «Either provide the file or change sslmode to disable server certificate verification.n» msgstr «» «корневой файл сертификата «%s« не существуетn» «Предоставьте файл с сертификатом или измените sslmode, чтобы отключить проверку сертификата.n» #: fe-secure.c:1203 #, c-format msgid «certificate could not be obtained: %sn» msgstr «не удалось получить сертификат: %sn» #: fe-secure.c:1231 msgid «SSL certificate’s common name contains embedded nulln» msgstr «Общее имя SSL сертификата содержит вставленный nulln» #: fe-secure.c:1307 msgid «no SSL error reported» msgstr «нераспознанный код ошибки SSL» #: fe-secure.c:1316 #, c-format msgid «SSL error code %lu» msgstr «ошибка SSL: %lu» #~ msgid «error querying socket: %sn» #~ msgstr «ошибка при запросе сокета: %sn» #~ msgid «could not get information about host «%s»: %sn» #~ msgstr «не удалось получить информацию о хосте «%s»: %sn» #~ msgid «unsupported protocoln» #~ msgstr «протокол не поддерживаетсяn» #~ msgid «server common name «%s» does not resolve to %ld.%ld.%ld.%ldn» #~ msgstr «имя сервера «%s» не транслируется в %ld.%ld.%ld.%ldn» #~ msgid «could not get user informationn» #~ msgstr «не удалось получить информацию о пользователеn» #~ msgid «invalid value of PGSSLKEY environment variablen» #~ msgstr «неверное значение для переменной окружения PGSSLKEYn» #~ msgid «private key file «%s» has wrong permissionsn» #~ msgstr «неправильные права доступа к файла личного ключа «%s»n» #~ msgid «could not open private key file «%s»: %sn» #~ msgstr «не удалось открыть файл личного ключа «%s»: %sn» #~ msgid «private key file «%s» changed during executionn» #~ msgstr «личный ключ «%s» изменился во время исполненияn» #~ msgid «certificate could not be validated: %sn» #~ msgstr «сертификат не может быть проверен: %sn» #~ msgid «Kerberos 4 error: %sn» #~ msgstr «ошибка Kerberos 4: %sn» #~ msgid «Kerberos 4 authentication failedn» #~ msgstr «аутентификация Kerberos 4 не удаласьn» #~ msgid «Kerberos 5 authentication failedn» #~ msgstr «аутентификация Kerberos 5 не удаласьn» #~ msgid «invalid authentication service name «%s», ignoredn» #~ msgstr «неверное имя сервиса аутентификации «%s», игнорируетсяn» #~ msgid «fe_getauthname: invalid authentication system: %dn» #~ msgstr «fe_getauthname: неверная система аутентификации: %dn» #~ msgid «could not receive server response to SSL negotiation packet: %sn» #~ msgstr «не был получен ответ сервера на пакет согласования SSL: %sn» #~ msgid «could not create large object for file «%s»n» #~ msgstr «не в состоянии создать большой объект (LO) для файла «%s»n» #~ msgid «could not open large object %un» #~ msgstr «не в состоянии открыть большой объект (LO) %un» #~ msgid «error while reading file «%s»n» #~ msgstr «ошибка при чтении файла «%s»n» #~ msgid «error while writing to file «%s»n» #~ msgstr «ошибка при записи в файл «%s»n»

Неформальное изложение возможностей Kerberos

Система Kerberos предназначена для решения следующей задачи. Имеется открытая (незащищенная) сеть, в узлах которой сосредоточены субъекты — пользователи, а также клиентские и серверные программные системы. Каждый субъект обладает секретным ключом. Чтобы субъект C мог доказать свою подлинность субъекту S (без этого S не станет обслуживать C), он должен не только назвать себя, но и продемонстрировать знание своего секретного ключа. C не может просто послать S свой секретный ключ, во-первых, потому, что сеть открыта (доступна для пассивного и активного прослушивания), а, во-вторых, потому, что S не знает (и не должен) знать секретный ключ C. Требуется менее прямолинейный способ демонстрации знания секретного ключа.

Система Kerberos представляет собой надежную третью сторону (то есть сторону, которой доверяют все), владеющую секретными ключами обслуживаемых субъектов и помогающую им в попарной проверке подлинности.

Чтобы с помощью Kerberos получить доступ к S (обычно это сервер), C (как правило — клиент) посылает Kerberos’у запрос, содержащий сведения о нем (клиенте) и о запрашиваемой услуге. В ответ Kerberos возвращает две порции информации: так называемый билет, зашифрованный секретным ключом сервера, и копию части информации из билета, зашифрованную секретным ключом клиента. Клиент должен расшифровать вторую порцию данных и переслать ее вместе с билетом серверу. Сервер, расшифровав билет, может сравнить его (билета) содержимое с дополнительной информацией, присланной клиентом. Совпадение свидетельствует о том, что клиент смог расшифровать предназначенные ему данные (ведь содержимое билета никому, кроме сервера и Kerberos, недоступно), то есть продемонстрировал знание своего секретного ключа. Значит, клиент — именно тот субъект, за кого себя выдает. Подчеркнем, что секретные ключи в процессе проверки подлинности не передавались по сети (даже в зашифрованном виде) — они только использовались для шифрования. Как организован первоначальный обмен ключами между Kerberos и субъектами и как субъекты хранят свои секретные ключи — вопрос отдельный.

Проиллюстрируем описанную процедуру Рис. 1.

Рисунок 1. Проверка сервером S подлинности клиента C (вариант 1). Здесь: c и s — сведения (например, имя), соответственно, о клиенте и сервере, d1 и d2 — дополнительная (по отношению к билету) информация. Tc.s — билет для клиента C на обслуживание у сервера S, Kc и Ks — секретные ключи клиента и сервера, {info}K — информация info, зашифрованная ключом K.

Изложенный вариант 1 — крайне упрощенная версия реальной процедуры проверки подлинности. Прежде всего, необходимо уточнить структуру пересылаемых запросов и возвращаемых ответов. И билет, и вторая порция информации, предоставляемая со стороны Kerberos, содержат случайный ключ, пригодный для шифрования сообщений, пересылаемых между клиентом и сервером. Этот ключ называется сеансовым и представляет собой общую секретную информацию, разделяемую C и S. Появление подобной общей информации и возможность организации конфиденциального взаимодействия — важный побочный продукт аутентификации средствами Kerberos.

Билет, который выдает Kerberos, имеет ограниченный срок годности. Естественно распространить этот срок и на сеансовый ключ. Когда срок годности истекает, необходимо проведение повторной проверки подлинности. Продолжительность стандартного срока годности зависит от политики безопасности, проводимой организацией. Типичный срок годности — 8 часов.

Вполне вероятно, что клиент C захочет убедиться в подлинности обслуживающего его сервера S. Чтобы это было возможным, клиент шифрует дополнительную информацию, передаваемую серверу, с помощью сеансового ключа. Сервер может узнать сеансовый ключ, только расшифровав билет. Если это случится и сервер вернет клиенту свидетельство того, что он сумел прочитать дополнительную информацию, C вправе считать подлинность сервера S установленной.

Далее, необходимо защитить информацию, пересылаемую по сети, от воспроизведения. Если этого не сделать, злоумышленник сможет послать серверу дубликаты билета и дополнительной информации и успешно выдать себя за «второго C». Стандартный способ защиты от воспроизведения — включение в нее временных штампов и/или так называемых одноразовых номеров, позволяющих удостовериться в «свежести» сообщений и в их неповторяемости (и, более того, в целостности последовательности сообщений). Одноразовые номера позволяют также ассоциировать ответы с предыдущими запросами.

Отобразим упомянутые уточнения на новом рисунке (Рис. 2).

Рисунок 2. Взаимная проверка клиентом C и сервером S подлинности другдруга (вариант 2). Здесь: timeexp — срок годности билета, n — одноразовый номер, Kc.s — сеансовый ключ, ts — временной штамп, ck — контрольная сумма.

Отдельного пояснения заслуживает обозначение s1 в первом запросе. Вообще говоря, клиенту нужен не конкретный сервер, а определенный сервис, о чем он и просит Kerberos. В ответ клиент получает адрес сервера, способного оказать запрашиваемую услугу.

Порции информации в сообщениях 3 и 4, шифруемые сеансовыми ключами, называют аутентификаторами. Они позволяют убедиться в подлинности предъявившего их субъекта. В дальнейшем аутентификатор клиента мы будем обозначать Ac, аутентификатор сервера — As.

Вариант 2 гораздо практичнее варианта 1, однако и он нуждается в уточнении. Естественно предположить, что клиенту понадобятся услуги нескольких серверов. Соответственно, чтобы доказать свою подлинность, клиенту придется несколько раз повторять диалог с Kerberos и использовать свой секретный ключ. К сожалению, долго держать наготове секретный ключ опасно — его могут украсть. Чтобы справиться с указанной проблемой, сервер Kerberos «раздваивается» на сервер начальной аутентификации (AS — Authentication Server) и сервер выдачи билетов (TGS — Ticket Granting Server). Клиент запрашивает у AS по схеме, изображенной на Рис. 2, билет к TGS («билет на получение билетов», «билет на билеты» — TGT, Ticket-Granting Ticket). TGT содержит сеансовый ключ для засекречивания общения между клиентом и сервером выдачи билетов. Билеты к другим серверам клиент получает у TGS на основании «билета на билеты».

В результате схема получения доступа к серверу приобретает вид, изображенный на Рис. 3.

Рисунок 3. Взаимная проверка клиентом C и сервером S подлинности друг друга (вариант 3). Здесь: Ac — аутентификатор клиента.

Таким образом, секретный ключ нужен клиенту только на короткое время для получения «билета на билеты». В дальнейшем используется сеансовый ключ, разделяемый клиентом и сервером выдачи билетов. Компрометация сеансового ключа, имеющего ограниченный срок годности, — вещь существенно менее опасная, чем раскрытие секретного ключа.

Любопытно отметить, что AS, вопреки своему названию, не проверяет подлинности обратившихся к нему субъектов. Билет на билеты может получить кто угодно, в том числе и злоумышленник, но воспользоваться этим билетом он сможет, только если знает секретный ключ субъекта, от имени которого он выступает. Отметим также, что если для программных субъектов (клиентов и серверов) способ хранения секретного ключа не определен, то для пользователей специфицируется алгоритм преобразования пароля в ключ. Иными словами, пользователю достаточно помнить только свой пароль.

Каждый сервер Kerberos обслуживает определенную область управления. До сих пор мы рассматривали случай, когда клиент и сервер находились в пределах одной области и взаимодействовали посредством локального Kerberos. Теперь обратимся к ситуации, когда клиент и сервер зарегистрированы в разных областях.

Чтобы субъекты из разных областей управления могли общаться друг с другом, между областями должно быть заключено соглашение, а серверы Kerberos должны обменяться секретными ключами. (Ключи могут быть разными для различных общающихся пар серверов Kerberos.) Поскольку между областями управления Kerberos существуют стандартные иерархические отношения, каждой области достаточно заключить соглашение и обменяться ключами с родителем и всеми потомками. В принципе возможно заключение соглашения между двумя произвольными областями, субъекты которых активно общаются друг с другом. Рис. 4 иллюстрирует отношения между областями управления.

Рисунок 4. Отношения между областями управления Kerberos.

При наличии договорных отношений локальный сервер выдачи билетов может выдать билет к удаленному TGS, который, в свою очередь, выдаст билет к удаленному серверу. Последовательность обмена сообщениями для этого случая показана на Рис. 5.

Рисунок 5. Взаимная проверка клиентом C и удаленным сервером S-rem подлинности друг друга (вариант 4).

В более общем случае клиенту придется пройти через несколько промежуточных серверов выдачи билетов. Впрочем, поскольку глубина вложенности областей управления обычно невелика (3 — 4), не должен быть длинным и путь до удаленного сервера.

Такова идейная основа механизма аутентификации, принятого в Kerberos. Следует отметить, что, помимо изложенных, сервер Kerberos предоставляет много дополнительных возможностей. Так, на самом деле время жизни билета задается как пара (начальное время, конечное время). В результате можно получать билеты «на потом», например, для пакетных заданий, выполняющихся ночью. Далее, имеется механизм билетов с правом передачи, что позволяет серверам выполнять определенные действия от имени обратившихся к ним клиентов (скажем, серверу печати осуществлять доступ к файлам пользователя). Есть и другие средства, на которых, однако, мы сейчас останавливаться не будем.

На реализацию и использование Kerberos можно смотреть с разных точек зрения. Пользователь видит Kerberos как набор команд (например, kinit — начало Kerberos-сеанса, kdestroy — разрушение Kerberos-билетов и окончание сеанса, klist — выдача текущего списка билетов, kpasswd — смена Kerberos-пароля и т.п.) или не видит его вообще, если соответствующие вызовы встроены в утилиты и команды операционной системы, такие как login, logout, passwd.

Для программиста Kerberos представляет собой набор библиотек, весьма разумно структурированных, так что можно легко заменять разные компоненты, например, криптографические. Две функции основной библиотеки — krb_mk_req и krb_rd_req, позволяют, соответственно, построить аутентификационный запрос к серверу и обработать его. При этом прикладной программист избавляется от рутинных аспектов общения с Kerberos. «Керберизация» приложений, то есть встраивание в них средств проверки подлинности, в значительной степени сводится к добавлению вызовов упомянутых функций, что, естественно, не слишком сложно.

С точки зрения системного администратора Kerberos — это набор административных средств конфигурирования, регистрации субъектов, работы с базой данных секретных ключей.

В последующих разделах Kerberos рассматривается более формально. Основой изложения является официальный документ сообщества Internet — RFC 1510 «The Kerberos Network Authentication Service (V5)».

Флаги, используемые в билетах

Каждый Kerberos-билет содержит набор флагов. Большинство из них запрашивается клиентом перед получением билета. Некоторые флаги автоматические устанавливает и сбрасывает сам Kerberos. Рассмотрение флагов и способов их использования позволяет в полном объеме продемонстрировать аутентификационные возможности сервера Kerberos.

Напомним, что клиент получает билеты, зашифрованные секретными ключами серверов (это может быть сервер выдачи «билетов на билеты» или один из прикладных серверов). Тем самым клиент лишен возможности изменять содержимое билетов. В частности, он не может устанавливать и сбрасывать флаги — эту роль целиком берет на себя Kerberos.

Начальные билеты

Флаг INITIAL указывает на то, что билет выдан сервером начальной аутентификации (AS). Серверы приложений, которым нужно знать секретный ключ пользователя (пример — программа изменения пароля), могут принимать билеты только с установленным флагом INITIAL как свидетельство недавнего использования именно секретного, а не сеансового, ключа.

Два дополнительных флага, PRE-AUTHENT и HW-AUTHENT, могут нести дополнительную информацию о начальной аутентификации, независимо от того, кто выдал данный билет — AS или TGS.

Негодные билеты

Флаг INVALID свидетельствует о том, что билет негоден. Серверы приложений должны отвергать билеты с этим флагом. Обычно флагом INVALID помечаются предварительные билеты, предназначенные для использования в будущем. Чтобы предварительный билет стал годным, его нужно зарегистрировать, направив в TGS запрос с опцией VALIDATE. Регистрация пройдет успешно только после наступления начального времени годности билета. Процедура регистрации позволяет выявлять (и отвергать) украденные предварительные билеты.

Обновляемые билеты

Билеты с длительным сроком годности удобны, но небезопасны, поскольку кража содержащейся в них информации открывает злоумышленнику доступ к соответствующим серверам также на длительное время. С другой стороны, использование краткосрочных билетов заставляет постоянно обращаться к секретному ключу, что представляет еще большую опасность.

Обновляемые билеты позволяют смягчить последствия кражи информации. Они имеют два срока годности — промежуточный и окончательный. Клиент должен периодически, до окончания промежуточного срока, представлять обновляемый билет в TGS с опцией RENEW. В ответ TGS возвращает новый билет с другим сеансовым ключом и более поздним промежуточным сроком годности. Все остальные поля переносятся из старого билета без изменений. Подобная периодическая перерегистрация в принципе позволяет TGS выявлять украденные билеты и отвергать их. В результате потенциальное время жизни нелегальных билетов уменьшается.

Обычно флаг RENEWABLE интерпретируется только TGS, однако некоторые особенно осторожные серверы могут отвергать билеты с этим флагом.

Флаг RENEWABLE устанавливается в билете лишь по явному запросу клиента к серверу начальной аутентификации (AS).

Предварительные билеты

Иногда нужны билеты, которые будут использоваться спустя довольно долгое время после выдачи. Например, от момента порождения пакетного задания до начала выполнения может проходить несколько часов. Поскольку держать годные билеты в пакетной очереди рискованно, Kerberos предлагает механизм предварительных билетов, получаемых в момент порождения задания, но «дремлющих» до момента активации и перерегистрации в TGS.

Флаг MAY-POSTDATE обычно интерпретируется только TGS в «билетах на билеты» и устанавливается лишь по явному запросу клиента к серверу начальной аутентификации (AS). По «билету на билеты» с флагом MAY-POSTDATE TGS выдает билет (к серверу) с флагом POSTDATED. Сервер может проверить, как давно был выдан предварительный билет и, возможно, отказать клиенту в обслуживании. Более того, билет с флагом POSTDATED первоначально содержит и флаг INVALID, так что клиент перед использованием должен перерегистрировать билет в TGS.

Доверенности

Когда возникает необходимость позволить серверу выполнить некоторые действия от имени клиента (например, получить доступ к файлам для их печати), можно воспользоваться имеющимся в Kerberos механизмом доверенностей.

Флаг PROXIABLE, установленный в «билете на билеты» (это происходит по умолчанию), дает право TGS выдать новый билет (но не «билет на билеты») с другим сетевым адресом. В новом билете устанавливается флаг PROXY. Клиент может передать серверу новый билет в качестве доверенности.

Чтобы затруднить использование украденных удостоверений, Kerberos-билеты обычно разрешается использовать только субъектам с сетевыми адресами, явно указанными в билете. В принципе сетевые адреса в билете можно не указывать, но это не рекомендуется. Вот почему клиент должен передать серверу доверенность — билет с его (сервера) сетевым адресом.

Билеты с правом передачи

Билеты с правом передачи позволяют развить механизм доверенностей и передавать серверу права на совершение любых действий от имени клиента. Подобное сильнодействующее средство полезно, например, когда пользователь, войдя в удаленную систему, хочет, чтобы проверка подлинности проходила так же, как и в случае локального входа.

Флаг FORWARDABLE трактуется почти так же, как PROXIABLE, однако дает право на получение новых «билетов на билеты» с другими сетевыми адресами и устанавливается лишь по явному запросу пользователя к серверу начальной аутентификации (AS) при получении первоначального «билета на билеты».

В принципе пользователь может получить новый «билет на билеты» с другими сетевыми адресами и без флага FORWARDABLE, обратившись непосредственно к AS, но тогда ему придется вводить свой пароль.

Флаг FORWARDED устанавливается в новом билете по явному запросу пользователя, когда он представляет TGS билет с флагом FORWARDABLE, задает опцию FORWARDED и указывает новый список сетевых адресов. Флаг FORWARDED наследуется при выдаче новых билетов.

Форматы данных в системе Kerberos

Опишем форматы двух важнейших объектов системы Kerberos — билета и аутентификатора. Описание дается в нотации ASN.1. Понимание этих форматов позволит лучше прочувствовать тонкости механизма аутентификации. Рис. 7 содержит описание структуры билета, а Рис. 6 — описание шифруемой (секретным ключом сервера) части билета.

Рисунок 6. Описание структуры билета

Листинг 1

 Рисунок 7. описание шифруемой части билета

Листинг 2

Поясним смысл компонентов билета.

tkt-vno. номер версии формата билета. Данный документ описывает версию 5.

realm. область управления, выдавшая билет, и, одновременно, область, содержащая сервер.

sname. имя сервера, к которому выдан данный билет.

enc-part. зашифрованная часть билета.

flags. битовая шкала флагов.

key. сеансовый ключ, выданный Kerberos для связи между клиентом и сервером.

crealm. область управления, в которой зарегистрирован клиент, и, одновременно, область, в которой происходила начальная проверка подлинности.

cname. имя клиента.

transited. список промежуточных областей управления, участвовавших в аутентификации клиента.

authtime. время выдачи первоначального билета, «наследником»

starttime. время, отмечающее начало срока годности билета. Если данное поле не задано, используется значение authtime.

endtime. время, отмечающее окончание срока годности билета. В принципе конкретные серверы могут накладывать свои, более жесткие, ограничения на время жизни билета.

renew-till. время, после которого даже обновляемый билет становится негодным.

caddr. список сетевых адресов, откуда билет может быть использован. Если список пуст, билет можно использовать откуда угодно. Данный список затрудняет использование злоумышленником украденного билета.

authorization-data. авторизационная информация, передаваемая владельцем билета серверу приложений. Предполагается, что это поле содержит имена обслуживаемых объектов и права доступа к ним. Поле authorization-data позволяет выдать доверенность на совершение определенных действий. Например, клиент, желающий напечатать файл, может передать серверу печати доверенность на чтение файла. Содержательная трактовка поля авторизации находится вне компетенции Kerberos; последний лишь переносит туда информацию, содержащуюся в запросе клиента на билет к серверу приложений.

Аутентификатор — это запись, посылаемая серверу вместе с билетом, удостоверяющая знание клиентом ключа шифрования, содержащегося в билете, помогающая серверу обнаружить воспроизведение (дублирование) информации и позволяющая выбрать «настоящий сеансовый ключ» для обслуживания конкретного сеанса связи между клиентом и сервером. Аутентификатор шифруется сеансовым ключом, копия которого находится в билете (Рис. 8).

Рисунок 8. Аутентификатор

Листинг 3

Комментарии к листингу:

authenticator-vno. номер версии формата аутентификатора (5).

crealm и cname. то же, что и для билета.

cksum. контрольная сумма прикладных данных, передаваемых серверу.

cusec. микросекундная часть временного штампа клиента.

ctime. основная часть временного штампа клиента.

subkey. выбранный клиентом ключ для защиты конкретного сеанса связи. Если это поле не задано, будет использоваться сеансовый ключ.

seq-number. начальный номер последовательности сообщений. Механизм номеров используется для контроля целостности последовательности и, в частности, для защиты от дублирования. Начальный номер рекомендуется выбирать случайным образом, а последующие номера не использовать дважды даже в разных сеансах.

authorization-data. то же, что и для билета (позволяет уточнить информацию, переданную в билете).

Типы пересылаемых сообщений

Обмен с сервером начальной аутентификации

Таблица 1. Обмен с сервером начальной аутентификации

Общение с сервером начальной аутентификации обычно инициируется клиентом, желающим получить удостоверение к определенному серверу, но не имеющим пока других удостоверений. Для шифровки и расшифровки используется секретный ключ клиента. Как правило, данный обмен происходит при входе в систему, для получения удостоверения к серверу выдачи билетов. Кроме того, общение с сервером начальной аутентификации используется для получения удостоверения к серверам, требующим знания именно секретного ключа (пример — сервер смены пароля).

В своем запросе (KRB_AS_REQ) клиент посылает открытым текстом свое имя и имя сервера, к которому он хочет получить удостоверение. Ответ, KRB_AS_REP, содержит билет, который клиент должен будет представить серверу, и сеансовый ключ для совместного использования клиентом и сервером. Билет шифруется секретным ключом сервера, сеансовый ключ и дополнительная информация — секретным ключом клиента. Сообщение KRB_AS_ REP содержит данные, позволяющие связать его с предыдущим запросом (KRB_AS_REQ) и обнаружить дублирование сообщений. В случае какой-либо ошибки возвращается сообщение KRB_ERROR, которое не шифруется.

Сервер аутентификации не делает попыток убедиться в подлинности обратившегося к нему субъекта. Просто он возвращает информацию, воспользоваться которой может лишь тот, кто знает секретный ключ субъекта.

Таблица 2. Обмен с сервером выдачи билетов

Обмен между клиентом и сервером выдачи билетов инициируется клиентом, когда тот хочет получить удостоверение к определенному серверу (возможно, зарегистрированному в удаленной области управления), обновить или зарегистрировать существующий билет или получить билет с доверенностью. В первом случае клиент должен располагать предварительно полученным от сервера начальной аутентификации билетом к TGS. Формат сообщений при обмене с сервером выдачи билетов почти тот же, что и для сервера начальной аутентификации. Основное отличие состоит в том, что для шифровки и расшифровки используется сеансовый ключ.

Запрос (KRB_TGS_REQ) состоит из информации, подтверждающей подлинность клиента, и заявки на удостоверение. Ответ (KRB_TGS_REP) содержит запрашиваемое удостоверение, зашифрованное сеансовым ключом, и данные, позволяющие обнаружить дублирование сообщений и связать ответ с запросом.

Таблица 3. Аутентификационный обмен клиент/сервер

Данный обмен используется сетевыми приложениями для взаимной проверки подлинности. Клиент должен располагать предварительно полученным удостоверением к серверу. Клиент передает серверу билет, аутентификатор зашифрованный сеансовым ключом) и некоторую дополнительную учетную информацию. Сервер в ответ (если этот ответ требуется) возвращает только аутентификатор, зашифрованный тем же сеансовым ключом.

Защищенные сообщения

Сообщения типа KRB_SAFE могут использоваться партнерами по общению, желающими контролировать целостность передаваемой информации. Контроль целостности достигается за счет включения в сообщение криптографической контрольной суммы. Используется последний субсеансовый или сеансовый ключ.

Конфиденциальные сообщения

Сообщения типа KRB_PRIV могут использоваться партнерами по общению, желающими защитить данные от нелегального прочтения и контролировать их целостность. Цель достигается криптографическими методами.

Пересылка удостоверений

Сообщения типа KRB_CRED используются для пересылки удостоверений с одного хоста на другой. В сообщение входят билет и зашифрованные данные, содержащие сеансовый ключ и другую ассоциированную с билетом информацию.

База данных Kerberos

Сервер Kerberos должен иметь доступ к базе данных, содержащей идентификаторы и секретные ключи субъектов. Записи в этой базе должны содержать по крайней мере информацию, показанную в Таб. 4.

Таблица 4. Обязательные поля базы данных Kerberos

Секретные ключи субъектов могут шифроваться «мастер-ключом» Kerberos.

Когда секретный ключ сервера изменяется нормальным образом (то есть не в результате компрометации старого ключа), старый ключ следует сохранять до тех пор, пока остаются годными билеты, выданные с его помощью. Таким образом, возможна ситуация, когда один субъект имеет несколько активных ключей. Информация, шифруемая секретным ключом, всегда помечается версией примененного ключа, иначе правильная расшифровка может стать невозможной.

Субъекту с несколькими активными ключами соответствует несколько записей в базе данных Kerberos. При выдаче билетов и в процессе начальной аутентификации всегда используется самый свежий ключ (с максимальным номером версии).

В реализации Kerberos в рамках проекта Афина записи базы данных содержали дополнительные поля, показанные в Таб. 5.

Таблица 5. Дополнительные поля базы данных Kerberos

Битовая шкала атрибутов может задавать характеристики билетов, допустимые для данного субъекта, или влиять на процесс преобразования пароля в секретный ключ.

Если политика безопасности, проводимая организацией, требует более детальной отчетности, в записи базы данных Kerberos могут быть включены поля, помогающие отследить все операции с билетами. Правда, при этом следует учитывать необходимость частых изменений базы, что может быть нежелательным и по соображениям эффективности, и по соображениям безопасности. Также возможно, но нежелательно использование внешней по отношению к Kerberos базы данных (например, службы имен сетевой операционной системы).

Предлагаемые направления развития системы Kerberos

Популярность системы Kerberos довольно быстро растет, а вместе с ней растет и число предложений, направленных на развитие Kerberos. Эти предложения можно разбить на две основные группы:

  • стандартизация программного интерфейса (как часть процесса выработки более общего прикладного программного интерфейса безопасности, затрагивающего не только аутентификацию);
  • стандартизация использования в процедуре начальной аутентификации одноразовых паролей и/или асимметричных методов шифрования.

Можно надеяться, что доступность системы Kerberos и гласность процедуры стандартизации сделают аутентификационный сервис еще более надежным и гибким.

I. Терминологический словарь

Авторизация. процесс определения правомочности использования клиентом определенной услуги, перечня доступных объектов, а также разрешенных видов доступа.

Аутентификатор. запись, содержащая информацию, про которую можно доказать, что она была недавно сгенерирована с использованием сеансового ключа, известного только клиенту и серверу.

Аутентификационный заголовок. запись, содержащая билет и удостоверение. Эта запись будет представлена серверу в процессе проверки подлинности.

Аутентификационный маршрут. последовательность промежуточных областей управления, пересекаемых в процессе проверки подлинности субъектов из разных областей.

Аутентификация (проверка подлинности). проверка того, что субъект является тем, за кого он себя выдает.

Билет. запись, помогающая клиенту доказать серверу свою подлинность. Билет содержит сведения о клиенте, сеансовый ключ, временной штамп и другую информацию. На билете ставится печать с помощью секретного ключа сервера. Билет действителен только вместе со свежим аутентификатором.

Билет на билеты (Ticket-Granting Ticket, TGT). билет к серверу выдачи билетов (Ticket-Granting Server, TGS), позволяющий получать билеты к другим серверам.

Доверенность. документ, дающий предъявителю право на доступ к определенным объектам или услугам. В системе Kerberos это может быть билет, использование которого ограничено содержимым поля авторизации. К билету должен прилагаться сеансовый ключ.

Идентификатор субъекта. имя, используемое для уникальной идентификации субъекта.

Клиент. процесс, использующий сетевые сервисы от имени пользователя. Отметим, что в некоторых случаях сервер сам может являться клиентом некоторого другого сервера (например, сервер печати может пользоваться услугами файлового сервера).

Обычный текст. исходные данные для функции шифрования или результат функции расшифровки. Расшифровка преобразует шифрованный текст в обычный.

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

Сеансовый ключ. временный ключ шифрования, используемый двумя субъектами. Время жизни такого ключа ограничено одним сеансом работы в системе.

Секретный ключ. ключ шифрования, разделяемый субъектом и KDC и используемый длительное время. В случае, когда субъектом является пользователь, секретный ключ вычисляется по паролю.

Сервер. субъект, предоставляющий ресурсы сетевым клиентам.

Сервис (услуга). ресурс, предоставляемый сетевым клиентам. Зачастую может поддерживаться несколькими серверами (например, сервис удаленных файлов).

Субсеансовый ключ. временный ключ шифрования, используемый двумя субъектами. Обмен субсеансовыми ключами защищается посредством сеансовых ключей. Время жизни субсеансового ключа ограничено одним сеансом общения между субъектами.

Субъект. пользователь, клиент или сервер, имеющий уникальное имя и участвующий в сетевом общении.

Удостоверение. совокупность билета и секретного сеансового ключа, необходимого для успешного использования билета в процессе проверки подлинности.

Центр распределения билетов (Key Distribution Center, KDC). сетевой сервис, предоставляющий билеты и временные сеансовые ключи, или конкретный сервер, оказывающий данную услугу, или хост, на котором функционирует этот сервер. KDC обслуживает запросы и на начальный билет (соответствующий компонент иногда называют сервером начальной аутентификации — Authentication Server, AS), и на билеты к конкретным серверам (этот компонент именуют сервером выдачи билетов — Ticket-Granting Server, TGS).

Цербер (Kerberos). не только мифологический трехголовый пес, охранявший подземное царство, но и название сервиса проверки подлинности для проекта Афина (Массачусетский технологический институт), протокол, используемый этим сервисом, а также программная реализация сервиса аутентификации.

Шифрованный текст. результат функции шифрования. Шифрование преобразует обычный текст в шифрованный.

Обобщенный прикладной программный интерфейс службы безопасности

Обобщенный прикладной программный интерфейс службы безопасности (Generic Security Service Application Program Interface — GSS-API) — это набор спецификаций, одобренных сообществом Internet и распространяющих идеологию открытых систем на такую традиционно закрытую область, как информационная безопасность.

Интерфейс безопасности GSS-API, в отличие от большинства других средств безопасности, ориентированных на локальное использование, преследует цель защиты коммуникаций между компонентами программных систем, построенных в архитектуре клиент/сервер. Он предоставляет услуги по взаимной аутентификации (проверке подлинности) общающихся партнеров и по контролю целостности и обеспечению конфиденциальности пересылаемых сообщений. Пользователями интерфейса безопасности GSS-API являются коммуникационные протоколы (обычно прикладного уровня) или другие программные системы, самостоятельно выполняющие пересылку данных.

Обобщенный интерфейс безопасности GSS-API не зависит от конкретной языковой среды и от механизма безопасности, обеспечивающего реальную защиту. Последнее обстоятельство позволяет создавать приложения, которые на уровне исходного текста мобильны по отношению к смене механизма безопасности. Тем самым реализуется открытость прикладных систем и соответствующих средств защиты. Следует отметить, что средства защиты могут быть существенно разными — от систем Kerberos, в основе которых лежат симметричные методы шифрования, и до продуктов, реализующих спецификации X.509, где явно оговаривается использование открытых ключей. Попутно мы видим, что обобщенный интерфейс безопасности GSS-API имеет под собой вполне конкретную почву.

На каждом компьютере, где предполагается использовать интерфейс безопасности GSS-API, должно быть установлено клиентское программное обеспечение соответствующего механизма защиты. Приложение, использующее GSS-API, локальным образом вызывает необходимые функции, получая в ответ так называемые токены безопасности. Подобный токен может содержать зашифрованное удостоверение пользователя, электронную подпись под сообщением или целое зашифрованное сообщение. Приложения обмениваются токенами безопасности, достигая тем самым аутентификации, целостности и конфиденциальности общения. Поскольку коммуникационные аспекты вынесены за пределы обобщенного интерфейса безопасности GSS-API, он автоматически оказывается независимым от сетевых протоколов. Сетевая мобильность приложений должна обеспечиваться иными средствами.

Данная работа основана на второй версии интерфейса GSS-API, описанной в документе [1]. Первая версия зафиксирована в RFC 1508 [2]. Отображение обобщенного интерфейса в языковую среду C — тема спецификации RFC 1509 [3]. Система Kerberos (версия 5) описана в RFC 1510 [4]. С рекомендациями X.509 можно ознакомиться по публикации [5].

Основные понятия

В этом разделе будут рассмотрены базовые элементы обобщенного интерфейса безопасности GSS-API.

Удостоверение

Удостоверение — это структура данных, позволяющая ее владельцу доказать партнеру по общению или третьей стороне, что он (владелец) является именно тем, за кого себя выдает. Таким образом, в GSS-API удостоверения выступают как средство аутентификации.

Естественно, что служба безопасности (например, Kerberos) совместно с операционной системой должны обеспечить защиту удостоверений от несанкционированного использования и/или изменения. Процессам, действующим от имени пользователей, не предоставляется прямого доступа к удостоверениям. Вместо этого, при необходимости процессы снабжаются дескрипторами удостоверений. Дескрипторы не содержат секретной информации и не нуждаются в защите. Нет смысла воровать дескрипторы, поскольку их интерпретация для разных процессов-предъявителей будет различной.

Вообще говоря, одному пользователю могут понадобиться удостоверения нескольких видов. Во-первых, структура удостоверений, несомненно, зависит от механизма безопасности, стоящего за обобщенным интерфейсом. Во-вторых, можно представить себе ситуацию, когда для общения с разными партнерами нужны различные удостоверения. В-третьих, особым образом должны быть устроены так называемые делегируемые удостоверения, служащие для передачи прав на выполнение определенных действий от имени некоторого пользователя. Есть и другие факторы, влияющие на структуру удостоверений.

В процессе входа пользователя в систему могут формироваться удостоверения стандартного вида, выдаваемые по умолчанию.

Контекст безопасности

Контекст безопасности — это пара структур данных (по одной локально хранимой структуре для каждого партнера по общению), в которых содержится разделяемая информация о состоянии процесса общения, необходимая для защиты пересылаемых сообщений. Как и удостоверения, контексты безопасности хранятся внутренним для службы безопасности образом — прикладные процессы снабжаются лишь дескрипторами контекстов. Контексты формируются на основании локально выданных или делегированных удостоверений.

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

Интерфейс GSS-API не зависит от используемого сетевого протокола. По этой причине формирование контекста безопасности никак не связано с установлением соединения в сетевом смысле. Более того, для GSS-API безразлично, используется ли протокол с установлением соединения или без такового. Организация потока сообщений, а также выделение из входного потока данных, генерируемых в рамках GSS-API, — обязанность прикладных систем.

Токены безопасности

Токены безопасности — это элементы данных, пересылаемые между пользователями интерфейса GSS-API с целью поддержания работоспособности этого интерфейса и защиты прикладной информации. Токены подразделяются на два класса. Контекстный класс предназначен для установления контекстов безопасности и для выполнения управляющих действий над ними. В рамках уже установленного контекста для защиты сообщений используются токены сообщений.

Когда приложение хочет начать общение с удаленным партнером, оно обращается к интерфейсу GSS-API с просьбой инициализировать контекст. В ответ возвращается контекстный токен безопасности, который приложение обязано переслать партнеру. Тот, получив токен, передает его локальному экземпляру GSS-API для проверки подлинности инициатора и продолжения (обычно — завершения) формирования контекста.

Если приложению необходимо защитить сообщение, обеспечив возможность контроля целостности и подлинности источника данных, оно передает сообщение интерфейсу GSS-API, получая в ответ токен, содержащий криптографическую контрольную сумму (имитовставку, хэш, дайджест), заверенную электронной подписью отправителя. После этого приложение должно переслать как само сообщение, так и защищающий его токен. Партнер, получив обе порции данных, передает их своему локальному экземпляру GSS-API для проверки авторства и целостности.

Для приложения структура токенов безопасности является закрытой. Токены генерируются и контролируются исключительно функциями GSS-API. Дело приложения — переслать их и передать соответствующим функциям для обработки. Естественно, служба безопасности обнаружит попытки приложения изменить токен, если подобные попытки будут предприняты.

Типы механизмов безопасности, имена и привязка к каналам

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

Конкретная служба характеризуется типом реализуемого механизма безопасности. В свою очередь, тип обозначается посредством структуры данных, называемой идентификатором объекта. На уровне обобщенного программного интерфейса структура идентификаторов объектов не уточняется.

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

Если токены являются структурой, закрытой для приложений, то структура имен, употребляемых при формировании контекста безопасности (имеются в виду имена партнеров по общению), закрыта для функций GSS-API. Имена рассматриваются этими функциями просто как последовательности байт, интерпретируемые, вероятно, коммуникационными компонентами приложений.

В GSS-API предусматривается наличие трех типов имен — внутренних, печатных и объектных. Как правило, аргументами функций GSS-API служат внутренние имена. Интерфейс GSS-API предоставляет функции для преобразования имен и выполнения некоторых других действий над ними.

Отметим, что интерпретация имен — дело довольно сложное, поскольку они могут, вообще говоря, принадлежать разным пространствам имен. Чтобы избежать неоднозначности, в состав имени включается идентификатор его типа.

Чтобы усилить защиту информации, в интерфейсе GSS-API предлагается возможность связывания контекста безопасности с определенными каналами передачи данных. Более точно, инициатор формирования контекста может указать набор каналов, которые допустимо использовать в рамках открываемого сеанса общения. Партнер должен подтвердить свое согласие на связывание с этим набором каналов. Канал характеризуется целевым адресом и некоторыми другими параметрами, такими как формат пересылаемой по нему информации, степень ее защищенности и т.п. Если так случится, что токен, отправленный для установления контекста, будет перехвачен, использование соответствующего контекста ограничится рамками связанных с ним каналов. Это, как можно надеяться, затруднит действия злоумышленника.

Классификация функций безопасности

Общие положения

Каждая функция, входящая в состав обобщенного интерфейса безопасности GSS-API, возвращает два кода ответа — основной и дополнительный. Набор основных кодов регламентируется в рамках GSS-API, дополнительные коды могут быть специфичны для различных служб безопасности.

Основные коды подразделяются на информирующие и сигнализирующие об ошибке. Перечислим некоторые информирующие коды:

GSS_S_COMPLETE. нормальное завершение

GSS_S_CONTINUE_NEEDED. требуется дополнительный вызов данной функции

GSS_S_DUPLICATE_TOKEN. обнаружено дублирование токена защиты сообщений

Следующие значения входят в число кодов, сигнализирующих об ошибке:

GSS_S_BAD_NAME. задано некорректное имя

GSS_S_CONTEXT_EXPIRED. истек срок действия контекста

GSS_S_CREDENTIALS_EXPIRED. истек срок действия удостоверения

GSS_S_DEFECTIVE_TOKEN. обнаружено повреждение токена безопасности

GSS_S_NO_CONTEXT. не задан контекст

GSS_S_NO_CRED. не задано удостоверение

Проанализировав основной код, приложение может сделать вывод о нормальном или ненормальном завершении функции. В последнем случае оно может принять во внимание дополнительный код, что даст пользователю больше информации, но, вообще говоря, уменьшит мобильность приложения.

Работа с удостоверениями

Работа приложения, опирающегося на интерфейс GSS-API, должна начинаться с получения удостоверения, которое засвидетельствует, что приложение имеет право выступать от имени определенного субъекта.

Интерфейс GSS-API предоставляет следующие функции для работы с удостоверениями:

GSS_Acquire_cred. запрос удостоверения для последующего использования

GSS_Release_cred. отказ от удостоверения, ставшего ненужным

GSS_Inquire_cred. получение информации об удостоверении

GSS_Add_cred. постепенное формирование удостоверения

GSS_Inquire_cred_by_mech. получение информации об удостоверении, связанной с конкретным механизмом безопасности

Как уже указывалось, приложение получает в свое распоряжение не само удостоверение, а его дескриптор. Этот дескриптор используется затем в качестве аргументов функций GSS_Release_cred, GSS_Inquire_cred, GSS_Add_cred, а также функций формирования контекста безопасности.

Функция GSS_Acquire_cred нужна в первую очередь серверным процессам, желающим явно указать, от чьего имени они выступают. Интерактивные пользователи могут неявным образом получать подразумеваемые удостоверения при входе в систему. Аналогично, при выходе такого пользователя из системы может автоматически выполняться вызов функции GSS_Release_cred.

Функция GSS_Inquire_cred позволяет получить информацию об удостоверении — имя ассоциированного субъекта, срок годности, применимость для операций с контекстом (инициация и/или принятие), поддерживаемые механизмы безопасности. Данная функция особенно полезна применительно к подразумеваемому удостоверению, характеристики которого могут меняться от системы к системе.

Функция GSS_Add_cred позволяет постепенно формировать удостоверения, добавляя в них поля, необходимые различным механизмам безопасности.

Функция GSS_Inquire_cred_by_mech полезна в среде, поддерживающей несколько механизмов безопасности. Она, в частности, позволяет убедиться в том, что данное удостоверение допускает использование совместно с конкретным механизмом безопасности.

Создание и уничтожение контекста безопасности

Создание контекста безопасности предшествует всем операциям по обмену сообщениями между потенциальными партнерами. В процессе формирования контекста партнеры могут убедиться в подлинности друг друга, а также договориться о степени защищенности коммуникаций. Впрочем, обычно, в силу асимметричности отношения клиент/сервер, аутентификация носит односторонний характер — сервер убеждается в подлинности клиента.

Для работы с контекстами обобщенный интерфейс безопасности GSS-API предоставляет следующие функции:

GSS_Init_sec_context. формирование «исходящего»

GSS_Accept_sec_context. формирование «входящего»

GSS_Delete_sec_context. отказ от контекста, ставшего ненужным

GSS_Process_context_token. обработка полученного контекстного токена

GSS_Context_time. выяснение времени, в течение которого контекст будет оставаться годным

GSS_Inquire_context. получение информации о контексте

GSS_Wrap_size_limit. выяснение максимального размера сообщения, которое можно зашифровать в рамках заданного контекста безопасности

GSS_Export_sec_context. передача контекста другому процессу

GSS_Import_sec_context. прием контекста, переданного другим процессом

Инициатор общения вызывает функцию GSS_Init_sec_context, передавая ей свое удостоверение — явно полученное или подразумеваемое. Кроме того, инициатор специфицирует запрашиваемую процедуру взаимной аутентификации и уровень защиты сообщений. В ответ ему возвращается токен, который следует переслать партнеру. Партнер, получив токен, передает его функции GSS_Accept_sec_context (вместе со своим удостоверением). Как правило, на этом формирование контекста заканчивается. Партнеры должны проанализировать флаги, ассоциированные с контекстом, чтобы узнать, каков реально предоставленный уровень защиты.

Если инициатор общения (обычно это клиент) желает убедиться в подлинности партнера, он передает функции GSS_Init_ sec_context флаг mutual_req_ flag (требуется взаимная аутентификация). В таком случае вызов GSS_Init_sec_context возвращает в качестве основного кода значение GSS_S_CONTINUE_NEEDED (а не GSS_S_ COMPLETE). Соответствующим образом меняется и генерируемый контекстный токен. Партнер, приняв и обработав (с помощью функции GSS_Accept_sec_context) присланную информацию, получит на выходе установленный флаг mutual_state и новый контекстный токен, который следует вернуть инициатору. Последний должен повторно обратиться к функции GSS_Init_sec_context с полученным токеном. При отсутствии ошибок GSS_Init_sec_context вернет, наконец, основной код GSS_S_COMPLETE, и формирование контекста на этом завершится.

В принципе служба безопасности может требовать при формировании контекста обмена несколькими токенами (даже без взаимной аутентификации). В этом случае инициатору придется несколько раз вызывать функцию GSS_Init_sec_context, а его партнеру — функцию GSS_Accept_sec_context. Все вызовы, кроме последнего, вернут основной код GSS_S_CONTINUE_NEEDED. Последний вызов, завершающий формирование контекста на соответствующей стороне, в нормальном случае выдаст основной код GSS_S_COMPLETE.

Общающиеся партнеры должны сами определять (способами, внешними по отношению к GSS-API), что из пересылаемой информации представляет собой контекстный токен и какой функции его следует передать.

При отказе от контекста, ставшего ненужным, можно получить от функции GSS_Delete_sec_context управляющий токен, подлежащий пересылке партнеру. Партнер, приняв токен, должен вызвать функцию GSS_Process_context_token, которая проанализирует управляющую информацию и удалит вторую половину сбрасываемого контекста.

Как правило, в процессе формирования контекста партнер получает информацию о его инициаторе. Инициатор может, посредством флага anon_req_ flag, запросить формирование «анонимного» контекста. Это имеет смысл при пользовании общедоступными услугами (получение свободно распространяемой информации и т.п.). Партнер вправе принять или отвергнуть анонимный контекст.

Функция GSS_Inquire_context позволяет получить информацию о контексте — имена инициатора общения и его партнера, срок годности, тип задействованного механизма безопасности, а также ассоциированные флаги (replay_det_state — обеспечивается отслеживание продублированных сообщений, conf_avail — предоставляется возможность шифровать сообщения и т.п.).

Функция GSS_Export_ sec_context позволяет получить токен, пригодный для передачи контекста безопасности другому процессу в пределах одной вычислительной системы. Передавать можно только полностью сформированный контекст. Вообще говоря, экспортировав контекст, процесс теряет право на его использование.

Для приема (импорта) контекста безопасности служит функция GSS_Import_sec_context.

Защита сообщений

В процессе формирования контекста партнеры по общению имеют возможность убедиться в подлинности друг друга. Все остальные средства службы безопасности направлены на защиту сообщений.

Интерфейс GSS-API предоставляет следующие функции для работы с сообщениями:

GSS_GetMIC. формирование токена, позволяющего контролировать целостность сообщения и подлинность его источника

GSS_VerifyMIC. проверка целостности сообщения и подлинности источника с помощью ассоциированного токена

GSS_Wrap. формирование инкапсулированного, возможно, зашифрованного, сообщения, содержащего информацию для контроля целостности и проверки подлинности источника

GSS_Unwrap. разбор инкапсулированного сообщения

При формировании контекста инициатор специфицирует требуемый уровень защиты сообщений. Ответные флаги показывают, обеспечивается ли этот уровень на самом деле. Флаг integ_avail информирует о возможности контроля целостности и подлинности источника сообщения, флаг conf_avail — о доступности средств шифрования. Прежде чем обращаться к функциям GSS_GetMIC/GSS_Wrap, приложение должно проверить состояние перечисленных флагов.

Функция GSS_GetMIC по сообщению формирует отдельный токен безопасности. Функция GSS_Wrap «упаковывает» контрольную информацию вместе с сообщением (быть может, зашифрованным). Приложения должны уметь различать токены безопасности и сообщения (инкапсулированные или нет) и обрабатывать их соответствующим образом.

Служба безопасности может предоставлять дополнительные услуги в виде отслеживания продублированных сообщений и (более сильного) контроля последовательности сообщений. При формировании контекста эти услуги могут быть заказаны (флаги replay_det_req_flag и sequence_req_flag). Ответные флаги показывают, действительно ли обеспечивается запрошенный уровень защиты. Если это так, то в ассоциированные токены безопасности или инкапсулированные сообщения прозрачным для приложения образом могут вставляться порядковые номера, временные штампы и т.п. Соответственно, приложение должно быть готово получить от функций GSS_VerifyMIC/GSS_Unwrap основные коды завершения GSS_S_DUPLICATE_TOKEN (обнаружено дублирование сообщений), GSS_S_OLD_TOKEN (старое сообщение), GSS_S_UNSEQ_TOKEN (опоздавшее сообщение), GSS_S_ GAP_TOKEN (сообщение пришло слишком рано — некоторые предшествующие сообщения еще не получены). Подозрительные сообщения, несмотря на ненормальный код завершения, передаются приложению, которое трактует ситуацию в соответствии с избранной политикой безопасности. В частности, ничто не мешает обработать сообщение обычным образом.

Некоторые службы безопасности могут по выбору предоставлять различное качество защиты (Quality Of Protection — QOP). Выбор подходящего качества важен для приложения с точки зрения разумного расходования ресурсов, поскольку сильная защита может требовать значительных накладных расходов. В спецификациях интерфейса GSS_API определяется формат элемента данных, описывающего качество защиты. Это 32-битное целое, состоящее из двух 16-битных частей, одна из которых относится к контролю целостности, а другая — к обеспечению конфиденциальности. В обоих случаях задается степень контроля, идентификаторы используемых алгоритмов и информация, специфичная для выбранного алгоритма.

Вспомогательные средства

В число вспомогательных входят следующие функции:

GSS_Display_status. получение текста сообщения, ассоциированного с кодом завершения

GSS_Indicate_mechs. получение списка типов механизмов безопасности, поддерживаемых локальной системой

GSS_Compare_name. сравнение имен на равенство

GSS_Display_name. преобразование имени из внутреннего представления в печатное

GSS_Import_name. преобразование имени из печатного представления во внутреннее

GSS_Release_name. отказ от ставшего ненужным внутреннего имени

GSS_Release_buffer. отказ от ставшего ненужным печатного имени

GSS_Release_oid_set. отказ от ставшего ненужным набора идентификаторов объектов

GSS_Import_name_object. преобразование именующего объекта во внутреннее имя

GSS_Export_name_object. преобразование внутреннего имени в именующий объект

и некоторые другие. Мы не будем подробно описывать вспомогательные функции.

Логика работы пользователей интерфейса безопасности

На Рис. 1 приведен примерный сценарий взаимодействия между клиентом и сервером. Предполагается, что для взаимной аутентификации достаточно обмена одной парой токенов безопасности и что партнеры запрашивают и контроль целостности, и обеспечение конфиденциальности сообщений, а служба безопасности предоставляет им эти средства.

Рисунок 1. Сценарий взаимодействия между клиентом и сервером. Детали, связанные с преобразованием имен, опущены. Текст в фигурных скобках является комментарием. Стрелка отделяет входные параметры от выходных.

Мы видим, что общая схема взаимодействия удаленных партнеров под защитой интерфейса безопасности GSS-API довольно проста, однако практическая реализация всех необходимых проверок (кодов завершения, установленных флагов) требует известной аккуратности.

Службы безопасности, которые могут предоставить интерфейс GSS-API

Обобщенный прикладной программный интерфейс службы безопасности GSS-API — это «всего лишь» спецификации, приобретающие реальную силу, только если за ними стоят конкретные системы. Мы рассмотрим две разновидности подобных систем — Kerberos и службы безопасности, основанные на рекомендациях X.509.

Данный раздел предназначен для тех, кто знаком с соответствующими службами.

Система Kerberos

Понятия системы Kerberos можно отображать на понятия обобщенного интерфейса безопасности GSS-API разными способами. Мы рассмотрим простейший из них.

Роль удостоверения выполняет билет на билеты (в терминологии Kerberos — Ticket Granting Ticket, TGT). Функция GSS_Acquire_cred выдаст дескриптор удостоверения.

Функция GSS_Init_sec_ context пройдет маршрут от локальной области управления до удаленной, в которой располагается сервер, и получит билет к серверу. В контекст безопасности, помимо прочих данных, войдет сгенерированный сеансовый ключ. Функция GSS_Init_ sec_context вернет в качестве токена безопасности сообщение, имеющее Kerberos-формат KRB_AP_REQ и использующееся при аутентификационном обмене клиент/сервер.

После получения сервером сообщения KRB_AP_REQ и его обработки функцией GSS_Accept_sec_context, обе стороны будут располагать общим сеансовым ключом, который они смогут использовать для защиты пересылаемых сообщений. Если требуется взаимная аутентификация, сервер должен переслать клиенту Kerberos-сообщение KRP_AP_ REP.

Естественным образом устанавливается соответствие между сроками годности удостоверений и контекстов с одной стороны, и сроками годности соответствующих билетов (обычных или предназначенных для получения других билетов) с другой стороны.

Выше было отмечено, что интерфейс GSS-API предусматривает возможность делегирования полномочий. Аналогичное средство имеется и в системе Kerberos (флаги PROXIABLE, PROXY, FORWARDABLE, FORWARDED).

Системы, основанные на рекомендациях X.509

Как известно, рекомендации X.509 предусматривают использование шифрования с открытыми ключами.

Функция GSS_Acquire_ cred формирует удостоверение, в которое входит секретный ключ пользователя. Тем самым открывается доступ к этому ключу от имени пользователя.

Функция GSS_Init_sec_ context получает от службы директорий заверенный сертификат сервера. Тем самым для клиента становится доступным открытый ключ сервера. GSS_Init_ sec_context генерирует сеансовый ключ (как часть контекста безопасности) и шифрует его открытым ключом сервера (для вставки в выходной токен). Сеансовый ключ будет использоваться для защиты сообщений, пересылаемых между клиентом и сервером. В токен, выдаваемый функцией GSS_Init_sec_context, помимо зашифрованного сеансового ключа включаются сведения о клиенте, зашифрованные его (клиента) секретным ключом. Таким образом гарантируется конфиденциальность сеансового ключа (только сервер сможет его расшифровать) и достоверность информации о клиенте (поскольку она заверена его электронной подписью).

Функция GSS_Accept_ sec_context, вызываемая сервером, получает от службы директорий сертификат клиента и, в частности, его открытый ключ. После этого становится возможной проверка подлинности присланного токена безопасности и аутентификация клиента. Сервер расшифровывает своим секретным ключом присланный в токене сеансовый ключ. После этого может начаться эффективный обмен защищенными сообщениями между клиентом и сервером.

Детальное описание некоторых функций безопасности

В этом разделе детально описываются входные и выходные параметры важнейших функций безопасности, а также выполняемые этими функциями действия. Подробное рассмотрение позволяет лучше почувствовать дух спецификаций GSS-API. Кроме того, появляется возможность остановиться на некоторых сравнительно тонких моментах, которые выше были лишь упомянуты.

В описаниях интерфейсов после имени параметра следует имя его типа. Поскольку интерфейс GSS-API — обобщенный, в нем не уточняется отображение на конкретную языковую среду. Впрочем, во многих случаях трактовка типов очевидна.

В фигурных скобках после имени параметра и его типа следует разъяснение назначения параметра.

GSS_Acquire_cred — получение дескриптора удостоверения

Функция GSS_Acquire_ cred предназначена для получения дескриптора удостоверения. Как правило, к ней обращаются только серверные компоненты приложений (клиентские удовлетворяются подразумеваемыми удостоверениями).

Входные параметры:

  • desired_name: INTERNAL_ NAME {имя, которое должно быть вписано в удостоверение; NULL означает подразумеваемое значение, определяемое по локальным правилам}
  • lifetime_req: INTEGER {запрашиваемый срок годности удостоверения, измеряемый в секундах; 0 означает подразумеваемый срок}
  • desired_mechs: SET_OF_OBJECT_IDENTIFIER {набор механизмов безопасности, которые должны поддерживать данное удостоверение; пустое множество означает заявку на подразумеваемый механизм. Вероятно, каждый механизм разместит в удостоверении свою, нужную только ему информацию}
  • cred_usage: INTEGER {возможные способы использования удостоверения: 0 — для инициирования и принятия контекстов, 1 — только для инициирования, 2 — только для принятия}

Выходные параметры:

  • major_status: INTEGER {основной код завершения}
  • minor_status: INTEGER {дополнительный код завершения}
  • output_cred_handle: CREDENTIAL_HANDLE {дескриптор выданного удостоверения}
  • actual_mechs: SET_OF_OBJECT_IDENTIFIER {набор предоставленных механизмов безопасности}
  • lifetime_rec: INTEGER {срок годности удостоверения; для обозначения неограниченного срока имеется выделенное значение}

Возможные значения основного кода завершения:

  • GSS_S_COMPLETE — запрашиваемое удостоверение успешно получено, со сроком годности (от текущего момента) lifetime_rec секунд, предназначенное для использования в соответствии со значением cred_usage, поддерживаемое набором механизмов безопасности actual_mechs. Для последующего доступа к удостоверению следует использовать дескриптор output_cred_handle.
  • GSS_S_BAD_MECH — запрашивается неподдерживаемый механизм безопасности. Удостоверение не выдается (в качестве значения output_cred_handle возвращается NULL).
  • GSS_S_BAD_NAMETYPE — запрашиваемое имя не удается проинтерпретировать. Удостоверение не выдается.
  • GSS_S_BAD_NAME — некорректное имя. Удостоверение не выдается.
  • GSS_S_FAILURE — удостоверение не удалось выдать по причинам, не специфицируемым на уровне GSS-API (например, из-за отсутствия прав на использование запрашиваемого имени).

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

GSS_Add_cred — постепенное формирование удостоверений

Функция GSS_Add_cred позволяет постепенно формировать удостоверения, пополняя их поддержкой новых механизмов безопасности, изменяя срок годности или предполагаемые способы использования.

Входные параметры:

  • cred_handle: CREDENTIAL_HANDLE {дескриптор удостоверения, полученный в результате предыдущих вызовов функций GSS_Acquire_cred или GSS_add_cred; NULL означает добавление к подразумеваемому удостоверению}
  • desired_name: INTERNAL_NAME {имя, которое должно быть вписано в удостоверение; NULL обозначает подразумеваемое имя}
  • initiator_time_req: INTEGER {запрашиваемый срок годности удостоверения для инициации контекстов; 0 — подразумеваемый срок}
  • acceptor_time_req: INTEGER {запрашиваемый срок годности удостоверения для приема контекстов; 0 — подразумеваемый срок}
  • desired_mech: OBJECT_ IDENTIFIER {добавляемый механизм безопасности}
  • cred_usage: INTEGER {способ использования удостоверения}

Выходные параметры:

  • major_status: INTEGER
  • minor_status: INTEGER
  • output_cred_handle: CREDENTIAL_HANDLE
  • actual_mechs: SET_OF_OBJECT_IDENTIFIER
  • initiator_time_rec: INTEGER {время в секундах; специальное значение резервируется для неограниченного срока годности}
  • acceptor_time_rec: INTEGER
  • real_cred_usage: INTEGER {результирующий способ использования удостоверения}

Смысл выходных параметров тот же, что и для функции GSS_Acquire_cred, лишь новое значение real_cred_usage показывает, для чего можно использовать скорректированное удостоверение. Прежними остались и основные коды завершения. Добавилось только одно новое значение — GSS_S_NO_ CRED, означающее, что дескриптору cred_handle не соответствует корректное удостоверение.

Во всех вызовах функций GSS_Acquire_cred и GSS_Add_ cred, имеющих дело с одним удостоверением, значения desired_ name должны совпадать.

GSS_Init_sec_context — инициация контекста безопасности

Функция GSS_Init_sec_ context предназначена для инициации контекста безопасности, формируемого общающимися партнерами, и для генерации токена, пересылка которого позволит удаленному партнеру выполнить свою часть работы по формированию контекста.

Входные параметры:

  • claimant_cred_handle: CREDENTIAL_HANDLE {дескриптор удостоверения инициатора взаимодействия; NULL означает подразумеваемое удостоверение}
  • input_context_handle: CONTEXT_HANDLE {дескриптор формируемого контекста; 0 означает, что формирование только начинается}
  • targ_name: INTERNAL_NAME {имя партнера по общению}
  • mech_type: OBJECT_IDENTIFIER {механизм безопасности, который должен поддерживать формируемый контекст; NULL означает подразумеваемый механизм}
  • deleg_rec_flag: BOOLEAN {запрашивается ли делегирование полномочий}
  • mutual_req_flag: BOOLEAN {запрашивается ли взаимная аутентификация}
  • replay_det_req_flag: BOOLEAN {запрашивается ли выявление продублированных токенов}
  • sequence_req_flag: BOOLEAN {запрашивается ли контроль целостности последовательности сообщений}
  • anon_req_flag: BOOLEAN {запрашивается ли анонимный контекст}
  • lifetime_req: INTEGER {запрашиваемый срок годности контекста в секундах; 0 означает подразумеваемый срок}
  • chan_bindings: OCTET_ STRING {набор каналов, с которым связывается контекст}
  • input_token: OCTET_ STRING {токен, полученный от партнера в результате предшествующих действий по формированию контекста; NULL означает, что формирование только начинается}

Выходные параметры:

  • major_status: INTEGER
  • minor_status: INTEGER
  • output_context_handle: CONTEXT_HANDLE {дескриптор формируемого контекста}
  • actual_mech_type: OBJECT_ IDENTIFIER {реальный механизм, поддерживающий формируемый контекст — значение, заведомо отличное от NULL}
  • output_token: OCTET_ STRING {выходной токен, который нужно переслать партнеру, чтобы тот мог продолжить формирование контекста; NULL означает, что больше ничего пересылать не нужно}
  • deleg_state: BOOLEAN {обеспечивается ли передача полномочий}
  • mutual_state: BOOLEAN {обеспечивается ли взаимная аутентификация}
  • replay_det_state: BOOLEAN {обеспечивается ли выявление продублированных токенов}
  • sequence_state: BOOLEAN {обеспечивается ли контроль целостности последовательности сообщений}
  • anon_state: BOOLEAN {обеспечивается ли анонимность контекста}
  • trans_state: BOOLEAN {возможен ли экспорт контекста}
  • prot_ready_state: BOOLEAN {обеспечивается ли защита сообщений, когда формирование контекста еще не завершено}
  • conf_avail: BOOLEAN {обеспечивается ли шифрование сообщений}
  • integ_avail: BOOLEAN {обеспечивается ли контроль целостности сообщений}
  • lifetime_rec: INTEGER {срок годности контекста в секундах}

Возможные значения основного кода завершения:

  • GSS_S_COMPLETE — контекст успешно инициализирован, а выходной токен содержит достаточно информации для завершения формирования контекста партнером и для начала защищенного обмена сообщениями.
  • GSS_S_CONTINUE_NEEDED — сгенерированный выходной токен нужно переслать партнеру. Тот должен прислать ответ, который послужит аргументом input_token для последующего ассоциированного вызова функции GSS_Init_sec_context. Пока не будет выдан код завершения GSS_S_COMPLETE, контекст безопасности нельзя считать сформированным.
  • GSS_S_DEFECTIVE_TOKEN — обнаружено нарушение целостности входного токена input_token. Формирование контекста не может быть продолжено.
  • GSS_S_DEFECTIVE_CREDENTIAL — обнаружено нарушение целостности удостоверения, заданного аргументом claimant_cred_handle. Формирование контекста не может быть продолжено.
  • GSS_S_BAD_SIG — входной токен input_toke содержит некорректную подпись. Формирование контекста не может быть продолжено.
  • GSS_S_NO_CRED — контекст не может быть сформирован либо по причине некорректности значения claimant_cred_handle, либо из-за того, что удостоверение не предназначено для инициации контекста, либо из-за отсутствия прав на использование данного удостоверения.
  • GSS_S_CREDENTIALS_EXPIRED — удостоверение просрочено. Формирование контекста не может быть продолжено.
  • GSS_S_BAD_BINDINGS — обнаружено несоответствие между информацией о наборе каналов, заданной аргументом chan_bindings, и аналогичной информацией, извлеченной из входного токена input_token. Несоответствие означает, что партнеры не могут договориться о привязке контекста к каналам. Формирование контекста не может быть продолжено.
  • GSS_S_NO_CONTEXT — значение параметра input_ context_handle не является корректным дескриптором контекста, в то время как оно должно быть таковым (выполняется не первый из ассоциированных вызовов GSS_ Init_sec_context). Формирование контекста не может быть продолжено.
  • GSS_S_BAD_NAMETYPE — запрашиваемое имя не удается проинтерпретировать. Формирование контекста не может быть продолжено.
  • GSS_S_BAD_NAME — некорректное имя. Формирование контекста не может быть продолжено.
  • GSS_S_BAD_MECH — запрашивается неподдерживаемый механизм безопасности. Формирование контекста не может быть продолжено.
  • GSS_S_FAILURE — формирование контекста не может быть продолжено по причинам, не специфицируемым на уровне GSS-API.

Вызов функции GSS_ Init_sec_context может привести к временной блокировке обратившегося к ней процесса, если для генерации контекста и получения выходного токена служба безопасности должна воспользоваться услугами сервера аутентификации, службы директорий или иного удаленного сервера.

Обычно для инициации контекста достаточно одного обращения к функции GSS_Init_ sec_context. Если это не так (например, из-за требования взаимной аутентификации), то для всех последующих обращений значение параметра claimant_cred_ handle должно оставаться неизменным. Это значение позволяет связать в цепочку ассоциированные вызовы GSS_Init_sec_context.

При первом обращении к GSS_Init_sec_context значение параметра input_context_handle должно равняться 0. При последующих вызовах его следует устанавливать равным output_context_handle (ассоциированные вызовы Goutput_context_handle, начиная со второго, не меняют дескриптор контекста безопасности).

Инициатор, посредством входных флагов, может запросить у службы безопасности предоставление дополнительных услуг: возможности делегирования прав доступа (флаг deleg_rec_flag), организации взаимной аутентификации (mutual_req_flag), контроля целостности последовательности сообщений (флаги replay_det_ req_flag и sequence_req_flag), сохранения инкогнито инициатора контекста (anon_req_flag). Соответствующие выходные флаги показывают, в состоянии ли служба безопасности предоставить запрашиваемые услуги. Кроме того, еще два выходных флага, integ_avail и conf_avail, показывают, поддерживается ли службой безопасности контроль целостности сообщений и их конфиденциальность (в принципе можно представить себе механизм, обеспечивающий только аутентификацию партнеров).

Отказ в поддержке некоторых запрашиваемых услуг не обязательно должен вести к отказу от формирования контекста безопасности. Мобильное приложение может принять те или иные меры (например, проинформировать пользователя о достижимом уровне защиты, взять на себя шифрование и т.п.), позволяющие продолжить работу.

GSS_Accept_sec_context — принятие контекста безопасности

Функция GSS_Accept_ sec_context предназначена для продолжения (как правило — завершения) формирования контекста безопасности. Мы будем называть это принятием контекста.

Входные параметры:

  • acceptor_cred_handle: CREDENTIAL_HANDLE {дескриптор удостоверения партнера, принимающего контекст; NULL означает подразумеваемое удостоверение}
  • input_context_handle: CONTEXT_HANDLE {дескриптор формируемого контекста; 0 означает, что принятие только начинается}
  • chan_bindings: OCTET_ STRING {набор каналов, с которым связывается контекст}
  • input_token: OCTET_ STRING {токен, полученный от партнера в результате предшествующих действий по формированию контекста}

Выходные параметры:

  • major_status: INTEGER
  • minor_status: INTEGER
  • src_name: INTERNAL_NAME {имя инициатора формирования контекста}
  • actual_mech_type: OBJECT_ IDENTIFIER {реальный механизм, поддерживающий формируемый контекст — значение, заведомо отличное от NULL}
  • output_context_handle: CONTEXT_HANDLE {дескриптор формируемого контекста}
  • deleg_state: BOOLEAN {обеспечивается ли передача полномочий}
  • mutual_state: BOOLEAN {обеспечивается ли взаимная аутентификация}
  • replay_det_state: BOOLEAN {обеспечивается ли выявление продублированных токенов}
  • sequence_state: BOOLEAN {обеспечивается ли контроль целостности последовательности сообщений}
  • anon_state: BOOLEAN {обеспечивается ли анонимность контекста}
  • trans_state: BOOLEAN {возможен ли экспорт контекста}
  • prot_ready_state: BOOLEAN {обеспечивается ли защита сообщений, когда формирование контекста еще не завершено}
  • conf_avail: BOOLEAN {обеспечивается ли шифрование сообщений}
  • integ_avail: BOOLEAN {обеспечивается ли контроль целостности сообщений}
  • lifetime_rec: INTEGER {срок годности контекста в секундах}
  • delegated_cred_handle: CREDENTIAL_HANDLE {дескриптор удостоверения, позволяющего инициировать новые контексты безопасности от имени партнера по общению и, тем самым, пользоваться его правами доступа}
  • output_token: OCTET_ STRING {выходной токен, который нужно переслать партнеру, чтобы тот мог продолжить формирование контекста; NULL означает, что больше ничего пересылать не нужно}

Функция GSS_Accept_ sec_context во многом аналогична функции инициации контекста GSS_Init_sec_context. Это относится и к кодам завершения, и к возможности повторных вызовов (если для формирования контекста требуется обмен несколькими токенами), и к блокировке обратившегося процесса, и к трактовке большинства входных и выходных параметров.

Отдельного рассмотрения заслуживают выходные параметры src_name и delegated_ cred_handle. Первый из них содержит имя инициатора формирования контекста. В принципе анализ этого имени может повлиять на поведение принимающего контекст. Если обеспечивается анонимность инициатора (установлен флаг anon_state), параметр src_name получает значение NULL (имя инициатора не было включено в токен безопасности).

Если установлен флаг deleg_state, то параметр delegated_cred_handle содержит дескриптор удостоверения, выданного на имя инициатора формирования контекста. Тем самым принимающей стороне делегируются полномочия формировать новые контексты безопасности не только от своего имени, но и от имени инициатора.Делегирование полномочий полезно, когда серверу требуется выполнить некоторые действия от имени клиента (например, сервер печати должен прочитать выдаваемые файлы).

GSS_GetMIC — обеспечение целостности сообщения

Функция GSS_GetMIC служит для обеспечения контроля целостности и подлинности источника сообщения. Сообщение и генерируемый токен безопасности являются корректными входными данными для последующего обращения к функции GSS_VerifyMIC.

Входные параметры:

  • context_handle: CONTEXT_ HANDLE {дескриптор контекста, в рамках которого происходит обмен сообщениями}
  • qop_req: INTEGER {запрашиваемое качество защиты; 0 обозначает подразумеваемое качество}
  • message: OCTET_STRING {защищаемое сообщение}

Выходные параметры:

  • major_status: INTEGER
  • minor_status: INTEGER
  • per_msg_token: OCTET_ STRING {генерируемый токен безопасности}

Возможные значения основного кода завершения:

  • GSS_S_COMPLETE — сообщение и сгенерированный токен безопасности готовы для передачи партнеру.
  • GSS_S_CONTEXT_EXPIRED — истек срок годности контекста.
  • GSS_S_CREDENTIALS_ EXPIRED — контекст распознан как корректный, однако срок годности ассоциированных с ним удостоверений истек.
  • GSS_S_NO_CONTEXT — не задан контекст.
  • GSS_S_BAD_QOP — некорректное значение параметра qop_req.
  • GSS_S_FAILURE — сообщение не может быть защищено по причинам, не специфицируемым на уровне GSS-API.

С помощью информации, содержащейся в контексте безопасности, для сообщения определяется порядковый номер и/или временной штамп, порождается электронная подпись отправителя и т.п. Сгенерированные данные включаются в токен безопасности, который следует передать вместе с исходным сообщением (последнее функцией GSS_GetMIC не изменяется).

Естественно, успешное завершение функции GSS_ GetMIC не гарантирует, что после передачи сообщения удаленному партнеру проверка, выполняемая функцией GSS_ VerifyMIC, даст положительный результат.

GSS_VerifyMIC — проверка целостности сообщения

Функция GSS_VerifyMIC позволяет проверить целостность и подлинность источника сообщения, защищенного функцией GSS_GetMIC.

Входные параметры:

  • context_handle: CONTEXT_ HANDLE {дескриптор контекста, в рамках которого происходит обмен сообщениями}
  • message: OCTET_STRING {контролируемое сообщение}
  • per_msg_token: OCTET_ STRING {токен безопасности, ассоциированный с сообщением}

Выходные параметры:

  • qop_state: INTEGER {обеспеченное качество защиты}
  • major_status: INTEGER
  • minor_status: INTEGER

Возможные значения основного кода завершения:

  • GSS_S_COMPLETE — проверка дала положительный результат.
  • GSS_S_DEFECTIVE_TOKEN — обнаружено искажение токена безопасности.
  • GSS_S_BAG_SIG — токен безопасности содержит некорректную электронную подпись.
  • GSS_S_DUPLICATE_TOKEN, GSS_S_OLD_TOKEN, GSS_S_UNSEQ_TOKEN, GSS_S_GAP_TOKEN — обнаружено дублирование или нарушение последовательности сообщений.
  • GSS_S_CONTEXT_EXPIRED, GSS_S_CREDENTIALS_EXPIRED, GSS_S_NO_ CONTEXT — то же, что и в случае GSS_GetMIC.
  • GSS_S_FAILURE — сообщение не может быть проверено по причинам, не специфицируемым на уровне GSS-API.

С помощью информации, содержащейся в контексте безопасности, проверяется целостность и подлинность источника сообщения и ассоциированного токена безопасности (корректность значения криптографической контрольной суммы, подлинность электронной подписи, допустимость порядкового номера и временного штампа и т.п.).

Выходной параметр qop_state показывает, защита какого качества была задействована соответствующим вызовом функции GSS_GetMIC.

GSS_Wrap — шифрование сообщения

Функция GSS_Wrap, помимо услуг, предоставляемых вызовом GSS_GetMIC, может обеспечить шифрование сообщения. В отличие от GSS_ GetMIC, результатом работы GSS_Wrap является инкапсулированное сообщение, содержащее необходимую контрольную информацию, а не исходное сообщение с дополнительным токеном безопасности.

Входные параметры:

  • context_handle: CONTEXT_ HANDLE {дескриптор контекста, в рамках которого происходит обмен сообщениями}
  • conf_req_flag: BOOLEAN {нужно ли шифровать защищаемое сообщение}
  • qop_req: INTEGER {запрашиваемое качество защиты; 0 обозначает подразумеваемое качество}
  • input_message: OCTET_ STRING {защищаемое сообщение}

Выходные параметры:

  • major_status: INTEGER
  • minor_status: INTEGER
  • conf_state: BOOLEAN {было ли сообщение на самом деле зашифровано}
  • output_message: OCTET_ STRING {инкапсулированное сообщение}

Возможные значения основного кода завершения для функции GSS_Wrap те же, что и для GSS_GetMIC.

С помощью информации, содержащейся в контексте безопасности, сообщение защищается от искажений и, быть может, шифруется. Порождаемое выходное сообщение output_message подлежит передаче партнеру по общению.

GSS_Unwrap — расшифровка сообщения

Функция GSS_Unwrap позволяет расшифровать, проверить целостность и подлинность источника применительно к сообщению, защищенному функцией GSS_Wrap.

Связь между функциями GSS_Wrap и GSS_Unwrap аналогична той, что существует между функциями GSS_ GetMIC и GSS_VerifyMIC.

Входные параметры:

  • context_handle: CONTEXT_ HANDLE {дескриптор контекста, в рамках которого происходит обмен сообщениями}
  • input_message: OCTET_ STRING {контролируемое сообщение}

Выходные параметры:

  • conf_state: BOOLEAN {было ли сообщение на самом деле зашифровано}
  • qop_state: INTEGER {обеспеченное качество защиты}
  • major_status: INTEGER
  • minor_status: INTEGER
  • output_message: OCTET_ STRING {расшифрованное сообщение}

Возможные значения основного кода завершения для функции GSS_Unwrap те же, что и для GSS_VerifyMIC.

С помощью информации, содержащейся в контексте безопасности, функция GSS_Unwrap расшифровывает сообщение, проверяется его целостность и подлинность источника. Расшифрованное сообщение выдается в качестве значения выходного параметра output_message.

Ограничения интерфейса безопасности

Обобщенный прикладной программный интерфейс службы безопасности GSS-API не содержит средств, направленных на контроль прав доступа или хотя бы на передачу авторизационной информации. Для этого, однако, есть веские причины.

Интерфейс безопасности должен обслуживать разнообразные приложения. Содержательная трактовка прав доступа, как и определение того, что (или кто) является объектом или субъектом контроля, может быть выполнена только самими приложениями. Даже для устоявшихся и сравнительно однородных сервисов, таких как файловый, авторизация в разных операционных средах может носить существенно разный характер. Более того, характер авторизации может меняться и для одной операционной среды при переходе от изолированной системы к распределенной конфигурации. В качестве примера достаточно привести SunOS, где правила доступа к файлам, находящимся на смонтированных NFS-томах, гораздо сложнее, чем в локальном случае.

Другую причину можно назвать политической. Спецификациям GSS-API в их нынешнем виде удовлетворяет такая популярная система, как Kerberos, не содержащая средств контроля доступа. Специфицировать подобные средства в GSS-API — значит лишиться поддержки со стороны Kerberos. В результате такой акции интерфейс безопасности «повиснет в воздухе», из-под него будет выбита почва.

В то же время проблемы авторизации, делегирования полномочий с ограничениями, несомненно, требуют решения (на прикладном уровне). Как передать серверу печати право на доступ только к определенным файлам и только на чтение? Как защитить строки своих таблиц в базе данных от удаления сервером приложений, оставив за ним возможность добавления информации? В общем виде решение очевидно — нужно перестроить систему авторизации на основе архитектуры клиент/сервер. В нынешней ситуации, когда каждое приложение (операционная система, СУБД, почтовая служба и т.п.) использует специфические методы контроля доступа, универсальное, стандартное решение в духе открытых систем получить невозможно.

Впрочем, первый и весьма важный шаг уже сделан. Имеется в виду реализация серверов аутентификации, которые позволили системно-независимым образом идентифицировать субъекты доступа. Трудно сказать, насколько быстро процесс пойдет дальше. По-видимому, рассчитывать на быстрый прогресс не приходится — слишком велика масса программного обеспечения, нуждающегося в пересмотре.

Еще одна проблема технического плана, вытекающая из архитектуры интерфейса GSS-API, состоит в том, что для коротких сообщений накладные расходы, связанные с обеспечением целостности и конфиденциальности данных, могут оказаться весьма значительными. Это может резко ухудшить характеристики таких протоколов, как telnet. Выбор минимально допустимого качества защиты и буферизация данных — вот методы, которые, вероятно, способны улучшить ситуацию.

Представление некоторых объектов интерфейса безопасности в среде языка C

Представление средствами языка C объектов, фигурирующих в обобщенном интерфейсе безопасности GSS-API, по большей части довольно очевидно (или не может быть стандартизовано, так как зависит от специфики механизма безопасности).

Прежде всего, вводится тип OM_uint32, соответствующий 32-битным беззнаковым целым значениям. Большинство структурных значений представляется с помощью указателя на дескриптор).

Листинг 1

Тип gss_buffer_t используется при задании составных аргументов — имен, дескрипторов, токенов, сообщений и т.п.

Идентификаторы объектов представляются следующим образом:

Листинг 2

Указатели elements ссылаются на начало представления идентификаторов, то есть на последовательности байт, устроенных в соответствии с базовыми правилами ASN.1.

Наборы объектных идентификаторов представлены на Рис. 2.

Рисунок 2. Наборы объектных идентификаторов

Листинг 3

Вводятся и некоторые другие типы, уточняющие представление структурированных значений.

Описание функции GSS_ Init_sec_context на языке C показано на Рис. 3.

Рисунок 3. Описание функции GSS_ Init_sec_context

Листинг 4

Отметим, что параметр context_handle является здесь одновременно входным и выходным, а основной код завершения возвращается как результат функции.

На Рис. 4 приведено определение еще нескольких величин.

Рисунок 4. Дополнительные определения

Листинг 5

Разумеется, есть еще много аспектов, оговоренных в документе [3], например, кто и когда отводит память под объекты и под дескрипторы, и каким образом эту память можно освобождать. Мы, однако, не будем на этом останавливаться.

Заключение

Обобщенный прикладной программный интерфейс службы безопасности GSS-API — попытка распространения идеологии открытых систем на такую важную и сложную область, как защита коммуникаций в среде клиент/сервер. Попытка эта представляется успешной. Сформулирован компактный интерфейс, допускающий естественное отображение на разные языковые среды и различные механизмы безопасности. В то же время выразительных возможностей интерфейса достаточно для решения задач аутентификации партнеров по общению и обеспечения целостности и конфиденциальности пересылаемой информации.

Литература

  1. J. Linn — Generic Security Service Application Program Interface, Version 2 — Internet-Draft, February 1996
  2. J. Linn — Generic Security Service Application Program Interface — Request for Comments: 1508, September 1993
  3. J. Wray — Generic Security Service API: C-bindings — Request for Comments: 1509, September 1993
  4. J. Kohl — The Kerberos Network Authentication Service (V5) — Request for Comments: 1510, September 1993
  5. Recommendation X.509. The Directory — Authentication Framework — Melbourne, 1988

Понравилась статья? Поделить с друзьями:
  • Покер старс ошибка 101
  • Повторная регистрация первичного документа ошибка 3 ндфл
  • Покемон го почему выдает ошибку
  • Повторная регистрация первичного документа код ошибки 0400200005
  • Показывать ошибки php ini