Active Directory Search to get users domain - asp.net

I am trying to query Active directory for a user to get a list of details:
1. First/Last Name
2. Email
3. UserName
4. Domain
I am able to get all except for the domain name. Here is my code:
Dim oroot As DirectoryEntry = New DirectoryEntry("GC://ldap.someCompany.com")
Dim osearcher As DirectorySearcher = New DirectorySearcher(oroot)
Dim result As SearchResult
osearcher.Filter = String.Format("(&(SAMAccountName={0}))", "myUsername")
osearcher.PropertiesToLoad.Add("cn")
osearcher.PropertiesToLoad.Add("SAMAccountName") 'Users login name
osearcher.PropertiesToLoad.Add("givenName") 'Users first name
osearcher.PropertiesToLoad.Add("sn") 'Users sur name
osearcher.PropertiesToLoad.Add("mail") 'Email address
result = osearcher.FindOne
Try
myUser.UserID = result.Properties("cn").Item(0)
myUser.Domain = ""
myUser.EmailAddress = result.Properties("mail").Item(0)
myUser.FirstName = result.Properties("givenName").Item(0)
myUser.LastName = result.Properties("sn").Item(0)
myUser.Domain = result.Properties("displayName").Item(0)
Catch ex As Exception
Return Nothing
End Try
This returns this string: GC://ldap.someCompany.com/CN=FirstName M LastName,OU=Employees,OU=Domain Users,DC=val1,DC=val2,DC=com
So, I have two questions. First, how do I get the domain name of the user? It appears to be in DC= (where I have val1)
Second, is there anyway to speed this search up? Right now, it takes about 10 seconds to run the query.
I am using .net 4.0 and Visual Studio 2010
Thanks for any help
jason

Strart from right and read the DC components, then you have the realm/domain of the account. See RFC2247.

Related

Sharepoint Updating MMS DocumentSet field

I have am writing some SharePoint 2013 integration to my companies product, to upload a document set with metadata and then upload some documents.
I have all this functionality working correctly, except for updating Document Set metadata fields that require MMS (Managed Metadata Service) fields.
dim docSetUrl as string = "http://someurl/"
Dim folder = Context.Web.GetFolderByServerRelativeUrl(docSetUrl)
Context.Load(folder)
Context.ExecuteQuery()
folder.Properties.Item("GeoObject") = "test" 'Normal string content (updates correctly)
folder.Properties.Item("Applicant") = "1353;#: Value A : REC-95342|9074b95b-9dcd-4c93-b548-32a5c7e7e083" 'Does not update correctly
folder.Update()
Context.ExecuteQuery()
Now as you can see from the code, I can update the GeoObject which just requires a string value, but for the Applicant object which is a MMS type, it just doesn't change (no errors).
If I log into SharePoint and manually use MMS to select an item, and then programatically check what it's value is : 353;#: Value A : REC-95342|9074b95b-9dcd-4c93-b548-32a5c7e7e083, if I clear the value manually and then try to push the found value back in, I still have no result.
How am I supposed to update a MMS field?
Thanks,
I was able to piece this together via lots of input from different sources. Such as https://unnieayilliath.com/2015/08/24/sharepoint-2013-updateclear-taxonomy-field-value-using-c-csom/
Dim value As TaxonomyFieldValue = New TaxonomyFieldValue()
value.WssId = -1
value.TermGuid = terms.First.Id.ToString
value.Label = terms.First.Name
Dim list As List = folder.ListItemAllFields.ParentList
Dim field As Field = list.Fields.GetByInternalNameOrTitle("Property")
Dim txField As TaxonomyField = Context.CastTo(Of TaxonomyField)(field)
txField.SetFieldValueByValue(folder.ListItemAllFields, value)
folder.ListItemAllFields.Update()
Context.Load(folder.ListItemAllFields)
Context.ExecuteQuery()

OpenLDAP: Retrieve parent DN

What I have:
I have following hierarchy in my openldap setup.
Account '1-AA' has a user 'Foo'.
Base DN is
o=MyCompany,dc=sanjose,dc=corp,dc=company,dc=edu
Account is directly under Base DN.
What I want:
I want to display what is the account id (here 1-AA) for user 'Foo'.
What I know/tried:
Using standard java ldap search as
env = new Hashtable<String, String>();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL,"ldap://<host>:<port>/dc=sanjose,dc=corp,dc=company,dc=edu");
LdapContext ctx = new InitialLdapContext(env, null);
NamingEnumeration<?> namingEnum = ctx.search("o=MyCompany",
"(user=Foo)", getSimpleSearchControls());
//hasNext loop
SearchResult result = (SearchResult) namingEnum.next();
System.out.println(result.getNameInNamespace());
Now the problem is that no result is returned in the above case. But if I try to get DN for Account 1-AA by changing search query to
NamingEnumeration<?> namingEnum = ctx.search("o=MyCompany",
"(Account=1-AA)", getSimpleSearchControls());
it works fine.
How can I get the parent DN here. In English I just want to say give me all the Account Ids for while user=Foo.
Assuming searching for (user=Foo) does return the entry user=Foo,Account=1-AA,o=MyCompany,dc=sanjose,dc=corp,dc=company,dc=edu, then javax.naming.ldap.LdapName can get you the rest of the way. http://docs.oracle.com/javase/tutorial/jndi/newstuff/ldapname.html has an example of taking a prefix or suffix from a DN.

LDAP user attribute request returns unusual results

I'm struggling to return user details from AD using LDAP, after i have authenticated that the user exists.
I am using a simple auth method as follows:
Function AuthenticateUser(path As String, user As String, pass As String) As Boolean
Dim de As New DirectoryEntry(path, user, pass, AuthenticationTypes.Secure)
Try
Dim ds As DirectorySearcher = New DirectorySearcher(de)
Dim result As SearchResult = ds.FindOne()
If result Is Nothing Then Return False
'>>DEBUG OUTPUTS ONLY:
displayName.Text = result.GetDirectoryEntry().Properties.Item("distinguishedName").Value
displayName.Text += result.GetDirectoryEntry().Properties("name").Value
Return True
Catch
Return False
End Try
End Function
the problem is that "distinguishedName" returns "DC=our-domain,DC=co,DC=uk"
and "name" returns just "our-domain", not the name of the user that has just been auth'ed
Note: the displayName.text outputs are purely for debug purposes
I have tried various combos of requests but nothing seems to return USER details.
ETA: to the security police: this is all within a https connection, I'm not sending passwords about in plain text!
1. Dim de As New DirectoryEntry(path, user, pass, AuthenticationTypes.Secure)
2. Try
3. Dim ds As DirectorySearcher = New DirectorySearcher(de)
4. Dim result As SearchResult = ds.FindOne()
Line 1 is basically creating a DirectoryEntry element, that refers to the object at path. The only purpose that the username and password parameters serve is to authorise access to whatever entity path refers to.
As you currently have things, you're binding to the domain, not to the user (but you're authorised to connect to the domain as that user).
You then, in line 3, create a DirectorySearcher. But the constructor you're using just says to root the search at de (which as we've established, is just the domain). You've not done anything yet to search for that particular user within the domain - they could be connecting to perform almost any kind of search imaginable.
What you might want to do is look at the overload of DirectorySearcher that accepts a filter parameter - and provide a filter parameter that restricts the search to just the user. I don't know what form your user parameter is in - if it is, say, in the form of a user principal name (user#domain), you might try specifying a filter of:
Dim ds As DirectorySearcher = New DirectorySearcher(de,"(userPrincipalName=" + user + ")")
If you have just a username, you'd want to search against sAMAccountName. If you have an older style domain name (domain\user), then usually you want to split that on \, discard the domain name, and still search on sAMAccountName.
Some (but not too much!) help on constructing the filter parameters is found in the Filter property documentation.

Update user using DirectoryService

So I managed to get some code rolling for updating the AD from an external sourced. However, I'm a bit confused about how it works.
I have a person with sAMAccount xxxx existing in different OUs.
Now, I only want to update the info in a specific OU, so I put that in my LDAP path. Still, it seem that the info has been updated in different OU's as well?
Could that be possible? Is it because there's only one "Person" object, or do the "GetDirectoryEntry()" not put me where I thought in the tree? Or.. am I only imagine and the weird things I see is becausde of something else.
Some code
DirectoryEntry entry = new DirectoryEntry(LDAP://my.path/ou=myou, dc=my, dc=path);
entry.Username = myUser
entry.Password = myPass
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = #"(&(objectClass=Person)(SamAccountname=" + person.id + "))";
SearchResult result = searcher.FindOne();
try
{
DirectoryEntry user = result.GetDirectoryEntry();
user.Properties["displayName"].Value = person.DisplayName;
user.Properties["givenName"].Value = person.Firstname;
user.CommitChanges();
user.Close();
}
catch (DirectoryServicesCOMException ex)
EDIT: It did update the Person object in all the OU's. So either the Person object is one and the same in the whole AD, whick makes my attempt to update them in only the specific OU pointless, or does the "result.GetDirectoryEntry" ignore the fact that I thought I was working only in my specific OU declared in my LDAP path.
Functionality confirmed, still wonder why I needed a specific test-ou since it's still the same users. Anyway, here we go!

Is asp.net caching my sql results?

I have the following method in an App_Code/Globals.cs file:
public static XmlDataSource getXmlSourceFromOrgid(int orgid)
{
XmlDataSource xds = new XmlDataSource();
var ctx = new SensusDataContext();
SqlConnection c = new SqlConnection(ctx.Connection.ConnectionString);
c.Open();
SqlCommand cmd = new SqlCommand(String.Format("select orgid, tekst, dbo.GetOrgTreeXML({0}) as Subtree from tblOrg where OrgID = {0}", orgid), c);
var rdr = cmd.ExecuteReader();
rdr.Read();
StringBuilder sb = new StringBuilder();
sb.AppendFormat("<node orgid=\"{0}\" tekst=\"{1}\">",rdr.GetInt32(0),rdr.GetString(1));
sb.Append(rdr.GetString(2));
sb.Append("</node>");
xds.Data = sb.ToString();
xds.ID = "treedata";
rdr.Close();
c.Close();
return xds;
}
This gives me an XML-structure to use with the asp.net treeview control (I also use the CssFriendly extender to get nicer code)
My problem is that if I logon on my pc with a code that gives me access on a lower level in the tree hierarchy (it's an orgianization hierarchy), it somehow "remembers" what level i logon at. So when my coworker tests from her computer with another code, giving access to another place in the tree, she get's the same tree as me.
(The tree is supposed to show your own level and down.)
I have added a html-comment to show what orgid it passes to the function, and the orgid passed is correct. So either the treeview caches something serverside, or the sqlquery caches it's result somehow...
Any ideas?
Sql function:
ALTER function [dbo].[GetOrgTreeXML](#orgid int)
returns XML
begin RETURN
(select org.orgid as '#orgid',
org.tekst as '#tekst',
[dbo].GetOrgTreeXML(org.orgid)
from tblOrg org
where (#orgid is null and Eier is null) or Eier=#orgid
for XML PATH('NODE'), TYPE)
end
Extra code as requested:
int orgid = int.Parse(Session["org"].ToString());
string orgname = context.Orgs.Where(q => q.OrgID == orgid).First().Tekst;
debuglit.Text = String.Format("<!-- Id: {0} \n name: {1} -->", orgid, orgname);
var orgxml = Globals.getXmlSourceFromOrgid(orgid);
tvNavtree.DataSource = orgxml;
tvNavtree.DataBind();
Where "debuglit" is a asp:Literal in the aspx file.
EDIT:
I have narrowed it down. All functions returns correct values. It just doesn't bind to it. I suspect the CssFriendly adapter to have something to do with it.
I disabled the CssFriendly adapter and the problem persists...
Stepping through it in debug it's correct all the way, with the stepper standing on "tvNavtree.DataBind();" I can hover the pointer over the tvNavtree.Datasource and see that it actually has the correct data. So something must be faulting in the binding process...
I would normally suspect the issue is with orgid that is getting passed in to your method, but you say that you have checked to make sure the right code is being passed. Just to confirm, show us the code that assigns the value to that.
Additionally, there are a few problems with your code, SQL injection risk being one of them. orgid is an int, offering some protection, but if at some point orgid is changed to require characters by your organization, a developer may just change the data type to string, suddenly opening up the app to SQL injection. You should remove the String.Fotmat, and use a parameterized query instead.
I found the problem. The XmlDataSource component has a cache function, which by default is enabled. When I disabled this, everything works nicely.

Resources