| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.security.jgss.spnego;  | 
 | 
 | 
 | 
import java.io.*;  | 
 | 
import java.util.*;  | 
 | 
import org.ietf.jgss.*;  | 
 | 
import sun.security.jgss.*;  | 
 | 
import sun.security.util.*;  | 
 | 
 | 
 | 
/**  | 
 | 
 * Implements the SPNEGO NegTokenTarg token  | 
 | 
 * as specified in RFC 2478  | 
 | 
 *  | 
 | 
 * NegTokenTarg ::= SEQUENCE { | 
 | 
 *      negResult   [0] ENUMERATED { | 
 | 
 *              accept_completed        (0),  | 
 | 
 *              accept_incomplete       (1),  | 
 | 
 *              reject                  (2) }   OPTIONAL,  | 
 | 
 *      supportedMech   [1] MechType            OPTIONAL,  | 
 | 
 *      responseToken   [2] OCTET STRING        OPTIONAL,  | 
 | 
 *      mechListMIC     [3] OCTET STRING        OPTIONAL  | 
 | 
 * }  | 
 | 
 *  | 
 | 
 * MechType::= OBJECT IDENTIFIER  | 
 | 
 *  | 
 | 
 *  | 
 | 
 * @author Seema Malkani  | 
 | 
 * @since 1.6  | 
 | 
 */  | 
 | 
 | 
 | 
public class NegTokenTarg extends SpNegoToken { | 
 | 
 | 
 | 
    private int negResult = 0;  | 
 | 
    private Oid supportedMech = null;  | 
 | 
    private byte[] responseToken = null;  | 
 | 
    private byte[] mechListMIC = null;  | 
 | 
 | 
 | 
    NegTokenTarg(int result, Oid mech, byte[] token, byte[] mechListMIC)  | 
 | 
    { | 
 | 
        super(NEG_TOKEN_TARG_ID);  | 
 | 
        this.negResult = result;  | 
 | 
        this.supportedMech = mech;  | 
 | 
        this.responseToken = token;  | 
 | 
        this.mechListMIC = mechListMIC;  | 
 | 
    }  | 
 | 
 | 
 | 
    // Used by sun.security.jgss.wrapper.NativeGSSContext  | 
 | 
      | 
 | 
    public NegTokenTarg(byte[] in) throws GSSException { | 
 | 
        super(NEG_TOKEN_TARG_ID);  | 
 | 
        parseToken(in);  | 
 | 
    }  | 
 | 
 | 
 | 
    final byte[] encode() throws GSSException { | 
 | 
        try { | 
 | 
              | 
 | 
            DerOutputStream targToken = new DerOutputStream();  | 
 | 
 | 
 | 
              | 
 | 
            DerOutputStream result = new DerOutputStream();  | 
 | 
            result.putEnumerated(negResult);  | 
 | 
            targToken.write(DerValue.createTag(DerValue.TAG_CONTEXT,  | 
 | 
                                true, (byte) 0x00), result);  | 
 | 
 | 
 | 
              | 
 | 
            if (supportedMech != null) { | 
 | 
                DerOutputStream mech = new DerOutputStream();  | 
 | 
                byte[] mechType = supportedMech.getDER();  | 
 | 
                mech.write(mechType);  | 
 | 
                targToken.write(DerValue.createTag(DerValue.TAG_CONTEXT,  | 
 | 
                                                true, (byte) 0x01), mech);  | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            if (responseToken != null) { | 
 | 
                DerOutputStream rspToken = new DerOutputStream();  | 
 | 
                rspToken.putOctetString(responseToken);  | 
 | 
                targToken.write(DerValue.createTag(DerValue.TAG_CONTEXT,  | 
 | 
                                        true, (byte) 0x02), rspToken);  | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            if (mechListMIC != null) { | 
 | 
                if (DEBUG) { | 
 | 
                    System.out.println("SpNegoToken NegTokenTarg: " + | 
 | 
                                                "sending MechListMIC");  | 
 | 
                }  | 
 | 
                DerOutputStream mic = new DerOutputStream();  | 
 | 
                mic.putOctetString(mechListMIC);  | 
 | 
                targToken.write(DerValue.createTag(DerValue.TAG_CONTEXT,  | 
 | 
                                        true, (byte) 0x03), mic);  | 
 | 
            } else if (GSSUtil.useMSInterop()) { | 
 | 
                  | 
 | 
                if (responseToken != null) { | 
 | 
                    if (DEBUG) { | 
 | 
                        System.out.println("SpNegoToken NegTokenTarg: " + | 
 | 
                                "sending additional token for MS Interop");  | 
 | 
                    }  | 
 | 
                    DerOutputStream rspToken = new DerOutputStream();  | 
 | 
                    rspToken.putOctetString(responseToken);  | 
 | 
                    targToken.write(DerValue.createTag(DerValue.TAG_CONTEXT,  | 
 | 
                                                true, (byte) 0x03), rspToken);  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            DerOutputStream out = new DerOutputStream();  | 
 | 
            out.write(DerValue.tag_Sequence, targToken);  | 
 | 
 | 
 | 
            return out.toByteArray();  | 
 | 
 | 
 | 
        } catch (IOException e) { | 
 | 
            throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,  | 
 | 
                "Invalid SPNEGO NegTokenTarg token : " + e.getMessage());  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void parseToken(byte[] in) throws GSSException { | 
 | 
        try { | 
 | 
            DerValue der = new DerValue(in);  | 
 | 
              | 
 | 
            if (!der.isContextSpecific((byte) NEG_TOKEN_TARG_ID)) { | 
 | 
                throw new IOException("SPNEGO NegoTokenTarg : " + | 
 | 
                        "did not have the right token type");  | 
 | 
            }  | 
 | 
            DerValue tmp1 = der.data.getDerValue();  | 
 | 
            if (tmp1.tag != DerValue.tag_Sequence) { | 
 | 
                throw new IOException("SPNEGO NegoTokenTarg : " + | 
 | 
                        "did not have the Sequence tag");  | 
 | 
            }  | 
 | 
 | 
 | 
              | 
 | 
            int lastField = -1;  | 
 | 
            while (tmp1.data.available() > 0) { | 
 | 
                DerValue tmp2 = tmp1.data.getDerValue();  | 
 | 
                if (tmp2.isContextSpecific((byte)0x00)) { | 
 | 
                    lastField = checkNextField(lastField, 0);  | 
 | 
                    negResult = tmp2.data.getEnumerated();  | 
 | 
                    if (DEBUG) { | 
 | 
                        System.out.println("SpNegoToken NegTokenTarg: negotiated" + | 
 | 
                                    " result = " + getNegoResultString(negResult));  | 
 | 
                    }  | 
 | 
                } else if (tmp2.isContextSpecific((byte)0x01)) { | 
 | 
                    lastField = checkNextField(lastField, 1);  | 
 | 
                    ObjectIdentifier mech = tmp2.data.getOID();  | 
 | 
                    supportedMech = new Oid(mech.toString());  | 
 | 
                    if (DEBUG) { | 
 | 
                        System.out.println("SpNegoToken NegTokenTarg: " + | 
 | 
                                    "supported mechanism = " + supportedMech);  | 
 | 
                    }  | 
 | 
                } else if (tmp2.isContextSpecific((byte)0x02)) { | 
 | 
                    lastField = checkNextField(lastField, 2);  | 
 | 
                    responseToken = tmp2.data.getOctetString();  | 
 | 
                } else if (tmp2.isContextSpecific((byte)0x03)) { | 
 | 
                    lastField = checkNextField(lastField, 3);  | 
 | 
                    if (!GSSUtil.useMSInterop()) { | 
 | 
                        mechListMIC = tmp2.data.getOctetString();  | 
 | 
                        if (DEBUG) { | 
 | 
                            System.out.println("SpNegoToken NegTokenTarg: " + | 
 | 
                                                "MechListMIC Token = " +  | 
 | 
                                                getHexBytes(mechListMIC));  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
        } catch (IOException e) { | 
 | 
            throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,  | 
 | 
                "Invalid SPNEGO NegTokenTarg token : " + e.getMessage());  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    int getNegotiatedResult() { | 
 | 
        return negResult;  | 
 | 
    }  | 
 | 
 | 
 | 
    // Used by sun.security.jgss.wrapper.NativeGSSContext  | 
 | 
      | 
 | 
    public Oid getSupportedMech() { | 
 | 
        return supportedMech;  | 
 | 
    }  | 
 | 
 | 
 | 
    byte[] getResponseToken() { | 
 | 
        return responseToken;  | 
 | 
    }  | 
 | 
 | 
 | 
    byte[] getMechListMIC() { | 
 | 
        return mechListMIC;  | 
 | 
    }  | 
 | 
}  |