Re: How does one control what the path is on the JSESSIONID cookie?
Christopher Schultz wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 John, On 6/23/2009 5:04 PM, John Caron wrote: Pid wrote: Filip Hanik - Dev Lists wrote: John Caron wrote: Tomcat 6.0.18 automatically adds the session cookie like: Set-Cookie: JSESSIONID=6D839FF3B960947CC6FD41B98CD02E0D; Path=/thredds How can I change the path part of the cookie? the only thing you can do is set it to empty, by using emptySessionPath. Or you could change the name of your application. That's unlikely to be helpful though. Why does it matter? p The client may have more than one session, which must be distinguished by the path, eg i need: Set-Cookie: JSESSIONID=6D839FF3B960947CC6FD41B98CD02E0D; Path=/thredds/p1 Multiple cookies is not a problem. If Tomcat receives multiple JSESSIONID cookies with a request, it will try all of them until it gets a match for the webapp being used to serve the request. That said, having overlapping webapp URL spaces is asking for trouble. Sorry, I didnt explain much context. This isnt for browsers, its a specialized web service for specialized clients. I have control of both the client and the server code. The clients are accessing remote scientific datasets. In certain circumstances, establishing a session with them for each dataset that they open solves some hard problems. A previous post had this filter, which im guessing i can modify : /** * This class will set the cookie maxAge to match the session timeout value. That way, a user who closes their browser and * re-enters the site will still have the same session if it has not timed out on the server. */ This filter was written for a very different purpose. HttpSession session = httpRequest.getSession(); Note that this filter creates sessions when when one is not necessary. thanks for reminding me of that. httpResponse.addCookie( sessionCookie ); //FIX! This doesn't actually get rid of the other cookie, but it seems to work OK This comment is telling: yes, the old cookie is not removed, and it really should be. A better solution would be to write a Valve that wraps the response to intercepts addCookie calls and re-write the maxage when the cookie is added. Im hoping to not use Valves since that makes my code Tomcat specific. I am delivering this webapp to some dozens of scientific institutions. Allowing them to run any servlet container is a big win. I have rewritten this as follows: public class CookieFilter implements Filter { public static final String JSESSIONID = JSESSIONID; public static final String SESSION_PATH = SESSION_PATH; public void init(FilterConfig config) throws ServletException { } public void doFilter(ServletRequest _request, ServletResponse _response, FilterChain chain) throws IOException, ServletException { chain.doFilter(_request, _response); // examine response after the request is processed if (_response instanceof HttpServletResponse) { HttpServletRequest httpRequest = (HttpServletRequest) _request; HttpServletResponse httpResponse = (HttpServletResponse) _response; HttpSession session = httpRequest.getSession(false); if ((session != null) (session.getId() != null) (session.getAttribute(SESSION_PATH) != null)) { Cookie sessionCookie = new Cookie(JSESSIONID, session.getId()); sessionCookie.setPath((String) session.getAttribute(SESSION_PATH)); httpResponse.addCookie(sessionCookie); } } } public void destroy() { } } However, it has no effect, the path stays equal the web context name. Im guessing there some code that rejects changing the session cookie ( I havent tracked it yet in the debugger). Is this a security thing or is there something in the Servlet spec that says what the path has to be? - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: How does one control what the path is on the JSESSIONID cookie?
Pid wrote: Filip Hanik - Dev Lists wrote: John Caron wrote: Tomcat 6.0.18 automatically adds the session cookie like: Set-Cookie: JSESSIONID=6D839FF3B960947CC6FD41B98CD02E0D; Path=/thredds How can I change the path part of the cookie? the only thing you can do is set it to empty, by using emptySessionPath. Or you could change the name of your application. That's unlikely to be helpful though. Why does it matter? p The client may have more than one session, which must be distinguished by the path, eg i need: Set-Cookie: JSESSIONID=6D839FF3B960947CC6FD41B98CD02E0D; Path=/thredds/p1 A previous post had this filter, which im guessing i can modify : package com.prosc.servlet; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; /** * This class will set the cookie maxAge to match the session timeout value. That way, a user who closes their browser and * re-enters the site will still have the same session if it has not timed out on the server. */ public class SessionCookieExtender implements Filter { private static final String JSESSIONID = JSESSIONID; public void init( FilterConfig config ) throws ServletException {} public void doFilter( ServletRequest _request, ServletResponse _response, FilterChain chain ) throws IOException, ServletException { if( _response instanceof HttpServletResponse ) { HttpServletRequest httpRequest = (HttpServletRequest)_request; HttpServletResponse httpResponse = (HttpServletResponse)_response; HttpSession session = httpRequest.getSession(); if( session != null session.getId() != null ) { Cookie sessionCookie = new Cookie( JSESSIONID, session.getId() ); int sessionTimeoutSeconds = session.getMaxInactiveInterval(); sessionCookie.setMaxAge( sessionTimeoutSeconds ); sessionCookie.setPath( httpRequest.getContextPath() ); httpResponse.addCookie( sessionCookie ); //FIX! This doesn't actually get rid of the other cookie, but it seems to work OK } } chain.doFilter( _request, _response ); } public void destroy() {} } If there is a better way to do it, Id love to hear! - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
How does one control what the path is on the JSESSIONID cookie?
Tomcat 6.0.18 automatically adds the session cookie like: Set-Cookie: JSESSIONID=6D839FF3B960947CC6FD41B98CD02E0D; Path=/thredds How can I change the path part of the cookie? thanks... - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Obtain a SocketChannel instead of OutputStream ?
My application is a scientific data server that transfers large amounts of binary data. I am looking to make it as fast as possible and have been experimenting with the NIO FileChannel.transferTo() method. This appears to be much faster (3-10X) than using an OutputStream, under some circumstances. So I am trying to see if I can use this from within Tomcat. So the question is whether there is a way to obtain a SocketChannel for the connection? The standard interface only allows to get an OutputStream. While Channels.newChannel(OutputStream out) gives a WriteableByteChannel, the transferTo() method does not work on it, apparently one needs to get the SocketChannel at a deeper level. Has anyone else tried this? Any ideas would be much appreciated. - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Is compress working? No Content-Encoding header
It seems bizarre, but it appears that the Accept-Encoding header is being lost somewhere on route from my home computer. running this test on my work computer works fine. sorry for the noise. Caldarale, Charles R wrote: From: John Caron [mailto:[EMAIL PROTECTED] Subject: Is compress working? No Content-Encoding header I tried to enable compression in Tomcat 6.0.10: I just tried the same thing in 6.0.14 with no problems, retrieving the same page that you tried. Connector config: Connector port=8080 protocol=HTTP/1.1 compression=on compressableMimeType=text/html,text/xml,text/plain,application/xml,appl ication/octet-stream,application/x-netcdf connectionTimeout=2 redirectPort=8443 / Request headers: GET /docs/logging.html HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9, text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://localhost:8080/docs/ Response headers: HTTP/1.x 200 OK Server: Apache-Coyote/1.1 Etag: W/22385-1184923216000 Last-Modified: Fri, 20 Jul 2007 09:20:16 GMT Content-Type: text/html Transfer-Encoding: chunked Content-Encoding: gzip Vary: Accept-Encoding Date: Sun, 09 Dec 2007 16:31:21 GMT If you haven't already done so, you might try clearing the Firefox cache, but that shouldn't matter since you're seeing a 200, not 304. You could try it again on 6.0.14. Are they any semi-clever boxes between your browser and motherlode.ucar.edu that might be caching responses? - Chuck THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers. - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Is compress working? No Content-Encoding header
I tried to enable compression in Tomcat 6.0.10: Connector port=9080 protocol=HTTP/1.1 maxThreads=50 connectionTimeout=2 redirectPort=9443 compression=on compressableMimeType=text/html,text/xml,text/plain,application/xml,application/octet-stream,application/x-netcdf / Now I am trying to see if that is working. I am using the Live HTTP Headers plugin for Firefox, which shows me the HTTP headers. For simplicity, I just make a request for a static html page, namely one of the tomcat docs: http://motherlode.ucar.edu:9080/docs/logging.html GET /docs/logging.html HTTP/1.1 Host: motherlode.ucar.edu:9080 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://motherlode.ucar.edu:9080/docs/introduction.html HTTP/1.x 200 OK Server: Apache-Coyote/1.1 Etag: W/22376-1182289456000 Last-Modified: Tue, 19 Jun 2007 21:44:16 GMT Content-Type: text/html Content-Length: 22376 Date: Sun, 09 Dec 2007 15:35:25 GMT I would expect to see a header in the response: Content-Encoding: gzip but its missing. I assume this means that the content is not compressed. I also tried compression=force to no avail. Also, I wonder what this sentance means: If the content-length is not known and compression is set to on or more aggressive, the output will also be compressed. What does the output refer to? The also implies something else besides the output? thanks for any help... - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: session hijacking again
Christopher Schultz wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 John, John Caron wrote: We plan on using SSL to do the initial authentication, but then use session ids without SSL for the data transfer. Okay, thanks for clarifying that. This is definitely a good thing to do, and it appears that session hijacking /will/ then be one of your only worries. Like AOL users, and some others going through proxies, etc. It's a relatively effective mechanism, and you might want to allow users to opt-in to this type of thing. You'll notice that some sites have a checkbox in the login form that says Restrict my session to this computer, and when that's enabled, you do the IP verification. That allows AOL (or other) users to opt-out of the security mechanism. Hmm I didnt know that about opt-out security. We arent really doing web sites, we are enabling data access by scientific programs. Oh, okay. So, you have something like an XML-based web service or something like that? yes, exactly You could offer a standard configuration for your customers (which uses IP checks) and then provide instructions to users for whom this poses a problem to disable this checking. Make the configurability of this feature part of the login request (i.e. add an optional parameter like verifyIPAddress=true|false) so that it cannot be changed after login to subvert your protection. very cool idea i hadnt thought of This is likely to cause problems with the browser getting out of sync with the server. Also, I'm not sure if you can change the session id in TC, so you might not be able to do this without a bunch of hacking around in the TC session code. yeah, im thinking i prefer the IP check, since our users tend to not be dialup. But Im wondering if i will have to hack around the tomcat code to do IP checking. Not at all. You have a few options: 1. Write a filter, applied to all URLs, that checks for a session flag -- something like verifyIPAddress -- which is the IP address of the user who logged-in. If the IP for the request != login IP, then do something simple like sendError(FORBIDDEN) or whatever. This is probably the easiest thing to do. Of course, you will have to put this session attribute into the session at some point, which is somewhat problematic since if you use container-managed logins, you never know when the login takes place. Are you using container-managed logins? yes. 2. You can replace the authenticator and authorization system with something else. I routinely recommend securityfilter, which is an Open Source project ans can be found at http://securityfilter.sourceforge.net. You can customize many parts of the login process, including what happens during and after login -- including something like setting a session attribute to turn on (or off) IP checking. You can also build IP checking into the additional code you write for authorization. Needless to say, this is more complex, but gives you greater control over the process. What are the implications of session hijacking for your service? Do you have any trade secrets or anything like that which are considered sensitive? What about potentially destructive modes of operation -- for instance, can a user delete or otherwise modify data? If you generally have read-only data, you might not need to worry too much about session hijacking. Its read-only, and no trade secrets or $$ involved. So im not convinced we even need to worry about session hijacking, but i'd like to know what are options are. I think that after your investigation, you may find that spending a lot of time preventing session hijacking is simply not worth it. I'm glad to see that someone is actually thinking about security issues instead of implementing something that sounds good. Nice job, John! thanks, but i havent done anything yet! Actually, that's the point: most people start doing before they have finished /thinking/. You are at least doing things in the proper order ;) I think i see how to get started. Thanks very much! Good luck, - -chris -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.6 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFFvnWN9CaO5/Lv0PARAvu5AJ9of7roniGwPAN4POlmdwkTcgM9jgCfak7R lbMJowQLBIjV/saklBw6gfo= =7AMj -END PGP SIGNATURE- - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
session hijacking again
Hello: Our application is serving large amounts of scientific data over HTTP. The user needs to login to access the data. We would like to use session ids to reduce the login overhead. We cant afford the overhead of HTTPS encryption of teh data (3 times slower ?). We realize this makes us vulnerable to session hijacking. Still, we arent transferring financial information, so tentatively we think its a reasonable risk. The Wikipedia article (http://en.wikipedia.org/wiki/Session_hijacking) suggest a couple of things that help, that seem reasonable to me: # Some services make secondary checks against the identity of the user. For example, a web server could check with each request made that the IP address of the user matched the one last used during that session. This does not prevent attacks by somebody who shares the same IP address, however, and could be frustrating for users who's IP address is liable to change during a browsing session. # Alternatively, some services will change the value of the cookie with each and every request. This dramatically reduces the window in which an attacker can operate and makes it easy to identify whether an attack has taken place, but can cause other technical problems (for example, preventing the back button from working properly, on the web). I would like to implement one or both of these in Tomcat: 1) IP checking and 2) session id switching. I guess others have thought about this. Does anyone have any advice or pointers (or code!) to get started. Thanks for any help. John Caron Unidata/UCAR - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Bypass web.xml declarative security (sort of)
thank you, I will investigate securityfilter Christopher Schultz wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 John, John Caron wrote: Instead of declaring which URLs need to be secure in web.xml, I would like to determine this when the URL comes in, but then use Tomcat to deal with the authentication if it is needed. Can anyone give me any pointers on where to get started with that? There's no standard way to do this. Your options are basically to either hack around with Tomcat's authentication and authorization code (which I don't recommend), implementing your own authentication and authorization scheme (or perhaps just the authorization scheme using something like a Valve or, better yet, a Filter), or piggyback on an existing project like securityfilter (http://securityfilter.sourceforge.net). I think that the third option will get you further faster. - -chris -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.6 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFFrwl79CaO5/Lv0PARAq1JAJ9eEbHMO1sejY3BizqHXEv/na339ACglZiV VLNVH1GgzwUcE6d9A5r4X94= =4O/I -END PGP SIGNATURE- - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
how to tell Tomcat to send a blank WWW-Authenticate header?
Christopher Schultz wrote: Also, you could set the error page that is used when a user doesn't have the proper credentials to something that gives you the opportunity to re-login in order to access the forbidden resource. When you want to log someone out of BASIC authentication, you have to send a blank WWW-Authenticate header to the client, just the same way that Tomcat would do if you weren't already authenticated. Is there a way to tell Tomcat to send a blank WWW-Authenticate header to the client when authorization fails? I would like to not use FORM authentication. thanks for any help - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Bypass web.xml declarative security (sort of)
Hello: Instead of declaring which URLs need to be secure in web.xml, I would like to determine this when the URL comes in, but then use Tomcat to deal with the authentication if it is needed. Can anyone give me any pointers on where to get started with that? thanks, John Caron - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Programmatic Security
Nicholas Sushkin wrote: On Wednesday 28 June 2006 14:05, John Caron wrote: I assume I need to get a session established, so that the authorization need only be done once. It would also be nice if I recieve a unauthorized request, that I could pass it to Tomcat's 401 challenge and authentication mechanism. However, im already down in my servlet code, past the point where Tomcat would handle the challenge and authentication, and I dont see any way to pass it back to Tomcat. You can create a separate servlet or jsp for accessing the content that requires authorization, then include that URL into web.xml stanza as requiring a valid user. Then, once that URL is accessed, Tomcat would prompt you to log in. In your secure servlet or JSP, you would get user id using getRemoteUser() and somehow decide whether the user is allowed access to the data corresponding to the current request parameters. How to decide whether a user is authorized to view a certain dataset is up to you. For example, you may want to create a table in your database mapping users to datasets. Here's an example of web.xml stanza, security-constraint display-nameDataset Security Constraint/display-name web-resource-collection web-resource-nameDataset Protected Area/web-resource-name !-- Define the context-relative URL(s) to be protected -- url-pattern/DatasetSecureServlet/url-pattern !-- If you list http methods, only those methods are protected -- http-methodDELETE/http-method http-methodGET/http-method http-methodPOST/http-method http-methodPUT/http-method /web-resource-collection auth-constraint !-- Anyone with one of the listed roles may access this area -- role-nameUser/role-name /auth-constraint /security-constraint Sorry if I am repeating something you already know. Thanks, its useful to hear someone else's take on the problem, even when I already know some of the details. I guess im fishing around for anyone who has thought about or implemented programmatic security instead of / in addition to container managed security. Thanks for your time. - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Programmatic Security
Pid wrote: It really depends on what you're trying to achieve, maybe you could elaborate? Do you need to restrict access to filesystem resources, servlets, jsps, images, DB content, or something else? Ok, I am creating a data server that is controlled by an XML configuration catalog of dataset objects. The dataset can refer to physical files on disk, or to virtual data that is created dynamically. It can be complicated, and large (tens of thousands of datasets) and I need to make it as easy as possible to configure. I need to allow the administrator to specify access constraints on a per-dataset basis. This more or less rules out having Tomcat controlling access through the URL pattern. So I think I need Programmatic Security. When a request comes in, I can quickly determine what access constraint (if any) is needed. I was planning on using the standard Tomcat security roles and user administration stuff. This is a data server, primarily talking to other programs (not humans using a browser). I am also helping to develop the client software that will access the data, so I am trying to understand all the possible ways to make this work. I assume I need to get a session established, so that the authorization need only be done once. It would also be nice if I recieve a unauthorized request, that I could pass it to Tomcat's 401 challenge and authentication mechanism. However, im already down in my servlet code, past the point where Tomcat would handle the challenge and authentication, and I dont see any way to pass it back to Tomcat. thanks for any thoughts on this Martin Gainty wrote: Good Evening All- The best way is to put up a Jsp / servlet which itself has the username/password information to let you behind the firewall There are a ton of https and firewalls you can install and configure to your hearts content But none would be more secure and safe than controlling authentication (a simple username/password) via the servlet Remember to tell .htaccces to disallow execute write and pretty much read permissions on everything except for your username/password screen I'm not sure introducing firewalls is any of any help inside a servlet. Nor really, is .htaccess given that he hasn't specified that he's using Apache. Yes, this is a standalone Tomcat server. Martin -- This email message and any files transmitted with it contain confidential information intended only for the person(s) to whom this email message is addressed. If you have received this email message in error, please notify the sender immediately by telephone or email and destroy the original message without making a copy. Thank you. - Original Message - From: John Caron [EMAIL PROTECTED] To: Tomcat Users List users@tomcat.apache.org Sent: Tuesday, June 27, 2006 9:01 PM Subject: Programmatic Security I need to implement fine-grained security access, so it looks to me like Programmatic Security (Servlet spec 12.3) is called for. I want to recieve the request in my servlet, then decide what access rights are needed for it. In this case, if I understand correctly, the user must already be authenticated means that they have tried to access a Tomcat-protected page (eg a login page), have been successfully authenticated by Tomcat, and further requests are returning the JSESSION cookie that was assigned during authentication. Is that right? Is there some other way the req.getRemoteUser() could return non-null? Is there some way that I can programatically trigger Tomcat to initiate the authentication process? Thanks for any help... - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Programmatic Security
I need to implement fine-grained security access, so it looks to me like Programmatic Security (Servlet spec 12.3) is called for. I want to recieve the request in my servlet, then decide what access rights are needed for it. In this case, if I understand correctly, the user must already be authenticated means that they have tried to access a Tomcat-protected page (eg a login page), have been successfully authenticated by Tomcat, and further requests are returning the JSESSION cookie that was assigned during authentication. Is that right? Is there some other way the req.getRemoteUser() could return non-null? Is there some way that I can programatically trigger Tomcat to initiate the authentication process? Thanks for any help... - To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]