Ejemplo n.º 1
0
/* does the ccache have a valid TGT? */
static time_t get_tgt_time(const char *ccname)
{
	krb5_context context;
	krb5_ccache ccache;
	krb5_cc_cursor cur;
	krb5_creds creds;
	krb5_principal principal;
	time_t credtime = 0;
	char *realm = NULL;

	if (krb5_init_context(&context)) {
		syslog(LOG_DEBUG, "%s: unable to init krb5 context", __func__);
		return 0;
	}

	if (krb5_cc_resolve(context, ccname, &ccache)) {
		syslog(LOG_DEBUG, "%s: unable to resolve krb5 cache", __func__);
		goto err_cache;
	}

	if (krb5_cc_set_flags(context, ccache, 0)) {
		syslog(LOG_DEBUG, "%s: unable to set flags", __func__);
		goto err_cache;
	}

	if (krb5_cc_get_principal(context, ccache, &principal)) {
		syslog(LOG_DEBUG, "%s: unable to get principal", __func__);
		goto err_princ;
	}

	if (krb5_cc_start_seq_get(context, ccache, &cur)) {
		syslog(LOG_DEBUG, "%s: unable to seq start", __func__);
		goto err_ccstart;
	}

	if ((realm = cifs_krb5_principal_get_realm(context, principal)) == NULL) {
		syslog(LOG_DEBUG, "%s: unable to get realm", __func__);
		goto err_ccstart;
	}

	while (!credtime && !krb5_cc_next_cred(context, ccache, &cur, &creds)) {
		char *name;
		if (krb5_unparse_name(context, creds.server, &name)) {
			syslog(LOG_DEBUG, "%s: unable to unparse name",
			       __func__);
			goto err_endseq;
		}
		if (krb5_realm_compare(context, creds.server, principal) &&
		    !strncasecmp(name, KRB5_TGS_NAME, KRB5_TGS_NAME_SIZE) &&
		    !strncasecmp(name + KRB5_TGS_NAME_SIZE + 1, realm,
				 strlen(realm))
		    && creds.times.endtime > time(NULL))
			credtime = creds.times.endtime;
		krb5_free_cred_contents(context, &creds);
		krb5_free_unparsed_name(context, name);
	}
err_endseq:
	krb5_cc_end_seq_get(context, ccache, &cur);
err_ccstart:
	krb5_free_principal(context, principal);
err_princ:
#if defined(KRB5_TC_OPENCLOSE)
	krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
#endif
	krb5_cc_close(context, ccache);
err_cache:
	krb5_free_context(context);
	return credtime;
}
Ejemplo n.º 2
0
Archivo: ms2mit.c Proyecto: cktan/tool2
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;
}
Ejemplo n.º 3
0
krb5_error_code KRB5_CALLCONV
krb5_cccol_have_content(krb5_context context)
{
    krb5_error_code ret;
    krb5_cccol_cursor col_cursor;
    krb5_cc_cursor cache_cursor;
    krb5_ccache cache;
    krb5_creds creds;
    krb5_boolean found = FALSE;
    struct errinfo errsave = EMPTY_ERRINFO;
    const char *defname;

    ret = krb5_cccol_cursor_new(context, &col_cursor);
    save_first_error(context, ret, &errsave);
    if (ret)
        goto no_entries;

    while (!found) {
        ret = krb5_cccol_cursor_next(context, col_cursor, &cache);
        save_first_error(context, ret, &errsave);
        if (ret || cache == NULL)
            break;

        ret = krb5_cc_start_seq_get(context, cache, &cache_cursor);
        save_first_error(context, ret, &errsave);
        if (ret)
            continue;
        while (!found) {
            ret = krb5_cc_next_cred(context, cache, &cache_cursor, &creds);
            save_first_error(context, ret, &errsave);
            if (ret)
                break;

            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:
    if (errsave.code) {
        /* Report the first error we encountered. */
        ret = k5_restore_ctx_error(context, &errsave);
        k5_wrapmsg(context, ret, KRB5_CC_NOTFOUND,
                   _("No Kerberos credentials available"));
    } else {
        /* Report the default cache name. */
        defname = krb5_cc_default_name(context);
        if (defname != NULL) {
            k5_setmsg(context, KRB5_CC_NOTFOUND,
                      _("No Kerberos credentials available "
                        "(default cache: %s)"), defname);
        }
    }
    return KRB5_CC_NOTFOUND;
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
/* fill in service tickets data */
gboolean
ka_get_service_tickets (GtkListStore * tickets, gboolean hide_conf_tickets)
{
    krb5_cc_cursor cursor;
    krb5_creds creds;
    krb5_error_code ret;
    GtkTreeIter iter;
    krb5_ccache ccache;
    char *name;
    krb5_timestamp sec;
    gchar start_time[128], end_time[128], end_time_markup[256];
    gboolean retval = FALSE;

    gtk_list_store_clear (tickets);

    krb5_timeofday (kcontext, &sec);
    ret = krb5_cc_default (kcontext, &ccache);
    g_return_val_if_fail (!ret, FALSE);

    ret = krb5_cc_start_seq_get (kcontext, ccache, &cursor);
    if (ret == KRB5_FCC_NOFILE) {
        ka_log_error_message_at_level (G_LOG_LEVEL_INFO, "krb5_cc_start_seq_get", kcontext, ret);

        gtk_list_store_append (tickets, &iter);
        gtk_list_store_set (tickets, &iter,
                            PRINCIPAL_COLUMN, _("Your ticket cache is currently empty"),
                            FORWARDABLE_COLUMN, FALSE,
                            RENEWABLE_COLUMN, FALSE,
                            PROXIABLE_COLUMN, FALSE, -1);
        retval = TRUE;
        goto out;
    } else if (ret) {
        goto out;
    }


    while ((ret = krb5_cc_next_cred (kcontext, ccache, &cursor, &creds)) == 0) {
        gboolean renewable, proxiable, forwardable;


        if (hide_conf_tickets && krb5_is_config_principal (kcontext,
                                                           creds.server)) {
            krb5_free_cred_contents (kcontext, &creds);
            continue;
        }

        if (creds.times.starttime)
            ka_format_time (creds.times.starttime, start_time,
                            sizeof (start_time));
        else
            ka_format_time (creds.times.authtime, start_time,
                            sizeof (start_time));

        ka_format_time (creds.times.endtime, end_time, sizeof (end_time));
        if (creds.times.endtime > sec)
            strcpy (end_time_markup, end_time);
        else
            g_snprintf (end_time_markup, sizeof (end_time_markup),
                        "%s <span foreground=\"red\" style=\"italic\">(%s)</span>",
                        end_time, _("Expired"));

        forwardable = get_cred_forwardable (&creds);
        renewable = get_cred_renewable (&creds);
        proxiable = get_cred_proxiable (&creds);

        ret = krb5_unparse_name (kcontext, creds.server, &name);
        if (!ret) {
            gtk_list_store_append (tickets, &iter);
            gtk_list_store_set (tickets, &iter,
                                PRINCIPAL_COLUMN, name,
                                START_TIME_COLUMN, start_time,
                                END_TIME_COLUMN, end_time_markup,
                                FORWARDABLE_COLUMN, forwardable,
                                RENEWABLE_COLUMN, renewable,
                                PROXIABLE_COLUMN, proxiable, -1);
            free (name);
        } else
            ka_log_error_message ("krb5_unparse_name", kcontext, ret);
        krb5_free_cred_contents (kcontext, &creds);
    }
    if (ret != KRB5_CC_END)
        ka_log_error_message ("krb5_cc_get_next", kcontext, ret);

    ret = krb5_cc_end_seq_get (kcontext, ccache, &cursor);
    if (ret)
        ka_log_error_message ("krb5_cc_end_seq_get", kcontext, ret);

    retval = TRUE;
  out:
    ret = krb5_cc_close (kcontext, ccache);
    g_return_val_if_fail (!ret, FALSE);

    return retval;
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
int
main(int argc, const char **argv)
{
    poptContext poptContext;
    int poptResult;
    uid_t uid;
    int kq;
    HANDLE lsaConnection = (HANDLE) NULL;
    PVOID pUserInfo = NULL;
    struct kevent event = { 0 };
    int numChanges = 1;
    krb5_context krb5Context = NULL;
    char krb5FileCachePath[PATH_MAX];
    krb5_ccache krb5FileCache = NULL;
    krb5_ccache krb5MemoryCache = NULL;
    krb5_cc_cursor krb5Cursor = NULL;
    krb5_creds krb5Credentials = { 0 };
    krb5_principal krb5Principal = NULL;
    krb5_error_code krb5Error;
    int exitStatus = 0;
    DWORD dwError = LW_ERROR_SUCCESS;

    poptContext = poptGetContext(NULL, argc, argv, Options, 0);
    while ((poptResult = poptGetNextOpt(poptContext)) >= 0)
    {
        /* All options are processed automatically. */
    }

    if (poptResult < -1)
    {
        fprintf(stderr, "%s: %s: %s\n", getprogname(),
                poptBadOption(poptContext, POPT_BADOPTION_NOALIAS),
                poptStrerror(poptResult));
        exitStatus = 1;
        goto error;
    }

    uid = getuid();

    /* Make sure we're running as an AD user. */
    dwError = LsaOpenServer(&lsaConnection);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaFindUserById(
                  lsaConnection,
                  uid,
                  0,
                  &pUserInfo);
    if (dwError == LW_ERROR_NO_SUCH_USER)
    {
        /*
         * Running as a non-AD user; exit 0 so launchd doesn't restart
         * the ticketcopy program (see com.beyondtrust.pbis.ticketcopy.plist).
         */
        LSA_LOG_DEBUG(
            "uid %lu is not an AD user; exiting",
            (unsigned long) uid);
        dwError = LW_ERROR_SUCCESS;
        goto cleanup;
    }
    BAIL_ON_LSA_ERROR(dwError);

    kq = kqueue();
    BAIL_ON_UNIX_ERROR(kq == -1);

    krb5Error = krb5_init_context(&krb5Context);
    BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

    krb5Error = krb5_cc_default(krb5Context, &krb5MemoryCache);
    BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

    snprintf(
        krb5FileCachePath,
        sizeof(krb5FileCachePath),
        "FILE:/tmp/krb5cc_%lu",
        (unsigned long) uid);

    while (1) /* Forever (or until an error occurs) */
    {
        while ((event.ident = open(krb5FileCachePath + 5, O_RDONLY)) == -1)
        {
            sleep(5);
        }

        event.filter = EVFILT_VNODE;
        event.flags = EV_ADD | EV_ENABLE | EV_CLEAR;
        event.fflags = NOTE_DELETE | NOTE_WRITE;
        numChanges = 1;

        krb5Error = krb5_cc_resolve(
                        krb5Context,
                        krb5FileCachePath,
                        &krb5FileCache);
        BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

        while (1) /* While the file continues to exist. */
        {
            /*
             * Turn off KRB5_TC_OPENCLOSE so the file will be opened once
             * and kept open.  This causes it to actually attempt to open
             * the file, so this is where we check for the file not
             * existing and retry after sleeping a bit.
             */
            krb5Error = krb5_cc_set_flags(krb5Context, krb5FileCache, 0);
            if (krb5Error == KRB5_FCC_NOFILE)
            {
                break;
            }
            BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

            /* Copy all credentials from the file to the memory cache. */
            krb5Error = krb5_cc_start_seq_get(
                            krb5Context,
                            krb5FileCache,
                            &krb5Cursor);
            BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

            while ((krb5Error = krb5_cc_next_cred(
                                    krb5Context,
                                    krb5FileCache,
                                    &krb5Cursor,
                                    &krb5Credentials)) == 0)
            {
                krb5Error = krb5_cc_store_cred(
                                krb5Context,
                                krb5MemoryCache,
                                &krb5Credentials);
                if (krb5Error == KRB5_FCC_NOFILE)
                {
                    krb5Error = krb5_cc_get_principal(
                                    krb5Context,
                                    krb5FileCache,
                                    &krb5Principal);
                    BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

                    /* The memory cache was destroyed; re-create it. */
                    krb5Error = krb5_cc_initialize(
                                    krb5Context,
                                    krb5MemoryCache,
                                    krb5Principal);
                    BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

                    krb5_free_principal(krb5Context, krb5Principal);
                    krb5Principal = NULL;

                    krb5Error = krb5_cc_store_cred(
                                    krb5Context,
                                    krb5MemoryCache,
                                    &krb5Credentials);
                }
                BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

                krb5_free_cred_contents(krb5Context, &krb5Credentials);
            }

            if (krb5Error != KRB5_CC_END)
            {
                BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);
            }

            krb5Error = krb5_cc_end_seq_get(
                            krb5Context,
                            krb5FileCache,
                            &krb5Cursor);
            krb5Cursor = NULL;
            BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

            /*
             * Turn KRB5_TC_OPENCLOSE back on; this will cause
             * the file to be closed and any locks to be
             * released.
             */
            krb5Error = krb5_cc_set_flags(
                            krb5Context,
                            krb5FileCache,
                            KRB5_TC_OPENCLOSE);
            BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);

            /*
             * Wait for the file to be modified or deleted.  The first
             * time this is called after the file is opened, numChanges
             * will be 1, which will install the fd into the event
             * list.  After that numChanges is changed to 0, so it will
             * just report events from the existing list.
             */
            if (kevent(kq, &event, numChanges, &event, 1, NULL) != 1)
            {
                fprintf(stderr, "kevent failed\n");
                exitStatus = 1;
                goto cleanup;
            }

            if (event.fflags & NOTE_DELETE)
            {
                break;
            }

            numChanges = 0;
        }

        krb5Error = krb5_cc_close(krb5Context, krb5FileCache);
        BAIL_ON_KRB5_ERROR(krb5Context, krb5Error, dwError);
        krb5FileCache = NULL;

        close(event.ident);
        event.ident = -1;

        /*
         * The cache file is usually removed as part of a
         * rename(2) system call, so only wait a short
         * time before the first attempt to re-open it.
         */
        usleep(100000);
    }

error:
cleanup:
    krb5_free_cred_contents(krb5Context, &krb5Credentials);

    if (krb5Cursor)
    {
        krb5_cc_end_seq_get(krb5Context, krb5FileCache, &krb5Cursor);
    }

    if (krb5FileCache)
    {
        krb5_cc_close(krb5Context, krb5FileCache);
    }

    if (krb5Principal)
    {
        krb5_free_principal(krb5Context, krb5Principal);
    }

    if (krb5Context)
    {
        krb5_free_context(krb5Context);
    }

    if (event.ident != -1)
    {
        close(event.ident);
    }

    if (pUserInfo)
    {
        LsaFreeUserInfo(0, pUserInfo);
    }

    if (lsaConnection != (HANDLE) NULL)
    {
        LsaCloseServer(lsaConnection);
    }

    if (dwError)
    {
        exitStatus = 1;
    }

    return exitStatus;
}