Back to index

openldap  2.4.31
Classes | Defines | Typedefs | Functions | Variables
kinit.c File Reference
#include <portable.h>
#include <slap.h>
#include "ldap_rq.h"
#include <ac/errno.h>
#include <ac/string.h>
#include <krb5/krb5.h>

Go to the source code of this file.

Classes

struct  kinit_data

Defines

#define SLAPD_MOD_KINIT   SLAPD_MOD_DYNAMIC

Typedefs

typedef struct kinit_data kinit_data

Functions

static void log_krb5_errmsg (krb5_context ctx, const char *func, krb5_error_code rc)
static int kinit_check_tgt (kinit_data *kid, int *remaining)
voidkinit_qtask (void *ctx, void *arg)
int kinit_initialize (void)
int init_module (int argc, char *argv[])
int term_module ()

Variables

static char * principal
static char * kt_name
static kinit_datakid

Class Documentation

struct kinit_data

Definition at line 30 of file kinit.c.

Class Members
krb5_ccache ccache
krb5_context ctx
krb5_keytab keytab
krb5_get_init_creds_opt * opts
krb5_principal princ

Define Documentation

#define SLAPD_MOD_KINIT   SLAPD_MOD_DYNAMIC

Definition at line 19 of file kinit.c.


Typedef Documentation

typedef struct kinit_data kinit_data

Function Documentation

int init_module ( int  argc,
char *  argv[] 
)

Definition at line 248 of file kinit.c.

                                        {
       if (argc > 0) {
              principal = ch_strdup(argv[0]);
       }
       if (argc > 1) {
              kt_name = ch_strdup(argv[1]);
       }
       if (argc > 2) {
              return -1;
       }
       return kinit_initialize();
}

Here is the call graph for this function:

static int kinit_check_tgt ( kinit_data kid,
int remaining 
) [static]

Definition at line 52 of file kinit.c.

{
       int ret=3;
       krb5_principal princ;
       krb5_error_code rc;
       krb5_cc_cursor cursor;
       krb5_creds creds;
       char *name;
       time_t now=time(NULL);

       rc = krb5_cc_get_principal(kid->ctx, kid->ccache, &princ);
       if (rc) {
              log_krb5_errmsg(kid->ctx, "krb5_cc_get_principal", rc);
              return 2;
       } else {
              if (!krb5_principal_compare(kid->ctx, kid->princ, princ)) {
                     Log0(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR,
                                   "Principal in ccache does not match requested principal\n");
                     krb5_free_principal(kid->ctx, princ);
                     return 2;
              }
       }

       rc = krb5_cc_start_seq_get(kid->ctx, kid->ccache, &cursor);
       if (rc) {
              log_krb5_errmsg(kid->ctx, "krb5_cc_start_seq_get", rc);
              krb5_free_principal(kid->ctx, princ);
              return -1;
       }

       while (!(rc = krb5_cc_next_cred(kid->ctx, kid->ccache, &cursor, &creds))) {
              if (krb5_is_config_principal(kid->ctx, creds.server)) {
                     krb5_free_cred_contents(kid->ctx, &creds);
                     continue;
              }

              if (creds.server->length==2 &&
                            (!strcmp(creds.server->data[0].data, "krbtgt")) &&
                            (!strcmp(creds.server->data[1].data, princ->realm.data))) {

                     krb5_unparse_name(kid->ctx, creds.server, &name);

                     *remaining = (time_t)creds.times.endtime-now;
                     if ( *remaining <= 0) {
                            Log1(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG,
                                          "kinit_qtask: TGT (%s) expired\n", name);
                     } else {
                            Log4(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG,
                                          "kinit_qtask: TGT (%s) expires in %dh:%02dm:%02ds\n",
                                          name, *remaining/3600, (*remaining%3600)/60, *remaining%60);
                     }
                     free(name);

                     if (*remaining <= 30) {
                            if (creds.times.renew_till-60 > now) {
                                   int renewal=creds.times.renew_till-now;
                                   Log3(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG,
                                                 "kinit_qtask: Time remaining for renewal: %dh:%02dm:%02ds\n",
                                                 renewal/3600, (renewal%3600)/60,  renewal%60);
                                   ret = 1;
                            } else {
                                   Log0(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG,
                                                 "kinit_qtask: Only short time left for renewal. "
                                                 "Trying to re-init.\n");
                                   ret = 2;
                            }
                     } else {
                            ret=0;
                     }
                     krb5_free_cred_contents(kid->ctx, &creds);
                     break;
              }
              krb5_free_cred_contents(kid->ctx, &creds);

       }
       krb5_cc_end_seq_get(kid->ctx, kid->ccache, &cursor);
       krb5_free_principal(kid->ctx, princ);
       return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 200 of file kinit.c.

{
       Log0( LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG, "kinit_initialize\n" );
       krb5_error_code rc;
       struct re_s *task = NULL;

       kid = ch_calloc(1, sizeof(kinit_data) );

       rc = krb5_init_context( &kid->ctx );
       if ( !rc )
              rc = krb5_cc_default(kid->ctx, &kid->ccache );

       if ( !rc ) {
              if (!principal) {
                     int len=STRLENOF("ldap/")+global_host_bv.bv_len+1;
                     principal=ch_calloc(len, 1);
                     snprintf(principal, len, "ldap/%s", global_host_bv.bv_val);
                     Log1(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG, "Principal <%s>\n", principal);

              }
              rc = krb5_parse_name(kid->ctx, principal, &kid->princ);
       }

       if ( !rc && kt_name) {
              rc = krb5_kt_resolve(kid->ctx, kt_name, &kid->keytab);
       }

       if ( !rc )
              rc = krb5_get_init_creds_opt_alloc(kid->ctx, &kid->opts);

       if ( !rc )
              rc = krb5_get_init_creds_opt_set_out_ccache( kid->ctx, kid->opts, kid->ccache);

       if ( !rc ) {
              ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
              task = ldap_pvt_runqueue_insert( &slapd_rq, 10, kinit_qtask, (void*)kid,
                            "kinit_qtask", "ldap/bronsted.g17.lan@G17.LAN" );
              ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
       }

       if (rc) {
              log_krb5_errmsg(kid->ctx, "kinit_initialize", rc);
              rc = -1;
       }
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void* kinit_qtask ( void ctx,
void arg 
)

Definition at line 133 of file kinit.c.

{
       struct re_s     *rtask = arg;
       kinit_data    *kid = (kinit_data*)rtask->arg;
       krb5_error_code rc;
       krb5_creds creds;
       int nextcheck, remaining, renew=0;
       Log0(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG, "kinit_qtask: running TGT check\n");

       memset(&creds, 0, sizeof(creds));

       renew = kinit_check_tgt(kid, &remaining);

       if (renew > 0) {
              if (renew==1) {
                     Log0(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG,
                                   "kinit_qtask: Trying to renew TGT: ");
                     rc = krb5_get_renewed_creds(kid->ctx, &creds, kid->princ, kid->ccache, NULL);
                     if (rc!=0) {
                            Log0(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG, "Failed\n");
                            log_krb5_errmsg( kid->ctx,
                                          "kinit_qtask, Renewal failed: krb5_get_renewed_creds", rc );
                            renew++;
                     } else {
                            Log0(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG, "Success\n");
                            krb5_cc_initialize(kid->ctx, kid->ccache, creds.client);
                            krb5_cc_store_cred(kid->ctx, kid->ccache, &creds);
                            krb5_free_cred_contents(kid->ctx, &creds);
                            renew=kinit_check_tgt(kid, &remaining);
                     }
              }
              if (renew > 1) {
                     Log0(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG,
                                   "kinit_qtask: Trying to get new TGT: ");
                     rc = krb5_get_init_creds_keytab( kid->ctx, &creds, kid->princ,
                                   kid->keytab, 0, NULL, kid->opts);
                     if (rc) {
                            Log0(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG, "Failed\n");
                            log_krb5_errmsg(kid->ctx, "krb5_get_init_creds_keytab", rc);
                     } else {
                            Log0(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG, "Success\n");
                            renew=kinit_check_tgt(kid, &remaining);
                     }
                     krb5_free_cred_contents(kid->ctx, &creds);
              }
       }
       if (renew == 0) {
              nextcheck = remaining-30;
       } else {
              nextcheck = 60;
       }

       ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
       if ( ldap_pvt_runqueue_isrunning( &slapd_rq, rtask )) {
              ldap_pvt_runqueue_stoptask( &slapd_rq, rtask );
       }
       Log3(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG,
                     "kinit_qtask: Next TGT check in %dh:%02dm:%02ds\n",
                     nextcheck/3600, (nextcheck%3600)/60,  nextcheck%60);
       rtask->interval.tv_sec = nextcheck;
       ldap_pvt_runqueue_resched( &slapd_rq, rtask, 0 );
       slap_wake_listener();
       ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
       return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void log_krb5_errmsg ( krb5_context  ctx,
const char *  func,
krb5_error_code  rc 
) [static]

Definition at line 43 of file kinit.c.

{
       const char* errmsg = krb5_get_error_message(ctx, rc);
       Log2(LDAP_DEBUG_ANY, LDAP_LEVEL_ERR, "slapd-kinit: %s: %s\n", func, errmsg);
       krb5_free_error_message(ctx, errmsg);
       return;
}

Here is the caller graph for this function:

Definition at line 262 of file kinit.c.

              {
       if (principal)
              ch_free(principal);
       if (kt_name)
              ch_free(kt_name);
       if (kid) {
              struct re_s *task;

              task=ldap_pvt_runqueue_find( &slapd_rq, kinit_qtask, (void*)kid);
              if (task) {
                     if ( ldap_pvt_runqueue_isrunning(&slapd_rq, task) ) {
                            ldap_pvt_runqueue_stoptask(&slapd_rq, task);
                     }
                     ldap_pvt_runqueue_remove(&slapd_rq, task);
              }
              if ( kid->ctx ) {
                     if ( kid->princ )
                            krb5_free_principal(kid->ctx, kid->princ);
                     if ( kid->ccache )
                            krb5_cc_close(kid->ctx, kid->ccache);
                     if ( kid->keytab )
                            krb5_kt_close(kid->ctx, kid->keytab);
                     if ( kid->opts )
                            krb5_get_init_creds_opt_free(kid->ctx, kid->opts);
                     krb5_free_context(kid->ctx);
              }
              ch_free(kid);
       }
       return 0;
}

Here is the call graph for this function:


Variable Documentation

kinit_data* kid [static]

Definition at line 40 of file kinit.c.

char* kt_name [static]

Definition at line 39 of file kinit.c.

char* principal [static]

Definition at line 38 of file kinit.c.