No Environ("password") for Active Directory User Binding? - authentication

I want to reuse the Windows authentication to bind to the Active Directory user and check group membership.
I can get the Windows username with Environ("username"), but how do I get the password? I don't want to have to require the user to reenter their password, but there is no Environ("password").
How do I make this code work?
Thanks!
Private Sub ADsAuthenticate()
Dim objConnection As New ADODB.Connection
Dim objRecordset As ADODB.Recordset
Dim objADsUser As IADsUser
Dim objADsGroup As IADsGroup
Dim strUsername As String
Dim strPassword As String
strUsername = Environ("username")
strPassword = Environ("password")
With objConnection
.Provider = "ADsDSOObject"
.Properties("User ID") = strUsername
.Properties("Password") = strPassword
.Properties("Encrypt Password") = True
.Open "ADs Provider"
Set objRecordset = .Execute("<LDAP://<server>/dc=<domain>,dc=com>;" _
& "(sAMAccountName=" & strUsername & ");ADsPath;Subtree")
End With
With objRecordset
If Not .EOF Then
Set objADsUser = GetObject("LDAP:").OpenDSObject(.Fields("ADsPath").Value, strUsername, strPassword, ADS_SECURE_AUTHENTICATION)
Debug.Print objADsUser.ADsPath
For Each objADsGroup In objADsUser.Groups
Debug.Print objADsGroup.Name
Next
End If
End With
objConnection.Close
End Sub

What makes you so sure the password is anywhere to read in the first place?
The accepted way to keep passwords is to only store a one-way hash of password (typically using the BCrypt hashing algorithm plus a salt/nonce), and when someone logs in use the same hashing technique on the attempted password to see if it matches your stored value. Instead of storing something readable like password1 (warning: bad password example!) you end up storing something more like 23e598ac098da42== that's much less useful to crackers.
This is why if you lose a password most systems require you to reset it rather than recover the old one for you — they don't even have a real copy of the old one to give you.

Related

VBA Form Connection Validation

I have a VBA form that opens upon opening excel which requires user login credentials and checks if it connects to the teradata database.
Private Sub cmdLogin_Click()
Dim Cn As ADODB.Connection
Dim Rc As ADODB.Recordset
Set Cn = New ADODB.Connection
Dim user As String
Dim password As String
Dim sConnect As String
user = Me.txtUserID.Value
password = Me.txtPassword.Value
sConnect = "Driver={Teradata};DBCname=TDPREP01;DatabaseName=DBADMIN ;Uid=" & user & ";Pwd=" & password & "; Authentication=LDAP;"
Cn.Open sConnect
If Cn.State = 1 Then
Unload Me
Application.Visible = True
Worksheets("do not open!").Cells(1, 1) = user
Worksheets("do not open!").Cells(2, 1) = password
Else
MsgBox "Invalid login credentials. Please Try again.", vbOKOnly + vbCritical, "Invalid Login Details"
End If
End Sub
If details are correct then I store the login details(To use later one for other modules).
The issue that I'm encountering is if the user inserts a wrong login...then I get an error message and my app crashes with the following error:
Obviously this is due to the app crashing upon the Cn.Open sConnect
Is there a way to check if the connection is valid with an if statement?
I tried something like If Cn.Open sConnect = True Then but that doesn't work.
Could anyone advise how I could apply the If statement to check if the connection is valid?
on error goto notgood
Cn.Open sConnect
<...>
notgood:
MsgBox "Error connecting to Teradata"

Compare String with Table fields value

Hello to all programmers, I am very new to MS Access, but have some experience with Excel (including VBA). I've been searching for few days now and tested several suggestions with zero success so far. It's getting frustrating already and I decided to ask directly for my case.
From a loaded form I get the user to input password via Inputbox, I need my code to search for that string in my table Crewlist, field Password and criteria is another field Admin (Yes/No).
To facilitate the search I made a query table containing all people with field Admin (all are Yes) and field Password.
Looking forward for any particular solution. So far I have tried creating array & recordset.
Edit
(e.g as requested - table containing required info to be compared)
Field1 Field2 Field3("Admin")
Name1 password1 No
Name2 password2 Yes
Name3 password3 Yes
"If " statement comparing Inputbox string with Field2 where Admin=Yes
Dlookup will return the first result, ie Password2, but Name3 and password3 should also be looked and compared).
Recordset and simple SQL code will be required, I am now working on it.
I would suggest using a simple DLookup expression for this task, for example, assuming that the password entered by the user is stored in a variable pwd, you might use:
DLookup("Password","Crewlist","Admin = True and Password = '" & pwd & "'")
The DLookup function will return Null if no match is found, which you can test with an If statement and the IsNull function, e.g.:
If IsNull(DLookup("Password","Crewlist","Admin = True and Password = '" & pwd & "'")) Then
MsgBox "Invalid Password!"
Else
' Do Stuff
End If
Here, I only specify the Password field as the field to be looked up as DLookup requires a specific field whose value should be returned. You could instead use the DCount function and test whether the return is non-zero, e.g.:
If DCount("*","Crewlist","Admin = True and Password = '" & pwd & "'") > 0 Then
' Do Stuff
Else
MsgBox "Invalid Password!"
End If
Implemented in the event handler for a button, this might be written as:
Private Sub Command0_Click()
Dim pwd As String
pwd = InputBox("Enter Password:", "Password")
If pwd <> vbNullString Then
If IsNull(DLookup("Password", "Crewlist", "Admin = True and Password = '" & pwd & "'")) Then
MsgBox "Invalid Password!"
Else
MsgBox "Access Granted!"
End If
End If
End Sub
Note that this is only checking the password, hence, with only the above code, the user could specify the password for any Admin user and be granted access.
You could easily check the username with an additonal prompt:
Private Sub Command0_Click()
Dim usr As String
Dim pwd As String
usr = InputBox("Enter Username:", "Username")
If usr <> vbNullString Then
pwd = InputBox("Enter Password:", "Password")
If pwd <> vbNullString Then
If IsNull(DLookup("Password", "Crewlist", "Admin = True and Username = '" & usr & "' and Password = '" & pwd & "'")) Then
MsgBox "Invalid Username or Password!"
Else
MsgBox "Access Granted!"
End If
End If
End If
End Sub
However, this would be more professional if you were to design your own modal form containing a textbox or combobox for the username and a textbox in which the user may specify their password.
Aside, storing passwords in a database in plain text is bad practice: consider hashing the password using an appropriate hash function and storing the hash value. Then, apply the same hash function to the user input and use the resulting hash value to test for a match in your database.
This way, only the user has knowledge of the password - since hashing is a one-way process, not even the database admin has knowledge of user's passwords. If a user needs to change their password, they would either be supplied with a new temporary password that they could change or would provide a new password following some other authentication.
As a general rule, never trust any service that is able to send you your original password - this reveals that such a service is storing passwords without encryption/masking.
This is what I came with this morning after reading some examples about recordset and looping. My code in VBA
Sub Auto_Logo0_Dblclick
Dim AdmPass As String
AdmPass = Inputbox ("Admin password required")
'next part is taken from my guide book for Access
Dim Con1 As ADODB.Connection
Set Con1 = CurrentProject.Connection
Dim rcrdPass As New ADODB.Recordset
rcrdPass.Activeconnection = Con1
'SQL part
Dim mySQL as String
mySQL = "SELECT Crewlist.Surname, Crewlist.Password,"
mySQL = mySQL & " Crewlist.Admin"
mySQL = mySQL & " From Crewlist"
mySQL = mySQL & " Where (Crewlist.Admin = 'Yes')"
rcrdPass.Open mySQL
With rcrdPass
If Not .BOF And Not .EOF Then
.MoveFirst
.MoveLast
While (Not .EOF)
If AdmPass = rcrdPass.Fields("Password") Then
Call DoCmd.SelectObject(acTable,,True)
Else Msgbox ("Wrong password, try again")
End If
.MoveNext
Wend
End If
End With
rcrdPass.Close
Set rcrdPass = Nothing
Set Con1 = Nothing
End sub

How to get email address with VBA based on windows login name?

How can I use VBA to get the email address of users on my network based on their Windows user name?
I have a log file that contains the UserName of everyone who launched this Access database. The username was generated from Environ("USERNAME") when they launched the database. I need to send an email to all recent users.
I don't need it to return the current users email address, and I don't need the code to send email.
I was wondering if it was possible using LDAP, but the example I have only works for the current logged in user. Is there another way?
Function GetEmailAddress(Optional strUserName As String = "") As String
' Get user's email address from LDAP
Dim sysInfo As Object
Dim oUser As Object
If strUserName = "" Then
' No name was passed in. Get it for the current user.
strUserName = Environ("USERNAME")
End If
' How I can I use strUserName to get the email address?
' The LDAP query below only works for the current logged in user.
Set sysInfo = CreateObject("ADSystemInfo")
Set oUser = GetObject("LDAP://" & sysInfo.UserName & "")
Debug.Print "Display Name: "; Tab(20); oUser.Get("DisplayName")
Debug.Print "Email Address: "; Tab(20); oUser.Get("mail")
Debug.Print "Computer Name: "; Tab(20); sysInfo.ComputerName
Debug.Print "Site Name: "; Tab(20); sysInfo.SiteName
Debug.Print "Domain DNS Name: "; Tab(20); sysInfo.DomainDNSName
GetEmailAddress = oUser.Get("mail")
Set sysInfo = Nothing
Set oUser = Nothing
End Function
Personally, I use the following function, though there are many possibilities.
Public Function GetMailAddress(strUsername As String) As String
Dim cmd As New ADODB.Command
Dim cn As New ADODB.Connection
Dim rs As ADODB.Recordset
cn.Open "Provider=ADsDSOObject;"
cmd.CommandText = "<LDAP://dc=MyCompany,dc=intranet>;(&(objectCategory=User)(CN=" & strUsername & "));mail;subtree"
cmd.ActiveConnection = cn
Set rs = cmd.Execute
GetMailAddress = rs.Fields(0).Value
End Function
You need to fill in the valid DC values for your LDAP server, of course.

Possible to query As400 DB2 via VB.Net without a PRG?

After spending a few days researching and trying to figure this out solo, I could really use some help.
I'm trying to query the As400's database directly from .Net without the use of a As400 program file. I have very little support other than "go ahead and try" from the As400 administrators (I'm being told what I'm attempting hasn't been done here before).
I'd really like to use CWBX. The code below successfully connects, but I could really use a pointer in the right direction on how to build a query:
Dim As400 As New AS400System
Dim AsProgram As New cwbx.Program
Dim AsCommand As New cwbx.Command
Dim strQuery As String
As400.Define("AS400")
As400.UserID = ""
As400.Password = ""
As400.IPAddress = ""
As400.Connect(cwbcoServiceEnum.cwbcoServiceRemoteCmd)
If As400.IsConnected(cwbcoServiceEnum.cwbcoServiceRemoteCmd) = 1 Then
MsgBox("Valid Connection")
Else
MsgBox("Invalid Connection")
Exit Sub
End If
'-----------------------------------------------------------------------------------------
'Trying to figure out first if this syntax is correct, and if so... where/how to call it??
'-----------------------------------------------------------------------------------------
strQuery = "SELECT * FROM Library.File WHERE FILEFIELD='Criteria'"
' ---
AsProgram.LibraryName = ""
AsProgram.ProgramName = "" '?
AsProgram.system = As400
'Assuming this will end up being a program call?
'AsProgram.Call()
As400.Disconnect(cwbcoServiceEnum.cwbcoServiceRemoteCmd)
I'm very open to any other methods/suggestions. I've looked for guides from IBM's site as well as MSDN and neither actually do direct querying without the use of an As400 program file. Is this even possible?
Here is a simple console app that will retrieve all the records from one table and display the row count.
Imports System.Data.OleDb
Module Module1
Sub Main()
Dim cmd As New OleDbCommand
Dim table As String = "YOUR TABLE"
cmd.CommandText = "SELECT * FROM " & table
Dim ip As String = "YOUR AS/400 IP GOES HERE"
Dim user As String = "YOUR USER ID"
Dim pass As String = "YOUR PASSWORD"
Dim defaultLib As String = "YOUR LIBRARY"
Dim connstring As String = "Provider=IBMDA400;" & _
"Data Source=" & ip & ";" & _
"Force Translate=0;" & _
"Default Collection=" & defaultLib & ";" & _
"User ID=" & user & ";" & _
"Password=" & pass
cmd.Connection = New OleDbConnection(connstring)
cmd.Connection.Open()
Dim dr As OleDbDataReader = cmd.ExecuteReader
Dim dt As New DataTable
dt.Load(dr)
Console.WriteLine(dt.Rows.Count)
Console.WriteLine("Press ENTER to close...")
Console.ReadLine()
End Sub
End Module
The remotecmd service is basically a Rexcd daemon. Not sure why you're messing with that when you want to simple query a DB table. The integrated DB in IBM i is accessible via ODBC, OLEDB, JBDC and most importantly for you a ADO.NET provider.
http://www-03.ibm.com/systems/power/software/i/access/windows/dotnet.html
All of the above mentioned drivers are available in the IBM i Access software. Note that while some of the IBM i Access features are chargeable, ex 5250 emulation, and you must have bought a license; the data access providers are not.
Included in the IBM i Access package is a collection of documentation known as the "Programmers Toolkit"
An example using the .NET data provider from that toolkit:
Public Sub Example()
Dim cn As iDB2Connection = New iDB2Connection("DataSource=mySystemi;")
Dim da As New iDB2DataAdapter("select * from mylib.mytable", cn)
End Sub
Lastly note that the (free) .NET provider doesn't support Microsoft's Entity Framework (EF). If you need EF support, you'll have to pay for DB2 Connect
http://www-03.ibm.com/software/products/en/db2-connect-family

Code To eliminate need to enter password

I have an access form that pulls together data from different tables. Some of them require a username and password be entered. This is going out to other users and I would rather them not have to enter the information over and over. Is there a code that I can use that whenever it prompts for a password to have it automatically logged in?
Currently I already have a connection for one DB connection that runs whenever the DB is opened. It looks like:
Public Function StartUp()
Dim cnn As ADODB.Connection
Dim localrst As New ADODB.Recordset
Dim remoterst As New ADODB.Recordset
On Error Resume Next
Set cnn = New ADODB.Connection
cnn.Open "Provider=SQLOLEDB; Data Source=SOURCE; Initial Catalog=NAME;" _
& "User Id=ID; Password=PW;"
If cnn.State = adStateOpen Then
MsgBox ("You have an established connection with the L&TD SQL Server Database and the CDData table has been uploaded to the server.")
Else
MsgBox ("Cannot connect to SQL Server. Data will be stored locally to CDData Table until application is opened again with an established connection.")
End If
On Error GoTo 0
End Function
Is there a way to add more connections to this so it connects to all 3?
The literal answer is; no. You can't make a password form autofill. However, you can set up your connection string so that no one has to fill it in.
'Set up the connection string
strConn = "PROVIDER=SQLOLEDB;DATA SOURCE=MyServerName;INITIAL CATALOG=MyDatabaseName;UID=MyStandardUserID;PWD=MyStandardPassword;"
cnComments.Open strConn
You can also set it up without the username and password:
'Set up the connection string
strConn = "PROVIDER=SQLOLEDB;DATA SOURCE=MyServerName;INITIAL CATALOG=MyDatabaseName;TRUSTED_CONNECTION=yes;"
cnComments.Open strConn