public override object GetContextAttribute(object context, GSSAttributeName attributeName) { AuthContext authContext = context as AuthContext; if (authContext != null) { switch (attributeName) { case GSSAttributeName.AccessToken: return(SSPIHelper.GetAccessToken(authContext.ServerContext)); case GSSAttributeName.DomainName: return(authContext.DomainName); case GSSAttributeName.IsGuest: return(authContext.IsGuest); case GSSAttributeName.MachineName: return(authContext.WorkStation); case GSSAttributeName.OSVersion: return(authContext.OSVersion); case GSSAttributeName.SessionKey: return(SSPIHelper.GetSessionKey(authContext.ServerContext)); case GSSAttributeName.UserName: return(authContext.UserName); } } return(null); }
public override NTStatus GetChallengeMessage(out object context, byte[] negotiateMessageBytes, out byte[] challengeMessageBytes) { SecHandle serverContext; try { challengeMessageBytes = SSPIHelper.GetType2Message(negotiateMessageBytes, out serverContext); } catch (Exception) { context = null; challengeMessageBytes = null; // We assume that the problem is not with our implementation. return(NTStatus.SEC_E_INVALID_TOKEN); } context = new AuthContext(serverContext); return(NTStatus.SEC_I_CONTINUE_NEEDED); }
public override bool DeleteSecurityContext(ref object context) { AuthContext authContext = context as AuthContext; if (authContext == null) { return(false); } SecHandle handle = ((AuthContext)context).ServerContext; uint result = SSPIHelper.DeleteSecurityContext(ref handle); bool success = (result == 0); // SEC_E_OK if (success) { context = null; } return(success); }
/// <summary> /// Authenticate will return false when the password is correct in these cases: /// 1. The correct password is blank and 'limitblankpassworduse' is set to 1. /// 2. The user is listed in the "Deny access to this computer from the network" list. /// </summary> public override NTStatus Authenticate(object context, byte[] authenticateMessageBytes) { AuthenticateMessage message; try { message = new AuthenticateMessage(authenticateMessageBytes); } catch (Exception) { return(NTStatus.SEC_E_INVALID_TOKEN); } AuthContext authContext = context as AuthContext; if (authContext == null) { // There are two possible reasons for authContext to be null: // 1. We have a bug in our implementation, let's assume that's not the case, // according to [MS-SMB2] 3.3.5.5.1 we aren't allowed to return SEC_E_INVALID_HANDLE anyway. // 2. The client sent AuthenticateMessage without sending NegotiateMessage first, // in this case the correct response is SEC_E_INVALID_TOKEN. return(NTStatus.SEC_E_INVALID_TOKEN); } authContext.DomainName = message.DomainName; authContext.UserName = message.UserName; authContext.WorkStation = message.WorkStation; if (message.Version != null) { authContext.OSVersion = message.Version.ToString(); } if ((message.NegotiateFlags & NegotiateFlags.Anonymous) > 0 || !IsUserExists(message.UserName)) { if (this.EnableGuestLogin) { authContext.IsGuest = true; return(NTStatus.STATUS_SUCCESS); } else { return(NTStatus.STATUS_LOGON_FAILURE); } } bool success; try { success = SSPIHelper.AuthenticateType3Message(authContext.ServerContext, authenticateMessageBytes); } catch (Exception) { // We assume that the problem is not with our implementation. return(NTStatus.SEC_E_INVALID_TOKEN); } if (success) { return(NTStatus.STATUS_SUCCESS); } else { Win32Error result = (Win32Error)Marshal.GetLastWin32Error(); // Windows will permit fallback when these conditions are met: // 1. The guest user account is enabled. // 2. The guest user account does not have a password set. // 3. The specified account does not exist. // OR: // The password is correct but 'limitblankpassworduse' is set to 1 (logon over a network is disabled for accounts without a password). bool allowFallback = (result == Win32Error.ERROR_ACCOUNT_RESTRICTION); if (allowFallback && this.EnableGuestLogin) { authContext.IsGuest = true; return(NTStatus.STATUS_SUCCESS); } else { return(ToNTStatus(result)); } } }