Solved

Set up AspNetAuth on FTP with IIS7 and FTP service 7.5

Posted on 2010-09-17
10
1,775 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
SQL Query - Issue with Top Statement 5 56
OpenVMS Training 1 59
Application gets hammered - IIS 2 49
Slow response time from SQL server/IIS when queried/generating reports 10 88
Preface There are many applications where some computing systems need have their system clocks running synchronized within a small margin and eventually need to be in sync with the global time. There are different solutions for this, i.e. the W3…
When it comes to showing a 404 error page to your visitors, you do not want that generic page to show, and you especially do not want your hosting provider’s ad error page to show either. In this article, I will show you how to enable the custom 40…
Attackers love to prey on accounts that have privileges. Reducing privileged accounts and protecting privileged accounts therefore is paramount. Users, groups, and service accounts need to be protected to help protect the entire Active Directory …

733 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