Solved

Set up AspNetAuth on FTP with IIS7 and FTP service 7.5

Posted on 2010-09-17
10
1,760 Views
Last Modified: 2013-12-02
Hi,

since days I try to set up IIS7 (with ftp services 7.5) to use my AspNetSqlRoleProvider to allow and deny access to the ftp server.

I found some tutorials but with both I cannot get it up and running.

http://learn.iis.net/page.aspx/389/configuring-ftp-with-net-membership-authentication/
http://learn.iis.net/page.aspx/305/configuring-ftp-75-user-isolation/

I set up the connection string, the defaultp Provider, the user role that shall be allowed to connect and the user isolation.

If I allow anonymous access it works. If I try to login with the user credentials that work on the website (and has additionally the role that is setup to allow access) it does not work.

It does only show "530 User cannot log in. Unable to establish connection"

Any help will be apreciated
0
Comment
Question by:HugoHiasl
  • 5
  • 5
10 Comments
 
LVL 13

Expert Comment

by:Greg Hejl
ID: 33711238
your authprovider is failing.

do some packet inspection with wireshark to determine where the failure is occuring

it's either your connection to sql or the query/response

are you getting any events related to this on your sql server?
0
 
LVL 12

Author Comment

by:HugoHiasl
ID: 33714435
You're right. Now It works.

But now there is one other problem.

I use user isolation. When the user "aaa" tries to log in, I get the error "530 User cannot log in. Home directory inaccessible".

The directory structure is

LocalUser
    aaa
    Public


When I set a role base authorization in the user isolation in the way that users with the role "ftpupload" may log in, the user directory "aaa" inherits this setting. With this setting the user "aaa" cannot log in.

When I change the authorization setting for the "aaa" directory from role based to user based and allow the user "aaa" access to it, he can log in and anything works.

But I do this, I need to setup every new user manually. I did not want that because there can be lots of users that register for the web page. I would like to automatically create the home directory when a user registers.

0
 
LVL 13

Expert Comment

by:Greg Hejl
ID: 33715267
set this up in your sign up script

when you create the user also create the home directory.  drop the home directory in the sql db along with user credentials.

have your authprovider pull the home dir
0
Three Reasons Why Backup is Strategic

Backup is strategic to your business because your data is strategic to your business. Without backup, your business will fail. This white paper explains why it is vital for you to design and immediately execute a backup strategy to protect 100 percent of your data.

 
LVL 12

Author Comment

by:HugoHiasl
ID: 33753927
Hi Greg,

I tried to figure your tips out. But I cannot find any place in the Role- or Membership-Providers where the homepage could be retrieved from the provider.

I also cannot find a setting in the ftp server to pull the home directory from the provider.
0
 
LVL 13

Expert Comment

by:Greg Hejl
ID: 33758485
does the directory exist?
0
 
LVL 12

Author Comment

by:HugoHiasl
ID: 33759827
I can create it when the user gets activated.

I plan to have site where a user register. This site has different roles. One of it is "ftpupload". Users with this role shall be able to upload files with user isolation. They shall not be able to see the files of other users.

I realized that I probably will be able to set up the proper rights using the IIS Management API. At the moment I try to figure out how this works.
0
 
LVL 13

Expert Comment

by:Greg Hejl
ID: 33760232
http://learn.iis.net/page.aspx/598/how-to-use-managed-code-c-to-create-a-simple-ftp-authentication-provider/

i'm sure you've probably been here,

we used this and added code for the connection to sql db and logging
0
 
LVL 12

Author Comment

by:HugoHiasl
ID: 33801768
I'm very close to what I want to achieve :-)

I'm now able to create virtual directories with the Microsoft.Web.Administration assembly.

I found nearly anything here: http://www.iis.net/ConfigReference/system.ftpServer/security/authorization

The only last problem I face is that I can setup authorization only for the main directory. I want to do it for single sub-directories. The attached code show the example for setting it for the main directory. But how to change if I want to set it for /aaa directory?
using System;using System.Text;using Microsoft.Web.Administration;
internal static class Sample
{
   private static void Main()
   {
      using (ServerManager serverManager = new ServerManager())
      {
         Configuration config = serverManager.GetApplicationHostConfiguration();
         ConfigurationSection authorizationSection = config.GetSection("system.ftpServer/security/authorization", "Default Web Site");
         ConfigurationElementCollection authorizationCollection = authorizationSection.GetCollection();

         ConfigurationElement addElement = authorizationCollection.CreateElement("add");
         addElement["accessType"] = @"Allow";
         addElement["roles"] = @"administrators";
         addElement["permissions"] = @"Read, Write";
         authorizationCollection.Add(addElement);

         ConfigurationElement addElement1 = authorizationCollection.CreateElement("add");
         addElement1["accessType"] = @"Deny";
         addElement1["users"] = @"guest";
         addElement1["permissions"] = @"Read, Write";
         authorizationCollection.Add(addElement1);

         serverManager.CommitChanges();
      }
   }
}

Open in new window

0
 
LVL 13

Accepted Solution

by:
Greg Hejl earned 500 total points
ID: 33802500
my assistant wrote this for sql auth and directory isolation.

we already had a db setup for users that sign up
REFERENCES: 

Microsoft.Web.FtpServer
System
System.Data


using System;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using Microsoft.Web.FtpServer;

namespace FtpAuthentication
{

    public class FtpAuth : 
        BaseProvider,
        IFtpAuthenticationProvider,
        IFtpHomeDirectoryProvider
    {
        /* Much of this code is taken from the Microsoft Technet article: How to Use Managed Code (C#) to Create a Simple FTP Authentication Provider
         * Modifications for MorePhotos logic by Adrian  9/25/2009
         * This is his first compiled application
         * 
         * large modification to attempt to resolve periodic iftphomedirectory lockout
         * 9/10/2010 Adrian Maule
         * 
         * 
         * */


        
        private string strHomeDir;
        private string strRole;
        SqlDataReader reader;

        public static SqlConnection getConn()
        {
            string strConn = "Server=db1;Initial Catalog=sitekeys;User Id=ftp_auth;Password=9ah3n8$*;Trusted_Connection=false";
            SqlConnection cn = new SqlConnection(strConn);
            return cn;
        }
        
        public static void WriteToFile(String strMessage)
        {
            // define the logfile name, new log file each day

            string strLogFileName = "c:\\logfiles\\FTP\\" + DateTime.Today.DayOfYear.ToString() + ".txt";
            StreamWriter w = File.AppendText(strLogFileName);

            w.Write("{0} {1}", 
                    DateTime.Now.ToLongTimeString(),
                    DateTime.Now.ToLongDateString());
            w.WriteLine(":" 
                    + strMessage);

             //Update the underlying file.
            w.Flush();
            w.Close();            
        }
       
        #region iftpAuthenticationProvider

        bool IFtpAuthenticationProvider.AuthenticateUser(
            string sessionId,
            string siteName,
            string userName,
            string userPassword,
            out string canonicalUserName)
            {
            canonicalUserName = userName;
            

            // First check to see if they are in the database
            //WriteToFile(strConn);

            WriteToFile("ftp_login: " + userName + ", password: " + userPassword);
            bool blnStatus = false;
            /*
             * we need to check for a usename/password match to both xxxxxxmanager and website.
             * */

            string sqlStatement = ""
                + "SELECT "
                    + "a.sitename, "
                    + "a.siteFTPHomeDir, "
                    + "a.FTPhomeDir, "
                    + "a.siteFTPUsername, "
                    + "a.FTPUsername "
                + "FROM userkeys a "
                + "WHERE "
                    + "(a.siteFTPusername = '" + userName + "' "
                    + "and a.siteFTPpassword = '" + userPassword + "')"
                + "OR  "
                    + "(a.FTPusername = '" + userName + "' "
                    + "and a.FTPpassword = '" + userPassword + "')";

           //WriteToFile(sqlStatement);

            try
            {
                // Verify that the user name and password are valid.

                /* I had some problems with the objects being open with the sql calls, 
                 * so I'm making sure that they are closed
                 * before I open them again 
                 * */
                
                //WriteToFile("SqlConnection Coming Up");

                SqlCommand cmd = new SqlCommand(sqlStatement);
                SqlConnection cn = getConn();
                if (cn.State != ConnectionState.Open)
                {
                    cn.Close();
                }
                cn.Open();

                cmd.Connection = cn;
                cmd.CommandText = sqlStatement;
                reader = cmd.ExecuteReader();

                if (reader.IsClosed != true)
                {
                    while (reader.Read())
                    {
                        blnStatus = true;
                    }
                    reader.Close();
                }
                cn.Close();

            }
            catch (Exception e)
            {
                WriteToFile("SQL FAIL " + e.ToString() + "\r\n" + sqlStatement);
                blnStatus = false;
            }
            finally
            {
                    reader.Close();
            }
            // Note: In this example, the user name is case-insensitive

            if (blnStatus != true)
            {
                WriteToFile("BAD AUTH: " + userName);
            }
            else
            {
                WriteToFile("AUTH OK : " + userName);
            }          
            return blnStatus;
        }
    #endregion

    

    #region IFtpHomeDirectoryProvider Members

    string IFtpHomeDirectoryProvider.GetUserHomeDirectoryData(
     string sessionId,
     string siteName,
     string userName)
        {
            WriteToFile("ftp_getDir: " + userName);
            string strOutput;
            string sqlStatement = ""
                    + "SELECT "
                       + "a.sitename, "
                        + "a.siteFTPHomeDir, "
                        + "a.FTPhomeDir, "
                        + "a.siteFTPUsername, "
                        + "a.FTPUsername, "
                        + "b.servername as webservername, "
                        + "c.servername as ftpservername "
                    + "FROM userkeys a "
                    + "LEFT JOIN servers b on a.webserver = b.id "
                    + "LEFT JOIN servers c on a.ftpserver = c.id "
                    + "WHERE "
                        + "(siteFTPusername = '" + userName + "' ) "
                    + "OR  "
                        + "(FTPusername = '" + userName + "' )";
           //WriteToFile(sqlStatement);
            try
            {
                /* I had some problems with the objects being open with the sql calls, 
                * so I'm making sure that they are closed
                * before I open them again 
                * */
               
                
                // Find which type of user it is.
                SqlConnection cn = getConn();
                if (cn.State != ConnectionState.Closed)
                {
                    cn.Close();
                }
                cn.Open();

                SqlCommand cmd = new SqlCommand(sqlStatement);
                cmd.Connection = cn;
                cmd.CommandText = sqlStatement;
                reader = cmd.ExecuteReader();
                string strWebUser="";
                string strPmUser="";
                string strWebDir="";
                string strWebServerName="";
                string strFtpServerName="";
                string strServerName="";

                while (reader.Read())
                {
                     strWebUser = reader["siteFTPUsername"].ToString();
                     strPmUser = reader["FTPUsername"].ToString();
                     strWebDir = reader["SiteFTPHomeDir"].ToString();
                     strWebServerName = reader["webservername"].ToString();
                     strFtpServerName = reader["ftpservername"].ToString();
                     strServerName = "";
                
                }
                reader.Close();
                if (userName == strWebUser)
                {
                    strHomeDir = strWebDir;
                    strRole = "Web";
                    strServerName = strWebServerName; WriteToFile("ftp_dir: " + userName + "; " + sessionId.ToString() + ":" + strRole + "HomeDir =  " + strHomeDir);
                }
                else if (userName == strPmUser)
                {
                    // this homedir needs to be the root of images to allow xxxxxmanager to path correctly
                    // we are using a DFS from mpfilemscsfs.
                    strHomeDir = "\\\\mpfilemscsfs\\images\\";
                    strRole = "xxxxxManager";
                    strServerName = strFtpServerName; WriteToFile("AUTHENTICATED: " + userName + "; " + sessionId.ToString() + ":" + strRole + "HomeDir =  " + strHomeDir);
                }
                else
                {
                    WriteToFile("NO USERTYPE FOUND FOR: " + userName);
                    strRole = "No Match";
                }
                reader.Close();
                cn.Close();
            }
            catch (Exception e)
            {

                WriteToFile("SQL FAIL: " + e.ToString() + "\r\n" + sqlStatement);
                strOutput="Failed";

            }
            finally
            {
            }

           
            /*
             * this area is a little insurance that we're going to path right on the servers
             * because there is a lot of D:\ and E:\ in userkeys
             * ALL PATHS LEAD TO \\mpfilemscsfs\
             * */
            
            string strEDrive = "e:\\";
            string strDDrive = "d:\\";
            string strCDrive = "c:\\";
            string strPath = "\\\\mpfilemscsfs\\";
            strHomeDir = strHomeDir.Replace(strDDrive, strPath);
            strHomeDir = strHomeDir.Replace(strEDrive, strPath);
            strHomeDir = strHomeDir.Replace(strCDrive, strPath);

            WriteToFile("ftp_dir: " + userName + ":" + strHomeDir);
            strOutput = strHomeDir;
            string strNow = System.DateTime.Now.ToString();

            return strOutput;
           // return "true";
        }
    #endregion
    }
}

Open in new window

0
 
LVL 12

Author Closing Comment

by:HugoHiasl
ID: 33803038
Perfect... thanks a lot.. I'll try tomorrow.

If I have further questions I will open a new question with new points :-)
0

Featured Post

Enterprise Mobility and BYOD For Dummies

Like “For Dummies” books, you can read this in whatever order you choose and learn about mobility and BYOD; and how to put a competitive mobile infrastructure in place. Developed for SMBs and large enterprises alike, you will find helpful use cases, planning, and implementation.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

If you are a web developer, you would be aware of the <iframe> tag in HTML. The <iframe> stands for inline frame and is used to embed another document within the current HTML document. The embedded document could be even another website.
Preparing an email is something we should all take special care with – especially when the email is for somebody you may not know very well. The pressures of everyday working life stacked with a hectic office environment can make this a real challen…
This Micro Tutorial will teach you how to censor certain areas of your screen. The example in this video will show a little boy's face being blurred. This will be demonstrated using Adobe Premiere Pro CS6.
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question