Example #1
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;
}
Example #2
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);
}
Example #3
0
static int
store_gss_creds(gss_store_state *state, char *princ_name, gss_cred_id_t delegated_cred)
{
   OM_uint32        maj_stat, min_stat;
   krb5_error_code  problem;
   const char *     temp_ccname = "FILE:/tmp/krb5cc_pykerberos_XXXXXX";
   int              ret = 1;

   problem = krb5_init_context(&state->context);
   if (problem) {
       PyErr_SetObject(BasicAuthException_class, Py_BuildValue("((s:i))",
                                                                "Cannot initialize Kerberos5 context", problem));
       return 0;
   }
   
   int name_len = strlen(temp_ccname);
   state->ccache_name = (char *)malloc(name_len + 1);
   strcpy(state->ccache_name, temp_ccname);
   int fd = mkstemp(state->ccache_name + strlen("FILE:"));
   if (fd < 0)
   {
       PyErr_SetObject(BasicAuthException_class, 
                       Py_BuildValue("(s:s)", "Error in mkstemp", strerror(errno)));
       ret = 0;
       goto end;
   }
   close(fd);

   problem = krb5_cc_resolve(state->context, state->ccache_name, &state->ccache);
   if (problem) {
       set_basicauth_error(state->context, problem);
       ret = 0;
       goto end;
   }
   
   problem = krb5_parse_name(state->context, princ_name, &state->client);
   if (problem) {
       set_basicauth_error(state->context, problem);
       goto end;
   }

   problem = krb5_cc_initialize(state->context, state->ccache, state->client);
   if (problem) {
       set_basicauth_error(state->context, problem);
       ret = 0;
       goto end;
   }
   
   maj_stat = gss_krb5_copy_ccache(&min_stat, delegated_cred, state->ccache);
   if (GSS_ERROR(maj_stat))
   {
       set_gss_error(maj_stat, min_stat);
       ret = 0;
       goto end;
   }

   ret = 1;
   return ret;

end:
   if (state->client != NULL)
      krb5_free_principal(state->context, state->client);
   if (state->ccache != NULL)
      krb5_cc_destroy(state->context, state->ccache);
   krb5_free_context(state->context);
   return ret;
}
Example #4
0
int
klist(struct klist_options *opt, int argc, char **argv)
{
    krb5_error_code ret;
    int exit_status = 0;

    int do_verbose =
	opt->verbose_flag ||
	opt->a_flag ||
	opt->n_flag;
    int do_test =
	opt->test_flag ||
	opt->s_flag;

    if(opt->version_flag) {
	print_version(NULL);
	exit(0);
    }

    if (opt->list_all_flag) {
	exit_status = list_caches(heimtools_context, opt);
	return exit_status;
    }

    if (opt->v5_flag) {
	krb5_ccache id;

	if (opt->all_content_flag) {
	    krb5_cc_cache_cursor cursor;
	    int first = 1;

	    ret = krb5_cc_cache_get_first(heimtools_context, NULL, &cursor);
	    if (ret)
		krb5_err(heimtools_context, 1, ret, "krb5_cc_cache_get_first");

	    if (opt->json_flag)
		printf("[");
	    while (krb5_cc_cache_next(heimtools_context, cursor, &id) == 0) {
		if (opt->json_flag && !first)
		    printf(",");

		exit_status |= display_v5_ccache(heimtools_context, id, do_test,
						 do_verbose, opt->flags_flag,
						 opt->hidden_flag, opt->json_flag);
		if (!opt->json_flag)
		    printf("\n\n");

		first = 0;
	    }
	    krb5_cc_cache_end_seq_get(heimtools_context, cursor);
	    if (opt->json_flag)
		printf("]");
	} else {
	    if(opt->cache_string) {
		ret = krb5_cc_resolve(heimtools_context, opt->cache_string, &id);
		if (ret)
		    krb5_err(heimtools_context, 1, ret, "%s", opt->cache_string);
	    } else {
		ret = krb5_cc_default(heimtools_context, &id);
		if (ret)
		    krb5_err(heimtools_context, 1, ret, "krb5_cc_resolve");
	    }
	    exit_status = display_v5_ccache(heimtools_context, id, do_test,
					    do_verbose, opt->flags_flag,
					    opt->hidden_flag, opt->json_flag);
	}
    }

    if (!do_test) {
#ifndef NO_AFS
	if (opt->tokens_flag && k_hasafs()) {
	    if (opt->v5_flag)
		printf("\n");
	    display_tokens(opt->verbose_flag);
	}
#endif
    }

    return exit_status;
}
Example #5
0
void
kerberos5_is(Authenticator *ap, unsigned char *data, int cnt)
{
    krb5_error_code ret;
    krb5_data outbuf;
    krb5_keyblock *key_block;
    char *name;
    krb5_principal server;
    krb5_authenticator authenticator;
    int zero = 0;

    if (cnt-- < 1)
	return;
    switch (*data++) {
    case KRB_AUTH:
	auth.data = (char *)data;
	auth.length = cnt;

	auth_context = NULL;

	ret = krb5_auth_con_init (context, &auth_context);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	ret = krb5_auth_con_setaddrs_from_fd (context,
					      auth_context,
					      &zero);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_auth_con_setaddrs_from_fd failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	ret = krb5_sock_to_principal (context,
				      0,
				      "host",
				      KRB5_NT_SRV_HST,
				      &server);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_sock_to_principal failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	ret = krb5_rd_req(context,
			  &auth_context,
			  &auth, 
			  server,
			  NULL,
			  NULL,
			  &ticket);
	krb5_free_principal (context, server);

	if (ret) {
	    char *errbuf;

	    asprintf(&errbuf,
		     "Read req failed: %s",
		     krb5_get_err_text(context, ret));
	    Data(ap, KRB_REJECT, errbuf, -1);
	    if (auth_debug_mode)
		printf("%s\r\n", errbuf);
	    free (errbuf);
	    return;
	}

	ret = krb5_auth_con_getkey(context, auth_context, &key_block);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_con_getkey failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_auth_con_getkey failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}
	
	ret = krb5_auth_getauthenticator (context,
					  auth_context,
					  &authenticator);
	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_getauthenticator failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_auth_getauthenticator failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	if (authenticator->cksum) {
	    char foo[2];

	    foo[0] = ap->type;
	    foo[1] = ap->way;

	    ret = krb5_verify_checksum (context,
					foo,
					sizeof(foo),
					key_block,
					authenticator->cksum);
	    if (ret) {
		Data(ap, KRB_REJECT, "No checksum", -1);
		if (auth_debug_mode)
		    printf ("No checksum\r\n");
		krb5_free_authenticator (context,
					 &authenticator);
		
		return;
	    }
	}
	krb5_free_authenticator (context,
				 &authenticator);

	ret = krb5_auth_con_getremotesubkey (context,
					     auth_context,
					     &key_block);

	if (ret) {
	    Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1);
	    auth_finished(ap, AUTH_REJECT);
	    if (auth_debug_mode)
		printf("Kerberos V5: "
		       "krb5_auth_con_getremotesubkey failed (%s)\r\n",
		       krb5_get_err_text(context, ret));
	    return;
	}

	if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
	    ret = krb5_mk_rep(context, &auth_context, &outbuf);
	    if (ret) {
		Data(ap, KRB_REJECT,
		     "krb5_mk_rep failed", -1);
		auth_finished(ap, AUTH_REJECT);
		if (auth_debug_mode)
		    printf("Kerberos V5: "
			   "krb5_mk_rep failed (%s)\r\n",
			   krb5_get_err_text(context, ret));
		return;
	    }
	    Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length);
	}
	if (krb5_unparse_name(context, ticket->client, &name))
	    name = 0;

	if(UserNameRequested && krb5_kuserok(context,
					     ticket->client,
					     UserNameRequested)) {
	    Data(ap, KRB_ACCEPT, name, name ? -1 : 0);
	    if (auth_debug_mode) {
		printf("Kerberos5 identifies him as ``%s''\r\n",
		       name ? name : "");
	    }

	    if(key_block->keytype == KEYTYPE_DES) {
		Session_Key skey;

		skey.type = SK_DES;
		skey.length = 8;
		skey.data = key_block->keyvalue.data;
		encrypt_session_key(&skey, 0);
	    }

	} else {
	    char *msg;

	    asprintf (&msg, "user `%s' is not authorized to "
		      "login as `%s'", 
		      name ? name : "<unknown>",
		      UserNameRequested ? UserNameRequested : "<nobody>");
	    if (msg == NULL)
		Data(ap, KRB_REJECT, NULL, 0);
	    else {
		Data(ap, KRB_REJECT, (void *)msg, -1);
		free(msg);
	    }
	}
	auth_finished(ap, AUTH_USER);

	krb5_free_keyblock_contents(context, key_block);
	
	break;
#ifdef	FORWARD
    case KRB_FORWARD: {
	struct passwd *pwd;
	char ccname[1024];	/* XXX */
	krb5_data inbuf;
	krb5_ccache ccache;
	inbuf.data = (char *)data;
	inbuf.length = cnt;

	pwd = getpwnam (UserNameRequested);
	if (pwd == NULL)
	    break;

	snprintf (ccname, sizeof(ccname),
		  "FILE:/tmp/krb5cc_%u", pwd->pw_uid);

	ret = krb5_cc_resolve (context, ccname, &ccache);
	if (ret) {
	    if (auth_debug_mode)
		printf ("Kerberos V5: could not get ccache: %s\r\n",
			krb5_get_err_text(context, ret));
	    break;
	}

	ret = krb5_cc_initialize (context,
				  ccache,
				  ticket->client);
	if (ret) {
	    if (auth_debug_mode)
		printf ("Kerberos V5: could not init ccache: %s\r\n",
			krb5_get_err_text(context, ret));
	    break;
	}

	ret = krb5_rd_cred (context,
			    auth_context,
			    ccache,
			    &inbuf);
	if(ret) {
	    char *errbuf;

	    asprintf (&errbuf,
		      "Read forwarded creds failed: %s",
		      krb5_get_err_text (context, ret));
	    if(errbuf == NULL)
		Data(ap, KRB_FORWARD_REJECT, NULL, 0);
	    else
		Data(ap, KRB_FORWARD_REJECT, errbuf, -1);
	    if (auth_debug_mode)
		printf("Could not read forwarded credentials: %s\r\n",
		       errbuf);
	    free (errbuf);
	} else
	    Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
	chown (ccname + 5, pwd->pw_uid, -1);
	if (auth_debug_mode)
	    printf("Forwarded credentials obtained\r\n");
	break;
    }
#endif	/* FORWARD */
    default:
	if (auth_debug_mode)
	    printf("Unknown Kerberos option %d\r\n", data[-1]);
	Data(ap, KRB_REJECT, 0, 0);
	break;
    }
}
Example #6
0
static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
                                               const char *realm_str,
                                               const char *princ_str,
                                               const char *keytab_name,
                                               const krb5_deltat lifetime,
                                               const char **ccname_out,
                                               time_t *expire_time_out)
{
    char *ccname;
    char *realm_name = NULL;
    char *full_princ = NULL;
    char *default_realm = NULL;
    char *tmp_str = NULL;
    krb5_context context = NULL;
    krb5_keytab keytab = NULL;
    krb5_ccache ccache = NULL;
    krb5_principal kprinc;
    krb5_creds my_creds;
    krb5_get_init_creds_opt options;
    krb5_error_code krberr;
    krb5_timestamp kdc_time_offset;
    int canonicalize = 0;
    int kdc_time_offset_usec;
    int ret;

    krberr = krb5_init_context(&context);
    if (krberr) {
        DEBUG(SSSDBG_OP_FAILURE, "Failed to init kerberos context\n");
        return krberr;
    }
    DEBUG(SSSDBG_TRACE_INTERNAL, "Kerberos context initialized\n");

    krberr = set_child_debugging(context);
    if (krberr != EOK) {
        DEBUG(SSSDBG_MINOR_FAILURE, "Cannot set krb5_child debugging\n");
    }

    if (!realm_str) {
        krberr = krb5_get_default_realm(context, &default_realm);
        if (krberr) {
            DEBUG(SSSDBG_OP_FAILURE, "Failed to get default realm name: %s\n",
                      sss_krb5_get_error_message(context, krberr));
            goto done;
        }

        realm_name = talloc_strdup(memctx, default_realm);
        krb5_free_default_realm(context, default_realm);
        if (!realm_name) {
            krberr = KRB5KRB_ERR_GENERIC;
            goto done;
        }
    } else {
        realm_name = talloc_strdup(memctx, realm_str);
        if (!realm_name) {
            krberr = KRB5KRB_ERR_GENERIC;
            goto done;
        }
    }

    DEBUG(SSSDBG_TRACE_INTERNAL, "got realm_name: [%s]\n", realm_name);

    if (princ_str) {
        if (!strchr(princ_str, '@')) {
            full_princ = talloc_asprintf(memctx, "%s@%s",
                                         princ_str, realm_name);
        } else {
            full_princ = talloc_strdup(memctx, princ_str);
        }
    } else {
        char hostname[HOST_NAME_MAX + 1];

        ret = gethostname(hostname, HOST_NAME_MAX);
        if (ret == -1) {
            krberr = KRB5KRB_ERR_GENERIC;
            goto done;
        }
        hostname[HOST_NAME_MAX] = '\0';

        DEBUG(SSSDBG_TRACE_LIBS, "got hostname: [%s]\n", hostname);

        ret = select_principal_from_keytab(memctx, hostname, realm_name,
                keytab_name, &full_princ, NULL, NULL);
        if (ret) {
            krberr = KRB5_KT_IOERR;
            goto done;
        }
    }
    if (!full_princ) {
        krberr = KRB5KRB_ERR_GENERIC;
        goto done;
    }
    DEBUG(SSSDBG_CONF_SETTINGS, "Principal name is: [%s]\n", full_princ);

    krberr = krb5_parse_name(context, full_princ, &kprinc);
    if (krberr) {
        DEBUG(SSSDBG_OP_FAILURE, "Unable to build principal: %s\n",
                  sss_krb5_get_error_message(context, krberr));
        goto done;
    }

    if (keytab_name) {
        krberr = krb5_kt_resolve(context, keytab_name, &keytab);
    } else {
        krberr = krb5_kt_default(context, &keytab);
    }
    DEBUG(SSSDBG_CONF_SETTINGS, "Using keytab [%s]\n", KEYTAB_CLEAN_NAME);
    if (krberr) {
        DEBUG(SSSDBG_FATAL_FAILURE,
              "Failed to read keytab file [%s]: %s\n",
               KEYTAB_CLEAN_NAME,
               sss_krb5_get_error_message(context, krberr));
        goto done;
    }

    /* Verify the keytab */
    ret = sss_krb5_verify_keytab_ex(full_princ, keytab_name, context, keytab);
    if (ret) {
        DEBUG(SSSDBG_OP_FAILURE,
                "Unable to verify principal is present in the keytab\n");
        krberr = KRB5_KT_IOERR;
        goto done;
    }

    ccname = talloc_asprintf(memctx, "FILE:%s/ccache_%s", DB_PATH, realm_name);
    if (!ccname) {
        krberr = KRB5KRB_ERR_GENERIC;
        goto done;
    }
    DEBUG(SSSDBG_TRACE_INTERNAL, "keytab ccname: [%s]\n", ccname);

    krberr = krb5_cc_resolve(context, ccname, &ccache);
    if (krberr) {
        DEBUG(SSSDBG_OP_FAILURE, "Failed to set cache name: %s\n",
                  sss_krb5_get_error_message(context, krberr));
        goto done;
    }

    memset(&my_creds, 0, sizeof(my_creds));
    memset(&options, 0, sizeof(options));

    krb5_get_init_creds_opt_set_address_list(&options, NULL);
    krb5_get_init_creds_opt_set_forwardable(&options, 0);
    krb5_get_init_creds_opt_set_proxiable(&options, 0);
    krb5_get_init_creds_opt_set_tkt_life(&options, lifetime);

    tmp_str = getenv("KRB5_CANONICALIZE");
    if (tmp_str != NULL && strcasecmp(tmp_str, "true") == 0) {
        DEBUG(SSSDBG_CONF_SETTINGS, "Will canonicalize principals\n");
        canonicalize = 1;
    }
    sss_krb5_get_init_creds_opt_set_canonicalize(&options, canonicalize);

    krberr = krb5_get_init_creds_keytab(context, &my_creds, kprinc,
                                        keytab, 0, NULL, &options);
    if (krberr) {
        DEBUG(SSSDBG_FATAL_FAILURE,
              "Failed to init credentials: %s\n",
               sss_krb5_get_error_message(context, krberr));
        sss_log(SSS_LOG_ERR,
                "Failed to initialize credentials using keytab [%s]: %s. "
                "Unable to create GSSAPI-encrypted LDAP connection.",
                KEYTAB_CLEAN_NAME,
                sss_krb5_get_error_message(context, krberr));
        goto done;
    }
    DEBUG(SSSDBG_TRACE_INTERNAL, "credentials initialized\n");

    /* Use updated principal if changed due to canonicalization. */
    krberr = krb5_cc_initialize(context, ccache, my_creds.client);
    if (krberr) {
        DEBUG(SSSDBG_OP_FAILURE, "Failed to init ccache: %s\n",
                  sss_krb5_get_error_message(context, krberr));
        goto done;
    }

    krberr = krb5_cc_store_cred(context, ccache, &my_creds);
    if (krberr) {
        DEBUG(SSSDBG_OP_FAILURE, "Failed to store creds: %s\n",
                  sss_krb5_get_error_message(context, krberr));
        goto done;
    }
    DEBUG(SSSDBG_TRACE_INTERNAL, "credentials stored\n");

#ifdef HAVE_KRB5_GET_TIME_OFFSETS
    krberr = krb5_get_time_offsets(context, &kdc_time_offset,
            &kdc_time_offset_usec);
    if (krberr) {
        DEBUG(SSSDBG_OP_FAILURE, "Failed to get KDC time offset: %s\n",
                  sss_krb5_get_error_message(context, krberr));
        kdc_time_offset = 0;
    } else {
        if (kdc_time_offset_usec > 0) {
            kdc_time_offset++;
        }
    }
    DEBUG(SSSDBG_TRACE_INTERNAL, "Got KDC time offset\n");
#else
    /* If we don't have this function, just assume no offset */
    kdc_time_offset = 0;
#endif

    krberr = 0;
    *ccname_out = ccname;
    *expire_time_out = my_creds.times.endtime - kdc_time_offset;

done:
    if (krberr != 0) KRB5_SYSLOG(krberr);
    if (keytab) krb5_kt_close(context, keytab);
    if (context) krb5_free_context(context);
    return krberr;
}
Example #7
0
static void do_v5_kvno (int count, char *names[],
                        char * ccache_name, char *etype_str, char *keytab_name,
			char *sname)
{
    krb5_error_code ret;
    krb5_context context = 0;
    int i, errors;
    krb5_enctype etype;
    krb5_ccache ccache;
    krb5_principal me;
    krb5_creds in_creds, *out_creds = NULL;
    Ticket ticket;
    size_t len;
    char *princ = NULL;
    krb5_keytab keytab = NULL;

    ret = krb5_init_context(&context);
    if (ret)
	errx(1, "krb5_init_context failed: %d", ret);

    if (etype_str) {
        ret = krb5_string_to_enctype(context, etype_str, &etype);
	if (ret)
	    krb5_err(context, 1, ret, "Failed to convert encryption type %s", etype_str);
    } else {
	etype = 0;
    }

    if (ccache_name)
        ret = krb5_cc_resolve(context, ccache_name, &ccache);
    else
        ret = krb5_cc_default(context, &ccache);
    if (ret)
        krb5_err(context, 1, ret, "Failed to open credentials cache %s",
                 (ccache_name) ? ccache_name : "(Default)");

    if (keytab_name) {
	ret = krb5_kt_resolve(context, keytab_name, &keytab);
	if (ret)
            krb5_err(context, 1, ret, "Can't resolve keytab %s", keytab_name);
    }

    ret = krb5_cc_get_principal(context, ccache, &me);
    if (ret)
        krb5_err(context, 1, ret, "krb5_cc_get_principal");

    errors = 0;

    for (i = 0; i < count; i++) {
	memset(&in_creds, 0, sizeof(in_creds));
        memset(&ticket, 0, sizeof(ticket));

	in_creds.client = me;

	if (sname != NULL) {
	    ret = krb5_sname_to_principal(context, names[i],
					  sname, KRB5_NT_SRV_HST,
					  &in_creds.server);
	} else {
	    ret = krb5_parse_name(context, names[i], &in_creds.server);
	}
	if (ret) {
	    if (!quiet_flag)
                krb5_warn(context, ret, "Couldn't parse principal name %s", names[i]);
            errors++;
	    continue;
	}

	ret = krb5_unparse_name(context, in_creds.server, &princ);
	if (ret) {
            krb5_warn(context, ret, "Couldn't format parsed principal name for '%s'",
                      names[i]);
	    errors++;
            goto next;
	}

	in_creds.session.keytype = etype;

	ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds);

	if (ret) {
            krb5_warn(context, ret, "Couldn't get credentials for %s", princ);
	    errors++;
	    goto next;
	}

	ret = decode_Ticket(out_creds->ticket.data, out_creds->ticket.length,
                            &ticket, &len);
	if (ret) {
	    krb5_err(context, 1, ret, "Can't decode ticket for %s", princ);
	    errors++;
            goto next;
	    continue;
	}

	if (keytab) {
            krb5_keytab_entry   kte;
            krb5_crypto         crypto;
            krb5_data           dec_data;
            EncTicketPart       decr_part;

            ret = krb5_kt_get_entry(context, keytab, in_creds.server,
                                    (ticket.enc_part.kvno != NULL)?
                                    *ticket.enc_part.kvno : 0,
                                    ticket.enc_part.etype,
                                    &kte);
            if (ret) {
                krb5_warn(context, ret, "Can't decrypt ticket for %s", princ);
                if (!quiet_flag)
                    printf("%s: kvno = %d, keytab entry invalid", princ,
                           (ticket.enc_part.kvno != NULL)?
                           *ticket.enc_part.kvno : 0);
                errors ++;
                goto next;
            }

            ret = krb5_crypto_init(context, &kte.keyblock, 0, &crypto);
            if (ret) {
                krb5_warn(context, ret, "krb5_crypto_init");
                errors ++;
                krb5_kt_free_entry(context, &kte);
                goto next;
            }

            ret = krb5_decrypt_EncryptedData (context, crypto, KRB5_KU_TICKET,
                                              &ticket.enc_part, &dec_data);
            krb5_crypto_destroy(context, crypto);
            krb5_kt_free_entry(context, &kte);

            if (ret) {
                krb5_warn(context, ret, "krb5_decrypt_EncryptedData");
                errors ++;
                goto next;
            }

            ret = decode_EncTicketPart(dec_data.data, dec_data.length,
                                       &decr_part, &len);
            krb5_data_free(&dec_data);
            if (ret) {
                krb5_warn(context, ret, "decode_EncTicketPart");
                errors ++;
                goto next;
            }

            if (!quiet_flag)
		printf("%s: kvno = %d, keytab entry valid\n", princ,
                       (ticket.enc_part.kvno != NULL)?
                       *ticket.enc_part.kvno : 0);

            free_EncTicketPart(&decr_part);
	} else {
	    if (!quiet_flag)
		printf("%s: kvno = %d\n", princ,
                       (ticket.enc_part.kvno != NULL)? *ticket.enc_part.kvno : 0);
	}

    next:
        if (out_creds) {
            krb5_free_creds(context, out_creds);
            out_creds = NULL;
        }

        if (princ) {
            krb5_free_unparsed_name(context, princ);
            princ = NULL;
        }

	krb5_free_principal(context, in_creds.server);

        free_Ticket(&ticket);
    }

    if (keytab)
	krb5_kt_close(context, keytab);
    krb5_free_principal(context, me);
    krb5_cc_close(context, ccache);
    krb5_free_context(context);

    if (errors)
	exit(1);

    exit(0);
}
Example #8
0
File: kinit.c Project: lha/heimdal
int
main (int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache  ccache;
    krb5_principal principal;
    int optidx = 0;
    krb5_deltat ticket_life = 0;
    int parseflags = 0;

    setprogname (argv[0]);

    setlocale (LC_ALL, "");
    bindtextdomain ("heimdal_kuser", HEIMDAL_LOCALEDIR);
    textdomain("heimdal_kuser");

    ret = krb5_init_context (&context);
    if (ret == KRB5_CONFIG_BADFORMAT)
	errx (1, "krb5_init_context failed to parse configuration file");
    else if (ret)
	errx(1, "krb5_init_context failed: %d", ret);

    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
	usage(1);

    if (help_flag)
	usage (0);

    if(version_flag) {
	print_version(NULL);
	exit(0);
    }

    argc -= optidx;
    argv += optidx;

    if (canonicalize_flag || enterprise_flag)
	parseflags |= KRB5_PRINCIPAL_PARSE_ENTERPRISE;

    if (pk_enterprise_flag) {
	ret = krb5_pk_enterprise_cert(context, pk_user_id,
				      argv[0], &principal,
				      &ent_user_id);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_pk_enterprise_certs");

	pk_user_id = NULL;

    } else if (anonymous_flag) {

	ret = krb5_make_principal(context, &principal, argv[0],
				  KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME,
				  NULL);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_make_principal");
	krb5_principal_set_type(context, principal, KRB5_NT_WELLKNOWN);

    } else {
	if (argv[0]) {
	    ret = krb5_parse_name_flags (context, argv[0], parseflags,
					 &principal);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_parse_name");
	} else {
	    ret = krb5_get_default_principal (context, &principal);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_get_default_principal");
	}
    }

    if(fcache_version)
	krb5_set_fcache_version(context, fcache_version);

    if(renewable_flag == -1)
	/* this seems somewhat pointless, but whatever */
	krb5_appdefault_boolean(context, "kinit",
				krb5_principal_get_realm(context, principal),
				"renewable", FALSE, &renewable_flag);
    if(do_afslog == -1)
	krb5_appdefault_boolean(context, "kinit",
				krb5_principal_get_realm(context, principal),
				"afslog", TRUE, &do_afslog);

    if(cred_cache)
	ret = krb5_cc_resolve(context, cred_cache, &ccache);
    else {
	if(argc > 1) {
	    char s[1024];
	    ret = krb5_cc_new_unique(context, NULL, NULL, &ccache);
	    if(ret)
		krb5_err(context, 1, ret, "creating cred cache");
	    snprintf(s, sizeof(s), "%s:%s",
		     krb5_cc_get_type(context, ccache),
		     krb5_cc_get_name(context, ccache));
	    setenv("KRB5CCNAME", s, 1);
	} else {
	    ret = krb5_cc_cache_match(context, principal, &ccache);
	    if (ret) {
		const char *type;
		ret = krb5_cc_default (context, &ccache);
		if (ret)
		    krb5_err (context, 1, ret, N_("resolving credentials cache", ""));

		/*
		 * Check if the type support switching, and we do,
		 * then do that instead over overwriting the current
		 * default credential
		 */
		type = krb5_cc_get_type(context, ccache);
		if (krb5_cc_support_switch(context, type)) {
		    krb5_cc_close(context, ccache);
		    ret = krb5_cc_new_unique(context, type, NULL, &ccache);
		}
	    }
	}
    }
    if (ret)
	krb5_err (context, 1, ret, N_("resolving credentials cache", ""));

#ifndef NO_AFS
    if(argc > 1 && k_hasafs ())
	k_setpag();
#endif

    if (lifetime) {
	int tmp = parse_time (lifetime, "s");
	if (tmp < 0)
	    errx (1, N_("unparsable time: %s", ""), lifetime);

	ticket_life = tmp;
    }

    if(addrs_flag == 0 && extra_addresses.num_strings > 0)
	krb5_errx(context, 1,
		  N_("specifying both extra addresses and "
		     "no addresses makes no sense", ""));
    {
	int i;
	krb5_addresses addresses;
	memset(&addresses, 0, sizeof(addresses));
	for(i = 0; i < extra_addresses.num_strings; i++) {
	    ret = krb5_parse_address(context, extra_addresses.strings[i],
				     &addresses);
	    if (ret == 0) {
		krb5_add_extra_addresses(context, &addresses);
		krb5_free_addresses(context, &addresses);
	    }
	}
	free_getarg_strings(&extra_addresses);
    }

    if(renew_flag || validate_flag) {
	ret = renew_validate(context, renew_flag, validate_flag,
			     ccache, server_str, ticket_life);
	exit(ret != 0);
    }

    get_new_tickets(context, principal, ccache, ticket_life, 1);

#ifndef NO_AFS
    if(do_afslog && k_hasafs())
	krb5_afslog(context, ccache, NULL, NULL);
#endif
    if(argc > 1) {
	struct renew_ctx ctx;
	time_t timeout;

	timeout = ticket_lifetime(context, ccache, principal, server_str) / 2;

	ctx.context = context;
	ctx.ccache = ccache;
	ctx.principal = principal;
	ctx.ticket_life = ticket_life;

	ret = simple_execvp_timed(argv[1], argv+1,
				  renew_func, &ctx, timeout);
#define EX_NOEXEC	126
#define EX_NOTFOUND	127
	if(ret == EX_NOEXEC)
	    krb5_warnx(context, N_("permission denied: %s", ""), argv[1]);
	else if(ret == EX_NOTFOUND)
	    krb5_warnx(context, N_("command not found: %s", ""), argv[1]);

	krb5_cc_destroy(context, ccache);
#ifndef NO_AFS
	if(k_hasafs())
	    k_unlog();
#endif
    } else {
	krb5_cc_close (context, ccache);
	ret = 0;
    }
    krb5_free_principal(context, principal);
    krb5_free_context (context);
    return ret;
}
Example #9
0
static krb5_error_code
get_ccache(krb5_context context, int *destroy, krb5_ccache *id)
{
    krb5_principal principal = NULL;
    krb5_error_code ret;
    krb5_keytab kt = NULL;

    *id = NULL;

    if (!issuid()) {
	const char *cache;

	cache = getenv("NTLM_ACCEPTOR_CCACHE");
	if (cache) {
	    ret = krb5_cc_resolve(context, cache, id);
	    if (ret)
		goto out;
	    return 0;
	}
    }

    ret = krb5_sname_to_principal(context, NULL, "host",
				  KRB5_NT_SRV_HST, &principal);
    if (ret)
	goto out;

    ret = krb5_cc_cache_match(context, principal, id);
    if (ret == 0)
	return 0;

    /* did not find in default credcache, lets try default keytab */
    ret = krb5_kt_default(context, &kt);
    if (ret)
	goto out;

    /* XXX check in keytab */
    {
	krb5_get_init_creds_opt *opt;
	krb5_creds cred;

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

	ret = krb5_cc_new_unique(context, "MEMORY", NULL, id);
	if (ret)
	    goto out;
	*destroy = 1;
	ret = krb5_get_init_creds_opt_alloc(context, &opt);
	if (ret)
	    goto out;
	ret = krb5_get_init_creds_keytab (context,
					  &cred,
					  principal,
					  kt,
					  0,
					  NULL,
					  opt);
	krb5_get_init_creds_opt_free(context, opt);
	if (ret)
	    goto out;
	ret = krb5_cc_initialize (context, *id, cred.client);
	if (ret) {
	    krb5_free_cred_contents (context, &cred);
	    goto out;
	}
	ret = krb5_cc_store_cred (context, *id, &cred);
	krb5_free_cred_contents (context, &cred);
	if (ret)
	    goto out;
    }

    krb5_kt_close(context, kt);

    return 0;

out:
    if (*id) {
	if (*destroy)
	    krb5_cc_destroy(context, *id);
	else
	    krb5_cc_close(context, *id);
	*id = NULL;
    }

    if (kt)
	krb5_kt_close(context, kt);

    if (principal)
	krb5_free_principal(context, principal);
    return ret;
}
Example #10
0
/*
 * Obtain credentials via a key in the keytab given
 * a keytab handle and a gssd_k5_kt_princ structure.
 * Checks to see if current credentials are expired,
 * if not, uses the keytab to obtain new credentials.
 *
 * Returns:
 *	0 => success (or credentials have not expired)
 *	nonzero => error
 */
static int gssd_get_single_krb5_cred(krb5_context context, krb5_keytab kt,
				     struct gssd_k5_kt_princ *ple, int nocache)
{
#if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
	krb5_get_init_creds_opt *init_opts = NULL;
#else
	krb5_get_init_creds_opt options;
#endif
	krb5_get_init_creds_opt *opts;
	krb5_creds my_creds;
	krb5_ccache ccache = NULL;
	char kt_name[BUFSIZ];
	char cc_name[BUFSIZ];
	int code;
	time_t now = time(0);
	char *cache_type;
	char *pname = NULL;
	char *k5err = NULL;

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

	if (ple->ccname && ple->endtime > now && !nocache) {
		printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
			 ple->ccname, ple->endtime);
		code = 0;
		goto out;
	}

	code = krb5_kt_get_name(context, kt, kt_name, BUFSIZ);
	if (code != 0) {
		printerr(0,
			 "ERROR: Unable to get keytab name in "
			 "gssd_get_single_krb5_cred\n");
		goto out;
	}

	if ((krb5_unparse_name(context, ple->princ, &pname)))
		pname = NULL;

#if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
	code = krb5_get_init_creds_opt_alloc(context, &init_opts);
	if (code) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0, "ERROR: %s allocating gic options\n", k5err);
		goto out;
	}
	if (krb5_get_init_creds_opt_set_addressless(context, init_opts, 1))
		printerr(1,
			 "WARNING: Unable to set option for addressless "
			 "tickets.  May have problems behind a NAT.\n");
#ifdef TEST_SHORT_LIFETIME
	/* set a short lifetime (for debugging only!) */
	printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
	krb5_get_init_creds_opt_set_tkt_life(init_opts, 5 * 60);
#endif
	opts = init_opts;

#else /* HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS */

	krb5_get_init_creds_opt_init(&options);
	krb5_get_init_creds_opt_set_address_list(&options, NULL);
#ifdef TEST_SHORT_LIFETIME
	/* set a short lifetime (for debugging only!) */
	printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n");
	krb5_get_init_creds_opt_set_tkt_life(&options, 5 * 60);
#endif
	opts = &options;
#endif

	code = krb5_get_init_creds_keytab(context, &my_creds,
					  ple->princ, kt, 0,
					  NULL, opts);
	if (code != 0) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(1,
			 "WARNING: %s while getting initial ticket for "
			 "principal '%s' using keytab '%s'\n", k5err,
			 pname ? pname : "<unparsable>", kt_name);
		goto out;
	}

	/*
	 * Initialize cache file which we're going to be using
	 */

	if (use_memcache)
		cache_type = "MEMORY";
	else
		cache_type = "FILE";
	snprintf(cc_name, sizeof(cc_name), "%s:%s/%s%s_%s", cache_type,
		 ccachesearch[0], GSSD_DEFAULT_CRED_PREFIX,
		 GSSD_DEFAULT_MACHINE_CRED_SUFFIX, ple->realm);
	ple->endtime = my_creds.times.endtime;
	if (ple->ccname != NULL)
		gsh_free(ple->ccname);
	ple->ccname = gsh_strdup(cc_name);
	if (ple->ccname == NULL) {
		printerr(0,
			 "ERROR: no storage to duplicate credentials "
			 "cache name '%s'\n", cc_name);
		code = ENOMEM;
		goto out;
	}
	code = krb5_cc_resolve(context, cc_name, &ccache);
	if (code != 0) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0, "ERROR: %s while opening credential cache '%s'\n",
			 k5err, cc_name);
		goto out;
	}
	code = krb5_cc_initialize(context, ccache, ple->princ);
	if (code != 0) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0,
			 "ERROR: %s while initializing credential "
			 "cache '%s'\n", k5err, cc_name);
	}
	code = krb5_cc_store_cred(context, ccache, &my_creds);
	if (code != 0) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0, "ERROR: %s while storing credentials in '%s'\n",
			 k5err, cc_name);
		goto out;
	}
	/* if we get this far, let gss mech know */
	gssd_set_krb5_ccache_name(cc_name);
	code = 0;
	printerr(2,
		 "Successfully obtained machine credentials for "
		 "principal '%s' stored in ccache '%s'\n", pname, cc_name);
 out:
#if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
	if (init_opts)
		krb5_get_init_creds_opt_free(context, init_opts);
#endif
	if (pname)
		k5_free_unparsed_name(context, pname);
	if (ccache)
		krb5_cc_close(context, ccache);
	krb5_free_cred_contents(context, &my_creds);
	gsh_free(k5err);
	return code;
}
Example #11
0
File: kinit.c Project: lha/heimdal
static krb5_error_code
get_new_tickets(krb5_context context,
		krb5_principal principal,
		krb5_ccache ccache,
		krb5_deltat ticket_life,
		int interactive)
{
    krb5_error_code ret;
    krb5_get_init_creds_opt *opt;
    krb5_creds cred;
    char passwd[256];
    krb5_deltat start_time = 0;
    krb5_deltat renew = 0;
    const char *renewstr = NULL;
    krb5_enctype *enctype = NULL;
    krb5_ccache tempccache;
    krb5_keytab kt = NULL;
    krb5_init_creds_context ctx;
#ifndef NO_NTLM
    struct ntlm_buf ntlmkey;
    memset(&ntlmkey, 0, sizeof(ntlmkey));
#endif
    passwd[0] = '\0';

    if (password_file) {
	FILE *f;

	if (strcasecmp("STDIN", password_file) == 0)
	    f = stdin;
	else
	    f = fopen(password_file, "r");
	if (f == NULL)
	    krb5_errx(context, 1, "Failed to open the password file %s",
		      password_file);

	if (fgets(passwd, sizeof(passwd), f) == NULL)
	    krb5_errx(context, 1,
		      N_("Failed to read password from file %s", ""),
		      password_file);
	if (f != stdin)
	    fclose(f);
	passwd[strcspn(passwd, "\n")] = '\0';
    }

#ifdef __APPLE__
    if (passwd[0] == '\0') {
	const char *realm;
	OSStatus osret;
	UInt32 length;
	void *buffer;
	char *name;

	realm = krb5_principal_get_realm(context, principal);

	ret = krb5_unparse_name_flags(context, principal,
				      KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name);
	if (ret)
	    goto nopassword;

	osret = SecKeychainFindGenericPassword(NULL, strlen(realm), realm,
					       strlen(name), name,
					       &length, &buffer, NULL);
	free(name);
	if (osret == noErr && length < sizeof(passwd) - 1) {
	    memcpy(passwd, buffer, length);
	    passwd[length] = '\0';
	}
    nopassword:
	do { } while(0);
    }
#endif

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

    ret = krb5_get_init_creds_opt_alloc (context, &opt);
    if (ret)
	krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");

    krb5_get_init_creds_opt_set_default_flags(context, "kinit",
	krb5_principal_get_realm(context, principal), opt);

    if(forwardable_flag != -1)
	krb5_get_init_creds_opt_set_forwardable (opt, forwardable_flag);
    if(proxiable_flag != -1)
	krb5_get_init_creds_opt_set_proxiable (opt, proxiable_flag);
    if(anonymous_flag)
	krb5_get_init_creds_opt_set_anonymous (opt, anonymous_flag);
    if (pac_flag != -1)
	krb5_get_init_creds_opt_set_pac_request(context, opt,
						pac_flag ? TRUE : FALSE);
    if (canonicalize_flag)
	krb5_get_init_creds_opt_set_canonicalize(context, opt, TRUE);
    if (pk_enterprise_flag || enterprise_flag || canonicalize_flag || windows_flag)
	krb5_get_init_creds_opt_set_win2k(context, opt, TRUE);
    if (pk_user_id || ent_user_id || anonymous_flag) {
	ret = krb5_get_init_creds_opt_set_pkinit(context, opt,
						 principal,
						 pk_user_id,
						 pk_x509_anchors,
						 NULL,
						 NULL,
						 pk_use_enckey ? 2 : 0 |
						 anonymous_flag ? 4 : 0,
						 krb5_prompter_posix,
						 NULL,
						 passwd);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_get_init_creds_opt_set_pkinit");
	if (ent_user_id)
	    krb5_get_init_creds_opt_set_pkinit_user_certs(context, opt, ent_user_id);
    }

    if (addrs_flag != -1)
	krb5_get_init_creds_opt_set_addressless(context, opt,
						addrs_flag ? FALSE : TRUE);

    if (renew_life == NULL && renewable_flag)
	renewstr = "1 month";
    if (renew_life)
	renewstr = renew_life;
    if (renewstr) {
	renew = parse_time (renewstr, "s");
	if (renew < 0)
	    errx (1, "unparsable time: %s", renewstr);

	krb5_get_init_creds_opt_set_renew_life (opt, renew);
    }

    if(ticket_life != 0)
	krb5_get_init_creds_opt_set_tkt_life (opt, ticket_life);

    if(start_str) {
	int tmp = parse_time (start_str, "s");
	if (tmp < 0)
	    errx (1, N_("unparsable time: %s", ""), start_str);

	start_time = tmp;
    }

    if(etype_str.num_strings) {
	int i;

	enctype = malloc(etype_str.num_strings * sizeof(*enctype));
	if(enctype == NULL)
	    errx(1, "out of memory");
	for(i = 0; i < etype_str.num_strings; i++) {
	    ret = krb5_string_to_enctype(context,
					 etype_str.strings[i],
					 &enctype[i]);
	    if(ret)
		errx(1, "unrecognized enctype: %s", etype_str.strings[i]);
	}
	krb5_get_init_creds_opt_set_etype_list(opt, enctype,
					       etype_str.num_strings);
    }

    ret = krb5_init_creds_init(context, principal, krb5_prompter_posix, NULL, start_time, opt, &ctx);
    if (ret)
	krb5_err(context, 1, ret, "krb5_init_creds_init");

    if (server_str) {
	ret = krb5_init_creds_set_service(context, ctx, server_str);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_init_creds_set_service");
    }

    if (fast_armor_cache_string) {
	krb5_ccache fastid;
	
	ret = krb5_cc_resolve(context, fast_armor_cache_string, &fastid);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_cc_resolve(FAST cache)");
	
	ret = krb5_init_creds_set_fast_ccache(context, ctx, fastid);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_init_creds_set_fast_ccache");
    }

    if(use_keytab || keytab_str) {

	if(keytab_str)
	    ret = krb5_kt_resolve(context, keytab_str, &kt);
	else
	    ret = krb5_kt_default(context, &kt);
	if (ret)
	    krb5_err(context, 1, ret, "resolving keytab");

	ret = krb5_init_creds_set_keytab(context, ctx, kt);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_init_creds_set_keytab");

    } else if (pk_user_id || ent_user_id || anonymous_flag) {

    } else if (!interactive) {
	krb5_warnx(context, "Not interactive, failed to get initial ticket");
	krb5_get_init_creds_opt_free(context, opt);
	return 0;
    } else {

	if (passwd[0] == '\0') {
	    char *p, *prompt;

	    krb5_unparse_name (context, principal, &p);
	    asprintf (&prompt, N_("%s's Password: "******""), p);
	    free (p);

	    if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){
		memset(passwd, 0, sizeof(passwd));
		errx(1, "failed to read password");
	    }
	    free (prompt);
	}

	if (passwd[0]) {
	    ret = krb5_init_creds_set_password(context, ctx, passwd);
	    if (ret)
		krb5_err(context, 1, ret, "krb5_init_creds_set_password");
	}
    }

    ret = krb5_init_creds_get(context, ctx);

#ifndef NO_NTLM
    if (ntlm_domain && passwd[0])
	heim_ntlm_nt_key(passwd, &ntlmkey);
#endif
    memset(passwd, 0, sizeof(passwd));

    switch(ret){
    case 0:
	break;
    case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */
	exit(1);
    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
    case KRB5KRB_AP_ERR_MODIFIED:
    case KRB5KDC_ERR_PREAUTH_FAILED:
	krb5_errx(context, 1, N_("Password incorrect", ""));
	break;
    case KRB5KRB_AP_ERR_V4_REPLY:
	krb5_errx(context, 1, N_("Looks like a Kerberos 4 reply", ""));
	break;
    default:
	krb5_err(context, 1, ret, "krb5_get_init_creds");
    }

    krb5_process_last_request(context, opt, ctx);

    if(ticket_life != 0) {
	if(abs(cred.times.endtime - cred.times.starttime - ticket_life) > 30) {
	    char life[64];
	    unparse_time_approx(cred.times.endtime - cred.times.starttime,
				life, sizeof(life));
	    krb5_warnx(context, N_("NOTICE: ticket lifetime is %s", ""), life);
	}
    }
    if(renew_life) {
	if(abs(cred.times.renew_till - cred.times.starttime - renew) > 30) {
	    char life[64];
	    unparse_time_approx(cred.times.renew_till - cred.times.starttime,
				life, sizeof(life));
	    krb5_warnx(context,
		       N_("NOTICE: ticket renewable lifetime is %s", ""),
		       life);
	}
    }

    ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, ccache),
			     NULL, &tempccache);
    if (ret)
	krb5_err (context, 1, ret, "krb5_cc_new_unique");

    ret = krb5_init_creds_store(context, ctx, tempccache);
    if (ret)
	krb5_err(context, 1, ret, "krb5_init_creds_store");

    krb5_init_creds_free(context, ctx);

    ret = krb5_cc_move(context, tempccache, ccache);
    if (ret)
	krb5_err (context, 1, ret, "krb5_cc_move");

    if (switch_cache_flags)
	krb5_cc_switch(context, ccache);

#ifndef NO_NTLM
    if (ntlm_domain && ntlmkey.data)
	store_ntlmkey(context, ccache, ntlm_domain, &ntlmkey);
#endif

    if (ok_as_delegate_flag || windows_flag || use_referrals_flag) {
	unsigned char d = 0;
	krb5_data data;

	if (ok_as_delegate_flag || windows_flag)
	    d |= 1;
	if (use_referrals_flag || windows_flag)
	    d |= 2;

	data.length = 1;
	data.data = &d;

	krb5_cc_set_config(context, ccache, NULL, "realm-config", &data);
    }

    krb5_get_init_creds_opt_free(context, opt);

    if (kt)			
	krb5_kt_close(context, kt);
    if (enctype)
	free(enctype);

    return 0;
}
Example #12
0
static int
create_krb5_tickets (krb5_context context, krb5_keytab kt)
{
    krb5_error_code ret;
    krb5_keytab_entry entry;
    krb5_creds cred;
    krb5_enctype etype;
    krb5_ccache ccache;

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

    ret = krb5_string_to_enctype (context, enc_type, &etype);
    if (ret)
	krb5_err (context, 1, ret, "krb5_string_to_enctype");
    ret = krb5_kt_get_entry (context, kt, server_principal,
			     0, etype, &entry);
    if (ret)
	krb5_err (context, 1, ret, "krb5_kt_get_entry");

    /*
     * setup cred
     */


    ret = krb5_copy_principal (context, client_principal, &cred.client);
    if (ret)
	krb5_err (context, 1, ret, "krb5_copy_principal");
    ret = krb5_copy_principal (context, server_principal, &cred.server);
    if (ret)
	krb5_err (context, 1, ret, "krb5_copy_principal");
    krb5_generate_random_keyblock(context, etype, &cred.session);

    cred.times.authtime = time(NULL);
    cred.times.starttime = time(NULL);
    cred.times.endtime = time(NULL) + expiration_time;
    cred.times.renew_till = 0;
    krb5_data_zero(&cred.second_ticket);

    ret = krb5_get_all_client_addrs (context, &cred.addresses);
    if (ret)
	krb5_err (context, 1, ret, "krb5_get_all_client_addrs");
    cred.flags.b = ticket_flags;


    /*
     * Encode encrypted part of ticket
     */

    encode_ticket (context, &entry.keyblock, etype, entry.vno, &cred);

    /*
     * Write to cc
     */

    if (ccache_str) {
	ret = krb5_cc_resolve(context, ccache_str, &ccache);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_resolve");
    } else {
	ret = krb5_cc_default (context, &ccache);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_default");
    }

    ret = krb5_cc_initialize (context, ccache, cred.client);
    if (ret)
	krb5_err (context, 1, ret, "krb5_cc_initialize");

    ret = krb5_cc_store_cred (context, ccache, &cred);
    if (ret)
	krb5_err (context, 1, ret, "krb5_cc_store_cred");

    krb5_free_cred_contents (context, &cred);
    krb5_cc_close (context, ccache);

    return 0;
}
Example #13
0
OM_uint32 GSSAPI_CALLCONV _gsskrb5_add_cred (
     OM_uint32           *minor_status,
     gss_const_cred_id_t input_cred_handle,
     gss_const_name_t    desired_name,
     const gss_OID       desired_mech,
     gss_cred_usage_t    cred_usage,
     OM_uint32           initiator_time_req,
     OM_uint32           acceptor_time_req,
     gss_cred_id_t       *output_cred_handle,
     gss_OID_set         *actual_mechs,
     OM_uint32           *initiator_time_rec,
     OM_uint32           *acceptor_time_rec)
{
    krb5_context context;
    OM_uint32 ret, lifetime;
    gsskrb5_cred cred, handle;
    krb5_const_principal dname;

    handle = NULL;
    cred = (gsskrb5_cred)input_cred_handle;
    dname = (krb5_const_principal)desired_name;

    GSSAPI_KRB5_INIT (&context);

    if (gss_oid_equal(desired_mech, GSS_KRB5_MECHANISM) == 0) {
	*minor_status = 0;
	return GSS_S_BAD_MECH;
    }

    if (cred == NULL && output_cred_handle == NULL) {
	*minor_status = 0;
	return GSS_S_NO_CRED;
    }

    if (cred == NULL) { /* XXX standard conformance failure */
	*minor_status = 0;
	return GSS_S_NO_CRED;
    }

    /* check if requested output usage is compatible with output usage */
    if (output_cred_handle != NULL) {
	HEIMDAL_MUTEX_lock(&cred->cred_id_mutex);
	if (cred->usage != cred_usage && cred->usage != GSS_C_BOTH) {
	    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
	    *minor_status = GSS_KRB5_S_G_BAD_USAGE;
	    return(GSS_S_FAILURE);
	}
    }

    /* check that we have the same name */
    if (dname != NULL &&
	krb5_principal_compare(context, dname,
			       cred->principal) != FALSE) {
	if (output_cred_handle)
	    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
	*minor_status = 0;
	return GSS_S_BAD_NAME;
    }

    /* make a copy */
    if (output_cred_handle) {
	krb5_error_code kret;

	handle = calloc(1, sizeof(*handle));
	if (handle == NULL) {
	    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
	    *minor_status = ENOMEM;
	    return (GSS_S_FAILURE);
	}

	handle->usage = cred_usage;
	handle->lifetime = cred->lifetime;
	handle->principal = NULL;
	handle->keytab = NULL;
	handle->ccache = NULL;
	handle->mechanisms = NULL;
	HEIMDAL_MUTEX_init(&handle->cred_id_mutex);

	ret = GSS_S_FAILURE;

	kret = krb5_copy_principal(context, cred->principal,
				  &handle->principal);
	if (kret) {
	    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
	    free(handle);
	    *minor_status = kret;
	    return GSS_S_FAILURE;
	}

	if (cred->keytab) {
	    char *name = NULL;

	    ret = GSS_S_FAILURE;

	    kret = krb5_kt_get_full_name(context, cred->keytab, &name);
	    if (kret) {
		*minor_status = kret;
		goto failure;
	    }

	    kret = krb5_kt_resolve(context, name,
				   &handle->keytab);
	    krb5_xfree(name);
	    if (kret){
		*minor_status = kret;
		goto failure;
	    }
	}

	if (cred->ccache) {
	    const char *type, *name;
	    char *type_name = NULL;

	    ret = GSS_S_FAILURE;

	    type = krb5_cc_get_type(context, cred->ccache);
	    if (type == NULL){
		*minor_status = ENOMEM;
		goto failure;
	    }

	    if (strcmp(type, "MEMORY") == 0) {
		ret = krb5_cc_new_unique(context, type,
					 NULL, &handle->ccache);
		if (ret) {
		    *minor_status = ret;
		    goto failure;
		}

		ret = krb5_cc_copy_cache(context, cred->ccache,
					 handle->ccache);
		if (ret) {
		    *minor_status = ret;
		    goto failure;
		}

	    } else {
		name = krb5_cc_get_name(context, cred->ccache);
		if (name == NULL) {
		    *minor_status = ENOMEM;
		    goto failure;
		}

		kret = asprintf(&type_name, "%s:%s", type, name);
		if (kret < 0 || type_name == NULL) {
		    *minor_status = ENOMEM;
		    goto failure;
		}

		kret = krb5_cc_resolve(context, type_name,
				       &handle->ccache);
		free(type_name);
		if (kret) {
		    *minor_status = kret;
		    goto failure;
		}
	    }
	}
	ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
	if (ret)
	    goto failure;

	ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
				     &handle->mechanisms);
	if (ret)
	    goto failure;
    }

    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);

    ret = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)cred,
				NULL, &lifetime, NULL, actual_mechs);
    if (ret)
	goto failure;

    if (initiator_time_rec)
	*initiator_time_rec = lifetime;
    if (acceptor_time_rec)
	*acceptor_time_rec = lifetime;

    if (output_cred_handle) {
	*output_cred_handle = (gss_cred_id_t)handle;
    }

    *minor_status = 0;
    return ret;

 failure:

    if (handle) {
	if (handle->principal)
	    krb5_free_principal(context, handle->principal);
	if (handle->keytab)
	    krb5_kt_close(context, handle->keytab);
	if (handle->ccache)
	    krb5_cc_destroy(context, handle->ccache);
	if (handle->mechanisms)
	    gss_release_oid_set(NULL, &handle->mechanisms);
	free(handle);
    }
    if (output_cred_handle)
	HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
    return ret;
}
Example #14
0
krb5_error_code KRB5_CALLCONV
krb5_verify_init_creds(krb5_context context,
                       krb5_creds *creds,
                       krb5_principal server_arg,
                       krb5_keytab keytab_arg,
                       krb5_ccache *ccache_arg,
                       krb5_verify_init_creds_opt *options)
{
    krb5_error_code ret;
    krb5_principal server;
    krb5_keytab keytab;
    krb5_ccache ccache;
    krb5_keytab_entry kte;
    krb5_creds in_creds, *out_creds;
    krb5_auth_context authcon;
    krb5_data ap_req;

    /* KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN */

    server = NULL;
    keytab = NULL;
    ccache = NULL;
    out_creds = NULL;
    authcon = NULL;
    ap_req.data = NULL;

    if (keytab_arg) {
        keytab = keytab_arg;
    } else {
        if ((ret = krb5_kt_default(context, &keytab)))
            goto cleanup;
    }

    if (server_arg) {
        ret = krb5_copy_principal(context, server_arg, &server);
        if (ret)
            goto cleanup;
    } else {
        /* Use a principal name from the keytab. */
        ret = k5_kt_get_principal(context, keytab, &server);
        if (ret) {
            /* There's no keytab, or it's empty, or we can't read it.
             * Allow this unless configuration demands verification. */
            if (!nofail(context, options, creds))
                ret = 0;
            goto cleanup;
        }
    }

    /* first, check if the server is in the keytab.  If not, there's
       no reason to continue.  rd_req does all this, but there's
       no way to know that a given error is caused by a missing
       keytab or key, and not by some other problem. */

    if (krb5_is_referral_realm(&server->realm)) {
        krb5_free_data_contents(context, &server->realm);
        ret = krb5_get_default_realm(context, &server->realm.data);
        if (ret) goto cleanup;
        server->realm.length = strlen(server->realm.data);
    }

    if ((ret = krb5_kt_get_entry(context, keytab, server, 0, 0, &kte))) {
        /* this means there is no keying material.  This is ok, as long as
           it is not prohibited by the configuration */
        if (!nofail(context, options, creds))
            ret = 0;
        goto cleanup;
    }

    krb5_kt_free_entry(context, &kte);

    /* If the creds are for the server principal, we're set, just do a mk_req.
     * Otherwise, do a get_credentials first.
     */

    if (krb5_principal_compare(context, server, creds->server)) {
        /* make an ap_req */
        if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, creds,
                                        &ap_req)))
            goto cleanup;
    } else {
        /* this is unclean, but it's the easiest way without ripping the
           library into very small pieces.  store the client's initial cred
           in a memory ccache, then call the library.  Later, we'll copy
           everything except the initial cred into the ccache we return to
           the user.  A clean implementation would involve library
           internals with a coherent idea of "in" and "out". */

        /* insert the initial cred into the ccache */

        if ((ret = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache))) {
            ccache = NULL;
            goto cleanup;
        }

        if ((ret = krb5_cc_initialize(context, ccache, creds->client)))
            goto cleanup;

        if ((ret = krb5_cc_store_cred(context, ccache, creds)))
            goto cleanup;

        /* set up for get_creds */
        memset(&in_creds, 0, sizeof(in_creds));
        in_creds.client = creds->client;
        in_creds.server = server;
        if ((ret = krb5_timeofday(context, &in_creds.times.endtime)))
            goto cleanup;
        in_creds.times.endtime += 5*60;

        if ((ret = krb5_get_credentials(context, 0, ccache, &in_creds,
                                        &out_creds)))
            goto cleanup;

        /* make an ap_req */
        if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, out_creds,
                                        &ap_req)))
            goto cleanup;
    }

    /* wipe the auth context for mk_req */
    if (authcon) {
        krb5_auth_con_free(context, authcon);
        authcon = NULL;
    }

    /* verify the ap_req */

    if ((ret = krb5_rd_req(context, &authcon, &ap_req, server, keytab,
                           NULL, NULL)))
        goto cleanup;

    /* if we get this far, then the verification succeeded.  We can
       still fail if the library stuff here fails, but that's it */

    if (ccache_arg && ccache) {
        if (*ccache_arg == NULL) {
            krb5_ccache retcc;

            retcc = NULL;

            if ((ret = krb5_cc_resolve(context, "MEMORY:rd_req2", &retcc)) ||
                (ret = krb5_cc_initialize(context, retcc, creds->client)) ||
                (ret = copy_creds_except(context, ccache, retcc,
                                         creds->server))) {
                if (retcc)
                    krb5_cc_destroy(context, retcc);
            } else {
                *ccache_arg = retcc;
            }
        } else {
            ret = copy_creds_except(context, ccache, *ccache_arg,
                                    server);
        }
    }

    /* if any of the above paths returned an errors, then ret is set accordingly.
     * Either that, or it's zero, which is fine, too
     */

cleanup:
    if ( server)
        krb5_free_principal(context, server);
    if (!keytab_arg && keytab)
        krb5_kt_close(context, keytab);
    if (ccache)
        krb5_cc_destroy(context, ccache);
    if (out_creds)
        krb5_free_creds(context, out_creds);
    if (authcon)
        krb5_auth_con_free(context, authcon);
    if (ap_req.data)
        free(ap_req.data);

    return(ret);
}
Example #15
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;
}
Example #16
0
static void
eval_kinit(heim_dict_t o)
{
    heim_string_t user, password, keytab, fast_armor_cc, pk_user_id, ccache;
    krb5_get_init_creds_opt *opt;
    krb5_init_creds_context ctx;
    krb5_principal client;
    krb5_keytab ktmem = NULL;
    krb5_ccache fast_cc = NULL;
    krb5_error_code ret;

    if (ptop)
	ptop->as_req++;

    user = heim_dict_get_value(o, HSTR("client"));
    if (user == NULL)
	krb5_errx(kdc_context, 1, "no client");

    password = heim_dict_get_value(o, HSTR("password"));
    keytab = heim_dict_get_value(o, HSTR("keytab"));
    pk_user_id = heim_dict_get_value(o, HSTR("pkinit-user-cert-id"));
    if (password == NULL && keytab == NULL && pk_user_id == NULL)
	krb5_errx(kdc_context, 1, "password, keytab, nor PKINIT user cert ID");

    ccache = heim_dict_get_value(o, HSTR("ccache"));

    ret = krb5_parse_name(kdc_context, heim_string_get_utf8(user), &client);
    if (ret)
	krb5_err(kdc_context, 1, ret, "krb5_unparse_name");

    /* PKINIT parts */
    ret = krb5_get_init_creds_opt_alloc (kdc_context, &opt);
    if (ret)
	krb5_err(kdc_context, 1, ret, "krb5_get_init_creds_opt_alloc");

    if (pk_user_id) {
	heim_bool_t rsaobj = heim_dict_get_value(o, HSTR("pkinit-use-rsa"));
	int use_rsa = rsaobj ? heim_bool_val(rsaobj) : 0;

	ret = krb5_get_init_creds_opt_set_pkinit(kdc_context, opt,
						 client,
						 heim_string_get_utf8(pk_user_id),
						 NULL, NULL, NULL,
						 use_rsa ? 2 : 0,
						 NULL, NULL, NULL);
	if (ret)
	    krb5_err(kdc_context, 1, ret, "krb5_get_init_creds_opt_set_pkinit");
    }

    ret = krb5_init_creds_init(kdc_context, client, NULL, NULL, 0, opt, &ctx);
    if (ret)
	krb5_err(kdc_context, 1, ret, "krb5_init_creds_init");

    fast_armor_cc = heim_dict_get_value(o, HSTR("fast-armor-cc"));
    if (fast_armor_cc) {

	ret = krb5_cc_resolve(kdc_context, heim_string_get_utf8(fast_armor_cc), &fast_cc);
	if (ret)
	    krb5_err(kdc_context, 1, ret, "krb5_cc_resolve");

	ret = krb5_init_creds_set_fast_ccache(kdc_context, ctx, fast_cc);
	if (ret)
	    krb5_err(kdc_context, 1, ret, "krb5_init_creds_set_fast_ccache");
    }
    
    if (password) {
	ret = krb5_init_creds_set_password(kdc_context, ctx, 
					   heim_string_get_utf8(password));
	if (ret)
	    krb5_err(kdc_context, 1, ret, "krb5_init_creds_set_password");
    }
    if (keytab) {
	krb5_keytab kt = NULL;

	ret = krb5_kt_resolve(kdc_context, heim_string_get_utf8(keytab), &kt);
	if (ret)
	    krb5_err(kdc_context, 1, ret, "krb5_kt_resolve");

	ret = krb5_kt_resolve(kdc_context, "MEMORY:keytab", &ktmem);
	if (ret)
	    krb5_err(kdc_context, 1, ret, "krb5_kt_resolve(MEMORY)");

	ret = copy_keytab(kdc_context, kt, ktmem);
	if (ret)
	    krb5_err(kdc_context, 1, ret, "copy_keytab");

	krb5_kt_close(kdc_context, kt);

	ret = krb5_init_creds_set_keytab(kdc_context, ctx, ktmem);
	if (ret)
	    krb5_err(kdc_context, 1, ret, "krb5_init_creds_set_keytab");
    }

    ret = krb5_init_creds_get(kdc_context, ctx);
    if (ret)
	krb5_err(kdc_context, 1, ret, "krb5_init_creds_get");

    if (ccache) {
	const char *name = heim_string_get_utf8(ccache);
	krb5_creds cred;
	krb5_ccache cc;

	ret = krb5_init_creds_get_creds(kdc_context, ctx, &cred);
	if (ret)
	    krb5_err(kdc_context, 1, ret, "krb5_init_creds_get_creds");

	ret = krb5_cc_resolve(kdc_context, name, &cc);
	if (ret)
	    krb5_err(kdc_context, 1, ret, "krb5_cc_resolve");

	krb5_init_creds_store(kdc_context, ctx, cc);

	ret = krb5_cc_close(kdc_context, cc);
	if (ret)
	    krb5_err(kdc_context, 1, ret, "krb5_cc_close");

	krb5_free_cred_contents(kdc_context, &cred);
    }

    krb5_init_creds_free(kdc_context, ctx);

    if (ktmem)
	krb5_kt_close(kdc_context, ktmem);
    if (fast_cc)
	krb5_cc_close(kdc_context, fast_cc);
}
Example #17
0
int
main (int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_principal principal;
    krb5_get_init_creds_opt *opt;
    krb5_ccache id = NULL;
    int exit_value;
    int optidx = 0;

    setprogname(argv[0]);

    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
	usage(1, args, sizeof(args) / sizeof(args[0]));
    if (help_flag)
	usage(0, args, sizeof(args) / sizeof(args[0]));
    if (version_flag) {
	print_version(NULL);
	return 0;
    }
    argc -= optidx;
    argv += optidx;

    ret = krb5_init_context (&context);
    if (ret)
	errx (1, "krb5_init_context failed: %d", ret);

    ret = krb5_get_init_creds_opt_alloc (context, &opt);
    if (ret)
	krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");

    krb5_get_init_creds_opt_set_tkt_life (opt, 300);
    krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
    krb5_get_init_creds_opt_set_proxiable (opt, FALSE);

    if (cred_cache_str) {
	ret = krb5_cc_resolve(context, cred_cache_str, &id);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_resolve");
    } else {
	ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_new_unique");
    }

    if (cred_cache_str == NULL) {
	krb5_principal admin_principal = NULL;
	krb5_creds cred;

	if (admin_principal_str) {
	    ret = krb5_parse_name (context, admin_principal_str,
				   &admin_principal);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_parse_name");
	} else if (argc == 1) {
	    ret = krb5_parse_name (context, argv[0], &admin_principal);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_parse_name");
	} else {
	    ret = krb5_get_default_principal (context, &admin_principal);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_get_default_principal");
	}

	ret = krb5_get_init_creds_password (context,
					    &cred,
					    admin_principal,
					    NULL,
					    krb5_prompter_posix,
					    NULL,
					    0,
					    "kadmin/changepw",
					    opt);
	switch (ret) {
	case 0:
	    break;
	case KRB5_LIBOS_PWDINTR :
	    return 1;
	case KRB5KRB_AP_ERR_BAD_INTEGRITY :
	case KRB5KRB_AP_ERR_MODIFIED :
	    krb5_errx(context, 1, "Password incorrect");
	    break;
	default:
	    krb5_err(context, 1, ret, "krb5_get_init_creds");
	}

	krb5_get_init_creds_opt_free(context, opt);

	ret = krb5_cc_initialize(context, id, admin_principal);
	krb5_free_principal(context, admin_principal);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_cc_initialize");

	ret = krb5_cc_store_cred(context, id, &cred);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_cc_store_cred");

	krb5_free_cred_contents (context, &cred);
    }

    if (argc == 0) {
	exit_value = change_password(context, NULL, id);
    } else {
	exit_value = 0;

	while (argc-- > 0) {

	    ret = krb5_parse_name (context, argv[0], &principal);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_parse_name");

	    ret = change_password(context, principal, id);
	    if (ret)
		exit_value = 1;
	    krb5_free_principal(context, principal);
	    argv++;
	}
    }

    if (cred_cache_str == NULL) {
	ret = krb5_cc_destroy(context, id);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_destroy");
    } else {
	ret = krb5_cc_close(context, id);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_close");
    }

    krb5_free_context (context);
    return exit_value;
}
Example #18
0
File: sasl.c Project: aixoss/samba
static ADS_STATUS ads_init_gssapi_cred(ADS_STRUCT *ads, gss_cred_id_t *cred)
{
	ADS_STATUS status;
	krb5_context kctx;
	krb5_error_code kerr;
	krb5_ccache kccache = NULL;
	uint32_t maj, min;

	*cred = GSS_C_NO_CREDENTIAL;

	if (!ads->auth.ccache_name) {
		return ADS_SUCCESS;
	}

	kerr = krb5_init_context(&kctx);
	if (kerr) {
		return ADS_ERROR_KRB5(kerr);
	}

#ifdef HAVE_GSS_KRB5_IMPORT_CRED
	kerr = krb5_cc_resolve(kctx, ads->auth.ccache_name, &kccache);
	if (kerr) {
		status = ADS_ERROR_KRB5(kerr);
		goto done;
	}

	maj = gss_krb5_import_cred(&min, kccache, NULL, NULL, cred);
	if (maj != GSS_S_COMPLETE) {
		status = ADS_ERROR_GSS(maj, min);
		goto done;
	}
#else
	/* We need to fallback to overriding the default creds.
	 * This operation is not thread safe as it changes the process
	 * environment variable, but we do not have any better option
	 * with older kerberos libraries */
	{
		const char *oldccname = NULL;

		oldccname = getenv("KRB5CCNAME");
		setenv("KRB5CCNAME", ads->auth.ccache_name, 1);

		maj = gss_acquire_cred(&min, GSS_C_NO_NAME, GSS_C_INDEFINITE,
				       NULL, GSS_C_INITIATE, cred, NULL, NULL);

		if (oldccname) {
			setenv("KRB5CCNAME", oldccname, 1);
		} else {
			unsetenv("KRB5CCNAME");
		}

		if (maj != GSS_S_COMPLETE) {
			status = ADS_ERROR_GSS(maj, min);
			goto done;
		}
	}
#endif

	status = ADS_SUCCESS;

done:
	if (!ADS_ERR_OK(status) && kccache != NULL) {
		krb5_cc_close(kctx, kccache);
	}
	krb5_free_context(kctx);
	return status;
}
Example #19
0
static int
proto (int sock, const char *svc)
{
    krb5_auth_context auth_context;
    krb5_error_code status;
    krb5_principal server;
    krb5_ticket *ticket;
    char *name;
    char ret_string[10];
    char hostname[MAXHOSTNAMELEN];
    krb5_data data;
    krb5_data remotename;
    krb5_data tk_file;
    krb5_ccache ccache;
    char ccname[MAXPATHLEN];
    struct passwd *pwd;

    status = krb5_auth_con_init (context, &auth_context);
    if (status)
	krb5_err(context, 1, status, "krb5_auth_con_init");

    status = krb5_auth_con_setaddrs_from_fd (context,
					     auth_context,
					     &sock);
    if (status)
	krb5_err(context, 1, status, "krb5_auth_con_setaddr");

    if(gethostname (hostname, sizeof(hostname)) < 0)
	krb5_err(context, 1, errno, "gethostname");

    status = krb5_sname_to_principal (context,
				      hostname,
				      svc,
				      KRB5_NT_SRV_HST,
				      &server);
    if (status)
	krb5_err(context, 1, status, "krb5_sname_to_principal");

    status = krb5_recvauth_match_version (context,
					  &auth_context,
					  &sock,
					  kfd_match_version,
					  NULL,
					  server,
					  0,
					  NULL,
					  &ticket);
    if (status)
	krb5_err(context, 1, status, "krb5_recvauth");

    status = krb5_unparse_name (context,
				ticket->client,
				&name);
    if (status)
	krb5_err(context, 1, status, "krb5_unparse_name");

    if(protocol_version == 0) {
	data.data = "old clnt"; /* XXX old clients only had room for
                                   10 bytes of message, and also
                                   didn't show it to the user */
	data.length = strlen(data.data) + 1;
	krb5_write_message(context, &sock, &data);
	sleep(2); /* XXX give client time to finish */
	krb5_errx(context, 1, "old client; exiting");
    }

    status=krb5_read_priv_message (context, auth_context,
				   &sock, &remotename);
    if (status)
	krb5_err(context, 1, status, "krb5_read_message");
    status=krb5_read_priv_message (context, auth_context,
				   &sock, &tk_file);
    if (status)
	krb5_err(context, 1, status, "krb5_read_message");

    krb5_data_zero (&data);

    if(((char*)remotename.data)[remotename.length-1] != '\0')
	krb5_errx(context, 1, "unterminated received");
    if(((char*)tk_file.data)[tk_file.length-1] != '\0')
	krb5_errx(context, 1, "unterminated received");

    status = krb5_read_priv_message(context, auth_context, &sock, &data);

    if (status) {
	krb5_err(context, 1, errno, "krb5_read_priv_message");
	goto out;
    }

    pwd = getpwnam ((char *)(remotename.data));
    if (pwd == NULL) {
	status=1;
	krb5_warnx(context, "getpwnam: %s failed",(char *)(remotename.data));
	goto out;
    }

    if(!krb5_kuserok (context,
		      ticket->client,
		      (char *)(remotename.data))) {
	status=1;
	krb5_warnx(context, "krb5_kuserok: permission denied");
	goto out;
    }

    if (setgid(pwd->pw_gid) < 0) {
	krb5_warn(context, errno, "setgid");
	goto out;
    }
    if (setuid(pwd->pw_uid) < 0) {
	krb5_warn(context, errno, "setuid");
	goto out;
    }

    if (tk_file.length != 1)
	snprintf (ccname, sizeof(ccname), "%s", (char *)(tk_file.data));
    else
	snprintf (ccname, sizeof(ccname), "FILE:/tmp/krb5cc_%lu",
		  (unsigned long)pwd->pw_uid);

    status = krb5_cc_resolve (context, ccname, &ccache);
    if (status) {
	krb5_warn(context, status, "krb5_cc_resolve");
        goto out;
    }
    status = krb5_cc_initialize (context, ccache, ticket->client);
    if (status) {
	krb5_warn(context, status, "krb5_cc_initialize");
        goto out;
    }
    status = krb5_rd_cred2 (context, auth_context, ccache, &data);
    krb5_cc_close (context, ccache);
    if (status) {
	krb5_warn(context, status, "krb5_rd_cred");
        goto out;

    }
    strlcpy(krb5_tkfile,ccname,sizeof(krb5_tkfile));
    krb5_warnx(context, "%s forwarded ticket to %s,%s",
	       name,
	       (char *)(remotename.data),ccname);
  out:
    if (status) {
	strlcpy(ret_string, "no", sizeof(ret_string));
	krb5_warnx(context, "failed");
    } else  {
	strlcpy(ret_string, "ok", sizeof(ret_string));
    }

    krb5_data_free (&tk_file);
    krb5_data_free (&remotename);
    krb5_data_free (&data);
    free(name);

    data.data = ret_string;
    data.length = strlen(ret_string) + 1;
    status = krb5_write_priv_message(context, auth_context, &sock, &data);
    krb5_auth_con_free(context, auth_context);

    return status;
}
Example #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;
}
Example #21
0
static int
CommandProc(struct cmd_syndesc *as, void *arock)
{
    krb5_principal princ = 0;
    char *cell, *pname, **hrealms, *service;
    char service_temp[MAXKTCREALMLEN + 20];
    krb5_creds incred[1], mcred[1], *outcred = 0, *afscred;
    krb5_ccache cc = 0;
#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
    krb5_get_init_creds_opt *gic_opts;
#else
    krb5_get_init_creds_opt gic_opts[1];
#endif
    char *tofree = NULL, *outname;
    int code;
    char *what;
    int i, dosetpag, evil, noprdb, id;
#ifdef AFS_RXK5
    int authtype;
#endif
    krb5_data enc_part[1];
    time_t lifetime;		/* requested ticket lifetime */
    krb5_prompter_fct pf = NULL;
    char *pass = 0;
    void *pa = 0;
    struct kp_arg klog_arg[1];

    char passwd[BUFSIZ];
    struct afsconf_cell cellconfig[1];

    static char rn[] = "klog";	/*Routine name */
    static int Pipe = 0;	/* reading from a pipe */
    static int Silent = 0;	/* Don't want error messages */

    int writeTicketFile = 0;	/* write ticket file to /tmp */

    service = 0;
    memset(incred, 0, sizeof *incred);
    /* blow away command line arguments */
    for (i = 1; i < zero_argc; i++)
	memset(zero_argv[i], 0, strlen(zero_argv[i]));
    zero_argc = 0;
    memset(klog_arg, 0, sizeof *klog_arg);

    /* first determine quiet flag based on -silent switch */
    Silent = (as->parms[aSILENT].items ? 1 : 0);

    if (Silent) {
	afs_set_com_err_hook(silent_errors);
    }

    if ((code = krb5_init_context(&k5context))) {
	afs_com_err(rn, code, "while initializing Kerberos 5 library");
	KLOGEXIT(code);
    }
    if ((code = rx_Init(0))) {
	afs_com_err(rn, code, "while initializing rx");
	KLOGEXIT(code);
    }
    initialize_U_error_table();
    /*initialize_krb5_error_table();*/
    initialize_RXK_error_table();
    initialize_KTC_error_table();
    initialize_ACFG_error_table();
    /* initialize_rx_error_table(); */
    if (!(tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) {
	afs_com_err(rn, 0, "can't get afs configuration (afsconf_Open(%s))",
	    AFSDIR_CLIENT_ETC_DIRPATH);
	KLOGEXIT(1);
    }

    /*
     * Enable DES enctypes, which are currently still required for AFS.
     * krb5_allow_weak_crypto is MIT Kerberos 1.8.  krb5_enctype_enable is
     * Heimdal.
     */
#if defined(HAVE_KRB5_ENCTYPE_ENABLE)
    i = krb5_enctype_valid(k5context, ETYPE_DES_CBC_CRC);
    if (i)
        krb5_enctype_enable(k5context, ETYPE_DES_CBC_CRC);
#elif defined(HAVE_KRB5_ALLOW_WEAK_CRYPTO)
    krb5_allow_weak_crypto(k5context, 1);
#endif

    /* Parse remaining arguments. */

    dosetpag = !! as->parms[aSETPAG].items;
    Pipe = !! as->parms[aPIPE].items;
    writeTicketFile = !! as->parms[aTMP].items;
    noprdb = !! as->parms[aNOPRDB].items;
    evil = (always_evil&1) || !! as->parms[aUNWRAP].items;

#ifdef AFS_RXK5
    authtype = 0;
    if (as->parms[aK5].items)
	authtype |= FORCE_RXK5;
    if (as->parms[aK4].items)
	authtype |= FORCE_RXKAD;
    if (!authtype)
	authtype |= env_afs_rxk5_default();
#endif

    cell = as->parms[aCELL].items ? as->parms[aCELL].items->data : 0;
    if ((code = afsconf_GetCellInfo(tdir, cell, "afsprot", cellconfig))) {
	if (cell)
	    afs_com_err(rn, code, "Can't get cell information for '%s'", cell);
	else
	    afs_com_err(rn, code, "Can't get determine local cell!");
	KLOGEXIT(code);
    }

    if (as->parms[aKRBREALM].items) {
	code = krb5_set_default_realm(k5context,
		as->parms[aKRBREALM].items->data);
	if (code) {
	    afs_com_err(rn, code, "Can't make <%s> the default realm",
		as->parms[aKRBREALM].items->data);
	    KLOGEXIT(code);
	}
    }
    else if ((code = krb5_get_host_realm(k5context, cellconfig->hostName[0], &hrealms))) {
	afs_com_err(rn, code, "Can't get realm for host <%s> in cell <%s>\n",
		cellconfig->hostName[0], cellconfig->name);
	KLOGEXIT(code);
    } else {
	if (hrealms && *hrealms) {
	    code = krb5_set_default_realm(k5context,
		    *hrealms);
	    if (code) {
		afs_com_err(rn, code, "Can't make <%s> the default realm",
		    *hrealms);
		KLOGEXIT(code);
	    }
	}
	if (hrealms) krb5_free_host_realm(k5context, hrealms);
    }

    id = getuid();
    if (as->parms[aPRINCIPAL].items) {
	pname = as->parms[aPRINCIPAL].items->data;
    } else {
	/* No explicit name provided: use Unix uid. */
	struct passwd *pw;
	pw = getpwuid(id);
	if (pw == 0) {
	    afs_com_err(rn, 0,
		"Can't figure out your name from your user id (%d).", id);
	    if (!Silent)
		fprintf(stderr, "%s: Try providing the user name.\n", rn);
	    KLOGEXIT(1);
	}
	pname = pw->pw_name;
    }
    code = krb5_parse_name(k5context, pname, &princ);
    if (code) {
	afs_com_err(rn, code, "Can't parse principal <%s>", pname);
	KLOGEXIT(code);
    }

    if (as->parms[aPASSWORD].items) {
	/*
	 * Current argument is the desired password string.  Remember it in
	 * our local buffer, and zero out the argument string - anyone can
	 * see it there with ps!
	 */
	strncpy(passwd, as->parms[aPASSWORD].items->data, sizeof(passwd));
	memset(as->parms[aPASSWORD].items->data, 0,
	       strlen(as->parms[aPASSWORD].items->data));
	pass = passwd;
    }

    if (as->parms[aLIFETIME].items) {
	char *life = as->parms[aLIFETIME].items->data;
	char *sp;		/* string ptr to rest of life */
	lifetime = 3600 * strtol(life, &sp, 0);	/* hours */
	if (sp == life) {
	  bad_lifetime:
	    if (!Silent)
		fprintf(stderr, "%s: translating '%s' to lifetime failed\n",
			rn, life);
	    return 1;
	}
	if (*sp == ':') {
	    life = sp + 1;	/* skip the colon */
	    lifetime += 60 * strtol(life, &sp, 0);	/* minutes */
	    if (sp == life)
		goto bad_lifetime;
	    if (*sp == ':') {
		life = sp + 1;
		lifetime += strtol(life, &sp, 0);	/* seconds */
		if (sp == life)
		    goto bad_lifetime;
		if (*sp)
		    goto bad_lifetime;
	    } else if (*sp)
		goto bad_lifetime;
	} else if (*sp)
	    goto bad_lifetime;
    } else
	lifetime = 0;

    /* Get the password if it wasn't provided. */
    if (!pass) {
	if (Pipe) {
	    strncpy(passwd, getpipepass(), sizeof(passwd));
	    pass = passwd;
	} else {
	    pf = klog_prompter;
	    pa = klog_arg;
	}
    }

    service = 0;
#ifdef AFS_RXK5
    if (authtype & FORCE_RXK5) {
	tofree = get_afs_krb5_svc_princ(cellconfig);
	snprintf(service_temp, sizeof service_temp, "%s", tofree);
    } else
#endif
    snprintf (service_temp, sizeof service_temp, "afs/%s", cellconfig->name);

    klog_arg->pp = &pass;
    klog_arg->pstore = passwd;
    klog_arg->allocated = sizeof(passwd);
    /* XXX should allow k5 to prompt in most cases -- what about expired pw?*/
#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
    code = krb5_get_init_creds_opt_alloc(k5context, &gic_opts);
    if (code) {
	afs_com_err(rn, code, "Can't allocate get_init_creds options");
	KLOGEXIT(code);
    }
#else
    krb5_get_init_creds_opt_init(gic_opts);
#endif

    for (;;) {
        code = krb5_get_init_creds_password(k5context,
	    incred,
	    princ,
	    pass,
	    pf,	/* prompter */
	    pa,	/* data */
	    0,	/* start_time */
	    0,	/* in_tkt_service */
	    gic_opts);
	if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN)
            break;
    }
    memset(passwd, 0, sizeof(passwd));
    if (code) {
	char *r = 0;
	if (krb5_get_default_realm(k5context, &r))
	    r = 0;
	if (r)
	    afs_com_err(rn, code, "Unable to authenticate in realm %s", r);
	else
	    afs_com_err(rn, code, "Unable to authenticate to use cell %s",
		cellconfig->name);
	if (r) free(r);
	KLOGEXIT(code);
    }

    for (;;writeTicketFile = 0) {
        if (writeTicketFile) {
            what = "getting default ccache";
            code = krb5_cc_default(k5context, &cc);
        } else {
            what = "krb5_cc_resolve";
            code = krb5_cc_resolve(k5context, "MEMORY:core", &cc);
            if (code) goto Failed;
        }
        what = "initializing ccache";
        code = krb5_cc_initialize(k5context, cc, princ);
        if (code) goto Failed;
        what = "writing Kerberos ticket file";
        code = krb5_cc_store_cred(k5context, cc, incred);
        if (code) goto Failed;
        if (writeTicketFile)
            fprintf(stderr,
                    "Wrote ticket file to %s\n",
                    krb5_cc_get_name(k5context, cc));
        break;
      Failed:
        if (code)
            afs_com_err(rn, code, "%s", what);
        if (writeTicketFile) {
            if (cc) {
                krb5_cc_close(k5context, cc);
                cc = 0;
            }
            continue;
        }
        KLOGEXIT(code);
    }

    for (service = service_temp;;service = "afs") {
        memset(mcred, 0, sizeof *mcred);
        mcred->client = princ;
        code = krb5_parse_name(k5context, service, &mcred->server);
        if (code) {
            afs_com_err(rn, code, "Unable to parse service <%s>\n", service);
            KLOGEXIT(code);
        }
        if (tofree) { free(tofree); tofree = 0; }
        if (!(code = krb5_unparse_name(k5context, mcred->server, &outname)))
            tofree = outname;
        else outname = service;
        code = krb5_get_credentials(k5context, 0, cc, mcred, &outcred);
        krb5_free_principal(k5context, mcred->server);
        if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN || service != service_temp) break;
#ifdef AFS_RXK5
        if (authtype & FORCE_RXK5)
            break;
#endif
    }
    afscred = outcred;

    if (code) {
	afs_com_err(rn, code, "Unable to get credentials to use %s", outname);
	KLOGEXIT(code);
    }

#ifdef AFS_RXK5
    if (authtype & FORCE_RXK5) {
	struct ktc_principal aserver[1];
	int viceid = 555;

	memset(aserver, 0, sizeof *aserver);
	strncpy(aserver->cell, cellconfig->name, MAXKTCREALMLEN-1);
	code = ktc_SetK5Token(k5context, aserver, afscred, viceid, dosetpag);
	if (code) {
	    afs_com_err(rn, code, "Unable to store tokens for cell %s\n",
		cellconfig->name);
	    KLOGEXIT(1);
	}
    } else
#endif
    {
	struct ktc_principal aserver[1], aclient[1];
	struct ktc_token atoken[1];

	memset(atoken, 0, sizeof *atoken);
	if (evil) {
	    size_t elen = enc_part->length;
	    atoken->kvno = RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY;
	    if (afs_krb5_skip_ticket_wrapper(afscred->ticket.data,
			afscred->ticket.length, (char **) &enc_part->data,
			&elen)) {
		afs_com_err(rn, 0, "Can't unwrap %s AFS credential",
		    cellconfig->name);
		KLOGEXIT(1);
	    }
	} else {
	    atoken->kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
	    *enc_part = afscred->ticket;
	}
	atoken->startTime = afscred->times.starttime;
	atoken->endTime = afscred->times.endtime;
	if (tkt_DeriveDesKey(get_creds_enctype(afscred),
			     get_cred_keydata(afscred),
			     get_cred_keylen(afscred), &atoken->sessionKey)) {
	    afs_com_err(rn, 0,
			"Cannot derive DES key from enctype %i of length %u",
			get_creds_enctype(afscred),
			(unsigned)get_cred_keylen(afscred));
	    KLOGEXIT(1);
	}
	memcpy(atoken->ticket, enc_part->data,
	    atoken->ticketLen = enc_part->length);
	memset(aserver, 0, sizeof *aserver);
	strncpy(aserver->name, "afs", 4);
	strncpy(aserver->cell, cellconfig->name, MAXKTCREALMLEN-1);
	memset(aclient, 0, sizeof *aclient);
	i = realm_len(k5context, afscred->client);
	if (i > MAXKTCREALMLEN-1) i = MAXKTCREALMLEN-1;
	memcpy(aclient->cell, realm_data(k5context, afscred->client), i);
	if (!noprdb) {
	    int viceid = 0;
	    k5_to_k4_name(k5context, afscred->client, aclient);
	    code = whoami(atoken, cellconfig, aclient, &viceid);
	    if (code) {
		afs_com_err(rn, code, "Can't get your viceid for cell %s", cellconfig->name);
		*aclient->name = 0;
	    } else
		snprintf(aclient->name, MAXKTCNAMELEN-1, "AFS ID %d", viceid);
	}
	if (!*aclient->name)
	    k5_to_k4_name(k5context, afscred->client, aclient);
	code = ktc_SetToken(aserver, atoken, aclient, dosetpag);
	if (code) {
	    afs_com_err(rn, code, "Unable to store tokens for cell %s\n",
		cellconfig->name);
	    KLOGEXIT(1);
	}
    }

    krb5_free_principal(k5context, princ);
    krb5_free_cred_contents(k5context, incred);
    if (outcred) krb5_free_creds(k5context, outcred);
    if (cc)
	krb5_cc_close(k5context, cc);
    if (tofree) free(tofree);

    return 0;
}
Example #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;
}
Example #23
0
int
main (int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache  ccache;
    int optidx = 0;
    int exit_val = 0;

    setprogname (argv[0]);

    if(getarg(args, num_args, argc, argv, &optidx))
	usage(1);

    if (help_flag)
	usage (0);

    if(version_flag){
	print_version(NULL);
	exit(0);
    }

    argc -= optidx;
    argv += optidx;

    if (argc != 0)
	usage (1);

    ret = krb5_init_context (&context);
    if (ret)
	errx (1, "krb5_init_context failed: %d", ret);

    if (all_flag) {
	krb5_cccol_cursor cursor;

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

	while (krb5_cccol_cursor_next (context, cursor, &ccache) == 0 && ccache != NULL) {

	    ret = krb5_cc_destroy (context, ccache);
	    if (ret) {
		krb5_warn(context, ret, "krb5_cc_destroy");
		exit_val = 1;
	    }
	}
	krb5_cccol_cursor_free(context, &cursor);

    } else {
	if(cache == NULL) {
	    ret = krb5_cc_default(context, &ccache);
	    if (ret)
		krb5_err(context, 1, ret, "krb5_cc_default");
	} else {
	    ret =  krb5_cc_resolve(context,
				   cache,
				   &ccache);
	    if (ret)
		krb5_err(context, 1, ret, "krb5_cc_resolve");
	}

	if (ret == 0) {
	    if (credential) {
		krb5_creds mcred;

		krb5_cc_clear_mcred(&mcred);

		ret = krb5_parse_name(context, credential, &mcred.server);
		if (ret)
		    krb5_err(context, 1, ret,
			     "Can't parse principal %s", credential);

		ret = krb5_cc_remove_cred(context, ccache, 0, &mcred);
		if (ret)
		    krb5_err(context, 1, ret,
			     "Failed to remove principal %s", credential);

		krb5_cc_close(context, ccache);
		krb5_free_principal(context, mcred.server);
		krb5_free_context(context);
		return 0;
	    }

	    ret = krb5_cc_destroy (context, ccache);
	    if (ret) {
		krb5_warn(context, ret, "krb5_cc_destroy");
		exit_val = 1;
	    }
	}
    }

    krb5_free_context (context);

#ifndef NO_AFS
    if (unlog_flag && k_hasafs ()) {
	if (k_unlog ())
	    exit_val = 1;
    }
#endif

    return exit_val;
}
Example #24
0
int
auks_krb5_cred_store(char *cachefilename, char *buffer,
		     size_t buffer_length)
{
	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 **creds;
	krb5_data data;
	krb5_replay_data krdata;

	/* 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 a nullified kerberos authentication context in order */
	/* to decode credential from 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 ctx_exit;
	}
	auks_log("kerberos authentication context successfully initialized");

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

	/* build a kerberos data structure with input buffer */
	data.data = buffer;
	data.length = buffer_length;

	/* build kerberos credential structure using this data structure */
	err_code = krb5_rd_cred(context, auth_context, &data,&creds,&krdata);
	if (err_code) {
		auks_error("unable to deserialize credential data : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_RD_CRED ;
		goto auth_ctx_exit;

	}
	auks_log("credential data successfully deserialized");

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

	/* initialize kerberos credential structure */
	err_code = krb5_cc_initialize(context,ccache,(*creds)->client);
	if (err_code) {
		auks_error("unable to initialize credential cache : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_INIT_CC ;
		goto cc_exit;

	}
	auks_log("credential cache successfully initialized",cachefilename);

	/* store credential in credential cache */
	err_code = krb5_cc_store_cred(context,ccache,*creds);
	if (err_code) {
		auks_error("unable to store credential in credential "
			   "cache : %s",error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_STORE_CRED ;
	} else {
		auks_log("credential successfully stored in credential cache");
		fstatus = AUKS_SUCCESS ;
	}

cc_exit:
	krb5_cc_close(context, ccache);

cred_exit:
	krb5_free_creds(context, *creds);
	free(creds);

auth_ctx_exit:
	krb5_auth_con_free(context, auth_context);

ctx_exit:
	krb5_free_context(context);

exit:
	return fstatus;
}
Example #25
0
static
DWORD
IDMKrbRenewCredentials(
    PIDM_KRB_CONTEXT pKrbContext
    )
{
    DWORD   dwError = 0;
    DWORD   dwCleanupError = 0;
    BOOLEAN bLocked = FALSE;
    BOOLEAN bRefreshCreds = FALSE;
    krb5_context   pCtx   = NULL;
    PSTR           pszPrincipal = NULL;
    krb5_principal pPrincipal = NULL;
    krb5_keytab    ktid   = 0;
    krb5_ccache    pCache = NULL;
    krb5_creds     creds = {0};

    IDM_RWMUTEX_LOCK_SHARED(&pKrbContext->mutex_rw, bLocked, dwError);
    BAIL_ON_ERROR(dwError);

    if (!pKrbContext->expiryTime)
    {
        bRefreshCreds = TRUE;
    }
    else
    {
        krb5_timestamp now = time(NULL);

        if (now >= pKrbContext->expiryTime)
        {
            bRefreshCreds = TRUE;
        }
        else
        {
            double threshold = (30 * 60); // 30 minutes
            double interval = difftime(pKrbContext->expiryTime, now);

            if (interval <= threshold)
            {
                bRefreshCreds = TRUE;
            }
        }
    }

    if (bRefreshCreds)
    {
        krb5_error_code errKrb = 0;
        krb5_deltat    startTime = 0;
        PSTR pszServiceName = NULL;
        krb5_get_init_creds_opt options = {0};
        krb5_timestamp origExpiryTime = pKrbContext->expiryTime;

        IDM_RWMUTEX_UNLOCK(&pKrbContext->mutex_rw, bLocked, dwError);
        BAIL_ON_ERROR(dwError);

        dwError = IDMKrbGetPrincipal(
                      pKrbContext->pszAccount,
                      pKrbContext->pszDomain,
                      &pszPrincipal);
        BAIL_ON_ERROR(dwError);

        errKrb = krb5_init_context(&pCtx);
        BAIL_ON_KERBEROS_ERROR(NULL, errKrb, dwError);

        errKrb = krb5_parse_name(pCtx, pszPrincipal, &pPrincipal);
        BAIL_ON_KERBEROS_ERROR(NULL, errKrb, dwError);

        errKrb = krb5_kt_default(pCtx, &ktid);
        BAIL_ON_KERBEROS_ERROR(NULL, errKrb, dwError);

        krb5_get_init_creds_opt_init(&options);
        krb5_get_init_creds_opt_set_forwardable(&options, TRUE);

        errKrb = krb5_get_init_creds_keytab(
                    pCtx,
                    &creds,
                    pPrincipal,
                    ktid,
                    startTime,
                    pszServiceName,
                    &options);
        BAIL_ON_KERBEROS_ERROR(NULL, errKrb, dwError);

        IDM_RWMUTEX_LOCK_EXCLUSIVE(&pKrbContext->mutex_rw, bLocked, dwError);
        BAIL_ON_ERROR(dwError);

        if (pKrbContext->expiryTime <= origExpiryTime)
        {
            errKrb = krb5_cc_resolve(pCtx, pKrbContext->pszCachePath, &pCache);
            BAIL_ON_KERBEROS_ERROR(NULL, errKrb, dwError);

            errKrb = krb5_cc_initialize(pCtx, pCache, pPrincipal);
            BAIL_ON_KERBEROS_ERROR(NULL, errKrb, dwError);

            errKrb = krb5_cc_store_cred(pCtx, pCache, &creds);
            BAIL_ON_KERBEROS_ERROR(NULL, errKrb, dwError);

            pKrbContext->expiryTime = creds.times.endtime;
        }
    }

cleanup:

    IDM_RWMUTEX_UNLOCK(&pKrbContext->mutex_rw, bLocked, dwCleanupError);

    if (pCtx)
    {
        if (ktid)
        {
            krb5_kt_close(pCtx, ktid);
            ktid = 0;
        }
        if (pPrincipal)
        {
            if (creds.client == pPrincipal)
            {
                creds.client = NULL;
            }

            krb5_free_principal(pCtx, pPrincipal);
        }

        krb5_free_cred_contents(pCtx, &creds);

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

        krb5_free_context(pCtx);
    }

    IDM_SAFE_FREE_MEMORY(pszPrincipal);

    if(!dwError)
    {
        dwError = dwCleanupError;
    }
    return dwError;

error:

    goto cleanup;
}
Example #26
0
int
auks_krb5_cred_get_fwd(char *ccachefilename, char *serverName,
		       char **p_buffer,
		       size_t * p_buffer_length)
{

	int fstatus = AUKS_ERROR ;

	/* kerberos related variables */
	krb5_error_code err_code;
	krb5_context context;
	krb5_ccache ccache;
	krb5_principal principal;
	krb5_creds **out_creds_array = NULL;
	krb5_auth_context auth_context;
	krb5_flags authopts;
	krb5_data outbuf;
	krb5_data *p_outbuf;
	krb5_replay_data krdata;

	authopts = AP_OPTS_MUTUAL_REQUIRED;
	authopts &= (~OPTS_FORWARD_CREDS);
	authopts &= (~OPTS_FORWARDABLE_CREDS);

	if ( serverName == NULL ) {
		auks_error("no host specified");
		fstatus = AUKS_ERROR_KRB5_CRED_NO_HOST_SPECIFIED ;
		goto exit;
	}

	/* 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");

	/* get principal using credential cache */
	err_code = krb5_cc_get_principal(context,ccache,&principal);
	if (err_code) {
		auks_error("unable to get principal from credential cache : %s",
			   error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_GET_PRINC ;
		goto cc_exit ;
	}
	auks_log("principal successfully extracted from credential cache");

	/* initialize kerberos authentication context */
	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 princ_exit;
	}
	auks_log("kerberos authentication context successfully initialized");

	/* do replay detection using timestamps */
	krb5_auth_con_setflags(context,auth_context,KRB5_AUTH_CONTEXT_RET_TIME);

	/* get forwarded credential for server */
	err_code = krb5_fwd_tgt_creds(context,auth_context,serverName,
				      principal,NULL,NULL,authopts,&outbuf);
	if (err_code) {
		auks_error("unable to get serialized and crypted forwarded "
			   "credential for %s from KDC : %s",
			   serverName,error_message(err_code));
		fstatus =  AUKS_ERROR_KRB5_CRED_GET_FWD_CRED ;
		goto auth_ctx_exit;
	}
	auks_log("serialized and crypted forwarded credential for %s "
		 "successfully got from KDC",serverName);

	/* desactive replay detection */
	krb5_auth_con_setflags(context,auth_context,0);

	/* decrypt (using session key stored in auth context) and */
	/* unserialized forwarded credential in a kerberos credential */
	/* structure */
	err_code = krb5_rd_cred(context,auth_context,&outbuf,&out_creds_array,
				&krdata);
	if (err_code) {
		auks_error("unable to unserialize and decrypt forwarded "
			   "credential for %s : %s",serverName,
			   error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_RD_CRED ;
		goto fwd_exit;
	}
	auks_log("unserialization and decryption of forwarded "
		 "credential for %s succesfully done",serverName);

	/* Reinitialize kerberos authentication context in order to */
	/* write credential to output buffer */
	krb5_auth_con_free(context,auth_context);
	err_code = krb5_auth_con_init(context,&auth_context);
	if (err_code) {
		auks_error("unable to reinitialize kerberos connection "
			   "authentication context : %s",error_message
			   (err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_INIT_AUTH_CTX ;
		goto rd_cred_exit;
	}
	auks_log("kerberos connection authentication context "
		 "reinitialization successfully done");

	/* no flags */
	krb5_auth_con_setflags(context,auth_context,0);

	/* serialize forwarded credential (no encryption because auth */
	/* context session key is nullified) */
	err_code = krb5_mk_1cred(context,auth_context,*out_creds_array,
				 &p_outbuf,&krdata);
	if (err_code) {
		auks_error("unable to serialize forwarded credential for "
			   "%s : %s",serverName,error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_MK_CRED ;
		goto rd_cred_exit;
	}
	auks_log("forwarded credential for %s successfully serialized",
		 serverName);

	/* allocate output buffer and store serialized credential */
	(*p_buffer) = (char *) malloc(p_outbuf->length * sizeof(char));
	if ((*p_buffer) == NULL) {
		auks_error("unable to allocate serialized credential output "
			   "buffer for %s",serverName);
		*p_buffer_length = 0 ;
		fstatus = AUKS_ERROR_KRB5_CRED_MALLOC ;
	} else {
		/* copy data */
		memcpy(*p_buffer,p_outbuf->data,p_outbuf->length);
		*p_buffer_length = p_outbuf->length;
		auks_log("forwarded credential successfully stored "
			 "in output buffer");
		fstatus	= AUKS_SUCCESS ;
	}

	krb5_free_data(context,p_outbuf);

rd_cred_exit:
	krb5_free_creds(context,*out_creds_array);
	free(out_creds_array);

fwd_exit:
	krb5_free_data_contents(context, &outbuf);

auth_ctx_exit:
	krb5_auth_con_free(context,auth_context);

princ_exit:
	krb5_free_principal(context, principal);

cc_exit:
	krb5_cc_close(context, ccache);

ctx_exit:
	krb5_free_context(context);

exit:
	return fstatus;
}
Example #27
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;
}
Example #28
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;
}
Example #29
0
char *					/* R: allocated response string */
auth_krb5 (
  /* PARAMETERS */
  const char *user,			/* I: plaintext authenticator */
  const char *password,			/* I: plaintext password */
  const char *service,                  /* I: service authenticating to */
  const char *realm                     /* I: user's realm */
  /* END PARAMETERS */
  )
{
    /* VARIABLES */
    krb5_context context;
    krb5_ccache ccache = NULL;
    krb5_keytab kt = NULL;
    krb5_principal auth_user;
    krb5_verify_opt opt;
    char * result;
    char tfname[2048];
    char principalbuf[2048];
    /* END VARIABLES */

    if (!user || !password) {
	syslog(LOG_ERR, "auth_krb5: NULL password or username?");
	return strdup("NO saslauthd internal NULL password or username");
    }

    if (krb5_init_context(&context)) {
	syslog(LOG_ERR, "auth_krb5: krb5_init_context");
	return strdup("NO saslauthd internal krb5_init_context error");
    }

    if (form_principal_name(user, service, realm, principalbuf, sizeof (principalbuf))) {
	syslog(LOG_ERR, "auth_krb5: form_principal_name");
	return strdup("NO saslauthd principal name error");
    }

    if (krb5_parse_name (context, principalbuf, &auth_user)) {
	krb5_free_context(context);
	syslog(LOG_ERR, "auth_krb5: krb5_parse_name");
	return strdup("NO saslauthd internal krb5_parse_name error");
    }

    if (krbtf_name(tfname, sizeof (tfname)) != 0) {
	syslog(LOG_ERR, "auth_krb5: could not generate ccache name");
	return strdup("NO saslauthd internal error");
    }

    if (krb5_cc_resolve(context, tfname, &ccache)) {
	krb5_free_principal(context, auth_user);
	krb5_free_context(context);
	syslog(LOG_ERR, "auth_krb5: krb5_cc_resolve");
	return strdup("NO saslauthd internal error");
    }

    if (keytabname) {
	if (krb5_kt_resolve(context, keytabname, &kt)) {
	    krb5_free_principal(context, auth_user);
	    krb5_cc_destroy(context, ccache);
	    krb5_free_context(context);
	    syslog(LOG_ERR, "auth_krb5: krb5_kt_resolve");
	    return strdup("NO saslauthd internal error");
	}
    }
    
    krb5_verify_opt_init(&opt);
    krb5_verify_opt_set_secure(&opt, 1);
    krb5_verify_opt_set_ccache(&opt, ccache);
    if (kt)
	krb5_verify_opt_set_keytab(&opt,  kt);
    krb5_verify_opt_set_service(&opt, verify_principal);
    
    if (krb5_verify_user_opt(context, auth_user, password, &opt)) {
	result = strdup("NO krb5_verify_user_opt failed");
    } else {
        result = strdup("OK");
    }
    
    krb5_free_principal(context, auth_user);
    krb5_cc_destroy(context, ccache);
    if (kt)
	krb5_kt_close(context, kt);
    krb5_free_context(context);

    return result;
}
Example #30
0
char *					/* R: allocated response string */
auth_krb5 (
  /* PARAMETERS */
  const char *user,			/* I: plaintext authenticator */
  const char *password,			/* I: plaintext password */
  const char *service,			/* I: service authenticating to */
  const char *realm			/* I: user's realm */
  /* END PARAMETERS */
  )
{
    /* VARIABLES */
    krb5_context context;
    krb5_ccache ccache = NULL;
    krb5_principal auth_user;
    krb5_creds creds;
    krb5_get_init_creds_opt opts;
    char * result;
    char tfname[2048];
    char principalbuf[2048];
    krb5_error_code code;
    /* END VARIABLES */

    if (!user|| !password) {
	syslog(LOG_ERR, "auth_krb5: NULL password or username?");
	return strdup("NO saslauthd internal error");
    }

    if (krb5_init_context(&context)) {
	syslog(LOG_ERR, "auth_krb5: krb5_init_context");
	return strdup("NO saslauthd internal error");
    }

    if (form_principal_name(user, service, realm, principalbuf, sizeof (principalbuf))) {
	syslog(LOG_ERR, "auth_krb5: form_principal_name");
	return strdup("NO saslauthd principal name error");
    }

    if (krb5_parse_name (context, principalbuf, &auth_user)) {
	krb5_free_context(context);
	syslog(LOG_ERR, "auth_krb5: krb5_parse_name");
	return strdup("NO saslauthd internal error");
    }
    
    if (krbtf_name(tfname, sizeof (tfname)) != 0) {
	syslog(LOG_ERR, "auth_krb5: could not generate ticket file name");
	return strdup("NO saslauthd internal error");
    }

    if (krb5_cc_resolve(context, tfname, &ccache)) {
	krb5_free_principal(context, auth_user);
	krb5_free_context(context);
	syslog(LOG_ERR, "auth_krb5: krb5_cc_resolve");
	return strdup("NO saslauthd internal error");
    }
    
    if (krb5_cc_initialize (context, ccache, auth_user)) {
	krb5_free_principal(context, auth_user);
	krb5_free_context(context);
	syslog(LOG_ERR, "auth_krb5: krb5_cc_initialize");
	return strdup("NO saslauthd internal error");
    }
    
    krb5_get_init_creds_opt_init(&opts);
    /* 15 min should be more than enough */
    krb5_get_init_creds_opt_set_tkt_life(&opts, 900); 
    if (code = krb5_get_init_creds_password(context, &creds, 
				     auth_user, password, NULL, NULL, 
				     0, NULL, &opts)) {
	krb5_cc_destroy(context, ccache);
	krb5_free_principal(context, auth_user);
	krb5_free_context(context);
	syslog(LOG_ERR, "auth_krb5: krb5_get_init_creds_password: %d", code);
	return strdup("NO saslauthd internal error");
    }
    
    /* at this point we should have a TGT. Let's make sure it is valid */
    if (krb5_cc_store_cred(context, ccache, &creds)) {
	krb5_free_principal(context, auth_user);
	krb5_cc_destroy(context, ccache);
	krb5_free_context(context);
	syslog(LOG_ERR, "auth_krb5: krb5_cc_store_cred");
	return strdup("NO saslauthd internal error");
    }
    
    if (!k5support_verify_tgt(context, ccache)) {
	syslog(LOG_ERR, "auth_krb5: k5support_verify_tgt");
	result = strdup("NO saslauthd internal error");
	goto fini;
    }
    
    /* 
     * fall through -- user is valid beyond this point  
     */
    
    result = strdup("OK");
 fini:
/* destroy any tickets we had */
    krb5_free_cred_contents(context, &creds);
    krb5_free_principal(context, auth_user);
    krb5_cc_destroy(context, ccache);
    krb5_free_context(context);

    return result;
}