コード例 #1
0
ファイル: renew.c プロジェクト: IIJ-NetBSD/netbsd-src
krb5_error_code
kcm_ccache_refresh(krb5_context context,
		   kcm_ccache ccache,
		   krb5_creds **credp)
{
    krb5_error_code ret;
    krb5_creds in, *out;
    krb5_kdc_flags flags;
    krb5_const_realm realm;
    krb5_ccache_data ccdata;
    const char *estr;

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

    KCM_ASSERT_VALID(ccache);

    if (ccache->client == NULL) {
	/* no primary principal */
	kcm_log(0, "Refresh credentials requested but no client principal");
	return KRB5_CC_NOTFOUND;
    }

    HEIMDAL_MUTEX_lock(&ccache->mutex);

    /* Fake up an internal ccache */
    kcm_internal_ccache(context, ccache, &ccdata);

    /* Find principal */
    in.client = ccache->client;

    if (ccache->server != NULL) {
	ret = krb5_copy_principal(context, ccache->server, &in.server);
	if (ret) {
	    estr = krb5_get_error_message(context, ret);
	    kcm_log(0, "Failed to copy service principal: %s",
		    estr);
	    krb5_free_error_message(context, estr);
	    goto out;
	}
    } else {
	realm = krb5_principal_get_realm(context, in.client);
	ret = krb5_make_principal(context, &in.server, realm,
				  KRB5_TGS_NAME, realm, NULL);
	if (ret) {
	    estr = krb5_get_error_message(context, ret);
	    kcm_log(0, "Failed to make TGS principal for realm %s: %s",
		    realm, estr);
	    krb5_free_error_message(context, estr);
	    goto out;
	}
    }

    if (ccache->tkt_life)
	in.times.endtime = time(NULL) + ccache->tkt_life;
    if (ccache->renew_life)
	in.times.renew_till = time(NULL) + ccache->renew_life;

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

    ret = krb5_get_kdc_cred(context,
			    &ccdata,
			    flags,
			    NULL,
			    NULL,
			    &in,
			    &out);
    if (ret) {
	estr = krb5_get_error_message(context, ret);
	kcm_log(0, "Failed to renew credentials for cache %s: %s",
		ccache->name, estr);
	krb5_free_error_message(context, estr);
	goto out;
    }

    /* Swap them in */
    kcm_ccache_remove_creds_internal(context, ccache);

    ret = kcm_ccache_store_cred_internal(context, ccache, out, 0, credp);
    if (ret) {
	estr = krb5_get_error_message(context, ret);
	kcm_log(0, "Failed to store credentials for cache %s: %s",
		ccache->name, estr);
	krb5_free_error_message(context, estr);
	krb5_free_creds(context, out);
	goto out;
    }

    free(out); /* but not contents */

out:
    HEIMDAL_MUTEX_unlock(&ccache->mutex);

    return ret;
}
コード例 #2
0
ファイル: do_as_req.c プロジェクト: drankye/kerb-token
/*ARGSUSED*/
void
process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
               const krb5_fulladdr *from, kdc_realm_t *kdc_active_realm,
               verto_ctx *vctx, loop_respond_fn respond, void *arg)
{
    krb5_error_code errcode;
    unsigned int s_flags = 0;
    krb5_data encoded_req_body;
    krb5_enctype useenctype;
    struct as_req_state *state;
    krb5_audit_state *au_state = NULL;

    state = k5alloc(sizeof(*state), &errcode);
    if (state == NULL) {
        (*respond)(arg, errcode, NULL);
        return;
    }
    state->respond = respond;
    state->arg = arg;
    state->request = request;
    state->req_pkt = req_pkt;
    state->from = from;
    state->active_realm = kdc_active_realm;

    errcode = kdc_make_rstate(kdc_active_realm, &state->rstate);
    if (errcode != 0) {
        (*respond)(arg, errcode, NULL);
        free(state);
        return;
    }

    /* Initialize audit state. */
    errcode = kau_init_kdc_req(kdc_context, state->request, from, &au_state);
    if (errcode) {
        (*respond)(arg, errcode, NULL);
        kdc_free_rstate(state->rstate);
        free(state);
        return;
    }
    state->au_state = au_state;

    if (state->request->msg_type != KRB5_AS_REQ) {
        state->status = "msg_type mismatch";
        errcode = KRB5_BADMSGTYPE;
        goto errout;
    }

    /* Seed the audit trail with the request ID and basic information. */
    kau_as_req(kdc_context, TRUE, au_state);

    if (fetch_asn1_field((unsigned char *) req_pkt->data,
                         1, 4, &encoded_req_body) != 0) {
        errcode = ASN1_BAD_ID;
        state->status = "Finding req_body";
        goto errout;
    }
    errcode = kdc_find_fast(&state->request, &encoded_req_body, NULL, NULL,
                            state->rstate, &state->inner_body);
    if (errcode) {
        state->status = "error decoding FAST";
        goto errout;
    }
    if (state->inner_body == NULL) {
        /* Not a FAST request; copy the encoded request body. */
        errcode = krb5_copy_data(kdc_context, &encoded_req_body,
                                 &state->inner_body);
        if (errcode) {
            state->status = "storing req body";
            goto errout;
        }
    }
    au_state->request = state->request;
    state->rock.request = state->request;
    state->rock.inner_body = state->inner_body;
    state->rock.rstate = state->rstate;
    state->rock.vctx = vctx;
    if (!state->request->client) {
        state->status = "NULL_CLIENT";
        errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
        goto errout;
    }
    if ((errcode = krb5_unparse_name(kdc_context,
                                     state->request->client,
                                     &state->cname))) {
        state->status = "UNPARSING_CLIENT";
        goto errout;
    }
    limit_string(state->cname);

    if (!state->request->server) {
        state->status = "NULL_SERVER";
        errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
        goto errout;
    }
    if ((errcode = krb5_unparse_name(kdc_context,
                                     state->request->server,
                                     &state->sname))) {
        state->status = "UNPARSING_SERVER";
        goto errout;
    }
    limit_string(state->sname);

    /*
     * We set KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY as a hint
     * to the backend to return naming information in lieu
     * of cross realm TGS entries.
     */
    setflag(state->c_flags, KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY);
    /*
     * Note that according to the referrals draft we should
     * always canonicalize enterprise principal names.
     */
    if (isflagset(state->request->kdc_options, KDC_OPT_CANONICALIZE) ||
        state->request->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL) {
        setflag(state->c_flags, KRB5_KDB_FLAG_CANONICALIZE);
        setflag(state->c_flags, KRB5_KDB_FLAG_ALIAS_OK);
    }
    if (include_pac_p(kdc_context, state->request)) {
        setflag(state->c_flags, KRB5_KDB_FLAG_INCLUDE_PAC);
    }
    errcode = krb5_db_get_principal(kdc_context, state->request->client,
                                    state->c_flags, &state->client);
    if (errcode == KRB5_KDB_CANTLOCK_DB)
        errcode = KRB5KDC_ERR_SVC_UNAVAILABLE;
    if (errcode == KRB5_KDB_NOENTRY) {
        state->status = "CLIENT_NOT_FOUND";
        if (vague_errors)
            errcode = KRB5KRB_ERR_GENERIC;
        else
            errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
        goto errout;
    } else if (errcode) {
        state->status = "LOOKING_UP_CLIENT";
        goto errout;
    }
    state->rock.client = state->client;

    /*
     * If the backend returned a principal that is not in the local
     * realm, then we need to refer the client to that realm.
     */
    if (!is_local_principal(kdc_active_realm, state->client->princ)) {
        /* Entry is a referral to another realm */
        state->status = "REFERRAL";
        au_state->cl_realm = &state->client->princ->realm;
        errcode = KRB5KDC_ERR_WRONG_REALM;
        goto errout;
    }

    au_state->stage = SRVC_PRINC;

    s_flags = 0;
    setflag(s_flags, KRB5_KDB_FLAG_ALIAS_OK);
    if (isflagset(state->request->kdc_options, KDC_OPT_CANONICALIZE)) {
        setflag(s_flags, KRB5_KDB_FLAG_CANONICALIZE);
    }
    errcode = krb5_db_get_principal(kdc_context, state->request->server,
                                    s_flags, &state->server);
    if (errcode == KRB5_KDB_CANTLOCK_DB)
        errcode = KRB5KDC_ERR_SVC_UNAVAILABLE;
    if (errcode == KRB5_KDB_NOENTRY) {
        state->status = "SERVER_NOT_FOUND";
        errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
        goto errout;
    } else if (errcode) {
        state->status = "LOOKING_UP_SERVER";
        goto errout;
    }

    au_state->stage = VALIDATE_POL;

    if ((errcode = krb5_timeofday(kdc_context, &state->kdc_time))) {
        state->status = "TIMEOFDAY";
        goto errout;
    }
    state->authtime = state->kdc_time; /* for audit_as_request() */

    if ((errcode = validate_as_request(kdc_active_realm,
                                       state->request, *state->client,
                                       *state->server, state->kdc_time,
                                       &state->status, &state->e_data))) {
        if (!state->status)
            state->status = "UNKNOWN_REASON";
        errcode += ERROR_TABLE_BASE_krb5;
        goto errout;
    }

    au_state->stage = ISSUE_TKT;

    /*
     * Select the keytype for the ticket session key.
     */
    if ((useenctype = select_session_keytype(kdc_active_realm, state->server,
                                             state->request->nktypes,
                                             state->request->ktype)) == 0) {
        /* unsupported ktype */
        state->status = "BAD_ENCRYPTION_TYPE";
        errcode = KRB5KDC_ERR_ETYPE_NOSUPP;
        goto errout;
    }

    if ((errcode = krb5_c_make_random_key(kdc_context, useenctype,
                                          &state->session_key))) {
        state->status = "RANDOM_KEY_FAILED";
        goto errout;
    }

    /*
     * Canonicalization is only effective if we are issuing a TGT
     * (the intention is to allow support for Windows "short" realm
     * aliases, nothing more).
     */
    if (isflagset(s_flags, KRB5_KDB_FLAG_CANONICALIZE) &&
        krb5_is_tgs_principal(state->request->server) &&
        krb5_is_tgs_principal(state->server->princ)) {
        state->ticket_reply.server = state->server->princ;
    } else {
        state->ticket_reply.server = state->request->server;
    }

    state->enc_tkt_reply.flags = 0;
    state->enc_tkt_reply.times.authtime = state->authtime;

    setflag(state->enc_tkt_reply.flags, TKT_FLG_INITIAL);
    setflag(state->enc_tkt_reply.flags, TKT_FLG_ENC_PA_REP);

    /*
     * It should be noted that local policy may affect the
     * processing of any of these flags.  For example, some
     * realms may refuse to issue renewable tickets
     */

    if (isflagset(state->request->kdc_options, KDC_OPT_FORWARDABLE))
        setflag(state->enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);

    if (isflagset(state->request->kdc_options, KDC_OPT_PROXIABLE))
        setflag(state->enc_tkt_reply.flags, TKT_FLG_PROXIABLE);

    if (isflagset(state->request->kdc_options, KDC_OPT_ALLOW_POSTDATE))
        setflag(state->enc_tkt_reply.flags, TKT_FLG_MAY_POSTDATE);

    state->enc_tkt_reply.session = &state->session_key;
    if (isflagset(state->c_flags, KRB5_KDB_FLAG_CANONICALIZE)) {
        state->client_princ = *(state->client->princ);
    } else {
        state->client_princ = *(state->request->client);
        /* The realm is always canonicalized */
        state->client_princ.realm = state->client->princ->realm;
    }
    state->enc_tkt_reply.client = &state->client_princ;
    state->enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
    state->enc_tkt_reply.transited.tr_contents = empty_string;

    if (isflagset(state->request->kdc_options, KDC_OPT_POSTDATED)) {
        setflag(state->enc_tkt_reply.flags, TKT_FLG_POSTDATED);
        setflag(state->enc_tkt_reply.flags, TKT_FLG_INVALID);
        state->enc_tkt_reply.times.starttime = state->request->from;
    } else
        state->enc_tkt_reply.times.starttime = state->kdc_time;

    kdc_get_ticket_endtime(kdc_active_realm,
                           state->enc_tkt_reply.times.starttime,
                           kdc_infinity, state->request->till, state->client,
                           state->server, &state->enc_tkt_reply.times.endtime);

    kdc_get_ticket_renewtime(kdc_active_realm, state->request, NULL,
                             state->client, state->server,
                             &state->enc_tkt_reply);

    /*
     * starttime is optional, and treated as authtime if not present.
     * so we can nuke it if it matches
     */
    if (state->enc_tkt_reply.times.starttime ==
        state->enc_tkt_reply.times.authtime)
        state->enc_tkt_reply.times.starttime = 0;

    state->enc_tkt_reply.caddrs = state->request->addresses;
    state->enc_tkt_reply.authorization_data = 0;

    /* If anonymous requests are being used, adjust the realm of the client
     * principal. */
    if (isflagset(state->request->kdc_options, KDC_OPT_REQUEST_ANONYMOUS)) {
        if (!krb5_principal_compare_any_realm(kdc_context,
                                              state->request->client,
                                              krb5_anonymous_principal())) {
            errcode = KRB5KDC_ERR_BADOPTION;
            state->status = "Anonymous requested but anonymous "
                "principal not used.";
            goto errout;
        }
        setflag(state->enc_tkt_reply.flags, TKT_FLG_ANONYMOUS);
        krb5_free_principal(kdc_context, state->request->client);
        state->request->client = NULL;
        errcode = krb5_copy_principal(kdc_context, krb5_anonymous_principal(),
                                      &state->request->client);
        if (errcode) {
            state->status = "Copying anonymous principal";
            goto errout;
        }
        state->enc_tkt_reply.client = state->request->client;
        setflag(state->client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH);
    }

    /*
     * Check the preauthentication if it is there.
     */
    if (state->request->padata) {
        check_padata(kdc_context, &state->rock, state->req_pkt,
                     state->request, &state->enc_tkt_reply, &state->pa_context,
                     &state->e_data, &state->typed_e_data, finish_preauth,
                     state);
    } else
        finish_preauth(state, 0);
    return;

errout:
    finish_process_as_req(state, errcode);
}
コード例 #3
0
ファイル: get_cred.c プロジェクト: Kendra123/heimdal
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_renewed_creds(krb5_context context,
		       krb5_creds *creds,
		       krb5_const_principal client,
		       krb5_ccache ccache,
		       const char *in_tkt_service)
{
    krb5_error_code ret;
    krb5_kdc_flags flags;
    krb5_creds in, *template, *out = NULL;

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

    ret = krb5_copy_principal(context, client, &in.client);
    if (ret)
	return ret;

    if (in_tkt_service) {
	ret = krb5_parse_name(context, in_tkt_service, &in.server);
	if (ret) {
	    krb5_free_principal(context, in.client);
	    return ret;
	}
    } else {
	const char *realm = krb5_principal_get_realm(context, client);

	ret = krb5_make_principal(context, &in.server, realm, KRB5_TGS_NAME,
				  realm, NULL);
	if (ret) {
コード例 #4
0
ファイル: get_s.c プロジェクト: Henauxg/minix
kadm5_ret_t
kadm5_s_get_principal(void *server_handle,
		      krb5_principal princ,
		      kadm5_principal_ent_t out,
		      uint32_t mask)
{
    kadm5_server_context *context = server_handle;
    kadm5_ret_t ret;
    hdb_entry_ex ent;

    memset(&ent, 0, sizeof(ent));
    ret = context->db->hdb_open(context->context, context->db, O_RDONLY, 0);
    if(ret)
	return ret;
    ret = context->db->hdb_fetch_kvno(context->context, context->db, princ,
				      HDB_F_DECRYPT|HDB_F_GET_ANY|HDB_F_ADMIN_DATA, 0, &ent);
    context->db->hdb_close(context->context, context->db);
    if(ret)
	return _kadm5_error_code(ret);

    memset(out, 0, sizeof(*out));
    if(mask & KADM5_PRINCIPAL)
	ret  = krb5_copy_principal(context->context, ent.entry.principal,
				   &out->principal);
    if(ret)
	goto out;
    if(mask & KADM5_PRINC_EXPIRE_TIME && ent.entry.valid_end)
	out->princ_expire_time = *ent.entry.valid_end;
    if(mask & KADM5_PW_EXPIRATION && ent.entry.pw_end)
	out->pw_expiration = *ent.entry.pw_end;
    if(mask & KADM5_LAST_PWD_CHANGE)
	hdb_entry_get_pw_change_time(&ent.entry, &out->last_pwd_change);
    if(mask & KADM5_ATTRIBUTES){
	out->attributes |= ent.entry.flags.postdate ? 0 : KRB5_KDB_DISALLOW_POSTDATED;
	out->attributes |= ent.entry.flags.forwardable ? 0 : KRB5_KDB_DISALLOW_FORWARDABLE;
	out->attributes |= ent.entry.flags.initial ? KRB5_KDB_DISALLOW_TGT_BASED : 0;
	out->attributes |= ent.entry.flags.renewable ? 0 : KRB5_KDB_DISALLOW_RENEWABLE;
	out->attributes |= ent.entry.flags.proxiable ? 0 : KRB5_KDB_DISALLOW_PROXIABLE;
	out->attributes |= ent.entry.flags.invalid ? KRB5_KDB_DISALLOW_ALL_TIX : 0;
	out->attributes |= ent.entry.flags.require_preauth ? KRB5_KDB_REQUIRES_PRE_AUTH : 0;
	out->attributes |= ent.entry.flags.server ? 0 : KRB5_KDB_DISALLOW_SVR;
	out->attributes |= ent.entry.flags.change_pw ? KRB5_KDB_PWCHANGE_SERVICE : 0;
	out->attributes |= ent.entry.flags.ok_as_delegate ? KRB5_KDB_OK_AS_DELEGATE : 0;
	out->attributes |= ent.entry.flags.trusted_for_delegation ? KRB5_KDB_TRUSTED_FOR_DELEGATION : 0;
	out->attributes |= ent.entry.flags.allow_kerberos4 ? KRB5_KDB_ALLOW_KERBEROS4 : 0;
	out->attributes |= ent.entry.flags.allow_digest ? KRB5_KDB_ALLOW_DIGEST : 0;
    }
    if(mask & KADM5_MAX_LIFE) {
	if(ent.entry.max_life)
	    out->max_life = *ent.entry.max_life;
	else
	    out->max_life = INT_MAX;
    }
    if(mask & KADM5_MOD_TIME) {
	if(ent.entry.modified_by)
	    out->mod_date = ent.entry.modified_by->time;
	else
	    out->mod_date = ent.entry.created_by.time;
    }
    if(mask & KADM5_MOD_NAME) {
	if(ent.entry.modified_by) {
	    if (ent.entry.modified_by->principal != NULL)
		ret = krb5_copy_principal(context->context,
					  ent.entry.modified_by->principal,
					  &out->mod_name);
	} else if(ent.entry.created_by.principal != NULL)
	    ret = krb5_copy_principal(context->context,
				      ent.entry.created_by.principal,
				      &out->mod_name);
	else
	    out->mod_name = NULL;
    }
    if(ret)
	goto out;

    if(mask & KADM5_KVNO)
	out->kvno = ent.entry.kvno;
    if(mask & KADM5_MKVNO) {
	size_t n;
	out->mkvno = 0; /* XXX */
	for(n = 0; n < ent.entry.keys.len; n++)
	    if(ent.entry.keys.val[n].mkvno) {
		out->mkvno = *ent.entry.keys.val[n].mkvno; /* XXX this isn't right */
		break;
	    }
    }
#if 0 /* XXX implement */
    if(mask & KADM5_AUX_ATTRIBUTES)
	;
    if(mask & KADM5_LAST_SUCCESS)
	;
    if(mask & KADM5_LAST_FAILED)
	;
    if(mask & KADM5_FAIL_AUTH_COUNT)
	;
#endif
    if(mask & KADM5_POLICY)
	out->policy = NULL;
    if(mask & KADM5_MAX_RLIFE) {
	if(ent.entry.max_renew)
	    out->max_renewable_life = *ent.entry.max_renew;
	else
	    out->max_renewable_life = INT_MAX;
    }
    if(mask & KADM5_KEY_DATA){
	size_t i;
	Key *key;
	krb5_key_data *kd;
	krb5_salt salt;
	krb5_data *sp;
	krb5_get_pw_salt(context->context, ent.entry.principal, &salt);
	out->key_data = malloc(ent.entry.keys.len * sizeof(*out->key_data));
	if (out->key_data == NULL && ent.entry.keys.len != 0) {
	    ret = ENOMEM;
	    goto out;
	}
	for(i = 0; i < ent.entry.keys.len; i++){
	    key = &ent.entry.keys.val[i];
	    kd = &out->key_data[i];
	    kd->key_data_ver = 2;
	    kd->key_data_kvno = ent.entry.kvno;
	    kd->key_data_type[0] = key->key.keytype;
	    if(key->salt)
		kd->key_data_type[1] = key->salt->type;
	    else
		kd->key_data_type[1] = KRB5_PADATA_PW_SALT;
	    /* setup key */
	    kd->key_data_length[0] = key->key.keyvalue.length;
	    kd->key_data_contents[0] = malloc(kd->key_data_length[0]);
	    if(kd->key_data_contents[0] == NULL && kd->key_data_length[0] != 0){
		ret = ENOMEM;
		break;
	    }
	    memcpy(kd->key_data_contents[0], key->key.keyvalue.data,
		   kd->key_data_length[0]);
	    /* setup salt */
	    if(key->salt)
		sp = &key->salt->salt;
	    else
		sp = &salt.saltvalue;
	    kd->key_data_length[1] = sp->length;
	    kd->key_data_contents[1] = malloc(kd->key_data_length[1]);
	    if(kd->key_data_length[1] != 0
	       && kd->key_data_contents[1] == NULL) {
		memset(kd->key_data_contents[0], 0, kd->key_data_length[0]);
		ret = ENOMEM;
		break;
	    }
	    memcpy(kd->key_data_contents[1], sp->data, kd->key_data_length[1]);
	    out->n_key_data = i + 1;
	}
	krb5_free_salt(context->context, salt);
    }
    if(ret){
	kadm5_free_principal_ent(context, out);
	goto out;
    }
    if(mask & KADM5_TL_DATA) {
	time_t last_pw_expire;
	const HDB_Ext_PKINIT_acl *acl;
	const HDB_Ext_Aliases *aliases;

	ret = hdb_entry_get_pw_change_time(&ent.entry, &last_pw_expire);
	if (ret == 0 && last_pw_expire) {
	    unsigned char buf[4];
	    _krb5_put_int(buf, last_pw_expire, sizeof(buf));
	    ret = add_tl_data(out, KRB5_TL_LAST_PWD_CHANGE, buf, sizeof(buf));
	}
	if(ret){
	    kadm5_free_principal_ent(context, out);
	    goto out;
	}
	/*
	 * If the client was allowed to get key data, let it have the
	 * password too.
	 */
	if(mask & KADM5_KEY_DATA) {
	    heim_utf8_string pw;

	    ret = hdb_entry_get_password(context->context,
					 context->db, &ent.entry, &pw);
	    if (ret == 0) {
		ret = add_tl_data(out, KRB5_TL_PASSWORD, pw, strlen(pw) + 1);
		free(pw);
	    }
	    krb5_clear_error_message(context->context);
	}

	ret = hdb_entry_get_pkinit_acl(&ent.entry, &acl);
	if (ret == 0 && acl) {
	    krb5_data buf;
	    size_t len;

	    ASN1_MALLOC_ENCODE(HDB_Ext_PKINIT_acl, buf.data, buf.length,
				acl, &len, ret);
	    if (ret) {
		kadm5_free_principal_ent(context, out);
		goto out;
	    }
	    if (len != buf.length)
		krb5_abortx(context->context,
			    "internal ASN.1 encoder error");
	    ret = add_tl_data(out, KRB5_TL_PKINIT_ACL, buf.data, buf.length);
	    free(buf.data);
	    if (ret) {
		kadm5_free_principal_ent(context, out);
		goto out;
	    }
	}
	if(ret){
	    kadm5_free_principal_ent(context, out);
	    goto out;
	}

	ret = hdb_entry_get_aliases(&ent.entry, &aliases);
	if (ret == 0 && aliases) {
	    krb5_data buf;
	    size_t len;

	    ASN1_MALLOC_ENCODE(HDB_Ext_Aliases, buf.data, buf.length,
			       aliases, &len, ret);
	    if (ret) {
		kadm5_free_principal_ent(context, out);
		goto out;
	    }
	    if (len != buf.length)
		krb5_abortx(context->context,
			    "internal ASN.1 encoder error");
	    ret = add_tl_data(out, KRB5_TL_ALIASES, buf.data, buf.length);
	    free(buf.data);
	    if (ret) {
		kadm5_free_principal_ent(context, out);
		goto out;
	    }
	}
	if(ret){
	    kadm5_free_principal_ent(context, out);
	    goto out;
	}

    }
out:
    hdb_free_entry(context->context, &ent);

    return _kadm5_error_code(ret);
}
コード例 #5
0
ファイル: get_cred.c プロジェクト: Alexandr-Galko/samba
static krb5_error_code
get_cred_kdc_capath_worker(krb5_context context,
                           krb5_kdc_flags flags,
                           krb5_ccache ccache,
                           krb5_creds *in_creds,
                           krb5_const_realm try_realm,
                           krb5_principal impersonate_principal,
                           Ticket *second_ticket,			
                           krb5_creds **out_creds,
                           krb5_creds ***ret_tgts)
{
    krb5_error_code ret;
    krb5_creds *tgt, tmp_creds;
    krb5_const_realm client_realm, server_realm;
    int ok_as_delegate = 1;

    *out_creds = NULL;

    client_realm = krb5_principal_get_realm(context, in_creds->client);
    server_realm = krb5_principal_get_realm(context, in_creds->server);
    memset(&tmp_creds, 0, sizeof(tmp_creds));
    ret = krb5_copy_principal(context, in_creds->client, &tmp_creds.client);
    if(ret)
	return ret;

    ret = krb5_make_principal(context,
			      &tmp_creds.server,
			      try_realm,
			      KRB5_TGS_NAME,
			      server_realm,
			      NULL);
    if(ret){
	krb5_free_principal(context, tmp_creds.client);
	return ret;
    }
    {
	krb5_creds tgts;

	ret = find_cred(context, ccache, tmp_creds.server,
			*ret_tgts, &tgts);
	if(ret == 0){
	    /* only allow implicit ok_as_delegate if the realm is the clients realm */
	    if (strcmp(try_realm, client_realm) != 0 || strcmp(try_realm, server_realm) != 0)
		ok_as_delegate = tgts.flags.b.ok_as_delegate;

	    *out_creds = calloc(1, sizeof(**out_creds));
	    if(*out_creds == NULL) {
		ret = ENOMEM;
		krb5_set_error_message(context, ret,
				       N_("malloc: out of memory", ""));
	    } else {
		ret = get_cred_kdc_address(context, ccache, flags, NULL,
					   in_creds, &tgts,
					   impersonate_principal,
					   second_ticket,
					   *out_creds);
		if (ret) {
		    free (*out_creds);
		    *out_creds = NULL;
		} else if (ok_as_delegate == 0)
		    (*out_creds)->flags.b.ok_as_delegate = 0;
	    }
	    krb5_free_cred_contents(context, &tgts);
	    krb5_free_principal(context, tmp_creds.server);
	    krb5_free_principal(context, tmp_creds.client);
	    return ret;
	}
    }
    if(krb5_realm_compare(context, in_creds->client, in_creds->server))
	return not_found(context, in_creds->server, KRB5_CC_NOTFOUND);

    /* XXX this can loop forever */
    while(1){
	heim_general_string tgt_inst;

	ret = get_cred_kdc_capath(context, flags, ccache, &tmp_creds,
				  NULL, NULL, &tgt, ret_tgts);
	if(ret) {
	    krb5_free_principal(context, tmp_creds.server);
	    krb5_free_principal(context, tmp_creds.client);
	    return ret;
	}
	/* 
	 * if either of the chain or the ok_as_delegate was stripped
	 * by the kdc, make sure we strip it too.
	 */
	if (ok_as_delegate == 0 || tgt->flags.b.ok_as_delegate == 0) {
	    ok_as_delegate = 0;
	    tgt->flags.b.ok_as_delegate = 0;
	}

	ret = add_cred(context, tgt, ret_tgts);
	if(ret) {
	    krb5_free_principal(context, tmp_creds.server);
	    krb5_free_principal(context, tmp_creds.client);
	    return ret;
	}
	tgt_inst = tgt->server->name.name_string.val[1];
	if(strcmp(tgt_inst, server_realm) == 0)
	    break;
	krb5_free_principal(context, tmp_creds.server);
	ret = krb5_make_principal(context, &tmp_creds.server,
				  tgt_inst, KRB5_TGS_NAME, server_realm, NULL);
	if(ret) {
	    krb5_free_principal(context, tmp_creds.server);
	    krb5_free_principal(context, tmp_creds.client);
	    return ret;
	}
	ret = krb5_free_creds(context, tgt);
	if(ret) {
	    krb5_free_principal(context, tmp_creds.server);
	    krb5_free_principal(context, tmp_creds.client);
	    return ret;
	}
    }
	
    krb5_free_principal(context, tmp_creds.server);
    krb5_free_principal(context, tmp_creds.client);
    *out_creds = calloc(1, sizeof(**out_creds));
    if(*out_creds == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
    } else {
	ret = get_cred_kdc_address (context, ccache, flags, NULL,
				    in_creds, tgt, impersonate_principal,
				    second_ticket, *out_creds);
	if (ret) {
	    free (*out_creds);
	    *out_creds = NULL;
	}
    }
    krb5_free_creds(context, tgt);
    return ret;
}                           
コード例 #6
0
ファイル: auks_krb5_cred.c プロジェクト: 3van/auks
int
auks_krb5_cred_deladdr_buffer(char *in_buf,size_t in_buf_len,
			      char** pout_buf,size_t *pout_buf_len)
{
	int fstatus = AUKS_ERROR ;

	/* kerberos related variables */
	krb5_error_code err_code;
	krb5_context context;
	krb5_auth_context auth_context;

	krb5_creds **creds;
	krb5_data data;
	krb5_replay_data krdata;

	krb5_data *p_outbuf;

	krb5_creds fwd_cred;
	krb5_creds *p_cred_out = NULL;

	krb5_address **addresses;

	char* buffer;
	size_t length;

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

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

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

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

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

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

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

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

	/* get addressless forwarded ticket */
	err_code = krb5_get_cred_via_tkt(context,(*creds),
					 ( KDC_OPT_CANONICALIZE |
					   KDC_OPT_FORWARDED |
					   ( (*creds)->ticket_flags &
					     KDC_TKT_COMMON_MASK )  ),
					 addresses=NULL,
					 &fwd_cred,&p_cred_out);
	if (err_code) {
		auks_error("unable to get addressless forwarded cred from auks"
			   " cred buffer : %s",error_message(err_code));
		fstatus = AUKS_ERROR_KRB5_CRED_GET_FWD_CRED ;
		goto cred_exit;
	}
	auks_log("addressless forwarded cred successfully"
		 " got using auks cred buffer");

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

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

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

	auks_log("in length : %u | out length : %u",
		 in_buf_len,
		 p_outbuf->length);
mk_exit:
	krb5_free_data(context,p_outbuf);

fwd_exit:
	krb5_free_creds(context,p_cred_out);

cred_exit:
	krb5_free_cred_contents(context,&fwd_cred);
	krb5_free_creds(context, *creds);
	free(creds);

auth_ctx_exit:
	krb5_auth_con_free(context, auth_context);

ctx_exit:
	krb5_free_context(context);

exit:
	return fstatus;
}
コード例 #7
0
ファイル: akimpersonate.c プロジェクト: gsell/openafs-osd
/*
 * Populate the credentials structure corresponding to the ticket we are
 * printing.
 */
static int
populate_creds(krb5_context context, krb5_principal service_principal,
	       krb5_principal client_principal, krb5_keyblock *session_key,
	       void *tr_in, void *er_in, krb5_creds *creds)
{
    krb5_error_code code;
#if USING_HEIMDAL
    Ticket *ticket_reply;
    EncTicketPart *enc_tkt_reply;
    size_t dummy;
#else
    krb5_ticket *ticket_reply;
    krb5_enc_tkt_part *enc_tkt_reply;
    krb5_data *temp = NULL;
#endif

    /* Requisite aliasing for Heimdal/MIT support. */
    ticket_reply = tr_in;
    enc_tkt_reply = er_in;

    code = krb5_copy_principal(context, service_principal, &creds->server);
    if (code != 0)
        goto cleanup;
    code = krb5_copy_principal(context, client_principal, &creds->client);
    if (code != 0)
        goto cleanup;
    code = krb5_copy_keyblock_contents(context, session_key,
				       &deref_session_key(creds));
    if (code != 0)
        goto cleanup;

#if USING_HEIMDAL
    creds->times.authtime = enc_tkt_reply->authtime;
    creds->times.starttime = *(enc_tkt_reply->starttime);
    creds->times.endtime = enc_tkt_reply->endtime;
    creds->times.renew_till = 0; /* *(enc_tkt_reply->renew_till) */
    creds->flags.b = enc_tkt_reply->flags;
#else
    creds->times = enc_tkt_reply->times;
    creds->ticket_flags = enc_tkt_reply->flags;
#endif

#if USING_HEIMDAL
    ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
		       ticket_reply, &dummy, code);
    if (code != 0 || dummy != creds->ticket.length)
	goto cleanup;
#else
    code = encode_krb5_ticket(ticket_reply, &temp);
    if (code != 0)
	goto cleanup;
    creds->ticket = *temp;
#endif

cleanup:
#if USING_HEIMDAL
    /* nothing */
#else
    free(temp);
#endif
    return code;
}
コード例 #8
0
ファイル: acquire.c プロジェクト: alepharchives/bitrig
static krb5_error_code
get_salt_and_kvno(krb5_context context,
		  kcm_ccache ccache,
		  krb5_enctype *etypes,
		  char *cpn,
		  char *newpw,
		  krb5_salt *salt,
		  unsigned *kvno)
{
    krb5_error_code ret;
    krb5_creds creds;
    krb5_ccache_data ccdata;
    krb5_flags options = 0;
    krb5_kdc_rep reply;
    struct kcm_keyseed_data s;

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

    s.password = NULL;
    s.salt.salttype = (int)ETYPE_NULL;
    krb5_data_zero(&s.salt.saltvalue);

    *kvno = 0;
    kcm_internal_ccache(context, ccache, &ccdata);
    s.password = newpw;

    /* Do an AS-REQ to determine salt and key version number */
    ret = krb5_copy_principal(context, ccache->client, &creds.client);
    if (ret)
	return ret;

    /* Yes, get a ticket to ourselves */
    ret = krb5_copy_principal(context, ccache->client, &creds.server);
    if (ret) {
	krb5_free_principal(context, creds.client);
	return ret;
    }
	
    ret = krb5_get_in_tkt(context,
			  options,
			  NULL,
			  etypes,
			  NULL,
			  kcm_password_key_proc,
			  &s,
			  NULL,
			  NULL,
			  &creds,
			  &ccdata,
			  &reply);
    if (ret) {
	kcm_log(0, "Failed to get self ticket for principal %s: %s",
		cpn, krb5_get_err_text(context, ret));
	krb5_free_salt(context, s.salt);
    } else {
	*salt = s.salt; /* retrieve stashed salt */
	if (reply.kdc_rep.enc_part.kvno != NULL)
	    *kvno = *(reply.kdc_rep.enc_part.kvno);
    }
    /* ccache may have been modified but it will get trashed anyway */

    krb5_free_creds_contents(context, &creds);
    krb5_free_kdc_rep(context, &reply);

    return ret;
}
コード例 #9
0
/**
 * @brief
 * 		Get a TGT for use at the remote host.
 *
 * @param[in]	context	-	The Kerberos context.
 * @param[in]	auth_context	- Authentication context
 * @param[in]	client	-	Principal to be copied
 * @param[in]	server	-	Server of type krb5_principal
 * @param[in]	cc	-	Credential cache handle
 * @param[out]	outbuf	-	Replay cache data (NULL if not needed)
 *
 * @return	krb5_error_code
 * @retval	0	- success
 * @retval	!=0	- failure
 */
static
krb5_error_code
fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, krb5_principal client, krb5_principal server, krb5_ccache cc, krb5_data outbuf)
{
	krb5_replay_data	replaydata;
	krb5_data		*scratch = 0;
	krb5_address		**addrs = 0;
	krb5_flags		kdcoptions;
	krb5_error_code		retval;
	krb5_creds		creds, tgt;
	krb5_creds		*pcreds;
	int			free_rhost = 0;
	char			*rhost;

	memset((char *)&creds, 0, sizeof(creds));
	memset((char *)&tgt, 0, sizeof(creds));

	if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST)
		return KRB5_FWD_BAD_PRINCIPAL;

	if (krb5_princ_size(context, server) < 2)
		return KRB5_CC_BADNAME;

	rhost = malloc(server->data[1].length+1);
	if (!rhost)
		return ENOMEM;
	free_rhost = 1;
	memcpy(rhost, server->data[1].data, server->data[1].length);
	rhost[server->data[1].length] = '\0';

	retval = krb5_os_hostaddr(context, rhost, &addrs);
	if (retval)
		goto errout;

	if ((retval = krb5_copy_principal(context, client, &creds.client)))
		goto errout;

	if ((retval = krb5_build_principal_ext(context, &creds.server,
		client->realm.length,
		client->realm.data,
		KRB5_TGS_NAME_SIZE,
		KRB5_TGS_NAME,
		client->realm.length,
		client->realm.data,
		0)))
		goto errout;

	/* fetch tgt directly from cache */
	retval = 	krb5_cc_retrieve_cred(context, cc, KRB5_TC_SUPPORTED_KTYPES,
		&creds, &tgt);
	if (retval)
		goto errout;

	/* tgt->client must be equal to creds.client */
	if (!krb5_principal_compare(context, tgt.client, creds.client)) {
		retval = KRB5_PRINC_NOMATCH;
		goto errout;
	}
	if (!tgt.ticket.length) {
		retval = KRB5_NO_TKT_SUPPLIED;
		goto errout;
	}

	kdcoptions = flags2options(tgt.ticket_flags)|
		KDC_OPT_FORWARDED;

	if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
		addrs, &creds, &pcreds)))
		goto errout;

	retval = krb5_mk_1cred(context, auth_context, pcreds,
		&scratch, &replaydata);
	krb5_free_creds(context, pcreds);

	if (retval) {
		if (scratch)
			krb5_free_data(context, scratch);
	}
	else {
		*outbuf = *scratch;
		free(scratch);
	}

errout:
	if (addrs)
		krb5_free_addresses(context, addrs);
	if (free_rhost)
		free(rhost);
	krb5_free_cred_contents(context, &creds);
	krb5_free_cred_contents(context, &tgt);

	return retval;
}
コード例 #10
0
ファイル: change.c プロジェクト: SimonWilkinson/heimdal
int
kt_change (struct change_options *opt, int argc, char **argv)
{
    krb5_error_code ret;
    krb5_keytab keytab;
    krb5_kt_cursor cursor;
    krb5_keytab_entry entry;
    int i, j, max;
    struct change_set *changeset;
    int errors = 0;

    if((keytab = ktutil_open_keytab()) == NULL)
	return 1;

    j = 0;
    max = 0;
    changeset = NULL;

    ret = krb5_kt_start_seq_get(context, keytab, &cursor);
    if(ret){
	krb5_warn(context, ret, "%s", keytab_string);
	goto out;
    }

    while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) {
	int add = 0;

	for (i = 0; i < j; ++i) {
	    if (krb5_principal_compare (context, changeset[i].principal,
					entry.principal)) {
		if (changeset[i].kvno < entry.vno)
		    changeset[i].kvno = entry.vno;
		break;
	    }
	}
	if (i < j) {
	    krb5_kt_free_entry (context, &entry);
	    continue;
	}

	if (argc == 0) {
	    add = 1;
	} else {
	    for (i = 0; i < argc; ++i) {
		krb5_principal princ;

		ret = krb5_parse_name (context, argv[i], &princ);
		if (ret) {
		    krb5_warn (context, ret, "%s", argv[i]);
		    continue;
		}
		if (krb5_principal_compare (context, princ, entry.principal))
		    add = 1;

		krb5_free_principal (context, princ);
	    }
	}

	if (add) {
	    if (j >= max) {
		void *tmp;

		max = max(max * 2, 1);
		tmp = realloc (changeset, max * sizeof(*changeset));
		if (tmp == NULL) {
		    krb5_kt_free_entry (context, &entry);
		    krb5_warnx (context, "realloc: out of memory");
		    ret = ENOMEM;
		    break;
		}
		changeset = tmp;
	    }
	    ret = krb5_copy_principal (context, entry.principal,
				       &changeset[j].principal);
	    if (ret) {
		krb5_warn (context, ret, "krb5_copy_principal");
		krb5_kt_free_entry (context, &entry);
		break;
	    }
	    changeset[j].kvno = entry.vno;
	    ++j;
	}
	krb5_kt_free_entry (context, &entry);
    }
    krb5_kt_end_seq_get(context, keytab, &cursor);

    if (ret == KRB5_KT_END) {
	ret = 0;
	for (i = 0; i < j; i++) {
	    if (verbose_flag) {
		char *client_name;

		ret = krb5_unparse_name (context, changeset[i].principal,
					 &client_name);
		if (ret) {
		    krb5_warn (context, ret, "krb5_unparse_name");
		} else {
		    printf("Changing %s kvno %d\n",
			   client_name, changeset[i].kvno);
		    free(client_name);
		}
	    }
	    ret = change_entry (keytab,
				changeset[i].principal, changeset[i].kvno,
				opt->realm_string,
				opt->admin_server_string,
				opt->server_port_integer);
	    if (ret != 0)
		errors = 1;
	}
    } else
	errors = 1;
    for (i = 0; i < j; i++)
	krb5_free_principal (context, changeset[i].principal);
    free (changeset);

 out:
    krb5_kt_close(context, keytab);
    return errors;
}
コード例 #11
0
    principal::principal(principal& o):base(),free(TRUE),ctx(o.getCtx()),_principal(NULL){
	if(o()!=NULL)
	    krb5_copy_principal(ctx(),o(),&_principal);
    };
コード例 #12
0
ファイル: clikrb5.c プロジェクト: edwacode/r6300v2
/*
  we can't use krb5_mk_req because w2k wants the service to be in a particular format
*/
static krb5_error_code ads_krb5_mk_req(krb5_context context, 
				       krb5_auth_context *auth_context, 
				       const krb5_flags ap_req_options,
				       const char *principal,
				       krb5_ccache ccache, 
				       krb5_data *outbuf, 
				       time_t *expire_time)
{
	krb5_error_code 	  retval;
	krb5_principal	  server;
	krb5_creds 		* credsp;
	krb5_creds 		  creds;
	krb5_data in_data;
	BOOL creds_ready = False;
	int i = 0, maxtries = 3;
	
	retval = smb_krb5_parse_name(context, principal, &server);
	if (retval) {
		DEBUG(1,("ads_krb5_mk_req: Failed to parse principal %s\n", principal));
		return retval;
	}
	
	/* obtain ticket & session key */
	ZERO_STRUCT(creds);
	if ((retval = krb5_copy_principal(context, server, &creds.server))) {
		DEBUG(1,("ads_krb5_mk_req: krb5_copy_principal failed (%s)\n", 
			 error_message(retval)));
		goto cleanup_princ;
	}
	
	if ((retval = krb5_cc_get_principal(context, ccache, &creds.client))) {
		/* This can commonly fail on smbd startup with no ticket in the cache.
		 * Report at higher level than 1. */
		DEBUG(3,("ads_krb5_mk_req: krb5_cc_get_principal failed (%s)\n", 
			 error_message(retval)));
		goto cleanup_creds;
	}

	while (!creds_ready && (i < maxtries)) {

		if ((retval = krb5_get_credentials(context, 0, ccache, 
						   &creds, &credsp))) {
			DEBUG(1,("ads_krb5_mk_req: krb5_get_credentials failed for %s (%s)\n",
				 principal, error_message(retval)));
			goto cleanup_creds;
		}

		/* cope with ticket being in the future due to clock skew */
		if ((unsigned)credsp->times.starttime > time(NULL)) {
			time_t t = time(NULL);
			int time_offset =(int)((unsigned)credsp->times.starttime-t);
			DEBUG(4,("ads_krb5_mk_req: Advancing clock by %d seconds to cope with clock skew\n", time_offset));
			krb5_set_real_time(context, t + time_offset + 1, 0);
		}

		if (!ads_cleanup_expired_creds(context, ccache, credsp)) {
			creds_ready = True;
		}

		i++;
	}

	DEBUG(10,("ads_krb5_mk_req: Ticket (%s) in ccache (%s:%s) is valid until: (%s - %u)\n",
		  principal, krb5_cc_get_type(context, ccache), krb5_cc_get_name(context, ccache),
		  http_timestring((unsigned)credsp->times.endtime), 
		  (unsigned)credsp->times.endtime));

	if (expire_time) {
		*expire_time = (time_t)credsp->times.endtime;
	}

	in_data.length = 0;
	retval = krb5_mk_req_extended(context, auth_context, ap_req_options, 
				      &in_data, credsp, outbuf);
	if (retval) {
		DEBUG(1,("ads_krb5_mk_req: krb5_mk_req_extended failed (%s)\n", 
			 error_message(retval)));
	}
	
	krb5_free_creds(context, credsp);

cleanup_creds:
	krb5_free_cred_contents(context, &creds);

cleanup_princ:
	krb5_free_principal(context, server);

	return retval;
}
コード例 #13
0
ファイル: fwd_tgt.c プロジェクト: Baalmart/krb5
/* Get a TGT for use at the remote host */
krb5_error_code KRB5_CALLCONV
krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context,
                   char *rhost, krb5_principal client, krb5_principal server,
                   krb5_ccache cc, int forwardable, krb5_data *outbuf)
/* Should forwarded TGT also be forwardable? */
{
    krb5_replay_data replaydata;
    krb5_data * scratch = 0;
    krb5_address **addrs = NULL;
    krb5_error_code retval;
    krb5_creds creds, tgt;
    krb5_creds *pcreds;
    krb5_flags kdcoptions;
    int close_cc = 0;
    int free_rhost = 0;
    krb5_enctype enctype = 0;
    krb5_keyblock *session_key;
    krb5_boolean old_use_conf_ktypes = context->use_conf_ktypes;

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

    if (cc == 0) {
        if ((retval = krb5int_cc_default(context, &cc)))
            goto errout;
        close_cc = 1;
    }
    retval = krb5_auth_con_getkey (context, auth_context, &session_key);
    if (retval)
        goto errout;
    if (session_key) {
        enctype = session_key->enctype;
        krb5_free_keyblock (context, session_key);
        session_key = NULL;
    } else if (server) { /* must server be non-NULL when rhost is given? */
        /* Try getting credentials to see what the remote side supports.
           Not bulletproof, just a heuristic.  */
        krb5_creds in, *out = 0;
        memset (&in, 0, sizeof(in));

        retval = krb5_copy_principal (context, server, &in.server);
        if (retval)
            goto punt;
        retval = krb5_copy_principal (context, client, &in.client);
        if (retval)
            goto punt;
        retval = krb5_get_credentials (context, 0, cc, &in, &out);
        if (retval)
            goto punt;
        /* Got the credentials.  Okay, now record the enctype and
           throw them away.  */
        enctype = out->keyblock.enctype;
        krb5_free_creds (context, out);
    punt:
        krb5_free_cred_contents (context, &in);
    }

    if ((retval = krb5_copy_principal(context, client, &creds.client)))
        goto errout;

    retval = krb5int_tgtname(context, &client->realm, &client->realm,
                             &creds.server);
    if (retval)
        goto errout;

    /* fetch tgt directly from cache */
    context->use_conf_ktypes = 1;
    retval = krb5_cc_retrieve_cred (context, cc, KRB5_TC_SUPPORTED_KTYPES,
                                    &creds, &tgt);
    context->use_conf_ktypes = old_use_conf_ktypes;
    if (retval)
        goto errout;

    /* tgt->client must be equal to creds.client */
    if (!krb5_principal_compare(context, tgt.client, creds.client)) {
        retval = KRB5_PRINC_NOMATCH;
        goto errout;
    }

    if (!tgt.ticket.length) {
        retval = KRB5_NO_TKT_SUPPLIED;
        goto errout;
    }

    if (tgt.addresses && *tgt.addresses) {
        if (rhost == NULL) {
            if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST) {
                retval = KRB5_FWD_BAD_PRINCIPAL;
                goto errout;
            }

            if (krb5_princ_size(context, server) < 2){
                retval = KRB5_CC_BADNAME;
                goto errout;
            }

            rhost = malloc(server->data[1].length+1);
            if (!rhost) {
                retval = ENOMEM;
                goto errout;
            }
            free_rhost = 1;
            memcpy(rhost, server->data[1].data, server->data[1].length);
            rhost[server->data[1].length] = '\0';
        }

        retval = krb5_os_hostaddr(context, rhost, &addrs);
        if (retval)
            goto errout;
    }

    creds.keyblock.enctype = enctype;
    creds.times = tgt.times;
    creds.times.starttime = 0;
    kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED;

    if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */
        kdcoptions &= ~(KDC_OPT_FORWARDABLE);

    if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
                                        addrs, &creds, &pcreds))) {
        if (enctype) {
            creds.keyblock.enctype = 0;
            if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
                                                addrs, &creds, &pcreds)))
                goto errout;
        }
        else goto errout;
    }
    retval = krb5_mk_1cred(context, auth_context, pcreds,
                           &scratch, &replaydata);
    krb5_free_creds(context, pcreds);

    if (retval) {
        if (scratch)
            krb5_free_data(context, scratch);
    } else {
        *outbuf = *scratch;
        free(scratch);
    }

errout:
    if (addrs)
        krb5_free_addresses(context, addrs);
    if (close_cc)
        krb5_cc_close(context, cc);
    if (free_rhost)
        free(rhost);
    krb5_free_cred_contents(context, &creds);
    krb5_free_cred_contents(context, &tgt);
    return retval;
}
コード例 #14
0
ファイル: copy_creds.c プロジェクト: andreiw/polaris
krb5_error_code KRB5_CALLCONV
krb5_copy_creds(krb5_context context, const krb5_creds *incred, krb5_creds **outcred)
{
    krb5_creds *tempcred;
    krb5_error_code retval;
    krb5_data *scratch;

    if (!(tempcred = (krb5_creds *)malloc(sizeof(*tempcred))))
	return ENOMEM;

#ifdef HAVE_C_STRUCTURE_ASSIGNMENT
    *tempcred = *incred;		/* copy everything quickly */
#else
    memcpy(tempcred, incred, sizeof(krb5_creds));
#endif
    retval = krb5_copy_principal(context, incred->client, &tempcred->client);
    if (retval)
	goto cleanlast;
    retval = krb5_copy_principal(context, incred->server, &tempcred->server);
    if (retval)
	goto cleanclient;
    retval = krb5_copy_keyblock_contents(context, &incred->keyblock,
					 &tempcred->keyblock);
    if (retval)
	goto cleanserver;
    retval = krb5_copy_addresses(context, incred->addresses, &tempcred->addresses);
    if (retval)
	goto cleanblock;
    retval = krb5_copy_data(context, &incred->ticket, &scratch);
    if (retval)
	goto cleanaddrs;
    tempcred->ticket = *scratch;
    krb5_xfree(scratch);
    retval = krb5_copy_data(context, &incred->second_ticket, &scratch);
    if (retval)
	goto cleanticket;

    tempcred->second_ticket = *scratch;
    krb5_xfree(scratch);

    retval = krb5_copy_authdata(context, incred->authdata,&tempcred->authdata);
    if (retval)
        goto clearticket;

    *outcred = tempcred;
    return 0;

 clearticket:    
    memset(tempcred->ticket.data,0,tempcred->ticket.length);
 cleanticket:
    free(tempcred->ticket.data);
 cleanaddrs:
    krb5_free_addresses(context, tempcred->addresses);
 cleanblock:
    krb5_xfree(tempcred->keyblock.contents);
 cleanserver:
    krb5_free_principal(context, tempcred->server);
 cleanclient:
    krb5_free_principal(context, tempcred->client);
 cleanlast:
    krb5_xfree(tempcred);
    return retval;
}
コード例 #15
0
ファイル: gss_credcache.c プロジェクト: JasonZen/nfs-ganesha
/*
 * Create, initialize, and add a new ple structure to the global list
 */
static struct gssd_k5_kt_princ *new_ple(krb5_context context,
					krb5_principal princ)
{
	struct gssd_k5_kt_princ *ple = NULL, *p;
	krb5_error_code code;
	char *default_realm;
	int is_default_realm = 0;

	ple = gsh_malloc(sizeof(struct gssd_k5_kt_princ));
	if (ple == NULL)
		goto outerr;
	memset(ple, 0, sizeof(*ple));

#ifdef HAVE_KRB5
	ple->realm = gsh_malloc(princ->realm.length + 1);
	if (ple->realm == NULL)
		goto outerr;
	strmaxcpy(ple->realm, princ->realm.data, princ->realm.length);
	ple->realm[princ->realm.length] = '\0';
#else
	ple->realm = gsh_strdup(princ->realm);
	if (ple->realm == NULL)
		goto outerr;
#endif
	code = krb5_copy_principal(context, princ, &ple->princ);
	if (code)
		goto outerr;

	/*
	 * Add new entry onto the list (if this is the default
	 * realm, always add to the front of the list)
	 */

	code = krb5_get_default_realm(context, &default_realm);
	if (code == 0) {
		if (strcmp(ple->realm, default_realm) == 0)
			is_default_realm = 1;
		k5_free_default_realm(context, default_realm);
	}

	if (is_default_realm) {
		ple->next = gssd_k5_kt_princ_list;
		gssd_k5_kt_princ_list = ple;
	} else {
		p = gssd_k5_kt_princ_list;
		while (p != NULL && p->next != NULL)
			p = p->next;
		if (p == NULL)
			gssd_k5_kt_princ_list = ple;
		else
			p->next = ple;
	}

	return ple;
 outerr:
	if (ple) {
		if (ple->realm)
			gsh_free(ple->realm);
		gsh_free(ple);
	}
	return NULL;
}
コード例 #16
0
krb5_error_code
sam_get_db_entry(krb5_context context, krb5_principal client,
                 int *sam_type, struct _krb5_db_entry_new **db_entry)
{
    struct _krb5_db_entry_new *assoc = NULL;
    krb5_principal newp = NULL;
    int probeslot;
    void *ptr = NULL;
    krb5_error_code retval;

    if (db_entry)
       *db_entry = NULL;
    retval = krb5_copy_principal(context, client, &newp);
    if (retval) {
        com_err("krb5kdc", retval, "copying client name for preauth probe");
        return retval;
    }

    probeslot = krb5_princ_size(context, newp)++;
    ptr = realloc(krb5_princ_name(context, newp),
                  krb5_princ_size(context, newp) * sizeof(krb5_data));
   if (ptr == NULL) {
       retval = ENOMEM;
       goto cleanup;
   }
   krb5_princ_name(context, newp) = ptr;

   for(sam_ptr = sam_inst_map; sam_ptr->name; sam_ptr++) {
       if (*sam_type && *sam_type != sam_ptr->sam_type)
           continue;

       krb5_princ_component(context,newp,probeslot)->data = sam_ptr->name;
       krb5_princ_component(context,newp,probeslot)->length =
           strlen(sam_ptr->name);
       retval = krb5_db_get_principal(context, newp, 0, &assoc);
       if (!retval)
           break;
   }
cleanup:
   if (ptr) {
       krb5_princ_component(context,newp,probeslot)->data = 0;
       krb5_princ_component(context,newp,probeslot)->length = 0;
       krb5_free_principal(context, newp);
   }
   if (probeslot)
       krb5_princ_size(context, newp)--;
   if (retval)
       return retval;
   if (sam_ptr->sam_type)  {
       /* Found entry of type sam_ptr->sam_type */
       if (sam_type)
           *sam_type = sam_ptr->sam_type;
       if (db_entry)
           *db_entry = assoc;
       else
           krb5_db_free_principal(context, assoc);
       return 0;
   } else {
       return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
   }
}
コード例 #17
0
ファイル: auks_krb5_cred.c プロジェクト: 3van/auks
int
auks_krb5_cred_renew(char *ccachefilename)
{
	int fstatus = AUKS_ERROR ;

	int read_cred_is_tgt = 0;
	int read_cred_is_renewable = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

seq_exit:
	krb5_free_cred_contents(context,&read_cred);

cc_exit:
	krb5_cc_close(context, ccache);

ctx_exit:
	krb5_free_context(context);

exit:
	return fstatus;
}
コード例 #18
0
ファイル: auth-krb5.c プロジェクト: sambuc/netbsd
/*
 * Try krb5 authentication. server_user is passed for logging purposes
 * only, in auth is received ticket, in client is returned principal
 * from the ticket
 */
int
auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *reply)
{
	krb5_error_code problem;
	krb5_principal server;
	krb5_ticket *ticket;
	int fd, ret;
	const char *errtxt;

	ret = 0;
	server = NULL;
	ticket = NULL;
	reply->length = 0;

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

	problem = krb5_auth_con_init(authctxt->krb5_ctx,
	    &authctxt->krb5_auth_ctx);
	if (problem)
		goto err;

	fd = packet_get_connection_in();
	problem = krb5_auth_con_setaddrs_from_fd(authctxt->krb5_ctx,
	    authctxt->krb5_auth_ctx, &fd);
	if (problem)
		goto err;

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

	problem = krb5_rd_req(authctxt->krb5_ctx, &authctxt->krb5_auth_ctx,
	    auth, server, NULL, NULL, &ticket);
	if (problem)
		goto err;

	problem = krb5_copy_principal(authctxt->krb5_ctx, ticket->client,
	    &authctxt->krb5_user);
	if (problem)
		goto err;

	/* if client wants mutual auth */
	problem = krb5_mk_rep(authctxt->krb5_ctx, authctxt->krb5_auth_ctx,
	    reply);
	if (problem)
		goto err;

	/* Check .k5login authorization now. */
	if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user,
	    authctxt->pw->pw_name))
		goto err;

	if (client)
		krb5_unparse_name(authctxt->krb5_ctx, authctxt->krb5_user,
		    client);

	ret = 1;
 err:
	if (server)
		krb5_free_principal(authctxt->krb5_ctx, server);
	if (ticket)
		krb5_free_ticket(authctxt->krb5_ctx, ticket);
	if (!ret && reply->length) {
		free(reply->data);
		memset(reply, 0, sizeof(*reply));
	}

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

	return (ret);
}
コード例 #19
0
ファイル: acquire_cred.c プロジェクト: Sp1l/heimdal
static OM_uint32 acquire_initiator_cred
		  (OM_uint32 * minor_status,
		   krb5_context context,
		   gss_const_OID credential_type,
		   const void *credential_data,
		   gss_const_name_t desired_name,
		   OM_uint32 time_req,
		   gss_const_OID desired_mech,
		   gss_cred_usage_t cred_usage,
		   gsskrb5_cred handle
		  )
{
    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 (credential_type != GSS_C_NO_OID &&
	!gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) {
	kret = KRB5_NOCREDS_SUPPLIED; /* XXX */
	goto end;
    }

    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 = krb5_get_init_creds_opt_alloc(context, &opt);
	if (kret)
	    goto end;
	if (credential_type != GSS_C_NO_OID &&
	    gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) {
	    gss_buffer_t password = (gss_buffer_t)credential_data;

	    /* XXX are we requiring password to be NUL terminated? */

	    kret = krb5_get_init_creds_password(context, &cred,
						handle->principal,
						password->value,
						NULL, NULL, 0, NULL, opt);
	} else {
	    kret = get_keytab(context, &keytab);
	    if (kret) {
		krb5_get_init_creds_opt_free(context, opt);
		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);
}
コード例 #20
0
ファイル: kinit.c プロジェクト: cg2v/heimdal
static void
get_princ_kt(krb5_context context,
	     krb5_principal *principal,
	     char *name)
{
    krb5_error_code ret;
    krb5_principal tmp;
    krb5_ccache ccache;
    krb5_kt_cursor cursor;
    krb5_keytab_entry entry;
    char *def_realm;

    if (name == NULL) {
	/*
	 * If the credential cache exists and specifies a client principal,
	 * use that.
	 */
	if (krb5_cc_default(context, &ccache) == 0) {
	    ret = krb5_cc_get_principal(context, ccache, principal);
	    krb5_cc_close(context, ccache);
	    if (ret == 0)
		return;
	}
    }

    if (name) {
	/* If the principal specifies an explicit realm, just use that. */
	int parseflags = KRB5_PRINCIPAL_PARSE_NO_DEF_REALM;

	parse_name_realm(context, name, parseflags, NULL, &tmp);
	if (krb5_principal_get_realm(context, tmp) != NULL) {
	    *principal = tmp;
	    return;
	}
    } else {
	/* Otherwise, search keytab for bare name of the default principal. */
	get_default_principal(context, &tmp);
	set_princ_realm(context, tmp, NULL);
    }

    def_realm = get_default_realm(context);

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

    while (ret == 0 &&
           krb5_kt_next_entry(context, kt, &entry, &cursor) == 0) {
        const char *realm;

        if (!krb5_principal_compare_any_realm(context, tmp, entry.principal))
            continue;
        if (*principal &&
	    krb5_principal_compare(context, *principal, entry.principal))
            continue;
        /* The default realm takes precedence */
        realm = krb5_principal_get_realm(context, entry.principal);
        if (*principal && strcmp(def_realm, realm) == 0) {
            krb5_free_principal(context, *principal);
            ret = krb5_copy_principal(context, entry.principal, principal);
            break;
        }
        if (!*principal)
            ret = krb5_copy_principal(context, entry.principal, principal);
    }
    if (ret != 0 || (ret = krb5_kt_end_seq_get(context, kt, &cursor)) != 0)
	krb5_err(context, 1, ret, "get_princ_kt");
    if (!*principal) {
	if (name)
	    parse_name_realm(context, name, 0, NULL, principal);
	else
	    krb5_err(context, 1, KRB5_CC_NOTFOUND, "get_princ_kt");
    }

    krb5_free_principal(context, tmp);
    free(def_realm);
}
コード例 #21
0
ファイル: gc_via_tkt.c プロジェクト: Akasurde/krb5
static krb5_error_code
kdcrep2creds(krb5_context context, krb5_kdc_rep *pkdcrep, krb5_address *const *address,
             krb5_data *psectkt, krb5_creds **ppcreds)
{
    krb5_error_code retval;
    krb5_data *pdata;

    if ((*ppcreds = (krb5_creds *)calloc(1,sizeof(krb5_creds))) == NULL) {
        return ENOMEM;
    }

    if ((retval = krb5_copy_principal(context, pkdcrep->client,
                                      &(*ppcreds)->client)))
        goto cleanup;

    if ((retval = krb5_copy_principal(context, pkdcrep->enc_part2->server,
                                      &(*ppcreds)->server)))
        goto cleanup;

    if ((retval = krb5_copy_keyblock_contents(context,
                                              pkdcrep->enc_part2->session,
                                              &(*ppcreds)->keyblock)))
        goto cleanup;
    TRACE_TGS_REPLY(context, (*ppcreds)->client, (*ppcreds)->server,
                    &(*ppcreds)->keyblock);

    if ((retval = krb5_copy_data(context, psectkt, &pdata)))
        goto cleanup_keyblock;
    (*ppcreds)->second_ticket = *pdata;
    free(pdata);

    (*ppcreds)->ticket_flags = pkdcrep->enc_part2->flags;
    (*ppcreds)->times = pkdcrep->enc_part2->times;
    (*ppcreds)->magic = KV5M_CREDS;

    (*ppcreds)->authdata = NULL;                        /* not used */
    (*ppcreds)->is_skey = psectkt->length != 0;

    if (pkdcrep->enc_part2->caddrs) {
        if ((retval = krb5_copy_addresses(context, pkdcrep->enc_part2->caddrs,
                                          &(*ppcreds)->addresses)))
            goto cleanup_keyblock;
    } else {
        /* no addresses in the list means we got what we had */
        if ((retval = krb5_copy_addresses(context, address,
                                          &(*ppcreds)->addresses)))
            goto cleanup_keyblock;
    }

    if ((retval = encode_krb5_ticket(pkdcrep->ticket, &pdata)))
        goto cleanup_keyblock;

    (*ppcreds)->ticket = *pdata;
    free(pdata);
    return 0;

cleanup_keyblock:
    krb5_free_keyblock_contents(context, &(*ppcreds)->keyblock);

cleanup:
    free (*ppcreds);
    *ppcreds = NULL;
    return retval;
}
コード例 #22
0
ファイル: vfy_increds.c プロジェクト: jmoldow/krb5
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);
}
コード例 #23
0
ファイル: sendauth.c プロジェクト: skiselkov/illumos-gate
krb5_error_code KRB5_CALLCONV
krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer fd, char *appl_version, krb5_principal client, krb5_principal server, krb5_flags ap_req_options, krb5_data *in_data, krb5_creds *in_creds, krb5_ccache ccache, krb5_error **error, krb5_ap_rep_enc_part **rep_result, krb5_creds **out_creds)
{
	krb5_octet		result;
	krb5_creds 		creds;
	krb5_creds		 * credsp = NULL;
	krb5_creds		 * credspout = NULL;
	krb5_error_code		retval = 0;
	krb5_data		inbuf, outbuf;
	int			len;
	krb5_ccache		use_ccache = 0;

	if (error)
	    *error = 0;

	/*
	 * First, send over the length of the sendauth version string;
	 * then, we send over the sendauth version.  Next, we send
	 * over the length of the application version strings followed
	 * by the string itself.
	 */
	outbuf.length = strlen(sendauth_version) + 1;
	outbuf.data = (char *) sendauth_version;
	if ((retval = krb5_write_message(context, fd, &outbuf)))
		return(retval);
	outbuf.length = strlen(appl_version) + 1;
	outbuf.data = appl_version;
	if ((retval = krb5_write_message(context, fd, &outbuf)))
		return(retval);
	/*
	 * Now, read back a byte: 0 means no error, 1 means bad sendauth
	 * version, 2 means bad application version
	 */
    if ((len = krb5_net_read(context, *((int *) fd), (char *)&result, 1)) != 1)
	return((len < 0) ? errno : ECONNABORTED);
    if (result == 1)
	return(KRB5_SENDAUTH_BADAUTHVERS);
    else if (result == 2)
	return(KRB5_SENDAUTH_BADAPPLVERS);
    else if (result != 0)
	return(KRB5_SENDAUTH_BADRESPONSE);
	/*
	 * We're finished with the initial negotiations; let's get and
	 * send over the authentication header.  (The AP_REQ message)
	 */

	/*
	 * If no credentials were provided, try getting it from the
	 * credentials cache.
	 */
	memset((char *)&creds, 0, sizeof(creds));

	/*
	 * See if we need to access the credentials cache
	 */
	if (!in_creds || !in_creds->ticket.length) {
		if (ccache)
			use_ccache = ccache;
		/* Solaris Kerberos */
		else if ((retval = krb5int_cc_default(context, &use_ccache)) != 0)
			goto error_return;
	}
	if (!in_creds) {
		if ((retval = krb5_copy_principal(context, server,
						  &creds.server)))
			goto error_return;
		if (client)
			retval = krb5_copy_principal(context, client,
						     &creds.client);
		else
			retval = krb5_cc_get_principal(context, use_ccache,
						       &creds.client);
		if (retval) {
			krb5_free_principal(context, creds.server);
			goto error_return;
		}
		/* creds.times.endtime = 0; -- memset 0 takes care of this
					zero means "as long as possible" */
		/* creds.keyblock.enctype = 0; -- as well as this.
					zero means no session enctype
					preference */
		in_creds = &creds;
	}
	if (!in_creds->ticket.length) {
		/* Solaris Kerberos */
	    if ((retval = krb5_get_credentials(context, 0,
					       use_ccache, in_creds, &credsp)) != 0)
		    goto error_return;
	    credspout = credsp;
	} else {
	    credsp = in_creds;
	}

	if (ap_req_options & AP_OPTS_USE_SUBKEY) {
	    /* Provide some more fodder for random number code.
	       This isn't strong cryptographically; the point here is
	       not to guarantee randomness, but to make it less likely
	       that multiple sessions could pick the same subkey.  */
	    char rnd_data[1024];
	    GETPEERNAME_ARG3_TYPE len2;
	    krb5_data d;
	    d.length = sizeof (rnd_data);
	    d.data = rnd_data;
	    len2 = sizeof (rnd_data);
	    if (getpeername (*(int*)fd, (GETPEERNAME_ARG2_TYPE *) rnd_data,
			     &len2) == 0) {
		d.length = len2;
		/* Solaris Kerberos */
		(void) krb5_c_random_seed (context, &d);
	    }
	    len2 = sizeof (rnd_data);
	    if (getsockname (*(int*)fd, (GETSOCKNAME_ARG2_TYPE *) rnd_data,
			     &len2) == 0) {
		d.length = len2;
		/* Solaris Kerberos */
		(void) krb5_c_random_seed (context, &d);
	    }
	}

	/* Solaris Kerberos */
	if ((retval = krb5_mk_req_extended(context, auth_context,
					   ap_req_options, in_data, credsp,
					   &outbuf)) != 0)
	    goto error_return;

	/*
	 * First write the length of the AP_REQ message, then write
	 * the message itself.
	 */
	retval = krb5_write_message(context, fd, &outbuf);
	free(outbuf.data);
	if (retval)
	    goto error_return;

	/*
	 * Now, read back a message.  If it was a null message (the
	 * length was zero) then there was no error.  If not, we the
	 * authentication was rejected, and we need to return the
	 * error structure.
	 */
	/* Solaris Kerberos */
	if ((retval = krb5_read_message(context, fd, &inbuf)) != 0)
	    goto error_return;

	if (inbuf.length) {
		if (error) {
		    /* Solaris Kerberos */
		    if ((retval = krb5_rd_error(context, &inbuf, error)) != 0) {
			krb5_xfree(inbuf.data);
			goto error_return;
		    }
		}
		retval = KRB5_SENDAUTH_REJECTED;
		krb5_xfree(inbuf.data);
		goto error_return;
	}

	/*
	 * If we asked for mutual authentication, we should now get a
	 * length field, followed by a AP_REP message
	 */
	if ((ap_req_options & AP_OPTS_MUTUAL_REQUIRED)) {
	    krb5_ap_rep_enc_part	*repl = 0;
	    /* Solaris Kerberos */
	    if ((retval = krb5_read_message(context, fd, &inbuf)) != 0)
		goto error_return;

	    /* Solaris Kerberos */
	    if ((retval = krb5_rd_rep(context, *auth_context, &inbuf,
				      &repl)) != 0) {
		if (repl)
		    krb5_free_ap_rep_enc_part(context, repl);
	        krb5_xfree(inbuf.data);
		goto error_return;
	    }

	    krb5_xfree(inbuf.data);
	    /*
	     * If the user wants to look at the AP_REP message,
	     * copy it for them.
	     */
	    if (rep_result)
		*rep_result = repl;
	    else
		krb5_free_ap_rep_enc_part(context, repl);
	}
	retval = 0;		/* Normal return */
	if (out_creds) {
	    *out_creds = credsp;
	    credspout = NULL;
	}

error_return:
    krb5_free_cred_contents(context, &creds);
    if (credspout != NULL)
	krb5_free_creds(context, credspout);
    /* Solaris Kerberos */
    if (!ccache && use_ccache)
	(void) krb5_cc_close(context, use_ccache);
    return(retval);
}
コード例 #24
0
ファイル: add_cred.c プロジェクト: abokth/heimdal
OM_uint32 GSSAPI_CALLCONV _gsskrb5_add_cred (
     OM_uint32           *minor_status,
     gss_const_cred_id_t input_cred_handle,
     gss_const_name_t    desired_name,
     const gss_OID       desired_mech,
     gss_cred_usage_t    cred_usage,
     OM_uint32           initiator_time_req,
     OM_uint32           acceptor_time_req,
     gss_cred_id_t       *output_cred_handle,
     gss_OID_set         *actual_mechs,
     OM_uint32           *initiator_time_rec,
     OM_uint32           *acceptor_time_rec)
{
    krb5_context context;
    OM_uint32 ret, lifetime;
    gsskrb5_cred cred, handle;
    krb5_const_principal dname;

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

    GSSAPI_KRB5_INIT (&context);

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

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

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

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

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

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

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

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

	ret = GSS_S_FAILURE;

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

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

	    ret = GSS_S_FAILURE;

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

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

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

	    ret = GSS_S_FAILURE;

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

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

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

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

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

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

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

    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);

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

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

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

    *minor_status = 0;
    return ret;

 failure:

    if (handle) {
	if (handle->principal)
	    krb5_free_principal(context, handle->principal);
	if (handle->keytab)
	    krb5_kt_close(context, handle->keytab);
	if (handle->ccache)
	    krb5_cc_destroy(context, handle->ccache);
	if (handle->mechanisms)
	    gss_release_oid_set(NULL, &handle->mechanisms);
	free(handle);
    }
    if (output_cred_handle)
	HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
    return ret;
}
コード例 #25
0
ファイル: get_cred.c プロジェクト: Alexandr-Galko/samba
static krb5_error_code
get_cred_kdc_referral(krb5_context context,
		      krb5_kdc_flags flags,
		      krb5_ccache ccache,
		      krb5_creds *in_creds,
		      krb5_principal impersonate_principal,
		      Ticket *second_ticket,			
		      krb5_creds **out_creds,
		      krb5_creds ***ret_tgts)
{
    krb5_const_realm client_realm;
    krb5_error_code ret;
    krb5_creds tgt, referral, ticket;
    int loop = 0;
    int ok_as_delegate = 1;

    if (in_creds->server->name.name_string.len < 2 && !flags.b.canonicalize) {
	krb5_set_error_message(context, KRB5KDC_ERR_PATH_NOT_ACCEPTED,
			       N_("Name too short to do referals, skipping", ""));
	return KRB5KDC_ERR_PATH_NOT_ACCEPTED;
    }

    memset(&tgt, 0, sizeof(tgt));
    memset(&ticket, 0, sizeof(ticket));

    flags.b.canonicalize = 1;

    *out_creds = NULL;

    client_realm = krb5_principal_get_realm(context, in_creds->client);

    /* find tgt for the clients base realm */
    {
	krb5_principal tgtname;
	
	ret = krb5_make_principal(context, &tgtname,
				  client_realm,
				  KRB5_TGS_NAME,
				  client_realm,
				  NULL);
	if(ret)
	    return ret;
	
	ret = find_cred(context, ccache, tgtname, *ret_tgts, &tgt);
	krb5_free_principal(context, tgtname);
	if (ret)
	    return ret;
    }

    referral = *in_creds;
    ret = krb5_copy_principal(context, in_creds->server, &referral.server);
    if (ret) {
	krb5_free_cred_contents(context, &tgt);
	return ret;
    }
    ret = krb5_principal_set_realm(context, referral.server, client_realm);
    if (ret) {
	krb5_free_cred_contents(context, &tgt);
	krb5_free_principal(context, referral.server);
	return ret;
    }

    while (loop++ < 17) {
	krb5_creds **tickets;
	krb5_creds mcreds;
	char *referral_realm;

	/* Use cache if we are not doing impersonation or contrainte deleg */
	if (impersonate_principal == NULL || flags.b.constrained_delegation) {
	    krb5_cc_clear_mcred(&mcreds);
	    mcreds.server = referral.server;
	    ret = krb5_cc_retrieve_cred(context, ccache, 0, &mcreds, &ticket);
	} else
	    ret = EINVAL;

	if (ret) {
	    ret = get_cred_kdc_address(context, ccache, flags, NULL,
				       &referral, &tgt, impersonate_principal,
				       second_ticket, &ticket);
	    if (ret)
		goto out;
	}

	/* Did we get the right ticket ? */
	if (krb5_principal_compare_any_realm(context,
					     referral.server,
					     ticket.server))
	    break;

	if (!krb5_principal_is_krbtgt(context, ticket.server)) {
	    krb5_set_error_message(context, KRB5KRB_AP_ERR_NOT_US,
				   N_("Got back an non krbtgt "
				      "ticket referrals", ""));
	    ret = KRB5KRB_AP_ERR_NOT_US;
	    goto out;
	}

	referral_realm = ticket.server->name.name_string.val[1];

	/* check that there are no referrals loops */
	tickets = *ret_tgts;

	krb5_cc_clear_mcred(&mcreds);
	mcreds.server = ticket.server;

	while(tickets && *tickets){
	    if(krb5_compare_creds(context,
				  KRB5_TC_DONT_MATCH_REALM,
				  &mcreds,
				  *tickets))
	    {
		krb5_set_error_message(context, KRB5_GET_IN_TKT_LOOP,
				       N_("Referral from %s "
					  "loops back to realm %s", ""),
				       tgt.server->realm,
				       referral_realm);
		ret = KRB5_GET_IN_TKT_LOOP;
                goto out;
	    }
	    tickets++;
	}	

	/* 
	 * if either of the chain or the ok_as_delegate was stripped
	 * by the kdc, make sure we strip it too.
	 */

	if (ok_as_delegate == 0 || ticket.flags.b.ok_as_delegate == 0) {
	    ok_as_delegate = 0;
	    ticket.flags.b.ok_as_delegate = 0;
	}

	ret = add_cred(context, &ticket, ret_tgts);
	if (ret)
	    goto out;

	/* try realm in the referral */
	ret = krb5_principal_set_realm(context,
				       referral.server,
				       referral_realm);
	krb5_free_cred_contents(context, &tgt);
	tgt = ticket;
	memset(&ticket, 0, sizeof(ticket));
	if (ret)
	    goto out;
    }

    ret = krb5_copy_creds(context, &ticket, out_creds);

out:
    krb5_free_principal(context, referral.server);
    krb5_free_cred_contents(context, &tgt);
    krb5_free_cred_contents(context, &ticket);
    return ret;
}
コード例 #26
0
ファイル: mk_cred.c プロジェクト: Akasurde/krb5
static krb5_error_code
krb5_mk_ncred_basic(krb5_context context,
                    krb5_creds **ppcreds, krb5_int32 nppcreds,
                    krb5_key key, krb5_replay_data *replaydata,
                    krb5_address *local_addr, krb5_address *remote_addr,
                    krb5_cred *pcred)
{
    krb5_cred_enc_part    credenc;
    krb5_error_code       retval;
    size_t                size;
    int                   i;

    credenc.magic = KV5M_CRED_ENC_PART;

    credenc.s_address = 0;
    credenc.r_address = 0;
    if (local_addr) krb5_copy_addr(context, local_addr, &credenc.s_address);
    if (remote_addr) krb5_copy_addr(context, remote_addr, &credenc.r_address);

    credenc.nonce = replaydata->seq;
    credenc.usec = replaydata->usec;
    credenc.timestamp = replaydata->timestamp;

    /* Get memory for creds and initialize it */
    size = sizeof(krb5_cred_info *) * (nppcreds + 1);
    credenc.ticket_info = (krb5_cred_info **) calloc(1, size);
    if (credenc.ticket_info == NULL)
        return ENOMEM;

    /*
     * For each credential in the list, initialize a cred info
     * structure and copy the ticket into the ticket list.
     */
    for (i = 0; i < nppcreds; i++) {
        credenc.ticket_info[i] = calloc(1, sizeof(krb5_cred_info));
        if (credenc.ticket_info[i] == NULL) {
            retval = ENOMEM;
            goto cleanup;
        }
        credenc.ticket_info[i+1] = NULL;

        credenc.ticket_info[i]->magic = KV5M_CRED_INFO;
        credenc.ticket_info[i]->times = ppcreds[i]->times;
        credenc.ticket_info[i]->flags = ppcreds[i]->ticket_flags;

        if ((retval = decode_krb5_ticket(&ppcreds[i]->ticket,
                                         &pcred->tickets[i])))
            goto cleanup;

        if ((retval = krb5_copy_keyblock(context, &ppcreds[i]->keyblock,
                                         &credenc.ticket_info[i]->session)))
            goto cleanup;

        if ((retval = krb5_copy_principal(context, ppcreds[i]->client,
                                          &credenc.ticket_info[i]->client)))
            goto cleanup;

        if ((retval = krb5_copy_principal(context, ppcreds[i]->server,
                                          &credenc.ticket_info[i]->server)))
            goto cleanup;

        if ((retval = krb5_copy_addresses(context, ppcreds[i]->addresses,
                                          &credenc.ticket_info[i]->caddrs)))
            goto cleanup;
    }

    /*
     * NULL terminate the lists.
     */
    pcred->tickets[i] = NULL;

    /* encrypt the credential encrypted part */
    retval = encrypt_credencpart(context, &credenc, key, &pcred->enc_part);

cleanup:
    krb5_free_cred_enc_part(context, &credenc);
    return retval;
}
コード例 #27
0
ファイル: sss_krb5.c プロジェクト: 3van/sssd
krb5_error_code find_principal_in_keytab(krb5_context ctx,
                                         krb5_keytab keytab,
                                         const char *pattern_primary,
                                         const char *pattern_realm,
                                         krb5_principal *princ)
{
    krb5_error_code kerr;
    krb5_error_code kt_err;
    krb5_error_code kerr_d;
    krb5_kt_cursor cursor;
    krb5_keytab_entry entry;
    bool principal_found = false;

    memset(&cursor, 0, sizeof(cursor));
    kerr = krb5_kt_start_seq_get(ctx, keytab, &cursor);
    if (kerr != 0) {
        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_kt_start_seq_get failed.\n");
        return kerr;
    }

    DEBUG(SSSDBG_TRACE_ALL,
          "Trying to find principal %s@%s in keytab.\n", pattern_primary, pattern_realm);
    memset(&entry, 0, sizeof(entry));
    while ((kt_err = krb5_kt_next_entry(ctx, keytab, &entry, &cursor)) == 0) {
        principal_found = match_principal(ctx, entry.principal, pattern_primary, pattern_realm);
        if (principal_found) {
            break;
        }

        kerr = sss_krb5_free_keytab_entry_contents(ctx, &entry);
        if (kerr != 0) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Failed to free keytab entry.\n");
        }
        memset(&entry, 0, sizeof(entry));
    }

    /* Close the keytab here.  Even though we're using cursors, the file
     * handle is stored in the krb5_keytab structure, and it gets
     * overwritten by other keytab calls, creating a leak. */
    kerr = krb5_kt_end_seq_get(ctx, keytab, &cursor);
    if (kerr != 0) {
        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_kt_end_seq_get failed.\n");
        goto done;
    }

    if (!principal_found) {
        kerr = KRB5_KT_NOTFOUND;
        DEBUG(SSSDBG_TRACE_FUNC,
              "No principal matching %s@%s found in keytab.\n",
               pattern_primary, pattern_realm);
        goto done;
    }

    /* check if we got any errors from krb5_kt_next_entry */
    if (kt_err != 0 && kt_err != KRB5_KT_END) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Error while reading keytab.\n");
        goto done;
    }

    kerr = krb5_copy_principal(ctx, entry.principal, princ);
    if (kerr != 0) {
        DEBUG(SSSDBG_CRIT_FAILURE, "krb5_copy_principal failed.\n");
        goto done;
    }

    kerr = 0;

done:
    kerr_d = sss_krb5_free_keytab_entry_contents(ctx, &entry);
    if (kerr_d != 0) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Failed to free keytab entry.\n");
    }

    return kerr;
}
コード例 #28
0
ファイル: kimpersonate.c プロジェクト: 2asoft/freebsd
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;
}
コード例 #29
0
ファイル: get_cred.c プロジェクト: Kendra123/heimdal
static krb5_error_code
get_cred_kdc(krb5_context context,
	     krb5_ccache id,
	     krb5_kdc_flags flags,
	     krb5_addresses *addresses,
	     krb5_creds *in_creds,
	     krb5_creds *krbtgt,
	     krb5_principal impersonate_principal,
	     Ticket *second_ticket,
	     krb5_creds *out_creds)
{
    TGS_REQ req;
    krb5_data enc;
    krb5_data resp;
    krb5_kdc_rep rep;
    KRB_ERROR error;
    krb5_error_code ret;
    unsigned nonce;
    krb5_keyblock *subkey = NULL;
    size_t len = 0;
    Ticket second_ticket_data;
    METHOD_DATA padata;

    krb5_data_zero(&resp);
    krb5_data_zero(&enc);
    padata.val = NULL;
    padata.len = 0;

    krb5_generate_random_block(&nonce, sizeof(nonce));
    nonce &= 0xffffffff;

    if(flags.b.enc_tkt_in_skey && second_ticket == NULL){
	ret = decode_Ticket(in_creds->second_ticket.data,
			    in_creds->second_ticket.length,
			    &second_ticket_data, &len);
	if(ret)
	    return ret;
	second_ticket = &second_ticket_data;
    }


    if (impersonate_principal) {
	krb5_crypto crypto;
	PA_S4U2Self self;
	krb5_data data;
	void *buf;
	size_t size = 0;

	self.name = impersonate_principal->name;
	self.realm = impersonate_principal->realm;
	self.auth = estrdup("Kerberos");

	ret = _krb5_s4u2self_to_checksumdata(context, &self, &data);
	if (ret) {
	    free(self.auth);
	    goto out;
	}

	ret = krb5_crypto_init(context, &krbtgt->session, 0, &crypto);
	if (ret) {
	    free(self.auth);
	    krb5_data_free(&data);
	    goto out;
	}

	ret = krb5_create_checksum(context,
				   crypto,
				   KRB5_KU_OTHER_CKSUM,
				   0,
				   data.data,
				   data.length,
				   &self.cksum);
	krb5_crypto_destroy(context, crypto);
	krb5_data_free(&data);
	if (ret) {
	    free(self.auth);
	    goto out;
	}

	ASN1_MALLOC_ENCODE(PA_S4U2Self, buf, len, &self, &size, ret);
	free(self.auth);
	free_Checksum(&self.cksum);
	if (ret)
	    goto out;
	if (len != size)
	    krb5_abortx(context, "internal asn1 error");

	ret = krb5_padata_add(context, &padata, KRB5_PADATA_FOR_USER, buf, len);
	if (ret)
	    goto out;
    }

    ret = init_tgs_req (context,
			id,
			addresses,
			flags,
			second_ticket,
			in_creds,
			krbtgt,
			nonce,
			&padata,
			&subkey,
			&req);
    if (ret)
	goto out;

    ASN1_MALLOC_ENCODE(TGS_REQ, enc.data, enc.length, &req, &len, ret);
    if (ret)
	goto out;
    if(enc.length != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");

    /* don't free addresses */
    req.req_body.addresses = NULL;
    free_TGS_REQ(&req);

    /*
     * Send and receive
     */
    {
	krb5_sendto_ctx stctx;
	ret = krb5_sendto_ctx_alloc(context, &stctx);
	if (ret)
	    return ret;
	krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);

	ret = krb5_sendto_context (context, stctx, &enc,
				   krbtgt->server->name.name_string.val[1],
				   &resp);
	krb5_sendto_ctx_free(context, stctx);
    }
    if(ret)
	goto out;

    memset(&rep, 0, sizeof(rep));
    if(decode_TGS_REP(resp.data, resp.length, &rep.kdc_rep, &len) == 0) {
	unsigned eflags = 0;

	ret = krb5_copy_principal(context,
				  in_creds->client,
				  &out_creds->client);
	if(ret)
	    goto out2;
	ret = krb5_copy_principal(context,
				  in_creds->server,
				  &out_creds->server);
	if(ret)
	    goto out2;
	/* this should go someplace else */
	out_creds->times.endtime = in_creds->times.endtime;

	/* XXX should do better testing */
	if (flags.b.constrained_delegation || impersonate_principal)
	    eflags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;

	ret = _krb5_extract_ticket(context,
				   &rep,
				   out_creds,
				   &krbtgt->session,
				   NULL,
				   0,
				   &krbtgt->addresses,
				   nonce,
				   eflags,
				   NULL,
				   decrypt_tkt_with_subkey,
				   subkey);
    out2:
	krb5_free_kdc_rep(context, &rep);
    } else if(krb5_rd_error(context, &resp, &error) == 0) {
	ret = krb5_error_from_rd_error(context, &error, in_creds);
	krb5_free_error_contents(context, &error);
    } else if(resp.length > 0 && ((char*)resp.data)[0] == 4) {
	ret = KRB5KRB_AP_ERR_V4_REPLY;
	krb5_clear_error_message(context);
    } else {
	ret = KRB5KRB_AP_ERR_MSG_TYPE;
	krb5_clear_error_message(context);
    }

out:
    if (second_ticket == &second_ticket_data)
	free_Ticket(&second_ticket_data);
    free_METHOD_DATA(&padata);
    krb5_data_free(&resp);
    krb5_data_free(&enc);
    if(subkey)
	krb5_free_keyblock(context, subkey);
    return ret;

}
コード例 #30
0
int Condor_Auth_Kerberos :: init_user()
{
    int             rc = TRUE;
    krb5_error_code code;
    krb5_ccache     ccache = (krb5_ccache) NULL;
    krb5_creds      mcreds;

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

    dprintf(D_SECURITY, "Acquiring credential for user\n");

    //------------------------------------------
    // First, try the default credential cache
    //------------------------------------------
    ccname_ = strdup(krb5_cc_default_name(krb_context_));
    
    if ((code = krb5_cc_resolve(krb_context_, ccname_, &ccache))) {
        goto error;
    }
    
    //------------------------------------------
    // Get principal info
    //------------------------------------------
    if ((code = krb5_cc_get_principal(krb_context_, ccache, &krb_principal_))) {
        goto error;
    }

    if ((code = krb5_copy_principal(krb_context_,krb_principal_,&mcreds.client))){
        goto error;
    }
    
    if ((code = krb5_copy_principal(krb_context_, server_, &mcreds.server))) {
        goto error;
    }
    
   	dprintf_krb5_principal ( D_FULLDEBUG, "init_user: pre mcreds->client is '%s'\n", mcreds.client);
	dprintf_krb5_principal ( D_FULLDEBUG, "init_user: pre mcreds->server is '%s'\n", mcreds.server);
	if (creds_) {
		dprintf_krb5_principal ( D_FULLDEBUG, "init_user: pre creds_->client is '%s'\n", creds_->client);
		dprintf_krb5_principal ( D_FULLDEBUG, "init_user: pre creds_->server is '%s'\n", creds_->server);
	} else {
		dprintf ( D_FULLDEBUG, "init_user: pre creds_ is NULL\n");
	}		

    if ((code = krb5_get_credentials(krb_context_, 0, ccache, &mcreds, &creds_))) {
        goto error;
    }                                   

	dprintf_krb5_principal ( D_FULLDEBUG, "init_user: post mcreds->client is '%s'\n", mcreds.client);
	dprintf_krb5_principal ( D_FULLDEBUG, "init_user: post mcreds->server is '%s'\n", mcreds.server);
	if (creds_) {
		dprintf_krb5_principal ( D_FULLDEBUG, "init_user: post creds_->client is '%s'\n", creds_->client);
		dprintf_krb5_principal ( D_FULLDEBUG, "init_user: post creds_->server is '%s'\n", creds_->server);
	} else {
		dprintf ( D_FULLDEBUG, "init_user: post creds_ is NULL\n");
	}		
    
    dprintf(D_SECURITY, "Successfully located credential cache\n");
    
    rc = TRUE;
    goto cleanup;
    
 error:
    dprintf( D_ALWAYS, "KERBEROS: %s\n", error_message(code) );
    rc = FALSE;

 cleanup:

    krb5_free_cred_contents(krb_context_, &mcreds);

    if (ccache) {  // maybe should destroy this
        krb5_cc_close(krb_context_, ccache);
    }
    return rc;
}