private void SpngNegotiationInitial(byte[] inToken) { byte[] securityToken = null; MechTypeList serverMechList = null; if ((inToken == null) || (inToken.Length == 0)) // Client Initiation Mode { InitializeSecurityContext(this.client.Config.MechList.Elements[0], securityToken); this.client.Context.NegotiationState = SpngNegotiationState.AcceptIncomplete; } else // Server Initiation Mode { try { securityToken = UnwrapInitialNegToken2(inToken, out serverMechList); this.client.NegotiateMechType(serverMechList); if (this.client.Context.NegotiationState == SpngNegotiationState.Reject) { //Negotiation failed. Do not need to throw exception in this case. return; } } catch { // check if reauth token SpngNegotiationToken negToken = new SpngNegotiationToken(); negToken.FromBytes(inToken); this.client.Context.NegotiatedMechType = negToken.SupportedMechType; // try use preview MechType to do Re-Initialize securityToken = null; } InitializeSecurityContext(this.client.Context.NegotiatedMechType, securityToken); } if (this.client.Context.NegotiationState == SpngNegotiationState.AcceptIncomplete) // server prefered mechtype can find from local support mechtype list. { try { securityMechContext.Initialize(securityToken); } catch (Exception ex) { if (securityMechContext is NlmpClientSecurityContext) { throw ex; } SwitchToNTLMSSP(securityToken); // try use NTLM } } else { securityMechContext.Initialize(null); } UpdateNegotiationToken(securityToken); }
/// <summary> /// Generate a NegotiationToken byte array, and insert the internal security token /// </summary> /// <param name="payloadType">the internal payload type</param> /// <param name="inToken">the internal security token</param> /// <returns>the generated NegotiationToken byte array</returns> private byte[] WrapNegotiationToken(SpngPayloadType payloadType, byte[] inToken) { byte[] mechListMic = null; if (this.needMechListMic && securityMechContext != null && !securityMechContext.NeedContinueProcessing) { mechListMic = this.client.GenerateMechListMIC(securityMechContext); } SpngNegotiationToken negToken = client.CreateNegotiationToken(payloadType, new NegState(NegState.accept_incomplete), inToken, mechListMic); return(negToken.ToBytes()); }
/// <summary> /// Retrieve the internal security token from NegotiationToken /// </summary> /// <param name="inToken">NegotiationToken byte array</param> /// <param name="mechListMic">the byte-array formatted MechListMIC that contains in the inner payload</param> /// <returns>the internal security token</returns> private byte[] UnwrapNegotiationToken(byte[] inToken, out byte[] mechListMic) { mechListMic = null; SpngNegotiationToken negToken = new SpngNegotiationToken(); negToken.FromBytes(inToken); if (negToken != null) { mechListMic = negToken.MechListMIC; } if (negToken.MechToken == null || negToken.MechToken.Length == 0) { return(null); } return(negToken.MechToken); }
/// <summary> /// Initialize the context from a token, and generate a new token. /// </summary> /// <param name="inToken">the token from server. "inToken" must be null when invoked first time.</param> /// <exception cref="ArgumentNullException">Except invoked at the first time, the "inToken" MUST not be null /// when invoking Initialize.</exception> /// <exception cref="InvalidOperationException">The internal state is invalid when invoking Initialize.</exception> /// <exception cref="InvalidOperationException">Invalid MechListMic</exception> public override void Initialize(byte[] inToken) { byte[] securityToken = null; MechTypeList serverMechList = null; bool isNeedWrap = true; switch (this.client.Context.NegotiationState) { case SpngNegotiationState.Initial: if ((inToken == null) || (inToken.Length == 0)) // Client Initiation Mode { InitializeSecurityContext(this.client.Config.MechList.Elements[0], securityToken); this.client.Context.NegotiationState = SpngNegotiationState.AcceptIncomplete; } else { try { securityToken = UnwrapInitialNegToken2(inToken, out serverMechList); this.client.NegotiateMechType(serverMechList); if (this.client.Context.NegotiationState == SpngNegotiationState.Reject) { //Negotiation failed. Do not need to throw exception in this case. return; } } catch { // check if reauth token SpngNegotiationToken negToken = new SpngNegotiationToken(); negToken.FromBytes(inToken); this.client.Context.NegotiatedMechType = negToken.SupportedMechType; // try use preview MechType to do Re-Initialize securityToken = null; } InitializeSecurityContext(this.client.Context.NegotiatedMechType, securityToken); } if (this.client.Context.NegotiationState == SpngNegotiationState.AcceptIncomplete) // server prefered mechtype can find from local support mechtype list. { try { securityMechContext.Initialize(securityToken); } catch { securityMechContext = null; // try use NTLM InitializeSecurityContext(this.client.Config.MechList.Elements[1], securityToken); this.client.Context.NegotiationState = SpngNegotiationState.AcceptIncomplete; securityMechContext.Initialize(securityToken); } } else { securityMechContext.Initialize(null); } if (this.client.Context.NegotiationState == SpngNegotiationState.SspiNegotiation) { //SSPI negotiation already has an SPNG wrapper. this.token = securityToken; } else { if (CurrentSecurityConfig.GetType() == typeof(NlmpClientSecurityConfig)) { NlmpClientSecurityConfig nlmpConfig = CurrentSecurityConfig as NlmpClientSecurityConfig; if ((nlmpConfig.SecurityAttributes & ClientSecurityContextAttribute.DceStyle) == ClientSecurityContextAttribute.DceStyle) { isNeedWrap = false; } } if (isNeedWrap) { this.token = WrapInitialNegToken(securityMechContext.Token); } else { this.token = securityMechContext.Token; } } break; case SpngNegotiationState.RequestMic: if ((inToken == null) || (inToken.Length == 0)) { throw new ArgumentNullException("inToken"); } securityToken = UnwrapNegotiationToken(inToken); this.needMechListMic = true; this.client.Context.NegotiationState = SpngNegotiationState.AcceptIncomplete; securityMechContext.Initialize(securityToken); if (securityMechContext.Token != null) { this.token = WrapNegotiationToken(SpngPayloadType.NegResp, securityMechContext.Token); } break; case SpngNegotiationState.AcceptIncomplete: if ((inToken == null) || (inToken.Length == 0)) { throw new ArgumentNullException("inToken"); } byte[] mechListMic = null; if (CurrentSecurityConfig.GetType() == typeof(NlmpClientSecurityConfig)) { NlmpClientSecurityConfig nlmpConfig = CurrentSecurityConfig as NlmpClientSecurityConfig; if ((nlmpConfig.SecurityAttributes & ClientSecurityContextAttribute.DceStyle) == ClientSecurityContextAttribute.DceStyle) { isNeedWrap = false; } } if (isNeedWrap) { securityToken = UnwrapNegotiationToken(inToken, out mechListMic); if (!securityMechContext.NeedContinueProcessing) { this.needContinueProcessing = false; this.client.Context.NegotiationState = SpngNegotiationState.AcceptCompleted; this.token = null; if (mechListMic != null && !this.client.VerifyMechListMIC(securityMechContext, mechListMic)) { throw new InvalidOperationException("Invalid MechListMic"); } } else { securityMechContext.Initialize(securityToken); if (!securityMechContext.NeedContinueProcessing) { this.needMechListMic = true; } this.token = WrapNegotiationToken(SpngPayloadType.NegResp, securityMechContext.Token); } } else { this.needContinueProcessing = false; if (!securityMechContext.NeedContinueProcessing) { this.client.Context.NegotiationState = SpngNegotiationState.AcceptCompleted; this.token = null; } else { securityToken = inToken; securityMechContext.Initialize(securityToken); this.token = securityMechContext.Token; } } break; case SpngNegotiationState.AcceptCompleted: throw new InvalidOperationException("Authentication completed!"); case SpngNegotiationState.SspiNegotiation: if (securityMechContext != null) { securityMechContext.Initialize(inToken); } break; default: // MUST be SpngNegotiationState.Reject throw new InvalidOperationException("Authentication rejected!"); } }