/** * Copyright (c) 2006-2008 Apple Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ #include #include "kerberosbasic.h" #include #include #include #undef PRINTFS extern PyObject *BasicAuthException_class; static void set_basicauth_error(krb5_context context, krb5_error_code code); static krb5_error_code verify_krb5_user(krb5_context context, krb5_principal principal, const char *password, krb5_principal server); int authenticate_user_krb5pwd(const char *user, const char *pswd, const char *service, const char *default_realm) { krb5_context kcontext = NULL; krb5_error_code code; krb5_principal client = NULL; krb5_principal server = NULL; int ret = 0; char *name = NULL; char *p = NULL; code = krb5_init_context(&kcontext); if (code) { PyErr_SetObject(BasicAuthException_class, Py_BuildValue("((s:i))", "Cannot initialize Kerberos5 context", code)); return 0; } ret = krb5_parse_name (kcontext, service, &server); if (ret) { set_basicauth_error(kcontext, ret); ret = 0; goto end; } code = krb5_unparse_name(kcontext, server, &name); if (code) { set_basicauth_error(kcontext, code); ret = 0; goto end; } #ifdef PRINTFS printf("Using %s as server principal for password verification\n", name); #endif free(name); name = NULL; name = (char *)malloc(256); p = strchr(user, '@'); if (p == NULL) { snprintf(name, 256, "%s@%s", user, default_realm); } else { snprintf(name, 256, "%s", user); } code = krb5_parse_name(kcontext, name, &client); if (code) { set_basicauth_error(kcontext, code); ret = 0; goto end; } code = verify_krb5_user(kcontext, client, pswd, server); if (code) { ret = 0; goto end; } ret = 1; end: #ifdef PRINTFS printf("kerb_authenticate_user_krb5pwd ret=%d user=%s authtype=%s\n", ret, user, "Basic"); #endif if (name) free(name); if (client) krb5_free_principal(kcontext, client); if (server) krb5_free_principal(kcontext, server); krb5_free_context(kcontext); return ret; } /* Inspired by krb5_verify_user from Heimdal */ static krb5_error_code verify_krb5_user(krb5_context context, krb5_principal principal, const char *password, krb5_principal server) { krb5_creds creds; krb5_get_init_creds_opt gic_options; krb5_error_code ret; char *name = NULL; memset(&creds, 0, sizeof(creds)); ret = krb5_unparse_name(context, principal, &name); if (ret == 0) { #ifdef PRINTFS printf("Trying to get TGT for user %s\n", name); #endif free(name); } krb5_get_init_creds_opt_init(&gic_options); ret = krb5_get_init_creds_password(context, &creds, principal, (char *)password, NULL, NULL, 0, NULL, &gic_options); if (ret) { set_basicauth_error(context, ret); goto end; } end: krb5_free_cred_contents(context, &creds); return ret; } static void set_basicauth_error(krb5_context context, krb5_error_code code) { PyErr_SetObject(BasicAuthException_class, Py_BuildValue("(s:i)", krb5_get_err_text(context, code), code)); }