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
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, [EMAIL PROTECTED]
  **/
 
+#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));
 }
+
_______________________________________________
calendarserver-dev mailing list
[email protected]
http://lists.macosforge.org/mailman/listinfo/calendarserver-dev

Reply via email to