[CalendarServer-dev] RFC: pykerberos exception handling (Ticket #51)

Guido Guenther agx at sigxcpu.org
Wed Sep 27 06:57:06 PDT 2006


Hi,
attached is a patch that implements basic exception handling in
pykerberos GSS path. This way we can get more information about the what
actually failed (current pykerberos only knows success or AUTH_FAILED).

I'm posting this here for comments:

Things I'm unsure about are:
 * how should the exception format look like? Currently I've chosen:
   (errmsg_maj, errcode_maj)(errmsg_min, errcode_min)
   
   so code like:
   
   try:
	rc = kerberos.authGSSClientStep(vc, "");
   except kerberos.KrbError, a:
	print a

   gives:
    (('Miscellaneous failure', 851968), ('No credentials cache found', -1765328189))

   or in the case the exception is unhandled:
    KrbError: (('Miscellaneous failure', 851968), ('Permission denied', 13))
   
   Should we better choose different exception classes for every type of
   problem (modeled after the error conditions listed in gssapi.h) -
   looks like overkill to me - we can add functions to analyze the error
   code in more detail at any later stage since we pass both major and
   minor code up to the application.
 * What exception classes do we want. What about:
    KrbError as base class
    KrbBasicAuthError(KrbError): exceptions in the basic auch module
    KrbGssAuthError(krbError): excpetions in the GSS module
   
I'd be happy about any comments on this.
Cheers,
 -- Guido
-------------- next part --------------
diff --git a/src/kerberos.c b/src/kerberos.c
index 419827c..1b1e098 100644
--- a/src/kerberos.c
+++ b/src/kerberos.c
@@ -21,6 +21,8 @@ #include <Python.h>
 #include "kerberosbasic.h"
 #include "kerberosgss.h"
 
+PyObject *KrbException_class;
+
 static PyObject *checkPassword(PyObject *self, PyObject *args)
 {
     const char *user;
@@ -54,6 +56,9 @@ static PyObject *authGSSClientInit(PyObj
 	pystate = PyCObject_FromVoidPtr(state, NULL);
 	
 	result = authenticate_gss_client_init(service, state);
+	if(result == AUTH_GSS_ERROR) {
+		return NULL;
+	}
 	
     return Py_BuildValue("(iO)", result, pystate);
 }
@@ -82,8 +87,8 @@ static PyObject *authGSSClientClean(PyOb
 static PyObject *authGSSClientStep(PyObject *self, PyObject *args)
 {
     gss_client_state *state;
-	PyObject *pystate;
-	char *challenge;
+    PyObject *pystate;
+    char *challenge;
     int result = 0;
 	
     if (!PyArg_ParseTuple(args, "Os", &pystate, &challenge) || !PyCObject_Check(pystate))
@@ -94,6 +99,9 @@ static PyObject *authGSSClientStep(PyObj
 		return NULL;
 
 	result = authenticate_gss_client_step(state, challenge);
+	if(result == AUTH_GSS_ERROR) {
+		return NULL;
+	}
 	
     return Py_BuildValue("i", result);
 }
@@ -142,6 +150,9 @@ static PyObject *authGSSServerInit(PyObj
 	pystate = PyCObject_FromVoidPtr(state, NULL);
 	
 	result = authenticate_gss_server_init(service, state);
+	if(result == AUTH_GSS_ERROR) {
+		return NULL;
+	}
 	
     return Py_BuildValue("(iO)", result, pystate);
 }
@@ -182,6 +193,9 @@ static PyObject *authGSSServerStep(PyObj
 		return NULL;
 	
 	result = authenticate_gss_server_step(state, challenge);
+	if(result == AUTH_GSS_ERROR) {
+		return NULL;
+	}
 	
     return Py_BuildValue("i", result);
 }
@@ -216,7 +230,7 @@ static PyObject *authGSSServerUserName(P
     return Py_BuildValue("s", state->username);
 }
 
-static PyMethodDef SpamMethods[] = {
+static PyMethodDef KerberosMethods[] = {
     {"checkPassword",  checkPassword, METH_VARARGS,
 		"Check the supplied user/password against Kerberos KDC."},
     {"authGSSClientInit",  authGSSClientInit, METH_VARARGS,
@@ -244,5 +258,14 @@ static PyMethodDef SpamMethods[] = {
 
 PyMODINIT_FUNC initkerberos(void)
 {
-    (void) Py_InitModule("kerberos", SpamMethods);
+    PyObject *m,*d;
+
+    m=Py_InitModule("kerberos", KerberosMethods);
+
+    d = PyModule_GetDict(m);
+    /* create the base exception class */
+    KrbException_class = PyErr_NewException("kerbros.KrbError", NULL, NULL);
+    PyDict_SetItemString( d, "KrbError", KrbException_class );
+    Py_INCREF(KrbException_class);
 }
+
diff --git a/src/kerberosgss.c b/src/kerberosgss.c
index 7200786..4d2882c 100644
--- a/src/kerberosgss.c
+++ b/src/kerberosgss.c
@@ -16,6 +16,7 @@
  * DRI: Cyrus Daboo, cdaboo at apple.com
  **/
 
+#include <Python.h>
 #include "kerberosgss.h"
 
 #include "base64.h"
@@ -24,17 +25,14 @@ #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#undef PRINTFS
+void set_gss_error(OM_uint32 err_maj, OM_uint32 err_min);
 
-static const char *get_gss_error(char *p, int psize, OM_uint32 err_maj, OM_uint32 err_min, char *prefix);
+extern PyObject *KrbException_class;
 
 int authenticate_gss_client_init(const char* service, gss_client_state *state)
 {
 	OM_uint32 maj_stat;
 	OM_uint32 min_stat;
-#ifdef PRINTFS
-	char buf[1024];
-#endif
 	gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER;
 	int ret = AUTH_GSS_COMPLETE;
 
@@ -45,15 +43,13 @@ #endif
 	
 	// Import server name first
 	name_token.length = strlen(service);
-    name_token.value = (char *)service;
+    	name_token.value = (char *)service;
 	
 	maj_stat = gss_import_name(&min_stat, &name_token, gss_krb5_nt_service_name, &state->server_name);
 	
 	if (GSS_ERROR(maj_stat))
 	{
-#ifdef PRINTFS
-		printf("%s\n", get_gss_error(buf, 1024, maj_stat, min_stat, "gss_import_name() failed"));
-#endif
+		set_gss_error(maj_stat, min_stat);
 		ret = AUTH_GSS_ERROR;
 		goto end;
 	}
@@ -90,9 +86,6 @@ int authenticate_gss_client_step(gss_cli
 {
 	OM_uint32 maj_stat;
 	OM_uint32 min_stat;
-#ifdef PRINTFS
-	char buf[1024];
-#endif
 	gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
 	gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
 	int ret = AUTH_GSS_CONTINUE;
@@ -129,9 +122,7 @@ #endif
 	
 	if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED))
 	{
-#ifdef PRINTFS
-		printf("%s\n", get_gss_error(buf, 1024, maj_stat, min_stat, "gss_init_sec_context() failed"));
-#endif
+		set_gss_error(maj_stat, min_stat);
 		ret = AUTH_GSS_ERROR;
 		goto end;
 	}
@@ -151,9 +142,7 @@ #endif
 	    maj_stat = gss_inquire_context(&min_stat, state->context, &gssuser, NULL, NULL, NULL,  NULL, NULL, NULL);
 		if (GSS_ERROR(maj_stat))
 		{
-#ifdef PRINTFS
-			printf("%s\n", get_gss_error(buf, 1024, maj_stat, min_stat, "gss_inquire_context() failed"));
-#endif
+			set_gss_error(maj_stat, min_stat);
 			ret = AUTH_GSS_ERROR;
 			goto end;
 		}
@@ -167,9 +156,7 @@ #endif
 			    gss_release_buffer(&min_stat, &name_token);
 			gss_release_name(&min_stat, &gssuser);
 			
-#ifdef PRINTFS
-			printf("%s\n", get_gss_error(buf, 1024, maj_stat, min_stat, "gss_display_name() failed"));
-#endif
+			set_gss_error(maj_stat, min_stat);
 			ret = AUTH_GSS_ERROR;
 			goto end;
 		}
@@ -194,9 +181,6 @@ int authenticate_gss_server_init(const c
 {
 	OM_uint32 maj_stat;
 	OM_uint32 min_stat;
-#ifdef PRINTFS
-	char buf[1024];
-#endif
 	gss_buffer_desc name_token = GSS_C_EMPTY_BUFFER;
 	int ret = AUTH_GSS_COMPLETE;
 	
@@ -216,9 +200,7 @@ #endif
 	
 	if (GSS_ERROR(maj_stat))
 	{
-#ifdef PRINTFS
-		printf("%s\n", get_gss_error(buf, 1024, maj_stat, min_stat, "gss_import_name() failed"));
-#endif
+		set_gss_error(maj_stat, min_stat);
 		ret = AUTH_GSS_ERROR;
 		goto end;
 	}
@@ -229,9 +211,7 @@ #endif
 
 	if (GSS_ERROR(maj_stat))
 	{
-#ifdef PRINTFS
-		printf("%s\n", get_gss_error(buf, 1024, maj_stat, min_stat, "gss_acquire_cred() failed"));
-#endif
+		set_gss_error(maj_stat, min_stat);
 		ret = AUTH_GSS_ERROR;
 		goto end;
 	}
@@ -274,9 +254,6 @@ int authenticate_gss_server_step(gss_ser
 {
 	OM_uint32 maj_stat;
 	OM_uint32 min_stat;
-#ifdef PRINTFS
-	char buf[1024];
-#endif
 	gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
 	gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
 	int ret = AUTH_GSS_CONTINUE;
@@ -297,9 +274,7 @@ #endif
 	}
 	else
 	{
-#ifdef PRINTFS
-		printf("No challenge parameter in request from client\n");
-#endif
+		PyErr_SetString(KrbException_class, "No challenge parameter in request from client");
 		ret = AUTH_GSS_ERROR;
 		goto end;
 	}
@@ -318,9 +293,7 @@ #endif
 	
 	if (GSS_ERROR(maj_stat))
 	{
-#ifdef PRINTFS
-		printf("%s\n", get_gss_error(buf, 1024, maj_stat, min_stat, "gss_accept_sec_context() failed"));
-#endif
+		set_gss_error(maj_stat, min_stat);
 		ret = AUTH_GSS_ERROR;
 		goto end;
 	}
@@ -335,9 +308,7 @@ #endif
 	maj_stat = gss_display_name(&min_stat, state->client_name, &output_token, NULL);
 	if (GSS_ERROR(maj_stat))
 	{
-#ifdef PRINTFS
-		printf("%s\n", get_gss_error(buf, 1024, maj_stat, min_stat, "gss_display_name() failed"));
-#endif
+		set_gss_error(maj_stat, min_stat);
 		ret = AUTH_GSS_ERROR;
 		goto end;
 	}
@@ -355,13 +326,15 @@ end:
 	return ret;
 }
 
-const char *get_gss_error(char *p, int psize, OM_uint32 err_maj, OM_uint32 err_min, char *prefix)
+
+void set_gss_error(OM_uint32 err_maj, OM_uint32 err_min)
 {
 	OM_uint32 maj_stat, min_stat; 
 	OM_uint32 msg_ctx = 0;
 	gss_buffer_desc status_string;
+	char buf_maj[512];
+	char buf_min[512];
 	
-	strncpy(p, prefix, psize);
 	do
 	{
 		maj_stat = gss_display_status (&min_stat,
@@ -372,8 +345,7 @@ const char *get_gss_error(char *p, int p
 									   &status_string);
 		if (GSS_ERROR(maj_stat))
 			break;
-		strncat(p, ": ", psize);
-		strncat(p, (char*) status_string.value, psize);
+		strncpy(buf_maj, (char*) status_string.value, sizeof(buf_maj));
 		gss_release_buffer(&min_stat, &status_string);
 		
 		maj_stat = gss_display_status (&min_stat,
@@ -384,12 +356,11 @@ const char *get_gss_error(char *p, int p
 									   &status_string);
 		if (!GSS_ERROR(maj_stat))
 		{
-			strncat(p, " (", psize);
-			strncat(p, (char*) status_string.value, psize);
-			strncat(p, ")", psize);
+			strncpy(buf_min, (char*) status_string.value, sizeof(buf_min));
 			gss_release_buffer(&min_stat, &status_string);
 		}
 	} while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
 	
-	return p;
+	PyErr_SetObject(KrbException_class, Py_BuildValue("((s:i)(s:i))", buf_maj, err_maj, buf_min, err_min));
 }
+


More information about the calendarserver-dev mailing list