Can I access a secured network folder with Directory.GetFiles()? - c#

Is it possible to access a network folder with Directory.GetFiles() that I would normally have to enter my credentials for when opening through explorer?

If the running user is the logon user (with profil loading) and have already access to the remote path (by entering credentials), your application, which may run with user's profile loaded, should access to the UNC path without any login.
Otherwise, you can use this piece of code to logon you can find in GitHub :
using (UNCAccessWithCredentials unc = new UNCAccessWithCredentials())
{
if (unc.NetUseWithCredentials("uncpath", user, domain, password))
{
// Directory.GetFiles() here
}
}

It is possible. I usually spawn a process to pass the credentials to the system. Please see the code posted below which does exactly this. Once the process has completed you will be able to use the network share.
public void MapPath() {
string strServer = “ServerName”;
string strShare = “ServerShare”;
string strUsername = “ServerUsername”;
string strPassword = “ServerPassword”;
Process pNetDelete = new Process();
pNetDelete.StartInfo.CreateNoWindow = true;
pNetDelete.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
pNetDelete.StartInfo.UseShellExecute = false;
pNetDelete.StartInfo.FileName = “net”;
pNetDelete.StartInfo.Arguments = string.Format(“use /DELETE {0}\
{1} /Y”, strServer, strShare);
pNetDelete.Start();
pNetDelete.WaitForExit();
Process pNetShare = new Process();
pNetShare.StartInfo.CreateNoWindow = true;
pNetShare.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
pNetShare.StartInfo.UseShellExecute = false;
pNetShare.StartInfo.RedirectStandardError = true;
pNetShare.StartInfo.RedirectStandardOutput = true;
pNetShare.StartInfo.FileName = “net”;
pNetShare.StartInfo.Arguments = string.Format(“use \\{0}\{1} /u:"{2}" "{3}"”,
strServer, strShare, strUsername, strPassword);
pNetShare.Start();
pNetShare.WaitForExit();
string strError = pNetShare.StandardError.ReadToEnd();
if (pNetShare.ExitCode != 0)
{
throw new Exception(strError);
}
}

Related

How to execute cmds using HTTP Post method in C#

We have a REST endpoint installed as a windows service on a server. This server will be used for test automation. The idea is make a POST request to the endpoint and that endpoint will kick off cypress tests based off the parameters specified in the POST url.
I have an existing powershell script that will do this. Ideally I'd like to call that script and fill in the needed params.
No matter what I do the request returns OK without actually running any of the commands. Is there a way to use a POST request to execute a cmds or a powershell script?? Code below(Note: I'm trying 2 different methods here neither work):
namespace CNet.TestRunner
{
public class AddTestRun : CNetApiEndpoint
{
[HttpPost("Cypress/{testName}/{serverName}")]
public CineNetResult TestRun(string testName, string serverName)
{
string test = testName + ".js";
string testPath = $#"..\EndToEndSpecs\cypress\integration\{test}";
var path = "%PROGRAMFILES%";
var resolvedPath = Environment.ExpandEnvironmentVariables(path);
string cmd = $#"{resolvedPath}\PowerShell\7\pwsh.exe "" '..\EndToEnd.ps1' '-TestPath {testPath}' '-HostToTest {serverName}' """;
Process P = Process.Start($#"{resolvedPath}\PowerShell\7\pwsh.exe", $#""" '..\EndToEnd.ps1' '-TestPath {testPath}' '-HostToTest {serverName}'""");
P.WaitForExit();
int result = P.ExitCode;
string resStr = result.ToString();
var model = new ResponseModel
{
Message = resStr,
DataPassed = $"{testName}|{serverName}"
};
var proc1 = new ProcessStartInfo();
string anyCommand = "yarn install";
proc1.UseShellExecute = true;
proc1.WorkingDirectory = #"C:\Windows\System32";
proc1.FileName = #"C:\Windows\System32\cmd.exe";
proc1.Verb = "runas";
proc1.Arguments = "/c " + anyCommand;
proc1.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(proc1);
return Ok(model);
}
}
}

Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))' firewall INetFwPolicy2

Access is denied.
private void MakeRule(string IP, int Protocole, NET_FW_RULE_DIRECTION_ ruleDirection, string ruleName)
{
Type tNetFwPolicy2 = Type.GetTypeFromProgID("HNetCfg.FwPolicy2");
INetFwPolicy2 fwPolicy2 = (INetFwPolicy2)Activator.CreateInstance(tNetFwPolicy2);
var currentProfiles = fwPolicy2.CurrentProfileTypes;
// Let's create a new rule
INetFwRule2 Rule = (INetFwRule2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule"));
Rule.Enabled = true;
NET_FW_RULE_DIRECTION_ direction = ruleDirection;
Rule.Direction = direction; //Inbound
Rule.Action = NET_FW_ACTION_.NET_FW_ACTION_BLOCK;
Rule.Profiles = currentProfiles;
Rule.Protocol = protNumber; // ANY/TCP/UDP
try
{
Rule.RemoteAddresses = str;
}
catch (Exception)
{
MessageBox.Show("Can't add Rules. Maybe a Format failure?");
}
//Rule.LocalPorts = "81"; //Port 81
//Name of rule
Rule.Name = ruleName;
// ...//
//Rule.Profiles = (int)NET_FW_PROFILE_TYPE_.NET_FW_PROFILE_TYPE_MAX;
// Now add the rule
INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
try
{
firewallPolicy.Rules.Add(Rule);
}
catch (Exception ex)
{
throw ex;
}
}
If you want to make your app run as administrator, you can create a manifest file to make it work.
First, please right click your project and add a new item called Application Manifest File.
Second, please find requestedExecutionLevel tag and change into the following tag:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
Third, you will get a UAC prompt when they start the program. Choose Restart under different credentials.
Finally, you can run the program with the amdin power.
Also, you can read the following link to use c# code to run the app as admin.
Run as administrator C#
Testabc user have the administrator right.
//Run EXTERNAL APP AS AN ADMIN
var pass = new SecureString();
pass.AppendChar('t');
pass.AppendChar('e');
pass.AppendChar('s');
pass.AppendChar('t');
var ps1File = #"C:\Users\testabc\Desktop\LT_Admin.ps1";
ProcessStartInfo processAdmin;
processAdmin = new ProcessStartInfo();
processAdmin.UseShellExecute = false;
processAdmin.CreateNoWindow = true;
processAdmin.WindowStyle=System.Diagnostics.ProcessWindowStyle.Hidden;
processAdmin.Password = pass;
processAdmin.UserName = "testabc";
processAdmin.Domain = "soft";
processAdmin.FileName = #"C:\windows\system32\windowspowershell\v1.0\powershell.exe";
processAdmin.Arguments = $"-NoProfile -ExecutionPolicy unrestricted -file \"{ps1File}\"";
processAdmin.RedirectStandardOutput = true;
Process.Start(processAdmin);
In ps1File I have this code
Start-Process -FilePath "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" -Verb RunAs
Working perfectly...

Validate user in intranet application

I need to use the windows credentials to allow my users to log in an intranet application. I am planning to create a table with usernames and roles and compare the username from Environment.UserName with my table. How safe is to relay on this? Is there a better way to achieve this task?
Thank you in advance.
You can do this using active directory authentication:
Bellow is sample code that you can try in your application.
string domainUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
string[] paramsLogin = domainUser.Split('\\');
string domain = paramsLogin[0].ToString();
string LdapPath = "";
string strDomainPath = DomainPath();
LdapPath = string.Format("LDAP://{0}/{1}", DomainName, strDomainPath);
string username = LoginUser.UserName;
string password = LoginUser.Password;
string domainAndUsername = domain + #"\" + username;
DirectoryEntry entry = new DirectoryEntry(LdapPath, domainAndUsername, password);
try
{
// Bind to the native AdsObject to force authentication.
Object obj = entry.NativeObject;
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + username + ")";
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
if (result != null)
{
IsLoginSucess = true;
//Do your stuff here
}
// Update the new path to the user in the directory
LdapPath = result.Path;
string _filterAttribute = (String)result.Properties["cn"][0];
}
catch (Exception ex)
{
IsLoginSucess = false;
}
If you are developing in a Windows application, take a look at this:
Authenticate user in WinForms (Nothing to do with ASP.Net)
System.Security.Principal.WindowsIdentity.GetCurrent() will give you the current Windows user
If you are developing a Web application, there is built in-support, you would need to have relevant entries in your web.config file
Using windows authentication in asp.net with c#
HttpContext.Current.User.Identity will get you the user identity

How to check if a user belongs to an AD group?

At first I thought the code below works because if I have the group as "IT" it functions correctly because my username is in the IT group in active directory. What I learned is it always returns true whether I have my username in the IT group or not and if i change it to any other group I am in it returns always returns false. Any help would be appreciated.
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
// tab control security for admin tab
bool admin = checkGroup("IT");
if ((admin == true) && (tabControl1.SelectedTab == tpHistory))
{
tabControl1.SelectedTab = tpHistory;
}
else if ((admin == false) && (tabControl1.SelectedTab == tpHistory))
{
tabControl1.SelectedTab = tpRequests;
MessageBox.Show("Unable to load tab. You have insufficient privileges.",
"Access Denied", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
}
// check active directory to see if user is in Marketing department group
private static bool checkGroup(string group)
{
WindowsIdentity identity = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(group);
}
Since you're on .NET 3.5 and up, you should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on System.DirectoryServices.AccountManagement
Basically, you can define a domain context and easily find users and/or groups in AD:
// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "DOMAINNAME");
// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "SomeUserName");
// find the group in question
GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, "YourGroupNameHere");
if(user != null)
{
// check if user is member of that group
if (user.IsMemberOf(group))
{
// do something.....
}
}
The new S.DS.AM makes it really easy to play around with users and groups in AD!
Slight deviation from #marc_s example, implemented in the static void Main() method in Program:
DomainCtx = new PrincipalContext( ContextType.Domain , Environment.UserDomainName );
if ( DomainCtx != null ) {
User = UserPrincipal.FindByIdentity( DomainCtx , Environment.UserName );
}
DomainCtx and User are both static properties declared under Program
Then in other forms i simply do something like this:
if ( Program.User.IsMemberOf(GroupPrincipal.FindByIdentity(Program.DomainCtx, "IT-All") )) {
//Enable certain Form Buttons and objects for IT Users
}
Check if current user in a group
public bool AuthenticateGroup(string groupfind)
{
var p = new Process();
StringBuilder stringbd = new StringBuilder();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = #"/c gpresult /V";
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = false;
p.StartInfo.UseShellExecute = false;
p.OutputDataReceived += (a, b) => stringbd.AppendLine(b.Data);
p.ErrorDataReceived += (a, b) => stringbd.AppendLine(b.Data);
p.Start();
p.BeginErrorReadLine();
p.BeginOutputReadLine();
p.WaitForExit();
var textfind = stringbd.ToString();
int findpoint = textfind.IndexOf("The user is a part of");
string findgroup = "";
if (findpoint > 0)
{
findgroup = textfind.Substring(findpoint, textfind.Length - findpoint);
}
return findgroup.Split('\n').ToList().Any(r=>r.Trim().ToLower()==groupfind.Trim().ToLower());
}
You cannot do it by this way.
You should query the active directory.
You can use a wrapper for AD. Check out http://www.codeproject.com/Articles/10301/Wrapper-API-for-using-Microsoft-Active-Directory-S
Why not:
bool isUserInGroup = HttpContext.User.IsInRole(".nameOfAdGroup");

mass .net update in iis6

We have about 200 web sites (on 3 separate servers, so 600 total) that we're going to have to update to run on .net 4 framework. They're currently set to run on .net 2. Does anyone know if there's a way to do this with a c# console program? Thanks!
Edit: I found a tool called IIS Metabase Explorer. Using that along with some code I had found a while ago for setting up a site in IIS 6, I came up with the following code. Hopefully it will be of help to others.
I would call it like
UpdateSiteToDotNet4("mytestsite", "mywebserver", #"D:\inetpub\wwwroot\", "DotNet4");
private void UpdateSiteToDotNet4(string siteName, string server, string serverPath, string newAppPoolId)
{
var service = new DirectoryEntry("IIS://" + server + "/W3SVC");
DirectoryEntries sites = service.Children;
bool found = false;
foreach (DirectoryEntry siteEntry in sites)
{
var siteId = siteEntry.Name;
DirectoryEntries siteSettings = siteEntry.Children; //Root
foreach (DirectoryEntry siteSetting in
from DirectoryEntry siteSetting in siteSettings
where siteSetting.SchemaClassName == "IIsWebVirtualDir"
let siteRoot = siteSetting.Properties["Path"][0].ToString()
where siteRoot.ToLower().Trim() == (serverPath + siteName).ToLower().Trim()
select siteSetting)
{
siteSetting.Properties["AppPoolId"].Value = newAppPoolId;
siteSetting.CommitChanges();
//Update to version v4.0.30319
var aspnet = string.Format(#"{0}\Microsoft.NET\Framework\v{1}\aspnet_regiis.exe", Environment.GetEnvironmentVariable("windir"), "4.0.30319");
var startInfo = new ProcessStartInfo(aspnet)
{
Arguments = string.Format("-sn \"{0}\"", "W3SVC/" + siteId + "/Root"),
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
CreateNoWindow = true
};
var process = new Process { StartInfo = startInfo };
process.Start();
process.WaitForExit();
process.Dispose();
found = true;
break;
}
if (found) break;
}
}

Categories