Unkown name exception while creating virtual directory with DirectoryServices - c#

I'm trying to create a virtual directory on a remote server using DirectoryServices by cloning the settings of another virtual directory, but I get a COMException: Unknown name. (Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME)) when invoking AppCreate.
This is the code I've written (simplified with most of tests removed):
public bool CreateVirtualDirectory(string serverName, string primaryVirtualDirectoryName, string virtualDirectoryName, MyUser user)
{
try
{
DirectoryEntry directoryEntry = null;
if (user != null)
directoryEntry = new DirectoryEntry("IIS://" + serverName + "/W3SVC/1/Root", user.UserName, user.Password, AuthenticationTypes.Secure | AuthenticationTypes.Sealing);
else
directoryEntry = new DirectoryEntry("IIS://" + serverName + "/W3SVC/1/Root");
DirectoryEntry primaryVirtualDirectory = directoryEntry.Children.Find(primaryVirtualDirectoryName, directoryEntry.SchemaClassName);
DirectoryEntry virtualDirectory = directoryEntry.Children.Add(virtualDirectoryName, directoryEntry.SchemaClassName);
virtualDirectory.CommitChanges();
virtualDirectory.Properties["Path"].Value = primaryVirtualDirectory.Properties["Path"].Value;
virtualDirectory.Properties["AppFriendlyName"][0] = virtualDirectoryName;
if (primaryVirtualDirectory.Properties["UNCUserName"] != null && primaryVirtualDirectory.Properties["UNCUserName"].Value != null && primaryVirtualDirectory.Properties["UNCUserName"].Value.ToString().Length > 0)
{
// IIS6 of IIS7
virtualDirectory.Properties["AuthNTLM"][0] = true;
virtualDirectory.Properties["UNCUserName"].Value = primaryVirtualDirectory.Properties["UNCUserName"].Value;
virtualDirectory.Properties["UNCPassword"].Value = primaryVirtualDirectory.Properties["UNCPassword"].Value;
}
else
{
// Older versions
virtualDirectory.Properties["AuthFlags"][0] = 5; // MD_AUTH_ANONYMOUS | MD_AUTH_NT
virtualDirectory.Properties["AnonymousUserName"].Value = primaryVirtualDirectory.Properties["AnonymousUserName"].Value;
virtualDirectory.Properties["AnonymousUserPass"].Value = primaryVirtualDirectory.Properties["AnonymousUserPass"].Value;
}
virtualDirectory.Properties["AccessRead"][0] = true;
virtualDirectory.Properties["AccessExecute"][0] = true;
virtualDirectory.Properties["AccessWrite"][0] = false;
virtualDirectory.Properties["AccessScript"][0] = true;
virtualDirectory.Properties["EnableDefaultDoc"][0] = true;
virtualDirectory.Properties["EnableDirBrowsing"][0] = false;
if (primaryVirtualDirectory.Properties["AppPoolId"] != null && primaryVirtualDirectory.Properties["AppPoolId"].Value != null && primaryVirtualDirectory.Properties["AppPoolId"].Value.ToString().Length > 0)
virtualDirectory.Properties["AppPoolId"].Value = primaryVirtualDirectory.Properties["AppPoolId"].Value;
virtualDirectory.Properties["ScriptMaps"].Value = primaryVirtualDirectory.Properties["ScriptMaps"].Value;
// I Tried adding these 3 lines but I keeo getting the same exception
// virtualDirectory.CommitChanges();
// virtualDirectory.Invoke("SetInfo");
// virtualDirectory.CommitChanges();
virtualDirectory.Invoke("AppCreate", true);
// I tried this instead but I still get the same exception
// virtualDirectory.Invoke("AppCreate2", 0);
virtualDirectory.CommitChanges();
return true;
}
catch (Exception exception)
{
return false;
}
}
I tried some variations (see comments in the code) using AppCreate2 instead of AppCreate or calling a CommitChanges and/or invoking SetInfo before the AppCreate, but all lead to the same exception.
The user credentials I'm using has adminstrator rights on the remote server. In fact if I copy the program to the remote server and run it there with the same credentials (I logged in with the same user on the remote server), using 'localhost' as servername and the user variable = null, it works without throwing the exception, so it must have something to do with the remote execution.
The remote server is a Windows Server 2003 R2 SP2 (32bit), the machine running this program is a Windows 7 Professional (64 bit).
Does anyone have any ideas ?

Related

LDAPS DirectorySearcher.FindOne throws exception

I am trying to validate a user using a secured LDAP query. My code throws an exception while calling
SearchResult result = search.FindOne;
Complete code:
public bool IsValidUser(object username)
{
isValidUser = false;
try
{
DirectoryEntry AD = new DirectoryEntry("LDAP://office:636/", "myaccount", "mypassword");
AD.AuthenticationType = AuthenticationTypes.SecureSocketsLayer;
DirectorySearcher search = new DirectorySearcher(AD);
search.SearchRoot = AD;
search.SearchScope = SearchScope.Subtree;
if (username == DBNull.Value == false & username != "")
{
search.Filter = "(&(objectClass=user) (sAMAccountName=" + username + "))";
SearchResult result = search.FindOne();
if ((result == null))
isValidUser = false;
else
isValidUser = true;
}
else
isValidUser = false;
}
catch (Exception ex)
{
// log(ex);
}
return isValidUser;
}
If I do not provide port number 636, it will work fine but I do not think then the LDAP is done under secured network.
Maybe it can help someone (or future me) - the domain controller can get corrupted sometimes, if it does it makes it impossible to use secure port 636, try to change to non secure port 389 to see if that's the case.
See also: "The server is not operational" domain controller configuration error when you configure a server by using Server Manager

a list of all users: Ldap referral error (LDAPReferralException)

I am using active directory and want a list of all users, basically in dotnet core. But I am receiving an exception:
Search result reference received, and referral following is off
Below is my code.
LdapSearchResults lsc = lc.Search("DC = xyz, DC = local", LdapConnection.SCOPE_ONE , "(|(objectClass = person)(objectClass = user))", null, false);
Necromancing - just in case the links go dark.
To fix it in your application, set ReferralFollowing to true.
if you get the message
Search result reference received, and referral following is off
, add
Novell.Directory.Ldap.LdapSearchConstraints cons = lc.SearchConstraints;
cons.ReferralFollowing = true;
lc.Constraints = cons;
to your code.
Example:
public static void GetUsers()
{
System.Collections.Generic.List<ARSoft.Tools.Net.Dns.SrvRecord> lsLdap = GetLdap();
ARSoft.Tools.Net.Dns.SrvRecord ldap = lsLdap[0];
string[] attrs = new string[] { "cn", "distinguishedName", "sAMAccountName", "userPrincipalName", "displayName", "givenName", "sn", "mail", "mailNickname", "memberOf", "homeDirectory", "msExchUserCulture" };
// CN = Common Name
// OU = Organizational Unit
// DC = Domain Component
string searchBase = "DC=cor,DC=local";
string searchFilter = "(&(objectClass=user)(objectCategory=person))";
string ldapHost = MySamples.TestSettings.ldapHost;
int ldapPort = MySamples.TestSettings.ldapPort;//System.Convert.ToInt32(args[1]);
string loginDN = MySamples.TestSettings.loginDN; // args[2];
string password = MySamples.TestSettings.password; // args[3];
Novell.Directory.Ldap.LdapConnection lc = new Novell.Directory.Ldap.LdapConnection();
int ldapVersion = Novell.Directory.Ldap.LdapConnection.Ldap_V3;
try
{
// connect to the server
lc.Connect(ldap.Target.ToString(), ldap.Port);
// bind to the server
lc.Bind(ldapVersion, loginDN, password);
Novell.Directory.Ldap.LdapSearchConstraints cons = lc.SearchConstraints;
cons.ReferralFollowing = true;
lc.Constraints = cons;
// To enable referral following, use LDAPConstraints.setReferralFollowing passing TRUE to enable referrals, or FALSE(default) to disable referrals.
Novell.Directory.Ldap.LdapSearchResults lsc = lc.Search(searchBase,
Novell.Directory.Ldap.LdapConnection.SCOPE_SUB,
searchFilter,
attrs,
false,
(Novell.Directory.Ldap.LdapSearchConstraints)null);
while (lsc.HasMore())
{
Novell.Directory.Ldap.LdapEntry nextEntry = null;
try
{
nextEntry = lsc.Next();
}
catch (Novell.Directory.Ldap.LdapReferralException eR)
{
// https://stackoverflow.com/questions/46052873/ldap-referal-error
// The response you received means that the directory you are requesting does not contain the data you look for,
// but they are in another directory, and in the response there is the information about the "referral" directory
// on which you need to rebind to "redo" the search.This principle in LDAP are the referral.
// https://www.novell.com/documentation/developer/ldapcsharp/?page=/documentation/developer/ldapcsharp/cnet/data/bp31k5d.html
// To enable referral following, use LDAPConstraints.setReferralFollowing passing TRUE to enable referrals, or FALSE (default) to disable referrals.
// are you sure your bind user meaning
// auth.impl.ldap.userid=CN=DotCMSUser,OU=Service Accounts,DC=mycompany,DC=intranet
// auth.impl.ldap.password = mypassword123
// has permissions to the user that is logging in and its groups?
System.Diagnostics.Debug.WriteLine(eR.LdapErrorMessage);
}
catch (Novell.Directory.Ldap.LdapException e)
{
// WARNING: Here catches only LDAP-Exception, no other types...
System.Console.WriteLine("Error: " + e.LdapErrorMessage);
// Exception is thrown, go for next entry
continue;
}
var atCN = nextEntry.getAttribute("cn");
var atUN = nextEntry.getAttribute("sAMAccountName");
var atDN = nextEntry.getAttribute("distinguishedName");
var atDIN = nextEntry.getAttribute("displayName");
if (atCN != null)
System.Console.WriteLine(atCN.StringValue);
if (atUN != null)
System.Console.WriteLine(atUN.StringValue);
if (atDN != null)
System.Console.WriteLine(atDN.StringValue);
if (atDIN != null)
System.Console.WriteLine(atDIN.StringValue);
System.Console.WriteLine("\n" + nextEntry.DN);
Novell.Directory.Ldap.LdapAttributeSet attributeSet = nextEntry.getAttributeSet();
System.Collections.IEnumerator ienum = attributeSet.GetEnumerator();
while (ienum.MoveNext())
{
Novell.Directory.Ldap.LdapAttribute attribute = (Novell.Directory.Ldap.LdapAttribute)ienum.Current;
string attributeName = attribute.Name;
string attributeVal = attribute.StringValue;
System.Console.WriteLine(attributeName + "value:" + attributeVal);
}
}
}
catch (System.Exception ex)
{
System.Console.WriteLine(ex.Message);
}
finally
{
// disconnect with the server
lc.Disconnect();
}
}
You have to activate the behaviour which will follow the referral returned by the directory.
The response you received means that the directory you are requesting does not contain the data you look for, but they are in another directory, and in the response there is the information about the "referral" directory on which you need to rebind to "redo" the search. This principle in LDAP are the referral.
I don't know how to do it in C#, but maybe have a look at :
https://www.novell.com/documentation/developer/ldapcsharp/?page=/documentation/developer/ldapcsharp/cnet/data/bp31k5d.html

Windows authentication with SharePoint Web Services via SOAP

I am trying to authenticate my SharePoint service t retrieve SPList Items :
private Cookie AuthenticateFBASite(string AuthenticationSiteURL, string UserName, string Password, NetworkCredential nc2)
{
Cookie CurrentSiteCookie = null;
using (Authentication.Authentication authSvc = new Authentication.Authentication())
{
authSvc.Url = AuthenticationSiteURL + "/_vti_bin/authentication.asmx";
authSvc.CookieContainer = new System.Net.CookieContainer(); //create a new cookie container
//set the FBA login information
authSvc.AllowAutoRedirect = true;
authSvc.PreAuthenticate = true;
authSvc.Credentials = nc2;
Authentication.LoginResult result = authSvc.Login(UserName, Password);
if (result.ErrorCode == Authentication.LoginErrorCode.NoError)
{
try
{
CookieCollection cookies = authSvc.CookieContainer.GetCookies(new Uri(AuthenticationSiteURL));
CurrentSiteCookie = cookies[result.CookieName];
return CurrentSiteCookie;
}
catch (System.Exception ex)
{
//Console.WriteLine("Exception occured while calling lists.asmx" + ex.Message);
return CurrentSiteCookie;
}
}
else if (result.ErrorCode == Authentication.LoginErrorCode.PasswordNotMatch)
{
return CurrentSiteCookie;
}
else
return CurrentSiteCookie;
}
}
and it was working fine till today i try to use it again but it return me an eror cookies[result.CookieName] is null , and this only happens on my machine not other machine .
#Eslan May i knw fom where your are calling this code ? from webpart or app or console application ? I suspect its authentication mode issue.

Reboot computer through WCF with WMI hosted on IIS c#

I have a WCF Service which is running on IIS. ApplicationPool uses the LocalSystem Identity.
The WCF Service has an method for rebooting the system with WMI using the following code:
ManagementBaseObject mboShutdown = null;
ManagementClass mcWin32 = null;
try
{
mcWin32 = new ManagementClass("Win32_OperatingSystem");
mcWin32.Get();
// You can't shutdown without security privileges
mcWin32.Scope.Options.EnablePrivileges = true;
ManagementBaseObject mboShutdownParams = mcWin32.GetMethodParameters("Win32Shutdown");
// Flag 6 means we want to trigger a force reboot
mboShutdownParams["Flags"] = "6";
mboShutdownParams["Reserved"] = "0";
foreach (ManagementObject manObj in mcWin32.GetInstances())
{
mboShutdown = manObj.InvokeMethod("Win32Shutdown", mboShutdownParams, null);
var result = Convert.ToInt32(mboShutdown["returnValue"]);
if (result != 0) throw new Win32Exception(result, "Could not restart local machine!");
}
}
catch (Exception ex)
{
SkippyLogger.WriteError(ex, "Error in IISAdminService.Restart");
throw ex;
}
finally
{
if (mcWin32 != null)
mcWin32.Dispose();
}
The method throw an exception with "Privilege not held".
Few things to try...
this
Can you run the same method, as LocalSystem outside of IIS - i.e host it as a windows service installed of IIS?
We have a similar system (hosted as a windows service) and it performs the actual reboot using this class.

Find idle time from remote pc using c#

I need to find out the idle time of remote pc from server pc using c# application. I have a list of IP addresses and host names connected in Local Area Network. I want to find out idle time more then 30 min for each computer connected in LAN. I done it for local pc, but it not works for remote pc. here is my code for local pc.
[DllImport("user32.dll")]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
private int GetIdleTime()
{
LASTINPUTINFO lastone = new LASTINPUTINFO();
lastone.cbSize = (uint)Marshal.SizeOf(lastone);
lastone.dwTime = 0;
int idleTime = 0;
int tickCount = Environment.TickCount;
if (GetLastInputInfo(ref lastone))
{
idleTime = tickCount - (int)lastone.dwTime;
return idleTime;
}
else
return 0;
}
Acording to MSDN, this is not possible entirely for the local machine let alone a remote one.
This function is useful for input idle detection. However,
GetLastInputInfo does not provide system-wide user input information
across all running sessions. Rather, GetLastInputInfo provides
session-specific user input information for only the session that
invoked the function.
You could however try one of the following:
Have a process on each PC which you can query.
Have a process on each
PC reporting to your central process.
Monitor remote PC processes to
determine if the screen saver is active.
If you do not have terminal services deactivated, and the clients are xp or higher, you can also use
ITerminalServicesSession.LastInputTime
For this you either use the Cassia libraries or p/invoke
WTSQuerySessionInformation
I use this remote WMI query:
object idleResult = Functions.remoteWMIQuery(machinename, "", "", "Select CreationDate From Win32_Process WHERE Name = \"logonUI.exe\"", "CreationDate", ref wmiOK);
Logonui.exe is the lockscreen. In business environments most systems lock when a user is idle.
You can translate the result like this in DateTime format
DateTime idleTime = Functions.ParseCIM_DATETIME((string)idleResult);
Where ParseCIM_DATETIME is this fucntion:
public static DateTime ParseCIM_DATETIME(string date)
{
//datetime object to store the return value
DateTime parsed = DateTime.MinValue;
//check date integrity
if (date != null && date.IndexOf('.') != -1)
{
//obtain the date with miliseconds
string newDate = date.Substring(0, date.IndexOf('.') + 4);
//check the lenght
if (newDate.Length == 18)
{
//extract each date component
int y = Convert.ToInt32(newDate.Substring(0, 4));
int m = Convert.ToInt32(newDate.Substring(4, 2));
int d = Convert.ToInt32(newDate.Substring(6, 2));
int h = Convert.ToInt32(newDate.Substring(8, 2));
int mm = Convert.ToInt32(newDate.Substring(10, 2));
int s = Convert.ToInt32(newDate.Substring(12, 2));
int ms = Convert.ToInt32(newDate.Substring(15, 3));
//compose the new datetime object
parsed = new DateTime(y, m, d, h, mm, s, ms);
}
}
//return datetime
return parsed;
}
The remote WMI Query function is as follows:
public static object remoteWMIQuery(string machine, string username, string password, string WMIQuery, string property, ref bool jobOK)
{
jobOK = true;
if (username == "")
{
username = null;
password = null;
}
// Configure the connection settings.
ConnectionOptions options = new ConnectionOptions();
options.Username = username; //could be in domain\user format
options.Password = password;
ManagementPath path = new ManagementPath(String.Format("\\\\{0}\\root\\cimv2", machine));
ManagementScope scope = new ManagementScope(path, options);
// Try and connect to the remote (or local) machine.
try
{
scope.Connect();
}
catch (ManagementException ex)
{
// Failed to authenticate properly.
jobOK = false;
return "Failed to authenticate: " + ex.Message;
//p_extendederror = (int)ex.ErrorCode;
//return Status.AuthenticateFailure;
}
catch (System.Runtime.InteropServices.COMException)
{
// Unable to connect to the RPC service on the remote machine.
jobOK = false;
return "Unable to connect to RPC service";
//p_extendederror = ex.ErrorCode;
//return Status.RPCServicesUnavailable;
}
catch (System.UnauthorizedAccessException)
{
// User not authorized.
jobOK = false;
return "Error: Unauthorized access";
//p_extendederror = 0;
//return Status.UnauthorizedAccess;
}
try
{
ObjectQuery oq = new ObjectQuery(WMIQuery);
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, oq);
foreach (ManagementObject queryObj in searcher.Get())
{
if (property != null)
{
return queryObj[property];
}
else return queryObj;
}
}
catch (Exception e)
{
jobOK = false;
return "Error: " + e.Message;
}
return "";
}
If you have the screensaver enabled I would suggest you check the CreateDate on the screensaver process and do a difference from the remote the createdate time and you get the idle time + the screensaver timeout
you might want to use WMI for this kind of thing
its a hack but it works

Categories

Resources