This application will be run on clients that are already authenticated in Active Directory.
Problem: the LDAP protocol (or Active Directory settings) seem to require username and password.
Goal: query Active Directory using LDAP in Java without having to authenticate (ask for username and password).
Gist: all clients who run this application have already logged in. Thus, they are already authenticated (into)/ by Active Directory.
Now that they are logged in and have access to AD outside the application, isn't it possible to "mooch" off of the fact that they are already authenticated and run my LDAP queries in my application?
Errors: while trying to maneuver past authentication; I have become accustomed to binding errors, log4j errors; and almost everything recommended on Stack Overflow, Oracle and Apache.
Methods tried: I have tried anonymous binding, Ldap api's, nada!!
Questions:
Is it possible to query Active Directory without authentication?
Is it possible to query Active Directory by telling the server that "hey, I am already logged into AD, proceed with my queries?" without prompting the user for Username and password?
Is it possible to query active directory without authentication?
I think no, you cannot as this will violate security. Another way might be to use Single sign on utilities that lets you sign in and then they will provide you the details.
Is it possible to query active directory by telling the server that
"hey, I am already logged into AD, proceed with my queries?" without
prompting the user for Username and password?
You can try http://spnego.sourceforge.net/ or http://jcifs.samba.org/src/docs/ntlmhttpauth.html to use NTLM
The following solution (or at least a very similar one) was used to solve this question:
import com4j.Variant;
import com4j.typelibs.ado20.ClassFactory;
import com4j.typelibs.ado20._Command;
import com4j.typelibs.ado20._Connection;
import com4j.typelibs.ado20._Recordset;
public static void queryADForComputers() throws Exception {
String query = "cn,sn,givenName,department";
String filter = "(&(objectclass=user)(objectcategory=person))";
String namingContext = "OU=Desktops,OU=Workstations,OU=HO,DC=win";
_Connection conn = ClassFactory.createConnection();
conn.provider("ADsDSOObject");
conn.open("Active Directory Provider","","",-1);
_Command cmd = ClassFactory.createCommand();
cmd.activeConnection(conn);
cmd.commandText("<LDAP://" + namingContext + ">;" + filter + ";" + query + ";subTree");
_Recordset rs = cmd.execute(null, Variant.getMissing(), -1);
System.out.println("Found " + rs.recordCount() + " users/computers/whatever i was looking for");
//Then here you can use a while loop while(!rs.eof())
//in which you can get each value as rs.fields().item(i).value();
//in my case, i did rs.fields().item(i).value().toString()
//or you can check for its type and go from there.
}
I worked on this a while ago and don't currently have an active directory to test and verify. but this should get you started.
Related
I'm writing an integration API in Java for IBM Domino 10, I want to perform resource (room) reservations, fetch and update them from an external source.
So far, I successfully created an entry in current user's calendar (current session) and the reservation is also successfull, however I want to create reservations as certain users (personification), since only one user is configured to use my API database. So the main user is used to do everything, but I'd like to pass him the credentials of other users and he should create the events & reservations in their calendars. I can verify if an user exists & if his password is correct, but I don't know how could I open his calendar because it's session based.
My current code:
Database mdb = session.getDbDirectory(session.getServerName()).openMailDatabase();
NotesCalendar cal = session.getCalendar(mdb);
java.text.SimpleDateFormat datefmt = new java.text.SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
String dStart = datefmt.format(dtStart);
String dEnd = datefmt.format(dtEnd);
Name nnOrganizer = session.createName(session.getEffectiveUserName());
String iCalEntry = "BEGIN:VCALENDAR\n" +
"PRODID:-//Test//Reservation API//EN\n" +
"VERSION:2.0\n" +
"BEGIN:VEVENT\n" +
"DTSTART:" + dStart + "\n" +
"DTEND:" + dEnd + "\n" +
"SUMMARY:Sample Meeting\n" +
"DESCRIPTION:TEST\n" +
"ORGANIZER;CN=admin/O=Corp:mailto:test#test.test\n" +
"ATTENDEE;ROLE=CHAIR;PARTSTAT=ACCEPTED;" + nnOrganizer.getCanonical() + ";RSVP=false:mailto:test#test.test\n" +
"ATTENDEE;CUTYPE=ROOM;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;" + nnResource.getCanonical() + ";RSVP=true:mailto:room#test.test\n" +
"END:VEVENT\n" +
"END:VCALENDAR\n";
NotesCalendarEntry entry = cal.createEntry(iCalEntry);
System.out.println("calendar uid " + entry.getUID());
How could I make this work with any user I want? So it's not using session.getCalendar() but something else, so I could create an entry in another user's calendar.
Also, how can I programatically get the organizer's & room's email addresses? As for now, they are hardcoded. I know I could do a directory lookup, but sometimes the email (internet address) isn't configured, and lookupNames returns nothing. Notes client somehow bypasses that and creates an email like Name_Surname/server#Corp, is it enough?
Edit
I achieved what I wanted by using the REST Service (CustomServiceBean) and NotesCalendar for creating/updating/deleting reservations, paired with direct document access to check for conflicts and read detailed room & reservation data. Everything works fine so far, reservations are visible in both user's calendar and the dtabase. However when I re-installed the server from scratch and added the database with rest service, I couldn't access the api with my default admin user (403 forbidden, You are forbidden to perform this operation ) server logs:
HTTP JVM: CLFAD0229E: Security exception occurred servicing request for: /db.nsf/services.xsp/api - HTTP Code: 403. For more detailed information, please consult error-log-0.xml
When I added the admin user to Configuration->Current Server Document->Security->Sign or run unrestricted methods and operations, it starts working correctly, even when accessing the API with newly registered users (that weren't assigned any groups, permissions, nothing at all just an internet password & address and they were created by the admin account)
Will this work correctly? I need to access the API from accounts of normal users, because I need to create entries in user's calendars.
I am trying to access the VersionOne data using the V1APIConnector. I can verify that I am using the correct data and meta URLs. I also have the correct domain/username and password.
But everytime I execute the below code, I get an Authentication error saying username/password is invalid and my account gets locked.
Once I unlocked my account, I tried again and the account was locked again. I am the V1 Administrator so I have the permissions.
Our VersionOne instance uses Windows Integrated Auththentication. Also my username is in the format -mydomain/myusername
Is there any different way to pass the credentials? Since my account is getting locked, it must mean at least the domain and the username are being passed correctly. Any Ideas?
V1APIConnector dataConnector = new V1APIConnector( _dataUrl, _username, _password);
V1APIConnector metaConnector = new V1APIConnector( _metaUrl );
IMetaModel metaModel = new MetaModel(metaConnector);
IServices services = new Services(metaModel, dataConnector);
System.out.println("Creating query");
IAssetType defectType = metaModel.getAssetType("Defect");
Query query = new Query(defectType);
IAttributeDefinition nameAttribute = defectType.getAttributeDefinition("Name");
query.getSelection().add(nameAttribute);
query.getPaging().setPageSize(3);
query.getPaging().setStart(0);
System.out.println("Retrieve from query");
QueryResult result = services.retrieve(query);
The Java.SDK ignores the username and password parameters of the V1APIConnector constructor when attempting to connect to a Windows Integrated instance, and instead uses the domain credentials that it is running under. If you are logged into your machine as "MyDomain\MyUsername" then that is the credentials that it will use. It does not support supplying the credentials of another account.
Note that there must also exist a VersionOne member account with the username set to "MyDomain\MyUsername" to successfully authenticate.
VersionOne locks accounts only when your license has expired, and if that happens, only the system administrator (Member:20) will remain active. In addition, administrators can deactivate accounts manually.
I want to IP Ban a user if he fails to login 5 times at my website. How do I get someone's IP in Java and then ban it from my site?
Currently, my login servlet looks like this. I know the counting system should be implemented differently and I will get working on that later. For now, I just want to test out IP bans.
if(user.isValid())
{
HttpSession session = request.getSession(true);
session.setAttribute("currentSessionUser",user);
response.sendRedirect("Unit_Info.jsp");
}else{
x=x+1;
System.out.println("Failed Login " + x + "\n");
if(x==5)
response.sendRedirect("http://google.com"); //IP BAN HIM
else
response.sendRedirect("index.jsp");
}
EDIT: Now that I think about it more, what happens if someone is using a proxy and constantly changing IPs when trying out username/passwords. Is there a sure way to ban the guy, whether he is using a proxy or not?
You could use fail2ban to achieve the same. Here is the resource. Else you can have a bit in the db which sets once it crosses the number of attempts parameter. You can put those IP addresses in the blocked list of the server.
I have been trying to connect to Teradata
Class.forName("com.teradata.jdbc.TeraDriver");
String connectionString = "jdbc:teradata://xxx.xxxxxx.com/database=xxxxxx, tmode=ANSI, charset=UTF8";
String user = "Rocket512";
String password = "aui8mn5";
Connection conn = DriverManager.getConnection(connectionString, user, password);
Got the following
Exception in thread "main" com.teradata.jdbc.jdbc_4.util.JDBCException: [Teradata Database]
[TeraJDBC 14.10.00.17] [Error 8017] [SQLState 28000] The UserId, Password or Account is invalid.
at com.teradata.jdbc.jdbc_4.util.ErrorFactory.makeDatabaseSQLException(ErrorFactory.java:300)
at com.teradata.jdbc.jdbc.GenericLogonController.run(GenericLogonController.java:666)
at com.teradata.jdbc.jdbc_4.TDSession.<init>(TDSession.java:216)
I know that the host is specified correctly since i did not get UnknownHost Exception.
Also I have double checked my userid and password are correct.
I ran query suggested by #beni23 (thank you)
select *
from dbc.logonoff
where logdate >= date '2013-10-31'
Here is the result that I got
What is Bad Password? I used SQL Assistant with this very password and it works great. Why cannot i connect with Java?
LDAP Authentication failures will not be captured in DBC.LogOnOff as a Bad Password event because the authentication doesn't take place on the database.
Typically the error message you are receiving, The UserId, Password or Account is invalid., is indicative of the user account being locked on the database.
SELECT U.UserName
, U.ProfileName
, U.DefaultAccount
, COALESCE(P.MAXLOGONATTEMPTS, S.MAXLOGONATTEMPTS) AS MaxLogonAttempts_
, U.LockedCount
, U.LockedDate
FROM dbc.UsersV U
LEFT JOIN
dbc.ProfileInfoV P
ON P.ProfileName = U.ProfileName
CROSS JOIN
dbc.SecurityDefaults S
WHERE UserName = 'Rocket512';
If LockedCount is not 0 than a failed logon attempt has occurred since the last successful logon to the database.
If LockedDate is not NULL it represents the date which the account was last locked.
MaxLogonAttempts_ will tell you how many times you can attempt to logon using database authentication (TD2) before the account is locked.
A couple of things I would suggest:
Remove whitespace between the parameters of connectString
Put the User and Password parameters in the connectString
Using original code above modify the connectString to add: ,ACCOUNT=$AMRWRW&DrT&r which should match what is returned by the query in my response above (I have added DefaultAccount).
EDIT: 11/12/13
May I suggest you download Teradata Studio Express and attempt to make a connection to the same Teradata system using JDBC much like you are here in your code. This may help shed light on the parameters you need to specify in your connection string in order to make the connection successful. You should be able to setup your connection parameters in Teradata Studio Express the same as you have here in your code and see if it works.
Using LDAP as the logon mechanism for a user that has not been granted the explicit right to logon with a NULL password has resulted in the error message `The UserId, Password or Account is invalid.'. I received this the other day using a privileged account without changing my logon mechanism from LDAP to TD2.
What does the following SQL return?
SELECT *
FROM DBC.LogonRulesV
WHERE UserName = 'Rocket512';
It may not return anything, which is okay. This simply means you ability to logon with that userid from any host on the system has not been explicitly granted or revoked.
EDIT: 05/22/18
The “Bad Password” event for an externally authenticated user may will appear in the event log when the provided password and the what is stored on the directory server do not match. In certain scenarios you can verify this by using ldapsearch from the PDN to submit an inquiry directly to the LDAP directory. You can find more details about using this command in the Security Administration manual. I’ve discovered this trying to triage a problem with a subset of user accounts that fail to authenticate to the directory. I felt it would be appropriate to update this answer with more details as my lead in statement at the top is not 100% accurate.
The following might not give you a solution, but might point you in the right direction. I think you'll want to check the dbc.logonoff table in teradata through a console to make sure that your user is not locked or get an idea whether your driver is hitting teradata.
select *
from dbc.logonoff
where logdate >= date '2013-10-31'
Reading this article Troubleshooting Security: The UserId, Password or Account is invalid. we can see the typical reason of this error.
Cause: LOGMECH=LDAP is specified, and the username/password credentials
are redundantly provided in the both LOGDATA and as separate
connection parameters.
Solution: Identify LDAP users via LOGDATA, or
via separate username/password parameters, but not both
simultaneously.
So, you should check this case. May be you can get connection without user/password
Perhaps you might have more luck with:
String driver = "com.teradata.jdbc.TeraDriver";
String conUrl="jdbc:teradata://xxx.xxxxxx.com/database=xxxxxx,USER=Rocket512,PASSWORD=aui8mn5,tmode=ANSI,charset=UTF8";
Class.forName(driver);
Connection dbConn = DriverManager.getConnection(conUrl);
If that doesn't work make sure to use the latest jdbc driver.
I had similar error and followed all the suggestions given in here. My account was not locked and I was able to connect to the DB with the same username and password, via SQL assistance editor.
The solution worked for me was adding following line in the connection string: LOGMECH=LDAP.
You need to know the logon mechanism for your Teradata, or you can reach out to your DBA team, as I did. So your connection string will look something like this:
String connurl="jdbc:teradata://xx/database=xx,USER=xx,PASSWORD=xx,tmode=ANSI,charset=UTF8,LOGMECH=LDAP";
Can i read user password policy from LDAP, like when it expires or more details like password strength (minimal length etc.) ? I need these information so I can use the same policy for users kept in my database. My java application require that users from the database have to be synchronized with domain.
If you want to get the password policy through LDAP queries try this
without PSO policy in your current domain
String searchDomain= "DC=company,DC=ORG";
String ldapQuery = "(&(objectClass=domainDNS))";
String ldapAttribute = "maxPwdAge";
If you use a PSO policy try this code
String domainLookupString = "CN=UsersPSO,CN=Password Settings Container,CN=System,DC=company,DC=ORG";
String ldapFilterString = "(&(objectClass=msDS-PasswordSettings))";
String ldapAttribute = "msDS-MaximumPasswordAge"
Usually, there are at least three different things that are of concern in these circumstances.
Account status, which includes such information as is the account locked, expired or disabled.
The account "status" is typically reflected on the MMC Account Tab.
We put some information on our wiki about the LDAP values at:
http://ldapwiki.willeke.com/wiki/Active%20Directory%20Account%20Lockout
and
http://ldapwiki.willeke.com/wiki/MMC%20Account%20Tab
Password status, is the password expired.
Unfortunately, the attributes that reflect the status of these conditions are not reflected in AD in real time. Some are only updated when a user attempts to authenticate. (either successfully or un-successfully).
-jim
Yes you can, with JNDI. You have to read the value of the pwdPolicySubentry operational attribute from the user's Context. This gives you the DN of the pwdPolicy object, which you then lookup as a Context with attributes, and get all the attributes starting with 'pwd'. However if the user has the default password policy you will have to look at your LDAP server configuration to find its DN. In OpenLDAP this is in slapd.conf in the ppolicy_default line in the 'overlay ppolicy' directives block.
It depends the underlying LDAP server.
For instance, if you are using Microsoft Active Directory, a user entry will have an attribute called accountExpires which is the date the account expires.
Active Directory also have a user attribute called userAccountControl which is a bit-mask specifying various account related states. For instance, if bit 24 is set, that means that the password has expired (userAccountControl & 0x800000 != 0). Bit 2 is "account disabled" etc. Read more at http://support.microsoft.com/kb/305144.
For other LDAP servers (OpenLDAP, ApacheDS, etc, etc) you'll have to look into the documentation.