Beispiel #1
0
krb5_error_code KRB5_CALLCONV
krb5_cc_copy_creds(krb5_context context, krb5_ccache incc, krb5_ccache outcc)
{
    krb5_error_code code;
    krb5_flags flags;
    krb5_cc_cursor cur = 0;
    krb5_creds creds;

    flags = 0;				/* turns off OPENCLOSE mode */
    if ((code = krb5_cc_set_flags(context, incc, flags)))
	return(code);
    /* the code for this will open the file for reading only, which
       is not what I had in mind.  So I won't turn off OPENCLOSE
       for the output ccache */
#if 0
    if ((code = krb5_cc_set_flags(context, outcc, flags)))
	return(code);
#endif

    if ((code = krb5_cc_start_seq_get(context, incc, &cur)))
	goto cleanup;

    while (!(code = krb5_cc_next_cred(context, incc, &cur, &creds))) {
	code = krb5_cc_store_cred(context, outcc, &creds);
	krb5_free_cred_contents(context, &creds);
	if (code)
	    goto cleanup;
    }

    if (code != KRB5_CC_END)
	goto cleanup;

    code = krb5_cc_end_seq_get(context, incc, &cur);
    cur = 0;
    if (code)
        goto cleanup;

    code = 0;

cleanup:
    flags = KRB5_TC_OPENCLOSE;

    /* If set then we are in an error pathway */
    if (cur) 
      krb5_cc_end_seq_get(context, incc, &cur);

    if (code)
	krb5_cc_set_flags(context, incc, flags);
    else
	code = krb5_cc_set_flags(context, incc, flags);

#if 0
    if (code)
	krb5_cc_set_flags(context, outcc, flags);
    else
	code = krb5_cc_set_flags(context, outcc, flags);
#endif

    return(code);
}
Beispiel #2
0
static int
check_for_tgt(krb5_context context, krb5_ccache ccache,
	      krb5_principal principal)
{
	krb5_error_code ret;
	krb5_creds creds;
	krb5_cc_cursor cur;
	int found = 0;

	ret = krb5_cc_start_seq_get(context, ccache, &cur);
	if (ret) 
		return 0;

	while (!found &&
		(ret = krb5_cc_next_cred(context, ccache, &cur, &creds)) == 0) {
		if (creds.server->length == 2 &&
				data_is_equal(creds.server->realm,
					      principal->realm) &&
				creds.server->data[0].length == 6 &&
				memcmp(creds.server->data[0].data,
						"krbtgt", 6) == 0 &&
				data_is_equal(creds.server->data[1],
					      principal->realm) &&
				creds.times.endtime > time(NULL))
			found = 1;
		krb5_free_cred_contents(context, &creds);
	}
	krb5_cc_end_seq_get(context, ccache, &cur);

	return found;
}
Beispiel #3
0
krb5_error_code KRB5_CALLCONV
krb5_cccol_have_content(krb5_context context)
{
    krb5_cccol_cursor col_cursor;
    krb5_cc_cursor cache_cursor;
    krb5_ccache cache;
    krb5_creds creds;
    krb5_boolean found = FALSE;

    if (krb5_cccol_cursor_new(context, &col_cursor))
        goto no_entries;

    while (!found && !krb5_cccol_cursor_next(context, col_cursor, &cache) &&
            cache != NULL) {
        if (krb5_cc_start_seq_get(context, cache, &cache_cursor))
            continue;
        while (!found &&
                !krb5_cc_next_cred(context, cache, &cache_cursor, &creds)) {
            if (!krb5_is_config_principal(context, creds.server))
                found = TRUE;
            krb5_free_cred_contents(context, &creds);
        }
        krb5_cc_end_seq_get(context, cache, &cache_cursor);
        krb5_cc_close(context, cache);
    }
    krb5_cccol_cursor_free(context, &col_cursor);
    if (found)
        return 0;

no_entries:
    krb5_set_error_message(context, KRB5_CC_NOTFOUND,
                           _("No Kerberos credentials available"));
    return KRB5_CC_NOTFOUND;
}
Beispiel #4
0
/*
 * Check if a ccache has any tickets.
 */
static krb5_error_code
cc_has_tickets(krb5_context kcontext, krb5_ccache ccache, int *has_tickets)
{
    krb5_error_code code;
    krb5_cc_cursor cursor;
    krb5_creds creds;
    krb5_timestamp now = time(0);

    *has_tickets = 0;

    code = krb5_cc_set_flags(kcontext, ccache, KRB5_TC_NOTICKET);
    if (code)
        return code;

    code = krb5_cc_start_seq_get(kcontext, ccache, &cursor);
    if (code)
        return code;

    while (!*has_tickets) {
        code = krb5_cc_next_cred(kcontext, ccache, &cursor, &creds);
        if (code)
            break;

        if (!krb5_is_config_principal(kcontext, creds.server) &&
            creds.times.endtime > now)
            *has_tickets = 1;

        krb5_free_cred_contents(kcontext, &creds);
    }
    krb5_cc_end_seq_get(kcontext, ccache, &cursor);

    return 0;
}
Beispiel #5
0
/* Display the contents of cache. */
static int
show_ccache(krb5_ccache cache)
{
    krb5_cc_cursor cur;
    krb5_creds creds;
    krb5_principal princ;
    krb5_error_code ret;

    ret = krb5_cc_get_principal(context, cache, &princ);
    if (ret) {
        com_err(progname, ret, "");
        return 1;
    }
    ret = krb5_unparse_name(context, princ, &defname);
    if (ret) {
        com_err(progname, ret, _("while unparsing principal name"));
        return 1;
    }

    printf(_("Ticket cache: %s:%s\nDefault principal: %s\n\n"),
           krb5_cc_get_type(context, cache), krb5_cc_get_name(context, cache),
           defname);
    /* XXX Translating would disturb table alignment; skip for now. */
    fputs("Valid starting", stdout);
    fillit(stdout, timestamp_width - sizeof("Valid starting") + 3, (int) ' ');
    fputs("Expires", stdout);
    fillit(stdout, timestamp_width - sizeof("Expires") + 3, (int) ' ');
    fputs("Service principal\n", stdout);

    ret = krb5_cc_start_seq_get(context, cache, &cur);
    if (ret) {
        com_err(progname, ret, _("while starting to retrieve tickets"));
        return 1;
    }
    while ((ret = krb5_cc_next_cred(context, cache, &cur, &creds)) == 0) {
        if (show_config || !krb5_is_config_principal(context, creds.server))
            show_credential(&creds);
        krb5_free_cred_contents(context, &creds);
    }
    krb5_free_principal(context, princ);
    krb5_free_unparsed_name(context, defname);
    defname = NULL;
    if (ret == KRB5_CC_END) {
        ret = krb5_cc_end_seq_get(context, cache, &cur);
        if (ret) {
            com_err(progname, ret, _("while finishing ticket retrieval"));
            return 1;
        }
        return 0;
    } else {
        com_err(progname, ret, _("while retrieving a ticket"));
        return 1;
    }
}
Beispiel #6
0
static int
print_tickets (krb5_context context,
	       krb5_ccache ccache,
	       krb5_principal principal)
{
    krb5_error_code ret;
    krb5_cc_cursor cursor;
    krb5_creds cred;
    char *str;

    ret = krb5_unparse_name (context, principal, &str);
    if (ret) {
	lreply(500, "krb5_unparse_name: %d", ret);
	return 500;
    }

    lreply(200, "%17s: %s:%s",
	   "Credentials cache",
	   krb5_cc_get_type(context, ccache),
	   krb5_cc_get_name(context, ccache));
    lreply(200, "%17s: %s", "Principal", str);
    free (str);

    ret = krb5_cc_start_seq_get (context, ccache, &cursor);
    if (ret) {
	lreply(500, "krb5_cc_start_seq_get: %d", ret);
	return 500;
    }

    lreply(200, "  Issued               Expires              Principal");

    while ((ret = krb5_cc_next_cred (context,
				     ccache,
				     &cursor,
				     &cred)) == 0) {
	if (print_cred(context, &cred))
	    return 500;
	krb5_free_cred_contents (context, &cred);
    }
    if (ret != KRB5_CC_END) {
	lreply(500, "krb5_cc_get_next: %d", ret);
	return 500;
    }
    ret = krb5_cc_end_seq_get (context, ccache, &cursor);
    if (ret) {
	lreply(500, "krb5_cc_end_seq_get: %d", ret);
	return 500;
    }

    return 200;
}
Beispiel #7
0
static void
check_ticket_count(gss_cred_id_t cred, int expected)
{
    krb5_error_code ret;
    krb5_context context = NULL;
    krb5_creds kcred;
    krb5_cc_cursor cur;
    krb5_ccache ccache;
    int count = 0;
    gss_key_value_set_desc store;
    gss_key_value_element_desc elem;
    OM_uint32 major, minor;
    const char *ccname = "MEMORY:count";

    store.count = 1;
    store.elements = &elem;
    elem.key = "ccache";
    elem.value = ccname;
    major = gss_store_cred_into(&minor, cred, GSS_C_INITIATE, &mech_krb5, 1, 0,
                                &store, NULL, NULL);
    check_gsserr("gss_store_cred_into", major, minor);

    ret = krb5_init_context(&context);
    check_k5err(context, "krb5_init_context", ret);

    ret = krb5_cc_resolve(context, ccname, &ccache);
    check_k5err(context, "krb5_cc_resolve", ret);

    ret = krb5_cc_start_seq_get(context, ccache, &cur);
    check_k5err(context, "krb5_cc_start_seq_get", ret);

    while (!krb5_cc_next_cred(context, ccache, &cur, &kcred)) {
        if (!krb5_is_config_principal(context, kcred.server))
            count++;
        krb5_free_cred_contents(context, &kcred);
    }

    ret = krb5_cc_end_seq_get(context, ccache, &cur);
    check_k5err(context, "krb5_cc_end_seq_get", ret);

    if (expected != count) {
        printf("Expected %d tickets but got %d\n", expected, count);
        exit(1);
    }

    krb5_cc_destroy(context, ccache);
    krb5_free_context(context);
}
Beispiel #8
0
/*
 * The default unset code path depends on the underlying ccache implementation
 * knowing how to remove a credential, which most types don't actually support,
 * so we have to jump through some hoops to ensure that when we set a value for
 * a key, it'll be the only value for that key that'll be found later.  The
 * ccache portions of libkrb5 will currently duplicate some of the actual
 * tickets.
 */
static void
unset_config(krb5_context context, krb5_ccache ccache,
             krb5_principal server, const char *key)
{
    krb5_ccache tmp1, tmp2;
    krb5_cc_cursor cursor;
    krb5_creds mcreds, creds;

    memset(&mcreds, 0, sizeof(mcreds));
    memset(&creds, 0, sizeof(creds));
    bail_on_err(context, "Error while deriving configuration principal names",
                k5_build_conf_principals(context, ccache, server, key,
                                         &mcreds));
    bail_on_err(context, "Error resolving first in-memory ccache",
                krb5_cc_resolve(context, "MEMORY:tmp1", &tmp1));
    bail_on_err(context, "Error initializing first in-memory ccache",
                krb5_cc_initialize(context, tmp1, mcreds.client));
    bail_on_err(context, "Error resolving second in-memory ccache",
                krb5_cc_resolve(context, "MEMORY:tmp2", &tmp2));
    bail_on_err(context, "Error initializing second in-memory ccache",
                krb5_cc_initialize(context, tmp2, mcreds.client));
    bail_on_err(context, "Error copying credentials to first in-memory ccache",
                krb5_cc_copy_creds(context, ccache, tmp1));
    bail_on_err(context, "Error starting traversal of first in-memory ccache",
                krb5_cc_start_seq_get(context, tmp1, &cursor));
    while (krb5_cc_next_cred(context, tmp1, &cursor, &creds) == 0) {
        if (!krb5_is_config_principal(context, creds.server) ||
            !krb5_principal_compare(context, mcreds.server, creds.server) ||
            !krb5_principal_compare(context, mcreds.client, creds.client)) {
            bail_on_err(context,
                        "Error storing non-config item to in-memory ccache",
                        krb5_cc_store_cred(context, tmp2, &creds));
        }
    }
    bail_on_err(context, "Error ending traversal of first in-memory ccache",
                krb5_cc_end_seq_get(context, tmp1, &cursor));
    bail_on_err(context, "Error clearing ccache",
                krb5_cc_initialize(context, ccache, mcreds.client));
    bail_on_err(context, "Error storing creds to the ccache",
                krb5_cc_copy_creds(context, tmp2, ccache));
    bail_on_err(context, "Error cleaning up first in-memory ccache",
                krb5_cc_destroy(context, tmp1));
    bail_on_err(context, "Error cleaning up second in-memory ccache",
                krb5_cc_destroy(context, tmp2));
}
Beispiel #9
0
int
main(int argc, char **argv)
{
	krb5_context ctx;
	krb5_ccache ccache;
	krb5_creds creds;
	krb5_cc_cursor cursor;
	krb5_error_code ret;

	ctx = NULL;
	ret = krb5_init_context(&ctx);
	if (ret != 0) {
		printf("Error initializing Kerberos.\n");
		return ret;
	}
	ccache = NULL;
	ret = krb5_cc_default(ctx, &ccache);
	if (ret != 0) {
		printf("Error initializing ccache.\n");
		return ret;
	}
	cursor = NULL;
	ret = krb5_cc_start_seq_get(ctx, ccache, &cursor);
	if (ret == 0) {
		memset(&creds, 0, sizeof(creds));
		while (krb5_cc_next_cred(ctx, ccache, &cursor, &creds) == 0) {
			if (creds.times.renew_till != 0) {
				printf("%lu\n",
				       (unsigned long) creds.times.renew_till -
				       (unsigned long) creds.times.starttime);
			} else {
				printf("0\n");
			}
			break;
		}
		krb5_cc_end_seq_get(ctx, ccache, &cursor);
	}
	krb5_cc_close(ctx, ccache);
	krb5_free_context(ctx);
	return 0;
}
Beispiel #10
0
/* Return 0 if cache is accessible, present, and unexpired; return 1 if not. */
static int
check_ccache(krb5_ccache cache)
{
    krb5_error_code ret;
    krb5_cc_cursor cur;
    krb5_creds creds;
    krb5_principal princ;
    krb5_boolean found_tgt, found_current_tgt, found_current_cred;

    if (krb5_cc_get_principal(context, cache, &princ) != 0)
        return 1;
    if (krb5_cc_start_seq_get(context, cache, &cur) != 0)
        return 1;
    found_tgt = found_current_tgt = found_current_cred = FALSE;
    while ((ret = krb5_cc_next_cred(context, cache, &cur, &creds)) == 0) {
        if (is_local_tgt(creds.server, &princ->realm)) {
            found_tgt = TRUE;
            if (ts_after(creds.times.endtime, now))
                found_current_tgt = TRUE;
        } else if (!krb5_is_config_principal(context, creds.server) &&
                   ts_after(creds.times.endtime, now)) {
            found_current_cred = TRUE;
        }
        krb5_free_cred_contents(context, &creds);
    }
    krb5_free_principal(context, princ);
    if (ret != KRB5_CC_END)
        return 1;
    if (krb5_cc_end_seq_get(context, cache, &cur) != 0)
        return 1;

    /* If the cache contains at least one local TGT, require that it be
     * current.  Otherwise accept any current cred. */
    if (found_tgt)
        return found_current_tgt ? 0 : 1;
    return found_current_cred ? 0 : 1;
}
Beispiel #11
0
/*
 *
 * k5_get_num_cred
 *
 * Returns: number of creds in the credential cache, -1 on error
 *
 */
int
k5_get_num_cred(int verbose)
{
  krb5_error_code code;
  krb5_cc_cursor cursor;
  krb5_creds c;
  int ncreds = 0;

  if (code = krb5_cc_start_seq_get(k5_context, k5_ccache, &cursor)) {
    if (code == KRB5_FCC_NOFILE)
      return 0;
    if (verbose)
      com_err(NULL, code, "while starting to retrieve tickets.");
    return -1;
  }

  while (1) {                                 /* Loop and get creds */
    code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c);
    if (code)
      break;
    ++ncreds;
  }

  if (code != KRB5_CC_END) {                  /* Error while looping??? */
    if (verbose)
      com_err(NULL, code, "while retrieving a ticket.");
    return -1;
  }

  if (code = krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor)) {
    if (verbose)
      com_err(NULL, code, "while closing ccache.");
  }

  return ncreds;
}
Beispiel #12
0
static int
k5_get_num_cred2()
{
  krb5_error_code code;
  krb5_cc_cursor cursor;
  krb5_creds c;
  int ncreds = 0;

  code = krb5_cc_start_seq_get(k5_context, k5_ccache, &cursor);
  if (code == KRB5_FCC_NOFILE)
    return 0;

  while (1) {
    code = krb5_cc_next_cred(k5_context, k5_ccache, &cursor, &c);
    if (code)
      break;
    ++ncreds;
  }

  if (code == KRB5_CC_END)
    krb5_cc_end_seq_get(k5_context, k5_ccache, &cursor);

  return ncreds;
}
Beispiel #13
0
static kbrccache_t userinitcontext(
    const char * user, const char * domain, const char * passwd, const char * cachename, int initialize,
    int * outError )
{
    krb5_context    kcontext = 0;
    krb5_ccache             kcache = 0;
    krb5_creds              kcreds;
    krb5_principal  kme = 0;
    krb5_error_code kres;
    char *                  pPass = strdup( passwd );
    char *                  pName = NULL;
    char *                  pCacheName = NULL;
    int                             numCreds = 0;

    memset( &kcreds, 0, sizeof(kcreds) );
    kres = krb5_init_context( &kcontext );
    if( kres )
        goto return_error;
    if( domain )
        kres = krb5_build_principal( kcontext, &kme, strlen(domain), domain, user, (char *) 0 );
    else
        kres = krb5_parse_name( kcontext, user, &kme );
    if( kres )
        goto fail;
    krb5_unparse_name( kcontext, kme, &pName );
    if( cachename )
    {
        if (asprintf(&pCacheName, "%s%s", cachename, pName) < 0)
        {
            kres = KRB5_CC_NOMEM;
            goto fail;
        }
        kres = krb5_cc_resolve( kcontext, pCacheName, &kcache );
        if( kres )
        {
            kres = krb5_cc_resolve( kcontext, CCACHE_PREFIX_DEFAULT, &kcache );
            if( kres == 0 )
                pCacheName = strdup(CCACHE_PREFIX_DEFAULT);
        }
    }
    else
    {
        kres = krb5_cc_default( kcontext, &kcache );
        pCacheName = strdup( krb5_cc_get_name( kcontext, kcache ) );
    }
    if( kres )
    {
        krb5_free_context(kcontext);
        goto return_error;
    }
    if( initialize )
        krb5_cc_initialize( kcontext, kcache, kme );
    if( kres == 0 && user && passwd )
    {
        long timeneeded = time(0L) +TKTTIMELEFT;
        int have_credentials = 0;
        krb5_cc_cursor cc_curs = NULL;
        numCreds = 0;
        if( (kres=krb5_cc_start_seq_get(kcontext, kcache, &cc_curs)) >= 0 )
        {
            while( (kres=krb5_cc_next_cred(kcontext, kcache, &cc_curs, &kcreds))== 0)
            {
                numCreds++;
                if( krb5_principal_compare( kcontext, kme, kcreds.client ) )
                {
                    if( kcreds.ticket_flags & TKT_FLG_INITIAL && kcreds.times.endtime>timeneeded )
                        have_credentials = 1;
                }
                krb5_free_cred_contents( kcontext, &kcreds );
                if( have_credentials )
                    break;
            }
            krb5_cc_end_seq_get( kcontext, kcache, &cc_curs );
        }
        else
        {
            const char * errmsg = error_message(kres);
            fprintf( stderr, "%s user init(%s): %s\n", "setpass", pName, errmsg );
        }
        if( kres != 0 || have_credentials == 0 )
        {
            krb5_get_init_creds_opt *options = NULL;
            kres = krb5_get_init_creds_opt_alloc(kcontext, &options);
            if ( kres == 0 )
            {
                get_init_creds_opt_init(options);
/*
** no valid credentials - get new ones
*/
                kres = krb5_get_init_creds_password( kcontext, &kcreds, kme, pPass,
                                                     NULL /*prompter*/,
                                                     NULL /*data*/,
                                                     0 /*starttime*/,
                                                     0 /*in_tkt_service*/,
                                                     options /*options*/ );
            }
            if( kres == 0 )
            {
                if( numCreds <= 0 )
                    kres = krb5_cc_initialize( kcontext, kcache, kme );
                if( kres == 0 )
                    kres = krb5_cc_store_cred( kcontext, kcache, &kcreds );
                if( kres == 0 )
                    have_credentials = 1;
            }
            krb5_get_init_creds_opt_free(kcontext, options);
        }
#ifdef NOTUSED
        if( have_credentials )
        {
            int mstat;
            kres = gss_krb5_ccache_name( &mstat, pCacheName, NULL );
            if( getenv( ENV_DEBUG_LDAPKERB ) )
                fprintf( stderr, "gss credentials cache set to %s(%d)\n", pCacheName, kres );
        }
#endif
        krb5_cc_close( kcontext, kcache );
    }
fail:
    if( kres )
    {
        const char * errmsg = error_message(kres);
        fprintf( stderr, "%s user init(%s): %s\n", "setpass", pName, errmsg );
    }
    krb5_free_principal( kcontext, kme );
    krb5_free_cred_contents( kcontext, &kcreds );
    if( pName )
        free( pName );
    free(pPass);
    krb5_free_context(kcontext);

return_error:
    if( kres )
    {
        if( pCacheName )
        {
            free(pCacheName);
            pCacheName = NULL;
        }
    }
    if( outError )
        *outError = kres;
    return pCacheName;
}
Beispiel #14
0
int
main(int argc, char *argv[])
{
    krb5_context kcontext = NULL;
    krb5_error_code code;
    krb5_ccache ccache=NULL;
    krb5_ccache mslsa_ccache=NULL;
    krb5_cc_cursor cursor;
    krb5_creds creds;
    krb5_principal princ = NULL;
    int found_tgt = 0;
    int has_tickets;
    int option;
    char * ccachestr = 0;

    prog = strrchr(argv[0], '/');
    prog = prog ? (prog + 1) : argv[0];

    while ((option = getopt(argc, argv, "c:h")) != -1) {
        switch (option) {
        case 'c':
            ccachestr = optarg;
            break;
        case 'h':
        default:
            xusage();
            break;
        }
    }

    if (code = krb5_init_context(&kcontext)) {
        com_err(argv[0], code, "while initializing kerberos library");
        goto cleanup;
    }

    if (code = krb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache)) {
        com_err(argv[0], code, "while opening MS LSA ccache");
        goto cleanup;
    }

    /* Enumerate tickets from cache looking for a TGT */
    if ((code = krb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor))) {
        com_err(argv[0], code, "while initiating the cred sequence of MS LSA ccache");
        goto cleanup;
    }

    while (!found_tgt) {
        code = krb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds);
        if (code)
            break;

        /* Check if the ticket is a TGT */
        if (is_local_tgt(creds.server))
            found_tgt = 1;

        krb5_free_cred_contents(kcontext, &creds);
    }
    krb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor);

    if (!found_tgt) {
        fprintf(stderr, "%s: Initial Ticket Getting Tickets are not available from the MS LSA\n",
                argv[0]);
        /* Only set the LSA cache as the default if it actually has tickets. */
        code = cc_has_tickets(kcontext, mslsa_ccache, &has_tickets);
        if (code)
            goto cleanup;

        if (has_tickets)
            code = krb5int_cc_user_set_default_name(kcontext, "MSLSA:");

        goto cleanup;
    }

    if (code = krb5_cc_get_principal(kcontext, mslsa_ccache, &princ)) {
        com_err(argv[0], code, "while obtaining MS LSA principal");
        goto cleanup;
    }

    if (ccachestr)
        code = krb5_cc_resolve(kcontext, ccachestr, &ccache);
    else
        code = krb5_cc_resolve(kcontext, "API:", &ccache);
    if (code) {
        com_err(argv[0], code, "while getting default ccache");
        goto cleanup;
    }
    if (code = krb5_cc_initialize(kcontext, ccache, princ)) {
        com_err (argv[0], code, "when initializing ccache");
        goto cleanup;
    }

    if (code = krb5_cc_copy_creds(kcontext, mslsa_ccache, ccache)) {
        com_err (argv[0], code, "while copying MS LSA ccache to default ccache");
        goto cleanup;
    }

    /* Don't try and set the default cache if the cache name was specified. */
    if (ccachestr == NULL) {
        /* On success set the default cache to API. */
        code = krb5int_cc_user_set_default_name(kcontext, "API:");
        if (code) {
            com_err(argv[0], code, "when setting default to API");
            goto cleanup;
        }
    }

cleanup:
    krb5_free_principal(kcontext, princ);
    if (ccache != NULL)
        krb5_cc_close(kcontext, ccache);
    if (mslsa_ccache != NULL)
        krb5_cc_close(kcontext, mslsa_ccache);
    krb5_free_context(kcontext);
    return code ? 1 : 0;
}
 ~State() {
   krb5_context ctx = context_.get();
   krb5_free_cred_contents(ctx, &creds_);
   krb5_error_code code = krb5_cc_end_seq_get(ctx, cc_->get(), &cursor_);
   raiseIf(ctx, code, "ending read of credentials cache");
 }
Beispiel #16
0
/*
 * Class:     sun_security_krb5_Credentials
 * Method:    acquireDefaultNativeCreds
 * Signature: ([I])Lsun/security/krb5/Credentials;
 */
JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativeCreds
(JNIEnv *env, jclass krbcredsClass, jintArray jetypes)
{
    jobject krbCreds = NULL;
    krb5_error_code err = 0;
    krb5_ccache ccache = NULL;
    krb5_cc_cursor cursor = NULL;
    krb5_creds creds;
    krb5_flags flags = 0;
    krb5_context kcontext = NULL;

    int netypes;
    jint *etypes = NULL;

    /* Initialize the Kerberos 5 context */
    err = krb5_init_context (&kcontext);

    if (!err) {
        err = krb5_cc_default (kcontext, &ccache);
    }

    if (!err) {
        err = krb5_cc_set_flags (kcontext, ccache, flags); /* turn off OPENCLOSE */
    }

    if (!err) {
        err = krb5_cc_start_seq_get (kcontext, ccache, &cursor);
    }

    netypes = (*env)->GetArrayLength(env, jetypes);
    etypes = (jint *) (*env)->GetIntArrayElements(env, jetypes, NULL);

    if (etypes != NULL && !err) {
        while ((err = krb5_cc_next_cred (kcontext, ccache, &cursor, &creds)) == 0) {
            char *serverName = NULL;

            if (!err) {
                err = krb5_unparse_name (kcontext, creds.server, &serverName);
                printiferr (err, "while unparsing server name");
            }

            if (!err) {
                char* slash = strchr(serverName, '/');
                char* at = strchr(serverName, '@');
                // Make sure the server's name is krbtgt/REALM@REALM, the etype
                // is supported, and the ticket has not expired
                if (slash && at &&
                        strncmp (serverName, "krbtgt", slash-serverName) == 0 &&
                            // the ablove line shows at must be after slash
                        strncmp (slash+1, at+1, at-slash-1) == 0 &&
                        isIn (creds.keyblock.enctype, netypes, etypes) &&
                        creds.times.endtime > time(0)) {
                    jobject ticket, clientPrincipal, targetPrincipal, encryptionKey;
                    jobject ticketFlags, startTime, endTime;
                    jobject authTime, renewTillTime, hostAddresses;

                    ticket = clientPrincipal = targetPrincipal = encryptionKey = NULL;
                    ticketFlags = startTime = endTime = NULL;
                    authTime = renewTillTime = hostAddresses = NULL;

                    // For the default credentials we're only interested in the krbtgt server.
                    clientPrincipal = BuildClientPrincipal(env, kcontext, creds.client);
                    if (clientPrincipal == NULL) goto cleanup;

                    targetPrincipal = BuildClientPrincipal(env, kcontext, creds.server);
                    if (targetPrincipal == NULL) goto cleanup;

                    // Build a sun/security/krb5/internal/Ticket
                    ticket = BuildTicket(env, &creds.ticket);
                    if (ticket == NULL) goto cleanup;

                    // Get the encryption key
                    encryptionKey = BuildEncryptionKey(env, &creds.keyblock);
                    if (encryptionKey == NULL) goto cleanup;

                    // and the ticket flags
                    ticketFlags = BuildTicketFlags(env, creds.ticket_flags);
                    if (ticketFlags == NULL) goto cleanup;

                    // Get the timestamps out.
                    startTime = BuildKerberosTime(env, creds.times.starttime);
                    if (startTime == NULL) goto cleanup;

                    authTime = BuildKerberosTime(env, creds.times.authtime);
                    if (authTime == NULL) goto cleanup;

                    endTime = BuildKerberosTime(env, creds.times.endtime);
                    if (endTime == NULL) goto cleanup;

                    renewTillTime = BuildKerberosTime(env, creds.times.renew_till);
                    if (renewTillTime == NULL) goto cleanup;

                    // Create the addresses object.
                    hostAddresses = BuildAddressList(env, creds.addresses);

                    if (krbcredsConstructor == 0) {
                        krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>",
                                                                  "(Lsun/security/krb5/internal/Ticket;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/EncryptionKey;Lsun/security/krb5/internal/TicketFlags;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/HostAddresses;)V");
                        if (krbcredsConstructor == 0) {
                            printf("Couldn't find sun.security.krb5.internal.Ticket constructor\n");
                            break;
                        }
                    }

                    // and now go build a KrbCreds object
                    krbCreds = (*env)->NewObject(
                                                 env,
                                                 krbcredsClass,
                                                 krbcredsConstructor,
                                                 ticket,
                                                 clientPrincipal,
                                                 targetPrincipal,
                                                 encryptionKey,
                                                 ticketFlags,
                                                 authTime,
                                                 startTime,
                                                 endTime,
                                                 renewTillTime,
                                                 hostAddresses);
cleanup:
                    if (ticket) (*env)->DeleteLocalRef(env, ticket);
                    if (clientPrincipal) (*env)->DeleteLocalRef(env, clientPrincipal);
                    if (targetPrincipal) (*env)->DeleteLocalRef(env, targetPrincipal);
                    if (encryptionKey) (*env)->DeleteLocalRef(env, encryptionKey);
                    if (ticketFlags) (*env)->DeleteLocalRef(env, ticketFlags);
                    if (authTime) (*env)->DeleteLocalRef(env, authTime);
                    if (startTime) (*env)->DeleteLocalRef(env, startTime);
                    if (endTime) (*env)->DeleteLocalRef(env, endTime);
                    if (renewTillTime) (*env)->DeleteLocalRef(env, renewTillTime);
                    if (hostAddresses) (*env)->DeleteLocalRef(env, hostAddresses);

                    // Stop if there is an exception or we already found the initial TGT
                    if ((*env)->ExceptionCheck(env) || krbCreds) {
                        break;
                    }
                }
            }

            if (serverName != NULL) { krb5_free_unparsed_name (kcontext, serverName); }

            krb5_free_cred_contents (kcontext, &creds);
        }

        if (err == KRB5_CC_END) { err = 0; }
        printiferr (err, "while retrieving a ticket");
    }

    if (!err) {
        err = krb5_cc_end_seq_get (kcontext, ccache, &cursor);
        printiferr (err, "while finishing ticket retrieval");
    }

    if (!err) {
        flags = KRB5_TC_OPENCLOSE; /* restore OPENCLOSE mode */
        err = krb5_cc_set_flags (kcontext, ccache, flags);
        printiferr (err, "while finishing ticket retrieval");
    }

    if (etypes != NULL) {
        (*env)->ReleaseIntArrayElements(env, jetypes, etypes, 0);
    }

    krb5_free_context (kcontext);
    return krbCreds;
}
Beispiel #17
0
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache src_cc = NULL;
    krb5_ccache dst_cc = NULL;
    krb5_cc_cursor cursor;
    krb5_principal me = NULL;
    krb5_creds cred;
    const char *during;
    Ticket t;
    size_t len;
    int make_kvno_absent = 0;
    int opt;

    memset(&cred, 0, sizeof (cred));
    during = "init_context";
    ret = krb5_init_context(&context);
    if (ret) goto err;

    while ((opt = getopt(argc, argv, "c:n")) != -1) {
	switch (opt) {
	case 'c':
	    during = "cc_resolve of source ccache";
	    ret = krb5_cc_resolve(context, optarg, &src_cc);
	    if (ret) goto err;
	    break;
	case 'n':
	    make_kvno_absent++;
	    break;
	case 'h':
	default:
	    fprintf(stderr, "Usage: %s [-n] [-c ccache]\n"
		    "\tThis utility edits a ccache, setting all ticket\n"
		    "\tenc_part kvnos to zero or absent (if -n is set).\n",
		    argv[0]);
	    return 1;
	}
    }

    if (!src_cc) {
	during = "cc_default";
	ret = krb5_cc_default(context, &src_cc);
	if (ret) goto err;
    }

    during = "cc_get_principal";
    ret = krb5_cc_get_principal(context, src_cc, &me);
    if (ret) goto err;

    if (optind != argc) {
	fprintf(stderr, "Usage: %s [-n] [-c ccache]\n"
		"\tThis utility edits a ccache, setting all ticket\n"
		"\tenc_part kvnos to zero or absent (if -n is set).\n",
		argv[0]);
	return 1;
    }

    during = "cc_new_unique of temporary ccache";
    ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, src_cc),
			     NULL, &dst_cc);

    during = "cc_initialize of temporary ccache";
    ret = krb5_cc_initialize(context, dst_cc, me);
    if (ret) goto err;

    during = "cc_start_seq_get";
    ret = krb5_cc_start_seq_get(context, src_cc, &cursor);
    if (ret) goto err;

    while ((ret = krb5_cc_next_cred(context, src_cc, &cursor, &cred)) == 0) {
	krb5_data data;

	during = "decode_Ticket";
	memset(&t, 0, sizeof (t));
	ret = decode_Ticket(cred.ticket.data, cred.ticket.length, &t, &len);
	if (ret == ASN1_MISSING_FIELD)
	    continue;
	if (ret) goto err;
	if (t.enc_part.kvno) {
	    *t.enc_part.kvno = 0;
	    if (make_kvno_absent) {
		free(t.enc_part.kvno);
		t.enc_part.kvno = NULL;
	    }
	    /*
	     * The new Ticket has to need less or same space as before, so
	     * we reuse cred->icket.data.
	     */
	    during = "encode_Ticket";
	    ASN1_MALLOC_ENCODE(Ticket, data.data, data.length, &t, &len, ret);
	    if (ret) {
		free_Ticket(&t);
		goto err;
	    }
	    krb5_data_free(&cred.ticket);
	    cred.ticket = data;
	}
	free_Ticket(&t);
	during = "cc_store_cred";
	ret = krb5_cc_store_cred(context, dst_cc, &cred);
	if (ret) goto err;
	krb5_free_cred_contents(context, &cred);
	memset(&cred, 0, sizeof (cred));
    }
    during = "cc_next_cred";
    if (ret != KRB5_CC_END) goto err;

    during = "cc_end_seq_get";
    ret = krb5_cc_end_seq_get(context, src_cc, &cursor);
    if (ret) goto err;

    during = "cc_move";
    ret = krb5_cc_move(context, dst_cc, src_cc);
    if (ret) goto err;
    dst_cc = NULL;

    during = "cc_switch";
    ret = krb5_cc_switch(context, src_cc);
    if (ret) goto err;

err:
    (void) krb5_free_principal(context, me);
    if (src_cc)
	(void) krb5_cc_close(context, src_cc);
    if (dst_cc)
	(void) krb5_cc_destroy(context, dst_cc);
    if (ret) {
	fprintf(stderr, "Failed while doing %s (%d)\n", during, ret);
	ret = 1;
    }
    return (ret);
}
Beispiel #18
0
static void
cc_test(krb5_context context, const char *name, krb5_flags flags)
{
    krb5_ccache id, id2;
    krb5_creds creds;
    krb5_error_code kret;
    krb5_cc_cursor cursor;
    krb5_principal tmp;

    const char *c_name;
    char newcache[300];
    char *save_type;

    kret = init_test_cred(context);
    CHECK(kret, "init_creds");

    kret = krb5_cc_resolve(context, name, &id);
    CHECK(kret, "resolve");
    kret = krb5_cc_initialize(context, id, test_creds.client);
    CHECK(kret, "initialize");

    c_name = krb5_cc_get_name(context, id);
    CHECK_STR(c_name, "get_name");

    c_name = krb5_cc_get_type(context, id);
    CHECK_STR(c_name, "get_type");
    save_type=strdup(c_name);
    CHECK_STR(save_type, "copying type");

    kret = krb5_cc_store_cred(context, id, &test_creds);
    CHECK(kret, "store");

    kret = krb5_cc_get_principal(context, id, &tmp);
    CHECK(kret, "get_principal");

    CHECK_BOOL(krb5_realm_compare(context, tmp, test_creds.client) != TRUE,
               "realms do not match", "realm_compare");


    CHECK_BOOL(krb5_principal_compare(context, tmp, test_creds.client) != TRUE,
               "principals do not match", "principal_compare");

    krb5_free_principal(context, tmp);

    kret = krb5_cc_set_flags (context, id, flags);
    CHECK(kret, "set_flags");

    kret = krb5_cc_start_seq_get(context, id, &cursor);
    CHECK(kret, "start_seq_get");
    kret = 0;
    while (kret != KRB5_CC_END) {
        if(debug) printf("Calling next_cred\n");
        kret = krb5_cc_next_cred(context, id, &cursor, &creds);
        if(kret == KRB5_CC_END) {
            if(debug) printf("next_cred: ok at end\n");
        }
        else {
            CHECK(kret, "next_cred");
            krb5_free_cred_contents(context, &creds);
        }

    }
    kret = krb5_cc_end_seq_get(context, id, &cursor);
    CHECK(kret, "end_seq_get");

    kret = krb5_cc_close(context, id);
    CHECK(kret, "close");


    /* ------------------------------------------------- */
    kret = krb5_cc_resolve(context, name, &id);
    CHECK(kret, "resolve2");

    {
        /* Copy the cache test*/
        snprintf(newcache, sizeof(newcache), "%s.new", name);
        kret = krb5_cc_resolve(context, newcache, &id2);
        CHECK(kret, "resolve of new cache");

        /* This should fail as the new creds are not initialized */
        kret = krb5_cc_copy_creds(context, id, id2);
        CHECK_FAIL(KRB5_FCC_NOFILE, kret, "copy_creds");

        kret = krb5_cc_initialize(context, id2, test_creds.client);
        CHECK(kret, "initialize of id2");

        kret = krb5_cc_copy_creds(context, id, id2);
        CHECK(kret, "copy_creds");

        kret = krb5_cc_destroy(context, id2);
        CHECK(kret, "destroy new cache");
    }

    /* Destroy the first cache */
    kret = krb5_cc_destroy(context, id);
    CHECK(kret, "destroy");

    /* ----------------------------------------------------- */
    /* Tests the generate new code */
    kret = krb5_cc_new_unique(context, save_type,
                              NULL, &id2);
    CHECK(kret, "new_unique");

    kret = krb5_cc_initialize(context, id2, test_creds.client);
    CHECK(kret, "initialize");

    kret = krb5_cc_store_cred(context, id2, &test_creds);
    CHECK(kret, "store");

    kret = krb5_cc_destroy(context, id2);
    CHECK(kret, "destroy id2");

    free(save_type);
    free_test_cred(context);

}
Beispiel #19
0
static void
print_tickets (krb5_context context,
	       krb5_ccache ccache,
	       krb5_principal principal,
	       int do_verbose,
	       int do_flags,
	       int do_hidden)
{
    krb5_error_code ret;
    char *str, *name;
    krb5_cc_cursor cursor;
    krb5_creds creds;
    krb5_deltat sec;

    rtbl_t ct = NULL;

    ret = krb5_unparse_name (context, principal, &str);
    if (ret)
	krb5_err (context, 1, ret, "krb5_unparse_name");

    printf ("%17s: %s:%s\n",
	    N_("Credentials cache", ""),
	    krb5_cc_get_type(context, ccache),
	    krb5_cc_get_name(context, ccache));
    printf ("%17s: %s\n", N_("Principal", ""), str);

    ret = krb5_cc_get_friendly_name(context, ccache, &name);
    if (ret == 0) {
	if (strcmp(name, str) != 0)
	    printf ("%17s: %s\n", N_("Friendly name", ""), name);
	free(name);
    }
    free (str);

    if(do_verbose) {
	printf ("%17s: %d\n", N_("Cache version", ""),
		krb5_cc_get_version(context, ccache));
    } else {
        krb5_cc_set_flags(context, ccache, KRB5_TC_NOTICKET);
    }

    ret = krb5_cc_get_kdc_offset(context, ccache, &sec);

    if (ret == 0 && do_verbose && sec != 0) {
	char buf[BUFSIZ];
	int val;
	int sig;

	val = sec;
	sig = 1;
	if (val < 0) {
	    sig = -1;
	    val = -val;
	}
	
	unparse_time (val, buf, sizeof(buf));

	printf ("%17s: %s%s\n", N_("KDC time offset", ""),
		sig == -1 ? "-" : "", buf);
    }

    printf("\n");

    ret = krb5_cc_start_seq_get (context, ccache, &cursor);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_start_seq_get");

    if(!do_verbose) {
	ct = rtbl_create();
	rtbl_add_column(ct, COL_ISSUED, 0);
	rtbl_add_column(ct, COL_EXPIRES, 0);
	if(do_flags)
	    rtbl_add_column(ct, COL_FLAGS, 0);
	rtbl_add_column(ct, COL_PRINCIPAL, 0);
	rtbl_set_separator(ct, "  ");
    }
    while ((ret = krb5_cc_next_cred (context,
				     ccache,
				     &cursor,
				     &creds)) == 0) {
	if (!do_hidden && krb5_is_config_principal(context, creds.server)) {
	    ;
	}else if(do_verbose){
	    print_cred_verbose(context, &creds);
	}else{
	    print_cred(context, &creds, ct, do_flags);
	}
	krb5_free_cred_contents (context, &creds);
    }
    if(ret != KRB5_CC_END)
	krb5_err(context, 1, ret, "krb5_cc_get_next");
    ret = krb5_cc_end_seq_get (context, ccache, &cursor);
    if (ret)
	krb5_err (context, 1, ret, "krb5_cc_end_seq_get");
    if(!do_verbose) {
	rtbl_format(ct, stdout);
	rtbl_destroy(ct);
    }
}
Beispiel #20
0
/*
 * call-seq:
 *   list_cache([cache_name]) -> array
 *
 * Call krb5_cc_next_cred to fetch credentials from a cachefile.  With no parameters, it fetches the credentials in the default cachefile.  With one parameter, it fetches the credentials in the named cachefile.  Returns a list of Krb5Auth::Krb5::Cred objects on success, raises Krb5Auth::Krb5::Exception on failure.
 */
static VALUE Krb5_list_cache_creds(int argc, VALUE *argv, VALUE self)
{
  VALUE cache_val;
  struct ruby_krb5 *kerb;
  krb5_error_code krbret;
  char *cache_name;
  krb5_ccache cc;
  krb5_cc_cursor cur;
  krb5_creds creds;
  char *name;
  char *sname;
  krb5_ticket *tkt;
  VALUE result;
  VALUE line;

  rb_scan_args(argc, argv, "01", &cache_val);

  cache_name = get_string_or_nil(cache_val);

  Data_Get_Struct(self, struct ruby_krb5, kerb);
  if (!kerb) {
    NOSTRUCT_EXCEPT();
    return Qfalse;
  }

  if (cache_name == NULL) {
    krbret = krb5_cc_default(kerb->ctx, &cc);
  }
  else {
    krbret = krb5_cc_resolve(kerb->ctx, cache_name, &cc);
  }

  if (krbret) {
    goto cache_fail_raise;
  }

  krbret = krb5_cc_start_seq_get(kerb->ctx, cc, &cur);
  if (krbret) {
    goto cache_fail_close;
  }

  result = rb_ary_new();
  while (!(krbret = krb5_cc_next_cred(kerb->ctx, cc, &cur, &creds))) {
    krbret = krb5_unparse_name(kerb->ctx, creds.client, &name);
    if (krbret) {
      krb5_free_cred_contents(kerb->ctx, &creds);
      break;
    }
    krbret = krb5_unparse_name(kerb->ctx, creds.server, &sname);
    if (krbret) {
      free(name);
      krb5_free_cred_contents(kerb->ctx, &creds);
      break;
    }
    krbret = krb5_decode_ticket(&creds.ticket, &tkt);
    if (krbret) {
      free(sname);
      free(name);
      krb5_free_cred_contents(kerb->ctx, &creds);
      break;
    }
    line = rb_class_new_instance(0, NULL, cCred);
    rb_iv_set(line, "@client", rb_str_new2(name));
    rb_iv_set(line, "@server", rb_str_new2(sname));
    rb_iv_set(line, "@starttime", INT2NUM(creds.times.starttime));
    rb_iv_set(line, "@authtime", INT2NUM(creds.times.authtime));
    rb_iv_set(line, "@endtime", INT2NUM(creds.times.endtime));
    rb_iv_set(line, "@ticket_flags", INT2NUM(creds.ticket_flags));
    rb_iv_set(line, "@cred_enctype", INT2NUM(creds.keyblock.enctype));
    rb_iv_set(line, "@ticket_enctype", INT2NUM(tkt->enc_part.enctype));
    rb_ary_push(result, line);
    krb5_free_ticket(kerb->ctx, tkt);
    free(sname);
    free(name);
    krb5_free_cred_contents(kerb->ctx, &creds);
  }

  if (krbret != KRB5_CC_END) {
    // FIXME: do we need to free up "result" here?  There will be no
    // references to it, so I think the garbage collector will pick it up,
    // but I'm not sure.

    goto cache_fail_close;
  }

  krbret = krb5_cc_end_seq_get(kerb->ctx, cc, &cur);

  krb5_cc_close(kerb->ctx, cc);

  return result;

 cache_fail_close:
  krb5_cc_close(kerb->ctx, cc);

 cache_fail_raise:
  Krb5_register_error(krbret);

  return Qfalse;
}
Beispiel #21
0
int
auks_krb5_cred_renew(char *ccachefilename)
{
	int fstatus = AUKS_ERROR ;

	int read_cred_is_tgt = 0;
	int read_cred_is_renewable = 0;

	/* kerberos related variables */
	krb5_context context;
	krb5_error_code err_code;
	krb5_ccache ccache;
	krb5_creds *p_cred_out = NULL;
	krb5_creds read_cred;
	krb5_creds renew_cred;
	krb5_cc_cursor cc_cursor;

	/* initialize kerberos context */
	err_code = krb5_init_context(&context);
	if (err_code) {
		auks_error("unable to initialize kerberos context : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_INIT_CTX ;
		goto exit;
	}
	auks_log("kerberos context successfully initialized");

	/* initialize kerberos credential cache structure */
	if (ccachefilename == NULL)
		err_code = krb5_cc_default(context,&ccache);
	else
		err_code = krb5_cc_resolve(context,ccachefilename,&ccache);
	if (err_code) {
		auks_error("unable to resolve credential cache : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_OPEN_CC ;
		goto ctx_exit ;
	}
	auks_log("credential cache successfully resolved");

	/* start credential cache sequential reading */
	err_code = krb5_cc_start_seq_get(context, ccache,&cc_cursor);
	if (err_code) {
		auks_error("unable to start credential cache sequential "
			   "read : %s",error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_READ_CC ;
		goto cc_exit;
	}
	auks_log("credential cache sequential read successfully started");

	/* try to get the first renewable TGT of the cache */
	do {
		err_code = krb5_cc_next_cred(context,ccache,
					     &cc_cursor,&read_cred);
		if (!err_code) {
			/* just check initial or forwarded tickets (TGTs) */
			if ((read_cred.ticket_flags & TKT_FLG_INITIAL)
			    || (read_cred.ticket_flags & TKT_FLG_FORWARDED)) {
				read_cred_is_tgt = 1;
				if (read_cred.ticket_flags
				    & TKT_FLG_RENEWABLE) {
					read_cred_is_renewable = 1;
					break;
				}
			}
		}
	}
	while (!err_code);

	/* stop credential cache sequential reading */
	err_code = krb5_cc_end_seq_get(context, ccache,&cc_cursor);
	if (err_code) {
		auks_error("unable to stop credential cache sequential "
			   "read : %s",error_message(err_code));
	} else
		auks_log("credential cache sequential read "
			 "successfully stopped");

	/* try to do renewal if a TGT was found */
	if (!read_cred_is_tgt) {
		auks_error("no TGT found in credential cache");
		fstatus = AUKS_ERROR_KRB5_CRED_NO_TGT_FOUND ;
		goto seq_exit;
	}

	/* try to do renewal if a renewable TGT was found */
	if (!read_cred_is_renewable) {
		auks_error("no renewable TGT found in credential cache");
		fstatus = AUKS_ERROR_KRB5_CRED_TGT_NOT_RENEWABLE ;
		goto seq_exit;
	}
	auks_log("renewable TGT found in credential cache");

	/* test if renewal is possible */
	if (read_cred.times.endtime >=
	    read_cred.times.renew_till) {
		auks_error("TGT can't be renew anymore");
		fstatus = AUKS_ERROR_KRB5_CRED_TGT_HAS_EXPIRED ;
		goto seq_exit;
	}
	auks_log("TGT is still renewable");

	/* renew credential cache TGT */
	memset(&renew_cred, 0,sizeof(renew_cred));

	/* copy client principal in futur credential */
	err_code = krb5_copy_principal(context,read_cred.client,
				       &renew_cred.client);
	if (err_code) {
		auks_error("unable to put client principal into "
			   "request cred : %s",error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_CP_PRINC ;
		goto cred_exit;
	}
	auks_log("client principal successfully put into request cred");

	/* copy krbtgt/... principal in futur credential as required */
	/* server principal for TGS */
	err_code = krb5_copy_principal(context,read_cred.server,
				       &renew_cred.server);
	if (err_code) {
		auks_error("unable to put server principal into "
			   "request cred : %s",error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_CP_PRINC ;
		goto cred_exit;
	}
	auks_log("server principal successfully put into request cred");

	/* renew credential cache TGT */
/* 	err_code = krb5_get_credentials_renew(context,KDC_OPT_RENEW,ccache, */
/* 					      &renew_cred,&p_cred_out); */
	err_code = krb5_get_cred_via_tkt(context,&read_cred,KDC_OPT_RENEW,
					 NULL,&renew_cred,&p_cred_out);

	if (err_code) {
		auks_error("unable to renew credential cache TGT : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_TGT_RENEW ;
	} else {
		auks_log("credential cache TGT successfully renewed");
		krb5_free_creds(context,p_cred_out);
		fstatus = AUKS_SUCCESS ;
	}

cred_exit:
	/* potential bug to check */
	krb5_free_cred_contents(context,&renew_cred);

seq_exit:
	krb5_free_cred_contents(context,&read_cred);

cc_exit:
	krb5_cc_close(context, ccache);

ctx_exit:
	krb5_free_context(context);

exit:
	return fstatus;
}
Beispiel #22
0
int
auks_krb5_cred_get(char *ccachefilename,char **pbuffer,
		   size_t * plength)
{
	int fstatus = AUKS_ERROR ;

	/* kerberos related variables */
	krb5_error_code err_code;
	krb5_context context;
	krb5_auth_context auth_context;
	krb5_ccache ccache;
	krb5_creds read_cred;
	krb5_cc_cursor cc_cursor;
	krb5_data *p_outbuf;
	krb5_replay_data krdata;

	int read_cred_was_used = 0;
	int read_cred_is_tgt = 0;

	char *buffer;
	size_t length;

	/* initialize kerberos context */
	err_code = krb5_init_context(&context);
	if (err_code) {
		auks_error("unable to initialize kerberos context : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_INIT_CTX ;
		goto exit;
	}
	auks_log("kerberos context successfully initialized");

	/* initialize kerberos credential cache structure */
	if (ccachefilename == NULL)
		err_code = krb5_cc_default(context, &ccache);
	else
		err_code = krb5_cc_resolve(context, ccachefilename,&ccache);
	if (err_code) {
		auks_error("unable to resolve credential cache : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_OPEN_CC ;
		goto ctx_exit ;
	}
	auks_log("credential cache successfully resolved");

	/* start credential cache sequential reading */
	err_code = krb5_cc_start_seq_get(context, ccache,&cc_cursor);
	if (err_code) {
		auks_error("unable to start credential cache sequential "
			   "read : %s",error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_READ_CC ;
		goto cc_exit;
	}
	auks_log("credential cache sequential read successfully started");

	/* look for the first TGT of the cache */
	do {
		err_code = krb5_cc_next_cred(context,ccache,
					     &cc_cursor,&read_cred);
		if (!err_code) {
			/* mark read_cred variable as used */
			read_cred_was_used = 1;
			/* just check initial or forwarded tickets (TGTs) */
			if ((read_cred.ticket_flags & TKT_FLG_INITIAL)
			    || (read_cred.ticket_flags & TKT_FLG_FORWARDED)) {
				read_cred_is_tgt = 1 ;
				break;
			}
		}
	}
	while (!err_code);

	/* stop credential cache sequential reading */
	err_code = krb5_cc_end_seq_get(context,ccache,&cc_cursor);
	if (err_code) {
		auks_error("unable to stop credential cache sequential "
			   "read : %s",error_message(err_code));
	} else
		auks_log("credential cache sequential read "
			 "successfully stopped");

	/* extract credential if a TGT was found */
	if (!read_cred_is_tgt) {
		auks_error("no TGT found in credential cache");
		fstatus = AUKS_ERROR_KRB5_CRED_NO_TGT_FOUND ;
		goto seq_exit;
	}
	auks_log("TGT found in credential cache");

	/* initialize a nullified kerberos authentication context in order */
	/* to serialize credential into buffer */
	err_code = krb5_auth_con_init(context,&auth_context);
	if (err_code) {
		auks_error("unable to initialize kerberos authentication "
			   "context : %s",error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_INIT_AUTH_CTX ;
		goto seq_exit;
	}
	auks_log("kerberos authentication context successfully initialized");

	/* clear kerberos authentication context flags */
	krb5_auth_con_setflags(context,auth_context,0);

	/* extract credential data */
	err_code = krb5_mk_1cred(context,auth_context,&read_cred,
				 &p_outbuf,&krdata);
	if (err_code) {
		auks_error("unable to dump credential into working buffer : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_MK_CRED ;
		goto auth_ctx_exit;
	}
	auks_log("credential successfully dumped into buffer");

	/* allocate output buffer */
	length = p_outbuf->length;
	buffer = (char *) malloc(length * sizeof(char));
	if (buffer == NULL) {
		auks_error("unable to allocate memory for credential data "
			   "storage");
		fstatus = AUKS_ERROR_KRB5_CRED_MALLOC ;
		goto cred_exit;
	}

	/* copy credential data into output buffer */
	memcpy(buffer,p_outbuf->data,length);
	*pbuffer = buffer;
	*plength = length;
	auks_log("credential successfully stored in output buffer");
	fstatus = AUKS_SUCCESS ;

cred_exit:
	krb5_free_data(context,p_outbuf);

auth_ctx_exit:
	/* free kerberos authentication context */
	krb5_auth_con_free(context,auth_context);

seq_exit:
	/* free credential contents */
	if (read_cred_was_used)
		krb5_free_cred_contents(context,&read_cred);

cc_exit:
	krb5_cc_close(context, ccache);

ctx_exit:
	krb5_free_context(context);

exit:
	return fstatus;
}
Beispiel #23
0
DWORD
LwKrb5CopyFromUserCache(
                krb5_context ctx,
                krb5_ccache destCC,
                uid_t uid
                )
{
    DWORD dwError = LW_ERROR_SUCCESS;
    PSTR  pszCachePath = NULL;
    krb5_ccache srcCC = NULL;
    krb5_cc_cursor srcPos = NULL;
    krb5_cc_cursor destPos = NULL;
    // Free with krb5_free_cred_contents
    krb5_creds srcCreds = {0};
    // Free with krb5_free_cred_contents
    krb5_creds destCreds = {0};
    krb5_error_code ret = 0;
    krb5_principal destClient = 0;
    BOOLEAN bIncludeTicket = TRUE;
    DWORD dwTime = 0;

    ret = krb5_cc_get_principal(
            ctx,
            destCC,
            &destClient);
    BAIL_ON_KRB_ERROR(ctx, ret);

    dwError = LwKrb5GetUserCachePath(
                    uid,
                    KRB5_File_Cache,
                    &pszCachePath);
    BAIL_ON_LW_ERROR(dwError);
    
    ret = krb5_cc_resolve(
            ctx,
            pszCachePath,
            &srcCC);
    BAIL_ON_KRB_ERROR(ctx, ret);

    ret = krb5_cc_start_seq_get(
            ctx,
            srcCC,
            &srcPos);
    if (ret == KRB5_FCC_NOFILE)
    {
        // The cache file does not exist
        ret = 0;
        goto cleanup;
    }
    if (ret == KRB5_CC_FORMAT)
    {
        // Some other user put a bad cc in place - don't copy anything
        // from it.
        ret = 0;
        goto cleanup;
    }
    BAIL_ON_KRB_ERROR(ctx, ret);

    dwTime = time(NULL);

    while (1)
    {
        krb5_free_cred_contents(
                ctx,
                &srcCreds);

        ret = krb5_cc_next_cred(
                ctx,
                srcCC,
                &srcPos,
                &srcCreds);
        if (ret == KRB5_CC_FORMAT) {
            break;
        } else if (ret == KRB5_CC_END) {
            break;
        } else {
            BAIL_ON_KRB_ERROR(ctx, ret);
        }

        if (!krb5_principal_compare(ctx, destClient, srcCreds.client))
        {
            /* Can't keep these creds. The client principal doesn't
             * match. */
            continue;
        }

        if ( srcCreds.times.endtime < dwTime )
        {
            /* Credentials are too old. */
            continue;
        }

        if (destPos != NULL)
        {
            krb5_cc_end_seq_get(
                    ctx,
                    destCC,
                    &destPos);
            destPos = NULL;
        }

        ret = krb5_cc_start_seq_get(
                ctx,
                destCC,
                &destPos);
        BAIL_ON_KRB_ERROR(ctx, ret);

        bIncludeTicket = TRUE;

        while(bIncludeTicket)
        {
            krb5_free_cred_contents(
                    ctx,
                    &destCreds);

            ret = krb5_cc_next_cred(
                    ctx,
                    destCC,
                    &destPos,
                    &destCreds);
            if (ret == KRB5_CC_END) {
                break;
            } else {
                BAIL_ON_KRB_ERROR(ctx, ret);
            }

            if (krb5_principal_compare(
                        ctx,
                        destCreds.server,
                        srcCreds.server))
            {
                /* These credentials are already in the dest cache
                 */
                bIncludeTicket = FALSE;
            }
        }

        if (bIncludeTicket)
        {
            // These creds can go in the new cache
            ret = krb5_cc_store_cred(ctx, destCC, &srcCreds);
            BAIL_ON_KRB_ERROR(ctx, ret);
        }
    }

cleanup:

    LW_SAFE_FREE_STRING(pszCachePath);

    if (ctx != NULL)
    {
        if (srcPos != NULL)
        {
            krb5_cc_end_seq_get(
                    ctx,
                    srcCC,
                    &srcPos);
        }
        if (destPos != NULL)
        {
            krb5_cc_end_seq_get(
                    ctx,
                    destCC,
                    &destPos);
        }
        if (srcCC != NULL)
        {
            krb5_cc_close(ctx, srcCC);
        }
        krb5_free_cred_contents(ctx, &srcCreds);
        krb5_free_cred_contents(ctx, &destCreds);
        if (destClient != NULL)
        {
            krb5_free_principal(ctx, destClient);
        }
    }

    return dwError;

error:
    goto cleanup;
}
Beispiel #24
0
static krb5_error_code
krb5_cc_retrieve_cred_seq (krb5_context context, krb5_ccache id,
			   krb5_flags whichfields, krb5_creds *mcreds,
			   krb5_creds *creds, int nktypes, krb5_enctype *ktypes)
{
     /* This function could be considerably faster if it kept indexing */
     /* information.. sounds like a "next version" idea to me. :-) */

     krb5_cc_cursor cursor;
     krb5_error_code kret;
     krb5_error_code nomatch_err = KRB5_CC_NOTFOUND;
     struct {
       krb5_creds creds;
       int pref;
     } fetched, best;
     int have_creds = 0;
     krb5_flags oflags = 0;
#define fetchcreds (fetched.creds)

     /* Solaris Kerberos */
     memset(&best, 0, sizeof (best));
     memset(&fetched, 0, sizeof (fetched));

     kret = krb5_cc_get_flags(context, id, &oflags);
     if (kret != KRB5_OK)
	  return kret;
     if (oflags & KRB5_TC_OPENCLOSE)
	 (void) krb5_cc_set_flags(context, id, oflags & ~KRB5_TC_OPENCLOSE);
     kret = krb5_cc_start_seq_get(context, id, &cursor);
     if (kret != KRB5_OK) {
	  if (oflags & KRB5_TC_OPENCLOSE)
	       krb5_cc_set_flags(context, id, oflags);
	  return kret;
     }

     while ((kret = krb5_cc_next_cred(context, id, &cursor, &fetchcreds)) == KRB5_OK) {
      if (krb5int_cc_creds_match_request(context, whichfields, mcreds, &fetchcreds))
      {
	      if (ktypes) {
		  fetched.pref = pref (fetchcreds.keyblock.enctype,
				       nktypes, ktypes);
		  if (fetched.pref < 0)
		      nomatch_err = KRB5_CC_NOT_KTYPE;
		  else if (!have_creds || fetched.pref < best.pref) {
		      if (have_creds)
			  krb5_free_cred_contents (context, &best.creds);
		      else
			  have_creds = 1;
		      best = fetched;
		      continue;
		  }
	      } else {
		  krb5_cc_end_seq_get(context, id, &cursor);
		  *creds = fetchcreds;
		  /* Solaris Kerberos */
		  creds->keyblock.hKey = CK_INVALID_HANDLE;
		  if (oflags & KRB5_TC_OPENCLOSE)
		      krb5_cc_set_flags(context, id, oflags);
		  return KRB5_OK;
	      }
	  }

	  /* This one doesn't match */
	  krb5_free_cred_contents(context, &fetchcreds);
     }

     /* If we get here, a match wasn't found */
     krb5_cc_end_seq_get(context, id, &cursor);
     if (oflags & KRB5_TC_OPENCLOSE)
	 krb5_cc_set_flags(context, id, oflags);
     if (have_creds) {
	 *creds = best.creds;
	 /* Solaris Kerberos */
	 creds->keyblock.hKey = CK_INVALID_HANDLE;
	 return KRB5_OK;
     } else
	 return nomatch_err;
}
OM_uint32 KRB5_CALLCONV
gss_krb5int_copy_ccache(OM_uint32 *minor_status,
                        gss_cred_id_t cred_handle,
                        const gss_OID desired_object,
                        const gss_buffer_t value)
{
    krb5_gss_cred_id_t k5creds;
    krb5_cc_cursor cursor;
    krb5_creds creds;
    krb5_error_code code;
    krb5_context context;
    krb5_ccache out_ccache;

    assert(value->length == sizeof(out_ccache));

    if (value->length != sizeof(out_ccache))
        return GSS_S_FAILURE;

    out_ccache = (krb5_ccache)value->value;

    /* cred handle will have been validated by gssspi_set_cred_option() */

    k5creds = (krb5_gss_cred_id_t) cred_handle;
    code = k5_mutex_lock(&k5creds->lock);
    if (code) {
        *minor_status = code;
        return GSS_S_FAILURE;
    }
    if (k5creds->usage == GSS_C_ACCEPT) {
        k5_mutex_unlock(&k5creds->lock);
        *minor_status = (OM_uint32) G_BAD_USAGE;
        return(GSS_S_FAILURE);
    }

    code = krb5_gss_init_context(&context);
    if (code) {
        k5_mutex_unlock(&k5creds->lock);
        *minor_status = code;
        return GSS_S_FAILURE;
    }

    code = krb5_cc_start_seq_get(context, k5creds->ccache, &cursor);
    if (code) {
        k5_mutex_unlock(&k5creds->lock);
        *minor_status = code;
        save_error_info(*minor_status, context);
        krb5_free_context(context);
        return(GSS_S_FAILURE);
    }
    while (!code && !krb5_cc_next_cred(context, k5creds->ccache, &cursor,
                                       &creds)) {
        code = krb5_cc_store_cred(context, out_ccache, &creds);
        krb5_free_cred_contents(context, &creds);
    }
    krb5_cc_end_seq_get(context, k5creds->ccache, &cursor);
    k5_mutex_unlock(&k5creds->lock);
    *minor_status = code;
    if (code)
        save_error_info(*minor_status, context);
    krb5_free_context(context);
    return code ? GSS_S_FAILURE : GSS_S_COMPLETE;
}
Beispiel #26
0
/*
 * Class:     sun_security_krb5_Credentials
 * Method:    acquireDefaultNativeCreds
 * Signature: ()Lsun/security/krb5/Credentials;
 */
JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativeCreds
(JNIEnv *env, jclass krbcredsClass)
{
    jobject krbCreds = NULL;
    krb5_error_code err = 0;
    krb5_ccache ccache = NULL;
    krb5_cc_cursor cursor = NULL;
    krb5_creds creds;
    krb5_flags flags = 0;
    krb5_context kcontext = NULL;

    /* Initialize the Kerberos 5 context */
    err = krb5_init_context (&kcontext);

    if (!err) {
        err = krb5_cc_default (kcontext, &ccache);
    }

    if (!err) {
        err = krb5_cc_set_flags (kcontext, ccache, flags); /* turn off OPENCLOSE */
    }

    if (!err) {
        err = krb5_cc_start_seq_get (kcontext, ccache, &cursor);
    }

    if (!err) {
        while ((err = krb5_cc_next_cred (kcontext, ccache, &cursor, &creds)) == 0) {
            char *serverName = NULL;

            if (!err) {
                err = krb5_unparse_name (kcontext, creds.server, &serverName);
                printiferr (err, "while unparsing server name");
            }

            if (!err) {
                if (strncmp (serverName, "krbtgt", strlen("krbtgt")) == 0) {
                    jobject ticket, clientPrincipal, targetPrincipal, encryptionKey;
                    jobject ticketFlags, startTime, endTime;
                    jobject authTime, renewTillTime, hostAddresses;

                    ticket = clientPrincipal = targetPrincipal = encryptionKey = NULL;
                    ticketFlags = startTime = endTime = NULL;
                    authTime = renewTillTime = hostAddresses = NULL;

                    // For the default credentials we're only interested in the krbtgt server.
                    clientPrincipal = BuildClientPrincipal(env, kcontext, creds.client);
                    if (clientPrincipal == NULL) goto cleanup;

                    targetPrincipal = BuildClientPrincipal(env, kcontext, creds.server);
                    if (targetPrincipal == NULL) goto cleanup;

                    // Build a com.ibm.security.krb5.Ticket
                    ticket = BuildTicket(env, &creds.ticket);
                    if (ticket == NULL) goto cleanup;

                    // Get the encryption key
                    encryptionKey = BuildEncryptionKey(env, &creds.keyblock);
                    if (encryptionKey == NULL) goto cleanup;

                    // and the ticket flags
                    ticketFlags = BuildTicketFlags(env, creds.ticket_flags);
                    if (ticketFlags == NULL) goto cleanup;

                    // Get the timestamps out.
                    startTime = BuildKerberosTime(env, creds.times.starttime);
                    if (startTime == NULL) goto cleanup;

                    authTime = BuildKerberosTime(env, creds.times.authtime);
                    if (authTime == NULL) goto cleanup;

                    endTime = BuildKerberosTime(env, creds.times.endtime);
                    if (endTime == NULL) goto cleanup;

                    renewTillTime = BuildKerberosTime(env, creds.times.renew_till);
                    if (renewTillTime == NULL) goto cleanup;

                    // Create the addresses object.
                    hostAddresses = BuildAddressList(env, creds.addresses);

                    if (krbcredsConstructor == 0) {
                        krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>",
                                              "(Lsun/security/krb5/internal/Ticket;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/EncryptionKey;Lsun/security/krb5/internal/TicketFlags;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/HostAddresses;)V");
                        if (krbcredsConstructor == 0) {
                            printf("Couldn't find com.ibm.security.krb5.Credentials constructor\n");
                            break;
                        }
                    }

                    // and now go build a KrbCreds object
                    krbCreds = (*env)->NewObject(
                                   env,
                                   krbcredsClass,
                                   krbcredsConstructor,
                                   ticket,
                                   clientPrincipal,
                                   targetPrincipal,
                                   encryptionKey,
                                   ticketFlags,
                                   authTime,
                                   startTime,
                                   endTime,
                                   renewTillTime,
                                   hostAddresses);
cleanup:
                    if (ticket) (*env)->DeleteLocalRef(env, ticket);
                    if (clientPrincipal) (*env)->DeleteLocalRef(env, clientPrincipal);
                    if (targetPrincipal) (*env)->DeleteLocalRef(env, targetPrincipal);
                    if (encryptionKey) (*env)->DeleteLocalRef(env, encryptionKey);
                    if (ticketFlags) (*env)->DeleteLocalRef(env, ticketFlags);
                    if (authTime) (*env)->DeleteLocalRef(env, authTime);
                    if (startTime) (*env)->DeleteLocalRef(env, startTime);
                    if (endTime) (*env)->DeleteLocalRef(env, endTime);
                    if (renewTillTime) (*env)->DeleteLocalRef(env, renewTillTime);
                    if (hostAddresses) (*env)->DeleteLocalRef(env, hostAddresses);
                }

            }

            if (serverName != NULL) {
                krb5_free_unparsed_name (kcontext, serverName);
            }

            krb5_free_cred_contents (kcontext, &creds);
        }

        if (err == KRB5_CC_END) {
            err = 0;
        }
        printiferr (err, "while retrieving a ticket");

    }

    if (!err) {
        err = krb5_cc_end_seq_get (kcontext, ccache, &cursor);
        printiferr (err, "while finishing ticket retrieval");
    }

    if (!err) {
        flags = KRB5_TC_OPENCLOSE; /* restore OPENCLOSE mode */
        err = krb5_cc_set_flags (kcontext, ccache, flags);
        printiferr (err, "while finishing ticket retrieval");
    }

    krb5_free_context (kcontext);
    return krbCreds;
}
static void
store_tickets(struct passwd *pwd, int ticket_newfiles, int ticket_store,
    int token_install)
{
	char cc_file[MAXPATHLEN];
	krb5_ccache ccache_store;
#ifdef KRB524
	int get_krb4_ticket = 0;
	char krb4_ticket_file[MAXPATHLEN];
#endif

	if (ticket_newfiles)
		snprintf(cc_file, sizeof(cc_file), "FILE:/tmp/krb5cc_%d",
		    pwd->pw_uid);
	else
		snprintf(cc_file, sizeof(cc_file), "%s",
		    krb5_cc_default_name(context));

	if (ticket_store) {
		ret = krb5_cc_resolve(context, cc_file, &ccache_store);
		if (ret != 0) {
			krb5_syslog(context, LOG_ERR, ret,
			    "krb5_cc_gen_new");
			exit(1);
		}

		ret = krb5_cc_copy_cache(context, ccache, ccache_store);
		if (ret != 0)
			krb5_syslog(context, LOG_ERR, ret,
			    "krb5_cc_copy_cache");

		chown(krb5_cc_get_name(context, ccache_store),
		    pwd->pw_uid, pwd->pw_gid);

		fprintf(back, BI_SETENV " KRB5CCNAME %s:%s\n",
		    krb5_cc_get_type(context, ccache_store),
		    krb5_cc_get_name(context, ccache_store));

#ifdef KRB524
		get_krb4_ticket = krb5_config_get_bool_default (context,
		    NULL, get_krb4_ticket, "libdefaults",
		    "krb4_get_tickets", NULL);
		if (get_krb4_ticket) {
			CREDENTIALS c;
			krb5_creds cred;
			krb5_cc_cursor cursor;

			ret = krb5_cc_start_seq_get(context, ccache, &cursor);
			if (ret != 0) {
				krb5_syslog(context, LOG_ERR, ret,
				    "start seq");
				exit(1);
			}

			ret = krb5_cc_next_cred(context, ccache,
			    &cursor, &cred);
			if (ret != 0) {
				krb5_syslog(context, LOG_ERR, ret,
				    "next cred");
				exit(1);
			}

			ret = krb5_cc_end_seq_get(context, ccache,
			    &cursor);
			if (ret != 0) {
				krb5_syslog(context, LOG_ERR, ret,
				    "end seq");
				exit(1);
			}

			ret = krb524_convert_creds_kdc_ccache(context, ccache,
			    &cred, &c);
			if (ret != 0) {
				krb5_syslog(context, LOG_ERR, ret,
				    "convert");
			} else {
				snprintf(krb4_ticket_file,
				    sizeof(krb4_ticket_file),
				    "%s%d", TKT_ROOT, pwd->pw_uid);
				krb_set_tkt_string(krb4_ticket_file);
				tf_setup(&c, c.pname, c.pinst);
				chown(krb4_ticket_file,
				    pwd->pw_uid, pwd->pw_gid);
			}
		}
#endif
	}

	/* Need to chown the ticket file */
#ifdef KRB524
	if (get_krb4_ticket)
		fprintf(back, BI_SETENV " KRBTKFILE %s\n",
		    krb4_ticket_file);
#endif
}
Beispiel #28
0
void
main(
    int argc,
    char *argv[]
    )
{
    krb5_context kcontext;
    krb5_error_code code;
    krb5_ccache ccache=NULL;
    krb5_ccache mslsa_ccache=NULL;
    krb5_cc_cursor cursor;
    krb5_creds creds;
    krb5_principal princ;
    int initial_ticket = 0;
    int option;
    char * ccachestr = 0;

    prog = strrchr(argv[0], '/');
    prog = prog ? (prog + 1) : argv[0];

    while ((option = getopt(argc, argv, "c:h")) != -1) {
        switch (option) {
        case 'c':
            ccachestr = optarg;
            break;
        case 'h':
        default:
            xusage();
            break;
        }
    }
        
    if (code = krb5_init_context(&kcontext)) {
        com_err(argv[0], code, "while initializing kerberos library");
        exit(1);
    }
  
    if (code = krb5_cc_resolve(kcontext, "MSLSA:", &mslsa_ccache)) {
        com_err(argv[0], code, "while opening MS LSA ccache");
        krb5_free_context(kcontext);
        exit(1);
    }

    if (code = krb5_cc_set_flags(kcontext, mslsa_ccache, KRB5_TC_NOTICKET)) {
        com_err(argv[0], code, "while setting KRB5_TC_NOTICKET flag");
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_free_context(kcontext);
        exit(1);
    }

    /* Enumerate tickets from cache looking for an initial ticket */
    if ((code = krb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor))) {
        com_err(argv[0], code, "while initiating the cred sequence of MS LSA ccache");
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_free_context(kcontext);
        exit(1);
    }

    while (!(code = krb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds))) 
    {
        if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
            krb5_free_cred_contents(kcontext, &creds);
            initial_ticket = 1;
            break;
        }
        krb5_free_cred_contents(kcontext, &creds);
    }
    krb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor);

    if (code = krb5_cc_set_flags(kcontext, mslsa_ccache, 0)) {
        com_err(argv[0], code, "while clearing flags");
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_free_context(kcontext);
        exit(1);
    }

    if ( !initial_ticket ) {
        fprintf(stderr, "%s: Initial Ticket Getting Tickets are not available from the MS LSA\n",
                argv[0]);
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_free_context(kcontext);
        exit(1);
    }

    if (code = krb5_cc_get_principal(kcontext, mslsa_ccache, &princ)) {
        com_err(argv[0], code, "while obtaining MS LSA principal");
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_free_context(kcontext);
        exit(1);
    }

    if (ccachestr)
        code = krb5_cc_resolve(kcontext, ccachestr, &ccache);
    else
        code = krb5_cc_default(kcontext, &ccache);
    if (code) {
        com_err(argv[0], code, "while getting default ccache");
        krb5_free_principal(kcontext, princ);
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_free_context(kcontext);
        exit(1);
    }
    if (code = krb5_cc_initialize(kcontext, ccache, princ)) {
        com_err (argv[0], code, "when initializing ccache");
        krb5_free_principal(kcontext, princ);
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_cc_close(kcontext, ccache);
        krb5_free_context(kcontext);
        exit(1);
    }

    if (code = krb5_cc_copy_creds(kcontext, mslsa_ccache, ccache)) {
        com_err (argv[0], code, "while copying MS LSA ccache to default ccache");
        krb5_free_principal(kcontext, princ);
        krb5_cc_close(kcontext, ccache);
        krb5_cc_close(kcontext, mslsa_ccache);
        krb5_free_context(kcontext);
        exit(1);
    }

    krb5_free_principal(kcontext, princ);
    krb5_cc_close(kcontext, ccache);
    krb5_cc_close(kcontext, mslsa_ccache);
    krb5_free_context(kcontext);
    return(0);
}
Beispiel #29
0
static int
kinit_check_tgt(kinit_data *kid, int *remaining)
{
	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)) {
			Log(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) {
				Log(LDAP_DEBUG_TRACE, LDAP_LEVEL_DEBUG,
						"kinit_qtask: TGT (%s) expired\n", name);
			} else {
				Log(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;
					Log(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 {
					Log(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;
}
Beispiel #30
0
static
NTSTATUS
LwIoCredentialCacheToTgt(
    PIO_CREDS pCacheToken,
    PIO_CREDS* ppCreds
)
{
    NTSTATUS Status = STATUS_SUCCESS;
    krb5_context pContext = NULL;
    krb5_error_code krb5Error = 0;
    krb5_ccache pCache = NULL;
    PSTR pszClientPrincipalName = NULL;
    PSTR pszServerPrincipalName = NULL;
    PSTR pszDesiredPrincipal = NULL;
    PSTR pszCredCachePath = NULL;
    PIO_CREDS pCreds = NULL;
    BOOLEAN bFoundTgt = FALSE;
    BOOLEAN bStartSeq = FALSE;
    krb5_creds creds;
    krb5_cc_cursor cursor;

    Status = LwRtlCStringAllocateFromWC16String(
                 &pszDesiredPrincipal,
                 pCacheToken->payload.krb5Ccache.pwszPrincipal);
    BAIL_ON_NT_STATUS(Status);

    Status = LwRtlCStringAllocateFromWC16String(
                 &pszCredCachePath,
                 pCacheToken->payload.krb5Ccache.pwszCachePath);
    BAIL_ON_NT_STATUS(Status);

    /* Open credentials cache */
    krb5Error = krb5_init_context(&pContext);
    if (krb5Error)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        BAIL_ON_NT_STATUS(Status);
    }

    krb5Error = krb5_cc_resolve(pContext, pszCredCachePath, &pCache);
    if (krb5Error)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }

    /* Look for a TGT */
    krb5Error = krb5_cc_start_seq_get(pContext, pCache, &cursor);
    if (krb5Error)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }

    bStartSeq = TRUE;

    while ((krb5Error = krb5_cc_next_cred(pContext, pCache, &cursor, &creds)) == 0)
    {
        /* Look tickets with the intial flag set */
        if (creds.ticket_flags & TKT_FLG_INITIAL)
        {
            /* Extract and compare client principal with desired principal */
            krb5Error = krb5_unparse_name(pContext, creds.client, &pszClientPrincipalName);
            if (krb5Error)
            {
                Status = STATUS_UNSUCCESSFUL;
                BAIL_ON_NT_STATUS(Status);
            }
            if (!strcmp(pszClientPrincipalName, pszDesiredPrincipal))
            {
                bFoundTgt = TRUE;
                break;
            }

            krb5_free_unparsed_name(pContext, pszClientPrincipalName);
            pszClientPrincipalName = NULL;
        }

        krb5_free_cred_contents(pContext, &creds);
    }

    if (!bFoundTgt)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }

    /* Extract server principal name */
    krb5Error = krb5_unparse_name(pContext, creds.server, &pszServerPrincipalName);
    if (krb5Error)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }

    /* Construct token from krb5 credential data */
    Status = LwIoAllocateMemory(sizeof(*pCreds), OUT_PPVOID(&pCreds));
    BAIL_ON_NT_STATUS(Status);

    pCreds->type = IO_CREDS_TYPE_KRB5_TGT;

    /* Copy principal names */
    Status = LwRtlWC16StringAllocateFromCString(
                 &pCreds->payload.krb5Tgt.pwszClientPrincipal,
                 pszClientPrincipalName);
    BAIL_ON_NT_STATUS(Status);

    Status = LwRtlWC16StringAllocateFromCString(
                 &pCreds->payload.krb5Tgt.pwszServerPrincipal,
                 pszServerPrincipalName);
    BAIL_ON_NT_STATUS(Status);

    /* Set time fields */
    pCreds->payload.krb5Tgt.authTime = creds.times.authtime;
    pCreds->payload.krb5Tgt.startTime = creds.times.starttime;
    pCreds->payload.krb5Tgt.endTime = creds.times.endtime;
    pCreds->payload.krb5Tgt.renewTillTime = creds.times.renew_till;

    /* Copy encryption key */
    pCreds->payload.krb5Tgt.keyType = creds.keyblock.enctype;
    pCreds->payload.krb5Tgt.ulKeySize = creds.keyblock.length;
    Status = LwIoAllocateMemory(
                 creds.keyblock.length,
                 OUT_PPVOID(&pCreds->payload.krb5Tgt.pKeyData));
    BAIL_ON_NT_STATUS(Status);
    memcpy(
        pCreds->payload.krb5Tgt.pKeyData,
        creds.keyblock.contents,
        creds.keyblock.length);

    /* Copy tgt */
    pCreds->payload.krb5Tgt.tgtFlags = creds.ticket_flags;
    pCreds->payload.krb5Tgt.ulTgtSize = creds.ticket.length;
    Status = LwIoAllocateMemory(
                 creds.ticket.length,
                 OUT_PPVOID(&pCreds->payload.krb5Tgt.pTgtData));
    BAIL_ON_NT_STATUS(Status);
    memcpy(
        pCreds->payload.krb5Tgt.pTgtData,
        creds.ticket.data,
        creds.ticket.length);

    *ppCreds = pCreds;

cleanup:

    LWIO_SAFE_FREE_MEMORY(pszDesiredPrincipal);
    LWIO_SAFE_FREE_MEMORY(pszCredCachePath);

    if (pszClientPrincipalName)
    {
        krb5_free_unparsed_name(pContext, pszClientPrincipalName);
    }

    if (pszServerPrincipalName)
    {
        krb5_free_unparsed_name(pContext, pszServerPrincipalName);
    }

    if (bFoundTgt)
    {
        krb5_free_cred_contents(pContext, &creds);
    }

    if (bStartSeq)
    {
        krb5_cc_end_seq_get(pContext, pCache, &cursor);
    }

    if (pCache)
    {
        krb5_cc_close(pContext, pCache);
    }

    if (pContext)
    {
        krb5_free_context(pContext);
    }

    return Status;

error:

    *ppCreds = NULL;

    if (pCreds)
    {
        LwIoDeleteCreds(pCreds);
    }

    goto cleanup;
}