summaryrefslogtreecommitdiff
path: root/source4/auth/kerberos/kerberos.c
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2012-04-26 11:05:51 -0400
committerSimo Sorce <idra@samba.org>2012-05-04 16:51:28 +0200
commit29d284c245c1b3458712c8140cd7b0d1ae175d1f (patch)
tree292f7657a2a06dcef322553d34b314ca66ab0471 /source4/auth/kerberos/kerberos.c
parent38a5a2c5c59029889d6c7c6dc80ab087956ca651 (diff)
downloadsamba-29d284c245c1b3458712c8140cd7b0d1ae175d1f.tar.gz
samba-29d284c245c1b3458712c8140cd7b0d1ae175d1f.tar.bz2
samba-29d284c245c1b3458712c8140cd7b0d1ae175d1f.zip
Move kerberos_kinit_password_cc to krb5samba lib
Diffstat (limited to 'source4/auth/kerberos/kerberos.c')
-rw-r--r--source4/auth/kerberos/kerberos.c421
1 files changed, 0 insertions, 421 deletions
diff --git a/source4/auth/kerberos/kerberos.c b/source4/auth/kerberos/kerberos.c
deleted file mode 100644
index b4e989d2ae..0000000000
--- a/source4/auth/kerberos/kerberos.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- kerberos utility library
- Copyright (C) Andrew Tridgell 2001
- Copyright (C) Remus Koos 2001
- Copyright (C) Nalin Dahyabhai 2004.
- Copyright (C) Jeremy Allison 2004.
- Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "system/kerberos.h"
-#include "auth/kerberos/kerberos.h"
-
-#ifdef HAVE_KRB5
-
-/*
- simulate a kinit, putting the tgt in the given credentials cache.
- Orignally by remus@snapserver.com
-
- The impersonate_principal is the principal if NULL, or the principal to impersonate
-
- The self_service, should be the local service (for S4U2Self if impersonate_principal is given).
-
- The target_service defaults to the krbtgt if NULL, but could be kpasswd/realm or a remote service (for S4U2Proxy)
-
-*/
- krb5_error_code kerberos_kinit_password_cc(krb5_context ctx, krb5_ccache store_cc,
- krb5_principal init_principal,
- const char *init_password,
- krb5_principal impersonate_principal,
- const char *self_service,
- const char *target_service,
- krb5_get_init_creds_opt *krb_options,
- time_t *expire_time, time_t *kdc_time)
-{
- krb5_error_code code = 0;
- krb5_get_creds_opt options;
- krb5_principal store_principal;
- krb5_creds store_creds;
- krb5_creds *s4u2self_creds;
- Ticket s4u2self_ticket;
- size_t s4u2self_ticketlen;
- krb5_creds *s4u2proxy_creds;
- krb5_principal self_princ;
- bool s4u2proxy;
- krb5_principal target_princ;
- krb5_ccache tmp_cc;
- const char *self_realm;
- krb5_principal blacklist_principal = NULL;
- krb5_principal whitelist_principal = NULL;
-
- if (impersonate_principal && self_service == NULL) {
- return EINVAL;
- }
-
- /*
- * If we are not impersonating, then get this ticket for the
- * target service, otherwise a krbtgt, and get the next ticket
- * for the target
- */
- code = krb5_get_init_creds_password(ctx, &store_creds,
- init_principal,
- init_password,
- NULL, NULL,
- 0,
- impersonate_principal ? NULL : target_service,
- krb_options);
- if (code != 0) {
- return code;
- }
-
- store_principal = init_principal;
-
- if (impersonate_principal == NULL) {
- goto store;
- }
-
- /*
- * We are trying S4U2Self now:
- *
- * As we do not want to expose our TGT in the
- * krb5_ccache, which is also holds the impersonated creds.
- *
- * Some low level krb5/gssapi function might use the TGT
- * identity and let the client act as our machine account.
- *
- * We need to avoid that and use a temporary krb5_ccache
- * in order to pass our TGT to the krb5_get_creds() function.
- */
- code = krb5_cc_new_unique(ctx, NULL, NULL, &tmp_cc);
- if (code != 0) {
- krb5_free_cred_contents(ctx, &store_creds);
- return code;
- }
-
- code = krb5_cc_initialize(ctx, tmp_cc, store_creds.client);
- if (code != 0) {
- krb5_cc_destroy(ctx, tmp_cc);
- krb5_free_cred_contents(ctx, &store_creds);
- return code;
- }
-
- code = krb5_cc_store_cred(ctx, tmp_cc, &store_creds);
- if (code != 0) {
- krb5_free_cred_contents(ctx, &store_creds);
- krb5_cc_destroy(ctx, tmp_cc);
- return code;
- }
-
- /*
- * we need to remember the client principal of our
- * TGT and make sure the KDC does not return this
- * in the impersonated tickets. This can happen
- * if the KDC does not support S4U2Self and S4U2Proxy.
- */
- blacklist_principal = store_creds.client;
- store_creds.client = NULL;
- krb5_free_cred_contents(ctx, &store_creds);
-
- /*
- * Check if we also need S4U2Proxy or if S4U2Self is
- * enough in order to get a ticket for the target.
- */
- if (target_service == NULL) {
- s4u2proxy = false;
- } else if (strcmp(target_service, self_service) == 0) {
- s4u2proxy = false;
- } else {
- s4u2proxy = true;
- }
-
- /*
- * For S4U2Self we need our own service principal,
- * which belongs to our own realm (available on
- * our client principal).
- */
- self_realm = krb5_principal_get_realm(ctx, init_principal);
-
- code = krb5_parse_name(ctx, self_service, &self_princ);
- if (code != 0) {
- krb5_free_principal(ctx, blacklist_principal);
- krb5_cc_destroy(ctx, tmp_cc);
- return code;
- }
-
- code = krb5_principal_set_realm(ctx, self_princ, self_realm);
- if (code != 0) {
- krb5_free_principal(ctx, blacklist_principal);
- krb5_free_principal(ctx, self_princ);
- krb5_cc_destroy(ctx, tmp_cc);
- return code;
- }
-
- code = krb5_get_creds_opt_alloc(ctx, &options);
- if (code != 0) {
- krb5_free_principal(ctx, blacklist_principal);
- krb5_free_principal(ctx, self_princ);
- krb5_cc_destroy(ctx, tmp_cc);
- return code;
- }
-
- if (s4u2proxy) {
- /*
- * If we want S4U2Proxy, we need the forwardable flag
- * on the S4U2Self ticket.
- */
- krb5_get_creds_opt_set_options(ctx, options, KRB5_GC_FORWARDABLE);
- }
-
- code = krb5_get_creds_opt_set_impersonate(ctx, options,
- impersonate_principal);
- if (code != 0) {
- krb5_get_creds_opt_free(ctx, options);
- krb5_free_principal(ctx, blacklist_principal);
- krb5_free_principal(ctx, self_princ);
- krb5_cc_destroy(ctx, tmp_cc);
- return code;
- }
-
- code = krb5_get_creds(ctx, options, tmp_cc,
- self_princ, &s4u2self_creds);
- krb5_get_creds_opt_free(ctx, options);
- krb5_free_principal(ctx, self_princ);
- if (code != 0) {
- krb5_free_principal(ctx, blacklist_principal);
- krb5_cc_destroy(ctx, tmp_cc);
- return code;
- }
-
- if (!s4u2proxy) {
- krb5_cc_destroy(ctx, tmp_cc);
-
- /*
- * Now make sure we store the impersonated principal
- * and creds instead of the TGT related stuff
- * in the krb5_ccache of the caller.
- */
- code = krb5_copy_creds_contents(ctx, s4u2self_creds,
- &store_creds);
- krb5_free_creds(ctx, s4u2self_creds);
- if (code != 0) {
- return code;
- }
-
- /*
- * It's important to store the principal the KDC
- * returned, as otherwise the caller would not find
- * the S4U2Self ticket in the krb5_ccache lookup.
- */
- store_principal = store_creds.client;
- goto store;
- }
-
- /*
- * We are trying S4U2Proxy:
- *
- * We need the ticket from the S4U2Self step
- * and our TGT in order to get the delegated ticket.
- */
- code = decode_Ticket((const uint8_t *)s4u2self_creds->ticket.data,
- s4u2self_creds->ticket.length,
- &s4u2self_ticket,
- &s4u2self_ticketlen);
- if (code != 0) {
- krb5_free_creds(ctx, s4u2self_creds);
- krb5_free_principal(ctx, blacklist_principal);
- krb5_cc_destroy(ctx, tmp_cc);
- return code;
- }
-
- /*
- * we need to remember the client principal of the
- * S4U2Self stage and as it needs to match the one we
- * will get for the S4U2Proxy stage. We need this
- * in order to detect KDCs which does not support S4U2Proxy.
- */
- whitelist_principal = s4u2self_creds->client;
- s4u2self_creds->client = NULL;
- krb5_free_creds(ctx, s4u2self_creds);
-
- /*
- * For S4U2Proxy we also got a target service principal,
- * which also belongs to our own realm (available on
- * our client principal).
- */
- code = krb5_parse_name(ctx, target_service, &target_princ);
- if (code != 0) {
- free_Ticket(&s4u2self_ticket);
- krb5_free_principal(ctx, whitelist_principal);
- krb5_free_principal(ctx, blacklist_principal);
- krb5_cc_destroy(ctx, tmp_cc);
- return code;
- }
-
- code = krb5_principal_set_realm(ctx, target_princ, self_realm);
- if (code != 0) {
- free_Ticket(&s4u2self_ticket);
- krb5_free_principal(ctx, target_princ);
- krb5_free_principal(ctx, whitelist_principal);
- krb5_free_principal(ctx, blacklist_principal);
- krb5_cc_destroy(ctx, tmp_cc);
- return code;
- }
-
- code = krb5_get_creds_opt_alloc(ctx, &options);
- if (code != 0) {
- free_Ticket(&s4u2self_ticket);
- krb5_free_principal(ctx, target_princ);
- krb5_free_principal(ctx, whitelist_principal);
- krb5_free_principal(ctx, blacklist_principal);
- krb5_cc_destroy(ctx, tmp_cc);
- return code;
- }
-
- krb5_get_creds_opt_set_options(ctx, options, KRB5_GC_FORWARDABLE);
- krb5_get_creds_opt_set_options(ctx, options, KRB5_GC_CONSTRAINED_DELEGATION);
-
- code = krb5_get_creds_opt_set_ticket(ctx, options, &s4u2self_ticket);
- free_Ticket(&s4u2self_ticket);
- if (code != 0) {
- krb5_get_creds_opt_free(ctx, options);
- krb5_free_principal(ctx, target_princ);
- krb5_free_principal(ctx, whitelist_principal);
- krb5_free_principal(ctx, blacklist_principal);
- krb5_cc_destroy(ctx, tmp_cc);
- return code;
- }
-
- code = krb5_get_creds(ctx, options, tmp_cc,
- target_princ, &s4u2proxy_creds);
- krb5_get_creds_opt_free(ctx, options);
- krb5_free_principal(ctx, target_princ);
- krb5_cc_destroy(ctx, tmp_cc);
- if (code != 0) {
- krb5_free_principal(ctx, whitelist_principal);
- krb5_free_principal(ctx, blacklist_principal);
- return code;
- }
-
- /*
- * Now make sure we store the impersonated principal
- * and creds instead of the TGT related stuff
- * in the krb5_ccache of the caller.
- */
- code = krb5_copy_creds_contents(ctx, s4u2proxy_creds,
- &store_creds);
- krb5_free_creds(ctx, s4u2proxy_creds);
- if (code != 0) {
- krb5_free_principal(ctx, whitelist_principal);
- krb5_free_principal(ctx, blacklist_principal);
- return code;
- }
-
- /*
- * It's important to store the principal the KDC
- * returned, as otherwise the caller would not find
- * the S4U2Self ticket in the krb5_ccache lookup.
- */
- store_principal = store_creds.client;
-
- store:
- if (blacklist_principal &&
- krb5_principal_compare(ctx, store_creds.client, blacklist_principal)) {
- char *sp = NULL;
- char *ip = NULL;
-
- code = krb5_unparse_name(ctx, blacklist_principal, &sp);
- if (code != 0) {
- sp = NULL;
- }
- code = krb5_unparse_name(ctx, impersonate_principal, &ip);
- if (code != 0) {
- ip = NULL;
- }
- DEBUG(1, ("kerberos_kinit_password_cc: "
- "KDC returned self principal[%s] while impersonating [%s]\n",
- sp?sp:"<no memory>",
- ip?ip:"<no memory>"));
-
- SAFE_FREE(sp);
- SAFE_FREE(ip);
-
- krb5_free_principal(ctx, whitelist_principal);
- krb5_free_principal(ctx, blacklist_principal);
- krb5_free_cred_contents(ctx, &store_creds);
- return KRB5_FWD_BAD_PRINCIPAL;
- }
- if (blacklist_principal) {
- krb5_free_principal(ctx, blacklist_principal);
- }
-
- if (whitelist_principal &&
- !krb5_principal_compare(ctx, store_creds.client, whitelist_principal)) {
- char *sp = NULL;
- char *ep = NULL;
-
- code = krb5_unparse_name(ctx, store_creds.client, &sp);
- if (code != 0) {
- sp = NULL;
- }
- code = krb5_unparse_name(ctx, whitelist_principal, &ep);
- if (code != 0) {
- ep = NULL;
- }
- DEBUG(1, ("kerberos_kinit_password_cc: "
- "KDC returned wrong principal[%s] we expected [%s]\n",
- sp?sp:"<no memory>",
- ep?ep:"<no memory>"));
-
- SAFE_FREE(sp);
- SAFE_FREE(ep);
-
- krb5_free_principal(ctx, whitelist_principal);
- krb5_free_cred_contents(ctx, &store_creds);
- return KRB5_FWD_BAD_PRINCIPAL;
- }
- if (whitelist_principal) {
- krb5_free_principal(ctx, whitelist_principal);
- }
-
- code = krb5_cc_initialize(ctx, store_cc, store_principal);
- if (code != 0) {
- krb5_free_cred_contents(ctx, &store_creds);
- return code;
- }
-
- code = krb5_cc_store_cred(ctx, store_cc, &store_creds);
- if (code != 0) {
- krb5_free_cred_contents(ctx, &store_creds);
- return code;
- }
-
- if (expire_time) {
- *expire_time = (time_t) store_creds.times.endtime;
- }
-
- if (kdc_time) {
- *kdc_time = (time_t) store_creds.times.starttime;
- }
-
- krb5_free_cred_contents(ctx, &store_creds);
-
- return 0;
-}
-
-
-#endif