[CalendarServer-changes] [1534] PyOpenDirectory/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Thu May 17 12:29:35 PDT 2007
Revision: 1534
http://trac.macosforge.org/projects/calendarserver/changeset/1534
Author: cdaboo at apple.com
Date: 2007-05-17 12:29:34 -0700 (Thu, 17 May 2007)
Log Message:
-----------
Merge of branches/users/cdaboo/better-errors-1318.
Modified Paths:
--------------
PyOpenDirectory/trunk/src/CDirectoryService.cpp
PyOpenDirectory/trunk/src/CDirectoryService.h
Added Paths:
-----------
PyOpenDirectory/trunk/test_auth.py
Modified: PyOpenDirectory/trunk/src/CDirectoryService.cpp
===================================================================
--- PyOpenDirectory/trunk/src/CDirectoryService.cpp 2007-05-17 16:56:17 UTC (rev 1533)
+++ PyOpenDirectory/trunk/src/CDirectoryService.cpp 2007-05-17 19:29:34 UTC (rev 1534)
@@ -31,8 +31,8 @@
extern PyObject* ODException_class;
-# define ThrowIfDSErr(x) { long dirStatus = x; if (dirStatus != eDSNoErr) throw dirStatus; }
-# define ThrowIfNULL(x) { if (x == NULL) throw -1L; }
+# define ThrowIfDSErr(x) { if (x != eDSNoErr) ThrowDSError(x, __FILE__, __LINE__); }
+# define ThrowIfNULL(x) { if (x == NULL) ThrowDSError(-1, __FILE__, __LINE__); }
// This is copied from WhitePages
#define kDSStdRecordTypeResources "dsRecTypeStandard:Resources"
@@ -96,9 +96,9 @@
// Get attribute map
return _ListAllRecordsWithAttributes(recordType, NULL, attributes);
}
- catch(long dserror)
+ catch(SDirectoryServiceException& dserror)
{
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices Error", dserror));
+ SetPythonException(dserror);
return NULL;
}
catch(...)
@@ -129,9 +129,9 @@
// Get attribute map
return _QueryRecordsWithAttributes(attr, value, matchType, NULL, casei, recordType, attributes);
}
- catch(long dserror)
+ catch(SDirectoryServiceException& dserror)
{
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices Error", dserror));
+ SetPythonException(dserror);
return NULL;
}
catch(...)
@@ -160,9 +160,9 @@
// Get attribute map
return _QueryRecordsWithAttributes(NULL, NULL, 0, query, casei, recordType, attributes);
}
- catch(long dserror)
+ catch(SDirectoryServiceException& dserror)
{
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices Error", dserror));
+ SetPythonException(dserror);
return NULL;
}
catch(...)
@@ -188,9 +188,9 @@
result = NativeAuthenticationBasic(guid, user, pswd);
return true;
}
- catch(long dserror)
+ catch(SDirectoryServiceException& dserror)
{
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices Error", dserror));
+ SetPythonException(dserror);
return false;
}
catch(...)
@@ -216,9 +216,9 @@
result = NativeAuthenticationDigest(guid, user, challenge, response, method);
return true;
}
- catch(long dserror)
+ catch(SDirectoryServiceException& dserror)
{
- PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", "DirectoryServices Error", dserror));
+ SetPythonException(dserror);
return false;
}
catch(...)
@@ -390,7 +390,7 @@
CloseNode();
CloseService();
}
- catch(long dsStatus)
+ catch(SDirectoryServiceException& dsStatus)
{
// Cleanup
if (context != NULL)
@@ -624,7 +624,7 @@
CloseNode();
CloseService();
}
- catch(long dsStatus)
+ catch(SDirectoryServiceException& dsStatus)
{
// Cleanup
if (context != NULL)
@@ -800,7 +800,7 @@
long aDataBufSize = sizeof(long) + ::strlen(user) + sizeof(long) + ::strlen(pswd);
authData = ::dsDataBufferAllocate(mDir, aDataBufSize);
if (authData == NULL)
- throw eDSNullDataBuff;
+ ThrowIfDSErr(eDSNullDataBuff);
long aCurLength = 0;
long aTempLength = ::strlen(user);
::memcpy(&(authData->fBufferData[aCurLength]), &aTempLength, sizeof(long));
@@ -926,7 +926,7 @@
sizeof(long) + ::strlen(method);
authData = ::dsDataBufferAllocate(mDir, aDataBufSize);
if (authData == NULL)
- throw eDSNullDataBuff;
+ ThrowIfDSErr(eDSNullDataBuff);
long aCurLength = 0;
long aTempLength = ::strlen(user);
::memcpy(&(authData->fBufferData[aCurLength]), &aTempLength, sizeof(long));
@@ -1009,7 +1009,7 @@
if (dirStatus != eDSNoErr)
{
mDir = 0L;
- throw dirStatus;
+ ThrowIfDSErr(dirStatus);
}
}
}
@@ -1065,7 +1065,7 @@
else
{
result = NULL;
- throw dirStatus;
+ ThrowIfDSErr(dirStatus);
}
dirStatus = ::dsDataListDeallocate(mDir, nodePath);
free(nodePath);
@@ -1110,7 +1110,7 @@
mData = ::dsDataBufferAllocate(mDir, cBufferSize);
if (mData == NULL)
{
- throw eDSNullDataBuff;
+ ThrowIfDSErr(eDSNullDataBuff);
}
mDataSize = cBufferSize;
}
@@ -1139,7 +1139,7 @@
mData = ::dsDataBufferAllocate(mDir, 2 * mDataSize);
if (mData == NULL)
{
- throw eDSNullDataBuff;
+ ThrowIfDSErr(eDSNullDataBuff);
}
mDataSize *= 2;
}
@@ -1184,3 +1184,19 @@
result[len] = 0;
return result;
}
+
+void CDirectoryService::ThrowDSError(long error, const char* file, long line)
+{
+ CDirectoryService::SDirectoryServiceException dirStatus;
+ dirStatus.mDSError = error;
+ ::snprintf(dirStatus.mDescription, 1024, "Exception raised in file %s at line %ld", file, line);
+ throw dirStatus;
+}
+
+void CDirectoryService::SetPythonException(const SDirectoryServiceException& ex)
+{
+ char error[1024];
+ ::snprintf(error, 1024, "%s %s", "DirectoryServices Error:", ex.mDescription);
+ PyErr_SetObject(ODException_class, Py_BuildValue("((s:i))", error, ex.mDSError));
+}
+
Modified: PyOpenDirectory/trunk/src/CDirectoryService.h
===================================================================
--- PyOpenDirectory/trunk/src/CDirectoryService.h 2007-05-17 16:56:17 UTC (rev 1533)
+++ PyOpenDirectory/trunk/src/CDirectoryService.h 2007-05-17 19:29:34 UTC (rev 1534)
@@ -40,6 +40,13 @@
bool AuthenticateUserDigest(const char* guid, const char* user, const char* challenge, const char* response, const char* method, bool& result);
private:
+
+ struct SDirectoryServiceException
+ {
+ long mDSError;
+ char mDescription[1024];
+ };
+
const char* mNodeName;
tDirReference mDir;
tDirNodeReference mNode;
@@ -70,4 +77,7 @@
char* CStringFromBuffer(tDataBufferPtr data);
char* CStringFromData(const char* data, size_t len);
+
+ void ThrowDSError(long error, const char* file, long line);
+ void SetPythonException(const SDirectoryServiceException& ex);
};
Copied: PyOpenDirectory/trunk/test_auth.py (from rev 1533, PyOpenDirectory/branches/users/cdaboo/better-errors-1318/test_auth.py)
===================================================================
--- PyOpenDirectory/trunk/test_auth.py (rev 0)
+++ PyOpenDirectory/trunk/test_auth.py 2007-05-17 19:29:34 UTC (rev 1534)
@@ -0,0 +1,201 @@
+#!/usr/bin/env python
+
+from getpass import getpass
+import opendirectory
+import dsattributes
+import md5
+import sha
+
+algorithms = {
+ 'md5': md5.new,
+ 'md5-sess': md5.new,
+ 'sha': sha.new,
+}
+
+# DigestCalcHA1
+def calcHA1(
+ pszAlg,
+ pszUserName,
+ pszRealm,
+ pszPassword,
+ pszNonce,
+ pszCNonce,
+ preHA1=None
+):
+ """
+ @param pszAlg: The name of the algorithm to use to calculate the digest.
+ Currently supported are md5 md5-sess and sha.
+
+ @param pszUserName: The username
+ @param pszRealm: The realm
+ @param pszPassword: The password
+ @param pszNonce: The nonce
+ @param pszCNonce: The cnonce
+
+ @param preHA1: If available this is a str containing a previously
+ calculated HA1 as a hex string. If this is given then the values for
+ pszUserName, pszRealm, and pszPassword are ignored.
+ """
+
+ if (preHA1 and (pszUserName or pszRealm or pszPassword)):
+ raise TypeError(("preHA1 is incompatible with the pszUserName, "
+ "pszRealm, and pszPassword arguments"))
+
+ if preHA1 is None:
+ # We need to calculate the HA1 from the username:realm:password
+ m = algorithms[pszAlg]()
+ m.update(pszUserName)
+ m.update(":")
+ m.update(pszRealm)
+ m.update(":")
+ m.update(pszPassword)
+ HA1 = m.digest()
+ else:
+ # We were given a username:realm:password
+ HA1 = preHA1.decode('hex')
+
+ if pszAlg == "md5-sess":
+ m = algorithms[pszAlg]()
+ m.update(HA1)
+ m.update(":")
+ m.update(pszNonce)
+ m.update(":")
+ m.update(pszCNonce)
+ HA1 = m.digest()
+
+ return HA1.encode('hex')
+
+# DigestCalcResponse
+def calcResponse(
+ HA1,
+ algo,
+ pszNonce,
+ pszNonceCount,
+ pszCNonce,
+ pszQop,
+ pszMethod,
+ pszDigestUri,
+ pszHEntity,
+):
+ m = algorithms[algo]()
+ m.update(pszMethod)
+ m.update(":")
+ m.update(pszDigestUri)
+ if pszQop == "auth-int":
+ m.update(":")
+ m.update(pszHEntity)
+ HA2 = m.digest().encode('hex')
+
+ m = algorithms[algo]()
+ m.update(HA1)
+ m.update(":")
+ m.update(pszNonce)
+ m.update(":")
+ if pszNonceCount and pszCNonce and pszQop:
+ m.update(pszNonceCount)
+ m.update(":")
+ m.update(pszCNonce)
+ m.update(":")
+ m.update(pszQop)
+ m.update(":")
+ m.update(HA2)
+ respHash = m.digest().encode('hex')
+ return respHash
+
+
+attempts = 100
+
+realm = "/Search"
+nonce = "128446648710842461101646794502"
+nc = "00000001"
+cnonce = "0a4f113b12345"
+uri = "/principals/"
+method = "GET"
+
+def doAuthDigest(username, password, qop, algorithm):
+ failures = 0
+
+ result = opendirectory.queryRecordsWithAttribute(
+ od,
+ dsattributes.kDSNAttrRecordName,
+ username,
+ dsattributes.eDSExact,
+ False,
+ dsattributes.kDSStdRecordTypeUsers,
+ [dsattributes.kDS1AttrGeneratedUID])
+ guid = result[username][dsattributes.kDS1AttrGeneratedUID]
+
+ 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 x in xrange(attempts):
+ success = opendirectory.authenticateUserDigest(
+ od,
+ guid,
+ 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):
+ failures = 0
+
+ result = opendirectory.queryRecordsWithAttribute(
+ od,
+ dsattributes.kDSNAttrRecordName,
+ username,
+ dsattributes.eDSExact,
+ False,
+ dsattributes.kDSStdRecordTypeUsers,
+ [dsattributes.kDS1AttrGeneratedUID])
+ guid = result[username][dsattributes.kDS1AttrGeneratedUID]
+
+ for x in xrange(attempts):
+ success = opendirectory.authenticateUserBasic(
+ od,
+ guid,
+ username,
+ password,
+ )
+
+ if not success:
+ failures += 1
+
+ print "\n%d failures out of %d attempts for Basic.\n\n" % (failures, attempts)
+
+search = raw_input("DS search path: ")
+user = raw_input("User: ")
+pswd = getpass("Password: ")
+
+od = opendirectory.odInit(search)
+
+doAuthBasic(user, pswd)
+doAuthDigest(user, pswd, None, "md5")
+#doAuth(user, pswd, "auth", "md5")
+#doAuth(user, pswd, "auth", "md5-sess")
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20070517/cc682e22/attachment.html
More information about the calendarserver-changes
mailing list