Skip to content

Commit

Permalink
Generate ASN.1 DER encoding for mechanism name.
Browse files Browse the repository at this point in the history
  • Loading branch information
adiaholic committed Jan 27, 2020
1 parent 9d626bf commit 30004d8
Show file tree
Hide file tree
Showing 6 changed files with 356 additions and 0 deletions.
1 change: 1 addition & 0 deletions smack-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies {
compile "org.jxmpp:jxmpp-core:$jxmppVersion"
compile "org.jxmpp:jxmpp-jid:$jxmppVersion"
compile "org.minidns:minidns-core:$miniDnsVersion"
compile "org.bouncycastle:bcprov-jdk15on:1.57"

This comment has been minimized.

Copy link
@vanitasvitae

vanitasvitae Jan 28, 2020

Member

There is $bouncyCastleVersion in version.gradle

testCompile project(':smack-xmlparser-stax')
testCompile project(':smack-xmlparser-xpp3')
testCompile "org.jxmpp:jxmpp-jid:$jxmppVersion:tests"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
*
* Copyright 2020 Aditya Borikar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack.sasl.gssApi;

/**
* If GSS_Inquire_SASLname_for_mech() fails and the GS2 implementation cannot
* map the OID to a SASL mechanism name via some other means, then the
* GS2 implementation MUST NOT use the given GSS-API mechanism.
* @author adiaholic
*
*/
public abstract class GSS_Inquire_SASLname {

public abstract boolean GSS_Inquire_SASLname_for_mech();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
/**
*
* Copyright 2020 Aditya Borikar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack.sasl.gssApi;

import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.security.auth.callback.CallbackHandler;

import org.jivesoftware.smack.SmackException.SmackSaslException;
import org.jivesoftware.smack.sasl.SASLMechanism;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;

/**
* Use of GSS-API mechanism in SASL by defining a new SASL mechanism family called GS2.
* This mechanism offers a number of improvements over the previous "SASL/GSSAPI" mechanism.
* In general, it uses fewer messages for authentication phase in some cases, and supports negotiable use of channel binding.
* Only GSS-API mechanisms that support channel binding and mutual authentication are supported.
* <br>
* The absence of `PLUS` suffix in the name `GSS-API` suggests that the server doesn't support channel binding.
* <br>
* SASL implementations can use the GSS_Inquire_SASLname_for_mech call
* to query for the SASL mechanism name of a GSS-API mechanism.
* <br>
* If the GSS_Inquire_SASLname_for_mech interface is not used, the GS2
* implementation needs some other mechanism to map mechanism Object
* Identifiers (OIDs) to SASL names internally.
* <br>
* In this case, the implementation can only support the mechanisms for which it knows the
* SASL name.
*
* @author adiaholic
*/
public class GssApiMechanism extends SASLMechanism{

public static final String NAME = "GSS-API";

public static final String GS2_PREFIX = "GS2-";

private String objectID = null;
/*
* The SASL Mechanism name is concatenation of the string "GS2-" and the
* Base32 encoding of the first 55 bits of the binary SHA-1 hash string
* computed over the ASN.1 DER encoding
* <br>
* Note : Some older GSS-API mechanisms were not specified with a SASL GS2 mechanism name.
*/
public String generateSASLMechanismNameFromGSSApiOIDs (String objectIdentifier) throws NoSuchAlgorithmException, IOException {

/*
* If any padding or non-alphabet characters are encountered,
* the name is not a GS2 family mechanism name.
* This name denotes that the server does not support channel binding,
* because the suffix "-PLUS" is missing .
*/

// To calculate the binary SHA-1 Hash
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] messageDigest = md.digest(getASN1DERencoding(objectIdentifier));
BigInteger no = new BigInteger(1, messageDigest);
String hashtext = no.toString(16);
while (hashtext.length() < 32) {
hashtext = "0" + hashtext;
}
String binarySHA1Hash = getFirst_7_OctetsInBinary(hashtext);
binarySHA1Hash = binarySHA1Hash.substring(0, 54);

String mechanismName = GS2_PREFIX + getBase32Encoding(binarySHA1Hash);

return mechanismName;
}

public String getBase32Encoding(String binarySHA1Hash) {
return binarySHA1Hash;
}

public String getFirst_7_OctetsInBinary(String hashtext) {
// first_7_octets_to_binary_drop_last_bit = "00011100 11111000 11110100 00101011
// 01011010 10011111 1000000";
return hashtext;
}

public byte[] getASN1DERencoding(String objectIdentifier) throws IOException {
ASN1ObjectIdentifier asn1ObjectIdentifier = new ASN1ObjectIdentifier(objectIdentifier).intern();
byte[] encoded = asn1ObjectIdentifier.getEncoded();
return encoded;
}

/*
* A GS2 mechanism that has a non-OID-derived SASL mechanism name is
* said to have a "user-friendly SASL mechanism name".
*/
public void generateSASLMechanismNameManually() {
}

@Override
protected void authenticateInternal(CallbackHandler cbh) throws SmackSaslException {
}

@Override
protected byte[] getAuthenticationText() throws SmackSaslException {
/**
* During the SASL authentication exchange for GS2, a number of messages
* following the following format are sent between the client and server. On
* success, this number is the same as the number of context tokens that the
* GSS-API mechanism would normally require in order to establish a security
* context. On failures, the exchange can be terminated early by any party.
*
* When using a GS2 mechanism the SASL client is always a GSS-API initiator and
* the SASL server is always a GSS-API acceptor. The client calls
* GSS_Init_sec_context and the server calls GSS_Accept_sec_context.
*
* All the SASL authentication messages exchanged are exactly the same as the
* security context tokens of the GSS-API mechanism, except for the initial
* security context token.
*
* The client and server MAY send GSS-API error tokens (tokens output by
* GSS_Init_sec_context() or GSS_Accept_sec_context() when the major status code
* is other than GSS_S_COMPLETE or GSS_S_CONTINUE_NEEDED). As this indicates an
* error condition, after sending the token, the sending side should fail the
* authentication.
*
* The initial security context token is modified as follows:
*
* o The initial context token header (see Section 3.1 of [RFC2743]) MUST be
* removed if present. If the header is not present, the client MUST send a
* "gs2-nonstd-flag" flag (see below). On the server side, this header MUST be
* recomputed and restored prior to passing the token to GSS_Accept_sec_context,
* except when the "gs2- nonstd-flag" is sent.
*
* o A GS2 header MUST be prefixed to the resulting initial context token. This
* header has the form "gs2-header" given below in ABNF [RFC5234].
*
* The figure below describes the permissible attributes, their use, and the
* format of their values. All attribute names are single US-ASCII letters and
* are case sensitive.
*
* The "gs2-cb-flag" signals the channel binding mode. One of "p", "n", or "y"
* is used. A "p" means the client supports and used a channel binding, and the
* name of the channel binding type is indicated. An "n" means that the client
* does not support channel binding. A "y" means the client supports channel
* binding, but believes the server does not support it, so it did not use a
* channel binding. See the next section for more details.
*/

// @Todo : Remove initial context token header if present

// @Todo : If header is not present, the client must send a 'gs2-nonstd-flag'.

// @Todo : GS2 header must be prefixed to the resulting initial context token.
// This header has the form 'gs2-header'
// ASN1InputStream input = new ASN1InputStream(objectID.getBytes());

return null;
}

@Override
public String getName() {
return NAME;
}

@Override
public int getPriority() {
return 0;
}

@Override
protected void checkIfSuccessfulOrThrow() throws SmackSaslException {
}

@Override
protected GssApiMechanism newInstance() {
return new GssApiMechanism();
}

public String getObjectID() {
return objectID;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
*
* Copyright 2020 Aditya Borikar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack.sasl.gssApi;

import javax.security.auth.callback.CallbackHandler;

import org.jivesoftware.smack.SmackException.SmackSaslException;
import org.jivesoftware.smack.sasl.SASLMechanism;

/**
* The plus inside the GSS-API-plus mechanism name suggests that the server supports channel binding.
*
* @author adiaholic
*/
public class GssApiPlusMechanism extends SASLMechanism{

@Override
protected void authenticateInternal(CallbackHandler cbh) throws SmackSaslException {
}

@Override
protected byte[] getAuthenticationText() throws SmackSaslException {
return null;
}

@Override
public String getName() {
return null;
}

@Override
public int getPriority() {
return 0;
}

@Override
protected void checkIfSuccessfulOrThrow() throws SmackSaslException {
}

@Override
protected SASLMechanism newInstance() {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
*
* Copyright 2020 Aditya Borikar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack.sasl.gssApi;
/*
* Implementation for RFC 5801 : GSSAPI for SASL - The GS2 Mechanism Family.
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
*
* Copyright 2020 Aditya Borikar
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack.sasl.gssApi;

import static org.junit.Assert.assertEquals;

import java.io.IOException;

import org.jivesoftware.smack.test.util.SmackTestSuite;

import org.junit.Test;

public class GssApiMechanismTest extends SmackTestSuite {

public static final String OID = "1.2.840.113554.1.2.2";

public static final String ASN_1_DER_of_OID_in_HEX = "06092A864886F712010202";

public static final String SHA1_of_ASN_1_DER_in_HEX = "1c f8 f4 2b 5a 9f 80 fa e9 f8 31 22 6d 5d 9d 56 27 86 61 ad";
public static final String first_7_octets_to_binary_drop_last_bit = "00011100 11111000 11110100 00101011 01011010 10011111 1000000";
public static final String binary_in_group_of_5 = "00011 10011 11100 01111 01000 01010 11010 11010 10011 11110 00000";
public static final String decimal_of_each_group = "3 19 28 15 8 10 26 26 19 30 0";
public static final String base32Encoding = "DT4PIK22T6A";
public static final String MECHANISM_NAME = "GS2-" + base32Encoding;

@Test
public void generateASN1DERTest() throws IOException {
GssApiMechanism gssApiMechanism = new GssApiMechanism();
byte[] asn1DERencoding = gssApiMechanism.getASN1DERencoding(OID);

String asn1_der_of_oid_in_hex = "";

for (byte b : asn1DERencoding) {
asn1_der_of_oid_in_hex += String.format("%02X", b);
}
assertEquals(ASN_1_DER_of_OID_in_HEX, asn1_der_of_oid_in_hex);
}
}

0 comments on commit 30004d8

Please sign in to comment.