[英]Decrypt kerberos ticket using Spnego
我正在使用spnego( http://spnego.sourceforge.net )在JBoss下進行kerberos身份驗證。
我需要解密kerberos票證才能訪問包含PAC數據的授權數據。 需要PAC數據來決定將哪些角色授予用戶。
如何訪問和解密kerberos票? 我在網上搜索了一些例子,但沒有努力。
我已成功使用http://spnego.sourceforge.net中的servlet過濾器與http://jaaslounge.sourceforge.net/中的PAC解析器結合使用,而無需使用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,它通過getUserPrincipal()公開了LogonInfo。
可以在此處找到完整演示上述代碼的示例項目:
https://github.com/EleotleCram/jetty-spnego-demo
spnego-pac過濾器(在上面的例子中使用)可以在這里找到:
https://github.com/EleotleCram/spnego.sf.net-fork
希望這對任何人都有幫助。
__
馬塞爾
這些人有完整的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票證,您將需要跳過一些箍。 不確定你是否需要它。
格蘭特
我提供了自己的問題解決方案:
我的解決方案基於BouncyCastle庫(用於解析部分令牌)和JaasLounge(用於解密令牌的加密部分)。 不幸的是,從JaasLounge解碼整個spnego令牌的代碼失敗了我的要求。 我必須自己寫。
我已經逐個解碼了票證,首先從byte []數組構造DERObjects:
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。
根包含:
1級包含:
2級包含:
0x01 0x00
,解析為布爾值(false) 3級包含:
機票部分 - 第4級包含:
加密的零件序列(級別5)包含:
問題出在DERBoolean構造函數中,當發現序列0x01 0x00時拋出ArrayIndexOutOfBoundException。 我不得不改變那個構造函數:
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];
}
如果你從spnegoToken
獲得機制令牌,如下所示:
byte[] mechanismToken = spnegoToken.getMechanismToken();
機制令牌通常是KerberosApRequest
。 有一個KerberosToken
構造函數,它接受KerberosApRequest
。 只需傳入mechanismToken
字節數組和密鑰即可解密內容。
自從我使用了spnego(將近一年)以來已經有一段時間......你問的是一個非常酷的問題。
我做了一點挖掘,並嘗試運行一些我曾經使用MS-AD的代碼,但今天感覺不到: - /
無論如何,我通過谷歌找到了這個鏈接: http : //www.google.com/url? sa = t&source = web&cd = 1&sqi = 2&ed = 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
希望這可以給你一些見解。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.