[CalendarServer-changes] [4593] PyOpenDirectory/branches/users/gaya/addigestauth
source_changes at macosforge.org
source_changes at macosforge.org
Fri Oct 16 16:31:55 PDT 2009
Revision: 4593
http://trac.macosforge.org/projects/calendarserver/changeset/4593
Author: gaya at apple.com
Date: 2009-10-16 16:31:54 -0700 (Fri, 16 Oct 2009)
Log Message:
-----------
First pass changes for ad digest auth
Modified Paths:
--------------
PyOpenDirectory/branches/users/gaya/addigestauth/pysrc/opendirectory.py
PyOpenDirectory/branches/users/gaya/addigestauth/src/CDirectoryServiceAuth.cpp
PyOpenDirectory/branches/users/gaya/addigestauth/src/CDirectoryServiceAuth.h
PyOpenDirectory/branches/users/gaya/addigestauth/src/PythonWrapper.cpp
PyOpenDirectory/branches/users/gaya/addigestauth/support/PyOpenDirectory.xcodeproj/project.pbxproj
PyOpenDirectory/branches/users/gaya/addigestauth/support/test.cpp
PyOpenDirectory/branches/users/gaya/addigestauth/test_auth.py
Modified: PyOpenDirectory/branches/users/gaya/addigestauth/pysrc/opendirectory.py
===================================================================
--- PyOpenDirectory/branches/users/gaya/addigestauth/pysrc/opendirectory.py 2009-10-16 23:25:33 UTC (rev 4592)
+++ PyOpenDirectory/branches/users/gaya/addigestauth/pysrc/opendirectory.py 2009-10-16 23:31:54 UTC (rev 4593)
@@ -71,7 +71,7 @@
@param attr: C{str} containing the attribute to search.
@param value: C{str} containing the value to search for.
@param matchType: C{int} DS match type to use when searching.
- @param casei: C{True} to do case-insenstive match, C{False} otherwise.
+ @param casei: C{True} to do case-insensitive match, C{False} otherwise.
@param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
@param attributes: C{list} or C{tuple} containing the attributes to return for each record.
@param count: C{int} maximum number of records to return (zero returns all).
@@ -87,7 +87,7 @@
@param obj: C{object} the object obtained from an odInit call.
@param compound: C{str} containing the compound search query to use.
- @param casei: C{True} to do case-insenstive match, C{False} otherwise.
+ @param casei: C{True} to do case-insensitive match, C{False} otherwise.
@param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
@param attributes: C{list} or C{tuple} containing the attributes to return for each record.
@param count: C{int} maximum number of records to return (zero returns all).
@@ -119,7 +119,7 @@
@param attr: C{str} containing the attribute to search.
@param value: C{str} containing the value to search for.
@param matchType: C{int} DS match type to use when searching.
- @param casei: C{True} to do case-insenstive match, C{False} otherwise.
+ @param casei: C{True} to do case-insensitive match, C{False} otherwise.
@param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
@param attributes: C{list} or C{tuple} containing the attributes to return for each record.
@param count: C{int} maximum number of records to return (zero returns all).
@@ -135,7 +135,7 @@
@param obj: C{object} the object obtained from an odInit call.
@param compound: C{str} containing the compound search query to use.
- @param casei: C{True} to do case-insenstive match, C{False} otherwise.
+ @param casei: C{True} to do case-insensitive match, C{False} otherwise.
@param recordType: C{str}, C{tuple} or C{list} containing the OD record types to lookup.
@param attributes: C{list} or C{tuple} containing the attributes to return for each record.
@param count: C{int} maximum number of records to return (zero returns all).
@@ -166,7 +166,27 @@
@param method: C{str} the HTTP method being used.
@return: C{True} if the user was found, C{False} otherwise.
"""
+def authenticateUserDigestToActiveDirectory(obj, nodename, user, response):
+ """
+ Authenticate using HTTP Digest credentials to an Active Directory node,
+ exported by Open Diretory
+
+ @param obj: C{object} the object obtained from an odInit call.
+ @param nodename: C{str} the directory nodename for the record to check.
+ @param user: C{str} the user identifier/directory record name to check.
+ @param response: C{str} the HTTP response sent from the client.
+ @return: C{True} if the user was found, C{False} otherwise.
+ """
+def getDigestMD5ChallengeFromActiveDirectory(obj, nodename):
+ """
+ Get an DigestMD5 challenge from Active Directory
+
+ @param obj: C{object} the object obtained from an odInit call.
+ @param nodename: C{str} the directory nodename for the record to check.
+ @return: C{string} containing the challenge
+ """
+
class ODError(Exception):
"""
Exceptions from DirectoryServices errors.
Modified: PyOpenDirectory/branches/users/gaya/addigestauth/src/CDirectoryServiceAuth.cpp
===================================================================
--- PyOpenDirectory/branches/users/gaya/addigestauth/src/CDirectoryServiceAuth.cpp 2009-10-16 23:25:33 UTC (rev 4592)
+++ PyOpenDirectory/branches/users/gaya/addigestauth/src/CDirectoryServiceAuth.cpp 2009-10-16 23:31:54 UTC (rev 4593)
@@ -21,6 +21,11 @@
#include "CDirectoryServiceException.h"
+#ifndef kDSStdAuthSASLProxy
+#define kDSStdAuthSASLProxy "dsAuthMethodStandard:dsAuthSASLProxy"
+#endif
+#define kSASLDIGESTMD5 "DIGEST-MD5"
+
#pragma mark -----Public API
CDirectoryServiceAuth::CDirectoryServiceAuth() :
@@ -39,7 +44,7 @@
// Authenticate a user to the directory using plain text credentials.
//
// @param nodename: the directory nodename for the user record.
-// @param user: the uid of the user.
+// @param user: the identifier/directory record name of the user.
// @param pswd: the plain text password to authenticate with.
// @return: true if authentication succeeds, false otherwise.
//
@@ -72,6 +77,7 @@
// Authenticate a user to the directory using HTTP DIGEST credentials.
//
// @param nodename: the directory nodename for the user record.
+// @param user: the identifier/directory record name of the user.
// @param challenge: HTTP challenge sent by server.
// @param response: HTTP response sent by client.
// @return: true if authentication succeeds, false otherwise.
@@ -100,6 +106,72 @@
}
}
+// AuthenticateUserDigestToActiveDirectory
+//
+// Authenticate a user to the directory using SASL Digest credentials.
+//
+// @param nodename: the directory nodename for the user record.
+// @param user: the identifier/directory record name of the user.
+// @param response: HTTP response sent by client.
+// @return: true if authentication succeeds, false otherwise.
+//
+bool CDirectoryServiceAuth::AuthenticateUserDigestToActiveDirectory(const char* nodename, const char* user, const char* response, bool& result, bool using_python)
+{
+ try
+ {
+ StPythonThreadState threading(using_python);
+
+ result = NativeAuthenticationSASLDigestToNode(nodename, user, response);
+ return true;
+ }
+ catch(CDirectoryServiceException& dserror)
+ {
+ if (using_python)
+ dserror.SetPythonException();
+ return false;
+ }
+ catch(...)
+ {
+ CDirectoryServiceException dserror;
+ if (using_python)
+ dserror.SetPythonException();
+ return false;
+ }
+}
+
+
+// GetDigestMD5ChallengeFromActiveDirectory
+//
+// Authenticate a user to the directory using SASL Digest credentials.
+//
+// @param nodename: the directory nodename for the user record.
+// @return: challange as CFStringRef
+//
+CFStringRef CDirectoryServiceAuth::GetDigestMD5ChallengeFromActiveDirectory(const char* nodename, bool using_python)
+{
+ try
+ {
+ StPythonThreadState threading(using_python);
+ CFStringRef challenge = NULL;
+ (void) NativeAuthenticationSASLDigestToNode(nodename, "anonymous", "", &challenge);
+ return challenge;
+ }
+ catch(CDirectoryServiceException& dserror)
+ {
+ if (using_python)
+ dserror.SetPythonException();
+ return NULL;
+ }
+ catch(...)
+ {
+ CDirectoryServiceException dserror;
+ if (using_python)
+ dserror.SetPythonException();
+ return NULL;
+ }
+}
+
+
#pragma mark -----Private API
// NativeAuthenticationBasicToNode
@@ -107,7 +179,7 @@
// Authenticate a user to the directory.
//
// @param nodename: the node to authenticate to.
-// @param user: the uid of the user.
+// @param user: the identifier/directory record name of the user.
// @param pswd: the plain text password to authenticate with.
// @return: true if authentication succeeds, false otherwise.
//
@@ -186,7 +258,7 @@
// Authenticate a user to the directory.
//
// @param nodename: the node to authenticate to.
-// @param user: the uid of the user.
+// @param user: the identifier/directory record name of the user.
// @param challenge: the server challenge.
// @param response: the client response.
// @param method: the HTTP method.
@@ -231,7 +303,7 @@
ThrowIfDSErr(eDSNullDataBuff);
// Fill the buffer
- ::dsFillAuthBuffer(authData, 4,
+ ::dsFillAuthBuffer(authData, ::strlen(method)?4:3,
::strlen(user), user,
::strlen(challenge), challenge,
::strlen(response), response,
@@ -270,6 +342,147 @@
return result;
}
+// NativeAuthenticationSASLDigestToNode
+//
+// Authenticate a user to the directory.
+//
+// @param nodename: the node to authenticate to.
+// @param user: the identifier/directory record name of the user.
+// @param sasldata: the client response.
+// @param saslResult: returned step data.
+// @return: true if authentication succeeds, false otherwise.
+//
+bool CDirectoryServiceAuth::NativeAuthenticationSASLDigestToNode(const char* nodename, const char* user, const char* sasldata, CFStringRef* saslResult)
+{
+ bool result = false;
+ tDirNodeReference node = 0L;
+ tDataNodePtr authType = NULL;
+ tDataBufferPtr authData = NULL;
+ tContextData context = NULL;
+
+ try
+ {
+ // Make sure we have a valid directory service
+ OpenService();
+
+ // Open the node we want to query
+ node = OpenNamedNode(nodename);
+
+ CreateBuffer();
+
+ // First, specify the type of authentication.
+ authType = ::dsDataNodeAllocateString(mDir, kDSStdAuthSASLProxy);
+
+ // Build input data
+ // Native authentication is a one step authentication scheme.
+ // Step 1
+ // Send: <length><user>
+ // <length><saslmechansim>
+ // <length><sasldata>
+ // Receive: success or failure and
+ // step data:
+ // <length><saslresultdata>
+ UInt32 aDataBufSize = sizeof(UInt32) + ::strlen(user) +
+ sizeof(UInt32) + ::strlen(kSASLDIGESTMD5) +
+ sizeof(UInt32) + ::strlen(sasldata);
+ authData = ::dsDataBufferAllocate(mDir, aDataBufSize);
+ if (authData == NULL)
+ ThrowIfDSErr(eDSNullDataBuff);
+
+ // Fill the buffer
+ ::dsFillAuthBuffer(authData, 3,
+ ::strlen(user), user,
+ ::strlen(kSASLDIGESTMD5), kSASLDIGESTMD5,
+ ::strlen(sasldata), sasldata);
+
+ // Do authentication
+ tDirStatus dirStatus = ::dsDoDirNodeAuth(node, authType, true, authData, mData, &context);
+ result = (dirStatus == eDSNoErr);
+
+ if (result && (NULL != saslResult))
+ {
+ // get first step data in string (always a string for kSASLDIGESTMD5)
+ *saslResult = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8*)&mData->fBufferData[4], *(UInt32*)&mData->fBufferData[0],
+ kCFStringEncodingUTF8, false);
+ }
+
+ // Cleanup
+ ::dsDataBufferDeAllocate(mDir, authData);
+ authData = NULL;
+ ::dsDataNodeDeAllocate(mDir, authType);
+ authType = NULL;
+ RemoveBuffer();
+
+ // If fatal error, force full reset
+ if (not result and (dirStatus != eDSAuthFailed))
+ {
+ CloseService();
+ }
+ }
+ catch(...)
+ {
+ // Cleanup
+ if (authData != NULL)
+ ::dsDataBufferDeAllocate(mDir, authData);
+ if (authType != NULL)
+ ::dsDataNodeDeAllocate(mDir, authType);
+ RemoveBuffer();
+ CloseService();
+
+ throw;
+ }
+
+ return result;
+}
+
+/*
+// NativeGenerateClientResponse
+//
+// Authenticate a user to the directory.
+//
+// @param nodename: the node to authenticate to.
+// @param user: the identifier/directory record name of the user.
+// @param sasldata: the client response.
+// @param saslResult: returned step data.
+// @return: true if authentication succeeds, false otherwise.
+//
+bool CDirectoryServiceAuth::NativeGenerateClientResponse(const char* serverChallenge, CFStringRef* response)
+{
+ bool result = false;
+ tDirNodeReference node = 0L;
+ tDataNodePtr authType = NULL;
+ tDataBufferPtr authData = NULL;
+ tContextData context = NULL;
+
+ try
+ {
+ sasl_conn = ::SASLClientNewContext( callbacks, &sasl_context );
+ // Client hashes the digest and responds
+ result = ::sasl_client_step(sasl_conn, (char *)[serverChal bytes], [serverChal length], NULL, &data, &len);
+ if (result != SASL_CONTINUE) {
+ printf("sasl_client_step = %d\n", result);
+ goto done;
+ }
+
+ }
+ catch(...)
+ {
+ // Cleanup
+ if (authData != NULL)
+ ::dsDataBufferDeAllocate(mDir, authData);
+ if (authType != NULL)
+ ::dsDataNodeDeAllocate(mDir, authType);
+ RemoveBuffer();
+ CloseService();
+
+ throw;
+ }
+
+ return result;
+}
+*/
+
+
// CloseService
//
// Close the directory service if previously open.
Modified: PyOpenDirectory/branches/users/gaya/addigestauth/src/CDirectoryServiceAuth.h
===================================================================
--- PyOpenDirectory/branches/users/gaya/addigestauth/src/CDirectoryServiceAuth.h 2009-10-16 23:25:33 UTC (rev 4592)
+++ PyOpenDirectory/branches/users/gaya/addigestauth/src/CDirectoryServiceAuth.h 2009-10-16 23:31:54 UTC (rev 4593)
@@ -32,6 +32,9 @@
bool AuthenticateUserBasic(const char* nodename, const char* user, const char* pswd, bool& result, bool using_python=true);
bool AuthenticateUserDigest(const char* nodename, const char* user, const char* challenge, const char* response, const char* method, bool& result, bool using_python=true);
+ bool AuthenticateUserDigestToActiveDirectory(const char* nodename, const char* user, const char* response, bool& result, bool using_python=true);
+
+ CFStringRef GetDigestMD5ChallengeFromActiveDirectory(const char* nodename, bool using_python=true);
protected:
@@ -40,6 +43,7 @@
bool NativeAuthenticationBasicToNode(const char* nodename, const char* user, const char* pswd);
bool NativeAuthenticationDigestToNode(const char* nodename, const char* user, const char* challenge, const char* response, const char* method);
+ bool NativeAuthenticationSASLDigestToNode(const char* nodename, const char* user, const char* sasldata, CFStringRef* saslResult = NULL);
virtual void CloseService();
virtual tDirNodeReference OpenNamedNode(const char* nodename);
Modified: PyOpenDirectory/branches/users/gaya/addigestauth/src/PythonWrapper.cpp
===================================================================
--- PyOpenDirectory/branches/users/gaya/addigestauth/src/PythonWrapper.cpp 2009-10-16 23:25:33 UTC (rev 4592)
+++ PyOpenDirectory/branches/users/gaya/addigestauth/src/PythonWrapper.cpp 2009-10-16 23:31:54 UTC (rev 4593)
@@ -909,7 +909,7 @@
}
/*
-def authenticateUserDigest(obj, guid, user, challenge, response, method):
+def authenticateUserDigest(obj, nodename, user, challenge, response, method):
"""
Authenticate using HTTP Digest credentials to Open Directory.
@@ -957,6 +957,92 @@
return NULL;
}
+/*
+def authenticateUserDigestToActiveDirectory(obj, nodename, user, challenge, response):
+ """
+ Authenticate using HTTP Digest credentials to an Active Directory node (exported by Open Directory).
+
+ @param obj: C{object} the object obtained from an odInit call.
+ @param nodename: C{str} the directory nodename for the record to check.
+ @param user: C{str} the user identifier/directory record name to check.
+ @param response: C{str} the HTTP response sent from the client.
+ @return: C{True} if the user was found, C{False} otherwise.
+ """
+ */
+extern "C" PyObject *authenticateUserDigestToActiveDirectory(PyObject *self, PyObject *args)
+{
+ PyObject* pyds;
+ const char* nodename;
+ const char* user;
+ const char* response;
+ if (!PyArg_ParseTuple(args, "Osss", &pyds, &nodename, &user, &response) || !PyCObject_Check(pyds))
+ {
+ PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices authenticateUserDigestToActiveDirectory: could not parse arguments", 0));
+ return NULL;
+ }
+
+ CDirectoryServiceManager* dsmgr = static_cast<CDirectoryServiceManager*>(PyCObject_AsVoidPtr(pyds));
+ if (dsmgr != NULL)
+ {
+ CDirectoryServiceAuth* ds = dsmgr->GetAuthService();
+ bool result = false;
+ bool authresult = false;
+ result = ds->AuthenticateUserDigestToActiveDirectory(nodename, user, response, authresult);
+ if (result)
+ {
+ if (authresult)
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+ }
+ }
+ else
+ PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices authenticateUserDigestToActiveDirectory: invalid directory service argument", 0));
+
+ return NULL;
+}
+
+/*
+def getDigestMD5ChallengeFromActiveDirectory(obj, nodename, user ):
+ """
+ Get the Digest MD5 challenge (a.k.a. a nonce) from an Active Directory node (exported by Open Directory).
+
+ @param obj: C{object} the object obtained from an odInit call.
+ @param nodename: C{str} the directory nodename for the record to check.
+ @param user: C{str} the user identifier/directory record name to check.
+ @return: C{string} containing the AD server-generated challange.
+ """
+ */
+extern "C" PyObject *getDigestMD5ChallengeFromActiveDirectory(PyObject *self, PyObject *args)
+{
+ PyObject* pyds;
+ const char* nodename;
+ if (!PyArg_ParseTuple(args, "Os", &pyds, &nodename) || !PyCObject_Check(pyds))
+ {
+ PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices authenticateUserDigestToActiveDirectory: could not parse arguments", 0));
+ return NULL;
+ }
+
+ CDirectoryServiceManager* dsmgr = static_cast<CDirectoryServiceManager*>(PyCObject_AsVoidPtr(pyds));
+ if (dsmgr != NULL)
+ {
+ CDirectoryServiceAuth* ds = dsmgr->GetAuthService();
+ CFStringRef challenge = NULL;
+ challenge = ds->GetDigestMD5ChallengeFromActiveDirectory(nodename);
+ if (challenge != NULL)
+ {
+ PyObject* result = CFStringToPyStr(challenge);
+ CFRelease(challenge);
+
+ return result;
+ }
+ }
+ else
+ PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices authenticateUserDigestToActiveDirectory: invalid directory service argument", 0));
+
+ return NULL;
+}
+
static PyMethodDef ODMethods[] = {
{"odInit", odInit, METH_VARARGS,
"Initialize the Open Directory system."},
@@ -980,6 +1066,10 @@
"Authenticate a user with a password to Open Directory using plain text authentication."},
{"authenticateUserDigest", authenticateUserDigest, METH_VARARGS,
"Authenticate a user with a password to Open Directory using HTTP DIGEST authentication."},
+ {"authenticateUserDigestToActiveDirectory", authenticateUserDigestToActiveDirectory, METH_VARARGS,
+ "Authenticate a user with a password to an Active Directory node (exported by Open Directory) using HTTP DIGEST authentication."},
+ {"getDigestMD5ChallengeFromActiveDirectory", getDigestMD5ChallengeFromActiveDirectory, METH_VARARGS,
+ "Get a Digest MD5 challange (a.k.a. a nonce) from an Active Directory node (exported by Open Directory)."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
Modified: PyOpenDirectory/branches/users/gaya/addigestauth/support/PyOpenDirectory.xcodeproj/project.pbxproj
===================================================================
--- PyOpenDirectory/branches/users/gaya/addigestauth/support/PyOpenDirectory.xcodeproj/project.pbxproj 2009-10-16 23:25:33 UTC (rev 4592)
+++ PyOpenDirectory/branches/users/gaya/addigestauth/support/PyOpenDirectory.xcodeproj/project.pbxproj 2009-10-16 23:31:54 UTC (rev 4593)
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
+ 661DFBCA1088E5C900846632 /* libsasl2.2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 661DFBC91088E5C900846632 /* libsasl2.2.dylib */; };
8DD76F650486A84900D96B5E /* test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* test.cpp */; settings = {ATTRIBUTES = (); }; };
AF00155A0B8A21340045DAEE /* Python.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF0015590B8A21340045DAEE /* Python.framework */; };
AF00155E0B8A21FD0045DAEE /* PythonWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF155A310A501F84007E1E6E /* PythonWrapper.cpp */; };
@@ -38,6 +39,7 @@
/* Begin PBXFileReference section */
08FB7796FE84155DC02AAC07 /* test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = test.cpp; sourceTree = "<group>"; };
+ 661DFBC91088E5C900846632 /* libsasl2.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsasl2.2.dylib; path = /usr/lib/libsasl2.2.dylib; sourceTree = "<absolute>"; };
8DD76F6C0486A84900D96B5E /* PyOpenDirectory */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = PyOpenDirectory; sourceTree = BUILT_PRODUCTS_DIR; };
AF0015590B8A21340045DAEE /* Python.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Python.framework; path = /System/Library/Frameworks/Python.framework; sourceTree = "<absolute>"; };
AF02AC560CBE690500F478B8 /* CDirectoryServiceException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CDirectoryServiceException.cpp; path = ../src/CDirectoryServiceException.cpp; sourceTree = SOURCE_ROOT; };
@@ -65,6 +67,7 @@
AF155A370A501F9D007E1E6E /* CoreFoundation.framework in Frameworks */,
AF155A380A501F9D007E1E6E /* DirectoryService.framework in Frameworks */,
AF00155A0B8A21340045DAEE /* Python.framework in Frameworks */,
+ 661DFBCA1088E5C900846632 /* libsasl2.2.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -116,6 +119,7 @@
AF0015590B8A21340045DAEE /* Python.framework */,
AF155A350A501F9D007E1E6E /* CoreFoundation.framework */,
AF155A360A501F9D007E1E6E /* DirectoryService.framework */,
+ 661DFBC91088E5C900846632 /* libsasl2.2.dylib */,
);
name = Frameworks;
sourceTree = "<group>";
Modified: PyOpenDirectory/branches/users/gaya/addigestauth/support/test.cpp
===================================================================
--- PyOpenDirectory/branches/users/gaya/addigestauth/support/test.cpp 2009-10-16 23:25:33 UTC (rev 4592)
+++ PyOpenDirectory/branches/users/gaya/addigestauth/support/test.cpp 2009-10-16 23:31:54 UTC (rev 4593)
@@ -32,9 +32,16 @@
void PrintDictionary(const void* key, const void* value, void* ref);
void PrintArrayArray(CFMutableArrayRef list);
void PrintArray(CFArrayRef list);
-void AuthenticateUser(CDirectoryServiceAuth* dir, const char* guid, const char* user, const char* pswd);
-void AuthenticateUserDigest(CDirectoryServiceAuth* dir, const char* guid, const char* user, const char* challenge, const char* response, const char* method);
+void AuthenticateUser(CDirectoryServiceAuth* dir, const char* nodename, const char* user, const char* pswd);
+void AuthenticateUserDigest(CDirectoryServiceAuth* dir, const char* nodename, const char* user, const char* challenge, const char* response, const char* method);
+void AuthenticateUserDigestToActiveDirectory(CDirectoryServiceAuth* dir, const char* nodename, const char* user, const char* response);
+void GetDigestMD5ChallengeFromActiveDirectory(CDirectoryServiceAuth* dir, const char* nodename);
+void AuthenticateUserDigestODAD(CDirectoryServiceAuth* dir, const char* nodename, const char* user, const char* pswd, bool verbose = false);
+
+CFStringRef GetClientResponseFromSASL( const char* username, const char* pswd, const char* serverchallenge );
+CFStringRef GetDigestMD5ChallengeFromSASL( void );
+
#define kDSStdRecordTypeResources "dsRecTypeStandard:Resources"
#define kDSNAttrServicesLocator "dsAttrTypeStandard:ServicesLocator"
#define kDSNAttrJPEGPhoto "dsAttrTypeStandard:JPEGPhoto"
@@ -44,7 +51,7 @@
CFMutableArrayRef data = dir->ListNodes(false);
if (data != NULL)
{
- printf("\n*** Nodes: %d ***\n", CFArrayGetCount(data));
+ printf("\n*** Nodes: %ld ***\n", CFArrayGetCount(data));
for(CFIndex i = 0; i < CFArrayGetCount(data); i++)
{
CFStringRef str = (CFStringRef)CFArrayGetValueAtIndex(data, i);
@@ -55,11 +62,11 @@
char localBuffer[256];
Boolean success;
success = CFStringGetCString(str, localBuffer, 256, kCFStringEncodingUTF8);
- printf("%d: %s\n", i, localBuffer);
+ printf("%ld: %s\n", i, localBuffer);
}
else
{
- printf("%d: %s\n", i, (const char*)bytes);
+ printf("%ld: %s\n", i, (const char*)bytes);
}
}
CFRelease(data);
@@ -80,7 +87,7 @@
CFMutableDictionaryRef nodeData = dir->GetNodeAttributes("/Search", attrsdict, false);
if (nodeData != NULL)
{
- printf("\n*** Node Attributes: %d ***\n", CFDictionaryGetCount(nodeData));
+ printf("\n*** Node Attributes: %ld ***\n", CFDictionaryGetCount(nodeData));
CFDictionaryApplyFunction(nodeData, PrintDictionary, NULL);
CFRelease(nodeData);
}
@@ -107,7 +114,7 @@
CFMutableArrayRef data = dir->ListAllRecordsWithAttributes(recordTypes, attrsdict, 0, false);
if (data != NULL)
{
- printf("\n*** Users: %d ***\n", CFArrayGetCount(data));
+ printf("\n*** Users: %ld ***\n", CFArrayGetCount(data));
for(CFIndex i = 0; i < CFArrayGetCount(data); i++)
{
CFArrayRef tuple = (CFArrayRef)CFArrayGetValueAtIndex(data, i);
@@ -119,11 +126,11 @@
char localBuffer[256];
Boolean success;
success = CFStringGetCString(str, localBuffer, 256, kCFStringEncodingUTF8);
- printf("%d: %s\n", i, localBuffer);
+ printf("%ld: %s\n", i, localBuffer);
}
else
{
- printf("%d: %s\n", i, (const char*)bytes);
+ printf("%ld: %s\n", i, (const char*)bytes);
}
}
CFRelease(data);
@@ -158,11 +165,11 @@
char localBuffer[256];
Boolean success;
success = CFStringGetCString(str, localBuffer, 256, kCFStringEncodingUTF8);
- printf("%d: %s\n", i, localBuffer);
+ printf("%ld: %s\n", i, localBuffer);
}
else
{
- printf("%d: %s\n", i, (const char*)bytes);
+ printf("%ld: %s\n", i, (const char*)bytes);
}
}
CFRelease(data);
@@ -262,17 +269,35 @@
//AuthenticateUser(authdir, "/LDAPv3/127.0.0.1", "oliverdaboo", "oliver");
AuthenticateUser(authdir, "/LDAPv3/127.0.0.1", "eleanordaboo", "eleanor");
- const char* n = "/LDAPv3/127.0.0.1";
- //const char* u = "test";
- //const char* c = "nonce=\"1\", qop=\"auth\", realm=\"Test\", algorithm=\"md5\", opaque=\"1\"";
- //const char* r = "username=\"test\", nonce=\"1\", cnonce=\"1\", nc=\"1\", realm=\"Test\", algorithm=\"md5\", opaque=\"1\", qop=\"auth\", uri=\"/\", response=\"4241f31ffe6f9c99b891f88e9c41caa9\"";
- //const char* c = "WWW-Authenticate: digest nonce=\"1621696297327727918745238639\", opaque=\"121994e78694cbdff74f12cb32ee6f00-MTYyMTY5NjI5NzMyNzcyNzkxODc0NTIzODYzOSwxMjcuMC4wLjEsMTE2ODU2ODg5NQ==\", realm=\"Test Realm\", algorithm=\"md5\", qop=\"auth\"";
- //const char* r = "Authorization: Digest username=\"test\", realm=\"Test Realm\", nonce=\"1621696297327727918745238639\", uri=\"/principals/users/test/\", response=\"e260f13cffcc15572ddeec9c31de437b\", opaque=\"121994e78694cbdff74f12cb32ee6f00-MTYyMTY5NjI5NzMyNzcyNzkxODc0NTIzODYzOSwxMjcuMC4wLjEsMTE2ODU2ODg5NQ==\", algorithm=\"md5\", cnonce=\"70cbd8f04227d8d46c0193b290beaf0d\", nc=00000001, qop=\"auth\"";
- const char* u = "";
- const char* c = "DIGEST-MD5";
- const char* r = "";
- AuthenticateUserDigest(authdir, n, u, c, r, "GET");
+ {
+ const char* n = "/LDAPv3/127.0.0.1";
+ //const char* u = "test";
+ //const char* c = "nonce=\"1\", qop=\"auth\", realm=\"Test\", algorithm=\"md5\", opaque=\"1\"";
+ //const char* r = "username=\"test\", nonce=\"1\", cnonce=\"1\", nc=\"1\", realm=\"Test\", algorithm=\"md5\", opaque=\"1\", qop=\"auth\", uri=\"/\", response=\"4241f31ffe6f9c99b891f88e9c41caa9\"";
+ //const char* c = "WWW-Authenticate: digest nonce=\"1621696297327727918745238639\", opaque=\"121994e78694cbdff74f12cb32ee6f00-MTYyMTY5NjI5NzMyNzcyNzkxODc0NTIzODYzOSwxMjcuMC4wLjEsMTE2ODU2ODg5NQ==\", realm=\"Test Realm\", algorithm=\"md5\", qop=\"auth\"";
+ //const char* r = "Authorization: Digest username=\"test\", realm=\"Test Realm\", nonce=\"1621696297327727918745238639\", uri=\"/principals/users/test/\", response=\"e260f13cffcc15572ddeec9c31de437b\", opaque=\"121994e78694cbdff74f12cb32ee6f00-MTYyMTY5NjI5NzMyNzcyNzkxODc0NTIzODYzOSwxMjcuMC4wLjEsMTE2ODU2ODg5NQ==\", algorithm=\"md5\", cnonce=\"70cbd8f04227d8d46c0193b290beaf0d\", nc=00000001, qop=\"auth\"";
+ const char* u = "";
+ const char* c = "DIGEST-MD5";
+ const char* r = "";
+ AuthenticateUserDigest(authdir, n, u, c, r, "GET");
+ }
+ GetDigestMD5ChallengeFromActiveDirectory(authdir, "/Active Directory/All Domains");
+
+ {
+ const char* n = "/Active Directory/All Domains";
+ const char* u = "";
+ const char* r = "";
+ AuthenticateUserDigestToActiveDirectory(authdir, n, u, r);
+ }
+
+
+ AuthenticateUser(authdir, "/Active Directory/All Domains", "servicetest", "pass");
+ AuthenticateUserDigestODAD(authdir, "/Active Directory/All Domains", "servicetest", "pass");
+
+ //AuthenticateUser(authdir, "/LDAPv3/127.0.0.1", "eleanordaboo", "eleanor");
+ //AuthenticateUserDigestODAD(authdir, "/LDAPv3/127.0.0.1", "eleanordaboo", "eleanor");
+
return 0;
}
@@ -282,12 +307,12 @@
if (dir->AuthenticateUserBasic(nodename, user, pswd, result, false))
{
if (result)
- printf("Authenticated user: %s\n", user);
+ printf("AuthenticateUserBasic() success; nodename:\"%s\", user:\"%s\", pswd:\"%s\"\n", nodename, user, pswd );
else
- printf("Not Authenticated user: %s\n", user);
+ printf("AuthenticateUserBasic() success, but auth failed; nodename:\"%s\", user:\"%s\", pswd:\"%s\"\n", nodename, user, pswd );
}
else
- printf("Failed authentication user: %s\n", user);
+ printf("AuthenticateUserBasic() failed; nodename:\"%s\", user:\"%s\", pswd:\"%s\"\n", nodename, user, pswd );
}
void AuthenticateUserDigest(CDirectoryServiceAuth* dir, const char* nodename, const char* user, const char* challenge, const char* response, const char* method)
@@ -296,14 +321,144 @@
if (dir->AuthenticateUserDigest(nodename, user, challenge, response, method, result, false))
{
if (result)
- printf("Authenticated user: %s\n", user);
+ printf("AuthenticateUserDigest() success; nodename:\"%s\", user:\"%s\", challenge:\"%s\", response:\"%s\", method:\"%s\"\n", nodename, user, challenge, response, method );
else
- printf("Not Authenticated user: %s\n", user);
+ printf("AuthenticateUserDigest() success, but auth failed; user:\"%s\", user:\"%s\", challenge:\"%s\", response:\"%s\", method:\"%s\"\n", nodename, user, challenge, response, method );
}
else
- printf("Failed authentication user: %s\n", user);
+ printf("AuthenticateUserDigest() failed, nodename:\"%s\", user:\"%s\", challenge:\"%s\", response:\"%s\", method:\"%s\"\n", nodename, user, challenge, response, method );
}
+
+void AuthenticateUserDigestToActiveDirectory(CDirectoryServiceAuth* dir, const char* nodename, const char* user, const char* response)
+{
+
+ bool result = false;
+ if (dir->AuthenticateUserDigestToActiveDirectory(nodename, user, response, result, false))
+ {
+ if (result)
+ printf("AuthenticateUserDigestToActiveDirectory() success; nodename:\"%s\", user:\"%s\", response:\"%s\"\n", nodename, user, response );
+ else
+ printf("AuthenticateUserDigestToActiveDirectory() success, but auth failed; nodename:\"%s\", user:\"%s\", response:\"%s\"\n", nodename, user, response );
+ }
+ else
+ printf("AuthenticateUserDigestToActiveDirectory() failed; nodename:\"%s\", user:\"%s\", response:\"%s\"\n", nodename, user, response );
+}
+
+void GetDigestMD5ChallengeFromActiveDirectory(CDirectoryServiceAuth* dir, const char* nodename)
+{
+
+ CFStringRef result = dir->GetDigestMD5ChallengeFromActiveDirectory(nodename, false);
+ if (NULL != result)
+ {
+ CFStringUtil s(result);
+ printf("GetDigestMD5ChallengeFromActiveDirectory() success; nodename:\"%s\", challenge:\"%s\"\n", nodename, s.temp_str());
+
+ CFRelease( result );
+ }
+ else
+ printf("GetDigestMD5ChallengeFromActiveDirectory() failed; nodename:\"%s\"\n", nodename);
+}
+
+
+void AuthenticateUserDigestODAD(CDirectoryServiceAuth* dir, const char* nodename, const char* user, const char* pswd, bool verbose)
+{
+ CFStringRef challengeRef = NULL;
+ CFStringRef responseRef = NULL;
+ bool activeDirectory = (0 == strncmp(nodename, "/Active Directory/", strlen("/Active Directory/")));
+
+ // first get server challange
+ if (activeDirectory)
+ {
+ // get server challenge from AD
+ challengeRef = dir->GetDigestMD5ChallengeFromActiveDirectory(nodename, false);
+ if (NULL != challengeRef)
+ {
+ if (verbose) {
+ CFStringUtil s(challengeRef);
+ printf("GetDigestMD5ChallengeFromActiveDirectory() success; nodename:\"%s\", challenge:\"%s\"\n", nodename, s.temp_str());
+ }
+ }
+ else
+ printf("GetDigestMD5ChallengeFromActiveDirectory() failed; nodename:\"%s\"\n", nodename);
+ }
+ else
+ {
+ // get server challenge from AD
+ challengeRef = GetDigestMD5ChallengeFromSASL();
+ if (NULL != challengeRef)
+ {
+ if (verbose) {
+ CFStringUtil s(challengeRef);
+ printf("GetDigestMD5ChallengeFromSASL() success; nodename:\"%s\", challenge:\"%s\"\n", nodename, s.temp_str());
+ }
+ }
+ else
+ printf("GetDigestMD5ChallengeFromSASL() failed; nodename:\"%s\"\n", nodename);
+ }
+
+ if (NULL != challengeRef)
+ {
+
+ CFStringUtil challengeStrUtil(challengeRef);
+ const char* challenge = challengeStrUtil.temp_str();
+
+ // now create response
+ responseRef = GetClientResponseFromSASL( user, pswd, challenge );
+ CFStringUtil responseStrUtil(responseRef);
+ const char* response = responseStrUtil.temp_str();
+
+ if (NULL != responseRef)
+ {
+ if (verbose) {
+ printf("GetClientResponseFromSASL() success; user:\"%s\", pswd:\"%s\", challenge:\"%s\", response:\"%s\"\n", user, pswd, challenge, response);
+ }
+ }
+ else
+ {
+ printf("GetClientResponseFromSASL() failed; user:\"%s\", pswd:\"%s\", challenge:\"%s\"\n", user, pswd, challenge);
+ goto exit;
+ }
+
+ if (activeDirectory)
+ {
+ // now auth
+ bool result = false;
+ if (dir->AuthenticateUserDigestToActiveDirectory(nodename, user, response, result, false))
+ {
+ if (result)
+ printf("AuthenticateUserDigestToActiveDirectory() success; nodename:\"%s\", user:\"%s\", response:\"%s\"\n", nodename, user, response );
+ else
+ printf("AuthenticateUserDigestToActiveDirectory() success, but auth failed; nodename:\"%s\", user:\"%s\", response:\"%s\"\n", nodename, user, response );
+ }
+ else
+ printf("AuthenticateUserDigestToActiveDirectory() failed; nodename:\"%s\", user:\"%s\", response:\"%s\"\n", nodename, user, response );
+ }
+ else
+ {
+ bool result = false;
+ const char* method = "";
+ if (dir->AuthenticateUserDigest(nodename, user, challenge, response, method, result, false))
+ {
+ if (result)
+ printf("AuthenticateUserDigest() success; nodename:\"%s\", user:\"%s\", challenge:\"%s\", response:\"%s\", method:\"%s\"\n", nodename, user, challenge, response, method );
+ else
+ printf("AuthenticateUserDigest() success, but auth failed; nodename:\"%s\", user:\"%s\", challenge:\"%s\", response:\"%s\", method:\"%s\"\n", nodename, user, challenge, response, method );
+ }
+ else
+ printf("AuthenticateUserDigest() failed, nodename:\"%s\", user:\"%s\", challenge:\"%s\", response:\"%s\", method:\"%s\"\n", nodename, user, challenge, response, method );
+ }
+ }
+
+exit:
+
+ if (NULL != challengeRef)
+ CFRelease( challengeRef );
+ if (NULL != responseRef)
+ CFRelease( responseRef );
+
+}
+
void CFDictionaryIterator(const void* key, const void* value, void* ref)
{
CFStringRef strkey = (CFStringRef)key;
@@ -390,7 +545,7 @@
for(CFIndex i = 0; i < CFArrayGetCount(list); i++)
{
CFMutableArrayRef array = (CFMutableArrayRef)CFArrayGetValueAtIndex(list, i);
- printf("Index: %d\n", i);
+ printf("Index: %ld\n", i);
PrintArray(array);
printf("\n");
}
@@ -409,11 +564,260 @@
char localBuffer[256];
Boolean success;
success = CFStringGetCString(str, localBuffer, 256, kCFStringEncodingUTF8);
- printf("%d: %s\n", i, localBuffer);
+ printf("%ld: %s\n", i, localBuffer);
}
else
{
- printf("%d: %s\n", i, (const char*)bytes);
+ printf("%ld: %s\n", i, (const char*)bytes);
}
}
}
+
+
+#pragma mark ----- SASL calls
+
+#include <sasl/sasl.h>
+
+#define kSASLMinSecurityFactor 0
+#define kSASLMaxSecurityFactor 65535
+#define kSASLMaxBufferSize 65536
+#define kSASLSecurityFlags 0
+#define kSASLPropertyNames (NULL)
+#define kSASLPropertyValues (NULL)
+
+typedef struct saslContext {
+ const char *user;
+ const char *pass;
+} saslContext;
+
+typedef int sasl_cbproc();
+
+
+int getrealm(void *context /*__attribute__((unused))*/,
+ int cb_id,
+ const char **availrealms,
+ const char **result)
+{
+ #pragma unused (context)
+
+ /* paranoia check */
+ if (cb_id != SASL_CB_GETREALM) return SASL_BADPARAM;
+ if (!result) return SASL_BADPARAM;
+
+ if ( availrealms ) {
+ *result = *availrealms;
+ }
+
+ return SASL_OK;
+}
+
+int simple(void *context /*__attribute__((unused))*/,
+ int cb_id,
+ const char **result,
+ unsigned *len)
+{
+ saslContext *text = (saslContext *)context;
+
+ //syslog(LOG_INFO, "in simple\n");
+
+ /* paranoia check */
+ if ( result == NULL )
+ return SASL_BADPARAM;
+
+ *result = NULL;
+
+ switch (cb_id) {
+ case SASL_CB_USER:
+ *result = text->user;
+ break;
+
+ case SASL_CB_AUTHNAME:
+ *result = text->user;
+ break;
+
+ default:
+ return SASL_BADPARAM;
+ }
+
+ if (*result != NULL && len != NULL)
+ *len = strlen(*result);
+
+ return SASL_OK;
+}
+
+
+int
+getsecret(sasl_conn_t *conn,
+ void *context /*__attribute__((unused))*/,
+ int cb_id,
+ sasl_secret_t **psecret)
+{
+ saslContext *text = (saslContext *)context;
+
+ //syslog(LOG_INFO, "in getsecret\n");
+
+ /* paranoia check */
+ if (! conn || ! psecret || cb_id != SASL_CB_PASS)
+ return SASL_BADPARAM;
+
+ size_t pwdLen = strlen(text->pass);
+ *psecret = (sasl_secret_t *) malloc( sizeof(sasl_secret_t) + pwdLen );
+ (*psecret)->len = pwdLen;
+ strcpy((char *)(*psecret)->data, text->pass);
+
+ return SASL_OK;
+}
+
+
+
+
+//----------------------------------------------------------------------------------------
+// SASLClientNewContext
+//
+// Returns: A SASL context, or NULL
+//
+// <callbacks> must be an array with capacity for at least 5 items
+//----------------------------------------------------------------------------------------
+
+sasl_conn_t *SASLClientNewContext( sasl_callback_t *callbacks, saslContext *context )
+{
+ int result = 0;
+ sasl_conn_t *sasl_conn = NULL;
+ sasl_security_properties_t secprops = { kSASLMinSecurityFactor, kSASLMaxSecurityFactor,
+ kSASLMaxBufferSize, kSASLSecurityFlags,
+ kSASLPropertyNames, kSASLPropertyValues };
+
+ result = sasl_client_init( NULL );
+ //printf( "sasl_client_init = %d\n", result );
+ if ( result != SASL_OK )
+ return NULL;
+
+ // callbacks we support
+ callbacks[0].id = SASL_CB_GETREALM;
+ callbacks[0].proc = (sasl_cbproc *)&getrealm;
+ callbacks[0].context = context;
+
+ callbacks[1].id = SASL_CB_USER;
+ callbacks[1].proc = (sasl_cbproc *)&simple;
+ callbacks[1].context = context;
+
+ callbacks[2].id = SASL_CB_AUTHNAME;
+ callbacks[2].proc = (sasl_cbproc *)&simple;
+ callbacks[2].context = context;
+
+ callbacks[3].id = SASL_CB_PASS;
+ callbacks[3].proc = (sasl_cbproc *)&getsecret;
+ callbacks[3].context = context;
+
+ callbacks[4].id = SASL_CB_LIST_END;
+ callbacks[4].proc = NULL;
+ callbacks[4].context = NULL;
+
+ result = sasl_client_new( "http", "servicetest.example.com", NULL, NULL, callbacks, 0, &sasl_conn );
+ //printf( "sasl_client_new = %d\n", result );
+ if ( result != SASL_OK )
+ return NULL;
+
+ result = sasl_setprop( sasl_conn, SASL_SEC_PROPS, &secprops );
+ //printf( "sasl_setprop = %d\n", result );
+ if ( result != SASL_OK ) {
+ sasl_dispose( &sasl_conn );
+ return NULL;
+ }
+
+ return sasl_conn;
+}
+
+
+CFStringRef GetClientResponseFromSASL( const char* username, const char* pswd, const char* serverchallenge )
+{
+ int result = 0;
+ sasl_callback_t callbacks[5] = {{0}};
+ saslContext sasl_context = { NULL, NULL };
+ sasl_conn_t *sasl_conn = NULL;
+ const char *data = NULL;
+ unsigned int len = 0;
+ const char *chosenmech = NULL;
+ CFStringRef response = NULL;
+
+ sasl_context.user = username;
+ sasl_context.pass = pswd;
+
+ // Client's first move
+ sasl_conn = SASLClientNewContext( callbacks, &sasl_context );
+
+ result = sasl_client_start( sasl_conn, "DIGEST-MD5", NULL, &data, &len, &chosenmech );
+ //printf( "sasl_client_start = %d, len = %d\n", result, len );
+ if ( result != SASL_CONTINUE )
+ goto done;
+
+ // Client hashes the digest and responds
+ result = sasl_client_step(sasl_conn, serverchallenge, strlen(serverchallenge), NULL, &data, &len);
+ if (result != SASL_CONTINUE) {
+ printf("sasl_client_step = %d\n", result);
+ goto done;
+ }
+
+ response = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)data, len, kCFStringEncodingUTF8, false);
+
+
+done:
+ if ( sasl_conn != NULL )
+ sasl_dispose( &sasl_conn );
+
+ return response;
+}
+
+//----------------------------------------------------------------------------------------
+// GetDigestMD5ChallengeFromSASL
+//
+// Returns: A server challenge for DIGEST-MD5 authentication
+//----------------------------------------------------------------------------------------
+
+CFStringRef GetDigestMD5ChallengeFromSASL( void )
+{
+ int result = 0;
+ sasl_conn_t *sasl_server_conn = NULL;
+ const char *serverOut = NULL;
+ unsigned int serverOutLen = 0;
+ CFStringRef challenge = NULL;
+
+ // Passing a minimum security factor of 2 or more triggers the latest digest-md5 specification.
+ // algorithm=md5-sess,qop=auth-conf.
+ sasl_security_properties_t secprops = { 2, kSASLMaxSecurityFactor,
+ kSASLMaxBufferSize, kSASLSecurityFlags,
+ kSASLPropertyNames, kSASLPropertyValues };
+
+ // Get a challenge from SASL
+ result = sasl_server_init_alt( NULL, "AppName" );
+ if ( result != SASL_OK ) {
+ printf( "sasl_server_init_alt = %d\n", result );
+ goto done;
+ }
+
+ //"127.0.0.1;80"
+ result = sasl_server_new( "http", "servicetest.example.com", NULL, NULL, NULL, NULL, 0, &sasl_server_conn );
+ if ( result != SASL_OK ) {
+ printf( "sasl_server_init_alt = %d\n", result );
+ goto done;
+ }
+
+ result = sasl_setprop( sasl_server_conn, SASL_SEC_PROPS, &secprops );
+
+ result = sasl_server_start( sasl_server_conn, "DIGEST-MD5", NULL, 0, &serverOut, &serverOutLen );
+ if ( result != SASL_CONTINUE ) {
+ printf( "sasl_server_start = %d\n", result );
+ goto done;
+ }
+
+ challenge = CFStringCreateWithBytes(kCFAllocatorDefault, (const UInt8*)serverOut, serverOutLen, kCFStringEncodingUTF8, false);
+
+done:
+ if ( sasl_server_conn != NULL )
+ sasl_dispose( &sasl_server_conn );
+
+ return challenge;
+}
+
+
+
Modified: PyOpenDirectory/branches/users/gaya/addigestauth/test_auth.py
===================================================================
--- PyOpenDirectory/branches/users/gaya/addigestauth/test_auth.py 2009-10-16 23:25:33 UTC (rev 4592)
+++ PyOpenDirectory/branches/users/gaya/addigestauth/test_auth.py 2009-10-16 23:31:54 UTC (rev 4593)
@@ -143,41 +143,61 @@
return
nodename = result[0][1][dsattributes.kDSNAttrMetaNodeLocation]
- expected = calcResponse(
- calcHA1(algorithm, username, realm, password, nonce, cnonce),
- algorithm, nonce, nc, cnonce, qop, method, uri, None
+ print( ' User node= "%s"' % nodename)
+ if nodename.startswith("/Active Directory/"):
+
+ challenge = opendirectory.getDigestMD5ChallengeFromActiveDirectory(od, nodename)
+ response = "bogus"
+ print " Challenge: %s" % (challenge,)
+ print " Response: %s" % (response, )
+
+ for _ignore_x in xrange(attempts):
+ success = opendirectory.authenticateUserDigestToActiveDirectory(
+ od,
+ nodename,
+ username,
+ response,
)
- #print expected
-
- if qop:
- challenge = 'Digest realm="%s", nonce="%s", algorithm=%s, qop="%s"' % (realm, nonce, algorithm, qop,)
+
+ if not success:
+ failures += 1
else:
- challenge = 'Digest realm="%s", nonce="%s", algorithm=%s' % (realm, nonce, algorithm,)
- if qop:
- response = ('Digest username="%s", realm="%s", '
- 'nonce="%s", digest-uri="%s", '
- 'response=%s, algorithm=%s, cnonce="%s", qop=%s, nc=%s' % (username, realm, nonce, uri, expected, algorithm, cnonce, qop, nc, ))
- else:
- response = ('Digest username="%s", realm="%s", '
- 'nonce="%s", digest-uri="%s", '
- 'response=%s, algorithm=%s' % (username, realm, nonce, uri, expected, algorithm, ))
- print " Challenge: %s" % (challenge,)
- print " Response: %s" % (response, )
+ expected = calcResponse(
+ calcHA1(algorithm, username, realm, password, nonce, cnonce),
+ algorithm, nonce, nc, cnonce, qop, method, uri, None
+ )
+ #print expected
+
+ if qop:
+ challenge = 'Digest realm="%s", nonce="%s", algorithm=%s, qop="%s"' % (realm, nonce, algorithm, qop,)
+ else:
+ challenge = 'Digest realm="%s", nonce="%s", algorithm=%s' % (realm, nonce, algorithm,)
+ if qop:
+ response = ('Digest username="%s", realm="%s", '
+ 'nonce="%s", digest-uri="%s", '
+ 'response=%s, algorithm=%s, cnonce="%s", qop=%s, nc=%s' % (username, realm, nonce, uri, expected, algorithm, cnonce, qop, nc, ))
+ else:
+ response = ('Digest username="%s", realm="%s", '
+ 'nonce="%s", digest-uri="%s", '
+ 'response=%s, algorithm=%s' % (username, realm, nonce, uri, expected, algorithm, ))
+
+ print " Challenge: %s" % (challenge,)
+ print " Response: %s" % (response, )
+
+ for _ignore_x in xrange(attempts):
+ success = opendirectory.authenticateUserDigest(
+ od,
+ nodename,
+ username,
+ challenge,
+ response,
+ method
+ )
+
+ if not success:
+ failures += 1
- for _ignore_x in xrange(attempts):
- success = opendirectory.authenticateUserDigest(
- od,
- nodename,
- username,
- challenge,
- response,
- method
- )
-
- if not success:
- failures += 1
-
print "\n%d failures out of %d attempts for Digest.\n\n" % (failures, attempts)
def doAuthBasic(username, password):
@@ -216,6 +236,6 @@
od = opendirectory.odInit(search)
-#doAuthBasic(user, pswd)
+doAuthBasic(user, pswd)
doAuthDigest(user, pswd, None, "md5")
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20091016/357bf64f/attachment-0001.html>
More information about the calendarserver-changes
mailing list