On Nov 23, 2008, at 10:16 AM, Jan Bartel wrote:
Hi David, David Jencks wrote:On Nov 21, 2008, at 4:59 AM, Jan Bartel wrote:Hi David, I've been looking at the changes to the constraint implementation to do the up-front merging. There are a couple of functional differences I noticed: 1. when there is an unrecognized data constraint, the new ConstraintSecurityHandler throws an IllegalArgumentException which is thrown out of the handler (line 250), which I think will result in a 500 response. Whereas, the jetty-6&7 code would send a 403 response.Well, it's an enumeration, so the only way this could happen is ifsomeone added a new value to the enumeration and recompiled. A bettererror message might be OK :-)Fair enough.2. if there is a forbidden constraint (ie no roles), the new code will always send back a 403, whereas the standard jetty code is lenient on forbidden constraints on form login and error pages (see lines 351 of jetty6 or 7 SecurityHandler).This is certainly a difference. Is it important? At the moment the only ways I can think of to support this are by adding a "notReallyForbidden" method to ServerAuthentication.I asked gregw about this behaviour, and the word is that the tck explicitly tests for this. If you have access to the tck, you might be able to verify that?
I haven't hooked the latest ServerAuthentication code up to geronimo yet, but the previous version using the jaspi auth modules seemed ok with the tck. (That version has the same lack of "notReallyForbidden" for login/error pages) I'll double check. I thought the spec and tck indicated that role-based constraints couldn't be applied to the login and error pages, but said nothing about forbidden constraints..... again I'll double check.
Just by the by, is there a huge benefit in the UserDataConstraint beingan enum rather than a class providing a primitive value that can be used in a switch statement? I'm thinking of the code at 206 in ConstraintSecurityHandler. I guess its one of those personal preference things, but I find the switch statements easier to read than the if-then-else series. But YMMV.I really like enums since they let the compiler limit the choices -- see (1) above. We could use the ordinal values in a switch statement.....if (dataConstraint == null) return true; switch (constraint.ordinal())..... but I think the if statements are less convoluted.BTW, the code needs to be reformatted to jetty standard conventions (http://docs.codehaus.org/display/JETTY/Jetty+Coding+Standards) or gregw will have conniptions ;)hmm.... I thought I'd done pretty well imitating the code style. Do youhave some way to fix it automatically?Lemme see ... as far as the brackets go, I have an eclipse codestylethat I can apply to each file, but the rigorous naming of data members with leading _or __ would have to be done manually.
aha.... I can fix that, probably tomorrow. The brackets might be tougher for me.
I'll look at the latest updates to the authenticators and the jaspi stuffnext.On the top of Monday's TODO list.BTW I think we should make your pre-processing of the constraints part of the standard jetty security handler (what you've called LegacyConstraintSecurityHandler).Correct me if I'm wrong, but the constraint preprocessing behaviour is separable from the jaspi authentication, so we could make that common between a ConstraintSecurityHandler that invoked non-jaspi authentication and another ConstraintSecurityHandler that invokedjaspi authentication?
The authentication (jaspi or ServerAuthentication) and authorization (constraints or jacc or....??) are completely separable, but I would not try to guarantee that the behavior of the legacy constraint security handler would be unchanged if we combined the constraints up front. If you guys are willing to risk that the legacy behavior will change or analyze it carefully enough so you're sure it won't, combining the constraints up front would really simplify the code. I don't understand how the legacy code works well enough to be comfortable claiming anything about it.
In terms of pluggability, I think so far I'm still leaning towards a default of current jetty authentication impl, with pluggability of the jaspi impl (probably via plugging in aJaspiConstraintSecurityHandler).
not sure what you mean here.... if you don't want to use the ServerAuthentication, RunAsToken, and UserIdentity abstractions it may be difficult to switch back and forth. If you mean you want to use the [Basic|Digest|Form|ClientCert]ServerAuthentication implementations for the known auth methods rather than the jaspi modules, I wholeheartedly agree.
BTW, thanks for putting so much work into the security refactoring!
np! david jencks
Janthanks! david jenckscheers Jan David Jencks wrote:Hi Jan,I rewrote the standard auth methods as ServerAuthentication classes on the plane ride home. I implemented Lazy and Caching (in session and SSO) as wrappers. Seems to compile but I haven't tried the tck yet.I'm not sure if I've put in all the necessary stuff e.g. timeouts?? butI think this is a lot more plausible than the pure jaspi implementations. thanks david jencks On Nov 3, 2008, at 9:13 AM, David Jencks wrote:Hi Jan, I'm about to hop on a plane so will respond in more detail later.I share your concerns about efficiency of the jaspi model, which is why I tried to put another hopefully efficient layer of interfaces in between the AbstractSecurityHandler and the jaspi auth modules. I was hoping that we could simply implement the known auth methods (FORM, BASIC,...) in terms of the ServerAuthentication interface directly and retain all possible efficiencies. Not having done it yet I mighthave missed some important points :-) I'll think some more about your comments and get back to you. thanks david jencks On Nov 3, 2008, at 1:56 AM, Jan Bartel wrote:Hi David, Having pored over the jaspi spec a few more times, and then having looked more closely at the code, I'm in a position to give some more detailed comments. Firstly, I like the cleaner distinction in functionality made with the UserIdentity and LoginService as compared with the previous UserPrincipal and UserRealm. I alsolike very much the refactoring of Abstract/ ConstraintSecurityHandlermethods. Here's the place where your antennae should sense a "but" coming :) But ... I have some reservations about the efficiency of the Jaspi Way. In particular, every request for which there is a role restriction will result in the user being fully reauthenticated. I understand that even this is an optimization and departure from the jaspi spec, which requires validateRequest to be called on each and every request, unless you know apriori that there is an exclusion constraint for the resource of the request. BTW the lazy authentication when there are no role constraints is another good optimization. As there is going to be more authenticating going on as compared with the previous situation, my next reservation takes on more significance, and that is the amount of object creation required to satisfy the convoluted jaspi callback design. Finally, IIUC the FormAuthenticator will call session.setAttribute(__J_AUTHENTICATED, form_cred) every time authentication is done (see line 365 of FormAuthenticator). In a clustered environment that would be undesirable. It seems to me that although we could tweak things a bit, to make them more efficient, we'd be getting ever farther away from the spec which does not seem to have efficiency as a design goal. Do you agree, or do you have some optimizations in mind? I'm wondering whether we could give the user the choice of security implmentation, but making both jetty "default" security AND jaspi security pluggable alternatives? I've had a brief poke around and I don't think it would take that much to achieve, but at this stage its a thought experiment without code to show. The ideas I've been tossing around to make it pluggable are to modify some of the interfaces of UserIdentity and LoginService and introduce a SecurityManager class to orchestrate things a little: UserIdentity ------------ Principal getUserPrincipal() String getAuthMethod() boolean isUserInRole(String role) setRunAsRole(RunAsToken) setServletHandler(ServletHandler) UserRealm (was LoginService) --------- UserIdentity authenticate (String user, Object credential) boolean reauthenticate (UserIdentity) SecurityManager -------------- UserIdentity authenticate (Request, Response) DefaultSecurityManager //implements SecurityManager ---------------------- JaspiSecurityManager //implements SecurityManager -------------------- AbstractSecurityHandler ---------------------- + setSecurityManager (SecurityManager) The AbstractSecurityHandler would be pretty much unchanged as it is now, except for the addition of a setter and getter for a SecurityManager instance, and the invocation of that manager where it currently invokes JaspiServerAuthentication.validateRequest(...) (around line 169).The DefaultSecurityManager implementation would call the authenticator(Basic, Form, Credential etc) directly, much as the ConstraintSecurityHandler did in the pre-jaspi version.The JaspiSecurityManager implementation would be equivalent to theJaspiServerAuthentication class functionality.Perhaps the biggest change would be to the LoginService, which I'venamed back to UserRealm, simply because its behaviour is more authentication related, rather than strictly login related. No problem thoughto keep the name LoginService if preferred. The authenticate() methodreturns a UserIdentity object, instead of ultimately setting a LoginCallback instance on the Subject (via the ServletCallbackHandler). I don'tsee that as a major problem - the ServletCallbackHandler could set the UserIdentity object on the Subject instead. Note that in a jaspi implementation, I expect that reauthenticate would never be called, orif it was, it would call authenticate() instead. The other issue is the Form, Basic, Digest etc AuthModules.I think we'd need another set for the default jetty implementationthat had no jaspi-style interfaces in it. I think though thatthey should be able to share a majority of code - avoiding duplicationwould be highly desirable.From the user's perspective, it would be simple to configure jaspi:WebAppContext webApp = ...; webApp.getSecurityHandler().setSecurityManager(new JaspiSecurityManager());I'm sure I haven't considered all aspects of pluggability. I'll try and get some time to turn the thoughts into code, which are a) moreeasily comprehended and b) will show up any areas I've neglected. cheers Jan David Jencks wrote:Yup, that's wrong.... should be fixed nowhoping to read your messages carefully before replying in the future,thanks david jencks On Oct 31, 2008, at 12:42 AM, Jan Bartel wrote:Hi David, No, I'm referring to this code:ConstraintSecurityHandler.checkUserDataPermissions line 235 and 259.It is doing a redirect there to get the request to come in again on the right connector (either the confidential or integral port asappropriate). cheers Jan David Jencks wrote:On Oct 30, 2008, at 10:54 PM, Jan Bartel wrote:Hi David, I'll reply to your reply in a later posting. For now, I just noticed something odd in the ConstraintSecurityHandler. If checkUserDataPermissions()notices the request was received on the wrong connector (ie onhttp instead ofhttps) and does a redirect, the AbstractSecurityHandler.handle()method goesahead and subjects the request to JASPI authentication. It seemsto me that at that point we want to stop processing the request altogether. It will be the redirected request that we're interested in processing further (either doing the auth or doing a redirect to a login form).I think you are referring to this code? if (!checkUserDataPermissions(pathInContext, base_request, base_response, constraintInfo)) { if (!base_request.isHandled()) { response.sendError(Response.SC_FORBIDDEN); base_request.setHandled(true); } return; }I think there's something odd here, but IIUC something other thanwhat you see. This is not proposing a redirect, it is plainly denying the request.I've been worrying about this because it prevents redirecting http requests to the equivalent https requests. Until recently I didn't think it was possible to do this redirect using jacc permissionsbut I think there is a solution....If the actual request is denied and is http we could create a newrequest with the url converted to https and checkUserDataPermissions onit.... if that check succeeds we can redirect to the more secureurl. This is somewhat analogous to the way we determine if authentication ismandatory, namely by doing a web resource permission check with theunauthenticated user. I might also have missed what you are looking at... thanks david jenckscheers Jan David Jencks wrote:Hi Jan, On Oct 29, 2008, at 7:37 PM, Jan Bartel wrote:Hi David, I'm still snatching time to tiptoe further around the jaspi branch. A couple of thoughts to run by you:1. UserIdentity and LoginService classnames. These are quasianalogousto UserPrincipal and UserRealm (although the behaviour has beenrefactored).I'm wondering whether it might not be a good idea to retain theold classnames, just so it might be easier for jetty users/developers to ease into understanding the new security structures?I'm not sure that keeping the old names would help anyone understand the new code, I rather think it would be confusing. I'd really rather not call UserIdentity a Principal since it isn't a Principal and depending on the security handler implementation can contain rather different things. The main point of introducing it was that in jetty integrations(Geronimo and from distant memory JBoss) the UserPrincipal wasridiculously overloaded to contain incredible amounts of non-principalinformation associated with the user's identity. I think thatinstead it makes sense to have an object that supplies the UserPrincipal, pluswhatever else the security system needs. I don't have strongobjectionto calling the LoginService UserRealm but I think its going to beconfusing and less informative since it doesn't have the non-login-service methods any more.1a. Actually thinking about this, it will probably be quite important forJetty users to be able to make a smooth transition over to ajaspi-basedimplementation. Do you think we can retain a UserRealm and aUserPrincipal with all their methods intact, but just "blend in" the jaspi-ness with some extra methods and some changed implementations of the existing apis?Maybe. I think the new interfaces are a lot clearer and more descriptive for embedding jetty that the old ones. I could lookinto writing adapters from UserIdentity to UserPrincipal and LoginService toUserRealm but I'm not entirely sure it will work. In particularI'm not at all sure the non login-service methods on UserRealm could plausibly be called.2. We allow a UserRealm to be explicitly set on a WebAppContext(well, strictly speaking itsWebAppContext .getSecurityHandler().setUserRealm(UserRealm)). I couldn't see specific support for that, only getting a list of LoginServices from the Server instance. Should be easy enough toput in though?I'm not sure how my code is different, except the LoginService isfinal and set in the constructor of ServletCallbackHandler, around line 1042 of WebXmlConfiguration. I don't recall changing this code much...3. With the JAAS stuff, which has its own set of callbacks it uses to obtain info, we used a DefaultCallbackHandler to plug in the right info, such as credentials, passwords, usernames and also extra request parameters from the login. I notice you'reusing an anonymous CallbackHandler instead to pass into the JAAS LoginContext.Is it possible to use the DefaultCallbackHandler instead? Itsupports a couple more callback types that some LoginModule implementations may depend on.I could misunderstand the DefaultCallbackHandler but I think that the extensions to a user-password callback handler all involve extractingcredentials from the request. In the jaspi architecture this isthe function of the auth module, not the password validation service. A login module that fishes directly in the request ought to be refactoredinto a plain login module that just validates the credentialsand an auth module that extracts the credentials from the message. Despite all the weirdness in jaspi I think this is a good idea and worth enforcing.I guess someone who really really wanted to preserve their loginmodulecould write a subclass of LoginCallback that dealt with request parameters, and a JAASLoginService subclass. This would be madeeasierby factoring out the CallbackHandler creation in JAASLoginServiceinto aprotected method. Looks like I left out some exception handlingthere too :-( I'd rather not encourage this however.4. Minor thing - is there a lot of value in the RunAsToken marker interfaceas opposed to just having a String? The roles and role mappingsarethemselves just Strings, so I was wondering what the utility is?This is an embedding thing also. It's pretty unclear what run-as is actually supposed to mean and how things like supplying the identity fora web service client or other remote call is supposed to work.(If theweb service is supposed to be called as the user, rather than theserver's identity, and you are in a run-as role, what credentials does this run-as-role identity supply????) In Geronimo we represent the run-as role by a Subject obtained by logging into a security realm. So, the geronimo run-as token has this Subject in it. We might want to store a UserIdentity there instead..... anyway I don't thinkconstraining the representation of the run-as identity is wise.BTW remember that the current auth modules implementing BASIC/DIGEST/FORM auth are more or less temporary until we more or lessagree on the main interfaces, at which time I plan to rewritethem in more jetty-friendly form (also after apachecon :-) Many thanks! david jencksbest regards Jan David Jencks wrote:On Oct 16, 2008, at 11:59 PM, Jan Bartel wrote:Hi David,Firstly, let me genuflect in recognition of your extraordinaryefforts for a) reading the spec b) being able to make heads or tails of it c) coming up with an implementation based on it!:-DI'm surpressing the urge to have a bit of rant at yet anotherjcp specthat is at the same time heavy on the verbiage and light oncomprehensibility. Your email was way more informative than what 29 people managed to produce in the spec.Anyway, looking at the code in the jetty-7-jaspi branch, and Iadmitthat so far I've only just had a cursory nosey around, wherewould we integrate the JAAS side of things? Implement a JAASLoginService?see org.mortbay.jetty.plus.jaas in modules/plus/jetty-plus Not sure if it is ideal, it's pretty much a simple modification of the former JAASUserRealmI'll have a deeper look at the code and get back to you withmoreinformed comments. This mail is to re-assure you that yourposthasn't fallen into the void and that we are looking forward tointegrating this into jetty-7 trunk!The main thing to remember might be that the current implementations of built-in security (FORM, BASIC, DIGEST etc) are in jaspi "modules" only until we agree on the jetty api at which point I was thinking to convert them back into more jetty specific code. Of course if you decide you really like jaspi.... :-)Jan PS I love this code-comment in ServletCallbackHandler:* Idiot class required by jaspi stupidity @#*($)#@&^) [EMAIL PROTECTED]&*$@Several parts of the jaspi spec look to me as if they are sort of stuckon at the end when someone realized it was incomplete, and theheavy useof CallbackHandler for two way communication between the jaspimodules and the container strikes me as one such point. thanks david jencks:) David Jencks wrote:Greg and Jan were kind enough to create a branch for me toplay aroundwith a JASPI (Java Authentication Service Provider Interface) integration with jetty and its getting to a point where I'mwilling to talk about it. Code is at https://svn.codehaus.org/jetty/jetty/branches/jetty-7-jaspiJASPI attempts to provide a uniform framework for messagingsystems, both client and server side, to plug in message authentication. On theclient you can add auth info to a request and validate authinfo on a response. On the server you can validate auth info on a request and addauth info to a response. The auth code can conduct arbitrarymessageexchanges to negotiate what info is needed and transmit theinfo. I've been working on the server side auth for jetty.The actual spec jaspi interfaces are not 100% ideal for httpand don't allow stuff like lazy authentication for unsecured resources so I'vecome up with interfaces similar in spirit to the jaspi ones.I've also tried to rework the implementation so it is morefriendly tointegration with other app servers with their own ideas aboutsecurity frameworks such as geronimo and in particular make jacc implementations easier. I expect these changes will also simplify integration with e.g.jboss and glassfish but I haven't seriously tried to verifythis. Currently all the authentication code (replacing the *Authenticator classes) is implemented in terms of jaspi but I plan to change this soon to use the jetty specific interfaces directly.So.... lets follow a HttpServletRequest/Response pair on itsvoyage through the security system...... it arrives at AbstractSecurityHandler.handle. This is atemplate method that runs through the following structure calling out to subclasses and the authentication system: 1. calls checkUserDataPermissions(pathInContext, base_request,base_response, constraintInfo). This checks the user dataconstraints,basically that the request arrived over the right kind ofconnection(http/https). Two obvious implementations of this are theexistingjetty constraint based implementation or one based on JACC.2. calls isAuthMandatory(base_request, base_response, constraintInfo) to determine if the request actually needs authentication. If it does notwe can often delay authentication until a method relying onauth resultsis called (such as getUserPrincipal or isUserInRole). Againthis can be implemented using constraints or JACC. 3. packs the request, response, and authManditory into aJettyMessageInfo holder object which can also pass variousauth info in a map. 4. delegates the authentication to the jaspi-like ServerAuthResult authResult = serverAuthentication.validateRequest(messageInfo);assuming we are not doing lazy auth, this will extract thecredentialsfrom the request (possibly conducing a multi-message exchangewith the client to request the credentials) and validate them.Validation can use a LoginService possibly provided to the ServerAuthentication which could be JAAS, Hash, JDBC, etcetc. Lazy auth results in returning a lazy result that only attemptsauthentication when info is actually needed. In this case nomessage exchange with the client is possible. <<<<<<<<<<<<<<<<<<<<5. Assuming that authentication succeeded (this includes thelazy case where the request would be allowed even without authentication), we wrap up the result in an identity delegate:UserIdentity userIdentity = newUserIdentity(authResult);base_request.setUserIdentity(userIdentity); The UserIdentity is the delegate for run-as role implementation and actually answering auth questions from the application program. Thisallows app servers to handle run-as roles however they want.6. Assuming authentication is mandatory, now that we know theuser, we can find out if they are in the appropriate roles: checkWebResourcePermissions(pathInContext, base_request, base_response, constraintInfo, userIdentity) 7. On success, we can actually handle the request: getHandler().handle(pathInContext, messageInfo.getRequestMessage(), messageInfo.getResponseMessage(), dispatch);8. Assuming no exceptions were thrown, we can now secure theresponse (normally a no-op for http):serverAuthentication.secureResponse(messageInfo, authResult);------------------------------------------- JASPI implementationsI wrote a fairly complete jaspi framework implementation forgeronimo(rather than the bits actually needed for http which I wrotefor jetty) and have a nearly-untested openid implementation. This (theoretically)lets you openid-enable your app by supplying an appropriatelogin page and useing the openid auth module. Theres also a glassfish implementation that I haven't looked at and someone wrote a SPNEGO auth module that works with it. http://spnego.ocean.net.au/ -------------------------------------------- How does this differ from what's there now?SecurityHandler: AbstractSecurityHandler now just has thebasicworkflow described about and delegates all actual work toeither subclasses (for authorization decisions and object creation) or the authentication delegate. This makes it easy to plug in alternate implementations such as a JACC implementation for an EE server.Authentication results and run-as roles: Formerly these wereeitherdirectly set in the request (possibly using lazy evaluation,with codeagain in Request) or stuffed into a Principal implementationvia theUserRealm. This really overloaded the idea of a Principalfor no apparent reason and made integration into app servers slightlyconvoluted. This is replaced with a UserIdentity interfaceprovidingseparate access to the auth results (user principal) and rolehandling (isUserInRole, and run-as handling). Subclasses of AbstractSecurityHandler can provide their own implementations of thisinterface. These typically delegate to implementations of ServerAuthResult, which can handle lazy authentication ifnecessary.UserRealm IMO glues together a lot of unrelated functions,primarily therole handling code now in UserIdentity and the credentialvalidation now in LoginService. Credential validation may not even be needed by theserver (e.g. openid). If needed it's called from somethingthatextracts credentials from the request. Implementations aregoing to do something like look up the user in a file or table or delegate to JAAS.On the other hand the role handling is called by jetty or bytheapplication and the implementation is done by the app server(jetty or e.g. geronimo). Aside from being related somehow to security, these are totally unrelated concerns. -------------------------------------------------- How does ServerAuthentication and LoginService relate to JASPI? The JASPI interface similar to ServerAuthentication is ServerAuthContext:void cleanSubject(MessageInfo messageInfo, Subject subject)throws AuthException;AuthStatus secureResponse(MessageInfo messageInfo, SubjectserviceSubject) throws AuthException;AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException;The main difference is that ServerAuthentication packagesall theresults into a ServerAuthResult object rather than modifyingtheclientSubject directly and hiding user principal and groupinfo in somecallback handers. This lets ServerAuthentication supportlazy auth.As far as configuration goes. you get a ServerAuthContext bycalling awhole lotta methods on some other stuff. or.... you can justcreate one and stuff it into an adapter, JaspiServerAuthentication. Probably we want to implement the built in auth methods as directServerAuthentication implementations rather than the currentServerAuthModule implementations (a ServerAuthContext is supposed todelegate to one or more ServerAuthModules, which have thesame interface).LoginService is a pretty straightforward way of asking forpasswordvalidation and getting some info back. JASPI has a peculiarIMO systembased on Callbacks. The container (jetty) supplies the authcontext with a CallbackHandler that enables bi-directional communication. Callbacks providing services to the auth module:PasswordValidationCallback: this lets the auth module ask forpassword validation: this is the closest to LoginService.CertStoreCallback, PrivateKeyCallback, SecretKeyCallback, andTrustStoreCallback all let the auth module ask for certificate services. AFAICT these are mostly for securing response messages, which is typically not done for http.Callbacks letting the auth module pass info to the server: CallerPrincipalCallback: supplies the caller principal sogetCallerPrincipal can return something. GroupPrincipalCallback supplies "groups" the user may be in. The meaning here is rather undefined but can be mapped to roles in some way, such as by assuming the groups and roles are the same.The use of callbacks here still seems rather weird to me butmay make more sense in the context of other messaging systems: jaspi is supposedto be applicable to all sorts of messaging, including ejbcalls, jms, web services, etc etc. I've put the caller principal and groups into the ServerAuthResultobject where they can be accessed directly (although possiblydetermined lazily). -------------------------------------------------------------- Comments...Right now it looks to me as if form auth needs to be non-lazysince part of the message exchange involves a request to j_security_check which isnormally not a secured response. Trying to evaluate authfor thislazily doesn't work... you never get back to the originalrequest.I don't see how this implementation could be significantlysimplified or sped up.... I'm certainly willing to look at problems. I've been discussing JACC with Greg for a long time now. The only thingI can see that is possible with constraint implementationsthat is not possible with jacc is redirecting an http request to the "equivalent"https request if a user data constraint is violated. I'mcurious aboutwhether this is something people want to do or usually setup. Many thanks, david jencks --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email-- Jan Bartel, Webtide LLC | [EMAIL PROTECTED] | http://www.webtide.com --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email--------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email-- Jan Bartel, Webtide LLC | [EMAIL PROTECTED] | http://www.webtide.com--------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email-- Jan Bartel, Webtide LLC | [EMAIL PROTECTED] | http://www.webtide.com--------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email-- Jan Bartel, Webtide LLC | [EMAIL PROTECTED] | http://www.webtide.com --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email--------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email-- Jan Bartel, Webtide LLC | [EMAIL PROTECTED] | http://www.webtide.com --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email--------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email--------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email-- Jan Bartel, Webtide LLC | [EMAIL PROTECTED] | http://www.webtide.com --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email--------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email-- Jan Bartel, Webtide LLC | [EMAIL PROTECTED] | http://www.webtide.com
