I need to check the syntax OID's for LDAP attributes but I can't find any good starting point. I'm using C# and currently System.DirectoryServices.Protocols (must stay generic / non-Active Directory specific).
For example, using Apache Directory Studio against we can see that in Active Directory the "distinguishedName" attribute has syntax OID "1.3.6.1.4.1.1466.115.121.1.12".
Can anyone please kick me in the right direction?
Okay, I figured it out. I used a combination of this and this SO posts to work it out. Here it is stitched together, if any other soulds out there need it. Note that this works on Active Directory and OpenLDAP (using System.DirectoryServices.Protocols).
var ldapConnection = new LdapConnection( "hostname.tld" );
ldapConnection.AuthType = AuthType.Yours;
ldapConnection.Credential = new NetworkCredential( "username", "password", "domain" );
ldapConnection.SessionOptions.ProtocolVersion = 3;
// Find the subschema first...
var searchRequest = new SearchRequest( null, "(objectClass=*)", SearchScope.Base, "subschemasubentry" );
var searchResponse = (SearchResponse) ldapConnection.SendRequest( searchRequest );
var subSchemaArray = searchResponse.Entries[0].Attributes["subschemasubentry"].GetValues( typeof( String ) );
var subSchema = (String) subSchemaArray[0];
// Now query the LDAP server and get the attribute types
searchRequest = new SearchRequest( subSchema, "(objectClass=*)", SearchScope.Base, "attributetypes" );
searchResponse = (SearchResponse) ldapConnection.SendRequest( searchRequest );
foreach ( string attributeType in searchResponse.Entries[0].Attributes["attributeTypes"].GetValues( typeof( String ) ) )
{
// This is a chunky string, but the name and syntax OID is listed here
Console.WriteLine(attributeType);
}
Related
We are using tagging in S3 for some files, however, if we use an "& " character in the value of the key value pair, I get the following error
"The TagValue you have provided is invalid"
Any ideas on how to get around this to work in S3?
Here is the code we are using with the AWS Sdk
var documents = await GetDocumentsAsync(clientDoc.ClientId);
var objectKey = $"{clientDoc.ClientId}/{clientDoc.FileName}";
var newTagSet = new Tagging
{
TagSet = new List<Tag>{
new Tag { Key = "ClientName", Value = clientDoc.ClientName ?? "" }
}
};
var putObjTagsRequest = new PutObjectTaggingRequest()
{
BucketName = _systemConfig.S3BucketName,
Key = objectKey,
Tagging = newTagSet
};
var response = await s3Client.PutObjectTaggingAsync(putObjTagsRequest);
Tags must follow the following regex ^([\p{L}\p{Z}\p{N}_.:/=+\-#]*)$
https://docs.aws.amazon.com/directoryservice/latest/devguide/API_Tag.html
The only way to 'get around it' would be to not use the character. You could encode it but at that point... probably best to just not use it.
I have the below snippet in PowerShell that is returning me the information I need for local administrators on a remote PC. I am trying to convert this code into c#, but have been having very little luck with it.
$ADMINS = get-wmiobject -computername $computername -Credential $Credential -query "select * from win32_groupuser where GroupComponent=""Win32_Group.Domain='$computername',Name='administrators'""" | % {$_.partcomponent}
I am able to get a basic wmi query working in c# as seen below :
Method
public IEnumerable<CimInstance> WmiQuerier(CimSession session , string wmiquery)
{
try
{
string Namespace = #"root\cimv2";
IEnumerable<CimInstance> CimInstances = new List<CimInstance>();
CimInstances = session.QueryInstances(Namespace, "WQL", wmiquery);
//IEnumerable<CimInstance> CimInstances2 = CimInstances.SelectMany()
return CimInstances;
}
catch (Exception ex )
{
Console.WriteLine(ex.Message);
throw;
}
TEST
[Test]
public void CimQuery()
{
string querystring = "SELECT * FROM win32_groupuser";
Wmi wmi = new Wmi();
NetworkCredential mynetcred = new NetworkCredential("Domain\\User", "Password%");
CimCredential mycimCred = wmi.ConvertCred(mynetcred);
CimSession mySession = wmi.WmiConnection(testcomp, mycimCred);
IEnumerable<CimInstance> querierResults = wmi.WmiQuerier(mySession, querystring).Take(5).ToList();
Assert.IsInstanceOf<IEnumerable<CimInstance>>(querierResults);
}
}
However, When I attempt to add in any kind of Where clause like I have in the powershell code, (See my attempt below )
"SELECT * FROM win32_groupuser Where GroupComponent = \"Win32_Group.Domain='MachineName',Name='administrators' \""
I get the error
Microsoft.Management.Infrastructure.CimException: 'The WS-Management
service cannot process the request. The WQL query is invalid. '
What am I doing incorrectly in my WQL string?
Here's a query that works. I know one thing...that the syntax of the WQL is extremely sensitive and unforgiving...especially regarding spaces and quote nesting. Funny enough, it's fine with uppercase/lowercase:
using System.Management;
//....
var domainName = "YourDomainName";
var groupName = "Administrators";
var wql = string.Format
(
#"select partcomponent from win32_groupuser where groupcomponent='Win32_Group.Domain=""{0}"",Name=""{1}""'",
domainName,
groupName
);
foreach ( var thing in new ManagementObjectSearcher( wql ).Get( ) )
{
foreach ( var property in thing.Properties )
{
//--> And then, if you want the account object...
var path = new ManagementPath( property.Value as string );
var account = new ManagementObject( path );
foreach ( var acctProp in account.Properties )
{
Console.WriteLine( $"{acctProp.Name}={acctProp.Value}" );
}
}
}
Edit: Just for yucks, I added code to get the referenced Win32_Account object...since the value of partcomponent is a qualified reference to that account object.
It isn't clear on your example why it is failing since you do not have the WHERE clause set. My best guess is that some characters are not being escaped like they should.
You can also use ORMi library to give your problem an indirect solution. You can do it this way:
WMIHelper helper = new WMIHelper("root\\CimV2");
var users = helper.Query("SELECT * FROM Win32_GroupUser").ToList().Where(u => u.Contains("Win32_Group.Domain='MachineName',Name='administrators'"));
I have this AD server "adserver.europe.company.com".
I know there are some ... "branches". "DC=europe,DC=company,DC=com","DC=africa,DC=company,DC=com", "DC=asia,DC=company,dc=com" etc.
If I query the server (using the DirectorySearcher class) with SearchScope = OneLevel and an empty base asking only for the distinguishedName I get only entries ending in "DC=europe,DC=company,DC=com".
However, if I use "DC=africa,DC=company,DC=com" as base, I do get the entries ending in "DC=africa,DC=company,DC=com".
How can I get all the branches for this AD server?
I managed to obtain all the partitions this way:
DirectoryContext aContext = new DirectoryContext( DirectoryContextType.DirectoryServer, LDAPServer, LDAPUser, LDAPPassword );
Forest aForest = Forest.GetForest( aContext );
foreach ( ApplicationPartition aPartition in aForest.ApplicationPartitions )
{
...
}
Forgive me if this is redundant or I'm missing something simple, but I'm playing around with ElasticSearch (and NEST in particular) to see if it would be a good add for our b2b ecommerce site's search function.
I grabbed the latest NuGet of NEST and then tried to serialize and add something to an index. Here is a snippet of the approach I was using
var localhost = new Uri("http://localhost/9200");
var setting = new ConnectionSettings(localhost).SetDefaultIndex("cpi_catalog");
var client = new ElasticClient(setting);
client.MapFromAttributes<Item>();
var testitem = new Item()
{
Description = "test",
Id = 9999999,
Manufacturer_Id = 5,
Quantity_Per_Unit = 1,
Quantity_Unit_Id = "EA",
SKU = "AVE29845",
Subtitle = "test",
Title = "test"
};
var status = client.Index(testitem);
However, it seems that testitem is never indexed at all, when I do a GET for /cpi_catalog/items/9999999 I get the following:
{"_index":"cpi_catalog","_type":"items","_id":"9999999","exists":false}
What seemingly simple thing am I missing here?
EDIT: When debugging, I get back a Nest.IndexResponse with all fields NULL besides status.OK which is false
Seems like the uri is has a typo:
var localhost = new Uri("http://localhost/9200");
should probably be:
var localhost = new Uri("http://localhost:9200");
I am indexing and searching with lucene.net, the only problem I am having with my code is that it does not find any hits when searching for "mvc2"(it seems to work with all the other words I search), I have tried a different analyzer(see comments by analyzer) and older lucene code, here is my index and search code, I would really appreciate if someone can show me where I am going wrong with this, Thanks.
////Indexing code
public void DoIndexing(string CvContent)
{
//state the file location of the index
const string indexFileLocation = #"C:\RecruitmentIndexer\IndexedCVs";
//if directory does not exist, create it, and create new index for it.
//if directory does exist, do not create directory, do not create new //index(add field to previous index).
bool creatNewDirectory; //to pass into lucene GetDirectory
bool createNewIndex; //to pass into lucene indexWriter
if (!Directory.Exists(indexFileLocation))
{
creatNewDirectory = true;
createNewIndex = true;
}
else
{
creatNewDirectory = false;
createNewIndex = false;
}
Lucene.Net.Store.Directory dir =
Lucene.Net.Store.FSDirectory.GetDirectory(indexFileLocation, creatNewDirectory);//creates if true
//create an analyzer to process the text
Lucene.Net.Analysis.Analyzer analyzer = new
Lucene.Net.Analysis.SimpleAnalyzer(); //this analyzer gets all //hits exept mvc2
//Lucene.Net.Analysis.Standard.StandardAnalyzer(); //this leaves out sql once //and mvc2 once
//create the index writer with the directory and analyzer defined.
Lucene.Net.Index.IndexWriter indexWriter = new
Lucene.Net.Index.IndexWriter(dir, analyzer,
/*true to create a new index*/ createNewIndex);
//create a document, add in a single field
Lucene.Net.Documents.Document doc = new
Lucene.Net.Documents.Document();
Lucene.Net.Documents.Field fldContent =
new Lucene.Net.Documents.Field("content",
CvContent,//"This is some text to search by indexing",
Lucene.Net.Documents.Field.Store.YES,
Lucene.Net.Documents.Field.Index.ANALYZED,
Lucene.Net.Documents.Field.TermVector.YES);
doc.Add(fldContent);
//write the document to the index
indexWriter.AddDocument(doc);
//optimize and close the writer
indexWriter.Optimize();
indexWriter.Close();
}
////search code
private void button2_Click(object sender, EventArgs e)
{
string SearchString = textBox1.Text;
///after creating an index, search
//state the file location of the index
const string indexFileLocation = #"C:\RecruitmentIndexer\IndexedCVs";
Lucene.Net.Store.Directory dir =
Lucene.Net.Store.FSDirectory.GetDirectory(indexFileLocation, false);
//create an index searcher that will perform the search
Lucene.Net.Search.IndexSearcher searcher = new
Lucene.Net.Search.IndexSearcher(dir);
SearchString = SearchString.Trim();
SearchString = QueryParser.Escape(SearchString);
//build a query object
Lucene.Net.Index.Term searchTerm =
new Lucene.Net.Index.Term("content", SearchString);
Lucene.Net.Search.Query query = new Lucene.Net.Search.TermQuery(searchTerm);
//execute the query
Lucene.Net.Search.Hits hits = searcher.Search(query);
label1.Text = hits.Length().ToString();
//iterate over the results.
for (int i = 0; i < hits.Length(); i++)
{
Lucene.Net.Documents.Document docMatch = hits.Doc(i);
MessageBox.Show(docMatch.Get("content"));
}
}
I believe that StandardAnalyzer actually strips out "2" from "mvc2", leaving the indexed word to be only "mvc". I'm not sure about SimpleAnalyzer though. You could try to use WhitespaceAnalyzer, which I believe doesn't strip out numbers.
You should also process your search input the same way that you process indexing. A TermQuery is a "identical" match, which means that you if you try to search for "mvc2" where the actual strings in your index always says "mvc", then you won't get a match.
I haven't found a way to actually make use of an analyzer unless I use the QueryParser, and even then I always had odd results.
You could try this in order to "tokenize" your search string in the same way as you index your document, and make a boolean AND search on all terms:
// We use a boolean query to combine all prefix queries
var analyzer = new SimpleAnalyzer();
var query = new BooleanQuery();
using ( var reader = new StringReader( queryTerms ) )
{
// This is what we need to do in order to get the terms one by one, kind of messy but seemed to be the only way
var tokenStream = analyzer.TokenStream( "why_do_I_need_this", reader );
var termAttribute = tokenStream.GetAttribute( typeof( TermAttribute ) ) as TermAttribute;
// This will return false when all tokens has been processed.
while ( tokenStream.IncrementToken() )
{
var token = termAttribute.Term();
query.Add( new PrefixQuery( new Term( KEYWORDS_FIELD_NAME, token ) ), BooleanClause.Occur.MUST );
}
// I don't know if this is necessary, but can't hurt
tokenStream.Close();
}
You can replace the PrefixQuery with TermQuery if you only want full matches (PrefixQuery would match anything starting with, "search*")