Расшифровать билет Kerberos, используя Spnego - PullRequest
14 голосов
/ 22 декабря 2010

Я использую spnego (http://spnego.sourceforge.net) для аутентификации kerberos под JBoss.

Мне нужно расшифровать билет kerberos для доступа к данным авторизации, которые будут содержать данные PAC.Данные PAC необходимы, чтобы решить, какие роли должны быть предоставлены пользователю.

Как получить доступ и расшифровать билет Kerberos?Я искал в сети примеры, но без усилий.

Ответы [ 5 ]

8 голосов
/ 10 апреля 2012

Я успешно использовал фильтр сервлета из http://spnego.sourceforge.net в сочетании с синтаксическим анализатором PAC из http://jaaslounge.sourceforge.net/ без необходимости явно что-то делать с анализаторами DER / ASN.1:

/** 
 * Retrieve LogonInfo (for example, Group SID) from the PAC Authorization Data
 * from a Kerberos Ticket that was issued by Active Directory.
 */  
byte[] kerberosTokenData = gssapiData;
try {
    SpnegoToken token = SpnegoToken.parse(gssapiData);
    kerberosTokenData = token.getMechanismToken();
} catch (DecodingException dex) {
    // Chromium bug: sends a Kerberos response instead of an spnego response 
    // with a Kerberos mechanism
} catch (Exception ex) {
    log.error("", ex);
}   

try {
    Object[] keyObjs = IteratorUtils.toArray(loginContext.getSubject()
                         .getPrivateCredentials(KerberosKey.class).iterator());
    KerberosKey[] keys = new KerberosKey[keyObjs.length];
    System.arraycopy(keyObjs, 0, keys, 0, keyObjs.length);

    KerberosToken token = new KerberosToken(kerberosTokenData, keys);
    log.info("Authorizations: "); 
    for (KerberosAuthData authData : token.getTicket().getEncData()
                                             .getUserAuthorizations()) {
        if (authData instanceof KerberosPacAuthData) {
            PacSid[] groupSIDs = ((KerberosPacAuthData) authData)
                                      .getPac().getLogonInfo().getGroupSids();
            log.info("GroupSids: " + Arrays.toString(groupSIDs));
            response.getWriter().println("Found group SIDs: " + 
                Arrays.toString(groupSIDs));
        } else {
            log.info("AuthData without PAC: " + authData.toString());
        }   
    }   
} catch (Exception ex) {
    log.error("", ex);
}   

Я также написал новый HttpFilter (разветвленный от spnego.sf.net): spnego-pac, который раскрывает LogonInfo через getUserPrincipal ().

Пример проекта, демонстрирующий приведенный выше код вполный можно найти здесь:

https://github.com/EleotleCram/jetty-spnego-demo

Фильтр spnego-pac (используется в приведенном выше примере) можно найти здесь:

https://github.com/EleotleCram/spnego.sf.net-fork

Надеюсь, это кому-нибудь пригодится.

__Marcel

8 голосов
/ 07 января 2011

Эти ребята имеют полную реализацию декодирования PAC:

http://jaaslounge.sourceforge.net/

Вы можете использовать анализатор токенов следующим образом:

HttpServletRequest request = (HttpServletRequest) req;
String header = request.getHeader("Authorization");
byte[] base64Token = header.substring(10).getBytes("UTF-8");
byte[] spnegoHeader = Base64.decode(base64Token);

SpnegoInitToken spnegoToken = new SpnegoInitToken(spnegoHeader);

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

Грант

5 голосов
/ 23 августа 2013

Я предоставляю свое собственное решение проблемы:

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

Я декодировал билет по частям, сначала создавая DERObjects из массива byte []:

private DERObject[] readDERObjects(byte[] bytes) throws IOException {
    ASN1InputStream stream = new ASN1InputStream(new ByteArrayInputStream(
        bytes));
    List<DERObject> objects = new ArrayList<DERObject>();
    DERObject curObj;
    while ((curObj = stream.readObject()) != null) {
        objects.add(untag(curObj));
    }
    return objects.toArray(new DERObject[0]);
}

Untag () - моя вспомогательная функция, чтобыудалить обертку DERTaggedObject

private DERObject untag(DERObject src) {
    if (src instanceof DERTaggedObject) {
        return ((DERTaggedObject) src).getObject();
    }
    return src;
}

Для извлечения последовательности DERObject из заданного DERObject я написал еще одну вспомогательную функцию:

private DERObject[] readDERObjects(DERObject container) throws IOException {
// do operation varying from the type of container
if (container instanceof DERSequence) {
    // decode using enumerator
    List<DERObject> objects = new ArrayList<DERObject>();
    DERSequence seq = (DERSequence) container;
    Enumeration enumer = seq.getObjects();
    while (enumer.hasMoreElements()) {
    DERObject curObj = (DERObject) enumer.nextElement();
    objects.add(untag(curObj));
    }
    return objects.toArray(new DERObject[0]);
}
if (container instanceof DERApplicationSpecific) {
    DERApplicationSpecific aps = (DERApplicationSpecific) container;
    byte[] bytes = aps.getContents();
    return readDERObjects(bytes);
}
if (container instanceof DEROctetString) {
    DEROctetString octets = (DEROctetString) container;
    byte[] bytes = octets.getOctets();
    return readDERObjects(bytes);
}
throw new IllegalArgumentException("Unable to decode sequence from "+container);
}

В конце, когда у меня появился DEROctetStream, он содержалзашифрованная часть, я только что использовал KerberosEncData:

KerberosEncData encData = new KerberosEncData(decrypted, matchingKey);

Последовательность байтов, которую мы получаем от браузера клиента, будет проанализирована в один DERApplicationSpecific, который является корневым уровнем билета 0.Корень содержит:

  • DERObjectIdentifier - SPNEGO OID
  • DERSequence - уровень 1

Уровень 1 содержит:

  • SEQUENCE DERObjectIdentifier - типы мехов
  • DEROctetString - завернутый DERApplicationSepecific - уровень 2

Уровень 2 содержит:

  • DERObjectIndentifier - Kerberos OID
  • KRB5_AP_REQ tag 0x01 0x00, анализируется как логическое значение (false)
  • DERApplicationSpecific - контейнер DERSequence - уровень 3

Уровень 3 содержит:

  • номер версии - должен быть 5
  • тип сообщения - 14 (AP_REQ)
  • опции AP (DERBITString)
  • DERApplicationSpecific - завернутый DERSequence с частью билета
  • DERSeqeuence с дополнительной частью билета - не обработано

Часть билета - уровень 4 содержит:

  • Версия билета - должно быть 5
  • Ticket realm - имя области, в которой аутентифицирован пользователь.
  • DERSequence имен серверов.Каждому имени сервера соответствует DERSequence из двух строк: имя сервера и имя экземпляра
  • DERSequence с зашифрованной частью

Последовательность зашифрованной части (уровень 5) содержит:

  • Используемый номер алгоритма
    • 1, 3 - DES
    • 16 - des3-cbc-sha1-kd
    • 17 - ETYPE-AES128-CTS-HMAC-SHA1-96
    • 18 - ETYPE-AES256-CTS-HMAC-SHA1-96
    • 23 - RC4-HMAC
    • 24 - RC4-HMAC-EXP
  • Номер версии ключа
  • Зашифрованная часть (DEROctetStream)

Проблема была с конструктором DERBoolean, который выдает ArrayIndexOutOfBoundException, когда была найдена последовательность 0x01 0x00.Мне пришлось изменить этот конструктор:

public DERBoolean(
    byte[]       value)
{
// 2011-01-24 llech make it byte[0] proof, sequence 01 00 is KRB5_AP_REQ
if (value.length == 0)
    this.value = 0;
else
    this.value = value[0];
}
5 голосов
/ 18 января 2011

Если вы получаете токен механизма от spnegoToken, например:

byte[] mechanismToken = spnegoToken.getMechanismToken(); 

Маркер механизма обычно является KerberosApRequest. Существует конструктор KerberosToken, который принимает KerberosApRequest. Просто передайте массив байтов mechanismToken вместе с ключом для расшифровки содержимого.

2 голосов
/ 22 декабря 2010

Ух ты, давно я пользовался spnego (почти год) ... Ты задаешь очень крутой вопрос.

Я немного покопался и собирался попытаться запустить какой-то код, который у меня был недавно, который работал с MS-AD, но просто не чувствовал его сегодня: - /

Во всяком случае, я нашел эту ссылку через Google: http://www.google.com/url?sa=t&source=web&cd=1&sqi=2&ved=0CBMQFjAA&url=http%3A%2F%2Fbofriis.dk%2Ffiles%2Fms_kerberos_pac.pdf&rct=j&q=java%20kerberos%20privilege%20attribute%20certificate&ei=2FASTbaLGcP38Abk07iQDg&usg=AFQjCNHcIfQRUTxkQUvLRcgOaQksCALTHA&sig2=g8yn7ie1PbzSkE2Mfv41Bw&cad=rja

Надеюсь, это поможет вам понять.

...