diff --git a/PyKAdminErrors.c b/PyKAdminErrors.c index a7940a7c43a49c43f68715fed2f00d91d83cb602..33a97b65c1b9d481ceb63bf3732bfd016af29cb1 100644 --- a/PyKAdminErrors.c +++ b/PyKAdminErrors.c @@ -4,10 +4,13 @@ static PyObject *_pykadmin_error_base; static PyObject *_pykadmin_errors; -//static PyObject *_pykadmin_kadm_errors; +//static PyObject *_pykadmin_kadm_errors; //static PyObject *_pykadmin_krb5_errors; -/* +/* + + k5-int.h + Initialize Error Classes kadmin.KAdminError(exceptions.Exception) @@ -24,7 +27,7 @@ int PyKAdminError_init_kdb(PyObject *module, PyObject *base); PyObject *PyKAdminError_init(PyObject *module) { - + static const char kBASE_ERROR[] = "KAdminError"; static const char kKADM_ERROR[] = "AdminError"; static const char kKRB5_ERROR[] = "KerberosError"; @@ -66,19 +69,16 @@ PyObject *PyKAdminError_init(PyObject *module) { PyKAdminError_kdb = PyErr_NewException(cname, _pykadmin_error_base, NULL); if (PyKAdminError_kadm) { - //Py_INCREF(PyKAdminError_kadm); PyModule_AddObject(module, kKADM_ERROR, PyKAdminError_kadm); PyKAdminError_init_kadm(module, PyKAdminError_kadm); } if (PyKAdminError_krb5) { - //Py_INCREF(PyKAdminError_krb5); PyModule_AddObject(module, kKRB5_ERROR, PyKAdminError_krb5); PyKAdminError_init_krb5(module, PyKAdminError_krb5); } if (PyKAdminError_kdb) { - //Py_INCREF(PyKAdminError_krb5); PyModule_AddObject(module, kKDB_ERROR, PyKAdminError_kdb); PyKAdminError_init_kdb(module, PyKAdminError_kdb); } @@ -110,8 +110,8 @@ static void _PyKAdminError_raise_exception(PyObject *storage, PyObject *error, c error_tuple = PyDict_GetItem(storage, error); if (error_tuple && (PyTuple_GET_SIZE(error_tuple) == 2)) { - error_object = PyTuple_GetItem(error_tuple, 0); - error_string = PyTuple_GetItem(error_tuple, 1); + error_object = PyTuple_GetItem(error_tuple, 0); + error_string = PyTuple_GetItem(error_tuple, 1); } } @@ -130,39 +130,47 @@ static void _PyKAdminError_raise_exception(PyObject *storage, PyObject *error, c } + Py_DECREF(error); Py_XDECREF(error_dict); } void PyKAdminError_raise_error(long value, char *caller) { + PyObject *error = PyLong_FromLong((long)value); _PyKAdminError_raise_exception(_pykadmin_errors, error, caller); } /* +void PyKAdminError_raise_kadm_error(kadm5_ret_t value, char *caller) { -void PyKAdminError_raise_error(krb5_error_code code, char *caller) { - PyObject *error = PyLong_FromLong((long)code); + PyObject *error = PyLong_FromLong((long)(value)); _PyKAdminError_raise_exception(_pykadmin_errors, error, caller); } -void PyKAdminError_raise_error(kadm5_ret_t retval, char *caller) { - PyObject *error = PyLong_FromLong((long)retval); +void PyKAdminError_raise_krb5_error(krb5_error_code value, char *caller) { + + PyObject *error = PyLong_FromLong((long)(value)); _PyKAdminError_raise_exception(_pykadmin_errors, error, caller); } -*/ +void PyKAdminError_raise_kdb_error(krb5_error_code value, char *caller) { + + PyObject *error = PyLong_FromLong((long)(value)); + _PyKAdminError_raise_exception(_pykadmin_errors, error, caller); + +*/ static int PyKAdminErrors_new_exception(PyObject *module, PyObject *base, PyObject *storage, PyObject *error, char *name, char *cname, char *message) { - int result = 0; + int result = 0; PyObject *exception = NULL; PyObject *tuple = NULL; if (module && base && storage && error && name && cname && message) { exception = PyErr_NewException(cname, base, NULL); - + if (exception) { result = PyModule_AddObject(module, name, exception); @@ -181,8 +189,8 @@ static int PyKAdminErrors_new_exception(PyObject *module, PyObject *base, PyObje } static int _pykadminerror_error_insert(PyObject *module, PyObject *base, krb5_error_code code, char *name, char *message) { - - int result = 0; + + int result = 0; char *cname = NULL; size_t length = strlen(kMODULE_NAME) + strlen(name) + 0xF; PyObject *error = PyLong_FromLong((long)code); @@ -191,7 +199,7 @@ static int _pykadminerror_error_insert(PyObject *module, PyObject *base, krb5_er cname = malloc(length); - if (cname) { + if (cname) { snprintf(cname, length, "%s.%s", kMODULE_NAME, name); result = PyKAdminErrors_new_exception(module, base, _pykadmin_errors, error, name, cname, message); free(cname); @@ -201,90 +209,46 @@ static int _pykadminerror_error_insert(PyObject *module, PyObject *base, krb5_er return result; } -/* -static int _pykadminerror_error_insert(PyObject *module, PyObject *base, krb5_error_code code, char *name, char *message) { - - int result = 0; - char *cname = NULL; - size_t length = strlen(kMODULE_NAME) + strlen(name) + 0xF; - PyObject *error = PyLong_FromLong(code); - - if (error) { - - cname = malloc(length); - - if (cname) { - snprintf(cname, length, "%s.%s", kMODULE_NAME, name); - result = PyKAdminErrors_new_exception(module, base, _pykadmin_krb5_errors, error, name, cname, message); - free(cname); - } - } - - return result; -} - - -static int _pykadminerror_error_insert(PyObject *module, PyObject *base, kadm5_ret_t retval, char *name, char *message) { - - int result = 0; - char *cname = NULL; - size_t length = strlen(kMODULE_NAME) + strlen(name) + 0xF; - PyObject *error = PyLong_FromUnsignedLong(retval); - - if (error) { - - cname = malloc(length); - - if (cname) { - snprintf(cname, length, "%s.%s", kMODULE_NAME, name); - result = PyKAdminErrors_new_exception(module, base, _pykadmin_kadm_errors, error, name, cname, message); - free(cname); - } - } - - return result; -} -*/ - - int PyKAdminError_init_krb5(PyObject *module, PyObject *base) { - int result = 0; + int result = 0; //_pykadmin_krb5_errors = PyDict_New(); if (_pykadmin_errors) { - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_NONE, "KDCNoneError", "No error"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_NAME_EXP, "KDCClientExpiredError", "Client's entry in database has expired"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_SERVICE_EXP, "KDCServerExpireError", "Server's entry in database has expired"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_BAD_PVNO, "KDCProtocolVersionError", "Requested protocol version not supported"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_C_OLD_MAST_KVNO, "KDCClientOldMasterKeyError", "Client's key is encrypted in an old master key"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_S_OLD_MAST_KVNO, "KDCServerOldMasterKeyError", "Server's key is encrypted in an old master key"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, "KDCClientNotFoundError", "Client not found in Kerberos database"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, "KDCServerNotFoundError", "Server not found in Kerberos database"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, "KDCPrincipalUniqueError", "Principal has multiple entries in Kerberos database"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_NULL_KEY, "KDCNullKeyError", "Client or server has a null key"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_CANNOT_POSTDATE, "KDCCannotPostdateError", "Ticket is ineligible for postdating"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_NEVER_VALID, "KDCNeverValidError", "Requested effective lifetime is negative or too short"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_POLICY, "KDCPolicyError", "KDC policy rejects request"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_BADOPTION, "KDCOptionError", "KDC can't fulfill requested option"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_ETYPE_NOSUPP, "KDCEncryptionSupportError", "KDC has no support for encryption type"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_SUMTYPE_NOSUPP, "KDCChecksumSupportError", "KDC has no support for checksum type"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_PADATA_TYPE_NOSUPP, "KDCPADataSupportError", "KDC has no support for padata type"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_TRTYPE_NOSUPP, "KDCTypeSupportError", "KDC has no support for transited type"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_CLIENT_REVOKED, "KDCClientRevokedError", "Clients credentials have been revoked"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_SERVICE_REVOKED, "KDCServerRevokedError", "Credentials for server have been revoked"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_TGT_REVOKED, "KDCTGTRevokedError", "TGT has been revoked"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_CLIENT_NOTYET, "KDCClientNotYetValidError", "Client not yet valid - try again later"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_SERVICE_NOTYET, "KDCServerNotYetValidError", "Server not yet valid - try again later"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_KEY_EXP, "KDCPasswordExpiredError", "Password has expired"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_PREAUTH_FAILED, "KDCPreauthFailedError", "Preauthentication failed"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_PREAUTH_REQUIRED, "KDCPreauthRequiredError", "Additional pre-authentication required"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_SERVER_NOMATCH, "KDCServerMatchError", "Requested server and ticket don't match"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_MUST_USE_USER2USER, "KDCRequireUser2UserError", "Server principal valid for user2user only"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_PATH_NOT_ACCEPTED, "KDCPathError", "KDC policy rejects transited path"); - _pykadminerror_error_insert(module, base, KRB5KDC_ERR_SVC_UNAVAILABLE, "KDCServiceUnavailableError", "A service is not available that is required to process the request"); - + /* Errors defined by /usr/include/krb5/krb5.h */ + + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_NONE, "KRB5KDCNoneError", "No error"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_NAME_EXP, "KRB5KDCClientExpiredError", "Client's entry in database has expired"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_SERVICE_EXP, "KRB5KDCServerExpireError", "Server's entry in database has expired"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_BAD_PVNO, "KRB5KDCProtocolVersionError", "Requested protocol version not supported"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_C_OLD_MAST_KVNO, "KRB5KDCClientOldMasterKeyError", "Client's key is encrypted in an old master key"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_S_OLD_MAST_KVNO, "KRB5KDCServerOldMasterKeyError", "Server's key is encrypted in an old master key"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, "KRB5KDCClientNotFoundError", "Client not found in Kerberos database"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, "KRB5KDCServerNotFoundError", "Server not found in Kerberos database"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, "KRB5KDCPrincipalUniqueError", "Principal has multiple entries in Kerberos database"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_NULL_KEY, "KRB5KDCNullKeyError", "Client or server has a null key"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_CANNOT_POSTDATE, "KRB5KDCCannotPostdateError", "Ticket is ineligible for postdating"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_NEVER_VALID, "KRB5KDCNeverValidError", "Requested effective lifetime is negative or too short"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_POLICY, "KRB5KDCPolicyError", "KDC policy rejects request"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_BADOPTION, "KRB5KDCOptionError", "KDC can't fulfill requested option"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_ETYPE_NOSUPP, "KRB5KDCEncryptionSupportError", "KDC has no support for encryption type"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_SUMTYPE_NOSUPP, "KRB5KDCChecksumSupportError", "KDC has no support for checksum type"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_PADATA_TYPE_NOSUPP, "KRB5KDCPADataSupportError", "KDC has no support for padata type"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_TRTYPE_NOSUPP, "KRB5KDCTypeSupportError", "KDC has no support for transited type"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_CLIENT_REVOKED, "KRB5KDCClientRevokedError", "Clients credentials have been revoked"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_SERVICE_REVOKED, "KRB5KDCServerRevokedError", "Credentials for server have been revoked"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_TGT_REVOKED, "KRB5KDCTGTRevokedError", "TGT has been revoked"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_CLIENT_NOTYET, "KRB5KDCClientNotYetValidError", "Client not yet valid - try again later"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_SERVICE_NOTYET, "KRB5KDCServerNotYetValidError", "Server not yet valid - try again later"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_KEY_EXP, "KRB5KDCPasswordExpiredError", "Password has expired"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_PREAUTH_FAILED, "KRB5KDCPreauthFailedError", "Preauthentication failed"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_PREAUTH_REQUIRED, "KRB5KDCPreauthRequiredError", "Additional pre-authentication required"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_SERVER_NOMATCH, "KRB5KDCServerMatchError", "Requested server and ticket don't match"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_MUST_USE_USER2USER, "KRB5KDCRequireUser2UserError", "Server principal valid for user2user only"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_PATH_NOT_ACCEPTED, "KRB5KDCPathError", "KDC policy rejects transited path"); + _pykadminerror_error_insert(module, base, KRB5KDC_ERR_SVC_UNAVAILABLE, "KRB5KDCServiceUnavailableError", "A service is not available that is required to process the request"); + // think AP stands for authentication or application protocol ? not sure _pykadminerror_error_insert(module, base, KRB5KRB_AP_ERR_BAD_INTEGRITY, "APIntegrityError", "Decrypt integrity check failed"); _pykadminerror_error_insert(module, base, KRB5KRB_AP_ERR_TKT_EXPIRED, "APTicketExpiredError", "Ticket expired"); @@ -422,7 +386,7 @@ int PyKAdminError_init_krb5(PyObject *module, PyObject *base) { _pykadminerror_error_insert(module, base, KRB5_BAD_ENCTYPE, "EncryptionTypeError", "Bad encryption type"); _pykadminerror_error_insert(module, base, KRB5_BAD_KEYSIZE, "KeySizeError", "Key size is incompatible with encryption type"); _pykadminerror_error_insert(module, base, KRB5_BAD_MSIZE, "MessageSizeError", "Message size is incompatible with encryption type"); - + _pykadminerror_error_insert(module, base, KRB5_CC_TYPE_EXISTS, "CCTypeExistsError", "Credentials cache type is already registered."); _pykadminerror_error_insert(module, base, KRB5_KT_TYPE_EXISTS, "KTTypeExistsError", "Key table type is already registered."); @@ -445,21 +409,21 @@ int PyKAdminError_init_krb5(PyObject *module, PyObject *base) { _pykadminerror_error_insert(module, base, KRB5_PREAUTH_BAD_TYPE, "PreauthTypeError", "Unsupported preauthentication type"); _pykadminerror_error_insert(module, base, KRB5_PREAUTH_NO_KEY, "PreauthKeyError", "Required preauthentication key not supplied"); _pykadminerror_error_insert(module, base, KRB5_PREAUTH_FAILED, "PreauthGenericError", "Generic preauthentication failure"); - + _pykadminerror_error_insert(module, base, KRB5_RCACHE_BADVNO, "RCVserionNumberError", "Unsupported replay cache format version number"); _pykadminerror_error_insert(module, base, KRB5_CCACHE_BADVNO, "CCVserionNumberError", "Unsupported credentials cache format version number"); _pykadminerror_error_insert(module, base, KRB5_KEYTAB_BADVNO, "KTVersionNumberError", "Unsupported key table format version number"); _pykadminerror_error_insert(module, base, KRB5_PROG_ATYPE_NOSUPP, "ProgramAddressTypeError", "Program lacks support for address type"); - + _pykadminerror_error_insert(module, base, KRB5_RC_REQUIRED, "RCRequiredError", "Message replay detection requires rcache parameter"); - + _pykadminerror_error_insert(module, base, KRB5_ERR_BAD_HOSTNAME, "HostnameError", "Hostname cannot be canonicalized"); _pykadminerror_error_insert(module, base, KRB5_ERR_HOST_REALM_UNKNOWN, "HostRealmUnknownError", "Cannot determine realm for host"); _pykadminerror_error_insert(module, base, KRB5_SNAME_UNSUPP_NAMETYPE, "ServiceNameUnsupportedError", "Conversion to service principal undefined for name type"); - + _pykadminerror_error_insert(module, base, KRB5KRB_AP_ERR_V4_REPLY, "APV4ReplyError", "Initial Ticket response appears to be Version 4 error"); - + _pykadminerror_error_insert(module, base, KRB5_REALM_CANT_RESOLVE, "RealmResolveError", "Cannot resolve network address for KDC in requested realm"); _pykadminerror_error_insert(module, base, KRB5_TKT_NOT_FORWARDABLE, "TicketNotForwardableError", "Requesting ticket can't get forwardable tickets"); _pykadminerror_error_insert(module, base, KRB5_FWD_BAD_PRINCIPAL, "ForwardPrincipalError", "Bad principal name while trying to forward credentials"); @@ -479,7 +443,7 @@ int PyKAdminError_init_krb5(PyObject *module, PyObject *base) { _pykadminerror_error_insert(module, base, KRB5_NOPERM_ETYPE, "EncryptionTypeError", "Encryption type not permitted"); _pykadminerror_error_insert(module, base, KRB5_CONFIG_ETYPE_NOSUPP, "ConfigEncryptionTypeError", "No supported encryption types (config file error?)"); _pykadminerror_error_insert(module, base, KRB5_OBSOLETE_FN, "ObsoleteFunctionError", "Program called an obsolete, deleted function"); - + _pykadminerror_error_insert(module, base, KRB5_EAI_FAIL, "EAIGenericError", "unknown getaddrinfo failure"); _pykadminerror_error_insert(module, base, KRB5_EAI_NODATA, "EAINoDataError", "no data available for host/domain name"); _pykadminerror_error_insert(module, base, KRB5_EAI_NONAME, "EAINoNameError", "host/domain name not found"); @@ -499,8 +463,8 @@ int PyKAdminError_init_krb5(PyObject *module, PyObject *base) { _pykadminerror_error_insert(module, base, KRB5_LOCAL_ADDR_REQUIRED, "LocalAddressRequiredError", "Auth context must contain local address"); _pykadminerror_error_insert(module, base, KRB5_REMOTE_ADDR_REQUIRED, "RemoteAddressRequiredError", "Auth context must contain remote address"); _pykadminerror_error_insert(module, base, KRB5_TRACE_NOSUPP, "TraceSupportError", "Tracing unsupported"); - - result = 1; + + result = 1; } return result; @@ -515,7 +479,7 @@ int PyKAdminError_init_kadm(PyObject *module, PyObject *base) { //_pykadmin_kadm_errors = PyDict_New(); if (_pykadmin_errors) { - + _pykadminerror_error_insert(module, base, KADM5_FAILURE, "FailureError", "Operation failed for unspecified reason"); _pykadminerror_error_insert(module, base, KADM5_AUTH_GET, "AuthGetError", "Operation requires ``get'' privilege"); _pykadminerror_error_insert(module, base, KADM5_AUTH_ADD, "AuthAddError", "Operation requires ``add'' privilege"); @@ -578,7 +542,7 @@ int PyKAdminError_init_kadm(PyObject *module, PyObject *base) { # ifdef KADM5_PASS_Q_GENERIC _pykadminerror_error_insert(module, base, KADM5_PASS_Q_GENERIC, "PasswordGenericError", "Database synchronization failed"); # endif - + result = 1; } @@ -587,6 +551,10 @@ int PyKAdminError_init_kadm(PyObject *module, PyObject *base) { } + + + + int PyKAdminError_init_kdb(PyObject *module, PyObject *base) { int result = 0; diff --git a/PyKAdminErrors.h b/PyKAdminErrors.h index ffaeb6db110d43fef48c788943b59e1cf54d87ee..6fb6fb9ebf73fa1f0534d642a5e2889879995127 100644 --- a/PyKAdminErrors.h +++ b/PyKAdminErrors.h @@ -12,16 +12,14 @@ #include "pykadmin.h" -#define PyKAdmin_RETURN_ERROR(value, caller) { PyKAdminError_raise_error((long)value, caller); return NULL; } - -//#define PyKAdmin_RETURN_KADM5_ERROR(retval, caller) { PyKAdminError_raise_kadm_error(retval, caller); return NULL; } -//#define PyKAdmin_RETURN_KRB5_ERROR(code, caller) { PyKAdminError_raise_krb5_error(code, caller); return NULL; } - PyObject *PyKAdminError_init(PyObject *module); -//void PyKAdminError_raise_kadm_error(kadm5_ret_t retval, char *caller); -//void PyKAdminError_raise_krb5_error(krb5_error_code code, char *caller); void PyKAdminError_raise_error(long code, char *caller); +/* +void PyKAdminError_raise_kadm_error(kadm5_ret_t retval, char *caller); +void PyKAdminError_raise_krb5_error(krb5_error_code code, char *caller); +void PyKAdminError_raise_kdb_error(krb5_error_code retval, char *caller); +*/ #endif diff --git a/PyKAdminIterator.c b/PyKAdminIterator.c index 23efd6e6ae3a8fc6c3957d3d1c251e0d0a55b434..a4884b756202755e4d5b1d2e1ceddf1ee8ffe68a 100644 --- a/PyKAdminIterator.c +++ b/PyKAdminIterator.c @@ -85,17 +85,18 @@ PyKAdminIterator *PyKAdminIterator_principal_iterator(PyKAdminObject *kadmin, ch if (iter) { - iter->count = 0x0; - iter->index = 0x0; + iter->count = 0x0; + iter->index = 0x0; - iter->kadmin = kadmin; - Py_INCREF(kadmin); + iter->kadmin = kadmin; + Py_INCREF(kadmin); - retval = kadm5_get_principals(kadmin->server_handle, match, &iter->names, &iter->count); - if (retval != KADM5_OK) { PyKAdmin_RETURN_ERROR(retval, "kadm5_get_principals"); } + retval = kadm5_get_principals(kadmin->server_handle, match, &iter->names, &iter->count); + if (retval != KADM5_OK) { + PyKAdminError_raise_error(retval, "kadm5_get_principals"); + } } - Py_XINCREF(iter); return iter; } @@ -107,17 +108,18 @@ PyKAdminIterator *PyKAdminIterator_policy_iterator(PyKAdminObject *kadmin, char if (iter) { - iter->count = 0x0; - iter->index = 0x0; + iter->count = 0x0; + iter->index = 0x0; - iter->kadmin = kadmin; - Py_INCREF(kadmin); + iter->kadmin = kadmin; + Py_INCREF(kadmin); - retval = kadm5_get_policies(kadmin->server_handle, match, &iter->names, &iter->count); - if (retval != KADM5_OK) { PyKAdmin_RETURN_ERROR(retval, "kadm5_get_policies"); } + retval = kadm5_get_policies(kadmin->server_handle, match, &iter->names, &iter->count); + if (retval != KADM5_OK) { + PyKAdminError_raise_error(retval, "kadm5_get_policies"); + } } - Py_XINCREF(iter); return iter; } diff --git a/PyKAdminObject.c b/PyKAdminObject.c index e70d4ae3a8253cb221d4cdfea1519dc6944981f0..413d382ca220ef87048e43f1c327543f94571525 100644 --- a/PyKAdminObject.c +++ b/PyKAdminObject.c @@ -12,11 +12,14 @@ static void PyKAdminObject_dealloc(PyKAdminObject *self) { kadm5_ret_t retval; if (self) { - krb5_db_unlock(self->context); + + if (self->locked) + krb5_db_unlock(self->context); if (self->server_handle) { retval = kadm5_destroy(self->server_handle); - if (retval) {} + if (retval != KADM5_OK) { + } self->server_handle = NULL; } @@ -44,17 +47,29 @@ static PyObject *PyKAdminObject_new(PyTypeObject *type, PyObject *args, PyObject if (self) { retval = kadm5_init_krb5_context(&self->context); - if (retval != KADM5_OK) { PyKAdmin_RETURN_ERROR(retval, "kadm5_init_krb5_context"); } + if (retval != KADM5_OK) { + PyKAdminError_raise_error(retval, "kadm5_init_krb5_context"); + Py_TYPE(self)->tp_free((PyObject *)self); + self = NULL; + goto cleanup; + } self->server_handle = NULL; // attempt to load the default realm code = krb5_get_default_realm(self->context, &self->realm); - if (code) { PyKAdmin_RETURN_ERROR(code, "krb5_get_default_realm"); } + + /*if (code) { + PyKAdminError_raise_krb5_error(code, "krb5_get_default_realm"); + goto cleanup; + }*/ self->_storage = PyDict_New(); + self->locked = 0; } +cleanup: + return (PyObject *)self; } @@ -81,13 +96,21 @@ static PyObject *PyKAdminObject_principal_exists(PyKAdminObject *self, PyObject if (self->server_handle) { code = krb5_parse_name(self->context, client_name, &princ); - if (code) { PyKAdmin_RETURN_ERROR(retval, "krb5_parse_name"); } + if (code) { + PyKAdminError_raise_error(code, "krb5_parse_name"); + goto cleanup; + } retval = kadm5_get_principal(self->server_handle, princ, &entry, KADM5_PRINCIPAL); if (retval == KADM5_OK) { result = Py_True; } else if (retval == KADM5_UNK_PRINC) { result = Py_False; } - else { PyKAdmin_RETURN_ERROR(retval, "kadm5_delete_principal"); } + else { + PyKAdminError_raise_error(retval, "kadm5_get_principal"); + goto cleanup; + } } + +cleanup: krb5_free_principal(self->context, princ); kadm5_free_principal_ent(self->server_handle, &entry); @@ -104,6 +127,8 @@ static PyObject *PyKAdminObject_delete_principal(PyKAdminObject *self, PyObject krb5_principal princ = NULL; char *client_name = NULL; + + PyObject *result = Py_True; if (!PyArg_ParseTuple(args, "s", &client_name)) return NULL; @@ -111,16 +136,28 @@ static PyObject *PyKAdminObject_delete_principal(PyKAdminObject *self, PyObject if (self->server_handle) { code = krb5_parse_name(self->context, client_name, &princ); - if (code) { PyKAdmin_RETURN_ERROR(retval, "krb5_parse_name"); } + if (code) { + PyKAdminError_raise_error(code, "krb5_parse_name"); + result = NULL; + goto cleanup; + } retval = kadm5_delete_principal(self->server_handle, princ); - if (retval != KADM5_OK) { PyKAdmin_RETURN_ERROR(retval, "kadm5_delete_principal"); } + if (retval != KADM5_OK) { + PyKAdminError_raise_error(retval, "kadm5_delete_principal"); + result = NULL; + goto cleanup; + } } + +cleanup: - krb5_free_principal(self->context, princ); + if (princ) + krb5_free_principal(self->context, princ); - Py_RETURN_TRUE; + Py_XINCREF(result); + return result; } @@ -131,7 +168,9 @@ static PyObject *PyKAdminObject_create_principal(PyKAdminObject *self, PyObject krb5_error_code code = 0; char *princ_name = NULL; char *princ_pass = NULL; - PyDictObject *db_args = NULL; + PyObject *db_args = NULL; + + PyObject *result = Py_True; kadm5_principal_ent_rec entry; @@ -152,16 +191,26 @@ static PyObject *PyKAdminObject_create_principal(PyKAdminObject *self, PyObject if (self->server_handle) { code = krb5_parse_name(self->context, princ_name, &entry.principal); - if (code) { PyKAdmin_RETURN_ERROR(retval, "krb5_parse_name"); } + if (code) { + PyKAdminError_raise_error(code, "krb5_parse_name"); + result = NULL; + goto cleanup; + } - retval = kadm5_create_principal(self->server_handle, &entry, KADM5_PRINCIPAL | KADM5_TL_DATA, princ_pass); - if (retval != KADM5_OK) { PyKAdmin_RETURN_ERROR(retval, "kadm5_create_principal"); } + retval = kadm5_create_principal(self->server_handle, &entry, (KADM5_PRINCIPAL | KADM5_TL_DATA), princ_pass); + if (retval != KADM5_OK) { + PyKAdminError_raise_error(retval, "kadm5_create_principal"); + result = NULL; + } } +cleanup: + kadm5_free_principal_ent(self->server_handle, &entry); - Py_RETURN_TRUE; + Py_XINCREF(result); + return result; } @@ -285,10 +334,12 @@ static int kdb_iter_princs(void *data, krb5_db_entry *kdb) { static PyObject *PyKAdminObject_each_principal(PyKAdminObject *self, PyObject *args, PyObject *kwds) { + PyObject *result = Py_True; char *match = NULL; krb5_error_code code = 0; kadm5_ret_t lock = KADM5_OK; + static char *kwlist[] = {"callback", "data", "match", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|Oz", kwlist, &PyFunction_Type, &self->each_principal.callback, &self->each_principal.data, &match)) @@ -306,26 +357,37 @@ static PyObject *PyKAdminObject_each_principal(PyKAdminObject *self, PyObject *a if ((lock == KADM5_OK) || (lock == KRB5_PLUGIN_OP_NOTSUPP)) { + if (lock == KADM5_OK) + self->locked = 1; + krb5_clear_error_message(self->context); code = krb5_db_iterate(self->context, match, kdb_iter_princs, (void *)self); - if (lock != KRB5_PLUGIN_OP_NOTSUPP) + if (lock != KRB5_PLUGIN_OP_NOTSUPP) { lock = kadm5_unlock(self->server_handle); + if (lock == KADM5_OK) + self->locked = 0; + } } Py_DECREF(self->each_principal.callback); Py_DECREF(self->each_principal.data); - if (code) { PyKAdmin_RETURN_ERROR(code, "krb5_db_iterate"); } + if (code) { + PyKAdminError_raise_error(code, "krb5_db_iterate"); + result = NULL; + goto cleanup; + } if (self->each_principal.error) { _pykadmin_each_restore_error(self->each_principal.error); - return NULL; } +cleanup: - Py_RETURN_TRUE; + Py_XINCREF(result); + return(result); } @@ -362,6 +424,8 @@ static PyObject *PyKAdminObject_each_policy(PyKAdminObject *self, PyObject *args krb5_error_code code = 0; kadm5_ret_t lock = KADM5_OK; + PyObject *result = Py_True; + static char *kwlist[] = {"", "data", "match", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|Oz", kwlist, &PyFunction_Type, &self->each_policy.callback, &self->each_policy.data, &match)) @@ -377,25 +441,38 @@ static PyObject *PyKAdminObject_each_policy(PyKAdminObject *self, PyObject *args if ((lock == KADM5_OK) || (lock == KRB5_PLUGIN_OP_NOTSUPP)) { + if (lock == KADM5_OK) + self->locked = 1; + krb5_clear_error_message(self->context); code = krb5_db_iter_policy(self->context, match, kdb_iter_pols, (void *)self); - if (lock != KRB5_PLUGIN_OP_NOTSUPP) + if (lock != KRB5_PLUGIN_OP_NOTSUPP) { lock = kadm5_unlock(self->server_handle); + if (lock == KADM5_OK) + self->locked = 0; + } } Py_DECREF(self->each_policy.callback); Py_DECREF(self->each_policy.data); - if (code) { PyKAdmin_RETURN_ERROR(code, "krb5_db_iter_policy"); } + if (code) { + PyKAdminError_raise_error(code, "krb5_db_iter_policy"); + result = NULL; + goto cleanup; + } if (self->each_policy.error) { _pykadmin_each_restore_error(self->each_policy.error); - return NULL; + result = NULL; } - Py_RETURN_TRUE; +cleanup: + + Py_XINCREF(result); + return result; } #endif diff --git a/PyKAdminObject.h b/PyKAdminObject.h index 828f731cac4764e666eb88e669fddbc2ad16a915..fe5b305115bdf333afc225f272d9c7b0af8a9c74 100644 --- a/PyKAdminObject.h +++ b/PyKAdminObject.h @@ -18,6 +18,8 @@ typedef struct { typedef struct { PyObject_HEAD + uint8_t locked; + krb5_context context; void *server_handle; char *realm; diff --git a/PyKAdminPrincipalObject.c b/PyKAdminPrincipalObject.c index b23275a6cbfdd3e5e8cb7259561748aabb9b8e1d..9be4e8ec39cb8649f1518f5185039995240adca8 100644 --- a/PyKAdminPrincipalObject.c +++ b/PyKAdminPrincipalObject.c @@ -196,7 +196,7 @@ static PyObject *PyKAdminPrincipal_set_attributes(PyKAdminPrincipalObject *self, self->mask |= KADM5_ATTRIBUTES; //retval = kadm5_modify_principal(self->kadmin->server_handle, &self->entry, KADM5_ATTRIBUTES); - //if (retval != KADM5_OK) { PyKAdminError_raise_error(retval, "kadm5_modify_principal"); return NULL; } + //if (retval != KADM5_OK) { raise_error(retval, "kadm5_modify_principal"); return NULL; } } Py_RETURN_TRUE; @@ -222,46 +222,67 @@ static PyObject *PyKAdminPrincipal_unset_attributes(PyKAdminPrincipalObject *sel static PyObject *PyKAdminPrincipal_commit(PyKAdminPrincipalObject *self) { + PyObject *result = NULL; kadm5_ret_t retval = KADM5_OK; if (self && self->mask) { retval = kadm5_modify_principal(self->kadmin->server_handle, &self->entry, self->mask); - if (retval != KADM5_OK) { PyKAdminError_raise_error(retval, "kadm5_modify_principal"); } + + if (retval == KADM5_OK) { + result = Py_True; + } else { + PyKAdminError_raise_error(retval, "kadm5_modify_principal"); + goto cleanup; + } self->mask = 0; } - Py_RETURN_TRUE; +cleanup: + + Py_XINCREF(result); + return result; } static PyObject *PyKAdminPrincipal_reload(PyKAdminPrincipalObject *self) { - krb5_error_code ret = 0; + PyObject *result = NULL; + + krb5_error_code code = 0; + kadm5_ret_t retval = KADM5_OK; krb5_principal temp = NULL; if (self) { - // we need to free prior to fetching otherwise we leak memory since principal and policy are pointers, alternitively we could manually free those - ret = krb5_copy_principal(self->kadmin->context, self->entry.principal, &temp); - if (ret) {} + code = krb5_copy_principal(self->kadmin->context, self->entry.principal, &temp); + if (code) { + PyKAdminError_raise_error(code, "krb5_copy_principal"); + goto cleanup; + } retval = kadm5_free_principal_ent(self->kadmin->server_handle, &self->entry); - if (retval != KADM5_OK) { PyKAdminError_raise_error(retval, "kadm5_free_principal_ent"); } - - if (retval == KADM5_OK) { - retval = kadm5_get_principal(self->kadmin->server_handle, temp, &self->entry, KADM5_PRINCIPAL_NORMAL_MASK); - if (retval != KADM5_OK) { PyKAdminError_raise_error(retval, "kadm5_get_principal"); } - } + if (retval != KADM5_OK) { + PyKAdminError_raise_error(retval, "kadm5_free_principal_ent"); + goto cleanup; + } - krb5_free_principal(self->kadmin->context, temp); + retval = kadm5_get_principal(self->kadmin->server_handle, temp, &self->entry, KADM5_PRINCIPAL_NORMAL_MASK); + if (retval != KADM5_OK) { + PyKAdminError_raise_error(retval, "kadm5_get_principal"); + goto cleanup; + } - if (retval != KADM5_OK) { return NULL; } } - Py_RETURN_TRUE; +cleanup: + + krb5_free_principal(self->kadmin->context, temp); + + Py_XINCREF(result); + return result; } @@ -272,6 +293,7 @@ static PyObject *PyKAdminPrincipal_unlock(PyKAdminPrincipalObject *self) { static PyObject *PyKAdminPrincipal_change_password(PyKAdminPrincipalObject *self, PyObject *args, PyObject *kwds) { + PyObject *result = Py_True; kadm5_ret_t retval = KADM5_OK; char *password = NULL; @@ -279,19 +301,28 @@ static PyObject *PyKAdminPrincipal_change_password(PyKAdminPrincipalObject *self return NULL; retval = kadm5_chpass_principal(self->kadmin->server_handle, self->entry.principal, password); - if (retval != KADM5_OK) { PyKAdminError_raise_error(retval, "kadm5_chpass_principal"); return NULL; } + if (retval != KADM5_OK) { + PyKAdminError_raise_error(retval, "kadm5_chpass_principal"); + result = NULL; + } - Py_RETURN_TRUE; + Py_XINCREF(result); + return result; } static PyObject *PyKAdminPrincipal_randomize_key(PyKAdminPrincipalObject *self) { + PyObject *result = Py_True; kadm5_ret_t retval = KADM5_OK; retval = kadm5_randkey_principal(self->kadmin->server_handle, self->entry.principal, NULL, NULL); - if (retval != KADM5_OK) { PyKAdminError_raise_error(retval, "kadm5_randkey_principal"); return NULL; } + if (retval != KADM5_OK) { + PyKAdminError_raise_error(retval, "kadm5_randkey_principal"); + result = NULL; + } - Py_RETURN_TRUE; + Py_XINCREF(result); + return result; } PyObject *PyKAdminPrincipal_RichCompare(PyObject *o1, PyObject *o2, int opid) { @@ -331,17 +362,21 @@ PyObject *PyKAdminPrincipal_RichCompare(PyObject *o1, PyObject *o2, int opid) { static PyObject *PyKAdminPrincipal_get_principal(PyKAdminPrincipalObject *self, void *closure) { krb5_error_code code = 0; - PyObject *principal = NULL; - char *client_name = NULL; + PyObject *principal = NULL; + char *client_name = NULL; - // todo: handle krb5_error_code code = krb5_unparse_name(self->kadmin->context, self->entry.principal, &client_name); - if (code) {} + if (code) { + PyKAdminError_raise_error(code, "krb5_unparse_name"); + goto cleanup; + } - if (client_name) { - principal = PyUnicode_FromString(client_name); + principal = PyUnicode_FromString(client_name); + +cleanup: + + if (client_name) free(client_name); - } return principal; } @@ -349,17 +384,22 @@ static PyObject *PyKAdminPrincipal_get_principal(PyKAdminPrincipalObject *self, static PyObject *PyKAdminPrincipal_get_mod_name(PyKAdminPrincipalObject *self, void *closure) { - krb5_error_code ret = 0; - PyObject *principal = NULL; - char *client_name = NULL; + krb5_error_code code = 0; + PyObject *principal = NULL; + char *client_name = NULL; - // todo: handle error - ret = krb5_unparse_name(self->kadmin->context, self->entry.mod_name, &client_name); + code = krb5_unparse_name(self->kadmin->context, self->entry.mod_name, &client_name); + if (code) { + PyKAdminError_raise_error(code, "krb5_unparse_name"); + goto cleanup; + } - if (client_name) { - principal = PyUnicode_FromString(client_name); + principal = PyUnicode_FromString(client_name); + +cleanup: + + if (client_name) free(client_name); - } return principal; } @@ -950,7 +990,7 @@ PyTypeObject PyKAdminPrincipalObject_Type = { PyKAdminPrincipalObject *PyKAdminPrincipalObject_principal_with_name(PyKAdminObject *kadmin, char *client_name) { - krb5_error_code errno; + krb5_error_code code; kadm5_ret_t retval = KADM5_OK; PyKAdminPrincipalObject *principal = (PyKAdminPrincipalObject *)Py_None; @@ -965,12 +1005,13 @@ PyKAdminPrincipalObject *PyKAdminPrincipalObject_principal_with_name(PyKAdminObj Py_INCREF(kadmin); principal->kadmin = kadmin; - errno = krb5_parse_name(kadmin->context, client_name, &temp); + code = krb5_parse_name(kadmin->context, client_name, &temp); + retval = kadm5_get_principal(kadmin->server_handle, temp, &principal->entry, (KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA)); krb5_free_principal(kadmin->context, temp); - if ((retval != KADM5_OK) || errno) { + if ((retval != KADM5_OK) || code) { PyKAdminPrincipal_dealloc(principal); principal = (PyKAdminPrincipalObject *)Py_None; } diff --git a/kadmin.c b/kadmin.c index 650c62094fac115cc7439f4a783aeb091045350b..c9e78ced13d6a1a4a9cf6145c87c1bd7f201707c 100644 --- a/kadmin.c +++ b/kadmin.c @@ -182,19 +182,23 @@ static PyKAdminObject *_kadmin_local(PyObject *self, PyObject *args) { static const char *kROOT_ADMIN = "root/admin"; - PyKAdminObject *kadmin = PyKAdminObject_create(); - PyObject *py_db_args = NULL; - kadm5_ret_t retval = KADM5_OK; - int result = 0; + PyKAdminObject *kadmin = NULL; + PyObject *py_db_args = NULL; char **db_args = NULL; char *client_name = NULL; + kadm5_config_params *params = NULL; + + kadm5_ret_t retval = KADM5_OK; + int result = 0; if (!PyArg_ParseTuple(args, "|O", &py_db_args)) return NULL; - db_args = pykadmin_parse_db_args(py_db_args); + kadmin = PyKAdminObject_create(); + + params = calloc(0x1, sizeof(kadm5_config_params)); - kadm5_config_params *params = calloc(0x1, sizeof(kadm5_config_params)); + db_args = pykadmin_parse_db_args(py_db_args); result = asprintf(&client_name, "%s@%s", kROOT_ADMIN, kadmin->realm); @@ -213,10 +217,22 @@ static PyKAdminObject *_kadmin_local(PyObject *self, PyObject *args) { db_args, &kadmin->server_handle); + if (retval != KADM5_OK) { - pykadmin_free_db_args(db_args); + Py_XDECREF(kadmin); + kadmin = NULL; + + PyKAdminError_raise_error(retval, "kadm5_init_with_password.local"); + + } + + if (client_name) + free(client_name); - if (retval != KADM5_OK) { PyKAdmin_RETURN_ERROR(retval, "kadm5_init_with_password.local"); } + if (params) + free(params); + + pykadmin_free_db_args(db_args); return kadmin; @@ -226,19 +242,20 @@ static PyKAdminObject *_kadmin_local(PyObject *self, PyObject *args) { static PyKAdminObject *_kadmin_init_with_ccache(PyObject *self, PyObject *args) { - PyKAdminObject *kadmin = PyKAdminObject_create(); - PyObject *py_db_args = NULL; - kadm5_ret_t retval = KADM5_OK; - krb5_error_code code = 0; + PyKAdminObject *kadmin = NULL; + PyObject *py_db_args = NULL; + kadm5_ret_t retval = KADM5_OK; + krb5_error_code code = 0; - krb5_principal princ = NULL; - char *ccache_name = NULL; - char *client_name = NULL; - char **db_args = NULL; + krb5_principal princ = NULL; + char *ccache_name = NULL; + char *client_name = NULL; + char *_resolved_client = NULL; + char **db_args = NULL; - krb5_ccache cc; + kadm5_config_params *params = NULL; - kadm5_config_params *params = calloc(0x1, sizeof(kadm5_config_params)); + krb5_ccache cc; memset(&cc, 0, sizeof(krb5_ccache)); @@ -246,29 +263,44 @@ static PyKAdminObject *_kadmin_init_with_ccache(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "|zzO", &client_name, &ccache_name, &py_db_args)) return NULL; + kadmin = PyKAdminObject_create(); + params = calloc(0x1, sizeof(kadm5_config_params)); + db_args = pykadmin_parse_db_args(py_db_args); if (!ccache_name) { code = krb5_cc_default(kadmin->context, &cc); - if (code) { PyKAdmin_RETURN_ERROR(code, "krb5_cc_default"); } + if (code) { + PyKAdminError_raise_error(code, "krb5_cc_default"); + goto cleanup; + } } else { code = krb5_cc_resolve(kadmin->context, ccache_name, &cc); - if (code) { PyKAdmin_RETURN_ERROR(code, "krb5_cc_resolve"); } + if (code) { + PyKAdminError_raise_error(code, "krb5_cc_resolve"); + goto cleanup; + } } - if (!client_name) { - code = krb5_cc_get_principal(kadmin->context, cc, &princ); - if (code) { PyKAdmin_RETURN_ERROR(code, "krb5_cc_get_principal"); } - - code = krb5_unparse_name(kadmin->context, princ, &client_name); - if (code) { PyKAdmin_RETURN_ERROR(code, "krb5_unparse_name"); } + _resolved_client = client_name; - krb5_free_principal(kadmin->context, princ); + if (!_resolved_client) { + code = krb5_cc_get_principal(kadmin->context, cc, &princ); + if (code) { + PyKAdminError_raise_error(code, "krb5_cc_get_principal"); + goto cleanup; + } + + code = krb5_unparse_name(kadmin->context, princ, &_resolved_client); + if (code) { + PyKAdminError_raise_error(code, "krb5_unparse_name"); + goto cleanup; + } } retval = kadm5_init_with_creds( kadmin->context, - client_name, + _resolved_client, cc, service_name, params, @@ -277,9 +309,29 @@ static PyKAdminObject *_kadmin_init_with_ccache(PyObject *self, PyObject *args) db_args, &kadmin->server_handle); - pykadmin_free_db_args(db_args); + if (retval != KADM5_OK) { + + Py_XDECREF(kadmin); + kadmin = NULL; + + PyKAdminError_raise_error(retval, "kadm5_init_with_creds"); + } + + +cleanup: + + // we only clean up _resolved_client if we calculated it, otherwise it is + // an internal pointer of a python object and freeing it will be illegal. + if ((client_name == NULL) && _resolved_client) + free(_resolved_client); + + krb5_free_principal(kadmin->context, princ); + krb5_cc_close(kadmin->context, cc); - if (retval != KADM5_OK) { PyKAdmin_RETURN_ERROR(retval, "kadm5_init_with_creds"); } + if (params) + free(params); + + pykadmin_free_db_args(db_args); return kadmin; } @@ -288,10 +340,10 @@ static PyKAdminObject *_kadmin_init_with_ccache(PyObject *self, PyObject *args) static PyKAdminObject *_kadmin_init_with_keytab(PyObject *self, PyObject *args) { - PyKAdminObject *kadmin = PyKAdminObject_create(); + PyKAdminObject *kadmin = NULL; PyObject *py_db_args = NULL; - kadm5_ret_t retval = KADM5_OK; + kadm5_ret_t retval = KADM5_OK; krb5_error_code code = 0; krb5_principal princ = NULL; @@ -299,11 +351,14 @@ static PyKAdminObject *_kadmin_init_with_keytab(PyObject *self, PyObject *args) char *keytab_name = NULL; char **db_args = NULL; - kadm5_config_params *params = calloc(0x1, sizeof(kadm5_config_params)); + kadm5_config_params *params = NULL; if (!PyArg_ParseTuple(args, "|zzO", &client_name, &keytab_name, &py_db_args)) return NULL; + kadmin = PyKAdminObject_create(); + params = calloc(0x1, sizeof(kadm5_config_params)); + db_args = pykadmin_parse_db_args(py_db_args); if (keytab_name == NULL) { @@ -313,15 +368,18 @@ static PyKAdminObject *_kadmin_init_with_keytab(PyObject *self, PyObject *args) if (client_name == NULL) { code = krb5_sname_to_principal(kadmin->context, NULL, "host", KRB5_NT_SRV_HST, &princ); - if (code) { PyKAdmin_RETURN_ERROR(code, "krb5_sname_to_principal"); } + if (code) { + PyKAdminError_raise_error(code, "krb5_sname_to_principal"); + goto cleanup; + } code = krb5_unparse_name(kadmin->context, princ, &client_name); - if (code) { PyKAdmin_RETURN_ERROR(code, "krb5_unparse_name"); } - - krb5_free_principal(kadmin->context, princ); + if (code) { + PyKAdminError_raise_error(code, "krb5_unparse_name"); + goto cleanup; + } } - retval = kadm5_init_with_skey( kadmin->context, client_name, @@ -333,9 +391,23 @@ static PyKAdminObject *_kadmin_init_with_keytab(PyObject *self, PyObject *args) db_args, &kadmin->server_handle); - pykadmin_free_db_args(db_args); + if (retval != KADM5_OK) { - if (retval != KADM5_OK) { PyKAdmin_RETURN_ERROR(retval, "kadm5_init_with_skey"); } + Py_XDECREF(kadmin); + kadmin = NULL; + + PyKAdminError_raise_error(retval, "kadm5_init_with_skey"); + } + +cleanup: + + if (princ) + krb5_free_principal(kadmin->context, princ); + + if (params) + free(params); + + pykadmin_free_db_args(db_args); return kadmin; } @@ -343,19 +415,22 @@ static PyKAdminObject *_kadmin_init_with_keytab(PyObject *self, PyObject *args) static PyKAdminObject *_kadmin_init_with_password(PyObject *self, PyObject *args) { - PyKAdminObject *kadmin = PyKAdminObject_create(); - PyObject *py_db_args = NULL; - kadm5_ret_t retval = KADM5_OK; + PyKAdminObject *kadmin = NULL; + PyObject *py_db_args = NULL; + kadm5_ret_t retval = KADM5_OK; char *client_name = NULL; char *password = NULL; char **db_args = NULL; - kadm5_config_params *params = calloc(0x1, sizeof(kadm5_config_params)); + kadm5_config_params *params = NULL; if (!PyArg_ParseTuple(args, "zz|O", &client_name, &password, &py_db_args)) return NULL; + kadmin = PyKAdminObject_create(); + params = calloc(0x1, sizeof(kadm5_config_params)); + db_args = pykadmin_parse_db_args(py_db_args); retval = kadm5_init_with_password( @@ -369,9 +444,18 @@ static PyKAdminObject *_kadmin_init_with_password(PyObject *self, PyObject *args db_args, &kadmin->server_handle); - pykadmin_free_db_args(db_args); + if (retval != KADM5_OK) { - if (retval != KADM5_OK) { PyKAdmin_RETURN_ERROR(retval, "kadm5_init_with_password"); } + Py_XDECREF(kadmin); + kadmin = NULL; + + PyKAdminError_raise_error(retval, "kadm5_init_with_password"); + } + + if (params) + free(params); + + pykadmin_free_db_args(db_args); return kadmin; diff --git a/pykadmin.h b/pykadmin.h index 61908a034615130a5f0e6250b76d10aaf4ae1b65..61217f5f2fadffb863a844f480999ef6fcc8a79b 100644 --- a/pykadmin.h +++ b/pykadmin.h @@ -8,6 +8,10 @@ struct module_state { PyObject *error; }; +#define Py_XRETURN(obj) { Py_XINCREF(obj); return obj; } + +#define Py_DEBUG_REFCOUNT(obj, str) {fprintf(stderr, "%s: %d\n", str, obj->ob_refcnt);} + #ifdef KADMIN_LOCAL # define kMODULE_NAME "kadmin_local" #else diff --git a/test/bootstrap_kdb.py b/test/bootstrap_kdb.py index 8efde35e111aadcdaadae5df48b18f86313fd0ca..23577e1c6a00b3839e4ea5a8f5e7724ea9eefe46 100644 --- a/test/bootstrap_kdb.py +++ b/test/bootstrap_kdb.py @@ -9,7 +9,7 @@ for a in xrange(97, 98): for c in xrange(97, 123): for d in xrange(97, 123): try: - admin.create_principal(chr(a) + chr(b) + chr(c) + chr(d)); + admin.ank(chr(a) + chr(b) + chr(c) + chr(d)); except kadmin.KAdminError as error: print error pass diff --git a/test/krb5.supp b/test/krb5.supp new file mode 100644 index 0000000000000000000000000000000000000000..bdc7072f764e6520a45c73de33e7dce86faade79 --- /dev/null +++ b/test/krb5.supp @@ -0,0 +1,10 @@ + + +{ + kadm5_init_leaks + Memcheck:Leak + fun:malloc + ... + fun:kadm5_init + ... +} \ No newline at end of file diff --git a/test/unittests.py b/test/unittests.py index 733b0f2ffd9c2860b9a5974aa4fcb1413025d75c..f608cc9a76286096e2308b7fc6527bc4b93ab4cb 100644 --- a/test/unittests.py +++ b/test/unittests.py @@ -1,4 +1,5 @@ +import gc import time import sys import kadmin @@ -6,6 +7,7 @@ import kadmin_local import unittest import subprocess import logging +from pprint import pprint import os.path @@ -31,6 +33,8 @@ def create_test_prinicipal(): if not os.path.isfile(TEST_KEYTAB): + sys.stderr.write("Generating test/admin keytab...\n") + command = ''' spawn kadmin.local -p root@EXAMPLE.COM @@ -280,7 +284,6 @@ class KAdminUnitTests(unittest.TestCase): class KAdminLocalUnitTests(unittest.TestCase): -#class KAdminLocalUnitTests(): ''' Missing in 2.6 ''' def assertIsNotNone(self, expr, msg=None): @@ -291,7 +294,7 @@ class KAdminLocalUnitTests(unittest.TestCase): def setUp(self): - + # let the exception bubble up the test. kadm = kadmin_local.local(); @@ -302,7 +305,7 @@ class KAdminLocalUnitTests(unittest.TestCase): self.logger = logging.getLogger('python-kadmin') - + def test_local(self): try: @@ -374,7 +377,6 @@ class KAdminLocalUnitTests(unittest.TestCase): kadm = self.kadm create_test_accounts() - pre_size = database_size() try: @@ -383,6 +385,7 @@ class KAdminLocalUnitTests(unittest.TestCase): except: self.fail("kadmin_local.ank rasied an error deleting an account.") + post_size = database_size() self.assertEqual(pre_size, len(TEST_ACCOUNTS) + post_size) @@ -494,18 +497,43 @@ class KAdminLocalUnitTests(unittest.TestCase): def main(): - confirm = input('run tests against local kadmin server [yes/no] ? ') + #confirm = input('run tests against local kadmin server [yes/no] ? ') - if confirm.lower() == 'yes': + #if confirm.lower() == 'yes': + if True: create_test_prinicipal() create_ccache() logging.basicConfig(filename=TEST_LOG, format=LOG_FORMAT, level=logging.DEBUG) - unittest.main() + # setup unit tests + + kadmin_tests = unittest.TestLoader().loadTestsFromTestCase(KAdminUnitTests) + kadmin_local_tests = unittest.TestLoader().loadTestsFromTestCase(KAdminLocalUnitTests) + + unittest.TextTestRunner(verbosity=2).run(kadmin_tests) + unittest.TextTestRunner(verbosity=2).run(kadmin_local_tests) + + #unittest.main() + if __name__ == '__main__': main() +# delete global constants + +del TEST_PRINCIPAL +del TEST_KEYTAB +del TEST_CCACHE +del TEST_PASSWORD +del TEST_LOG +del LOG_FORMAT +del TEST_ACCOUNTS + +# collect memory so our valgrind reports clear up any still reachable which shouldnt be +gc.collect() + +pprint(locals()) +pprint(globals()) diff --git a/test/valgrind-python-leaks.supp b/test/valgrind-python-leaks.supp new file mode 100644 index 0000000000000000000000000000000000000000..685bde0d08c643dbb41a58f4f67bc5c67a789263 --- /dev/null +++ b/test/valgrind-python-leaks.supp @@ -0,0 +1,193 @@ +# These are unfreed memory (still reachable blocks) detected in python +# valgrind should not systematically run with these suppressions on, since +# they might potentially hide real leaks (even though we would likely have +# a matching Ada leak in any case), but these suppressions might prove +# useful when analyzing the result of valgrind with --show-reachable=yes + +{ + Python leak + Memcheck:Leak + fun:malloc + fun:* + fun:PyString_InternInPlace +} +{ + Python leak + Memcheck:Leak + fun:malloc + fun:* + fun:PyEval_EvalFrameEx +} +{ + From opensuse 11.2 (python 2.6) + Memcheck:Leak + fun:malloc + obj:*libpython* + fun:PyDict_Merge +} +{ + From opensuse 11.2 (python 2.6) + Memcheck:Leak + fun:malloc + obj:*libpython* + fun:PyObject_GenericSetAttr +} +{ + From opensuse 11.2 (python 2.6) + Memcheck:Leak + fun:malloc + obj:*libpython* + obj:*_gobject.so* + obj:*atk.so* +} +{ + From opensuse 11.2 (python 2.6) + Memcheck:Leak + fun:malloc + obj:*libpython* + obj:*_gobject.so* + obj:*pango.so* + fun:initpango +} +{ + From opensuse 11.2 (python 2.6) + Memcheck:Leak + fun:malloc + obj:*libpython* + obj:*_gobject.so* + obj:*gio.so* + fun:init_gio +} +{ + From opensuse 11.2 (python 2.6) + Memcheck:Leak + fun:realloc + fun:g_realloc + fun:g_type_set_qdata + obj:*_gobject.so* + fun:init_gobject +} +{ + From opensuse 11.2 (python 2.6) + Memcheck:Leak + fun:malloc + obj:*libpython* + obj:*_gobject.so + obj:*_gtk.so + fun:init_gtk +} +{ + From opensuse 11.2 (python 2.6) + Memcheck:Leak + fun:malloc + obj:*libpython* + fun:_PyInt_Init +} +{ + From opensuse 11.2 (python 2.6) + Memcheck:Leak + fun:malloc + obj:*libpython* + fun:PyType_Ready +} +{ + From opensuse 11.2 (python 2.6) + Memcheck:Leak + fun:malloc + fun:PyString_FromStringAndSize +} +{ + From opensuse 11.2 (python 2.6) + Memcheck:Leak + fun:malloc + obj:*libpython* + obj:*libpython* + fun:PyObject_Call +} +{ + From opensuse 11.2 (python 2.6) + Memcheck:Leak + fun:malloc + obj:*libpython* + fun:PyInt_FromLong +} +{ + From opensuse 11.2 (python 2.6) + Memcheck:Leak + fun:malloc + fun:_PyObject_GC_Malloc +} +{ + From opensuse 11.2 (python 2.6) + Memcheck:Leak + fun:malloc + obj:*libpython* + obj:*libpython* + fun:PyEval_EvalFrameEx +} + + +{ + Python leak + Memcheck:Leak + fun:malloc + fun:* + fun:PyDict_SetItemString +} +{ + <insert_a_suppression_name_here> + Memcheck:Leak + fun:malloc + fun:_PyObject_GC_Malloc + fun:PyType_GenericAlloc +} +{ + Python leak (ignore all memory allocated by python itself....) + Memcheck:Leak + fun:malloc + fun:PyObject_Malloc +} +{ + Python leak (ignore all memory allocated by python itself....) + Memcheck:Leak + fun:realloc + fun:_PyObject_GC_Resize +} +{ + Python leak (ignore all memory allocated by python itself....) + Memcheck:Leak + fun:realloc + fun:_PyObject_GC_NewVar +} +{ + Python leak (ignore all memory allocated by python itself....) + Memcheck:Leak + fun:malloc + fun:_PyObject_GC_NewVar +} +{ + Python leak + Memcheck:Leak + fun:malloc + fun:_PyObject_GC_NewVar + fun:PyFrame_New + fun:PyEval_EvalCodeEx + fun:function_call +} +{ + Python leak (Python 2.6) + Memcheck:Leak + fun:malloc + fun:_PyObject_GC_Malloc + fun:_PyObject_GC_NewVar + fun:PyFrame_New +} + + +{ + GNAT does not release the secondary stack + Memcheck:Leak + fun:malloc + fun:gnatcoll__memory__alloc + fun:system__secondary_stack__ss_allocate +}