My favorites | Sign in
Project Home Downloads Source
READ-ONLY: This project has been archived. For more information see this post.
Search
for
  Advanced search   Search tips   Subscriptions
Issue 137: Eclipse Plugin Enhancement: Allow username/password to be passed as part of webservice call.
1 person starred this issue and may be notified of changes. Back to list
Status:  Fixed
Owner:  marc.es...@gmail.com
Closed:  Mar 2009


 
Reported by nmis...@gmail.com, Aug 7, 2008

It would be nice to be able to pass the username/password as part of the
RemoteFacade webservice call from Eclipse. This would allow users who can't
put the RemoteFacade behind basic auth to secure the webservice. See:
http://groups.google.com/group/mxunit/browse_thread/thread/e384cb7779678e9b
Aug 7, 2008
Project Member #1 marc.es...@gmail.com
thanks nathan! OK, so, before we go down the "change the api and have it pass
usernames/passwords across the wire", let's figure out if there's a way to do this
with the existing stuff built in.

first, can you explain what exactly the security risk is in the first place by having
the "empty" remotefacade.cfc not behind your ntlm security? what does this expose
that would be "bad"?
Aug 7, 2008
#2 nmis...@gmail.com
Hey Marc, the more I think about this the more I realize this is an organizational
issue I need to deal with on my end. For the record there is a way to do it with the
existing stuff built in, just use basic auth over SSL. (I haven't tried it, but if
basic auth works in the plugin I'm assuming basic auth over SSL will work as well.) 
The problem is, my server admins are reluctant to enable basic auth as they see it as
a potential security issue, which it could be if not used over SSL. (Usernames and
passwords are sent in clear text.) But again, this is my issue, not yours.

As for the security issues of having a publicly accessible remotefacade.cfc, there
are a few. First malicious users could gain insight into the design of your
application. This obviously depends on your tests, and how useful that information
may be is questionable, but there is the potential to expose a vulnerability via your
tests. (Now I would argue if you are worried about security at all you shouldn't be
developing on a publicly accessible development server, but...)  Second, many of my
unit tests run against the database, and a few are pretty resource intensive. I would
think you could create a DOS attack or just generally mess with someone by pounding
on the remotefacade.cfc. 

The best approach I think would be to have NTLM support, but I realize there are
challenges there.



Aug 7, 2008
Project Member #3 marc.es...@gmail.com
nathan,
  ahhhh, i didn't understand that this was publicly accessible. I thought it was a
dev server inside your own environment. I understand that many government shops, and
military in particular, still require shared dev servers with ntlm auth even though
they're not publicly accessible.
  As for the ntlm authentication, I'm going to assume you're using ntlmv2, and
unfortunately it looks like the only package out there that supports ntlmv2 is an
extremely expensive (5k or so if i remember correctly) package. the stuff in
httpclient, which i'm using in the plugin, only supports ntlmv1, which apparently
noone uses anyway. also from what i remember, the folks at apache working on axis and
httpclient have no intentions at all of providing ntlmv2 support.

a few things to consider if you want to try it out: every time you hit "run" on the
plugin view, here's what happens:

1) plugin calls startTestRun() from the remote facade, which returns a "test run key"
2) plugin passes that test run key back to the framework for every test it calls
3) plugin calls endTestRun() when all tests are complete.

possibly you could hook into this. maybe you change startTestRun() to return a custom
kind of key... instead of just a UUID, maybe it's a UUID + some special key.  then,
in your executeTestCase(), you can look for that special token to be passed in the
testrunkey. if the token isn't present, then throw an error.

this way, even someone who knows that executeTestCase is a method in the framework
wouldn't be able to run it b/c they'd have ot know your special token.

the bad thing here is that that still leaves getComponentMethods() exposed because
that doesn't use any test run key. still... they'd have to be pretty good at guessing
the full path to your objects for this to be useful, and even then what they'd see is
a list of test names returned.

If none of this is sufficient, then we can talk more about passing the login
credentials in every webservice request. i'm not opposed to that since it does make
sense to me. largely the decisions to be made are around the obfuscation of the
credentials... is md5 checksum enough, for example? either case, it couldn't be clear
text, obviously. so it'd have to be encrypted in such a way that on the CF side,
you'd need to be able to encrypt a known set of credentials and compare them with the
encrypted credentials passed over the wire and confirm they match. i.e. not cfif
arguments.password eq "nathanIsCool" but instead cfif arguments.password eq
hash("nathanIsCool")

here though, you'd probably have problems with this in a team environment b/c you'd
need to compare the credentials against a list of people's stuff... unless you just
had a group username/password to use which would make sense in your case.

Let me know if you want to pursue this further!
Owner: marc.esher
Aug 7, 2008
#4 nmis...@gmail.com
I don't think it is necessary to pursue this further. Thanks for entertaining the
idea though.
Aug 7, 2008
Project Member #5 marc.es...@gmail.com
sure thing Nathan. If you change your mind, don't hesitate to post back here!
Aug 7, 2008
#6 nmis...@gmail.com
Marc, I thought about this a little more and basic auth sends the username/password
over the wire for every request, so I just needed to trigger basic auth via
ColdFusion. Placing the attached Application.cfc in the same folder as my "empty"
remotefacade.cfc triggers basic authentication. This should work, however loading the
test methods seems to fail with the following error: "Exception message trying to
connect to url https://seven-dev.wharton.upenn.edu/stat/tests/remotefacade.cfc?wsdl
is: org.xml.sax.SAXParseException: Premature end of file." 

I can get a list of tests, just not a list of methods. Any ideas?
 
Application.cfc
722 bytes   View   Download
Aug 8, 2008
Project Member #7 marc.es...@gmail.com
off the top of my head, no. a few questions though: 

1) is your server a unix server by any chance? possibly you're hitting this bug if it
is: https://code.google.com/p/mxunit/issues/detail?id=138

2) if you hit the remotefacade.cfc?wsdl&method=ping in your browser, does it prompt
you for username and password? and if you type them in, do you get a response?

3) in eclipse, if you go to window -- show view -- PDE Runtime -- Error Log, do you
see any entries in the error log that have any more detail?  

thanks nathan.
Aug 8, 2008
#8 nmis...@gmail.com
1) I'm on windows.

2) Yes I can access the remotefacade.cfc via my browser.  I get a username/password
prompt and after logging in I see the correct headers being sent. 

3) Looking at this log I can see no webservice calls are working. I have errors
similar to:

AxisFault
 faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
 faultSubcode: 
 faultString: org.xml.sax.SAXParseException: Premature end of file.
 faultActor: 
 faultNode: 
 faultDetail: 
	{http://xml.apache.org/axis/}stackTrace:org.xml.sax.SAXParseException: Premature end
of file.
	at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
	at org.apache.xerces.util.ErrorHandlerWrapper.fatalError(Unknown Source)
	at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
	at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
	at org.apache.xerces.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
	at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
	at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
	at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
	at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
	at javax.xml.parsers.SAXParser.parse(SAXParser.java:345)
	at
org.apache.axis.encoding.DeserializationContext.parse(DeserializationContext.java:227)
	at org.apache.axis.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:696)
	at org.apache.axis.Message.getSOAPEnvelope(Message.java:424)
	at org.apache.axis.server.AxisServer.initSOAPConstants(AxisServer.java:345)
	at org.apache.axis.server.AxisServer.invoke(AxisServer.java:279)
	at org.apache.axis.transport.http.AxisServlet.doPost(AxisServlet.java:699)
	at coldfusion.xml.rpc.CFCServlet.doAxisPost(CFCServlet.java:163)
	at coldfusion.filter.AxisFilter.invoke(AxisFilter.java:43)
	at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:219)
	at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:51)
	at coldfusion.filter.PathFilter.invoke(PathFilter.java:86)
	at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:69)
	at
coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28)
	at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38)
	at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22)
	at coldfusion.xml.rpc.CFCServlet.invoke(CFCServlet.java:106)
	at coldfusion.xml.rpc.CFCServlet.doPost(CFCServlet.java:182)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
	at org.apache.axis.transport.http.AxisServletBase.service(AxisServletBase.java:327)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
	at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:78)
	at jrun.servlet.ServletInvoker.invoke(ServletInvoker.java:91)
	at jrun.servlet.JRunInvokerChain.invokeNext(JRunInvokerChain.java:42)
	at jrun.servlet.JRunRequestDispatcher.invoke(JRunRequestDispatcher.java:259)
	at jrun.servlet.ServletEngineService.dispatch(ServletEngineService.java:541)
	at jrun.servlet.jrpp.JRunProxyService.invokeRunnable(JRunProxyService.java:204)
	at jrunx.scheduler.ThreadPool$ThreadThrottle.invokeRunnable(ThreadPool.java:428)
	at jrunx.scheduler.WorkerThread.run(WorkerThread.java:66)

	{http://xml.apache.org/axis/}hostname:xxxxxxxxxxxxxxxxxxxxxxx


I'm actually testing with the getServerType method and one thing I have noticed,
accessing the remotefacade via my browser uses a HTTP GET  request. The eclipse
plugin uses a HTTP/XML POST and ColdFusion seems to choke on this. The error message
above (Premature end of file) is actually being return by ColdFusion.


Aug 8, 2008
Project Member #9 marc.es...@gmail.com
hey nathan, in the mxunit/samples directory there's a file named
"RemoteFacadeTester.cfm". Can you open that up, plop your URL into there, add your
username/password to the cfinvoke tag, and see what you get?
Aug 8, 2008
#10 nmis...@gmail.com
I get the same error:

 Cannot perform web service invocation executeTestCase.
The fault returned when invoking the web service operation is:

AxisFault
 faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
 faultSubcode: 
 faultString: org.xml.sax.SAXParseException: Premature end of file.
 faultActor: 
 faultNode: 
 faultDetail: 
	{http://xml.apache.org/axis/}stackTrace:org.xml.sax.SAXParseException: Premature end
of file.
	at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
	at org.apache.xerces.util.ErrorHandlerWrapper.fatalError(Unknown Source)
	at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
	at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
	at org.apache.xerces.impl.XMLVersionDetector.determineDocVersion(Unknown Source)
	at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
	at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
	at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
	at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
	at javax.xml.parsers.SAXParser.parse(SAXParser.j... ''

 
The error occurred in C:\inetpub\wwwroot\mxunit\samples\RemoteFacadeTester.cfm: line 34

32 : <!--- now run that same component using the remote facade --->
33 : <h1>running test through remote facade</h1>
34 : <cfinvoke webservice="#remoteURL#" method="executeTestCase"
componentName="#mycomponent#" methodNames="#myfunction#" TestRunKey=""
returnvariable="remoteRunResults" username="username" password="password">
35 : 
36 : <cfdump var="#remoteRunResults#" label="remoteRunResults" expand="false">

Aug 8, 2008
Project Member #11 marc.es...@gmail.com
whew. i was hoping you'd say that! Because that means it's not a plugin problem per se.

now, as to figure out how to figure it out... do you have any tcp monitoring tools? I
think the thing is we need to see the stuff going back and forth over the wire. can
you do that?
Aug 8, 2008
#12 nmis...@gmail.com
It is definitely not a plugin problem. I've already looked at the HTTP traffic using
Wireshark and it looks fine. The problem seems to be with ColdFusion. If I call the
GetHttpRequestData() function in either Application.cfm or Application.cfc's
onRequestStart method ColdFusion chokes on the HTTP/XML POST. If I take the call to
GetHttpRequestData() it works fine.

This works:

<cffunction name="onRequestStart" returnType="boolean" output="true">
    <cfargument type="String" name="targetPage" required=true/>
    <cfset var requestData = "" />	
    <cfreturn true />
</cffunction>

This fails:

<cffunction name="onRequestStart" returnType="boolean" output="true">
    <cfargument type="String" name="targetPage" required=true/>
    <cfset var requestData = GetHttpRequestData() />
    <cfreturn true />
</cffunction>


Aug 8, 2008
#13 nmis...@gmail.com
I don't have time to investigate further at the moment, but I'll be looking into this
some more over the weekend.
Aug 8, 2008
Project Member #14 marc.es...@gmail.com
fascinating.

tell me: is there anything you'd like me to do to help you figure this out?
Aug 8, 2008
Project Member #15 marc.es...@gmail.com
sounds good.
Aug 8, 2008
#16 nmis...@gmail.com
If you know how to get the request header data without using GetHttpRequestData()
that would help. If you don't know how to do that off the top of your head I can look
it up. 

I'll definitely let you know what I find out.
Aug 8, 2008
Project Member #17 marc.es...@gmail.com
i believe you can use getSoapRequestHeader() for this.
Aug 8, 2008
#18 nmis...@gmail.com
OK, so it seams calling GetHttpRequestData() causes soap requests to bomb out. The
attached Application.cfc sucessfully implements basic authentication for the
remotefacade.cfc by reading the Authorization HTTP header via GetPageContext(). This
sample has the username and password hardcoded as "username" and "password" but you
could easily modify it to look up credentials wherever you may have them stored.
Note, for basic authentication to be secure you must use it over SSL.

Thanks for your help with this Marc.
Application.cfc
765 bytes   View   Download
Aug 8, 2008
Project Member #19 marc.es...@gmail.com
nice! So you're all set then?
Aug 8, 2008
#20 nmis...@gmail.com
Yep.
Mar 28, 2009
Project Member #21 marc.es...@gmail.com
(No comment was entered for this change.)
Status: Fixed

Powered by Google Project Hosting