452 lines
14 KiB
VB.net
452 lines
14 KiB
VB.net
Imports System.Security.Principal
|
|
Imports System.Collections
|
|
Imports CSLA.Data
|
|
Imports System.Security.Cryptography
|
|
Imports System.Text
|
|
Imports GZTW.Data
|
|
Imports System.Reflection
|
|
Imports GZTW.Profile
|
|
|
|
|
|
|
|
|
|
|
|
''' <summary>
|
|
'''
|
|
''' </summary>
|
|
Namespace Security
|
|
|
|
''' <summary>
|
|
''' Implements a custom Identity class that supports
|
|
''' CSLA .NET data access via the DataPortal.
|
|
''' </summary>
|
|
<Serializable()> _
|
|
Public Class BusinessIdentity
|
|
Inherits ReadOnlyBase
|
|
|
|
Implements IIdentity
|
|
|
|
Private mUsername As String
|
|
Private mRoles As New ArrayList
|
|
|
|
|
|
|
|
|
|
#Region "AyaNova Specific"
|
|
''Store the rights for this user when logged in
|
|
Private mUserRightsTable As New Hashtable
|
|
|
|
|
|
''Store the user GUID for this user
|
|
Private mID As New Guid
|
|
|
|
'*********************************************************
|
|
'VALUES REPLICATED HERE SO THEY CAN BE PASSED THROUGH A
|
|
'DATAPORTAL FOR THE BIZ OBJECTS USAGE
|
|
|
|
'Users language setting
|
|
Private mLanguage As String
|
|
|
|
'corresponds to the Global object's cjk index value
|
|
Private mCJKIndex As Boolean
|
|
|
|
'corresponds to the global objects same value
|
|
Private mUseNotification As Boolean
|
|
|
|
|
|
'Used for diagnostics purposes so any code remote
|
|
'or local can know if a remote data portal is in use
|
|
'or a direct database connection
|
|
Private mUsingRemoteDataPortal As Boolean
|
|
|
|
'handy dandy flag for notification server
|
|
'so biz objects can allow only if is one
|
|
'for security
|
|
Private mIsGenerator As Boolean
|
|
|
|
|
|
'case 1163
|
|
Private mOverrideTimeZone As Boolean
|
|
Private mTimeZoneOffset As Double
|
|
|
|
|
|
'*********************************************************
|
|
|
|
|
|
|
|
|
|
''' <summary>
|
|
''' Rights property.
|
|
''' </summary>
|
|
Public ReadOnly Property UserRightsTable() As Hashtable
|
|
Get
|
|
Return mUserRightsTable
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Right - return a user right based on passed in rights string
|
|
''' </summary>
|
|
Friend Function UserRight(ByVal RightName As String) As Int16
|
|
Return CType(mUserRightsTable(RightName), Int16)
|
|
End Function
|
|
|
|
|
|
''' <summary>
|
|
''' User ID property
|
|
''' </summary>
|
|
Public ReadOnly Property ID() As Guid
|
|
|
|
Get
|
|
Return mID
|
|
End Get
|
|
End Property
|
|
''' <summary>
|
|
''' IsGenerator property
|
|
''' </summary>
|
|
Public ReadOnly Property IsGenerator() As Boolean
|
|
|
|
Get
|
|
Return mIsGenerator
|
|
End Get
|
|
End Property
|
|
|
|
|
|
|
|
''' <summary>
|
|
''' User language property
|
|
''' </summary>
|
|
Public Property Language() As String
|
|
Get
|
|
Return mLanguage
|
|
End Get
|
|
Set(ByVal Value As String)
|
|
mLanguage = Value
|
|
End Set
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Index method property
|
|
''' </summary>
|
|
Public Property CJKIndex() As Boolean
|
|
|
|
Get
|
|
Return mCJKIndex
|
|
End Get
|
|
Set(ByVal Value As Boolean)
|
|
mCJKIndex = Value
|
|
End Set
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Notification property
|
|
''' </summary>
|
|
Public Property UseNotification() As Boolean
|
|
|
|
Get
|
|
Return mUseNotification
|
|
End Get
|
|
Set(ByVal Value As Boolean)
|
|
mUseNotification = Value
|
|
End Set
|
|
End Property
|
|
|
|
|
|
''' <summary>
|
|
''' Override time zone property
|
|
''' </summary>
|
|
Public Property OverrideTimeZone() As Boolean
|
|
'case 1163
|
|
Get
|
|
Return mOverrideTimeZone
|
|
End Get
|
|
Set(ByVal Value As Boolean)
|
|
mOverrideTimeZone = Value
|
|
End Set
|
|
End Property
|
|
''' <summary>
|
|
''' Time zone offset property
|
|
''' </summary>
|
|
Public Property TimeZoneOffset() As Double
|
|
'case 1163
|
|
Get
|
|
Return mTimeZoneOffset
|
|
End Get
|
|
Set(ByVal Value As Double)
|
|
mTimeZoneOffset = Value
|
|
End Set
|
|
End Property
|
|
|
|
|
|
''' <summary>
|
|
''' Flag - true = remote dataportal, false=direct db connection
|
|
''' Used for diagnostics purposes so any code remote
|
|
''' or local can know if a remote data portal is in use
|
|
''' or a direct database connection
|
|
''' </summary>
|
|
Public Property UsingRemoteDataPortal() As Boolean
|
|
Get
|
|
Return mUsingRemoteDataPortal
|
|
End Get
|
|
|
|
Set(ByVal Value As Boolean)
|
|
mUsingRemoteDataPortal = Value
|
|
End Set
|
|
End Property
|
|
|
|
#End Region
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#Region " IIdentity "
|
|
|
|
''' <summary>
|
|
''' Implements the IsAuthenticated property defined by IIdentity.
|
|
''' </summary>
|
|
Public ReadOnly Property IsAuthenticated() As Boolean _
|
|
Implements IIdentity.IsAuthenticated
|
|
Get
|
|
Return Len(mUsername) > 0
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Implements the AuthenticationType property defined by IIdentity.
|
|
''' </summary>
|
|
Public ReadOnly Property AuthenticationType() As String _
|
|
Implements IIdentity.AuthenticationType
|
|
Get
|
|
Return "CSLA"
|
|
End Get
|
|
End Property
|
|
|
|
''' <summary>
|
|
''' Implements the Name property defined by IIdentity.
|
|
''' </summary>
|
|
Public ReadOnly Property Name() As String _
|
|
Implements IIdentity.Name
|
|
Get
|
|
Return mUsername
|
|
End Get
|
|
End Property
|
|
|
|
#End Region
|
|
|
|
|
|
|
|
#Region " Create and Load "
|
|
|
|
Friend Shared Function LoadIdentity(ByVal UserName As String, ByVal Password As String, ByVal ACS As AyaNovaConnectionSettings) As BusinessIdentity
|
|
'These are set here to apply to the entire program afterwards as this is
|
|
'the first call to DataPortal
|
|
'This replaces the config file method in DataPortal without
|
|
'having to give a references to ACS in DataPortal
|
|
DataPortal.mIsRemote = ACS.IsRemote
|
|
DataPortal.mPortalString = ACS.DataPortalConnection
|
|
|
|
'case 1971 was: Return CType(DataPortal.Fetch(New Criteria(UserName, Password)), BusinessIdentity) ', ACS
|
|
Return CType(DataPortal.Fetch(New Criteria(UserName, Password, ACS)), BusinessIdentity) ', ACS
|
|
End Function
|
|
|
|
<Serializable()> _
|
|
Private Class Criteria
|
|
Public Username As String
|
|
Public Password As String
|
|
Public ACS As AyaNovaConnectionSettings
|
|
'case 1971 WAS THIS: Public Sub New(ByVal Username As String, ByVal Password As String) ', ByVal ACS As AyaNovaConnectionSettings
|
|
Public Sub New(ByVal Username As String, ByVal Password As String, ByVal ACS As AyaNovaConnectionSettings)
|
|
Me.Username = Username
|
|
Me.Password = Password
|
|
'case 1071 was this commented out: 'Me.ACS = ACS
|
|
Me.ACS = ACS
|
|
|
|
End Sub
|
|
End Class
|
|
|
|
Private Sub New()
|
|
' prevent direct creation
|
|
End Sub
|
|
|
|
#End Region
|
|
|
|
#Region " Data access "
|
|
|
|
''' <summary>
|
|
''' Retrieves the identity data for a specific user.
|
|
''' </summary>
|
|
Protected Overrides Sub DataPortal_Fetch(ByVal Criteria As Object)
|
|
Dim crit As Criteria = CType(Criteria, Criteria)
|
|
'Dim lText As String
|
|
|
|
|
|
|
|
'exeAssembly
|
|
Try
|
|
' mRoles.Clear()
|
|
mUserRightsTable.Clear()
|
|
|
|
|
|
'case 1971 commented following two lines
|
|
'Dim ACS As New AyaNovaConnectionSettings()
|
|
'ACS.GetConnectionData()
|
|
|
|
|
|
|
|
|
|
'case 1971 redux, was failing at dataportal as it was trying to use clients connection settings
|
|
Dim dbase As GZTWDatabase
|
|
If crit.ACS.IsRemote Then
|
|
'don't use the provided connection settings, load them directly
|
|
Dim DATAPORTAL_ACS As New AyaNovaConnectionSettings()
|
|
DATAPORTAL_ACS.GetConnectionData()
|
|
dbase = GZTWDatabaseFactory.CreateDatabase(DATAPORTAL_ACS)
|
|
Else
|
|
dbase = GZTWDatabaseFactory.CreateDatabase(crit.ACS)
|
|
End If
|
|
|
|
|
|
|
|
|
|
'Dim dbase As GZTWDatabase = GZTWDatabaseFactory.CreateDatabase(crit.ACS)
|
|
|
|
Dim cm As DBCommandWrapper = dbase.GetSqlStringCommandWrapper("SELECT aID, aUserType, aFirstName, aLastName, aInitials, aLanguage FROM aUser WHERE aUser.aLogin=@Login AND aUser.aPassword=@Password AND aUser.AACTIVE=@aTrue;")
|
|
|
|
'Modifications to work with AyaNova
|
|
'md5 style pass / login
|
|
|
|
'TODO: FIPS
|
|
'case 3378
|
|
|
|
|
|
'******************************************************************************
|
|
'FIPS MODE SETTING
|
|
'CAUTION, REMARK THIS CAREFULLY!!
|
|
'#Const FIPS_MODE = True
|
|
#Const FIPS_MODE = False
|
|
''******************************************************************************
|
|
|
|
|
|
#If FIPS_MODE = True Then
|
|
|
|
Dim shaM As New SHA256Cng
|
|
#Else
|
|
Dim shaM As New SHA256Managed
|
|
#End If
|
|
'PRE_FIPS: Dim shaM As New SHA256Managed
|
|
|
|
|
|
Dim encoder As New UTF8Encoding
|
|
|
|
'Hash and convert the hash bytes to hex string of 64 characters
|
|
Dim sLogin As String = BitConverter.ToString(shaM.ComputeHash(encoder.GetBytes(crit.Username))).Replace("-", "")
|
|
Dim sPassword As String = BitConverter.ToString(shaM.ComputeHash(encoder.GetBytes(crit.Username + crit.Password))).Replace("-", "")
|
|
|
|
Dim sCallerSig As String = "nada"
|
|
Dim sCallerName As String = ""
|
|
' A data portal doesn't have an entry assembly (apparently)
|
|
If [Assembly].GetEntryAssembly() Is Nothing Then
|
|
sCallerName = "DataPortal"
|
|
Else
|
|
sCallerName = [Assembly].GetEntryAssembly().GetName().Name()
|
|
If [Assembly].GetEntryAssembly().GetName().GetPublicKeyToken() Is Nothing Then
|
|
|
|
sCallerSig = "nada"
|
|
Else
|
|
sCallerSig = BitConverter.ToString([Assembly].GetEntryAssembly().GetName().GetPublicKeyToken())
|
|
|
|
|
|
End If
|
|
End If
|
|
|
|
|
|
|
|
cm.AddInParameter("@Password", DbType.String, sPassword)
|
|
cm.AddInParameter("@Login", DbType.String, sLogin)
|
|
cm.AddInParameter("@aTrue", DbType.Boolean, True)
|
|
|
|
|
|
|
|
Dim dr As New SafeDataReader(dbase.ExecuteReader(cm))
|
|
Try
|
|
If dr.Read() Then
|
|
|
|
'ID is first result
|
|
mID = dr.GetGuid(0)
|
|
|
|
|
|
|
|
' Firstname and lastname
|
|
mUsername = dr.GetString(2) + " " + dr.GetString(3)
|
|
|
|
'Language
|
|
mLanguage = dr.GetString(5)
|
|
|
|
|
|
|
|
'usertype notification server?
|
|
If dr.GetInt16(1) = 6 Then
|
|
'ensure generator is logging in from one of our own apps only
|
|
If "DF-66-A8-D8-E4-98-33-D3" <> sCallerSig Or sCallerName <> "Generator" Then
|
|
Throw New System.Security.SecurityException("Generator login exception")
|
|
End If
|
|
|
|
mIsGenerator = True
|
|
|
|
Else
|
|
mIsGenerator = False
|
|
End If
|
|
|
|
'Get the security rights result set
|
|
'and stuff into the rights table
|
|
dr.Close()
|
|
|
|
|
|
|
|
cm.Command.CommandText = "SELECT aUserRight.aRight, " & _
|
|
"aUserRight.aSecurityLevel FROM aUser " & _
|
|
"INNER JOIN aUserRight ON aUser.aMemberOfGroup " & _
|
|
"= aUserRight.aSecurityGroupID WHERE aUser.aLogin=@Login AND aUser.aPassword=@Password;"
|
|
|
|
|
|
|
|
|
|
dr = New SafeDataReader(dbase.ExecuteReader(cm))
|
|
|
|
While dr.Read
|
|
If mIsGenerator = True Then
|
|
mUserRightsTable.Add(dr.GetString(0), 2) 'set all rights to read only for notification server
|
|
Else
|
|
mUserRightsTable.Add(dr.GetString(0), dr.GetInt16(1))
|
|
End If
|
|
|
|
End While
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Else
|
|
mUsername = ""
|
|
End If
|
|
|
|
Finally
|
|
dr.Close()
|
|
End Try
|
|
|
|
Finally
|
|
'cn.Close()
|
|
|
|
End Try
|
|
End Sub
|
|
|
|
#End Region
|
|
|
|
End Class
|
|
|
|
End Namespace
|