Get my application to be allowed access through firewall using c# - c#

i am trying to get my application to be allowed through firewall, as I have to do ftp in active and passive mode is not an option as servers are not configured for that. so i tried the below code which compiles fine, I exexcute it using:
MyApp.Classes.INetFwMgr mgr = new MyApp.Classes.INetFwMgr();
mgr.AuthorizeApplication(Application.ProductName, Application.StartupPath,
NET_FW_SCOPE_.NET_FW_SCOPE_ALL,
NET_FW_IP_VERSION_.NET_FW_IP_VERSION_ANY);
And the class which does the job:
private const string CLSID_FIREWALL_MANAGER =
"{304CE942-6E39-40D8-943A-B913C40C9CD4}";
private static NetFwTypeLib.INetFwMgr GetFirewallManager()
{
Type objectType = Type.GetTypeFromCLSID(
new Guid(CLSID_FIREWALL_MANAGER));
return Activator.CreateInstance(objectType)
as NetFwTypeLib.INetFwMgr;
}
private const string PROGID_AUTHORIZED_APPLICATION =
"HNetCfg.FwAuthorizedApplication";
public bool AuthorizeApplication(string title, string applicationPath,
NET_FW_SCOPE_ scope, NET_FW_IP_VERSION_ ipVersion)
{
// Create the type from prog id
Type type = Type.GetTypeFromProgID(PROGID_AUTHORIZED_APPLICATION);
INetFwAuthorizedApplication auth = Activator.CreateInstance(type)
as INetFwAuthorizedApplication;
auth.Name = title;
auth.ProcessImageFileName = applicationPath; //Getting Access Denied Exception Here
auth.Scope = scope;
auth.IpVersion = ipVersion;
auth.Enabled = true;
NetFwTypeLib.INetFwMgr manager = GetFirewallManager();
try
{
manager.LocalPolicy.CurrentProfile.AuthorizedApplications.Add(auth);
}
catch (Exception ex)
{
return false;
}
return true;
}
using above code, but i get Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) c# exception on line
auth.ProcessImageFileName = applicationPath;
any ideas what to do ?
Edit1: How would i run this as an admin using code?
Edit2: I also tried Putting <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> in manifest did not make a difference
P.S.This programs execution context can be Win 7, vista, xp

Firewall management is a system level security feature and has to be done outside of user mode application code. Configuration must be done by an administrator.
It is bad practice to write the code that you wrote and assume that your application will be run as administrator. Even if it is run by an administrator, you now have an application that "does FTP stuff" and "does firewall stuff". No application has ever been written like this.
You can write code that interacts with the system firewall, and that code must be run with elevated permissions. Typically such "helper applications" are never even created however as Windows (and every other OS) has all the necessary management tools shipped with the OS (i.e. wf.msc).

i have observed that if i change the order of ftp download statements to following windows dialog appears asking that do you want to allow this program access through firewall; if i click allow access the code works perfectly.
requestDownload = (FtpWebRequest)WebRequest.Create(uri);
requestDownload.UsePassive = false;
requestDownload.KeepAlive = false;
requestDownload.UseBinary = true;
requestDownload.Method = WebRequestMethods.Ftp.DownloadFile;
requestDownload.Credentials = new NetworkCredential(ftpInfoDownload[3], ftpInfoDownload[4]);
responseDownload = (FtpWebResponse)requestDownload.GetResponse();
Stream ftpStream = responseDownload.GetResponseStream();

Try opening the FTP ports in the firewall -- ports 20 and 21 -- and see if that solves your issue.

For running as a different user:
Run Code as a different user (C#)
As for getting through the firewall, have you talked to the person/group responsible for the firewall security? They may have some rules in place that you could use.

Related

How to change DCOM config identity programmatically

Is there any way to get the information about Launching identity of DCOM application programmatically. See the picture attached to understand what i mean.
I tried to use WMI
ManagementObjectSearcher s = new ManagementObjectSearcher(new ManagementScope(#"\\.\root\cimv2"), new ObjectQuery(
"select * from Win32_DCOMApplicationSetting where AppID='{048EB43E-2059-422F-95E0-557DA96038AF}'"))
ManagementObjectCollection dcomSett = s.Get();
var value = dcomSett.Cast<ManagementObject>().ToArray()
[0].Properties["RunAsUser"].Value;
but "RunAsUser" property was empty.
Also tried Interop.COMAdmin
COMAdmin.COMAdminCatalogClass catalog = (COMAdmin.COMAdminCatalogClass)new COMAdmin.COMAdminCatalog();
(COMAdmin.COMAdminCatalogCollection)catalog.GetCollection("Applications")
in this way i managed to get applications which are listed under the "COM+ Applications" node in the "Component Services" snap-in of MMC:
I'm new in COM, DCOM, COM+ stuff and sure that i missed something important.
After a while i found out why i used to get NULL in the first approach (ManagementObject).
You will receive:
NULL if identity is currently set to The launching user
"Interactive User" in case of "The interactive user"
some string with username in case of third option (see the first picture)
But still i need a way to change identity for items like Microsoft PowerPoint Slide under DCOM Config node in MMC.
In the DCOM config, if you are using a specific user for the identity and you want to update the password via code, you need to update it in the Local Security Authority (LSA). This is possible with Windows API calls. MS has some sample code for a utility called dcomperm that does it, and you can see how they implemented in C++. You could make the same calls in C#. See the SetRunAsPassword method here. They are using the method LsaOpenPolicy to get a handle to the policy and calling LsaStorePrivateData to update the password. Then they are adding "login as a batch job" access to the account (but that shouldn't be necessary if you are only changing the password).
This sample code on pinvoke.net looks like it is making the requisite calls, except for the optional part about granting the login as a batch job permission. Note the "key" in the LSA is in the format SCM:{GUID-of-DCOM-object} Example: SCM:{00000000-0000-0000-0000-000000000000}
Oh, and I should mention as an aside that if you wanted to change the RunAs user itself (i.e. the username), you'd need to also update that in the windows registry directly (AFAIK that's the only way to do it). DCOM entries are stored under HKLM\SOFTWARE\Classes\AppID. You can do that with WMI or just use the Registry classes in .NET.
This is very simple , you can get APPId from
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\{048EB43E-2059-422F-95E0-557DA96038AF}
using
(RegistryKey dcomPPTIdentity = Registry.LocalMachine.OpenSubKey("Software\\Classes\\AppID\\{048EB43E-2059-422F-95E0-557DA96038AF}"))
{
if (dcomPPTIdentity != null)
{
Registry.SetValue(dcomPPTIdentity.ToString(), "RunAs", "userName");
}
}
I am using COMAdmin DLL successfully. Try something like this:
COMAdminCatalog catalog = new COMAdminCatalog();
COMAdminCatalogCollection applications = catalog.GetCollection("Applications");
applications.Populate();
for (int i = 0; i < applications.Count; i++)
{
COMAdminCatalogObject application = COMAppCollectionInUse.Item[i];
if (application.Name == "Your COM+ application name")
{
application.Value["Identity"] = "nt authority\\localservice"; // for example
}
}
This works for me on my development server. Keep in mind, it is run against the server directly on the server
using COMAdmin;
using System;
namespace ComComponents
{
class Program
{
static void Main(string[] args)
{
COMAdminCatalog catalog = new COMAdminCatalog();
COMAdminCatalogCollection applications = catalog.GetCollection("Applications");
applications.Populate();
for (int i = 0; i < applications.Count; i++)
{
COMAdminCatalogObject application = applications.Item[i];
Console.WriteLine(application.Name);
Console.WriteLine(application.Value["Identity"]);
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}

"ClickOnce does not support the request execution level 'requireAdministrator.'"

So I was writing an application that requires access to the registry.
I had not touched any build settings, wanting to get the thing working before I added the other touches, such as a description or name.
Out of the blue, I get an error that will not go away. ClickOnce does not support the request execution level 'requireAdministrator'. Now, I hadn't touched ClickOnce in this application. All I had done was include a manifest file requesting these permissions.
My problem now is that this error will not go away, and I cannot compile my program. Any advice on what to do? (Side note: I am about to go to bed, so I will check this tomorrow afternoon).
Edit: This comment gives a good answer, too.
Click once appears to get enabled whenever you click "Publish", whether you want it to or not! If you are using "requireAdministrator" then it appears that you cannot use ClickOnce, and therefore cannot "Publish" your project.
Original:
Turns out that under the Security tab, "Enable ClickOnce security settings" was checked. Even though I didn't check it.
Anyway, unchecking that stopped ClickOnce giving me errors. That took a while to find...
I know this an old question but I came here two years later so:
You can disable the ClicKOnce from the Security tab on project properites to help the issue; see below:
If you ever use the publishing wizard, or 'Publish Now', the click-once checkbox gets automatically selected...
I know this is old but I stumbled across it looking for answers. In my case, I AM using the publish function and I need to keep using it. I also need access to admin capabilities. So for that reason, none of the above answers worked for me.
I ended up adding a method to the very start of my application that checks if it's being run as an administrator and if it isn't, relaunch itself as an admin. To do this, you need the following references added.
using System;
using System.Diagnostics;
using System.Reflection;
using System.Security.Principal;
Then you will need to put this somewhere that your main method has handy access to. I'm using WPF so I added it to MainWindow.xaml.cs but you can add it anywhere early on in your code. Just remember to add "static" to these methods should you need it.
private void AdminRelauncher()
{
if (!IsRunAsAdmin())
{
ProcessStartInfo proc = new ProcessStartInfo();
proc.UseShellExecute = true;
proc.WorkingDirectory = Environment.CurrentDirectory;
proc.FileName = Assembly.GetEntryAssembly().CodeBase;
proc.Verb = "runas";
try
{
Process.Start(proc);
Application.Current.Shutdown();
}
catch(Exception ex)
{
Console.WriteLine("This program must be run as an administrator! \n\n" + ex.ToString());
}
}
}
private bool IsRunAsAdmin()
{
try
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(id);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
catch (Exception)
{
return false;
}
}
Lastly, at the start of your program, add a reference to the method. In my case, I added it to MainWindow but adding it to Main works too.
public MainWindow()
{
InitializeComponent();
AdminRelauncher(); //This is the only important line here, add it to a place it gets run early on.
}
Hope this helps!
For .NET Core and .NET 5+
If you're stumbling upon this in the 20s, this is how you would change the above to work with .NET Core and .NET 5+
The only function that needs changing is the AdminRelauncher and it should look like this instead.
private static void AdminRelauncher()
{
if (!IsRunAsAdmin())
{
ProcessStartInfo proc = new ProcessStartInfo();
proc.UseShellExecute = true;
proc.WorkingDirectory = Environment.CurrentDirectory;
proc.FileName = Assembly.GetEntryAssembly().Location.Replace(".dll", ".exe");
proc.Verb = "runas";
try
{
Process.Start(proc);
Environment.Exit(0);
}
catch (Exception ex)
{
Console.WriteLine("This program must be run as an administrator! \n\n" + ex.ToString());
}
}
}
The only big changes is as someone pointed out Application isn't always available. So Environment.Exit(0) can replace it and the filename needs to replace .exe with .dll. This has been tested as of .NET 6
For those who use uncheck "Enable ClickOnce security settings" can't work, to try the method I find.
First, leave your app.manifest requestedExecutionLevel item as is:
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
And then you edit your Program.cs file like this:
using System;
using System.Diagnostics;
using System.Reflection;
using System.Security.Principal;
using System.Windows.Forms;
restruct main method like:
static void Main()
{
var wi = WindowsIdentity.GetCurrent();
var wp = new WindowsPrincipal(wi);
bool runAsAdmin = wp.IsInRole(WindowsBuiltInRole.Administrator);
if (!runAsAdmin)
{
// It is not possible to launch a ClickOnce app as administrator directly,
// so instead we launch the app as administrator in a new process.
var processInfo = new ProcessStartInfo(Assembly.GetExecutingAssembly().CodeBase);
// The following properties run the new process as administrator
processInfo.UseShellExecute = true;
processInfo.Verb = "runas";
// Start the new process
try
{
Process.Start(processInfo);
}
catch (Exception)
{
// The user did not allow the application to run as administrator
MessageBox.Show("Sorry, but I don't seem to be able to start " +
"this program with administrator rights!");
}
// Shut down the current process
Application.Exit();
}
else
{
// We are running as administrator
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
It works on Windows 10 and Visual Studio 2019!
This action can be achieved by selecting "Enable ClickOnce security settings" (since it cannot be "unchecked" during a Publish, as stated) and then by selecting "This is a partial trust application". "Local Intranet" will be automatically selected in the drop-down menu which is perfectly fine.
Save your changes, Publish the application, done-skis. :-)
I have the same problem s I resolve it by unchecking the "Enable ClickOnce security settings"
To Find this option in Visual Studio Right Click on your Project ==>properties==>Select Security==> Enable ClickOnce security settings (This option was already checked so I unchecked it and my problem get resolved).
Here is the code snippet for VB.NET
If Not New WindowsPrincipal(WindowsIdentity.GetCurrent).IsInRole(WindowsBuiltInRole.Administrator) Then
Process.Start(New ProcessStartInfo With { _
.UseShellExecute = True, _
.WorkingDirectory = Environment.CurrentDirectory, _
.FileName = Assembly.GetEntryAssembly.CodeBase, _
.Verb = "runas"})
EDIT: But if you deploy in this way, some AV-Software blocks your code.
For anyone who's run into this, I thought I'd contribute what ended up working for me.
Yep, the 'Enable ClickOnce security settings' option automatically gets re-checked, if you un-check it, when you do Build > Publish .
For me, I don't need to 'Publish' -- it's a simple, portable .exe that creates Scheduled Tasks for my users and I needed to make sure it elevated, even when logged-in as an Administrator.
So I just grabbed my latest .exe from \bin\Release and that's what gets deployed on my clients' systems.
Worked just as expected -- i.e. when I put it on a system w/ UAC enabled/at its highest setting, the .exe has the 'shield' on it, and when I run it, even when logged-in as an Administrator, it elevates and I get the UAC prompt.
My little task scheduler app is now able to create the task without getting an 'Access Denied' error (which previously, could only be worked-around by right-clicking the .exe and clicking Run as Administrator).
Take a look in your app.Manifest file and you'll see this:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
There's instructions there in the comments, but just deleting the "requireAdministrator" and insert this in is place solved the problem for me:
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
just
Imports System.security
and
U will get no error and your application will be run as admin

Permission For writing to LOCAL_MACHINE

I made an app that allows windows users to spoof Mac Address .
It works by adding "NetworkAdapter": "00ff00ff00ff" key/value pair to registry of the users selected nic.
The problem is that every time the app tries to make changes to windows registry Windows pop's up a warning dialog, e.g.:
but clicking continue will add the registry values successfully and the app functions normally.
What can i do/or add changes in my code to make the dialog box disappear or can i do it in a better way?
The app requires Admin Privileges
here's the git repo of the app
here's the method:
public void SetMac(string macAddress)
{
const string Name = #"SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}";
using (RegistryKey key0 = Registry.LocalMachine.OpenSubKey(Name, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.FullControl))
{
string[] x = key0.GetSubKeyNames();
foreach (string name in x)
{
var var1 = Registry.LocalMachine.OpenSubKey(Name,RegistryKeyPermissionCheck.ReadWriteSubTree,RegistryRights.FullControl);
var v = var1.OpenSubKey(name, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.FullControl);
var z = v.GetValue("DriverDesc");
if (comboBox1.Text == z.ToString() )
{
v.SetValue("NetworkAddress",comboBox2.Text);
MessageBox.Show(z.ToString());
}
v.Close();
var1.Close();
}
key0.Close();
}
}
You need to run your app under elevated privileges, see Requested registry access is not allowed.
The problem here is that the user does not have permission to open the target key for writing. As abatishchev has already suggested, you need to run the application elevated so that the user actually has Administrators group membership when the code is executed.
The reason that this looks like a CAS permission error is a design flaw in the RegistryKey.OpenSubKey method. It ought to throw an UnauthorizedAccessException when the target key cannot be opened for writing due to inadequate user permissions, but it actually throws a SecurityException instead. The problem ends up appearing to be due to insuffience CAS permissions when it is really the user, not the code, that lacks permissions to edit the key.

How to prevent the Network Location dialog (home, work, public) appearing for new connections?

I've written a piece of software that uses an USB 3G Dongle to connect to the internet if a connection doesn't already exist.
When the software loads, it detects whether the internet is available and if not, then creates a dial up connection (via RAS) and then dials it.
If this happens for the first time, the network location dialog comes up asking the user to select whether it's home, work or public.
Is there anyway, I can either programatically set the network location of a connection, or even tell windows not to show the dialog and automatically set the location to public?
Cheers
Gavin
Edit: For ScottM
public bool Connect(bool monitorSignalUpdates)
{
RasPhoneBook rpb = new RasPhoneBook();
rpb.Open(true);
if (!rpb.Entries.Contains("3G Connection"))
{
rpb.Entries.Add(RasEntry.CreateBroadbandEntry("3G Connection", RasDevice.GetDeviceByName("HUAWEI Mobile Connect - 3G Modem", RasDeviceType.Modem), true));
}
_rd = new RasDialer();
_rd.EntryName = "3G Connection";
_rd.PhoneNumber = "*99#";
try
{
_rd.Dial();
if (monitorSignalUpdates)
{
_queryPort.DataReceived += new SerialDataReceivedEventHandler(_queryPort_DataReceived);
}
return true;
}
catch (Exception ex)
{
int i = 99;
}
return false;
}
This registry entry controls whether Windows will prompt for ("Home/Work/Public"):
HKLM\System\CurrentControlSet\Control\Network\NewNetworkWindowOff
http://technet.microsoft.com/en-us/library/gg252535%28v=ws.10%29.aspx
You can always "“Turn off Notification on New Networks” from system tray :)
And if you can do that, I'm sure there's a registry hack and/or a PowerShell API for doing the same:
http://technet.microsoft.com/en-us/library/cc725831%28v=ws.10%29.aspx

Launching GUI App from Windows Service - Window Does Not Appear

I have written a simple windows service which will launch a exe specified in the
onstart() method of the service. After starting the service the exe got launched it only
presents in the memory but it doesnt show in the explorer.
I'm trying to launch a calc.exe from my code.it shows the exe in the memory but it
doesnt comes into my view(i.e) in the explorer.
Below is my code to launch the exe in the onStart() method
Process pr=new Process();
pr.StartInfo.FileName="calc.exe";
pr.StartInfo.WindowStyle=ProcessWindowStyle.Maximized;
pr.StartInfo.CreateNoWindow=false;
pr.Start();
// pr.WaitForExit();
Services run in other session on Vista or later and applications started directly from services are started in the same session by default. Starting applications in other sessions is possible - you have to find the id of the user session and use CreateProcessAsUser.
If more than one user is logged in and you need to start your program for all users you must find the ids of all sessions.
Here is sample code:
int session = Win32.WTSGetActiveConsoleSessionId();
if (session == 0xFFFFFFFF)
{
return false;
}
IntPtr userToken;
bool res = Win32.WTSQueryUserToken(session, out userToken);
if (!res)
{
this.log.WriteEntry("Error WTSQueryUserToken");
return false;
}
string path = GetPath();
string dir = Path.GetDirectoryName(path);
Win32.STARTUPINFO si = new Win32.STARTUPINFO();
si.lpDesktop = "winsta0\\default";
si.cb = Marshal.SizeOf(si);
Win32.PROCESS_INFORMATION pi = new Win32.PROCESS_INFORMATION();
Win32.SECURITY_ATTRIBUTES sa = new Win32.SECURITY_ATTRIBUTES();
sa.bInheritHandle = 0;
sa.nLength = Marshal.SizeOf(sa);
sa.lpSecurityDescriptor = IntPtr.Zero;
if (!Win32.CreateProcessAsUser(userToken, // user token
path, // exexutable path
string.Empty, // arguments
ref sa, // process security attributes ( none )
ref sa, // thread security attributes ( none )
false, // inherit handles?
0, // creation flags
IntPtr.Zero, // environment variables
dir, // current directory of the new process
ref si, // startup info
out pi)) // receive process information in pi
{
int error = Marshal.GetLastWin32Error();
this.log.WriteEntry("Error CreateProcessAsUser:" + error);
return false;
}
Services are run under different account privileges (LocalService/NetworkService etc)and hence they don't have access to your desktop (under your login account's control).
Services are meant to do their job silently and thats what they should do. (with the exception of logging something in windows event log when they have something important to say)
If you open your service's properties window, go to the Log On tab then check the "Allow service to interact with desktop" check box you will get the behavior you want. Also depending on what app you what to run you may need to change the log on account.
Services are not interactive by definition, so you shouldn't expect any user interface elements to show when you launch an application from a service.
It's by design...
Like already mentioned from the others a windows service is "normally" running under a separate account ("LocalSystem" or "NetworkService"). This is the reason why you might no see the UI of the program started by your service. Also services are not intended to have a UI, they act as a background service.
But also note that starting a application by a service can be a high security risk, because the application is running with the same privileges than your service is. Normally this would be the local system account.
I don't know what your are trying to achieve with your service, but consider to use the autostart function of windows instead of a service to run your application.

Categories

Resources