Exemple #1
0
static krb5_error_code mod_authn_gssapi_verify_krb5_init_creds(server *srv, krb5_context context, krb5_creds *creds, krb5_principal ap_req_server, krb5_keytab ap_req_keytab)
{
    krb5_error_code ret;
    krb5_data req;
    krb5_ccache local_ccache       = NULL;
    krb5_creds *new_creds          = NULL;
    krb5_auth_context auth_context = NULL;
    krb5_keytab keytab             = NULL;
    char *server_name;

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

    if (ap_req_keytab == NULL) {
        ret = krb5_kt_default(context, &keytab);
        if (ret)
            return ret;
    } else
        keytab = ap_req_keytab;

    ret = krb5_cc_resolve(context, "MEMORY:", &local_ccache);
    if (ret) {
        log_error_write(srv, __FILE__, __LINE__, "s", "krb5_cc_resolve() failed when verifying KDC");
        /* return ret; */
        goto end;
    }

    ret = krb5_cc_initialize(context, local_ccache, creds->client);
    if (ret) {
        log_error_write(srv, __FILE__, __LINE__, "s", "krb5_cc_initialize() failed when verifying KDC");
        goto end;
    }

    ret = krb5_cc_store_cred(context, local_ccache, creds);
    if (ret) {
        log_error_write(srv, __FILE__, __LINE__, "s", "krb5_cc_store_cred() failed when verifying KDC");
        goto end;
    }

    ret = krb5_unparse_name(context, ap_req_server, &server_name);
    if (ret) {
        log_error_write(srv, __FILE__, __LINE__, "s", "krb5_unparse_name() failed when verifying KDC");
        goto end;
    }
    krb5_free_unparsed_name(context, server_name);

    if (!krb5_principal_compare(context, ap_req_server, creds->server)) {
        krb5_creds match_cred;

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

        match_cred.client = creds->client;
        match_cred.server = ap_req_server;

        ret = krb5_get_credentials(context, 0, local_ccache, &match_cred, &new_creds);
        if (ret) {
            log_error_write(srv, __FILE__, __LINE__, "s", "krb5_get_credentials() failed when verifying KDC");
            goto end;
        }
        creds = new_creds;
    }

    ret = krb5_mk_req_extended(context, &auth_context, 0, NULL, creds, &req);
    if (ret) {
        log_error_write(srv, __FILE__, __LINE__, "s", "krb5_mk_req_extended() failed when verifying KDC");
        goto end;
    }

    krb5_auth_con_free(context, auth_context);
    auth_context = NULL;
    ret = krb5_auth_con_init(context, &auth_context);
    if (ret) {
        log_error_write(srv, __FILE__, __LINE__, "s", "krb5_auth_con_init() failed when verifying KDC");
        goto end;
    }

    /* use KRB5_AUTH_CONTEXT_DO_SEQUENCE to skip replay cache checks */
    krb5_auth_con_setflags(context, auth_context, KRB5_AUTH_CONTEXT_DO_SEQUENCE);
    ret = krb5_rd_req(context, &auth_context, &req, ap_req_server, keytab, 0, NULL);
    if (ret) {
        log_error_write(srv, __FILE__, __LINE__, "s", "krb5_rd_req() failed when verifying KDC");
        goto end;
    }

    end:
        krb5_free_data_contents(context, &req);
        if (auth_context)
            krb5_auth_con_free(context, auth_context);
        if (new_creds)
            krb5_free_creds(context, new_creds);
        if (ap_req_keytab == NULL && keytab)
            krb5_kt_close(context, keytab);
        if (local_ccache)
            krb5_cc_destroy(context, local_ccache);

    return ret;
}
Exemple #2
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);
}
Exemple #3
0
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;
#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);
    }

    if(use_keytab || keytab_str) {
	krb5_keytab kt;
	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_get_init_creds_keytab (context,
					  &cred,
					  principal,
					  kt,
					  start_time,
					  server_str,
					  opt);
	krb5_kt_close(context, kt);
    } else if (pk_user_id || ent_user_id || anonymous_flag) {
	ret = krb5_get_init_creds_password (context,
					    &cred,
					    principal,
					    passwd,
					    krb5_prompter_posix,
					    NULL,
					    start_time,
					    server_str,
					    opt);
    } 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));
		exit(1);
	    }
	    free (prompt);
	}


	ret = krb5_get_init_creds_password (context,
					    &cred,
					    principal,
					    passwd,
					    krb5_prompter_posix,
					    NULL,
					    start_time,
					    server_str,
					    opt);
    }
    krb5_get_init_creds_opt_free(context, opt);
#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");
    }

    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_cc_initialize (context, tempccache, cred.client);
    if (ret)
	krb5_err (context, 1, ret, "krb5_cc_initialize");

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

    krb5_free_cred_contents (context, &cred);

    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);
    }


    if (enctype)
	free(enctype);

    return 0;
}
Exemple #4
0
static krb5_error_code
renew_validate(krb5_context context,
	       int renew,
	       int validate,
	       krb5_ccache cache,
	       const char *server,
	       krb5_deltat life)
{
    krb5_error_code ret;
    krb5_ccache tempccache = NULL;
    krb5_creds in, *out = NULL;
    krb5_kdc_flags flags;

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

    ret = krb5_cc_get_principal(context, cache, &in.client);
    if (ret) {
	krb5_warn(context, ret, "krb5_cc_get_principal");
	return ret;
    }
    ret = get_server(context, in.client, server, &in.server);
    if (ret) {
	krb5_warn(context, ret, "get_server");
	goto out;
    }

    if (renew) {
	/*
	 * no need to check the error here, it's only to be
	 * friendly to the user
	 */
	krb5_get_credentials(context, KRB5_GC_CACHED, cache, &in, &out);
    }

    flags.i = 0;
    flags.b.renewable         = flags.b.renew = renew;
    flags.b.validate          = validate;

    if (forwardable_flag != -1)
	flags.b.forwardable       = forwardable_flag;
    else if (out)
	flags.b.forwardable 	  = out->flags.b.forwardable;

    if (proxiable_flag != -1)
	flags.b.proxiable         = proxiable_flag;
    else if (out)
	flags.b.proxiable 	  = out->flags.b.proxiable;

    if (anonymous_flag)
	flags.b.request_anonymous = anonymous_flag;
    if (life)
	in.times.endtime = time(NULL) + life;

    if (out) {
	krb5_free_creds(context, out);
	out = NULL;
    }


    ret = krb5_get_kdc_cred(context,
			    cache,
			    flags,
			    NULL,
			    NULL,
			    &in,
			    &out);
    if (ret) {
	krb5_warn(context, ret, "krb5_get_kdc_cred");
	goto out;
    }

    ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, cache),
			     NULL, &tempccache);
    if (ret) {
	krb5_warn(context, ret, "krb5_cc_new_unique");
	goto out;
    }

    ret = krb5_cc_initialize(context, tempccache, in.client);
    if (ret) {
	krb5_warn(context, ret, "krb5_cc_initialize");
	goto out;
    }

    ret = krb5_cc_store_cred(context, tempccache, out);
    if (ret) {
	krb5_warn(context, ret, "krb5_cc_store_cred");
	goto out;
    }

    /*
     * We want to preserve cc configs as some are security-relevant, and
     * anyways it's the friendly thing to do.
     */
    ret = copy_configs(context, tempccache, cache, out->server);
    if (ret)
	goto out;

    ret = krb5_cc_move(context, tempccache, cache);
    if (ret) {
	krb5_warn(context, ret, "krb5_cc_move");
	goto out;
    }
    tempccache = NULL;

out:
    if (tempccache)
	krb5_cc_close(context, tempccache);
    if (out)
	krb5_free_creds(context, out);
    krb5_free_cred_contents(context, &in);
    return ret;
}
Exemple #5
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;
}
static krb5_error_code
get_new_cache(krb5_context context,
	      krb5_principal client,
	      const char *password,
	      krb5_prompter_fct prompter,
	      const char *keytab,
	      const char *server_name,
	      krb5_ccache *ret_cache)
{
    krb5_error_code ret;
    krb5_creds cred;
    krb5_get_init_creds_opt *opt;
    krb5_ccache id;

    ret = krb5_get_init_creds_opt_alloc (context, &opt);
    if (ret)
	return ret;

    krb5_get_init_creds_opt_set_default_flags(context, "kadmin",
					      krb5_principal_get_realm(context,
								       client),
					      opt);


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

    if(password == NULL && prompter == NULL) {
	krb5_keytab kt;
	if(keytab == NULL)
	    ret = krb5_kt_default(context, &kt);
	else
	    ret = krb5_kt_resolve(context, keytab, &kt);
	if(ret) {
	    krb5_get_init_creds_opt_free(context, opt);
	    return ret;
	}
	ret = krb5_get_init_creds_keytab (context,
					  &cred,
					  client,
					  kt,
					  0,
					  server_name,
					  opt);
	krb5_kt_close(context, kt);
    } else {
	ret = krb5_get_init_creds_password (context,
					    &cred,
					    client,
					    password,
					    prompter,
					    NULL,
					    0,
					    server_name,
					    opt);
    }
    krb5_get_init_creds_opt_free(context, opt);
    switch(ret){
    case 0:
	break;
    case KRB5_LIBOS_PWDINTR:	/* don't print anything if it was just C-c:ed */
    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
    case KRB5KRB_AP_ERR_MODIFIED:
	return KADM5_BAD_PASSWORD;
    default:
	return ret;
    }
    ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id);
    if(ret)
	return ret;
    ret = krb5_cc_initialize (context, id, cred.client);
    if (ret)
	return ret;
    ret = krb5_cc_store_cred (context, id, &cred);
    if (ret)
	return ret;
    krb5_free_cred_contents (context, &cred);
    *ret_cache = id;
    return 0;
}
Exemple #7
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)
{
#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) {
		printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
			 ple->ccname, ple->endtime);
		code = 0;
		goto out;
	}

	if ((code = krb5_kt_get_name(context, kt, kt_name, BUFSIZ))) {
		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

	if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ,
					       kt, 0, NULL, opts))) {
		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)
		free(ple->ccname);
	ple->ccname = 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;
	}
	if ((code = krb5_cc_resolve(context, cc_name, &ccache))) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0, "ERROR: %s while opening credential cache '%s'\n",
			 k5err, cc_name);
		goto out;
	}
	if ((code = krb5_cc_initialize(context, ccache, ple->princ))) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0, "ERROR: %s while initializing credential "
			 "cache '%s'\n", k5err, cc_name);
		goto out;
	}
	if ((code = krb5_cc_store_cred(context, ccache, &my_creds))) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0, "ERROR: %s while storing credentials in '%s'\n",
			 k5err, cc_name);
		goto out;
	}

	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);
	free(k5err);
	return (code);
}
Exemple #8
0
static OM_uint32 acquire_initiator_cred
		  (OM_uint32 * minor_status,
		   krb5_context context,
		   const gss_name_t desired_name,
		   OM_uint32 time_req,
		   const gss_OID_set desired_mechs,
		   gss_cred_usage_t cred_usage,
		   gsskrb5_cred handle,
		   gss_OID_set * actual_mechs,
		   OM_uint32 * time_rec
		  )
{
    OM_uint32 ret;
    krb5_creds cred;
    krb5_principal def_princ;
    krb5_get_init_creds_opt *opt;
    krb5_ccache ccache;
    krb5_keytab keytab;
    krb5_error_code kret;

    keytab = NULL;
    ccache = NULL;
    def_princ = NULL;
    ret = GSS_S_FAILURE;
    memset(&cred, 0, sizeof(cred));

    /*
     * If we have a preferred principal, lets try to find it in all
     * caches, otherwise, fall back to default cache, ignore all
     * errors while searching.
     */

    if (handle->principal) {
	kret = krb5_cc_cache_match (context,
				    handle->principal,
				    &ccache);
	if (kret == 0) {
	    ret = GSS_S_COMPLETE;
	    goto found;
	}
    }

    if (ccache == NULL) {
	kret = krb5_cc_default(context, &ccache);
	if (kret)
	    goto end;
    }
    kret = krb5_cc_get_principal(context, ccache, &def_princ);
    if (kret != 0) {
	/* we'll try to use a keytab below */
	krb5_cc_close(context, ccache);
	def_princ = NULL;
	kret = 0;
    } else if (handle->principal == NULL)  {
	kret = krb5_copy_principal(context, def_princ, &handle->principal);
	if (kret)
	    goto end;
    } else if (handle->principal != NULL &&
	       krb5_principal_compare(context, handle->principal,
				      def_princ) == FALSE) {
	krb5_free_principal(context, def_princ);
	def_princ = NULL;
	krb5_cc_close(context, ccache);
	ccache = NULL;
    }
    if (def_princ == NULL) {
	/* We have no existing credentials cache,
	 * so attempt to get a TGT using a keytab.
	 */
	if (handle->principal == NULL) {
	    kret = krb5_get_default_principal(context, &handle->principal);
	    if (kret)
		goto end;
	}
	kret = get_keytab(context, &keytab);
	if (kret)
	    goto end;
	kret = krb5_get_init_creds_opt_alloc(context, &opt);
	if (kret)
	    goto end;
	kret = krb5_get_init_creds_keytab(context, &cred,
	    handle->principal, keytab, 0, NULL, opt);
	krb5_get_init_creds_opt_free(context, opt);
	if (kret)
	    goto end;
	kret = krb5_cc_new_unique(context, krb5_cc_type_memory,
				  NULL, &ccache);
	if (kret)
	    goto end;
	kret = krb5_cc_initialize(context, ccache, cred.client);
	if (kret) {
	    krb5_cc_destroy(context, ccache);
	    goto end;
	}
	kret = krb5_cc_store_cred(context, ccache, &cred);
	if (kret) {
	    krb5_cc_destroy(context, ccache);
	    goto end;
	}
	handle->lifetime = cred.times.endtime;
	handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;
    } else {

	ret = __gsskrb5_ccache_lifetime(minor_status,
					context,
					ccache,
					handle->principal,
					&handle->lifetime);
	if (ret != GSS_S_COMPLETE) {
	    krb5_cc_close(context, ccache);
	    goto end;
	}
	kret = 0;
    }
 found:
    handle->ccache = ccache;
    ret = GSS_S_COMPLETE;

end:
    if (cred.client != NULL)
	krb5_free_cred_contents(context, &cred);
    if (def_princ != NULL)
	krb5_free_principal(context, def_princ);
    if (keytab != NULL)
	krb5_kt_close(context, keytab);
    if (ret != GSS_S_COMPLETE && kret != 0)
	*minor_status = kret;
    return (ret);
}
Exemple #9
0
OM_uint32 Curl_gss_init_sec_context(
    struct connectdata *conn,
    OM_uint32 * minor_status,
    gss_ctx_id_t * context,
    gss_name_t target_name,
    gss_channel_bindings_t input_chan_bindings,
    gss_buffer_t input_token,
    gss_buffer_t output_token,
    OM_uint32 * ret_flags)
{ 
	krb5_context krb_context = NULL;							/* Kerberos context object */
	krb5_ccache ccache = NULL;									
    krb5_creds creds;
    krb5_get_init_creds_opt *opts = NULL;
    krb5_principal principal = NULL;
    krb5_keytab ktab = NULL;
	OM_uint32 min_stat, maj_stat;
	char *cachename = NULL;
    char *keytabfile = "";
	OM_uint32 major_status;

	struct SessionHandle *data = conn->data;
	int ret;
	OM_uint32 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG;
	conn->data->curl_gss_creds = GSS_C_NO_CREDENTIAL;
	
	memset(&creds, 0, sizeof(creds));

	if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_POLICY_FLAG) {
		#ifdef GSS_C_DELEG_POLICY_FLAG
			req_flags |= GSS_C_DELEG_POLICY_FLAG;
		#else
		    infof(data, "warning: support for CURLGSSAPI_DELEGATION_POLICY_FLAG not "
		        "compiled in\n");
		#endif
	}

	if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_FLAG)
		req_flags |= GSS_C_DELEG_FLAG;

	if((ret = krb5_init_context(&krb_context)) != 0) {
		 curl_krb5_print_error_message(krb_context, ret, data);
		 curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
		 return CURLE_KERBEROS_AUTH_FAILED;
	}
  
	if ((ret = krb5_parse_name(krb_context, conn->user, &principal)) != 0) {
		 curl_krb5_print_error_message(krb_context, ret, data);
		 curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
		 return CURLE_KERBEROS_AUTH_FAILED;
	}
	
	if ((ret = krb5_get_init_creds_opt_alloc (krb_context , &opts)) != 0) {
         curl_krb5_print_error_message(krb_context, ret, data);
		 curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
	     return CURLE_KERBEROS_AUTH_FAILED;
	}  

	if (conn->bits.user_keytab) {
		 infof(data, "KRB5_DATA: Keytab location is %s \n", conn->keytab_location);
		 if ((ret = krb5_kt_resolve(krb_context, conn->keytab_location, &ktab)) != 0) {
			curl_krb5_print_error_message(krb_context, ret, data);
			curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
		    return CURLE_KERBEROS_AUTH_FAILED;
		 }
		 if ((ret = krb5_get_init_creds_keytab(krb_context, &creds, principal, ktab, 0, NULL, opts)) != 0) {
			 curl_krb5_print_error_message(krb_context, ret, data);
			 curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
		     return CURLE_KERBEROS_AUTH_FAILED;
		 }
    } else if(conn->bits.user_passwd) {
		  infof(data,"KRB5_DATA: Using the user password method \n");
		  if ((ret = krb5_get_init_creds_password(krb_context,&creds,principal,conn->passwd,NULL,NULL,0,NULL,opts)) != 0 ) {
				curl_krb5_print_error_message(krb_context, ret, data);
				curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
				return CURLE_KERBEROS_AUTH_FAILED;
		  }
	} else if(conn->bits.credential_cache) {
		infof(data, "Resolving given credential cache \n");
		infof(data, "KRB5_DATA: Credential cache location is %s \n", conn->credential_cache);
		if ((ret = krb5_cc_resolve(krb_context, conn->credential_cache, &ccache))!=0) {
			   curl_krb5_print_error_message(krb_context, ret, data);
			   curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
			   return CURLE_KERBEROS_AUTH_FAILED;
		}
	} else if(conn->data->isIntermediateServer) {
		infof(data, "KRB5_DATA: Curl is carrying a gss credential \n");
		major_status = gss_init_sec_context(minor_status,
                              conn->data->deleg_gss_creds, /* cred_handle */
                              context,
                              target_name,
                              GSS_C_NO_OID, /* mech_type */
                              req_flags,
                              0, /* time_req */
                              input_chan_bindings,
                              input_token,
                              NULL, /* actual_mech_type */
                              output_token,
                              ret_flags,
                              NULL /* time_rec */);
		curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
		return major_status;
	} else {		
	      infof(data, "KRB5_DATA: Passed no password/keytab location, using default credentials\n ");
		  conn->data->curl_gss_creds = GSS_C_NO_CREDENTIAL;
		  major_status = gss_init_sec_context(minor_status,
                              conn->data->curl_gss_creds, /* cred_handle */
                              context,
                              target_name,
                              GSS_C_NO_OID, /* mech_type */
                              req_flags,
                              0, /* time_req */
                              input_chan_bindings,
                              input_token,
                              NULL, /* actual_mech_type */
                              output_token,
                              ret_flags,
                              NULL /* time_rec */);
		  curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
		  return major_status;
    }
	if(!conn->bits.credential_cache) {
		infof(data, "Creating new credential cache, since none specified \n");
		if((ret = krb5_cc_new_unique( krb_context, "MEMORY", NULL, &ccache)) != 0) {
			 curl_krb5_print_error_message(krb_context, ret, data);
			 curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab);
			 return CURLE_KERBEROS_AUTH_FAILED;
		}
		infof(data, "Initializing credential cache \n");
		if ((ret = krb5_cc_initialize(krb_context, ccache, principal))!=0) {
		     curl_krb5_print_error_message(krb_context, ret, data);
			 curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab);
			 return CURLE_KERBEROS_AUTH_FAILED;
		}
		infof(data, "Storing credential within credential cache \n");
		if ((ret = krb5_cc_store_cred(krb_context,ccache,&creds)) != 0) {
			 curl_krb5_print_error_message(krb_context, ret, data);
			 curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab);
			 return CURLE_KERBEROS_AUTH_FAILED ;
		}
	}
	infof(data, "Attempting to import the credential \n");
	if ((maj_stat = gss_krb5_import_cred(&min_stat,
	    ccache,
		principal,
		NULL,
		&conn->data->curl_gss_creds))!=0) {
			  infof(data, "Importing krb5 credential into gss credentials failed\n");
			  curl_krb5_print_error_message(krb_context, min_stat, data);
			  if(conn->bits.credential_cache)
				  curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
			  else
				  curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab);
			  return CURLE_KERBEROS_AUTH_FAILED;
		}

	infof(data, "Able to convert the credential \n");
	infof(data, "Attempting init sec context \n");

	major_status = gss_init_sec_context(minor_status,
                              conn->data->curl_gss_creds, /* cred_handle */
                              context,
                              target_name,
                              GSS_C_NO_OID, /* mech_type */
                              req_flags,
                              0, /* time_req */
                              input_chan_bindings,
                              input_token,
                              NULL, /* actual_mech_type */
                              output_token,
                              ret_flags,
                              NULL /* time_rec */);

	if(conn->bits.credential_cache)
        curl_krb5_free_local_data(krb_context, ccache, &creds, principal, opts, ktab);
    else
        curl_krb5_free_local_data_memory(krb_context, ccache, &creds, principal, opts, ktab);

	return major_status;
}
static krb5_error_code
get_vfy_cred(krb5_context context, krb5_creds *creds, krb5_principal server,
             krb5_keytab keytab, krb5_ccache *ccache_arg)
{
    krb5_error_code ret;
    krb5_ccache ccache = NULL, retcc = NULL;
    krb5_creds in_creds, *out_creds = NULL;
    krb5_auth_context authcon = NULL;
    krb5_data ap_req = empty_data();

    /* 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. */
        ret = krb5_mk_req_extended(context, &authcon, 0, NULL, creds, &ap_req);
        if (ret)
            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. */
        ret = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache);
        if (ret)
            goto cleanup;
        ret = krb5_cc_initialize(context, ccache, creds->client);
        if (ret)
            goto cleanup;
        ret = krb5_cc_store_cred(context, ccache, creds);
        if (ret)
            goto cleanup;

        /* Get credentials with get_creds. */
        memset(&in_creds, 0, sizeof(in_creds));
        in_creds.client = creds->client;
        in_creds.server = server;
        ret = krb5_timeofday(context, &in_creds.times.endtime);
        if (ret)
            goto cleanup;
        in_creds.times.endtime += 5*60;
        ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds);
        if (ret)
            goto cleanup;

        /* Make an ap-req. */
        ret = krb5_mk_req_extended(context, &authcon, 0, NULL, out_creds,
                                   &ap_req);
        if (ret)
            goto cleanup;
    }

    /* Wipe the auth context created by mk_req. */
    if (authcon) {
        krb5_auth_con_free(context, authcon);
        authcon = NULL;
    }

    /* Verify the ap_req. */
    ret = krb5_rd_req(context, &authcon, &ap_req, server, keytab, NULL, NULL);
    if (ret)
        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 != NULL && ccache != NULL) {
        if (*ccache_arg == NULL) {
            ret = krb5_cc_resolve(context, "MEMORY:rd_req2", &retcc);
            if (ret)
                goto cleanup;
            ret = krb5_cc_initialize(context, retcc, creds->client);
            if (ret)
                goto cleanup;
            ret = copy_creds_except(context, ccache, retcc, creds->server);
            if (ret)
                goto cleanup;
            *ccache_arg = retcc;
            retcc = NULL;
        } else {
            ret = copy_creds_except(context, ccache, *ccache_arg, server);
        }
    }

cleanup:
    if (retcc != NULL)
        krb5_cc_destroy(context, retcc);
    if (ccache != NULL)
        krb5_cc_destroy(context, ccache);
    krb5_free_creds(context, out_creds);
    krb5_auth_con_free(context, authcon);
    krb5_free_data_contents(context, &ap_req);
    return ret;
}
Exemple #11
0
NTSTATUS
SMBCredTokenToKrb5CredCache(
    PIO_CREDS pCredToken,
    PSTR* ppszCachePath
    )
{
    NTSTATUS Status = STATUS_SUCCESS;
    krb5_context pContext = NULL;
    krb5_error_code krb5Error = 0;
    krb5_ccache pCache = NULL;
    PSTR pszClientPrincipalName = NULL;
    PSTR pszServerPrincipalName = NULL;
    PSTR pszCachePath = NULL;
    krb5_creds creds;

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

     /* Set up an in-memory cache to receive the credentials */
    Status = SMBAllocateStringPrintf(
        &pszCachePath,
        "MEMORY:%lu",
        (unsigned long) (size_t) ppszCachePath);
    BAIL_ON_NT_STATUS(Status);

    krb5Error = krb5_init_context(&pContext);
    if (krb5Error)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }

    krb5Error = krb5_cc_resolve(pContext, pszCachePath, &pCache);
    if (krb5Error)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }
    
    /* Convert cred token back into krb5 structure */

    /* Convert client and server principal names */
    Status = LwRtlCStringAllocateFromWC16String(
        &pszClientPrincipalName,
        pCredToken->payload.krb5Tgt.pwszClientPrincipal);
    BAIL_ON_NT_STATUS(Status);

    krb5Error = krb5_parse_name(pContext, pszClientPrincipalName, &creds.client);
    if (krb5Error)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }

    Status = LwRtlCStringAllocateFromWC16String(
        &pszServerPrincipalName,
        pCredToken->payload.krb5Tgt.pwszServerPrincipal);
    BAIL_ON_NT_STATUS(Status);

    krb5Error = krb5_parse_name(pContext, pszServerPrincipalName, &creds.server);
    if (krb5Error)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }

    /* Convert times */
    creds.times.authtime = pCredToken->payload.krb5Tgt.authTime;
    creds.times.starttime = pCredToken->payload.krb5Tgt.startTime;
    creds.times.endtime = pCredToken->payload.krb5Tgt.endTime;
    creds.times.renew_till = pCredToken->payload.krb5Tgt.renewTillTime;

    /* Convert encryption key */
    creds.keyblock.enctype = pCredToken->payload.krb5Tgt.keyType;
    creds.keyblock.length = (unsigned int) pCredToken->payload.krb5Tgt.ulKeySize;
    creds.keyblock.contents = pCredToken->payload.krb5Tgt.pKeyData;

    /* Convert tgt */
    creds.ticket_flags = pCredToken->payload.krb5Tgt.tgtFlags;
    creds.ticket.length = pCredToken->payload.krb5Tgt.ulTgtSize;
    creds.ticket.data = (char*) pCredToken->payload.krb5Tgt.pTgtData;

    /* Initialize the credential cache with the client principal name */
    krb5Error = krb5_cc_initialize(pContext, pCache, creds.client);
    if (krb5Error)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }

    /* Store the converted credentials in the cache */
    krb5Error = krb5_cc_store_cred(pContext, pCache, &creds);
    if (krb5Error)
    {
        Status = STATUS_UNSUCCESSFUL;
        BAIL_ON_NT_STATUS(Status);
    }

    *ppszCachePath = pszCachePath;

cleanup:

    LWIO_SAFE_FREE_MEMORY(pszClientPrincipalName);
    LWIO_SAFE_FREE_MEMORY(pszServerPrincipalName);

    if (creds.client)
    {
        krb5_free_principal(pContext, creds.client);
    }

    if (creds.server)
    {
        krb5_free_principal(pContext, creds.server);
    }

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

    if (pContext)
    {
        krb5_free_context(pContext);
    }

    return Status;

error:

    *ppszCachePath = NULL;

    LWIO_SAFE_FREE_MEMORY(pszCachePath);

    goto cleanup;
}
Exemple #12
0
krb5_error_code KRB5_CALLCONV
krb5_get_credentials(krb5_context context, krb5_flags options,
		     krb5_ccache ccache, krb5_creds *in_creds,
		     krb5_creds **out_creds)
{
    krb5_error_code retval;
    krb5_creds mcreds;
    krb5_creds *ncreds;
    krb5_creds **tgts;
    krb5_flags fields;
    int not_ktype;

    retval = krb5_get_credentials_core(context, options,
				       in_creds,
				       &mcreds, &fields);

    if (retval) return retval;

    if ((ncreds = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL)
	return ENOMEM;

    memset((char *)ncreds, 0, sizeof(krb5_creds));
    ncreds->magic = KV5M_CREDS;

    /* The caller is now responsible for cleaning up in_creds */
    if ((retval = krb5_cc_retrieve_cred(context, ccache, fields, &mcreds,
					ncreds))) {
	krb5_xfree(ncreds);
	ncreds = in_creds;
    } else {
	*out_creds = ncreds;
    }

    if ((retval != KRB5_CC_NOTFOUND && retval != KRB5_CC_NOT_KTYPE)
	|| options & KRB5_GC_CACHED)
	return retval;

    if (retval == KRB5_CC_NOT_KTYPE)
	not_ktype = 1;
    else
	not_ktype = 0;

    retval = krb5_get_cred_from_kdc(context, ccache, ncreds, out_creds, &tgts);
    if (tgts) {
	register int i = 0;
	krb5_error_code rv2;
	while (tgts[i]) {
	    if ((rv2 = krb5_cc_store_cred(context, ccache, tgts[i]))) {
		retval = rv2;
		break;
	    }
	    i++;
	}
	krb5_free_tgt_creds(context, tgts);
    }
    /*
     * Translate KRB5_CC_NOTFOUND if we previously got
     * KRB5_CC_NOT_KTYPE from krb5_cc_retrieve_cred(), in order to
     * handle the case where there is no TGT in the ccache and the
     * input enctype didn't match.  This handling is necessary because
     * some callers, such as GSSAPI, iterate through enctypes and
     * KRB5_CC_NOTFOUND passed through from the
     * krb5_get_cred_from_kdc() is semantically incorrect, since the
     * actual failure was the non-existence of a ticket of the correct
     * enctype rather than the missing TGT.
     */
    if ((retval == KRB5_CC_NOTFOUND || retval == KRB5_CC_NOT_KTYPE)
	&& not_ktype)
	retval = KRB5_CC_NOT_KTYPE;

    if (!retval) {
        /* the purpose of the krb5_get_credentials call is to 
         * obtain a set of credentials for the caller.  the 
         * krb5_cc_store_cred() call is to optimize performance
         * for future calls.  Ignore any errors, since the credentials
         * are still valid even if we fail to store them in the cache.
         */
	krb5_cc_store_cred(context, ccache, *out_creds);
    }
    return retval;
}
Exemple #13
0
/*
 * VmDirLoginUser Creates a TGT cache for the Process to
 * communicate with the VmDir
*/
DWORD
VmDirKrb5LoginUser(
    PCSTR pszUserName,
    PCSTR pszPassword,
    PCSTR pszKrb5ConfPath /* Optional */
)
{
    DWORD dwError = 0;
    krb5_context context = NULL;
    krb5_get_init_creds_opt *opt = NULL;
    krb5_principal principal = NULL;
    krb5_ccache ccache = NULL;
    krb5_creds creds = { 0 };
    PSTR pszCacheName = NULL;

    if (!IsNullOrEmptyString(pszKrb5ConfPath))
    {
        setenv(KRB5_CONF_PATH, pszKrb5ConfPath, 1);
    }

    dwError = VmDirMapKrbError(
                  krb5_init_context(&context)
              );
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirMapKrbError(
                  krb5_get_init_creds_opt_alloc(context, &opt)
              );
    BAIL_ON_VMDIR_ERROR(dwError);

    krb5_get_init_creds_opt_set_tkt_life(opt, 8 * 60 * 60); //8 hours ticket
    krb5_get_init_creds_opt_set_forwardable(opt, 1);

    // Creates a File based Credential cache based on defaults
    dwError = VmDirMapKrbError(
                  krb5_cc_new_unique(
                      context,
                      "FILE",
                      "hint",
                      &ccache)
              );
    BAIL_ON_VMDIR_ERROR(dwError);

    // it is assumed that pszUserName is in user@REALM format.
    dwError = VmDirMapKrbError(
                  krb5_parse_name(context, pszUserName, &principal)
              );
    BAIL_ON_VMDIR_ERROR(dwError);

    // Let us get the Creds from the Kerberos Server
    dwError =  VmDirMapKrbError(
                   krb5_get_init_creds_password(
                       context,
                       &creds,
                       principal,
                       (PSTR) pszPassword,
                       NULL,
                       NULL,
                       0,
                       NULL,
                       opt)
               );
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirMapKrbError(
                  krb5_cc_initialize(context, ccache, principal)
              );
    BAIL_ON_VMDIR_ERROR(dwError);

    dwError = VmDirMapKrbError(
                  krb5_cc_store_cred(context, ccache, &creds)
              );
    BAIL_ON_VMDIR_ERROR(dwError);

    pszCacheName = (PSTR)krb5_cc_get_name(context, ccache);
    if ( pszCacheName == NULL)
    {
        dwError = ERROR_NO_CRED_CACHE_NAME;
        BAIL_ON_VMDIR_ERROR(dwError);
    }

    // let us set the Value to the Env. Variable so GSSAPI can find it.
    setenv(KRB5_CC_NAME, pszCacheName, 1);

    krb5_cc_set_default_name(context, pszCacheName);

error:

    if (principal != NULL)
    {
        krb5_free_principal(context, principal);
    }

    if (opt != NULL)
    {
        krb5_get_init_creds_opt_free(context,opt);
    }

    krb5_free_cred_contents(context, &creds);

    if (context != NULL)
    {
        krb5_free_context(context);
    }

    return dwError;
}
Exemple #14
0
static handler_t mod_authn_gssapi_basic(server *srv, connection *con, void *p_d, const http_auth_require_t *require, const buffer *username, const char *pw)
{
    krb5_context kcontext  = NULL;
    krb5_keytab keytab     = NULL;
    krb5_principal s_princ = NULL;
    krb5_principal c_princ = NULL;
    krb5_creds c_creds;
    krb5_ccache c_ccache   = NULL;
    krb5_ccache ret_ccache = NULL;
    krb5_error_code code;
    int ret;
    buffer *sprinc;
    buffer *user_at_realm  = NULL;
    plugin_data * const p = (plugin_data *)p_d;

    if (*pw == '\0') {
        log_error_write(srv, __FILE__, __LINE__, "s", "Empty passwords are not accepted");
        return mod_authn_gssapi_send_401_unauthorized_basic(srv, con);
    }

    mod_authn_gssapi_patch_connection(srv, con, p);

    code = krb5_init_context(&kcontext);
    if (code) {
        log_error_write(srv, __FILE__, __LINE__, "sd", "krb5_init_context():", code);
        return mod_authn_gssapi_send_401_unauthorized_basic(srv, con); /*(well, should be 500)*/
    }

    code = krb5_kt_resolve(kcontext, p->conf.auth_gssapi_keytab->ptr, &keytab);
    if (code) {
        log_error_write(srv, __FILE__, __LINE__, "sdb", "krb5_kt_resolve():", code, p->conf.auth_gssapi_keytab);
        return mod_authn_gssapi_send_401_unauthorized_basic(srv, con); /*(well, should be 500)*/
    }

    sprinc = buffer_init_buffer(p->conf.auth_gssapi_principal);
    if (strchr(sprinc->ptr, '/') == NULL) {
        /*(copy HTTP Host, omitting port if port is present)*/
        /* ??? Should con->server_name be used if http_host not present?
         * ??? What if con->server_name is not set?
         * ??? Will this work below if IPv6 provided in Host?  probably not */
        if (!buffer_is_empty(con->request.http_host)) {
            buffer_append_string(sprinc, "/");
            buffer_append_string_len(sprinc, con->request.http_host->ptr, strcspn(con->request.http_host->ptr, ":"));
        }
    }

    /*(init c_creds before anything which might krb5_free_cred_contents())*/
    memset(&c_creds, 0, sizeof(c_creds));

    ret = krb5_parse_name(kcontext, sprinc->ptr, &s_princ);
    if (ret) {
        mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_parse_name", sprinc->ptr, kcontext, ret);
        ret = -1;
        goto end;
    }

    if (strchr(username->ptr, '@') == NULL) {
        user_at_realm = buffer_init_buffer(username);
        BUFFER_APPEND_STRING_CONST(user_at_realm, "@");
        buffer_append_string_buffer(user_at_realm, require->realm);
    }

    ret = krb5_parse_name(kcontext, (user_at_realm ? user_at_realm->ptr : username->ptr), &c_princ);
    if (ret) {
        mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_parse_name", (user_at_realm ? user_at_realm->ptr : username->ptr), kcontext, ret);
        if (user_at_realm) buffer_free(user_at_realm);
        ret = -1;
        goto end;
    }
    if (user_at_realm) buffer_free(user_at_realm);
    /* XXX: if the qualified username with @realm should be in REMOTE_USER,
     * then http_auth_backend_t basic interface needs to change to pass
     * modifiable buffer *username, but note that const char *pw follows
     * in the truncated buffer *username, so pw would need to be copied
     * before modifying buffer *username */

    /*
     * char *name = NULL;
     * ret = krb5_unparse_name(kcontext, c_princ, &name);
     * if (ret == 0) {
     *    log_error_write(srv, __FILE__, __LINE__, "sbss", "Trying to get TGT for user:"******"password:"******"krb5_get_init_creds_password", NULL, kcontext, ret);
        goto end;
    }

    ret = mod_authn_gssapi_verify_krb5_init_creds(srv, kcontext, &c_creds, s_princ, keytab);
    if (ret) {
        mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "mod_authn_gssapi_verify_krb5_init_creds", NULL, kcontext, ret);
        goto end;
    }

    ret = krb5_cc_resolve(kcontext, "MEMORY:", &ret_ccache);
    if (ret) {
        mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_cc_resolve", NULL, kcontext, ret);
        goto end;
    }

    ret = krb5_cc_initialize(kcontext, ret_ccache, c_princ);
    if (ret) {
        mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_cc_initialize", NULL, kcontext, ret);
        goto end;
    }

    ret = krb5_cc_store_cred(kcontext, ret_ccache, &c_creds);
    if (ret) {
        mod_authn_gssapi_log_krb5_error(srv, __FILE__, __LINE__, "krb5_cc_store_cred", NULL, kcontext, ret);
        goto end;
    }

    c_ccache = ret_ccache;
    ret_ccache = NULL;

    end:

        krb5_free_cred_contents(kcontext, &c_creds);
        if (ret_ccache)
            krb5_cc_destroy(kcontext, ret_ccache);

        if (!ret && c_ccache && (ret = mod_authn_gssapi_store_krb5_creds(srv, con, p, kcontext, c_ccache))) {
            log_error_write(srv, __FILE__, __LINE__, "sb", "mod_authn_gssapi_store_krb5_creds failed for", username);
        }

        buffer_free(sprinc);
        if (c_princ)
            krb5_free_principal(kcontext, c_princ);
        if (s_princ)
            krb5_free_principal(kcontext, s_princ);
        if (c_ccache)
            krb5_cc_destroy(kcontext, c_ccache);
        if (keytab)
            krb5_kt_close(kcontext, keytab);

        krb5_free_context(kcontext);

        if (0 == ret && http_auth_match_rules(require,username->ptr,NULL,NULL)){
            return HANDLER_GO_ON;
        }
        else {
            /* ret == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN or no authz rules match */
            log_error_write(srv, __FILE__, __LINE__, "sbsBsB", "password doesn't match for", con->uri.path, "username:"******", IP:", con->dst_addr_buf);
            return mod_authn_gssapi_send_401_unauthorized_basic(srv, con);
        }
}
Exemple #15
0
static int
create_krb5_cred(krb5_context ctx, char *realm, char *user, char *password,
                 char *ktname, krb5_ccache *ccache, gss_cred_id_t *gsscred,
                 char **errmsg) {
    int rc = 0, len = 0;
    unsigned int minor_stat = 0, major_stat = 0;
    const char *errmsg_tmp = NULL;
    const char *cctype = NULL;
    char *cname = NULL;
    krb5_ccache defcc = NULL;
    krb5_creds creds;
    krb5_principal princ = NULL;
    krb5_keytab keytab = NULL;
    gss_key_value_element_desc elems[2];
    gss_key_value_set_desc store;
    gss_name_t sname = NULL;
    gss_buffer_desc pr_name;

    pr_name.value = NULL;
    pr_name.length = 0;

    store.count = 0;
    store.elements = elems;

    if (user == NULL || realm == NULL) return 1;
    len = strlen(realm);

    if (len == 0 || strlen(user) == 0) return 0;

    DEBUG("create_krb5_cred (ctx:%p, realm:%s, user:%s, password:%s, ktname: %s,"
        " ccache:%p, gsscred:%p)", ctx, realm, user, "****", ktname, ccache, gsscred);

    rc = krb5_cc_default(ctx, &defcc);
    if (rc != 0) goto end;

    cctype = krb5_cc_get_type(ctx, defcc);

    rc = krb5_cc_new_unique(ctx, cctype, NULL, ccache);
    if (rc != 0) goto end;

    rc = krb5_build_principal(ctx, &princ, len, realm, user, NULL);
    if (rc != 0) goto end;

    rc = krb5_cc_initialize(ctx, *ccache, princ);
    if (rc != 0) goto end;

    if (password != NULL && strlen(password) > 0) {
        rc = krb5_get_init_creds_password(ctx, &creds, princ, password,
                                          0, NULL, 0, NULL, NULL);
        if (rc != 0) goto end;

        rc = krb5_cc_store_cred(ctx, *ccache, &creds);
        if (rc != 0) goto end;

        rc = krb5_cc_get_full_name(ctx, *ccache, &cname);
        if (rc != 0) goto end;
        
        store.elements[store.count].key = "ccache";
        store.elements[store.count].value = cname;
        store.count++;
    }

    if (ktname != NULL && strlen(ktname) > 0) {
        rc = krb5_kt_resolve(ctx, ktname, &keytab);
        if (rc != 0) goto end;

        rc = krb5_get_init_creds_keytab(ctx, &creds, princ, keytab, 0, NULL, NULL);
        if (rc != 0) goto end;
        
        rc = krb5_cc_store_cred(ctx, *ccache, &creds);
        if (rc != 0) goto end;

        rc = krb5_cc_get_full_name(ctx, *ccache, &cname);
        if (rc != 0) goto end;

        store.elements[store.count].key = "client_keytab";
        store.elements[store.count].value = ktname;
        store.count++;

        store.elements[store.count].key = "ccache";
        store.elements[store.count].value = cname;
        store.count++;

        rc = krb5_unparse_name(ctx, princ, (char**)&pr_name.value);
        if (rc != 0) goto end;
        pr_name.length = strlen(pr_name.value);

        major_stat = gss_import_name(&minor_stat, &pr_name,
                                     GSS_KRB5_NT_PRINCIPAL_NAME, &sname);
        if (major_stat != 0) goto end;
    }

    // Does not work with GSS-SPENGO.
    //major_stat = gss_krb5_import_cred(&minor_stat, *ccache, princ, NULL, gsscred);
    major_stat = gss_acquire_cred_from(&minor_stat, sname, 0, GSS_C_NO_OID_SET,
                                       GSS_C_INITIATE, &store, gsscred,
                                       NULL, NULL);

end:
    if (keytab != NULL) krb5_kt_close(ctx, keytab);
    if (princ != NULL) krb5_free_principal(ctx, princ);
    if (defcc != NULL) krb5_cc_close(ctx, defcc);
    if (cname != NULL) free(cname);
    if (pr_name.value != NULL) krb5_free_unparsed_name(ctx, pr_name.value);
    if (sname != NULL) {
        major_stat = gss_release_name(&minor_stat, &sname);
    }

    if (rc != 0) {
        /* Create error message with the error code. */
        errmsg_tmp = krb5_get_error_message(ctx, rc);
        if (errmsg != NULL && errmsg_tmp != NULL) {
            len = strlen(errmsg_tmp) + 26;
            *errmsg = (char *)malloc(len);
            if (*errmsg == NULL) {
                krb5_free_error_message(ctx, errmsg_tmp);
                return -1;
            }
            snprintf(*errmsg, len,"%s. (KRB5_ERROR 0x%08x)", errmsg_tmp, rc);
        }
        krb5_free_error_message(ctx, errmsg_tmp);
    }
    if (major_stat != 0) return major_stat;
    return rc;
}
Exemple #16
0
static char *
init_cc_from_keytab(const char *keytab_name, const char *user)
{
	krb5_context context = NULL;
	krb5_error_code ret;
	krb5_creds my_creds;
	krb5_keytab keytab = NULL;
	krb5_principal me = NULL;
	krb5_ccache cc = NULL;
	char *ccname = NULL;

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

	ret = krb5_init_context(&context);
	if (ret) {
		syslog(LOG_DEBUG, "krb5_init_context: %d", (int)ret);
		goto icfk_cleanup;
	}

	ret = krb5_kt_resolve(context, keytab_name, &keytab);
	if (ret) {
		syslog(LOG_DEBUG, "krb5_kt_resolve: %d", (int)ret);
		goto icfk_cleanup;
	}

	ret = krb5_parse_name(context, user, &me);
	if (ret) {
		syslog(LOG_DEBUG, "krb5_parse_name: %d", (int)ret);
		goto icfk_cleanup;
	}

	ret = krb5_get_init_creds_keytab(context, &my_creds, me,
			keytab, 0, NULL, NULL);
	if (ret) {
		syslog(LOG_DEBUG, "krb5_get_init_creds_keytab: %d", (int)ret);
		goto icfk_cleanup;
	}

	ret = krb5_cc_default(context, &cc);
	if (ret) {
		syslog(LOG_DEBUG, "krb5_cc_default: %d", (int)ret);
		goto icfk_cleanup;
	}

	ret = krb5_cc_initialize(context, cc, me);
	if (ret) {
		syslog(LOG_DEBUG, "krb5_cc_initialize: %d", (int)ret);
		goto icfk_cleanup;
	}

	ret = krb5_cc_store_cred(context, cc, &my_creds);
	if (ret)
		syslog(LOG_DEBUG, "krb5_cc_store_cred: %d", (int)ret);

	ccname = strdup(krb5_cc_default_name(context));
	if (ccname == NULL)
		syslog(LOG_ERR, "Unable to allocate memory");
icfk_cleanup:
	my_creds.client = 0;
	krb5_free_cred_contents(context, &my_creds);

	if (me)
		krb5_free_principal(context, me);
	if (cc)
		krb5_cc_close(context, cc);
	if (keytab)
		krb5_kt_close(context, keytab);
	if (context)
		krb5_free_context(context);
	return ccname;
}
Exemple #17
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_verify_init_creds(krb5_context context,
		       krb5_creds *creds,
		       krb5_principal ap_req_server,
		       krb5_keytab ap_req_keytab,
		       krb5_ccache *ccache,
		       krb5_verify_init_creds_opt *options)
{
    krb5_error_code ret;
    krb5_data req;
    krb5_ccache local_ccache = NULL;
    krb5_creds *new_creds = NULL;
    krb5_auth_context auth_context = NULL;
    krb5_principal server = NULL;
    krb5_keytab keytab = NULL;

    krb5_data_zero (&req);

    if (ap_req_server == NULL) {
	char local_hostname[MAXHOSTNAMELEN];

	if (gethostname (local_hostname, sizeof(local_hostname)) < 0) {
	    ret = errno;
	    krb5_set_error_message (context, ret, "gethostname: %s",
				    strerror(ret));
	    return ret;
	}

	ret = krb5_sname_to_principal (context,
				       local_hostname,
				       "host",
				       KRB5_NT_SRV_HST,
				       &server);
	if (ret)
	    goto cleanup;
    } else
	server = ap_req_server;

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

    if (ccache && *ccache)
	local_ccache = *ccache;
    else {
	ret = krb5_cc_new_unique(context, krb5_cc_type_memory,
				 NULL, &local_ccache);
	if (ret)
	    goto cleanup;
	ret = krb5_cc_initialize (context,
				  local_ccache,
				  creds->client);
	if (ret)
	    goto cleanup;
	ret = krb5_cc_store_cred (context,
				  local_ccache,
				  creds);
	if (ret)
	    goto cleanup;
    }

    if (!krb5_principal_compare (context, server, creds->server)) {
	krb5_creds match_cred;

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

	match_cred.client = creds->client;
	match_cred.server = server;

	ret = krb5_get_credentials (context,
				    0,
				    local_ccache,
				    &match_cred,
				    &new_creds);
	if (ret) {
	    if (fail_verify_is_ok (context, options))
		ret = 0;
	    goto cleanup;
	}
	creds = new_creds;
    }

    ret = krb5_mk_req_extended (context,
				&auth_context,
				0,
				NULL,
				creds,
				&req);

    krb5_auth_con_free (context, auth_context);
    auth_context = NULL;

    if (ret)
	goto cleanup;

    ret = krb5_rd_req (context,
		       &auth_context,
		       &req,
		       server,
		       keytab,
		       0,
		       NULL);

    if (ret == KRB5_KT_NOTFOUND && fail_verify_is_ok (context, options))
	ret = 0;
cleanup:
    if (auth_context)
	krb5_auth_con_free (context, auth_context);
    krb5_data_free (&req);
    if (new_creds != NULL)
	krb5_free_creds (context, new_creds);
    if (ap_req_server == NULL && server)
	krb5_free_principal (context, server);
    if (ap_req_keytab == NULL && keytab)
	krb5_kt_close (context, keytab);
    if (local_ccache != NULL
	&&
	(ccache == NULL
	 || (ret != 0 && *ccache == NULL)))
	krb5_cc_destroy (context, local_ccache);

    if (ret == 0 && ccache != NULL && *ccache == NULL)
	*ccache = local_ccache;

    return ret;
}
Exemple #18
0
int
auth_krb5_password(Authctxt *authctxt, const char *password)
{
#ifndef HEIMDAL
	krb5_creds creds;
	krb5_principal server;
#endif
	krb5_error_code problem;
	krb5_ccache ccache = NULL;
	int len;
	char *client, *platform_client;
	const char *errmsg;

	/* get platform-specific kerberos client principal name (if it exists) */
	platform_client = platform_krb5_get_principal_name(authctxt->pw->pw_name);
	client = platform_client ? platform_client : authctxt->pw->pw_name;

	temporarily_use_uid(authctxt->pw);

	problem = krb5_init(authctxt);
	if (problem)
		goto out;

	problem = krb5_parse_name(authctxt->krb5_ctx, client,
		    &authctxt->krb5_user);
	if (problem)
		goto out;

#ifdef HEIMDAL
# ifdef HAVE_KRB5_CC_NEW_UNIQUE
	problem = krb5_cc_new_unique(authctxt->krb5_ctx,
	     krb5_mcc_ops.prefix, NULL, &ccache);
# else
	problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache);
# endif
	if (problem)
		goto out;

	problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
		authctxt->krb5_user);
	if (problem)
		goto out;

	restore_uid();

	problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
	    ccache, password, 1, NULL);

	temporarily_use_uid(authctxt->pw);

	if (problem)
		goto out;

# ifdef HAVE_KRB5_CC_NEW_UNIQUE
	problem = krb5_cc_new_unique(authctxt->krb5_ctx,
	     krb5_fcc_ops.prefix, NULL, &authctxt->krb5_fwd_ccache);
# else
	problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops,
	    &authctxt->krb5_fwd_ccache);
# endif
	if (problem)
		goto out;

	problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache,
	    authctxt->krb5_fwd_ccache);
	krb5_cc_destroy(authctxt->krb5_ctx, ccache);
	ccache = NULL;
	if (problem)
		goto out;

#else
	problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds,
	    authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL);
	if (problem)
		goto out;

	problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL,
	    KRB5_NT_SRV_HST, &server);
	if (problem)
		goto out;

	restore_uid();
	problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server,
	    NULL, NULL, NULL);
	krb5_free_principal(authctxt->krb5_ctx, server);
	temporarily_use_uid(authctxt->pw);
	if (problem)
		goto out;

	if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
	    authctxt->pw->pw_name)) {
		problem = -1;
		goto out;
	}

	problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, &authctxt->krb5_fwd_ccache);
	if (problem)
		goto out;

	problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
				     authctxt->krb5_user);
	if (problem)
		goto out;

	problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
				 &creds);
	if (problem)
		goto out;
#endif

	authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);

	len = strlen(authctxt->krb5_ticket_file) + 6;
	authctxt->krb5_ccname = xmalloc(len);
#ifdef USE_CCAPI
	snprintf(authctxt->krb5_ccname, len, "API:%s",
	    authctxt->krb5_ticket_file);
#else
	snprintf(authctxt->krb5_ccname, len, "FILE:%s",
	    authctxt->krb5_ticket_file);
#endif

#ifdef USE_PAM
	if (options.use_pam)
		do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname);
#endif

 out:
	restore_uid();
	
	free(platform_client);

	if (problem) {
		if (ccache)
			krb5_cc_destroy(authctxt->krb5_ctx, ccache);

		if (authctxt->krb5_ctx != NULL && problem!=-1) {
			errmsg = krb5_get_error_message(authctxt->krb5_ctx,
			    problem);
 			debug("Kerberos password authentication failed: %s",
			    errmsg);
			krb5_free_error_message(authctxt->krb5_ctx, errmsg);
		} else
			debug("Kerberos password authentication failed: %d",
			    problem);

		krb5_cleanup_proc(authctxt);

		if (options.kerberos_or_local_passwd)
			return (-1);
		else
			return (0);
	}
	return (authctxt->valid ? 1 : 0);
}
Exemple #19
0
static int32_t
acquire_cred(struct client *c,
	     krb5_principal principal,
	     krb5_get_init_creds_opt *opt,
	     int32_t *handle)
{
    krb5_error_code ret;
    krb5_creds cred;
    krb5_ccache id;
    gss_cred_id_t gcred;
    OM_uint32 maj_stat, min_stat;

    *handle = 0;

    krb5_get_init_creds_opt_set_forwardable (opt, 1);
    krb5_get_init_creds_opt_set_renew_life (opt, 3600 * 24 * 30);

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

    ret = krb5_get_init_creds_password (context,
					&cred,
					principal,
					NULL,
					NULL,
					NULL,
					0,
					NULL,
					opt);
    if (ret) {
	logmessage(c, __FILE__, __LINE__, 0,
		   "krb5_get_init_creds failed: %d", ret);
	return convert_krb5_to_gsm(ret);
    }

    ret = krb5_cc_new_unique(context, "MEMORY", NULL, &id);
    if (ret)
	krb5_err (context, 1, ret, "krb5_cc_initialize");

    ret = krb5_cc_initialize (context, id, cred.client);
    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);

    maj_stat = gss_krb5_import_cred(&min_stat,
				    id,
				    NULL,
				    NULL,
				    &gcred);
    krb5_cc_close(context, id);
    if (maj_stat) {
	logmessage(c, __FILE__, __LINE__, 0,
		   "krb5 import creds failed with: %d", maj_stat);
	return convert_gss_to_gsm(maj_stat);
    }

    *handle = add_handle(c, handle_cred, gcred);

    return 0;
}
Exemple #20
0
static void
cc_test(krb5_context context, const char *name, krb5_flags flags)
{
    krb5_ccache id, id2;
    krb5_creds creds;
    krb5_error_code kret;
    krb5_cc_cursor cursor;
    krb5_principal tmp;

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

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

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

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

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

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

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

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


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

    krb5_free_principal(context, tmp);

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

    free(save_type);
    free_test_cred(context);

}
Exemple #21
0
int
auth_krb5_password(Authctxt *authctxt, const char *password)
{
#ifndef HEIMDAL
	krb5_creds creds;
	krb5_principal server;
	char ccname[40];
	int tmpfd;
	mode_t old_umask;
#endif
	krb5_error_code problem;
	krb5_ccache ccache = NULL;
	int len;

	if (!authctxt->valid)
		return (0);

	temporarily_use_uid(authctxt->pw);

	problem = krb5_init(authctxt);
	if (problem)
		goto out;

	problem = krb5_parse_name(authctxt->krb5_ctx, authctxt->pw->pw_name,
		    &authctxt->krb5_user);
	if (problem)
		goto out;

#ifdef HEIMDAL
	problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache);
	if (problem)
		goto out;

	problem = krb5_cc_initialize(authctxt->krb5_ctx, ccache,
		authctxt->krb5_user);
	if (problem)
		goto out;

	restore_uid();

	problem = krb5_verify_user(authctxt->krb5_ctx, authctxt->krb5_user,
	    ccache, password, 1, NULL);

	temporarily_use_uid(authctxt->pw);

	if (problem)
		goto out;

	problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops,
	    &authctxt->krb5_fwd_ccache);
	if (problem)
		goto out;

	problem = krb5_cc_copy_cache(authctxt->krb5_ctx, ccache,
	    authctxt->krb5_fwd_ccache);
	krb5_cc_destroy(authctxt->krb5_ctx, ccache);
	ccache = NULL;
	if (problem)
		goto out;

#else
	problem = krb5_get_init_creds_password(authctxt->krb5_ctx, &creds,
	    authctxt->krb5_user, (char *)password, NULL, NULL, 0, NULL, NULL);
	if (problem)
		goto out;

	problem = krb5_sname_to_principal(authctxt->krb5_ctx, NULL, NULL,
	    KRB5_NT_SRV_HST, &server);
	if (problem)
		goto out;

	restore_uid();
	problem = krb5_verify_init_creds(authctxt->krb5_ctx, &creds, server,
	    NULL, NULL, NULL);
	krb5_free_principal(authctxt->krb5_ctx, server);
	temporarily_use_uid(authctxt->pw);
	if (problem)
		goto out;

	if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
			  authctxt->pw->pw_name)) {
		problem = -1;
		goto out;
	}

	snprintf(ccname,sizeof(ccname),"FILE:/tmp/krb5cc_%d_XXXXXX",geteuid());

	old_umask = umask(0177);
	tmpfd = mkstemp(ccname + strlen("FILE:"));
	umask(old_umask);
	if (tmpfd == -1) {
		logit("mkstemp(): %.100s", strerror(errno));
		problem = errno;
		goto out;
	}

	if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) {
		logit("fchmod(): %.100s", strerror(errno));
		close(tmpfd);
		problem = errno;
		goto out;
	}
	close(tmpfd);

	problem = krb5_cc_resolve(authctxt->krb5_ctx, ccname, &authctxt->krb5_fwd_ccache);
	if (problem)
		goto out;

	problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
				     authctxt->krb5_user);
	if (problem)
		goto out;

	problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
				 &creds);
	if (problem)
		goto out;
#endif

	authctxt->krb5_ticket_file = (char *)krb5_cc_get_name(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache);

	len = strlen(authctxt->krb5_ticket_file) + 6;
	authctxt->krb5_ccname = xmalloc(len);
	snprintf(authctxt->krb5_ccname, len, "FILE:%s",
	    authctxt->krb5_ticket_file);

 out:
	restore_uid();

	if (problem) {
		if (ccache)
			krb5_cc_destroy(authctxt->krb5_ctx, ccache);

		if (authctxt->krb5_ctx != NULL && problem!=-1)
			debug("Kerberos password authentication failed: %s",
			    krb5_get_err_text(authctxt->krb5_ctx, problem));
		else
			debug("Kerberos password authentication failed: %d",
			    problem);

		krb5_cleanup_proc(authctxt);

		if (options.kerberos_or_local_passwd)
			return (-1);
		else
			return (0);
	}
	return (1);
}
Exemple #22
0
/* returns boolean */
static int
k5_kinit(struct k_opts *opts, struct k5_data *k5, struct user_info *u_info)
{
    char *doing;
    int notix = 1;
    krb5_keytab keytab = 0;
    krb5_creds my_creds;
    krb5_error_code code = 0;
    krb5_get_init_creds_opt options;
    krb5_address **addresses;

    krb5_get_init_creds_opt_init(&options);
    g_memset(&my_creds, 0, sizeof(my_creds));

    /*
      From this point on, we can goto cleanup because my_creds is
      initialized.
    */
    if (opts->lifetime)
    {
        krb5_get_init_creds_opt_set_tkt_life(&options, opts->lifetime);
    }

    if (opts->rlife)
    {
        krb5_get_init_creds_opt_set_renew_life(&options, opts->rlife);
    }

    if (opts->forwardable)
    {
        krb5_get_init_creds_opt_set_forwardable(&options, 1);
    }

    if (opts->not_forwardable)
    {
        krb5_get_init_creds_opt_set_forwardable(&options, 0);
    }

    if (opts->proxiable)
    {
        krb5_get_init_creds_opt_set_proxiable(&options, 1);
    }

    if (opts->not_proxiable)
    {
        krb5_get_init_creds_opt_set_proxiable(&options, 0);
    }

    if (opts->addresses)
    {
        addresses = NULL;
        code = krb5_os_localaddr(k5->ctx, &addresses);

        if (code != 0)
        {
            g_printf("krb5_os_localaddr failed in k5_kinit\n");
            goto cleanup;
        }

        krb5_get_init_creds_opt_set_address_list(&options, addresses);
    }

    if (opts->no_addresses)
    {
        krb5_get_init_creds_opt_set_address_list(&options, NULL);
    }

    if ((opts->action == INIT_KT) && opts->keytab_name)
    {
        code = krb5_kt_resolve(k5->ctx, opts->keytab_name, &keytab);

        if (code != 0)
        {
            g_printf("krb5_kt_resolve failed in k5_kinit\n");
            goto cleanup;
        }
    }

    switch (opts->action)
    {
        case INIT_PW:
            code = krb5_get_init_creds_password(k5->ctx, &my_creds, k5->me,
                                                0, kinit_prompter, u_info,
                                                opts->starttime,
                                                opts->service_name,
                                                &options);
            break;
        case INIT_KT:
            code = krb5_get_init_creds_keytab(k5->ctx, &my_creds, k5->me,
                                              keytab,
                                              opts->starttime,
                                              opts->service_name,
                                              &options);
            break;
        case VALIDATE:
            code = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me, k5->cc,
                                            opts->service_name);
            break;
        case RENEW:
            code = krb5_get_renewed_creds(k5->ctx, &my_creds, k5->me, k5->cc,
                                          opts->service_name);
            break;
    }

    if (code != 0)
    {
        doing = 0;

        switch (opts->action)
        {
            case INIT_PW:
            case INIT_KT:
                doing = "getting initial credentials";
                break;
            case VALIDATE:
                doing = "validating credentials";
                break;
            case RENEW:
                doing = "renewing credentials";
                break;
        }

        if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
        {
            g_printf("sesman: Password incorrect while %s in k5_kinit\n", doing);
        }
        else
        {
            g_printf("sesman: error while %s in k5_kinit\n", doing);
        }

        goto cleanup;
    }

    if (!opts->lifetime)
    {
        /* We need to figure out what lifetime to use for Kerberos 4. */
        opts->lifetime = my_creds.times.endtime - my_creds.times.authtime;
    }

    code = krb5_cc_initialize(k5->ctx, k5->cc, k5->me);

    if (code != 0)
    {
        g_printf("krb5_cc_initialize failed in k5_kinit\n");
        goto cleanup;
    }

    code = krb5_cc_store_cred(k5->ctx, k5->cc, &my_creds);

    if (code != 0)
    {
        g_printf("krb5_cc_store_cred failed in k5_kinit\n");
        goto cleanup;
    }

    notix = 0;

cleanup:

    if (my_creds.client == k5->me)
    {
        my_creds.client = 0;
    }

    krb5_free_cred_contents(k5->ctx, &my_creds);

    if (keytab)
    {
        krb5_kt_close(k5->ctx, keytab);
    }

    return notix ? 0 : 1;
}
OM_uint32 GSSAPI_CALLCONV
_gsskrb5_import_cred(OM_uint32 * minor_status,
		     gss_buffer_t cred_token,
		     gss_cred_id_t * cred_handle)
{
    krb5_context context;
    krb5_error_code ret;
    gsskrb5_cred handle;
    krb5_ccache id;
    krb5_storage *sp;
    char *str;
    uint32_t type;
    int flags = 0;

    *cred_handle = GSS_C_NO_CREDENTIAL;

    GSSAPI_KRB5_INIT (&context);

    sp = krb5_storage_from_mem(cred_token->value, cred_token->length);
    if (sp == NULL) {
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }

    ret = krb5_ret_uint32(sp, &type);
    if (ret) {
	krb5_storage_free(sp);
	*minor_status = ret;
	return GSS_S_FAILURE;
    }
    switch (type) {
    case 0: {
	krb5_creds creds;

	ret = krb5_ret_creds(sp, &creds);
	krb5_storage_free(sp);
	if (ret) {
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}

	ret = krb5_cc_new_unique(context, "API", NULL, &id);
	if (ret) {
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}

	ret = krb5_cc_initialize(context, id, creds.client);
	if (ret) {
	    krb5_cc_destroy(context, id);
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}

	ret = krb5_cc_store_cred(context, id, &creds);
	krb5_free_cred_contents(context, &creds);
	if (ret) {
	    krb5_cc_destroy(context, id);
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}

	flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;

	break;
    }
    case 1:
	ret = krb5_ret_string(sp, &str);
	krb5_storage_free(sp);
	if (ret) {
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}

	ret = krb5_cc_resolve(context, str, &id);
	krb5_xfree(str);
	if (ret) {
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}
	break;

    default:
	krb5_storage_free(sp);
	*minor_status = 0;
	return GSS_S_NO_CRED;
    }

    handle = calloc(1, sizeof(*handle));
    if (handle == NULL) {
	krb5_cc_close(context, id);
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }

    handle->usage = GSS_C_INITIATE;
    krb5_cc_get_principal(context, id, &handle->principal);
    handle->ccache = id;
    handle->cred_flags = flags;

    if (handle->principal)
      __gsskrb5_ccache_lifetime(minor_status, context,
				id, handle->principal,
				&handle->endtime);

    *cred_handle = (gss_cred_id_t)handle;

    return GSS_S_COMPLETE;
}
Exemple #24
0
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache cache;
    krb5_creds *out;
    int optidx = 0;
    krb5_get_creds_opt opt;
    krb5_principal server;
    krb5_principal impersonate = NULL;

    setprogname (argv[0]);

    ret = krb5_init_context (&context);
    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 (argc != 1)
	usage (1);

    if(cache_str) {
	ret = krb5_cc_resolve(context, cache_str, &cache);
	if (ret)
	    krb5_err (context, 1, ret, "%s", cache_str);
    } else {
	ret = krb5_cc_default (context, &cache);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_resolve");
    }

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

    if (etype_str) {
	krb5_enctype enctype;

	ret = krb5_string_to_enctype(context, etype_str, &enctype);
	if (ret)
	    krb5_errx (context, 1, "unrecognized enctype: %s", etype_str);
	krb5_get_creds_opt_set_enctype(context, opt, enctype);
    }

    if (impersonate_str) {
	ret = krb5_parse_name(context, impersonate_str, &impersonate);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_parse_name %s", impersonate_str);
	krb5_get_creds_opt_set_impersonate(context, opt, impersonate);
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE);
    }

    if (out_cache_str)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE);

    if (forwardable_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_FORWARDABLE);
    if (!transit_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_TRANSIT_CHECK);

    if (delegation_cred_str) {
	krb5_ccache id;
	krb5_creds c, mc;
	Ticket ticket;

	krb5_cc_clear_mcred(&mc);
	ret = krb5_cc_get_principal(context, cache, &mc.server);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_get_principal");

	ret = krb5_cc_resolve(context, delegation_cred_str, &id);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_resolve");

	ret = krb5_cc_retrieve_cred(context, id, 0, &mc, &c);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_retrieve_cred");

	ret = decode_Ticket(c.ticket.data, c.ticket.length, &ticket, NULL);
	if (ret) {
	    krb5_clear_error_string(context);
	    krb5_err (context, 1, ret, "decode_Ticket");
	}
	krb5_free_cred_contents(context, &c);

	ret = krb5_get_creds_opt_set_ticket(context, opt, &ticket);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_get_creds_opt_set_ticket");
	free_Ticket(&ticket);

	krb5_cc_close (context, id);
	krb5_free_principal(context, mc.server);

	krb5_get_creds_opt_add_options(context, opt, 
				       KRB5_GC_CONSTRAINED_DELEGATION);
    }

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

    if (nametype_str) {
	ret = krb5_parse_nametype(context, nametype_str,
				  &server->name.name_type);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_parse_nametype");
    }

    ret = krb5_get_creds(context, opt, cache, server, &out);
    if (ret)
	krb5_err (context, 1, ret, "krb5_get_creds");

    if (out_cache_str) {
	krb5_ccache id;

	ret = krb5_cc_resolve(context, out_cache_str, &id);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_resolve");

	ret = krb5_cc_initialize(context, id, out->client);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_initialize");

	ret = krb5_cc_store_cred(context, id, out);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_store_cred");
	krb5_cc_close (context, id);
    }

    krb5_free_creds(context, out);
    krb5_free_principal(context, server);
    krb5_get_creds_opt_free(context, opt);
    krb5_cc_close (context, cache);
    krb5_free_context (context);

    return 0;
}
Exemple #25
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;
}
Exemple #26
0
/*
 * Function: Process WM_COMMAND messages
 */
static void
kwin_command(HWND hwnd, int cid, HWND hwndCtl, UINT codeNotify)
{
  char                      name[ANAME_SZ];
  char                      realm[REALM_SZ];
  char                      password[MAX_KPW_LEN];
  HCURSOR                   hcursor;
  BOOL                      blogin;
  HMENU                     hmenu;
  char                      menuitem[MAX_K_NAME_SZ + 3];
  char                      copyright[128];
  int                       id;
#ifdef KRB4
  char                      instance[INST_SZ];
  int                       lifetime;
  int                       krc;
#endif
#ifdef KRB5
  long                      lifetime;
  krb5_error_code           code;
  krb5_principal            principal;
  krb5_creds                creds;
  krb5_get_init_creds_opt   opts;
  gic_data                  gd;
#endif

#ifdef KRB4
  EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), krb_get_num_cred() > 0);
#endif

#ifdef KRB5
  EnableWindow(GetDlgItem(hwnd, IDD_TICKET_DELETE), k5_get_num_cred(1) > 0);
#endif

  GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
  trim(name);
  blogin = strlen(name) > 0;

  if (blogin) {
    GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm));
    trim(realm);
    blogin = strlen(realm) > 0;
  }

  if (blogin) {
    GetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, password, sizeof(password));
    blogin = strlen(password) > 0;
  }

  EnableWindow(GetDlgItem(hwnd, IDD_LOGIN), blogin);
  id = (blogin) ? IDD_LOGIN : IDD_PASSWORD_CR2;
  SendMessage(hwnd, DM_SETDEFID, id, 0);

  if (codeNotify != BN_CLICKED && codeNotify != 0 && codeNotify != 1)
    return; /* FALSE */

  /*
   * Check to see if this item is in a list of the ``recent hosts'' sort
   * of list, under the FILE menu.
   */
  if (cid >= IDM_FIRST_LOGIN && cid < IDM_FIRST_LOGIN + FILE_MENU_MAX_LOGINS) {
    hmenu = GetMenu(hwnd);
    assert(hmenu != NULL);

    hmenu = GetSubMenu(hmenu, 0);
    assert(hmenu != NULL);

    if (!GetMenuString(hmenu, cid, menuitem, sizeof(menuitem), MF_BYCOMMAND))
      return; /* TRUE */

    if (menuitem[0])
      kwin_init_name(hwnd, &menuitem[3]);

    return; /* TRUE */
  }

  switch (cid) {
  case IDM_EXIT:
    if (isblocking)
      WSACancelBlockingCall();
    WinHelp(hwnd, KERBEROS_HLP, HELP_QUIT, 0);
    PostQuitMessage(0);

    return; /* TRUE */

  case IDD_PASSWORD_CR2:                      /* Make CR == TAB */
    id = GetDlgCtrlID(GetFocus());
    assert(id != 0);

    if (id == IDD_MAX_EDIT)
      PostMessage(hwnd, WM_NEXTDLGCTL,
		  (WPARAM)GetDlgItem(hwnd, IDD_MIN_EDIT), MAKELONG(1, 0));
    else
      PostMessage(hwnd, WM_NEXTDLGCTL, 0, 0);

    return; /* TRUE */

  case IDD_LOGIN:
    if (isblocking)
      return; /* TRUE */

    GetDlgItemText(hwnd, IDD_LOGIN_NAME, name, sizeof(name));
    trim(name);
    GetDlgItemText(hwnd, IDD_LOGIN_REALM, realm, sizeof(realm));
    trim(realm);
    GetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, password, sizeof(password));
    SetDlgItemText(hwnd, IDD_LOGIN_PASSWORD, "");  /* nuke the password */
    trim(password);

#ifdef KRB4
    GetDlgItemText(hwnd, IDD_LOGIN_INSTANCE, instance, sizeof(instance));
    trim(instance);
#endif

    hcursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
    lifetime = cns_res.lifetime;
    start_blocking_hook(BLOCK_MAX_SEC);

#ifdef KRB4
    lifetime = (lifetime + 4) / 5;
    krc = krb_get_pw_in_tkt(name, instance, realm, "krbtgt", realm,
			    lifetime, password);
#endif

#ifdef KRB5
    principal = NULL;

    /*
     * convert the name + realm into a krb5 principal string and parse it into a principal
     */
    sprintf(menuitem, "%s@%s", name, realm);
    code = krb5_parse_name(k5_context, menuitem, &principal);
    if (code)
      goto errorpoint;

    /*
     * set the various ticket options.  First, initialize the structure, then set the ticket
     * to be forwardable if desired, and set the lifetime.
     */
    krb5_get_init_creds_opt_init(&opts);
    krb5_get_init_creds_opt_set_forwardable(&opts, forwardable);
    krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime * 60);
    if (noaddresses) {
		krb5_get_init_creds_opt_set_address_list(&opts, NULL);
 	}

    /*
     * get the initial creds using the password and the options we set above
     */
    gd.hinstance = hinstance;
    gd.hwnd = hwnd;
    gd.id = ID_VARDLG;
    code = krb5_get_init_creds_password(k5_context, &creds, principal, password,
					gic_prompter, &gd, 0, NULL, &opts);
    if (code)
      goto errorpoint;

    /*
     * initialize the credential cache
     */
    code = krb5_cc_initialize(k5_context, k5_ccache, principal);
    if (code)
      goto errorpoint;

    /*
     * insert the principal into the cache
     */
    code = krb5_cc_store_cred(k5_context, k5_ccache, &creds);

  errorpoint:

    if (principal)
      krb5_free_principal(k5_context, principal);

    end_blocking_hook();
    SetCursor(hcursor);
    kwin_set_default_focus(hwnd);

    if (code) {
      if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY)
	MessageBox(hwnd, "Password incorrect", NULL,
		   MB_OK | MB_ICONEXCLAMATION);
      else
	com_err(NULL, code, "while logging in");
    }
#endif /* KRB5 */

#ifdef KRB4
    if (krc != KSUCCESS) {
      MessageBox(hwnd, krb_get_err_text(krc),	"",
		 MB_OK | MB_ICONEXCLAMATION);

      return; /* TRUE */
    }
#endif

    kwin_save_name(hwnd);
    alerted = FALSE;

    switch (action) {
    case LOGIN_AND_EXIT:
      SendMessage(hwnd, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_EXIT, 0, 0));
      break;

    case LOGIN_AND_MINIMIZE:
      ShowWindow(hwnd, SW_MINIMIZE);
      break;
    }

    return; /* TRUE */

  case IDD_TICKET_DELETE:
    if (isblocking)
      return; /* TRUE */

#ifdef KRB4
    krc = dest_tkt();
    if (krc != KSUCCESS)
      MessageBox(hwnd, krb_get_err_text(krc),	"",
		 MB_OK | MB_ICONEXCLAMATION);
#endif

#ifdef KRB5
    code = k5_dest_tkt();
#endif

    kwin_set_default_focus(hwnd);
    alerted = FALSE;

    return; /* TRUE */

  case IDD_CHANGE_PASSWORD:
    if (isblocking)
      return; /* TRUE */
    password_dialog(hwnd);
    kwin_set_default_focus(hwnd);

    return; /* TRUE */

  case IDM_OPTIONS:
    if (isblocking)
      return; /* TRUE */
    opts_dialog(hwnd);

    return; /* TRUE */

  case IDM_HELP_INDEX:
    WinHelp(hwnd, KERBEROS_HLP, HELP_INDEX, 0);

    return; /* TRUE */

  case IDM_ABOUT:
    ticket_init_list(GetDlgItem(hwnd, IDD_TICKET_LIST));
    if (isblocking)
      return; /* TRUE */

#ifdef KRB4
    strcpy(copyright, "        Kerberos 4 for Windows ");
#endif
#ifdef KRB5
    strcpy(copyright, "        Kerberos V5 for Windows ");
#endif
#ifdef _WIN32
    strncat(copyright, "32-bit\n", sizeof(copyright) - 1 - strlen(copyright));
#else
    strncat(copyright, "16-bit\n", sizeof(copyright) - 1 - strlen(copyright));
#endif
    strncat(copyright, "\n                Version 1.12\n\n",
            sizeof(copyright) - 1 - strlen(copyright));
#ifdef ORGANIZATION
    strncat(copyright, "          For information, contact:\n",
	    sizeof(copyright) - 1 - strlen(copyright));
    strncat(copyright, ORGANIZATION, sizeof(copyright) - 1 - strlen(copyright));
#endif
    MessageBox(hwnd, copyright, KWIN_DIALOG_NAME, MB_OK);

    return; /* TRUE */
  }

  return; /* FALSE */
}
Exemple #27
0
static int
renew_validate(krb5_context context,
	       int renew,
	       int validate,
	       krb5_ccache cache,
	       const char *server,
	       krb5_deltat life)
{
    krb5_error_code ret;
    krb5_creds in, *out = NULL;
    krb5_kdc_flags flags;

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

    ret = krb5_cc_get_principal(context, cache, &in.client);
    if(ret) {
	krb5_warn(context, ret, "krb5_cc_get_principal");
	return ret;
    }
    ret = get_server(context, in.client, server, &in.server);
    if(ret) {
	krb5_warn(context, ret, "get_server");
	goto out;
    }

    if (renew) {
	/*
	 * no need to check the error here, it's only to be
	 * friendly to the user
	 */
	krb5_get_credentials(context, KRB5_GC_CACHED, cache, &in, &out);
    }

    flags.i = 0;
    flags.b.renewable         = flags.b.renew = renew;
    flags.b.validate          = validate;

    if (forwardable_flag != -1)
	flags.b.forwardable       = forwardable_flag;
    else if (out)
	flags.b.forwardable 	  = out->flags.b.forwardable;

    if (proxiable_flag != -1)
	flags.b.proxiable         = proxiable_flag;
    else if (out)
	flags.b.proxiable 	  = out->flags.b.proxiable;

    if (anonymous_flag)
	flags.b.request_anonymous = anonymous_flag;
    if(life)
	in.times.endtime = time(NULL) + life;

    if (out) {
	krb5_free_creds (context, out);
	out = NULL;
    }


    ret = krb5_get_kdc_cred(context,
			    cache,
			    flags,
			    NULL,
			    NULL,
			    &in,
			    &out);
    if(ret) {
	krb5_warn(context, ret, "krb5_get_kdc_cred");
	goto out;
    }
    ret = krb5_cc_initialize(context, cache, in.client);
    if(ret) {
	krb5_free_creds (context, out);
	krb5_warn(context, ret, "krb5_cc_initialize");
	goto out;
    }
    ret = krb5_cc_store_cred(context, cache, out);

    if(ret == 0 && server == NULL) {
	/* only do this if it's a general renew-my-tgt request */
#ifndef NO_AFS
	if(do_afslog && k_hasafs())
	    krb5_afslog(context, cache, NULL, NULL);
#endif
    }

    krb5_free_creds (context, out);
    if(ret) {
	krb5_warn(context, ret, "krb5_cc_store_cred");
	goto out;
    }
out:
    krb5_free_cred_contents(context, &in);
    return ret;
}
Exemple #28
0
 krb5_error_code smb_krb5_renew_ticket(const char *ccache_string,	/* FILE:/tmp/krb5cc_0 */
				       const char *client_string,	/* [email protected] */
				       const char *service_string,	/* krbtgt/[email protected] */
				       time_t *expire_time)
{
	krb5_error_code ret;
	krb5_context context = NULL;
	krb5_ccache ccache = NULL;
	krb5_principal client = NULL;

	initialize_krb5_error_table();
	ret = krb5_init_context(&context);
	if (ret) {
		goto done;
	}

	if (!ccache_string) {
		ccache_string = krb5_cc_default_name(context);
	}

	DEBUG(10,("smb_krb5_renew_ticket: using %s as ccache\n", ccache_string));

	/* FIXME: we should not fall back to defaults */
	ret = krb5_cc_resolve(context, CONST_DISCARD(char *, ccache_string), &ccache);
	if (ret) {
		goto done;
	}

#ifdef HAVE_KRB5_GET_RENEWED_CREDS	/* MIT */
	{
		krb5_creds creds;
	
		if (client_string) {
			ret = smb_krb5_parse_name(context, client_string, &client);
			if (ret) {
				goto done;
			}
		} else {
			ret = krb5_cc_get_principal(context, ccache, &client);
			if (ret) {
				goto done;
			}
		}
	
		ret = krb5_get_renewed_creds(context, &creds, client, ccache, CONST_DISCARD(char *, service_string));
		if (ret) {
			DEBUG(10,("smb_krb5_renew_ticket: krb5_get_kdc_cred failed: %s\n", error_message(ret)));
			goto done;
		}

		/* hm, doesn't that create a new one if the old one wasn't there? - Guenther */
		ret = krb5_cc_initialize(context, ccache, client);
		if (ret) {
			goto done;
		}
	
		ret = krb5_cc_store_cred(context, ccache, &creds);

		if (expire_time) {
			*expire_time = (time_t) creds.times.endtime;
		}

		krb5_free_cred_contents(context, &creds);
	}
#elif defined(HAVE_KRB5_GET_KDC_CRED)	/* Heimdal */
	{
		krb5_kdc_flags flags;
		krb5_creds creds_in;
		krb5_realm *client_realm;
		krb5_creds *creds;

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

		if (client_string) {
			ret = smb_krb5_parse_name(context, client_string, &creds_in.client);
			if (ret) {
				goto done;
			}
		} else {
			ret = krb5_cc_get_principal(context, ccache, &creds_in.client);
			if (ret) {
				goto done;
			}
		}

		if (service_string) {
			ret = smb_krb5_parse_name(context, service_string, &creds_in.server);
			if (ret) { 
				goto done;
			}
		} else {
			/* build tgt service by default */
			client_realm = krb5_princ_realm(context, creds_in.client);
			if (!client_realm) {
				ret = ENOMEM;
				goto done;
			}
			ret = krb5_make_principal(context, &creds_in.server, *client_realm, KRB5_TGS_NAME, *client_realm, NULL);
			if (ret) {
				goto done;
			}
		}

		flags.i = 0;
		flags.b.renewable = flags.b.renew = True;

		ret = krb5_get_kdc_cred(context, ccache, flags, NULL, NULL, &creds_in, &creds);
		if (ret) {
			DEBUG(10,("smb_krb5_renew_ticket: krb5_get_kdc_cred failed: %s\n", error_message(ret)));
			goto done;
		}
		
		/* hm, doesn't that create a new one if the old one wasn't there? - Guenther */
		ret = krb5_cc_initialize(context, ccache, creds_in.client);
		if (ret) {
			goto done;
		}
	
		ret = krb5_cc_store_cred(context, ccache, creds);

		if (expire_time) {
			*expire_time = (time_t) creds->times.endtime;
		}
						
		krb5_free_cred_contents(context, &creds_in);
		krb5_free_creds(context, creds);
	}
#else
#error No suitable krb5 ticket renew function available
#endif


done:
	if (client) {
		krb5_free_principal(context, client);
	}
	if (context) {
		krb5_free_context(context);
	}
	if (ccache) {
		krb5_cc_close(context, ccache);
	}

	return ret;
    
}
Exemple #29
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;
}
Exemple #30
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_credentials_with_flags(krb5_context context,
				krb5_flags options,
				krb5_kdc_flags flags,
				krb5_ccache ccache,
				krb5_creds *in_creds,
				krb5_creds **out_creds)
{
    krb5_error_code ret;
    krb5_creds **tgts;
    krb5_creds *res_creds;
    int i;
    
    *out_creds = NULL;
    res_creds = calloc(1, sizeof(*res_creds));
    if (res_creds == NULL) {
	krb5_set_error_string(context, "malloc: out of memory");
	return ENOMEM;
    }

    if (in_creds->session.keytype)
	options |= KRB5_TC_MATCH_KEYTYPE;

    /* 
     * If we got a credential, check if credential is expired before
     * returning it.
     */
    ret = krb5_cc_retrieve_cred(context,
                                ccache,
                                in_creds->session.keytype ?
                                KRB5_TC_MATCH_KEYTYPE : 0,
                                in_creds, res_creds);
    /* 
     * If we got a credential, check if credential is expired before
     * returning it, but only if KRB5_GC_EXPIRED_OK is not set.
     */
    if (ret == 0) {
	krb5_timestamp timeret;

	/* If expired ok, don't bother checking */
        if(options & KRB5_GC_EXPIRED_OK) {
            *out_creds = res_creds;
            return 0;
        }
	    
	krb5_timeofday(context, &timeret);
	if(res_creds->times.endtime > timeret) {
	    *out_creds = res_creds;
	    return 0;
	}
	if(options & KRB5_GC_CACHED)
	    krb5_cc_remove_cred(context, ccache, 0, res_creds);

    } else if(ret != KRB5_CC_END) {
        free(res_creds);
        return ret;
    }
    free(res_creds);
    if(options & KRB5_GC_CACHED) {
	not_found(context, in_creds->server);
        return KRB5_CC_NOTFOUND;
    }
    if(options & KRB5_GC_USER_USER)
	flags.b.enc_tkt_in_skey = 1;
    if (flags.b.enc_tkt_in_skey)
	options |= KRB5_GC_NO_STORE;

    tgts = NULL;
    ret = get_cred_from_kdc_flags(context, flags, ccache, 
				  in_creds, NULL, NULL, out_creds, &tgts);
    for(i = 0; tgts && tgts[i]; i++) {
	krb5_cc_store_cred(context, ccache, tgts[i]);
	krb5_free_creds(context, tgts[i]);
    }
    free(tgts);
    if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0)
	krb5_cc_store_cred(context, ccache, *out_creds);
    return ret;
}