An application I wrote to automatically collect log files from dozens of different Windows web servers required authentication in order to get to the log files. Leaving the folders wide open for "Everyone" would have been a terrible idea, naturally, as visitor IPs, usernames and other sensitive information could be gathered and used for nefarious purposes. FTP could have been used but not all of the servers had the service installed and management would be a bit of a pain. And sincere there weren't any firewall rules blocking CIFS access to the servers, we could just setup a share and easily grab logs.
First I looked at user impersonation, something the ASP.Net web developers at the government agency used often for accessing shares using domain authentication. However impersonation only works for domain accounts or accounts that reside on the local machine and as I didn't want to go through the trouble of getting an AD user just for log access, I had to find another way.
A long search brought me to the netapi32.dll which handles Net Use command lines for mapping drives, devices and other neat things usually seen in login scripts and such. I found almost exactly what I needed in a post by Willy Denoyette on an unofficial Microsoft usergroup but the code was in C# (which I prefer myself) but the agency standards only allow for VB code. I couldn't find the VB version anywhere and there were a few requests, so here's a class, with descriptions, that you can plug into your project and authenticate to any share.
First off, you have to import the Interop class to allow .Net to work with unmanaged code.
Imports System.Runtime.InteropServices
Next we have to declare a structure similar to the USE_INFO_2 structure used by the unmanaged .dll.
''' <summary>
''' VB.NET version of the USE_INFO_2 class needed to access
''' remote file shares by the NetApi32.dll file
''' </summary>
<StructLayout(LayoutKind.Sequential)> Public Structure USE_INFO_2
<MarshalAs(UnmanagedType.LPWStr)> Dim ui2_local As String
<MarshalAs(UnmanagedType.LPWStr)> Dim ui2_remote As String
<MarshalAs(UnmanagedType.LPWStr)> Dim ui2_password As String
Dim ui2_status As UInt32
Dim ui2_asg_type As UInt32
Dim ui2_refcount As UInt32
Dim ui2_usecount As UInt32
<MarshalAs(UnmanagedType.LPWStr)> Dim ui2_username As String
<MarshalAs(UnmanagedType.LPWStr)> Dim ui2_domainname As String
End Structure
Note that the strings must be marshalled as LPWstr types in order to be parsed correctly by the dll. Next we have to define an enumerator to define how to close an existing network connection if it exists.
''' <summary>
''' Enumerator for handling the deletion of a shared resource
''' USE_NOFORCE - does not close the connection if open files exist
''' USE_FORCE - fails the disconnection even if open files exist
''' USE_LOGS_OF_FORCE - closes open files then deletes the connection
''' </summary>
Enum ForceCond
USE_NOFORCE
USE_FORCE
USE_LOTS_OF_FORCE
End Enum
The next step is to use the DllImport method to create a reference to the dll's NetUseAdd method that will let us provide credentials and connect to another network share.
''' <summary>
''' Imports the NetUseAdd method from the NetAPI32 that tells windows to add access to a UNC share
''' with the provided credentials
''' </summary>
''' <param name="UncServerName">Share name, usually set this to Nothing</param>
''' <param name="Level">Should always be 2 to indicate we're authenticating to a shared resource. 1 means
''' we are not authenticated and would need a USE_INFO_1 structure</param>
''' <param name="Buf">The USE_INFO_2 structure to pass</param>
''' <param name="ParmError">A pointer to a value that receives the index of the first member of the
''' information structure in error when the ERROR_INVALID_PARAMETER error is returned.
''' If this parameter is NULL, the index is not returned on error.</param>
''' <returns>0 on login success, a system error code if there was an error</returns>
<DllImport("C:\windows\system32\netapi32.dll")> Public Shared Function NetUseAdd(ByRef UncServerName As String, ByVal Level As UInt32, ByRef Buf As USE_INFO_2, ByRef ParmError As UInt32) As UInt32
End Function
Good point Daniel, this should probably be used more for a server situation where only admins have the ability to logon, not for desktops.
This is good option to get access to network folders, the only disadvantage of this, is that when You open connection for example to \\172.21.7.218\ShareTest , user on the computer in which You did it has also full acces to that folder (not only program he runs), although he shouldn't. This is a bit risky.
Fantastic!
Works great where other methods failed.
Hi Leon, That’s strange as it looks like you’re using it correctly. If you run the NetUseWithCredentials, does it connect properly and can you see the connection from a command line using NET USE? Make sure the name under NET USE is exactly the same as what you put in NetUseDel. I’m guessing it may drop the dollar sign for some reason.
Dear Chris,
Thank you SOOO much for the code and explanation about accessing network shares on non domain servers and passing the username and password to obtain access.
I'd been looking for several days for something like this. I had found C#, C and C++ examples, but am completely illiterate with those languages.
It took me some time, but finally I got the part on gaining access to the network share working. The problem at the moment for me is that I get error 2250, network share does not exist, when trying to use NetUseDel to disconnect the share.
-I know it's much to ask, but might you have some suggestions?
The code I use calling the function in your class is as follows.:
NetUseWithCredentials("\\172.21.7.218\ShareTest$", "Username", Nothing, "Password")
The code using NetUseDel, and giving error 2250, is the following:
NetUseDel(Nothing, "\\172.21.7.218\ShareTest$", ForceCond.USE_LOTS_OF_FORCE)
From your comments I understand that this should be correct.
Using net use from a command window does show the share, and using net use from that same command prompt to remove the share works properly.
I hope you might have some suggestions.
Thanks for your kind help and patience.
Best regards,
Leon
droopy928gt@yahoo.com