OpenLdap with Directory Services - Load operational attributes - c#

I'm currently developing a custom Membership provider using the DirectoryServices API to interface with a OpenLdap server (running on a cloud based Ubuntu instance) to handle authentication for our new website. However I'm running into an issue where we need to access some of the operational attributes e.g. reading 'pwdAccountLockedTime' to see if the user account is locked or removing it to unlock the user account.
I have tried adding the required attributes to the DirectorySearcher's PropertiesToLoad collection, but this does not seem to load the required properties into the DirectoryEntry when we load it from the SearchResult.
In Novell (which we used previously) we could specify the string array { "*", "+" } when searching or reading to load the entry with all attributes (including the operational ones), but this doesn't seem to work in Directory Services.
We are currently using the Mono framework as our servers are running on Ubuntu instances, and the Mono project status for System.DirectoryServices currently reports as complete (apart from 2 namespaces that we aren't using), so we're not too sure if this is a Mono bug (it wouldn't be the first we've found in some of the lesser used libraries) or if we are using the DirectoryServices API incorrectly.
Long question short, how do you correctly load operational attributes when using the DirectoryServices API?

Turns out the additional requested attributes are loaded (and { "*", "+" } does work), its just that instead of the attributes being loaded into the DirectoryEntry's Properties collection, they are instead (for some reason) only loaded into the Properties collection of the SearchResult, and not into the DirectoryEntry.

Related

ASP.NET Core 6.0+: How to get the current (case-sensitive) IIS Website Name?

I'm trying to get the name of my ASP.NET 6 app hosted in IIS. What I need is exactly this name with proper casing:
In .NET Framework 4.8, this name was provided by HttpRequest.ApplicationPath and it was returned with proper casing (as configured in IIS, not as in the coming request's URL). However, it doesn't exist in .NET 6.
I tried:
HttpContext.Request.PathBase, but it returns the path exactly as in the requesting URL, not as in the IIS
injecting IServerAddressesFeature and IWebHostEnvironment, but none of them contains the name from IIS with correct casing
IServerAddressesFeature, but also didn't find anything relevant here
getting server variables: IServerVariablesFeature serverVars = HttpContext.Features.Get<IServerVariablesFeature>() and then the IIS Site name: string iis_version = serverVars["INSTANCE_NAME"] (see documentation here), but it returns the app name in capital letters (MYSITE.WEB)
Does anyone know how to get this site's name as configured in IIS (with proper casing)?
TL;DR:
Use the APPL_MD_PATH server-variable.
This contains the IIS Metabase Application Path string. (AFAIK, "MD" stands for "Meta-database").
Quoteth the docs:
https://learn.microsoft.com/en-us/previous-versions/iis/6.0-sdk/ms524602(v=vs.90)?redirectedfrom=MSDN
"APPL_MD_PATH - Retrieves the metabase path of the application."
Like so:
// This code assumes HttpContext is available, such as in a Middleware method or `Controller` subclass.
using Microsoft.AspNetCore.Http;
String? iisMetabasePath = httpContext.GetServerVariable("APPL_MD_PATH");
// or (long-form):
String? iisMetabasePath = HttpContextServerVariableExtensions.GetServerVariable( httpContext, "APPL_MD_PATH" );
Then just trim-off the /LM/W3SVC/ part.
Note that when you run your code outside of IIS, such as with ASP.NET Core's development server, all IIS-specific data, like "APPL_MD_PATH" won't be available, so make sure you're handling that case too.
Original research: What happened to ApplicationRoot?
Time to bust-out ILSpy...
HttpRequest.ApplicationPath is HttpRuntime.AppDomainAppVirtualPath.
HttpRuntime.AppDomainAppVirtualPath is VirtualPath.GetVirtualPathStringNoTrailingSlash(HttpRuntime._theRuntime._appDomainAppVPath).
HttpRuntime._theRuntime._appDomainAppVPath is set in HttpRuntime.Init().
HttpRuntime.Init() sets _appDomainAppVPath from HttpRuntime.GetAppDomainString(".appVPath")).
"AppDomain Strings" are small serializable scalar values that are associated with each AppDomain.
Generally speaking, ASP.NET in .NET Framework (aka System.Web) creates a new AppDomain for each Application Scope in IIS.
And of course, AppDomains no-longer exist in .NET Core and later.
So let's find out where the String value for ".appVPath" comes from...
System.Web.Hosting.ApplicationManager::PopulateDomainBindings sets dict.Add(".appVPath", appVPath.VirtualPathString)
"domain bindings" in this context refers to AppDomain bindings: nothing at all to do with DNS domain-names or Host header bindings in IIS. Yay for overloaded terminology.
PopulateDomainBindings is called by System.Web.Hosting.ApplicationManager::CreateAppDomainWithHostingEnvironment.
And it gets virtualPath: VirtualPath.Create(appHost.GetVirtualPath()).
appHost.GetVirtualPath() is IApplicationHost.GetVirtualPath().
There are 2 in-box implementations: System.Web.Hosting.ISAPIApplicationHost and System.Web.Hosting.SimpleApplicationHost. We're interested in ISAPIApplicationHost.
ISAPIApplicationHost gets its virtualPath from the runtime argument to String appId and String appPath in the IAppManagerAppDomainFactory.Create method.
And IAppManagerAppDomainFactory is a COM interface used directly by IIS.
The plot thickens...
At this point I got lost trawling through the legacy IIS 6 ISAPI documentation, looking for traces of the original COM definition of IAppManagerAppDomainFactory but came up empty-handed.
It's probably handled by webengine4.dll which is a native DLL and I don't have the time to bust-out Ghidra right now...
I did notice that the ISAPI request entrypoint method HttpExtensionProc (and its LPEXTENSION_CONTROL_BLOCK parameter) do not contain the IIS Application Scope AppId or Virtual Path, which surprised me - but most importantly: this suggests the value must likely come from the GetServerVariable or ServerSupportFunction callbacks....
However that's likely a waste of time anyway IIS 6 is not IIS7+ and IIS7+'s interfaces are no-longer called "ISAPI" but instead called just "IIS Native-Code API" (that's the most plain and boring API name I've seen in a while...).
So, starting with the "IIS Native-Code API" documentation I quickly found the IWpfApplicationInfoUtil::GetApplicationPropertiesFromAppId method (here "WPF" means "Worker Process Framework", and is entirely unrelated to the other UI-related WPF).
I also found the same data exposed via the IMetadataInfo.GetMetaPath() method (which returns a string of the form "LM/WEBROOT/AppHost/{SiteId}").
So how does an application get a IWpfApplicationInfoUtil interface reference?
IWorkerProcessFramework->GetWpfInterface(WPF_APPLICATION_INFO_UTIL_ID)->GetApplicationPropertiesFromAppId
So how do you get IWorkerProcessFramework?
It's passed as a parameter into your w3wp.exe worker DLL.
So let's see what AspNetCoreModuleV2 does...
Actually AspNetCoreModuleV2 uses IIS's IHttpApplication, derp.
IHttpApplication exposes GetAppConfigPath() which also returns a string of the form /LM/W3SVC/1/ROOT/{Site Name}.
ASP.NET Core seems to use it in a few places.
At this point I gave up as it's now 6:20am, but that was a fun dive!

Dynamic CRM new fields

Some new fields were create in Dynamics CRM.
Now need to push some data to those new fields from asp.net website.
Need to add those new fields to:
[assembly: Microsoft.Xrm.Sdk.Client.ProxyTypesAssemblyAttribute()]
namespace Xrm
how should this be done? I read that these is a tool that generates this class file (CrmSvcUtil.exe).
But I do not understand how this would work.
Is this something that need to be done through Dynamics CRM admin?
Please advise.
Thanks
This should be done by user which has System Administrator or System Customizer, because this user has to have access to all entities metadata.
Basically you should start with downloading CRM SDK, for your version of CRM. For example the latest SDK can be found here:
https://www.microsoft.com/en-us/download/details.aspx?id=50032
Install the SDK and go to the bin folder inside the folder where you installed it. There you can find crmsvcutil.exe. This tool is something like svcutil.exe - it simply generates proxy classes using CRM metadata service. So instead of referring to Account entity like that:
var account = new Entity("account")
you can simply do:
var account = new Account();
and you will have all the properties that account in your system has.
In order to generate this classes just run crmsvcutil.exe using windows command line with proper credentials (it's very well documented if you run it without any parameters). example usage would be:
crmsvcutil /url:https://orgname.api.crm4.dynamics.com/XRMServices/2011/Organization.svc /u:user#orgname.onmicrosoft.com /p:password /serviceContextName:XrmServiceContext /out:Proxies.cs /n:Xrm
this would generate file Proxies.cs, containing namespace Xrm (the one you have posted in your question) with all the entities and fields. Of course the parameters may vary based on what type of organization you are connecting to. If you have problems with specifying proper values then simply put /il as last command line parameter - it will open an interactive login form, that would make it simpler for you to pass proper connection data.

Modifying SharePoint List Using ASMX WebServices

I am writing a custom piece of code that dynamically creates modified document libraries. I've attempted to create a document library template, which succeeds in the UI but cannot be found via-webservices.
So to get to the point - I am attempting to:
1. Set "Allow Management Of Content Types" on the list.
2. Add a new Content Type (Already Created) to the list.
3. Set the new content type as the default content type.
4. Remove the "Document" content type from the list.
So far I have succeeded in being able to "Apply" the custom content type but the others are evading my grasp. The methods I have attempted are through the Lists.asmx service and the method described here: http://msdn.microsoft.com/en-us/library/websvclists.lists.updatelist.aspx
I tried setting the Flags property and a few other potential candidates with no success and no error messages complaining about what I was trying to attempt.
One limitation is that I do NOT have access to the sharepoint dll where this is living.
Once completed - this would be a plugin living in another non-sharepoint system. The only option to include the SharePoint client dll's would be to perform an ILMerge.
EDIT:
http://msdn.microsoft.com/en-us/library/sharepoint/jj193051.aspx (SharePoint 2013 Web Services)
http://msdn.microsoft.com/en-us/library/ee705814(v=office.16).aspx (SharePoint 2010 Web Services)
and yes - technically the ASMX services sound like they're on their way out: http://msdn.microsoft.com/en-us/library/sharepoint/jj164060.aspx
Edit: Tags are relevant to the question.
use SharePoint Client Object Model. This is a library that wraps calls to webservices that allows among other things to batch commands.
The operations you mention are all available.
here is a link to an article that explains Client Object Model:
http://www.codeproject.com/Articles/399156/SharePoint-2010-Client-Object-Model-Introduction
The article focus on ListItems but you can also interact with list properties, even web properties if you want.
Please note that you don't need to run Client Object Model from your sharepoint server. Note the "Client" part in the name.

Get Assembly Build Date in Azure Web Role

In an Azure web role, I want to retrieve the date/time when an assembly was build. I've seen a few tricks to do this by retrieving the linker timestamp from the PE header, but this requires you to read the Assembly.Location which doesn't seem to work in a Azure project. I get this exception:
NotSupportedException - The invoked member is not supported in a dynamic assembly
Perhaps there's a better way of getting this info. Perhaps I can grab the date/time when the Web Role was deployed? That would work for me as well.
Thanks for any help.
You are asking two separate things. It is very much possible that the time when code was compiled/build could be far different then when the role was deployed. So you may get the same date/time and may not, there is no guarantee unless you control build and deploy same time.
If your objective is to know when the role was deployed, you can add this date/time in multiple location and retrieve it in your Role specific code directly. I am not sure if there is a way to get the deployment time from the role and will look deep later.
Here are few suggestions comes in my mind immediately:
Create a "String" setting in your Service Configuration and read it in your Role specific Code. Keep in mind you can not get Service Configuration settings directly in Web Role specific W3WP.exe process as these two process run separately and need some extra coding.
You can also add Date/Time to service configuration and access either in Startup task to process further as below:
http://blogs.msdn.com/b/avkashchauhan/archive/2011/11/09/how-to-access-service-configuration-settings-in-windows-azure-startup-task.aspx
You can add Date/Time setting in your App.Config and access it. I have described here:
http://blogs.msdn.com/b/avkashchauhan/archive/2011/10/25/reading-configuration-entries-using-system-configuration-configurationmanager-class-in-a-windows-azure-application.aspx
In the solution you linked to, instead of doing this:
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
Try doing this:
System.Reflection.Assembly assembly = typeof(AClassInMyAssembly).Assembly;
I'm not sure that will work, but I think it might. If not, you might consider if the Assembly Version would work for your purposes.

Display custom header or column in Windows Explorer

My app adds some custom metadata to files. I want to display it in Windows Explorer like this:
or this:
Is there a way to do this in .NET?
There are two approaches to building custom columns in Windows File Manager: using Windows Property System and Property Definitions for Cloud Storage Provider. You will typically use the first approach to create custom properties for file types that you own. You will use the second approach when displaying custom data from your document management system or any other storage.
Using a Windows Property System.
You can create custom properties for specific file types in Windows Vista and later versions. These properties can be read-only or read-write. As well as they can be indexed by Window Search indexer and participate in the search. There are some limitations:
Microsoft clearly says that property handlers must be in C++, it can not be in .NET:
...property handlers cannot be implemented in managed code and should be
implemented in C++.
The property is tied to the specific file type, which typically belongs to your application. You can not create a property for all file types.
Using Cloud Storage Provider Property Definitions
In Windows 10 Creators Update and later you can add custom columns for file systems created using Cloud Sync Engine API (Storage Provider, Cloud Filter API). This API is used in such tools as OneDrive. You will need to register a Cloud Storage Provider sync root with custom properties definitions, provide data for your custom columns and finally implement a Cloud Storage provider using Cloud File/Cloud Filter API.
Property definitions are not tied to a file type and can be added for all files. Also, even though only some API is available in .NET you still can call Win32 functions and build a cloud provider using managed code only.
Registering the Cloud Storage provider. Here is an example of the Storage Provider registration with custom columns in C#:
StorageProviderSyncRootInfo storageInfo = new StorageProviderSyncRootInfo();
storageInfo.Path = await StorageFolder.GetFolderFromPathAsync("C:\\Users\\User1\\VFS\\");
...
// Adds columns to Windows File Manager.
// Show/hide columns in the "More..." context menu on the columns header.
var proDefinitions = storageInfo.StorageProviderItemPropertyDefinitions;
proDefinitions.Add(new StorageProviderItemPropertyDefinition { DisplayNameResource = "Lock Expires", Id = 2, });
proDefinitions.Add(new StorageProviderItemPropertyDefinition { DisplayNameResource = "Lock Scope", Id = 3, });
StorageProviderSyncRootManager.Register(storageInfo);
A complete registration example could be found here.
Providing data for property definitions. To provide the data for the columns you will use StorageProviderItemProperties.SetAsync() call:
IStorageItem storageItem = await Windows.Storage.StorageFile.GetFileFromPathAsync(path);
StorageProviderItemProperty propState = new StorageProviderItemProperty()
{
Id = 3,
Value = "Exclusive",
IconResource = "C:\\path\\icon.ico" // The optional icon to be displayed in the Status column.
};
await StorageProviderItemProperties.SetAsync(storageItem, new StorageProviderItemProperty[] { propState });
Another approach would be implementing IStorageProviderItemPropertySource interface. It returns properties based on your file path.
Cloud Storage Provider implementation. Finally, you will need a complete file system implementation, supplying data for your files/folders placeholders. You can find complete examples in .NET/C# here:
This post is marked obsolete because the content is out of date. It is not currently accepting new interactions.
PLEASE PAY ATTENTION: THIS ANSWER IS FOR XP AND VISTA ONLY, IT IS OUTDATED
It can be done on XP using a Column Handler shell extension - see here:
http://www.codeproject.com/Articles/3747/Explorer-column-handler-shell-extension-in-C#
However IColumnHandler is not supported on Vista and up. Here you have to implement PropertyHandler. See Windows SDK \Samples\winui\Shell\AppShellIntegration\PropertyHandlers.
Each property is described by property schema XML file. This property schema must be registered with PSRegisterPropertySchema(). Property handler implements IInitializeWithXXX, IPropertyStore and optionally IPropertyStoreCapabilities. You have to register CLSID of your implementation for each file extension you want to handle.
Unfortunately, you cannot use AllFileSystemObject or * in registration.

Categories

Resources