Example #1
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_rd_req_out_get_keyblock(krb5_context context,
			     krb5_rd_req_out_ctx out,
			     krb5_keyblock **keyblock)
{
    return krb5_copy_keyblock(context, out->keyblock, keyblock);
}
mit_krb5_error_code KRB5_CALLCONV
krb5_kt_read_service_key(mit_krb5_context context,
			 mit_krb5_pointer keyprocarg,
			 mit_krb5_principal principal,
			 mit_krb5_kvno vno,
			 mit_krb5_enctype enctype,
			 mit_krb5_keyblock **key)
{
    mit_krb5_keytab keytab;
    mit_krb5_keytab_entry entry;
    mit_krb5_error_code ret;

    LOG_ENTRY();

    if (keyprocarg)
	ret = krb5_kt_resolve (context, keyprocarg, &keytab);
    else
	ret = krb5_kt_default (context, &keytab);

    if (ret)
	return ret;

    ret = krb5_kt_get_entry (context, keytab, principal, vno, enctype, &entry);
    krb5_kt_close (context, keytab);
    if (ret)
	return ret;
    ret = krb5_copy_keyblock (context, &entry.key, key);
    krb5_kt_free_entry(context, &entry);
    return ret;
}
Example #3
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_read_service_key(krb5_context context,
			 krb5_pointer keyprocarg,
			 krb5_principal principal,
			 krb5_kvno vno,
			 krb5_enctype enctype,
			 krb5_keyblock **key)
{
    krb5_keytab keytab;
    krb5_keytab_entry entry;
    krb5_error_code ret;

    if (keyprocarg)
	ret = krb5_kt_resolve (context, keyprocarg, &keytab);
    else
	ret = krb5_kt_default (context, &keytab);

    if (ret)
	return ret;

    ret = krb5_kt_get_entry (context, keytab, principal, vno, enctype, &entry);
    krb5_kt_close (context, keytab);
    if (ret)
	return ret;
    ret = krb5_copy_keyblock (context, &entry.keyblock, key);
    krb5_kt_free_entry(context, &entry);
    return ret;
}
Example #4
0
static krb5_error_code
HMAC_MD5_any_checksum(krb5_context context,
		      const krb5_keyblock *key,
		      const void *data,
		      size_t len,
		      unsigned usage,
		      Checksum *result)
{
    struct key_data local_key;
    krb5_error_code ret;

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

    ret = krb5_copy_keyblock(context, key, &local_key.key);
    if (ret)
	return ret;

    ret = krb5_data_alloc (&result->checksum, 16);
    if (ret) {
	krb5_free_keyblock(context, local_key.key);
	return ret;
    }

    result->cksumtype = CKSUMTYPE_HMAC_MD5;
    ret = _krb5_HMAC_MD5_checksum(context, &local_key, data, len, usage, result);
    if (ret)
	krb5_data_free(&result->checksum);
    
    krb5_free_keyblock(context, local_key.key);
    return ret;
}
Example #5
0
KRB5_DEPRECATED
KRB5_LIB_FUNCTION krb5_error_code KRB5_CALLCONV
krb5_keytab_key_proc (krb5_context context,
		      krb5_enctype enctype,
		      krb5_salt salt,
		      krb5_const_pointer keyseed,
		      krb5_keyblock **key)
{
    krb5_keytab_key_proc_args *args  = rk_UNCONST(keyseed);
    krb5_keytab keytab = args->keytab;
    krb5_principal principal  = args->principal;
    krb5_error_code ret;
    krb5_keytab real_keytab;
    krb5_keytab_entry entry;

    if(keytab == NULL)
	krb5_kt_default(context, &real_keytab);
    else
	real_keytab = keytab;

    ret = krb5_kt_get_entry (context, real_keytab, principal,
			     0, enctype, &entry);

    if (keytab == NULL)
	krb5_kt_close (context, real_keytab);

    if (ret)
	return ret;

    ret = krb5_copy_keyblock (context, &entry.keyblock, key);
    krb5_kt_free_entry(context, &entry);
    return ret;
}
Example #6
0
static krb5_error_code
keyblock_key_proc(krb5_context context, krb5_enctype enctype,
		  krb5_const_pointer keyseed,
		  krb5_salt salt, krb5_data *s2kparms,
		  krb5_keyblock **key)
{
    return krb5_copy_keyblock (context, keyseed, key);
}
Example #7
0
static krb5_error_code KRB5_CALLCONV
krb5_skey_key_proc (krb5_context context,
		    krb5_enctype type,
		    krb5_salt salt,
		    krb5_const_pointer keyseed,
		    krb5_keyblock **key)
{
    return krb5_copy_keyblock (context, keyseed, key);
}
Example #8
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_keyblock_key_proc (krb5_context context,
			krb5_keytype type,
			krb5_data *salt,
			krb5_const_pointer keyseed,
			krb5_keyblock **key)
{
    return krb5_copy_keyblock (context, keyseed, key);
}
Example #9
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_auth_con_setuserkey(krb5_context context,
			 krb5_auth_context auth_context,
			 krb5_keyblock *keyblock)
{
    if(auth_context->keyblock)
	krb5_free_keyblock(context, auth_context->keyblock);
    return krb5_copy_keyblock(context, keyblock, &auth_context->keyblock);
}
Example #10
0
static krb5_error_code
copy_key(krb5_context context,
	 krb5_keyblock *in,
	 krb5_keyblock **out)
{
    if(in)
	return krb5_copy_keyblock(context, in, out);
    *out = NULL; /* is this right? */
    return 0;
}
Example #11
0
static krb5_error_code
krb5_generate_authenticator(krb5_context context, krb5_authenticator *authent,
			    krb5_principal client, krb5_checksum *cksum,
			    krb5_keyblock *key, krb5_ui_4 seq_number,
			    krb5_authdata **authorization,
			    krb5_authdata_context ad_context,
			    krb5_enctype *desired_etypes,
			    krb5_enctype tkt_enctype)
{
    krb5_error_code retval;
    krb5_authdata **ext_authdata = NULL;

    authent->client = client;
    authent->checksum = cksum;
    if (key) {
	retval = krb5_copy_keyblock(context, key, &authent->subkey);
	if (retval)
	    return retval;
    } else
	authent->subkey = 0;
    authent->seq_number = seq_number;
    authent->authorization_data = NULL;

    if (ad_context != NULL) {
	retval = krb5_authdata_export_authdata(context,
					       ad_context,
					       AD_USAGE_AP_REQ,
					       &ext_authdata);
	if (retval)
	    return retval;
    }

    if (authorization != NULL || ext_authdata != NULL) {
	retval = krb5_merge_authdata(context,
				     authorization,
				     ext_authdata,
				     &authent->authorization_data);
	if (retval) {
	    krb5_free_authdata(context, ext_authdata);
	    return retval;
	}
	krb5_free_authdata(context, ext_authdata);
    }

    /* Only send EtypeList if we prefer another enctype to tkt_enctype */
    if (desired_etypes != NULL && desired_etypes[0] != tkt_enctype) {
	retval = make_etype_list(context, desired_etypes, tkt_enctype,
				 &authent->authorization_data);
	if (retval)
	    return retval;
    }

    return(krb5_us_timeofday(context, &authent->ctime, &authent->cusec));
}
Example #12
0
krb5_error_code KRB5_CALLCONV
krb5_copy_authenticator(krb5_context context, const krb5_authenticator *authfrom, krb5_authenticator **authto)
{
    krb5_error_code retval;
    krb5_authenticator *tempto;

    if (!(tempto = (krb5_authenticator *)MALLOC(sizeof(*tempto))))
	return ENOMEM;
#ifdef HAVE_C_STRUCTURE_ASSIGNMENT
    *tempto = *authfrom;
#else
    (void) memcpy(tempto, authfrom, sizeof(krb5_authenticator));
#endif

    retval = krb5_copy_principal(context, authfrom->client, &tempto->client);
    if (retval) {
	krb5_xfree_wrap(tempto, sizeof(*tempto));
	return retval;
    }
    
    if (authfrom->checksum &&
	(retval = krb5_copy_checksum(context, authfrom->checksum, &tempto->checksum))) {
	    krb5_free_principal(context, tempto->client);    
	    krb5_xfree_wrap(tempto, sizeof(*tempto));
	    return retval;
    }
    
    if (authfrom->subkey) {
	    retval = krb5_copy_keyblock(context, authfrom->subkey, &tempto->subkey);
	    if (retval) {
		    krb5_xfree_wrap(tempto->subkey, sizeof(krb5_keyblock));
		    krb5_free_checksum(context, tempto->checksum);
		    krb5_free_principal(context, tempto->client);    
		    krb5_xfree_wrap(tempto, sizeof(*tempto));
		    return retval;
	    }
    }
    
    if (authfrom->authorization_data) {
		retval = krb5_copy_authdata(context, authfrom->authorization_data,
				    &tempto->authorization_data);
		if (retval) {
		    krb5_xfree_wrap(tempto->subkey, sizeof(krb5_keyblock));
		    krb5_free_checksum(context, tempto->checksum);
		    krb5_free_principal(context, tempto->client);    
		    krb5_free_authdata(context, tempto->authorization_data);
		    krb5_xfree_wrap(tempto, sizeof(*tempto));
		    return retval;
		}
    }

    *authto = tempto;
    return 0;
}
Example #13
0
// Get session key from ccache or service ticket.
void DecryptionManager::PacketHandler::readServiceSessionKey(
    krb5_ticket* ticket) {
  Krb5CCache *ccache = decryptionManager_->getCCache();
  if (ccache) {
    Krb5Credentials creds = ccache->retrieveCred(ticket->server);
    krb5_copy_keyblock(ctx_->get(), &creds.get().keyblock, &sessionKey_);
  } else {
    krb5_error_code code = krb5_server_decrypt_ticket_keytab(
        ctx_->get(),
        decryptionManager_->getServerKeytab()->get(),
        ticket);
    if (code) {
      onError("Cannot decrypt service ticket using the given server keytab");
      return;
    }

    krb5_copy_keyblock(ctx_->get(),
                       ticket->enc_part2->session,
                       &sessionKey_);
  }
}
Example #14
0
static krb5_error_code
get_as_key_keytab(krb5_context context,
                  krb5_principal client,
                  krb5_enctype etype,
                  krb5_prompter_fct prompter,
                  void *prompter_data,
                  krb5_data *salt,
                  krb5_data *params,
                  krb5_keyblock *as_key,
                  void *gak_data,
                  k5_response_items *ritems)
{
    krb5_keytab keytab = (krb5_keytab) gak_data;
    krb5_error_code ret;
    krb5_keytab_entry kt_ent;
    krb5_keyblock *kt_key;

    /* We don't need the password from the responder to create the AS key. */
    if (as_key == NULL)
        return 0;

    /* if there's already a key of the correct etype, we're done.
       if the etype is wrong, free the existing key, and make
       a new one. */

    if (as_key->length) {
        if (as_key->enctype == etype)
            return(0);

        krb5_free_keyblock_contents(context, as_key);
        as_key->length = 0;
    }

    if (!krb5_c_valid_enctype(etype))
        return(KRB5_PROG_ETYPE_NOSUPP);

    if ((ret = krb5_kt_get_entry(context, keytab, client,
                                 0, /* don't have vno available */
                                 etype, &kt_ent)))
        return(ret);

    ret = krb5_copy_keyblock(context, &kt_ent.key, &kt_key);

    /* again, krb5's memory management is lame... */

    *as_key = *kt_key;
    free(kt_key);

    (void) krb5_kt_free_entry(context, &kt_ent);

    return(ret);
}
Example #15
0
void
encryption_init (krb5_creds * creds)
{
  krb5_keyblock *newkey = 0;

  krb5_auth_con_getlocalsubkey (telnet_context, auth_context, &newkey);
  if (session_key)
    {
      krb5_free_keyblock (telnet_context, session_key);
      session_key = 0;
    }

  if (newkey)
    {
      switch (newkey->enctype)
	{
	case ENCTYPE_DES_CBC_CRC:
	case ENCTYPE_DES_CBC_MD5:
	  krb5_copy_keyblock (telnet_context, newkey, &session_key);
	  break;

	default:
	  switch (creds->keyblock.enctype)
	    {
	    case ENCTYPE_DES_CBC_CRC:
	    case ENCTYPE_DES_CBC_MD5:
	      krb5_copy_keyblock (telnet_context, &creds->keyblock,
				  &session_key);
	      break;

	    default:
	      DEBUG (("can't determine which keyblock to use"));
	      /*FIXME: abort? */
	    }
	}

      krb5_free_keyblock (telnet_context, newkey);
    }
}
Example #16
0
krb5_error_code KRB5_CALLCONV
krb5_copy_authenticator(krb5_context context, const krb5_authenticator *authfrom,
                        krb5_authenticator **authto)
{
    krb5_error_code retval;
    krb5_authenticator *tempto;

    if (!(tempto = (krb5_authenticator *)malloc(sizeof(*tempto))))
        return ENOMEM;
    *tempto = *authfrom;

    retval = krb5_copy_principal(context, authfrom->client, &tempto->client);
    if (retval) {
        free(tempto);
        return retval;
    }

    if (authfrom->checksum &&
        (retval = krb5_copy_checksum(context, authfrom->checksum, &tempto->checksum))) {
        krb5_free_principal(context, tempto->client);
        free(tempto);
        return retval;
    }

    if (authfrom->subkey) {
        retval = krb5_copy_keyblock(context, authfrom->subkey, &tempto->subkey);
        if (retval) {
            free(tempto->subkey);
            krb5_free_checksum(context, tempto->checksum);
            krb5_free_principal(context, tempto->client);
            free(tempto);
            return retval;
        }
    }

    if (authfrom->authorization_data) {
        retval = krb5_copy_authdata(context, authfrom->authorization_data,
                                    &tempto->authorization_data);
        if (retval) {
            free(tempto->subkey);
            krb5_free_checksum(context, tempto->checksum);
            krb5_free_principal(context, tempto->client);
            krb5_free_authdata(context, tempto->authorization_data);
            free(tempto);
            return retval;
        }
    }

    *authto = tempto;
    return 0;
}
Example #17
0
void
ZSetSession(krb5_keyblock *keyblock) {
    krb5_error_code result;

    if (__Zephyr_keyblock) {
         krb5_free_keyblock_contents(Z_krb5_ctx, __Zephyr_keyblock);
         result = krb5_copy_keyblock_contents(Z_krb5_ctx, keyblock, __Zephyr_keyblock);
    } else {
         result = krb5_copy_keyblock(Z_krb5_ctx, keyblock, &__Zephyr_keyblock);
    }

    if (result) /*XXX we're out of memory? */
	return;
}
Example #18
0
krb5_error_code
kdc_fast_handle_reply_key(struct kdc_request_state *state,
                          krb5_keyblock *existing_key,
                          krb5_keyblock **out_key)
{
    krb5_error_code retval = 0;
    kdc_realm_t *kdc_active_realm = state->realm_data;

    if (state->armor_key)
        retval = krb5_c_fx_cf2_simple(kdc_context,
                                      state->strengthen_key, "strengthenkey",
                                      existing_key,
                                      "replykey", out_key);
    else
        retval = krb5_copy_keyblock(kdc_context, existing_key, out_key);
    return retval;
}
Example #19
0
static krb5_error_code
get_key_from_keytab(krb5_context context,
		    krb5_auth_context *auth_context,
		    krb5_ap_req *ap_req,
		    krb5_const_principal server,
		    krb5_keytab keytab,
		    krb5_keyblock **out_key)
{
    krb5_keytab_entry entry;
    krb5_error_code ret;
    int kvno;
    krb5_keytab real_keytab;

    if(keytab == NULL)
	krb5_kt_default(context, &real_keytab);
    else
	real_keytab = keytab;
    
    if (ap_req->ticket.enc_part.kvno)
	kvno = *ap_req->ticket.enc_part.kvno;
    else
	kvno = 0;

    ret = krb5_kt_get_entry (context,
			     real_keytab,
			     server,
			     kvno,
			     ap_req->ticket.enc_part.etype,
			     &entry);
    if(ret)
	goto out;
    ret = krb5_copy_keyblock(context, &entry.keyblock, out_key);
    krb5_kt_free_entry (context, &entry);
out:    
    if(keytab == NULL)
	krb5_kt_close(context, real_keytab);
    
    return ret;
}
Example #20
0
krb5_error_code
krb5int_generate_and_save_subkey (krb5_context context,
				  krb5_auth_context auth_context,
				  krb5_keyblock *keyblock,
				  krb5_enctype enctype)
{
    /* 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.  */
    struct {
	krb5_int32 sec, usec;
    } rnd_data;
    krb5_data d;
    krb5_error_code retval;

    krb5_crypto_us_timeofday (&rnd_data.sec, &rnd_data.usec);
    d.length = sizeof (rnd_data);
    d.data = (char *) &rnd_data;
    (void) krb5_c_random_add_entropy (context, KRB5_C_RANDSOURCE_TIMING, &d);

    if (auth_context->send_subkey)
	krb5_free_keyblock(context, auth_context->send_subkey);
    if ((retval = krb5_generate_subkey_extended(context, keyblock, enctype,
						&auth_context->send_subkey)))
	return retval;

    if (auth_context->recv_subkey)
	krb5_free_keyblock(context, auth_context->recv_subkey);
    retval = krb5_copy_keyblock(context, auth_context->send_subkey,
				&auth_context->recv_subkey);
    if (retval) {
	krb5_free_keyblock(context, auth_context->send_subkey);
	auth_context->send_subkey = NULL;
	return retval;
    }
    return 0;
}
Example #21
0
static krb5_error_code
HMAC_MD5_any_checksum(krb5_context context,
		      const krb5_keyblock *key,
		      const void *data,
		      size_t len,
		      unsigned usage,
		      Checksum *result)
{
    struct _krb5_key_data local_key;
    struct krb5_crypto_iov iov;
    krb5_error_code ret;

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

    ret = krb5_copy_keyblock(context, key, &local_key.key);
    if (ret)
	return ret;

    ret = krb5_data_alloc (&result->checksum, 16);
    if (ret) {
	krb5_free_keyblock(context, local_key.key);
	return ret;
    }

    result->cksumtype = CKSUMTYPE_HMAC_MD5;
    iov.data.data = (void *)data;
    iov.data.length = len;
    iov.flags = KRB5_CRYPTO_TYPE_DATA;

    ret = _krb5_HMAC_MD5_checksum(context, NULL, &local_key, usage, &iov, 1,
                                  result);
    if (ret)
	krb5_data_free(&result->checksum);

    krb5_free_keyblock(context, local_key.key);
    return ret;
}
Example #22
0
/*
 * effects: If keyprocarg is not NULL, it is taken to be the name of a 
 *	keytab.  Otherwise, the default keytab will be used.  This 
 *	routine opens the keytab and finds the principal associated with
 *	principal, vno, and enctype and returns the resulting key in *key 
 *	or returning an error code if it is not	found. 
 * returns: Either KSUCCESS or error code.
 * errors: error code if not found or keyprocarg is invalid.
 */
krb5_error_code KRB5_CALLCONV
krb5_kt_read_service_key(krb5_context context, krb5_pointer keyprocarg, krb5_principal principal, krb5_kvno vno, krb5_enctype enctype, krb5_keyblock **key)
{
    krb5_error_code kerror = KSUCCESS;
    char keytabname[MAX_KEYTAB_NAME_LEN + 1]; /* + 1 for NULL termination */
    krb5_keytab id;
    krb5_keytab_entry entry;
        
    /*
     * Get the name of the file that we should use. 
     */
    if (!keyprocarg) {
	if ((kerror = krb5_kt_default_name(context, (char *)keytabname, 
					   sizeof(keytabname) - 1))!= KSUCCESS)
	    return (kerror);
    } else {
	memset(keytabname, 0, sizeof(keytabname));
	(void) strncpy(keytabname, (char *)keyprocarg, 
		       sizeof(keytabname) - 1);
    }

    if ((kerror = krb5_kt_resolve(context, (char *)keytabname, &id)))
	return (kerror);

    kerror = krb5_kt_get_entry(context, id, principal, vno, enctype, &entry);
    krb5_kt_close(context, id);

    if (kerror)
	return(kerror);

    krb5_copy_keyblock(context, &entry.key, key);

    krb5_kt_free_entry(context, &entry);

    return (KSUCCESS);
}
Example #23
0
krb5_error_code
Z_krb5_init_keyblock(krb5_context context,
	krb5_enctype type,
	size_t size,
	krb5_keyblock **key)
{
#ifdef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
	return krb5_init_keyblock(context, type, size, key);
#else
	krb5_error_code ret;
	krb5_keyblock *tmp, tmp_ss;
	tmp = &tmp_ss;

	*key = NULL;
	Z_enctype(tmp) = type;
	Z_keylen(tmp) = size;
	Z_keydata(tmp) = malloc(size);
	if (!Z_keydata(tmp))
		return ENOMEM;
	ret =  krb5_copy_keyblock(context, tmp, key);
	free(Z_keydata(tmp));
	return ret;
#endif
}
Example #24
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_rd_req_ctx(krb5_context context,
		krb5_auth_context *auth_context,
		const krb5_data *inbuf,
		krb5_const_principal server,
		krb5_rd_req_in_ctx inctx,
		krb5_rd_req_out_ctx *outctx)
{
    krb5_error_code ret;
    krb5_ap_req ap_req;
    krb5_rd_req_out_ctx o = NULL;
    krb5_keytab id = NULL, keytab = NULL;
    krb5_principal service = NULL;

    *outctx = NULL;

    o = calloc(1, sizeof(*o));
    if (o == NULL) {
	krb5_set_error_message(context, ENOMEM,
			       N_("malloc: out of memory", ""));
	return ENOMEM;
    }

    if (*auth_context == NULL) {
	ret = krb5_auth_con_init(context, auth_context);
	if (ret)
	    goto out;
    }

    ret = krb5_decode_ap_req(context, inbuf, &ap_req);
    if(ret)
	goto out;

    /* Save that principal that was in the request */
    ret = _krb5_principalname2krb5_principal(context,
					     &o->server,
					     ap_req.ticket.sname,
					     ap_req.ticket.realm);
    if (ret)
	goto out;

    if (ap_req.ap_options.use_session_key &&
	(*auth_context)->keyblock == NULL) {
	ret = KRB5KRB_AP_ERR_NOKEY;
	krb5_set_error_message(context, ret,
			       N_("krb5_rd_req: user to user auth "
				  "without session key given", ""));
	goto out;
    }

    if (inctx && inctx->keytab)
	id = inctx->keytab;

    if((*auth_context)->keyblock){
	ret = krb5_copy_keyblock(context,
				 (*auth_context)->keyblock,
				 &o->keyblock);
	if (ret)
	    goto out;
    } else if(inctx && inctx->keyblock){
	ret = krb5_copy_keyblock(context,
				 inctx->keyblock,
				 &o->keyblock);
	if (ret)
	    goto out;
    } else {

	if(id == NULL) {
	    krb5_kt_default(context, &keytab);
	    id = keytab;
	}
	if (id == NULL)
	    goto out;

	if (server == NULL) {
	    ret = _krb5_principalname2krb5_principal(context,
						     &service,
						     ap_req.ticket.sname,
						     ap_req.ticket.realm);
	    if (ret)
		goto out;
	    server = service;
	}

	ret = get_key_from_keytab(context,
				  &ap_req,
				  server,
				  id,
				  &o->keyblock);
	if (ret) {
	    /* If caller specified a server, fail. */
	    if (service == NULL && (context->flags & KRB5_CTX_F_RD_REQ_IGNORE) == 0)
		goto out;
	    /* Otherwise, fall back to iterating over the keytab. This
	     * have serious performace issues for larger keytab.
	     */
	    o->keyblock = NULL;
	}
    }

    if (o->keyblock) {
	/*
	 * We got an exact keymatch, use that.
	 */

	ret = krb5_verify_ap_req2(context,
				  auth_context,
				  &ap_req,
				  server,
				  o->keyblock,
				  0,
				  &o->ap_req_options,
				  &o->ticket,
				  KRB5_KU_AP_REQ_AUTH);

	if (ret)
	    goto out;

    } else {
	/*
	 * Interate over keytab to find a key that can decrypt the request.
	 */

	krb5_keytab_entry entry;
	krb5_kt_cursor cursor;
	int done = 0, kvno = 0;

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

	if (ap_req.ticket.enc_part.kvno)
	    kvno = *ap_req.ticket.enc_part.kvno;

	ret = krb5_kt_start_seq_get(context, id, &cursor);
	if (ret)
	    goto out;

	done = 0;
	while (!done) {
	    krb5_principal p;

	    ret = krb5_kt_next_entry(context, id, &entry, &cursor);
	    if (ret) {
		_krb5_kt_principal_not_found(context, ret, id, o->server,
					     ap_req.ticket.enc_part.etype,
					     kvno);
		krb5_kt_end_seq_get(context, id, &cursor);
		goto out;
	    }

	    if (entry.keyblock.keytype != ap_req.ticket.enc_part.etype) {
		krb5_kt_free_entry (context, &entry);
		continue;
	    }

	    ret = krb5_verify_ap_req2(context,
				      auth_context,
				      &ap_req,
				      server,
				      &entry.keyblock,
				      0,
				      &o->ap_req_options,
				      &o->ticket,
				      KRB5_KU_AP_REQ_AUTH);
	    if (ret) {
		krb5_kt_free_entry(context, &entry);
		continue;
	    }

	    /*
	     * Found a match, save the keyblock for PAC processing,
	     * and update the service principal in the ticket to match
	     * whatever is in the keytab.
	     */

	    ret = krb5_copy_keyblock(context,
				     &entry.keyblock,
				     &o->keyblock);
	    if (ret) {
		krb5_kt_free_entry(context, &entry);
		krb5_kt_end_seq_get(context, id, &cursor);
		goto out;
	    }

	    ret = krb5_copy_principal(context, entry.principal, &p);
	    if (ret) {
		krb5_kt_free_entry(context, &entry);
		krb5_kt_end_seq_get(context, id, &cursor);
		goto out;
	    }
	    krb5_free_principal(context, o->ticket->server);
	    o->ticket->server = p;
	    
	    krb5_kt_free_entry(context, &entry);

	    done = 1;
	}
	krb5_kt_end_seq_get(context, id, &cursor);
    }

    /* If there is a PAC, verify its server signature */
    if (inctx == NULL || inctx->check_pac) {
	krb5_pac pac;
	krb5_data data;

	ret = krb5_ticket_get_authorization_data_type(context,
						      o->ticket,
						      KRB5_AUTHDATA_WIN2K_PAC,
						      &data);
	if (ret == 0) {
	    ret = krb5_pac_parse(context, data.data, data.length, &pac);
	    krb5_data_free(&data);
	    if (ret)
		goto out;

	    ret = krb5_pac_verify(context,
				  pac,
				  o->ticket->ticket.authtime,
				  o->ticket->client,
				  o->keyblock,
				  NULL);
	    krb5_pac_free(context, pac);
	    if (ret == 0)
		o->flags |= KRB5_RD_REQ_OUT_PAC_VALID;
	    ret = 0;
	} else
	    ret = 0;
    }
 out:

    if (ret || outctx == NULL) {
	krb5_rd_req_out_ctx_free(context, o);
    } else
	*outctx = o;

    free_AP_REQ(&ap_req);

    if (service)
	krb5_free_principal(context, service);

    if (keytab)
	krb5_kt_close(context, keytab);

    return ret;
}
Example #25
0
krb5_error_code KRB5_CALLCONV
krb5_rd_rep(krb5_context context, krb5_auth_context auth_context,
	    const krb5_data *inbuf, krb5_ap_rep_enc_part **repl)
{
    krb5_error_code 	  retval;
    krb5_ap_rep 	* reply;
    krb5_data 	 	  scratch;

    if (!krb5_is_ap_rep(inbuf))
	return KRB5KRB_AP_ERR_MSG_TYPE;

    /* decode it */

    if ((retval = decode_krb5_ap_rep(inbuf, &reply)))
	return retval;

    /* put together an eblock for this encryption */

    scratch.length = reply->enc_part.ciphertext.length;
    if (!(scratch.data = malloc(scratch.length))) {
	krb5_free_ap_rep(context, reply);
	return(ENOMEM);
    }

    if ((retval = krb5_c_decrypt(context, auth_context->keyblock,
				 KRB5_KEYUSAGE_AP_REP_ENCPART, 0,
				 &reply->enc_part, &scratch)))
	goto clean_scratch;

    /* now decode the decrypted stuff */
    retval = decode_krb5_ap_rep_enc_part(&scratch, repl);
    if (retval)
	goto clean_scratch;

    /* Check reply fields */
    if (((*repl)->ctime != auth_context->authentp->ctime) ||
      ((*repl)->cusec != auth_context->authentp->cusec)) {
	retval = KRB5_MUTUAL_FAILED;
	goto clean_scratch;
    }

    /* Set auth subkey */
    if ((*repl)->subkey) {
	if (auth_context->recv_subkey) {
	    krb5_free_keyblock(context, auth_context->recv_subkey);
	    auth_context->recv_subkey = NULL;
	}
	retval = krb5_copy_keyblock(context, (*repl)->subkey,
				    &auth_context->recv_subkey);
	if (retval)
	    goto clean_scratch;
	if (auth_context->send_subkey) {
	    krb5_free_keyblock(context, auth_context->send_subkey);
	    auth_context->send_subkey = NULL;
	}
	retval = krb5_copy_keyblock(context, (*repl)->subkey,
				    &auth_context->send_subkey);
	if (retval) {
	    krb5_free_keyblock(context, auth_context->send_subkey);
	    auth_context->send_subkey = NULL;
	}
	/* not used for anything yet */
	auth_context->negotiated_etype = (*repl)->subkey->enctype;
    }

    /* Get remote sequence number */
    auth_context->remote_seq_number = (*repl)->seq_number;

clean_scratch:
    memset(scratch.data, 0, scratch.length); 

    krb5_free_ap_rep(context, reply);
    free(scratch.data);
    return retval;
}
Example #26
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req_ctx(krb5_context context,
		krb5_auth_context *auth_context,
		const krb5_data *inbuf,
		krb5_const_principal server,
		krb5_rd_req_in_ctx inctx,
		krb5_rd_req_out_ctx *outctx)
{
    krb5_error_code ret;
    krb5_ap_req ap_req;
    krb5_principal service = NULL;
    krb5_rd_req_out_ctx o = NULL;

    ret = _krb5_rd_req_out_ctx_alloc(context, &o);
    if (ret)
	goto out;

    if (*auth_context == NULL) {
	ret = krb5_auth_con_init(context, auth_context);
	if (ret)
	    goto out;
    }

    ret = krb5_decode_ap_req(context, inbuf, &ap_req);
    if(ret)
	goto out;

    if(server == NULL){
	ret = _krb5_principalname2krb5_principal(context,
						 &service,
						 ap_req.ticket.sname,
						 ap_req.ticket.realm);
	if (ret)
	    goto out;
	server = service;
    }
    if (ap_req.ap_options.use_session_key &&
	(*auth_context)->keyblock == NULL) {
	krb5_set_error_string(context, "krb5_rd_req: user to user auth "
			      "without session key given");
	ret = KRB5KRB_AP_ERR_NOKEY;
	goto out;
    }

    if((*auth_context)->keyblock){
	ret = krb5_copy_keyblock(context,
				 (*auth_context)->keyblock,
				 &o->keyblock);
	if (ret)
	    goto out;
    } else if(inctx->keyblock){
	ret = krb5_copy_keyblock(context,
				 inctx->keyblock,
				 &o->keyblock);
	if (ret)
	    goto out;
    } else {
	krb5_keytab keytab = NULL;

	if (inctx && inctx->keytab)
	    keytab = inctx->keytab;

	ret = get_key_from_keytab(context, 
				  auth_context, 
				  &ap_req,
				  server,
				  keytab,
				  &o->keyblock);
	if(ret)
	    goto out;
    }

    ret = krb5_verify_ap_req2(context,
			      auth_context,
			      &ap_req,
			      server,
			      o->keyblock,
			      0,
			      &o->ap_req_options,
			      &o->ticket,
			      KRB5_KU_AP_REQ_AUTH);

    if (ret)
	goto out;

    /* If there is a PAC, verify its server signature */
    if (inctx->check_pac) {
	krb5_pac pac;
	krb5_data data;

	ret = krb5_ticket_get_authorization_data_type(context,
						      o->ticket,
						      KRB5_AUTHDATA_WIN2K_PAC,
						      &data);
	if (ret == 0) {
	    ret = krb5_pac_parse(context, data.data, data.length, &pac);
	    krb5_data_free(&data);
	    if (ret)
		goto out;
	
	    ret = krb5_pac_verify(context,
				  pac, 
				  o->ticket->ticket.authtime,
				  o->ticket->client, 
				  o->keyblock, 
				  NULL);
	    krb5_pac_free(context, pac);
	    if (ret)
		goto out;
	}
	ret = 0;
    }
out:
    if (ret || outctx == NULL) {
	krb5_rd_req_out_ctx_free(context, o);
    } else 
	*outctx = o;

    free_AP_REQ(&ap_req);
    if(service)
	krb5_free_principal(context, service);
    return ret;
}
Example #27
0
static krb5_error_code
make_seal_token_v1_iov(krb5_context context,
                       krb5_gss_ctx_id_rec *ctx,
                       int conf_req_flag,
                       int *conf_state,
                       gss_iov_buffer_desc *iov,
                       int iov_count,
                       int toktype)
{
    krb5_error_code code = 0;
    gss_iov_buffer_t header;
    gss_iov_buffer_t padding;
    gss_iov_buffer_t trailer;
    krb5_checksum md5cksum;
    krb5_checksum cksum;
    size_t k5_headerlen = 0, k5_trailerlen = 0;
    size_t data_length = 0, assoc_data_length = 0;
    size_t tmsglen = 0, tlen;
    unsigned char *ptr;
    krb5_keyusage sign_usage = KG_USAGE_SIGN;

    assert(toktype == KG_TOK_WRAP_MSG);

    md5cksum.length = cksum.length = 0;
    md5cksum.contents = cksum.contents = NULL;

    header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
    if (header == NULL)
        return EINVAL;

    padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
    if (padding == NULL && (ctx->gss_flags & GSS_C_DCE_STYLE) == 0)
        return EINVAL;

    trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
    if (trailer != NULL)
        trailer->buffer.length = 0;

    /* Determine confounder length */
    if (toktype == KG_TOK_WRAP_MSG || conf_req_flag)
        k5_headerlen = kg_confounder_size(context, ctx->enc);

    /* Check padding length */
    if (toktype == KG_TOK_WRAP_MSG) {
        size_t k5_padlen = (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) ? 1 : 8;
        size_t gss_padlen;
        size_t conf_data_length;

        kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length);
        conf_data_length = k5_headerlen + data_length - assoc_data_length;

        if (k5_padlen == 1)
            gss_padlen = 1; /* one byte to indicate one byte of padding */
        else
            gss_padlen = k5_padlen - (conf_data_length % k5_padlen);

        if (ctx->gss_flags & GSS_C_DCE_STYLE) {
            /* DCE will pad the actual data itself; padding buffer optional and will be zeroed */
            gss_padlen = 0;

            if (conf_data_length % k5_padlen)
                code = KRB5_BAD_MSIZE;
        } else if (padding->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) {
            code = kg_allocate_iov(padding, gss_padlen);
        } else if (padding->buffer.length < gss_padlen) {
            code = KRB5_BAD_MSIZE;
        }
        if (code != 0)
            goto cleanup;

        /* Initialize padding buffer to pad itself */
        if (padding != NULL) {
            padding->buffer.length = gss_padlen;
            memset(padding->buffer.value, (int)gss_padlen, gss_padlen);
        }

        if (ctx->gss_flags & GSS_C_DCE_STYLE)
            tmsglen = k5_headerlen; /* confounder length */
        else
            tmsglen = conf_data_length + padding->buffer.length + assoc_data_length;
    }

    /* Determine token size */
    tlen = g_token_size(ctx->mech_used, 14 + ctx->cksum_size + tmsglen);

    k5_headerlen += tlen - tmsglen;

    if (header->type & GSS_IOV_BUFFER_FLAG_ALLOCATE)
        code = kg_allocate_iov(header, k5_headerlen);
    else if (header->buffer.length < k5_headerlen)
        code = KRB5_BAD_MSIZE;
    if (code != 0)
        goto cleanup;

    header->buffer.length = k5_headerlen;

    ptr = (unsigned char *)header->buffer.value;
    g_make_token_header(ctx->mech_used, 14 + ctx->cksum_size + tmsglen, &ptr, toktype);

    /* 0..1 SIGN_ALG */
    store_16_le(ctx->signalg, &ptr[0]);

    /* 2..3 SEAL_ALG or Filler */
    if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) {
        store_16_le(ctx->sealalg, &ptr[2]);
    } else {
        /* No seal */
        ptr[2] = 0xFF;
        ptr[3] = 0xFF;
    }

    /* 4..5 Filler */
    ptr[4] = 0xFF;
    ptr[5] = 0xFF;

    /* pad the plaintext, encrypt if needed, and stick it in the token */

    /* initialize the checksum */
    switch (ctx->signalg) {
    case SGN_ALG_DES_MAC_MD5:
    case SGN_ALG_MD2_5:
        md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
        break;
    case SGN_ALG_HMAC_SHA1_DES3_KD:
        md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3;
        break;
    case SGN_ALG_HMAC_MD5:
        md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
        if (toktype != KG_TOK_WRAP_MSG)
            sign_usage = 15;
        break;
    default:
    case SGN_ALG_DES_MAC:
        abort ();
    }

    code = krb5_c_checksum_length(context, md5cksum.checksum_type, &k5_trailerlen);
    if (code != 0)
        goto cleanup;
    md5cksum.length = k5_trailerlen;

    if (k5_headerlen != 0) {
        code = kg_make_confounder(context, ctx->enc, ptr + 14 + ctx->cksum_size);
        if (code != 0)
            goto cleanup;
    }

    /* compute the checksum */
    code = kg_make_checksum_iov_v1(context, md5cksum.checksum_type,
                                   ctx->cksum_size, ctx->seq, ctx->enc,
                                   sign_usage, iov, iov_count, toktype,
                                   &md5cksum);
    if (code != 0)
        goto cleanup;

    switch (ctx->signalg) {
    case SGN_ALG_DES_MAC_MD5:
    case SGN_ALG_3:
        code = kg_encrypt(context, ctx->seq, KG_USAGE_SEAL,
                          (g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ?
                           ctx->seq->contents : NULL),
                          md5cksum.contents, md5cksum.contents, 16);
        if (code != 0)
            goto cleanup;

        cksum.length = ctx->cksum_size;
        cksum.contents = md5cksum.contents + 16 - cksum.length;

        memcpy(ptr + 14, cksum.contents, cksum.length);
        break;
    case SGN_ALG_HMAC_SHA1_DES3_KD:
        assert(md5cksum.length == ctx->cksum_size);
        memcpy(ptr + 14, md5cksum.contents, md5cksum.length);
        break;
    case SGN_ALG_HMAC_MD5:
        memcpy(ptr + 14, md5cksum.contents, ctx->cksum_size);
        break;
    }

    /* create the seq_num */
    code = kg_make_seq_num(context, ctx->seq, ctx->initiate ? 0 : 0xFF,
                           (OM_uint32)ctx->seq_send, ptr + 14, ptr + 6);
    if (code != 0)
        goto cleanup;

    if (conf_req_flag) {
        if (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) {
            unsigned char bigend_seqnum[4];
            krb5_keyblock *enc_key;
            size_t i;

            store_32_be(ctx->seq_send, bigend_seqnum);

            code = krb5_copy_keyblock(context, ctx->enc, &enc_key);
            if (code != 0)
                goto cleanup;

            assert(enc_key->length == 16);

            for (i = 0; i < enc_key->length; i++)
                ((char *)enc_key->contents)[i] ^= 0xF0;

            code = kg_arcfour_docrypt_iov(context, enc_key, 0,
                                          bigend_seqnum, 4,
                                          iov, iov_count);
            krb5_free_keyblock(context, enc_key);
        } else {
            code = kg_encrypt_iov(context, ctx->proto,
                                  ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0),
                                  0 /*EC*/, 0 /*RRC*/,
                                  ctx->enc, KG_USAGE_SEAL, NULL,
                                  iov, iov_count);
        }
        if (code != 0)
            goto cleanup;
    }

    ctx->seq_send++;
    ctx->seq_send &= 0xFFFFFFFFL;

    code = 0;

    if (conf_state != NULL)
        *conf_state = conf_req_flag;

cleanup:
    if (code != 0)
        kg_release_iov(iov, iov_count);
    krb5_free_checksum_contents(context, &md5cksum);

    return code;
}
Example #28
0
static krb5_error_code
krb5_rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context,
			const krb5_ap_req *req, krb5_const_principal server,
			krb5_keytab keytab, krb5_flags *ap_req_options,
			krb5_ticket **ticket, int check_valid_flag)
{
    krb5_error_code 	  retval = 0;
    krb5_timestamp 	  currenttime;
    krb5_principal_data princ_data;
    
    req->ticket->enc_part2 == NULL;
    if (server && krb5_is_referral_realm(&server->realm)) {
	char *realm;
	princ_data = *server;
	server = &princ_data;
	retval = krb5_get_default_realm(context, &realm);
	if (retval)
	    return retval;
	princ_data.realm.data = realm;
	princ_data.realm.length = strlen(realm);
    }
    if (server && !krb5_principal_compare(context, server, req->ticket->server)) {
	char *found_name = 0, *wanted_name = 0;
	if (krb5_unparse_name(context, server, &wanted_name) == 0
	    && krb5_unparse_name(context, req->ticket->server, &found_name) == 0)
	    krb5_set_error_message(context, KRB5KRB_AP_WRONG_PRINC,
				   "Wrong principal in request (found %s, wanted %s)",
				   found_name, wanted_name);
	krb5_free_unparsed_name(context, wanted_name);
	krb5_free_unparsed_name(context, found_name);
	retval =  KRB5KRB_AP_WRONG_PRINC;
	goto cleanup;
    }

    /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY)
       do we need special processing here ?	*/

    /* decrypt the ticket */
    if ((*auth_context)->keyblock) { /* User to User authentication */
    	if ((retval = krb5_decrypt_tkt_part(context, (*auth_context)->keyblock,
					    req->ticket)))
goto cleanup;
	krb5_free_keyblock(context, (*auth_context)->keyblock);
	(*auth_context)->keyblock = NULL;
    } else {
    	if ((retval = krb5_rd_req_decrypt_tkt_part(context, req, keytab)))
	    goto cleanup;
    }

    /* XXX this is an evil hack.  check_valid_flag is set iff the call
       is not from inside the kdc.  we can use this to determine which
       key usage to use */
    if ((retval = decrypt_authenticator(context, req, 
					&((*auth_context)->authentp),
					check_valid_flag)))
	goto cleanup;

    if (!krb5_principal_compare(context, (*auth_context)->authentp->client,
				req->ticket->enc_part2->client)) {
	retval = KRB5KRB_AP_ERR_BADMATCH;
	goto cleanup;
    }

    if ((*auth_context)->remote_addr && 
      !krb5_address_search(context, (*auth_context)->remote_addr, 
			   req->ticket->enc_part2->caddrs)) {
	retval = KRB5KRB_AP_ERR_BADADDR;
	goto cleanup;
    }

    /* okay, now check cross-realm policy */

#if defined(_SINGLE_HOP_ONLY)

    /* Single hop cross-realm tickets only */

    { 
	krb5_transited *trans = &(req->ticket->enc_part2->transited);

      	/* If the transited list is empty, then we have at most one hop */
      	if (trans->tr_contents.data && trans->tr_contents.data[0])
            retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
    }

#elif defined(_NO_CROSS_REALM)

    /* No cross-realm tickets */

    { 
	char		* lrealm;
      	krb5_data      	* realm;
      	krb5_transited 	* trans;
  
	realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
	trans = &(req->ticket->enc_part2->transited);

	/*
      	 * If the transited list is empty, then we have at most one hop 
      	 * So we also have to check that the client's realm is the local one 
	 */
      	krb5_get_default_realm(context, &lrealm);
      	if ((trans->tr_contents.data && trans->tr_contents.data[0]) ||
          strlen(lrealm) != realm->length ||
          memcmp(lrealm, realm->data, strlen(lrealm))) {
            retval = KRB5KRB_AP_ERR_ILL_CR_TKT;
      	}
      	free(lrealm);
    }

#else

    /* Hierarchical Cross-Realm */
  
    {
      	krb5_data      * realm;
      	krb5_transited * trans;
  
	realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
	trans = &(req->ticket->enc_part2->transited);

	/*
      	 * If the transited list is not empty, then check that all realms 
      	 * transited are within the hierarchy between the client's realm  
      	 * and the local realm.                                        
  	 */
	if (trans->tr_contents.data && trans->tr_contents.data[0]) {
	    retval = krb5_check_transited_list(context, &(trans->tr_contents), 
					       realm,
					       krb5_princ_realm (context,
								 server));
      	}
    }

#endif

    if (retval)  goto cleanup;

    /* only check rcache if sender has provided one---some services
       may not be able to use replay caches (such as datagram servers) */

    if ((*auth_context)->rcache) {
	krb5_donot_replay  rep;
        krb5_tkt_authent   tktauthent;

	tktauthent.ticket = req->ticket;	
	tktauthent.authenticator = (*auth_context)->authentp;
	if (!(retval = krb5_auth_to_rep(context, &tktauthent, &rep))) {
	    retval = krb5_rc_store(context, (*auth_context)->rcache, &rep);
	    krb5_xfree(rep.server);
	    krb5_xfree(rep.client);
	}

	if (retval)
	    goto cleanup;
    }

    retval = krb5_validate_times(context, &req->ticket->enc_part2->times);
    if (retval != 0)
	    goto cleanup;

    if ((retval = krb5_timeofday(context, &currenttime)))
	goto cleanup;

    if (!in_clock_skew((*auth_context)->authentp->ctime)) {
	retval = KRB5KRB_AP_ERR_SKEW;
	goto cleanup;
    }

    if (check_valid_flag) {
      if (req->ticket->enc_part2->flags & TKT_FLG_INVALID) {
	retval = KRB5KRB_AP_ERR_TKT_INVALID;
	goto cleanup;
      }
    }

    /* check if the various etypes are permitted */

    if ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_PERMIT_ALL) {
	/* no etype check needed */;
    } else if ((*auth_context)->permitted_etypes == NULL) {
	int etype;
	/* check against the default set */
	if ((!krb5_is_permitted_enctype(context,
					etype = req->ticket->enc_part.enctype)) ||
	    (!krb5_is_permitted_enctype(context,
					etype = req->ticket->enc_part2->session->enctype)) ||
	    (((*auth_context)->authentp->subkey) &&
	     !krb5_is_permitted_enctype(context,
					etype = (*auth_context)->authentp->subkey->enctype))) {
	    char enctype_name[30];
	    retval = KRB5_NOPERM_ETYPE;
	    if (krb5_enctype_to_string(etype, enctype_name, sizeof(enctype_name)) == 0)
		krb5_set_error_message(context, retval,
				       "Encryption type %s not permitted",
				       enctype_name);
	    goto cleanup;
	}
    } else {
	/* check against the set in the auth_context */
	int i;

	for (i=0; (*auth_context)->permitted_etypes[i]; i++)
	    if ((*auth_context)->permitted_etypes[i] ==
		req->ticket->enc_part.enctype)
		break;
	if (!(*auth_context)->permitted_etypes[i]) {
	    char enctype_name[30];
	    retval = KRB5_NOPERM_ETYPE;
	    if (krb5_enctype_to_string(req->ticket->enc_part.enctype,
				       enctype_name, sizeof(enctype_name)) == 0)
		krb5_set_error_message(context, retval,
				       "Encryption type %s not permitted",
				       enctype_name);
	    goto cleanup;
	}
	
	for (i=0; (*auth_context)->permitted_etypes[i]; i++)
	    if ((*auth_context)->permitted_etypes[i] ==
		req->ticket->enc_part2->session->enctype)
		break;
	if (!(*auth_context)->permitted_etypes[i]) {
	    char enctype_name[30];
	    retval = KRB5_NOPERM_ETYPE;
	    if (krb5_enctype_to_string(req->ticket->enc_part2->session->enctype,
				       enctype_name, sizeof(enctype_name)) == 0)
		krb5_set_error_message(context, retval,
				       "Encryption type %s not permitted",
				       enctype_name);
	    goto cleanup;
	}
	
	if ((*auth_context)->authentp->subkey) {
	    for (i=0; (*auth_context)->permitted_etypes[i]; i++)
		if ((*auth_context)->permitted_etypes[i] ==
		    (*auth_context)->authentp->subkey->enctype)
		    break;
	    if (!(*auth_context)->permitted_etypes[i]) {
		char enctype_name[30];
		retval = KRB5_NOPERM_ETYPE;
		if (krb5_enctype_to_string((*auth_context)->authentp->subkey->enctype,
					   enctype_name,
					   sizeof(enctype_name)) == 0)
		    krb5_set_error_message(context, retval,
					   "Encryption type %s not permitted",
					   enctype_name);
		goto cleanup;
	    }
	}
    }

    (*auth_context)->remote_seq_number = (*auth_context)->authentp->seq_number;
    if ((*auth_context)->authentp->subkey) {
	if ((retval = krb5_copy_keyblock(context,
					 (*auth_context)->authentp->subkey,
					 &((*auth_context)->recv_subkey))))
	    goto cleanup;
	retval = krb5_copy_keyblock(context, (*auth_context)->authentp->subkey,
				    &((*auth_context)->send_subkey));
	if (retval) {
	    krb5_free_keyblock(context, (*auth_context)->recv_subkey);
	    (*auth_context)->recv_subkey = NULL;
	    goto cleanup;
	}
    } else {
	(*auth_context)->recv_subkey = 0;
	(*auth_context)->send_subkey = 0;
    }

    if ((retval = krb5_copy_keyblock(context, req->ticket->enc_part2->session,
				     &((*auth_context)->keyblock))))
	goto cleanup;

    /*
     * If not AP_OPTS_MUTUAL_REQUIRED then and sequence numbers are used 
     * then the default sequence number is the one's complement of the
     * sequence number sent ot us.
     */
    if ((!(req->ap_options & AP_OPTS_MUTUAL_REQUIRED)) && 
      (*auth_context)->remote_seq_number) {
	(*auth_context)->local_seq_number ^= 
	  (*auth_context)->remote_seq_number;
    }

    if (ticket)
   	if ((retval = krb5_copy_ticket(context, req->ticket, ticket)))
	    goto cleanup;
    if (ap_req_options)
    	*ap_req_options = req->ap_options;
    retval = 0;
    
cleanup:
    if (server == &princ_data)
	krb5_free_default_realm(context, princ_data.realm.data);
    if (retval) {
	/* only free if we're erroring out...otherwise some
	   applications will need the output. */
	if (req->ticket->enc_part2)
	    krb5_free_enc_tkt_part(context, req->ticket->enc_part2);
	req->ticket->enc_part2 = NULL;
    }
    return retval;
}
Example #29
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_mk_rep(krb5_context context,
	    krb5_auth_context auth_context,
	    krb5_data *outbuf)
{
    krb5_error_code ret;
    AP_REP ap;
    EncAPRepPart body;
    u_char *buf = NULL;
    size_t buf_size;
    size_t len = 0;
    krb5_crypto crypto;

    ap.pvno = 5;
    ap.msg_type = krb_ap_rep;

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

    body.ctime = auth_context->authenticator->ctime;
    body.cusec = auth_context->authenticator->cusec;
    if (auth_context->flags & KRB5_AUTH_CONTEXT_USE_SUBKEY) {
	if (auth_context->local_subkey == NULL) {
	    ret = krb5_auth_con_generatelocalsubkey(context,
						    auth_context,
						    auth_context->keyblock);
	    if(ret) {
		free_EncAPRepPart(&body);
		return ret;
	    }
	}
	ret = krb5_copy_keyblock(context, auth_context->local_subkey,
				 &body.subkey);
	if (ret) {
	    free_EncAPRepPart(&body);
	    return krb5_enomem(context);
	}
    } else
	body.subkey = NULL;
    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
	if(auth_context->local_seqnumber == 0)
	    krb5_generate_seq_number (context,
				      auth_context->keyblock,
				      &auth_context->local_seqnumber);
	ALLOC(body.seq_number, 1);
	if (body.seq_number == NULL) {
	    free_EncAPRepPart(&body);
	    return krb5_enomem(context);
	}
	*(body.seq_number) = auth_context->local_seqnumber;
    } else
	body.seq_number = NULL;

    ap.enc_part.etype = auth_context->keyblock->keytype;
    ap.enc_part.kvno  = NULL;

    ASN1_MALLOC_ENCODE(EncAPRepPart, buf, buf_size, &body, &len, ret);
    free_EncAPRepPart (&body);
    if(ret)
	return ret;
    if (buf_size != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");
    ret = krb5_crypto_init(context, auth_context->keyblock,
			   0 /* ap.enc_part.etype */, &crypto);
    if (ret) {
	free (buf);
	return ret;
    }
    ret = krb5_encrypt (context,
			crypto,
			KRB5_KU_AP_REQ_ENC_PART,
			buf + buf_size - len,
			len,
			&ap.enc_part.cipher);
    krb5_crypto_destroy(context, crypto);
    free(buf);
    if (ret)
	return ret;

    ASN1_MALLOC_ENCODE(AP_REP, outbuf->data, outbuf->length, &ap, &len, ret);
    if (ret == 0 && outbuf->length != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");
    free_AP_REP (&ap);
    return ret;
}
Example #30
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_verify_ap_req2(krb5_context context,
		    krb5_auth_context *auth_context,
		    krb5_ap_req *ap_req,
		    krb5_const_principal server,
		    krb5_keyblock *keyblock,
		    krb5_flags flags,
		    krb5_flags *ap_req_options,
		    krb5_ticket **ticket,
		    krb5_key_usage usage)
{
    krb5_ticket *t;
    krb5_auth_context ac;
    krb5_error_code ret;
    EtypeList etypes;

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

    if(ticket)
	*ticket = NULL;

    if (auth_context && *auth_context) {
	ac = *auth_context;
    } else {
	ret = krb5_auth_con_init(context, &ac);
	if (ret)
	    return ret;
    }

    t = calloc(1, sizeof(*t));
    if (t == NULL) {
	ret = ENOMEM;
	krb5_clear_error_message(context);
	goto out;
    }

    if (ap_req->ap_options.use_session_key && ac->keyblock){
	ret = krb5_decrypt_ticket(context, &ap_req->ticket,
				  ac->keyblock,
				  &t->ticket,
				  flags);
	krb5_free_keyblock(context, ac->keyblock);
	ac->keyblock = NULL;
    }else
	ret = krb5_decrypt_ticket(context, &ap_req->ticket,
				  keyblock,
				  &t->ticket,
				  flags);

    if(ret)
	goto out;

    ret = _krb5_principalname2krb5_principal(context,
					     &t->server,
					     ap_req->ticket.sname,
					     ap_req->ticket.realm);
    if (ret) goto out;
    ret = _krb5_principalname2krb5_principal(context,
					     &t->client,
					     t->ticket.cname,
					     t->ticket.crealm);
    if (ret) goto out;

    ret = decrypt_authenticator(context,
				&t->ticket.key,
				&ap_req->authenticator,
				ac->authenticator,
				usage);
    if (ret)
	goto out;

    {
	krb5_principal p1, p2;
	krb5_boolean res;

	_krb5_principalname2krb5_principal(context,
					   &p1,
					   ac->authenticator->cname,
					   ac->authenticator->crealm);
	_krb5_principalname2krb5_principal(context,
					   &p2,
					   t->ticket.cname,
					   t->ticket.crealm);
	res = krb5_principal_compare(context, p1, p2);
	krb5_free_principal(context, p1);
	krb5_free_principal(context, p2);
	if (!res) {
	    ret = KRB5KRB_AP_ERR_BADMATCH;
	    krb5_clear_error_message(context);
	    goto out;
	}
    }

    /* check addresses */

    if (t->ticket.caddr
	&& ac->remote_address
	&& !krb5_address_search(context,
				ac->remote_address,
				t->ticket.caddr)) {
	ret = KRB5KRB_AP_ERR_BADADDR;
	krb5_clear_error_message(context);
	goto out;
    }

    /* check timestamp in authenticator */
    {
	krb5_timestamp now;

	krb5_timeofday(context, &now);

	if (krb5_time_abs(ac->authenticator->ctime, now) > context->max_skew) {
	    ret = KRB5KRB_AP_ERR_SKEW;
	    krb5_clear_error_message(context);
	    goto out;
	}
    }

    if (ac->authenticator->seq_number)
	krb5_auth_con_setremoteseqnumber(context, ac,
					 *ac->authenticator->seq_number);

    /* XXX - Xor sequence numbers */

    if (ac->authenticator->subkey) {
	ret = krb5_auth_con_setremotesubkey(context, ac,
					    ac->authenticator->subkey);
	if (ret)
	    goto out;
    }

    ret = find_etypelist(context, ac, &etypes);
    if (ret)
	goto out;

    ac->keytype = (krb5_keytype)ETYPE_NULL;

    if (etypes.val) {
	size_t i;

	for (i = 0; i < etypes.len; i++) {
	    if (krb5_enctype_valid(context, etypes.val[i]) == 0) {
		ac->keytype = etypes.val[i];
		break;
	    }
	}
    }

    /* save key */
    ret = krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock);
    if (ret) goto out;

    if (ap_req_options) {
	*ap_req_options = 0;
	if (ac->keytype != ETYPE_NULL)
	    *ap_req_options |= AP_OPTS_USE_SUBKEY;
	if (ap_req->ap_options.use_session_key)
	    *ap_req_options |= AP_OPTS_USE_SESSION_KEY;
	if (ap_req->ap_options.mutual_required)
	    *ap_req_options |= AP_OPTS_MUTUAL_REQUIRED;
    }

    if(ticket)
	*ticket = t;
    else
	krb5_free_ticket(context, t);
    if (auth_context) {
	if (*auth_context == NULL)
	    *auth_context = ac;
    } else
	krb5_auth_con_free(context, ac);
    free_EtypeList(&etypes);
    return 0;
 out:
    free_EtypeList(&etypes);
    if (t)
	krb5_free_ticket(context, t);
    if (auth_context == NULL || *auth_context == NULL)
	krb5_auth_con_free(context, ac);
    return ret;
}