lennartsandersson | 10 Sep 10:11 2010
Picon

Client fails to access EWS for Exchange 2007/2010 due to authentication issue

I have written a small client program (based on latest gSOAP 2.7) that is trying to access the Exchange Web Services (EWS) interface.
It is compiled with flags WITH_OPENSSL, WITH_COOKIES and WITH_NONAMESPACES.
The problem is, no matter what I try, the generated HTTP request fails due to some authentication issue in the Exchange server.

On the other hand, IE can access EWS without authentication issues when logged on to the Exchange server with the same credentials as the client program is using.  Accessing https://<server>.<domain>/EWS/Exchange.asmx in the browser opens WSDL file https://<server>.<domain>/EWS/Service.wsdl without asking for user credentials.

Has anyone run into this prob lem before?
What is wrong with the credentials that I'm supplying via the client program?
Do I need to do something else (gSOAP related or not) in the client program, or is it an IIS/Exchange configuration issue, or both?

Configuration

Exchange 2007 Server on Windows 2003
Installed self-signed certificate, generated during Exchange installation
Logged on as Administrator under the domain where Exchange is installed

Configuration of IIS -> (local computer) -> Web Sites -> Default Web Site -> EWS in IIS Manager:
Basic or Integrated Windows authentication selected (see results for each case below)
Require SSL + Ignore client certificates s elected

gSOAP-based client program

The client program, running on the Exchange Server machine itself, does the following:

1. Logon as Administrator in domain testdomain.lab with LogonUserW()
2. Impersonate this user with ImpersonateLoggedOnUser()
3. Initialize gSOAP client context with SOAP_SSL_NO_AUTHENTICATION using soap_ssl_client_context()
4. Call the gSOAP function that invokes the FindItem Exchange Web Services (EWS) operation, wrapped in HTTP/SOAP/XML

The test client output show that LogonUserW(), ImpersonateLoggedOnUser() and soap_ssl_client_context() all complete successfully.
The problem is that #4 is never executed because the HTTP request fails due to some authentication issue in the Exchange server.

I also got the following SSL-related error/warning message when soap_call___ns1__FindItem() is called:

"SSL verify error or warning with certificate at depth 0: unable to get local issuer certificate
 certificate issuer /CN=ex07-64-hub
 certificate subject /CN=ex07-64-hub"

I assume this should be interpreted as a benign warning because we're using a self-signed certificate.  Is that correct?

Client program source code

int main(int argc, char *argv[])
{
    struct soap *pSoap = NULL;

    UChar pustrUsername[20] = {L"Administrator"};
    UChar pustrPassword[20] = {L"xxxxxxxx"};
    UChar pustrDomain[20]   = {L"testdomain.lab"};

    char pstrUserid[20] = {"Administrator"};
    char pstrPasswd[20] = {"xxxxxxxx"};

    AgentAuthenticateUser(pustrUsername,pustrPassword,pustrDomain);

    pSoap = soap_new();
    //pSoap->userid = pstrUserid;
    //pSoap->passwd = pstrPasswd;

    soap_set_namespaces(pSoap,ews_namespaces);
    soap_ssl_init();

    if (SOAP_OK == soap_ssl_client_context(pSoap,
                                                 SOAP_SSL_NO_AUTHENTICATION,
                                                 NULL,NULL,NULL,NULL,NULL))
    {
        char pstrFqdn[100] = {"https://ex07-64-hub.testdomain.lab/ews/exchange.asmx"};

        struct ns1__FindItemType  request;
        struct __ns1__FindItemResponse    response;
        struct ns3__ItemResponseShapeType  itemShape;
        struct ns3__NonEmptyArrayOfBaseFolderIdsType  parentFolderIds;
        struct ns3__FolderIdType  folderId;
        struct ns3__DistinguishedFolderIdType  inbox;

        printf("Initialized soap client context\n");

        memset(&request,0,sizeof(request));
        memset(&response,0,sizeof(response));
        memset(&itemShape,0,sizeof(itemSha pe));
        memset(&parentFolderIds,0,sizeof(parentFolderIds));
        memset(&folderId,0,sizeof(folderId));
        memset(&inbox,0,sizeof(inbox));

        itemShape.BaseShape = ns3__DefaultShapeNamesType__Default;
        request.ItemShape = &itemShape;
        inbox.Id = ns3__DistinguishedFolderIdNameType__inbox;
        parentFolderIds.DistinguishedFolderId = &inbox;
        request.ParentFolderIds = &parentFolderIds;
        request .Traversal = ns3__ItemQueryTraversalType__Shallow;

        if (SOAP_OK == soap_call___ns1__FindItem(pSoap,pstrFqdn,"",&request,&response))
        {
            printf("Item found!\n");
        }
        else
        {
            printf("Failed to find item\n");
            printf("\nSOAP Fault:\n\n");
            soap_print_fault(pSoap, stderr);
        }
   &n bsp;}
    else
    {
        printf("Failed to initialize soap client context\n");
    }
}

Basic authentication (with soap struct members 'userid' and 'passwd' set in client program)

HTTP request, generated by gSOAP:

POST /ews/exchange.asmx HTTP/1.1
Host: ex07-64-hub.testdomain.lab
User-Agent: gSOAP/2.7
Content-Type: text/xml; charset=utf-8
Content-Length: 859
Connection: close
Authorization: Basic QWRtaW5pc3RyYXRvcjpsZXRtZWluQDIwMTA=
SOAPAction: ""

<?xml version="1.0" encoding="UTF-8"? >
<SOAP-ENV:Envelope 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:ns3="http://schemas.microsoft.com/exchange/services/2006/types" 
xmlns:ns1="http://schemas.microsoft.com/exchange/services/2006/messages">
<SOAP-ENV:Body>
<ns1:FindItem Traversal="Shallow">
<ns1:ItemShape xsi:type="ns3:ItemResponseShapeType">
<ns3:BaseShape xsi:type="ns3:DefaultShapeNamesType">Default</ns3:BaseShape>
</ns1:ItemShape>
<ns1: ParentFolderIds xsi:type="ns3:NonEmptyArrayOfBaseFolderIdsType">
<ns3:DistinguishedFolderId xsi:type="ns3:DistinguishedFolderIdType" Id="inbox">
</ns3:DistinguishedFolderId>
</ns1:ParentFolderIds>
</ns1:FindItem>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

HTTP response (HTML formatting removed to improve readability):

HTTP/1.1 401 Unauthorized
Content-Length: 1539
Content-Type: text/html
Server: Microsoft-IIS/6.0
WWW-Authenticate: Basic realm="ex07-64-hub.testdomain.lab"
X-Powered-By: ASP.NET
Date: Thu, 09 Sep 2010 19:08:09 GMT
Connection: close

You are not authorized to view this page
You do not have permission to view this directory or page using the credentials that you supplied.
HTTP Error 401.1 - Unauthorized: Access is denied due to invalid credentials.
Internet Information Services (IIS)

NTLM authentication (with soap struct members 'userid' and 'passwd' NOT set in client program)

HTTP request, generated by gSOAP:

POST /ews/exchange.asmx HTTP/1.1
Host: ex07-64-hub.testdomain.lab
User-Agent: gSOAP/2.7
Content-Type: text/xml; charset=utf-8
Content-Length: 859
Connection: close
SOAPAction: ""

<<< The SOAP Envelope t hat goes here is identical to the one in the example above >>>

HTTP response (HTML formatting removed to improve readability):

HTTP/1.1 401 Unauthorized
Content-Length: 1656
Content-Type: text/html
Server: Microsoft-IIS/6.0
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
Date: Thu, 09 Sep 2010 22:27:19 GMT
Connection: close

You are not authorized to view this page
You do not have permission to view this directory or page using the credentials that you supplied because your Web browser is sending a WWW-Authenticate header field that the Web server is not configured to accept.
HTTP Error 401.2 - Unauthorized: Access is denied due to server configuration.
Internet Information Services (IIS)



__._,_.___


Your email settings: Individual Email|Traditional
Change settings via the Web (Yahoo! ID required)
Change settings via email: Switch delivery to Daily Digest | Switch to Fully Featured
Visit Your Group | Yahoo! Groups Terms of Use | Unsubscribe

__,_._,___
Brad Hards | 10 Sep 12:01 2010
Picon

Re: Client fails to access EWS for Exchange 2007/2010 due to authentication issue

On Friday, September 10, 2010 06:11:59 pm lennartsandersson wrote:
> I have written a small client program (based on latest gSOAP 2.7) that
> is trying to access the Exchange Web Services (EWS) interface.It is
> compiled with flags WITH_OPENSSL, WITH_COOKIES and WITH_NONAMESPACES.The
> problem is, no matter what I try, the generated HTTP request fails due
> to some authentication issue in the Exchange server.
I had some success by enabling only Basic authentication. My code looks
kind-of like this:
#include "soapExchangeServiceBindingProxy.h"
#include "ExchangeServiceBinding.nsmap"

static _ns2__RequestServerVersion requestServerVersion;
static bool getFullTimeZone( true );

int main()
{
    ExchangeServiceBindingProxy service;

    if (soap_register_plugin(&service, logging)) {
        soap_print_fault(&service, stderr);
    }

    struct logging_data *logdata = (struct logging_data*)soap_lookup_plugin(&service, logging_id);
    logdata->inbound = stdout;
    logdata->outbound = stdout;

    service.soap_endpoint = "https://win-snt3rtn45is.phillip.local/EWS/Exchange.asmx";
    service.userid = "testuser1";
    service.passwd = "tusa%0001";
    service.ssl_flags = SOAP_SSL_NO_AUTHENTICATION;

    requestServerVersion.Version = ns2__ExchangeVersionType__Exchange2010;

    service.soap_header( 0, &requestServerVersion, 0 );

    ns1__GetServerTimeZonesType request;
    request.ReturnFullTimeZoneData = &getFullTimeZone;
    struct __ns1__GetServerTimeZonesResponse response;

    if (service.GetServerTimeZones(&request, response) == SOAP_OK) {
        std::cout << "Success! Response:" << std::endl;
        // much more parsing of the output here.
    }
}

> On the other hand, IE can access EWS without authentication issues when
> logged on to the Exchange server with the same credentials as the client
> program is using.  Accessing https://<server>.<domain>/EWS/Exchange.asmx
> in the browser opens WSDL file
> https://<server>.<domain>/EWS/Service.wsdl without asking for user
> credentials.
That probably isn't equivalent (e.g. GET vs POST). Also, if the browser is on a machine
that is joined to the domain, it might do things under the covers.

> Has anyone run into this problem before?What is wrong with the
> credentials that I'm supplying via the client program?Do I need to do
> something else (gSOAP related or not) in the client program, or is it an
> IIS/Exchange configuration issue, or both?
To make it work properly, we'll probably need NTLM (or Negotiate) support.
I've started to look at this, but I have no idea how to do this from a plugin,
because I can't see howmake the "same" call with different authentication
arguments.

> NTLM authentication (with soap struct members 'userid' and 'passwd' NOT
> set in client program)
How are you providing NTLM auth?

Also, you might like to look at the server logs.

Brad

------------------------------------

Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/gsoap/

<*> Your email settings:
    Individual Email | Traditional

<*> To change settings online go to:
    http://groups.yahoo.com/group/gsoap/join
    (Yahoo! ID required)

<*> To change settings via email:
    gsoap-digest@... 
    gsoap-fullfeatured@...

<*> To unsubscribe from this group, send an email to:
    gsoap-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/

lennartsandersson | 10 Sep 22:08 2010
Picon

Re: Client fails to access EWS for Exchange 2007/2010 due to authentication issue

--- In gsoap@..., Brad Hards <bradh <at> ...> wrote:
>
> On Friday, September 10, 2010 06:11:59 pm lennartsandersson wrote:
> > I have written a small client program (based on latest gSOAP 2.7) that
> > is trying to access the Exchange Web Services (EWS) interface.It is
> > compiled with flags WITH_OPENSSL, WITH_COOKIES and WITH_NONAMESPACES.The
> > problem is, no matter what I try, the generated HTTP request fails due
> > to some authentication issue in the Exchange server.
> I had some success by enabling only Basic authentication. My code looks
> kind-of like this:
> #include "soapExchangeServiceBindingProxy.h"
> #include "ExchangeServiceBinding.nsmap"
> 
> static _ns2__RequestServerVersion requestServerVersion;
> static bool getFullTimeZone( true );
> 
> int main()
> {
>     ExchangeServiceBindingProxy service;
> 
>     if (soap_register_plugin(&service, logging)) {
>         soap_print_fault(&service, stderr);
>     }
>     
>     struct logging_data *logdata = (struct logging_data*)soap_lookup_plugin(&service, logging_id);
>     logdata->inbound = stdout;
>     logdata->outbound = stdout;
> 
>     service.soap_endpoint = "https://win-snt3rtn45is.phillip.local/EWS/Exchange.asmx";
>     service.userid = "testuser1";
>     service.passwd = "tusa%0001";
>     service.ssl_flags = SOAP_SSL_NO_AUTHENTICATION;
>     
>     requestServerVersion.Version = ns2__ExchangeVersionType__Exchange2010;
> 
>     service.soap_header( 0, &requestServerVersion, 0 );
> 
>     ns1__GetServerTimeZonesType request;
>     request.ReturnFullTimeZoneData = &getFullTimeZone;
>     struct __ns1__GetServerTimeZonesResponse response;
> 
>     if (service.GetServerTimeZones(&request, response) == SOAP_OK) {
>         std::cout << "Success! Response:" << std::endl;
>         // much more parsing of the output here.
>     }
> }
> 
Thanks Brad for the quick response. I'll try this and let you know if I have further questions.

> > NTLM authentication (with soap struct members 'userid' and 'passwd' NOT
> > set in client program)
> How are you providing NTLM auth?
> 
All I meant here is that I set the authentication in IIS for EWS to Integrated Windows authentication to see
what result I would get. I have no idea how to make that work. For now, I just happy to try to make it work using
Basic authentication per your suggestion above.

------------------------------------

Yahoo! Groups Links

<*> To visit your group on the web, go to:
    http://groups.yahoo.com/group/gsoap/

<*> Your email settings:
    Individual Email | Traditional

<*> To change settings online go to:
    http://groups.yahoo.com/group/gsoap/join
    (Yahoo! ID required)

<*> To change settings via email:
    gsoap-digest@... 
    gsoap-fullfeatured@...

<*> To unsubscribe from this group, send an email to:
    gsoap-unsubscribe@...

<*> Your use of Yahoo! Groups is subject to:
    http://docs.yahoo.com/info/terms/


Gmane