Have a utility I wrote that checks (among other things) the last time a set of servers was rebooted. This works great as long as the servers are all within my domain and the user launching the app have rights on the servers. Added a section where the user can specify alternative credentials, in our case specifically to deal with another domain. The credentials I am feeding into have domain admin rights on the destination domain, yet my code is getting an Access Denied (Unauthorized Access) error.
thanks!
private void btnLastReboot_Click(object sender, EventArgs e)
{
ConnectionOptions conOpts = new ConnectionOptions();
if (selectedList.Count > 0)
{
Cursor currentCursor = Cursor.Current;
Cursor.Current = Cursors.WaitCursor;
stripProgress.Visible = true;
stripProgress.Minimum = 0;
stripProgress.Maximum = selectedList.Count();
stripProgress.Step = 1;
stripProgress.Value = 0;
rtfOut.SelectionTabs = new int[] { 100, 200 };
rtfOut.Text = "";
var sq = new SelectQuery("Win32_OperatingSystem");
if (prefs.useCurrentUser == true)
{
// Setting all fields to NULL causes current user info to be used
conOpts.Username = null;
conOpts.Password = null;
conOpts.Authority = null;
}
else
{
conOpts.Username = prefs.userName;
conOpts.Password = prefs.password.ToString();
conOpts.Authority = "ntlmdomain:" + prefs.domain;
}
foreach (ServerList anEntry in selectedList)
{
stripProgress.Value++;
try
{
var mgmtScope = new ManagementScope("\\\\" + anEntry.ServerName + "\\root\\cimv2", conOpts);
mgmtScope.Connect();
var mgmtSearcher = new ManagementObjectSearcher(mgmtScope, sq);
foreach (var item in mgmtSearcher.Get())
{
var lastBoot = item.GetPropertyValue("LastBootUpTime").ToString();
DateTime lboot = ManagementDateTimeConverter.ToDateTime(lastBoot);
rtfOut.Text += anEntry.ServerName + "\t";
if(anEntry.ServerName.Length <= 9)
{
rtfOut.Text += "\t";
}
rtfOut.Text += lboot.ToLongDateString() + " (" + lboot.ToLongTimeString() + ")\r\n";
}
}
catch (Exception ex)
{
if (ex is UnauthorizedAccessException)
{
rtfOut.Text += anEntry.ServerName + "\t <Access Denied>\r\n";
}
else
{
rtfOut.Text += anEntry.ServerName + "\t <not responding>\r\n";
}
}
}
stripProgress.Visible = false;
Cursor.Current = currentCursor;
}
}
Had to sleep on it, but the answer finally hit me in the shower...
I store the password the user provides in a SecureString variable, but the ConnectionOptions' password field expects the value as a clear string. I was able to test this by temporarily hard coding a password in, which then worked. The final solution was to convert the SecureString to a clear string and then assign it to the ConnectionOption.
If anyone is curious, I used this bit to convert the password back:
string password = new System.Net.NetworkCredential(string.Empty, securePassword).Password;
I tried to bind x509 certificate and send data via client's webservice.
I created a window form application and use Microsoft.web.Service3, but when I run this win app on my local it gives me an error like:
Authentication Failure: SOAP body must be signed for signature-based
authentication. No credentials were provided. Contact IT
SOASvsSupport.
Can anyone help here?
private void btnSubmit_Click(object sender, EventArgs e)
{
string certificateFile = #"C:\XYZ\MyTest.cer";
System.Security.Cryptography.X509Certificates.X509Certificate x509Certificate = new System.Security.Cryptography.X509Certificates.X509Certificate(certificateFile);
//X509Certificate x509Certificate = X509Certificate.CreateFromCertFile(certificateFile);
MyTest.DataService rdf = new MyTest.DataService();
RvsDataFeed[] rvs = rdf.GetRvsDataFeed();
txtXml.Text = "";
if (rvs != null)
{
foreach (RvsDataFeed rvsdata in rvs)
{
try
{
TrackingRequest wbttreq = new TrackingRequest();
ClientType cit = new ClientType();
cit.requestorAppName = "MMM";
cit.requestorUserName = rvsdata.ID;
wbttreq.ClientInfo = cit;
ClientWSDL.DataUtility xyzWSDL = new ClinetWSDL.DataUtility();
xyzWSDL.Url = "http://xyz.xy";
xyzWSDL.ClientCertificates.Add(x509Certificate);
txtXml.Text = txtXml.Text + Environment.NewLine + SerializeToString(td);
TrackingResponse res = new TrackingResponse();
xyzWSDL.WriteBack(wbttreq);
rdf.LogRvsDataFeedSent(rvsdata.DataFeedID);
}
catch (Exception ex)
{
txtXml.Text = txtXml.Text + Environment.NewLine + ex.Message;
}
}
}
}
private void btnSubmit_Click(object sender, EventArgs e)
{
string certificateFile = #"C:\XYZ\MyTest.cer";
System.Security.Cryptography.X509Certificates.X509Certificate x509Certificate = new System.Security.Cryptography.X509Certificates.X509Certificate(certificateFile);
//X509Certificate x509Certificate = X509Certificate.CreateFromCertFile(certificateFile);
MyTest.DataService rdf = new MyTest.DataService();
RvsDataFeed[] rvs = rdf.GetRvsDataFeed();
txtXml.Text = "";
if (rvs != null)
{
foreach (RvsDataFeed rvsdata in rvs)
{
try
{
TrackingRequest wbttreq = new TrackingRequest();
ClientType cit = new ClientType();
cit.requestorAppName = "MMM";
cit.requestorUserName = rvsdata.ID;
wbttreq.ClientInfo = cit;
ClientWSDL.DataUtility xyzWSDL = new ClinetWSDL.DataUtility();
xyzWSDL.Url = "http://xyz.xy";
xyzWSDL.ClientCertificates.Add(x509Certificate);
txtXml.Text = txtXml.Text + Environment.NewLine + SerializeToString(td);
TrackingResponse res = new TrackingResponse();
xyzWSDL.WriteBack(wbttreq);
rdf.LogRvsDataFeedSent(rvsdata.DataFeedID);
}
catch (Exception ex)
{
txtXml.Text = txtXml.Text + Environment.NewLine + ex.Message;
}
}
}
}
Hi I would like to avoid printing certain rows (valid accounts) in my foreach loop (in GetSAM)as opposed to printing everything.
When I try to do so by commenting away the line (in valSAM) that prints the valid accounts, the will be a blank in the area where a valid account once was. I understand that this is because the foreach loops through all the variables in the database.
How am I able to remove the gaps between the output?
GetSAM:
//Get SAMAccount
private static string GetSAM(string ldapAddress, string serviceAccountUserName, string serviceAccountPassword)
{
string ldapPath = "LDAP://" + ldapAddress;
string ldapFilter = "(&(objectclass=user)(objectcategory=person))";
DirectoryEntry directoryEntry = new DirectoryEntry(ldapPath, serviceAccountUserName, serviceAccountPassword);
string readOutput;
List<string> list = new List<string>();
List<int> invalid = new List<int>();
using (DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry))
{
string samAccountName;
directorySearcher.Filter = ldapFilter;
directorySearcher.SearchScope = SearchScope.Subtree;
directorySearcher.PageSize = 1000;
using (SearchResultCollection searchResultCollection = directorySearcher.FindAll())
{
**foreach (SearchResult result in searchResultCollection)
{
samAccountName = result.Properties["sAMAccountName"][0].ToString();
if (valSAM(samAccountName, ldapAddress, serviceAccountUserName, serviceAccountPassword)!= true)
{
invalid.Add('1');
}
list.Add(samAccountName);
} //end of foreach**
// Count all accounts
int totalAccounts = list.Count;
// Count all invalid accounts
int invalidAccounts = invalid.Count;
Console.WriteLine("Found " + invalidAccounts + " invalid accounts out of " + totalAccounts + " user accounts.\nQuery in " + ldapAddress + " has finished.\n");
Console.WriteLine("Press [enter] to continue.\n");
readOutput = Console.ReadLine();
}//SearchResultCollection will be disposed here
}
return readOutput;
}
valSAM:
//Validate SAMAccount
private static bool valSAM(string samAccountName, string ldapAddress, string serviceAccountUserName, string serviceAccountPassword)
{
string ldapPath = "LDAP://" + ldapAddress;
DirectoryEntry directoryEntry = new DirectoryEntry(ldapPath, serviceAccountUserName, serviceAccountPassword);
StringBuilder builder = new StringBuilder();
bool accountValidation = false;
//create instance fo the directory searcher
DirectorySearcher desearch = new DirectorySearcher(directoryEntry);
//set the search filter
desearch.Filter = "(&(sAMAccountName=" + samAccountName + ")(objectcategory=user))";
//find the first instance
SearchResult results = desearch.FindOne();
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, ldapAddress))
{
//if users are present in database
if (results != null)
{
//Check if account is activated
bool isAccountActived = IsActive(results.GetDirectoryEntry());
//Check if account is expired or locked
bool isAccountLocked = IsAccountLockOrExpired(results.GetDirectoryEntry());
accountValidation = ((isAccountActived != true) || (isAccountLocked));
//account is invalid
if (accountValidation)
{
builder.Append("User account " + samAccountName + " is invalid. ");
if ((isAccountActived != true) && (isAccountLocked))
{
builder.Append("Account is inactive and locked or expired.").Append('\n'); ;
} else if (isAccountActived != true)
{
builder.Append("Account is inactive.").Append('\n'); ;
}
else if (isAccountLocked)
{
builder.Append("Account is locked or has expired.").Append('\n'); ;
}
else
{
builder.Append("Unknown reason for status. Contact admin for help.").Append('\n'); ;
}
accountValidation = false;
}
//account is valid
if ((isAccountActived) && (isAccountLocked != true))
{
**//builder.Append("User account " + samAccountName + " is valid.").Append('\n');
accountValidation = true;
}
}
else Console.WriteLine("Nothing found.");
Console.WriteLine(builder);
}//end of using
return accountValidation;
}
You probably want to only write if builder has something otherwise it will print an empty line. Namely, change
Console.WriteLine(builder);
to
if (builder.Length > 0)
{
Console.WriteLine(builder);
}
or just
Console.Write(builder);
if you're going to handle all of the new lines in the builder itself. If you're going to do that, use StringBuilder.AppendLine() instead of hardcoding the '\n' like that.
StringBuilder.AppendLine https://msdn.microsoft.com/en-us/library/system.text.stringbuilder.appendline(v=vs.110).aspx
I'm using the following code:
private string GetTitle(string userName)
{
string title = string.Empty;
try
{
DirectoryEntry myLdapConnection = createDirectoryEntry();
DirectorySearcher search = new DirectorySearcher(myLdapConnection);
search.ReferralChasing = ReferralChasingOption.All;
search.Filter = "(cn=" + userName + ")";
search.PropertiesToLoad.Add("title");
SearchResult result = search.FindOne();
if (result != null)
{
// create new object from search result
DirectoryEntry entryToUpdate = result.GetDirectoryEntry();
title = entryToUpdate.Properties["title"][0].ToString();
}
else Console.WriteLine("User not found!");
}
catch (Exception e)
{
Console.WriteLine("Exception caught:\n\n" + e.ToString());
}
return title;
}
and get this error:
A referral was returned from the server.
from line: SearchResult result = search.FindOne();
How can I solve this?
I need to create a new website in iis 6.0 (Windows server 2003 r2 sp2) and create a new virtual directory with .net framework 4.0 and assign it to created website.
here is my code :
public static int CreateWebSite(string webSiteName, string PhysicalPath, string PortNumber, string HostHeader, string DefaultDoc, string appPoolName, out string errorMessage)
{
errorMessage = string.Empty;
try
{
DirectoryEntry root = new DirectoryEntry("IIS://localhost/W3SVC");
// Find unused ID value for new web site
int siteID = 1;
foreach (DirectoryEntry e in root.Children)
{
if (e.SchemaClassName == "IIsWebServer")
{
int ID = Convert.ToInt32(e.Name);
if (ID >= siteID)
{
siteID = ID + 1;
}
}
}
DirectoryEntry site = (DirectoryEntry)root.Invoke("Create", "IIsWebServer", siteID);
site.Invoke("Put", "ServerComment", webSiteName);
site.Invoke("Put", "KeyType", "IIsWebServer");
site.Invoke("Put", "ServerBindings", ":" + PortNumber + ":" + HostHeader);
site.Invoke("Put", "ServerState", 2);
site.Invoke("Put", "FrontPageWeb", 1);
site.Invoke("Put", "DefaultDoc", DefaultDoc);
site.Invoke("Put", "ServerAutoStart", 1);
site.Invoke("Put", "ServerSize", 1);
site.Invoke("SetInfo");
DirectoryEntry siteVDir = site.Children.Add("Root", "IISWebVirtualDir");
if (appPoolName != "")
{
object[] param = { 0, appPoolName, true };
siteVDir.Invoke("AppCreate3", param);
}
siteVDir.Properties["AppIsolated"][0] = 2;
siteVDir.Properties["Path"][0] = PhysicalPath;
siteVDir.Properties["AccessFlags"][0] = 513;
siteVDir.Properties["AspEnableParentPaths"][0] = true;
siteVDir.Properties["AppFriendlyName"][0] = webSiteName;
siteVDir.Properties["FrontPageWeb"][0] = 1;
siteVDir.Properties["AppRoot"][0] = "LM/W3SVC/" + siteID + "/Root";
siteVDir.Properties["AppFriendlyName"][0] = "Root";
siteVDir.Properties["AspSessionTimeout"][0] = "60";
siteVDir.Properties["AuthFlags"].Value = 4;//integrity windows Authentication checked
siteVDir.Properties["AuthAnonymous"][0] = true;//Anonymouse uncheck
siteVDir.Properties["HttpErrors"].Add("401,1,FILE," + PhysicalPath + "/Lib/CustomError/SSOLoginError.htm");
siteVDir.Properties["HttpErrors"].Add("401,2,FILE," + PhysicalPath + "/Lib/CustomError/SSOLoginError.htm");
siteVDir.Properties["HttpErrors"].Add("401,3,FILE," + PhysicalPath + "/Lib/CustomError/SSOLoginError.htm");
siteVDir.Properties["HttpErrors"].Add("401,4,FILE," + PhysicalPath + "/Lib/CustomError/SSOLoginError.htm");
siteVDir.Properties["HttpErrors"].Add("401,5,FILE," + PhysicalPath + "/Lib/CustomError/SSOLoginError.htm");
siteVDir.Properties["HttpErrors"].Add("401,7,FILE," + PhysicalPath + "/Lib/CustomError/SSOLoginError.htm");
//For SSO, Set special settings for WinLogin.aspx page -- This has beed added after version 8.1.1001
DirectoryEntry deLoginDir;
deLoginDir = siteVDir.Children.Add("WinLogin.aspx", siteVDir.SchemaClassName);
deLoginDir.Properties["AuthAnonymous"][0] = false;//Anonymouse uncheck
deLoginDir.Properties["AuthFlags"].Value = 4;//integrity windows Authentication checked
deLoginDir.CommitChanges();
////////////////////////////////////////////
siteVDir.CommitChanges();
siteVDir.Invoke("AppDelete");
siteVDir.Invoke("AppCreate", true);
siteVDir.Invoke("AppEnable");
site.CommitChanges();
#region AssignApplicationPool
DirectoryEntry vDir = new DirectoryEntry("IIS://localhost/W3SVC/" + siteID.ToString() + "/Root");
string className = vDir.SchemaClassName.ToString();
if (className.EndsWith("VirtualDir"))
{
object[] param = { 0, appPoolName, true };
vDir.Invoke("AppCreate3", param);
vDir.Properties["AppIsolated"][0] = "2";
vDir.CommitChanges();
}
else
{
return -1;
}
if (Environment.OSVersion.Version.Major < 6)
{
try
{
const string aspNetV1 = "1.0.3705";
const string aspNetV11 = "1.1.4322";
const string aspNetV2 = "2.0.50727";
const string aspNetV4 = "4.0.30319";
const string targetAspNetVersion = aspNetV4;
//loop through the script maps
for (var i = 0; i < siteVDir.Properties["ScriptMaps"].Count; i++)
{
//replace the versions if they exists
siteVDir.Properties["ScriptMaps"][i] =
siteVDir.Properties["ScriptMaps"][i].ToString().Replace(aspNetV1, targetAspNetVersion);
siteVDir.Properties["ScriptMaps"][i] =
siteVDir.Properties["ScriptMaps"][i].ToString().Replace(aspNetV11, targetAspNetVersion);
siteVDir.Properties["ScriptMaps"][i] =
siteVDir.Properties["ScriptMaps"][i].ToString().Replace(aspNetV2, targetAspNetVersion);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
errorMessage = ex.Message + Environment.NewLine + ex.StackTrace;
}
}
else
{
string appPoolPath = #"IIS://localhost/W3SVC/AppPools/" + appPoolName;
try
{
var appPoolEntry = new DirectoryEntry(appPoolPath);
appPoolEntry.Properties["managedRuntimeVersion"].Value = "v4.0";
appPoolEntry.Invoke("SetInfo", null);
appPoolEntry.CommitChanges();
appPoolEntry.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
errorMessage = ex.Message + Environment.NewLine + ex.StackTrace;
}
siteVDir.CommitChanges();
siteVDir.Close();
}
#endregion
return siteID;
}
catch
{
return -1;
}
}
This code should work fine in IIS 6.0 (Windows 2003) and IIS 7.5+ (Windows 7 and Windows 2008).
in windows 7 and 2008 every thing looks fine! but in windows 2003 I have some problems:
Asp.net version of website does not change to v4
Application Pool does not seems correct and its node in inetmgr only have one node with name Root not the name of website
in the properties window of website -> home directory tab, application name is empty!
what is wrong with my code?
thanks in advance
DirectoryEntry sited = new DirectoryEntry(string.Format("IIS://localhost/w3svc/{0}/Root", websiteID.ToString()));
sited.Properties["AccessRead"].Add(true);
PropertyValueCollection testScriptMap = sited.Properties["ScriptMaps"];
object[] allValues = (object[])testScriptMap.Value;
object[] newValues = new object[allValues.Length];
string oldVersion = "v1.1.4322";
string newVersion = "v2.0.50727";
//... etc to 4.0.30319 .....
for (int i = 0; i < allValues.Length; i++)
{
if (allValues[i] is string)
{
string temp = allValues[i] as string;
if (temp.Contains(oldVersion))
{
newValues[i] = temp.Replace(oldVersion, newVersion);
}
else
{
newValues[i] = allValues[i];
}
}
else
{
newValues[i] = allValues[i];
}
}
testScriptMap.Value = newValues;
sited.CommitChanges();