proftpd saving %u to var and rewrite it afterwards - mod-rewrite

currently working on an ftp proxy with ProFTPD.
Our setup is pretty much still the same as in this issue.
However, we struggle to make use of the username.
As we want to hide/transport the target server in the username we
do an rewrite on the username to get it cleaned up.
So far so good, we can use the clean username.
To do an LDAP authentication.
However we are still in need of the targetserver string that was in the username before the rewrite.
Any information on how to:
save the original username to a environment variable before it is rewritten (and prevent the env variable to be rewritten as well)
use the ProFTPD notes (read about it but somehow failed to find and docs on it)
access the original username (not the rewritten one)
any other information how to accomplish hiding username and targetserver in the connection and using it
are very welcome.
Maybe there is some kind of technique that we do use in the wrong way or a technique that we failed to use so far.
Edit:
Regarding #Castaglia
Was said we do have 2 infos in the original username. ADuser#RemoteServer.
Withe the ADuser we want to establish an LDAP authentication. With the RemoteServer info we want to connect to a remote server with credentials we queried from MySQL.
What we struggle with right now is making use of both infos. With the rewrite we get a clean user but loose the server.
So what we are looking for is some sort of option to save the original string to a var. And rewrite it 2 times. One time into a userstring to authenticate ans one time into a server name to know which server the user wants to connect to.

For interested party, this is how we (me and Daniel) solved it.
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCondition %m USER
RewriteRule ^(.*#)?([0-9A-Za-z]+)(#)?(.*)? $2
</IfModule>
<IfModule mod_ldap.c>
LDAPServer ...
...
</ifModule>
<IfModule mod_sql.c>
SQLBackend mysql
SQLConnectInfo ...
SQLLog USER server_token
SQLNamedQuery server_token UPDATE "buffer_token='%{note:mod_rewrite.$4}' WHERE username = '%U'" users
SQLAuthenticate off
SQLNamedQuery get-url SELECT "concat('ftp://',ftp_username, ':', ftp_password, '#', ftp_servername) FROM users inner join server_user on users.id = user_id inner join servers on servers.id = server_id WHERE username = '%U' and token = buffer_token"
</IfModule>
<IfModule mod_proxy.c>
...
</IfModule>
ProxyReverseServers sql:/get-url

I think that to get what you want to achieve, you might try the following.
First, modify the RewriteRule slightly, in order to capture the second part of your USER command (e.g. "RemoteServer"), thus:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCondition %m USER
RewriteRule ^(.*#)?([0-9A-Za-z]+)(#)?(.*)? $2
</IfModule>
Next, in your SQL query configuration, use a note reference to retrieve that regex group:
<IfModule mod_sql.c>
...
SQLConnectInfo ... PERCONNECTION
...
SQLNamedQuery get-url SELECT "concat('ftp://',ftp_username, ':', ftp_password, '#', ftp_servername) FROM users ... WHERE concat(username, '#', token) = '%{note:mod_rewrite.$4}'"
...
</IfModule>
That %{note:mod_rewrite.$4} notation says "interpolate the value of the session note stored under the key 'mod_rewrite.$4'". And mod_rewrite stashes/records the groups of the matched RewriteRule in those session notes; the $N uses a 1-based index, thus $1 for the first group,
$2 for the second group (which would be the "ADuser" value in your example USER command), $3 for the third group, etc.
I've updated my answer to also include the use of the "PERCONNECTION" SQLConnectInfo policy. Why? This tells the mod_sql module to connect to the SQL database when a client connects, rather than waiting until the client has provided all of the necessary credentials. Due to the way that mod_rewrite stashes its notes about the captured regex groups, this is necessary: those notes are only captured for the duration of that command only (i.e. in your case, only the USER command). Thus we want to use the configured SQL statement when the USER command is processed, since that is when that %{note:mod_rewrite.$4} reference will be valid.
Hope this helps!

Related

Rewriting url with the following regular expression

I'm trying to do a mod rewrite to get this url: localhost/test/index.php?hello
I created a file for this page called hello.php and it is in the folder /test
To clarify, I have another page that has a link to my hello.php, but what is the correct url so I can display localhost/test/index.php?hello in the url when I click the link to access my hello.php page.
The following doesn't seem like it is right:
RewriteRule ^.*$ index.php?$1 [L]
Try this if you want to just do php files.
RewriteEngine on
RewriteRule (.*)\.php$ /index.php?$1 [L]
To clarify what my answer does. It gives you more friendly URLs which it sounded like what your were asking for.
So you can use localhost/hello.php and it will be internally redirect to /localhost/index.php?hello. Internally means they will never see localhost/index.php?hello and will always see localhost/hello.php in their browser.
You can do any URL and it will rewrite to a php file. e.g. localhost/index.php?newpage and you can use /localhost/newpage.php
Hope that is clearer.
EDIT
You want the reverse but I don't know how your PHP is constructed but query strings are typically field/value pairs. For example name=john, page=contact, action=hello etc. You have index.php?hello but hello has no content or value.
That's probably why you're having such a hard time even re-writing your URL. Using $_GETwould require a value.
So what I would do, is if your URL was like this using field/value pairs
index.php?action=hello
Then in the index.php file you could do something like
$action = $_GET["action"];
if($action == "hello"){
//show contents of hello, include a page or whatever
}
Once you have good URLs it would be easy to rewrite it.
So if the URL that you want shown is like
index.php?action=hello and you want to redirect it to hello.php
Your .htaccess would look like this
RewriteRule ^action=([^/]+) /$1.php [R,L]
That would redirect it to the php file. If you don't want to show the redirection and keep it an internal redirect you can remove the R flag and just keep [L].
I personally don't want the user to see really long query strings URL example. mysite.com?page=music&artist=someartist&title=sometitle
So all my URL's are rewritten to be shorter and friendlier like my original answer.
you don't need .htaccess for 2. as far as you're using GET parametr - use it in index.php:
if (isset($_GET['hello'])) include('hello.php');
this will show the contents of hello.php inside index.php

Mod_rewrite - don't display certain query string in the url

I know this question may have been asked several times, but to be honest I haven't yet found a complete answer for this.
I have this url:
modelDetails.php?manufacturerName=$1&manfuacturerID=$2&modelName=$3&modelID=$4&yachtCode=$5&lang=$6
Is it possible not to display yachtCode and lang in the url and still pass the values from page to page?
This is my htacces file:
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^(.*)\.html$ $1.php [nc]
RewriteCond %{QUERY_STRING} ^lang=(EN|DE|NL)$ [NC]
RewriteRule ^(.*)/([0-9]+)/(.*)/([0-9]+)/([0-9]+)$ modelDetails.php?manufacturerName=$1&manufacturerID=$2&modelName=$3&modelID=$4&yachtCode=$5 [L,QSA]
If you remove the data from the query string, then the only other way to access the data is to retrieve it from a cookie. But to set the cookie you'll have to have the yachtCode value appear in the query string at some point.
The only alternative would be to use POST (the mode used by a web form) instead of GET (the mode which is generally used). POST mode submits variables as part of the request, rather than adding the variables to the query string. But you can't force a hyperlink to use POST mode, so this is probably not of use to you.
In short, you probably can't hide yachtCode from the end user completely.

apache2 tomcat6 mod_rewrite with pretty urls loses user session info - empties shopping cart

I have tried this with both mod_jk and mod_proxy and get the same result.
Using this mod_rewrite rule works fine:
RewriteRule ^/(.*)\-blah.html$ /blah/blah/blah?blah=l2vb&party_name=$1 [R,L]
The trouble with this is the ugly new URL /blah/blah/blah?blah=l2vb&party_name is displayed in the address line of the browser, which is what I'd hoped to avoid. It seems to be the [R] flag that does this.
The following rule hides the ugly URL and displays only the new pretty one:
RewriteRule ^/(.*)\-blah.html$ /blah/blah/blah?blah=l2vb&party_name=$1 [P,L]
NB: The only difference here is the flags at the end between the [].
The trouble is that if the user already had something in their shopping cart it gets emptied. Somehow their connect session (or whatever it is - rather out of my depth here!) gets re-initialised so they appear to be starting from scratch.
I have tried several other combinations of flags, like [PT,L], [R,PT] etc and had no luck so far.
The [R] flag means 302 Redirect Code, which obviously changes the URL in a browser.
I think you need QSA flag:
RewriteRule ^/(.*)\-blah.html$ /blah/blah/blah?blah=l2vb&party_name=$1 [QSA,L]
QSA flag will preserve existing query string (to be more precise, will append it to the new URL) .. which otherwise gets lost as you DO manipulate with query string. I think session ID or something may be passed via query string .. and when URL gets rewritten it is lost, so server creates new session. If that is the case, then the above should solve your problem.
Apache documentation: http://httpd.apache.org/docs/current/rewrite/flags.html#flag_qsa

Mod_rewrite and MySql

I have a url eg. www.example.com/user.php?user_id=9 , where the user_id field maps to one of the pk in the user table . I don't want the url to be like this , instead i want to have a url like www.example.com/user/Aditya-Shukla.i am using apache 2 and I understand that mod-rewrite module has sets of rewriting rules which can be used to create url alias.
My question is
I have all href in the form www.example.com/user.php?user_id=9. So to change the url I suppose i have to change all the href's to the www.example.com/user/Aditya-Shukla and for rewriting the rule do a query to get a record?
Is there a better solution .
No, mod_rewrite does not have sets of rewriting rules. It rather provides directives to build rules based on regular expression patterns that can be combined with additional conditions.
In your case you would build a rule that takes any requested URL path that starts with /user/ and has another path segment following and rewrites it internally to your user.php, like:
RewriteEngine on
RewriteRule ^/user/([^/]+)$ /user.php?name=$1
The first directive RewriteEngine on is just to enable mod_rewrite. And the second directive RewriteRule … is the rule as described above: ^/user/([^/]+)$ is the pattern that matches any URL path that starts with /user/ (i.e. ^/user/) and that is followed by one path segment (i.e. ([^/]+)$). That request is then rewritten internally to /user.php while the matched path segment behind the /user/ is used as a parameter value for the name parameter ($1 is a reference to the matched value of the first group denoted with (…)).
So this will rewrite a request of /user/Aditya-Shukla internally to /user.php?name=Aditya-Shukla. You can then use that user name and look it up in your table.
You can either add a RewriteRule that will rewrite user/Aditya-Shukla to user.php?user_name=Aditya-Shukla and handle the rest in your code.
RewriteEngine On
RewriteRule ^user/(.*)$ user.php?user_name=$1
Or using a RewriteMap directive to lookup usernames, which will allow to rewrite user/Aditya-Shukla directly to user.php?user_id=9
I presume that within your own site you will always create the canonical form of the URL, i.e.:
/user/Aditya-Shukla
...and you are just having to deal with outside links that are not in canonical form, i.e. "old links" like:
www.example.com/user.php?user_id=9
mod_rewrite may not be suitable for remapping in this situation. I am presuming you may have very many users, and that number may grow. mod_rewrite does have a RewriteMap directive and yes there are ways to generate your map dynamically, but I don't think that would be a good design (to dynamically create a map of userId-to-userName dynamically every time your rewrite rule matches...)
Instead you should simply write your user.php code to lookup the correct userName, assemble the canonical form of URL you want, and send a redirect back to the client. Something like:
Header( "HTTP/1.1 301 Moved Permanently" );
Header( "Location: http://www.example.com/user/Aditya-Shukla" );
You should probably also use a 301 redirect (instead of 302) to indicate this is a "permanent" URL change, which will help search bots index your site correctly if it encounters an "old style" URL out there.
-broc

Dealing with non-hardcoded domain names with mod_rewrite

I am migrating my application which provides a subsite for each user from domain.com/~user to user.domain.com. In order to do this, I wrote the following RewriteRule:
RewriteRule ^~([a-z_]+)(/.*)?$ http://$1.%{HTTP_HOST}$2 [R=301,QSA,NC]
However, %{HTTP_HOST} doesn't do exactly what I need it to, because if for instance a user browses to www.domain.com/~user, it'll redirect to user.www.domain.com which is obviously not what I'm looking for.
I know that I can replace %{HTTP_HOST} with a hardcoded domain, but I don't want to do this either, because I will be rolling out the changes on multiple domains and don't want to have to customize it for each one. Is there a better way to make a singular change without hardcoding? (Furthermore, what if the base domain already has a subdomain -- ie. sub.domain.com/~user -> user.sub.domain.com)
Try it with this additional RewriteCond:
RewriteCond %{HTTP_HOST} ^(www\.)?(.+)
RewriteRule ^~([a-z_]+)(/.*)?$ http://$1.%2$2 [R=301,QSA,NC]
This will remove the www. prefix from the host if present.

Resources