示例#1
0
int
krb5_kdc_process_request(krb5_context context, 
			 krb5_kdc_configuration *config,
			 unsigned char *buf, 
			 size_t len, 
			 krb5_data *reply,
			 krb5_boolean *prependlength,
			 const char *from,
			 struct sockaddr *addr,
			 int datagram_reply)
{
    KDC_REQ req;
    Ticket ticket;
    DigestREQ digestreq;
    krb5_error_code ret;
    size_t i;

    gettimeofday(&_kdc_now, NULL);
    if(decode_AS_REQ(buf, len, &req, &i) == 0){
	krb5_data req_buffer;

	req_buffer.data = buf;
	req_buffer.length = len;

	ret = _kdc_as_rep(context, config, &req, &req_buffer, 
			  reply, from, addr, datagram_reply);
	free_AS_REQ(&req);
	return ret;
    }else if(decode_TGS_REQ(buf, len, &req, &i) == 0){
	ret = _kdc_tgs_rep(context, config, &req, reply, from, addr);
	free_TGS_REQ(&req);
	return ret;
    }else if(decode_Ticket(buf, len, &ticket, &i) == 0){
	ret = _kdc_do_524(context, config, &ticket, reply, from, addr);
	free_Ticket(&ticket);
	return ret;
    }else if(decode_DigestREQ(buf, len, &digestreq, &i) == 0){
	ret = _kdc_do_digest(context, config, &digestreq, reply, from, addr);
	free_DigestREQ(&digestreq);
	return ret;
    } else if(_kdc_maybe_version4(buf, len)){
	*prependlength = FALSE; /* elbitapmoc sdrawkcab XXX */
	_kdc_do_version4(context, config, buf, len, reply, from, 
			 (struct sockaddr_in*)addr);
	return 0;
    } else if (config->enable_kaserver) {
	ret = _kdc_do_kaserver(context, config, buf, len, reply, from,
			       (struct sockaddr_in*)addr);
	return ret;
    }
			  
    return -1;
}
示例#2
0
文件: aklog.c 项目: bagdxk/openafs
static void
copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
    Ticket ticket;
    size_t len;
    int ret;

    ret = decode_Ticket(v5cred->ticket.data, v5cred->ticket.length,
                        &ticket, &len);
    if (ret == 0) {
        strncpy(dest, ticket.realm, destlen - 1);
        dest[destlen - 1] = '\0';

        free_Ticket(&ticket);
    }
}
示例#3
0
文件: creds.c 项目: B-Rich/smart
/* FIXME */
PyObject *creds_parse(krb5CredsObject *self, PyObject *args)
{
	krb5_error_code ret;
	PyObject *tuple;
	Ticket t;
	size_t len;
	char *s;
	int error = 0;

	if ((tuple = PyTuple_New(3)) == NULL) {
		error = 1;
		goto out;
	};

	decode_Ticket(self->creds.ticket.data, self->creds.ticket.length, &t, &len);

	ret = krb5_enctype_to_string(self->context, t.enc_part.etype, &s);
	if (ret != 0) {
		asprintf(&s, "unknown (%d)", t.enc_part.etype);
	}
	PyTuple_SetItem(tuple, 0, PyString_FromString(s));
	free(s);

	if (t.enc_part.kvno)
		PyTuple_SetItem(tuple, 1, PyInt_FromLong(*t.enc_part.kvno));
	else
		PyTuple_SetItem(tuple, 1, PyInt_FromLong(-1));

	ret = krb5_unparse_name(self->context, self->creds.server, &s);
	if (ret)
		krb5_exception(self->context, 1, ret, "krb5_unparse_name");
	PyTuple_SetItem(tuple, 2, PyString_FromString(s));
	free(s);

	//PyTuple_SetItem(tuple, 0, PyInt_FromLong(entry.vno));
	//PyTuple_SetItem(tuple, 1, PyString_FromString(etype));
	//PyTuple_SetItem(tuple, 2, PyString_FromString(principal));
	//PyTuple_SetItem(tuple, 3, PyInt_FromLong(entry.timestamp));
	//PyTuple_SetItem(tuple, 4, PyString_FromString(entry.keyblock.keyvalue.data));

 out:
	if (error)
		return NULL;
	else
		return tuple;
}
示例#4
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_build_ap_req (krb5_context context,
		   krb5_enctype enctype,
		   krb5_creds *cred,
		   krb5_flags ap_options,
		   krb5_data authenticator,
		   krb5_data *retdata)
{
  krb5_error_code ret = 0;
  AP_REQ ap;
  Ticket t;
  size_t len;
  
  ap.pvno = 5;
  ap.msg_type = krb_ap_req;
  memset(&ap.ap_options, 0, sizeof(ap.ap_options));
  ap.ap_options.use_session_key = (ap_options & AP_OPTS_USE_SESSION_KEY) > 0;
  ap.ap_options.mutual_required = (ap_options & AP_OPTS_MUTUAL_REQUIRED) > 0;
  
  ap.ticket.tkt_vno = 5;
  copy_Realm(&cred->server->realm, &ap.ticket.realm);
  copy_PrincipalName(&cred->server->name, &ap.ticket.sname);

  decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len);
  copy_EncryptedData(&t.enc_part, &ap.ticket.enc_part);
  free_Ticket(&t);

  ap.authenticator.etype = enctype;
  ap.authenticator.kvno  = NULL;
  ap.authenticator.cipher = authenticator;

  ASN1_MALLOC_ENCODE(AP_REQ, retdata->data, retdata->length,
		     &ap, &len, ret);
  if(ret == 0 && retdata->length != len)
      krb5_abortx(context, "internal error in ASN.1 encoder");
  free_AP_REQ(&ap);
  return ret;

}
示例#5
0
static void
print_and_decode_tkt (krb5_context context,
		      krb5_data *ticket,
		      krb5_principal server,
		      krb5_enctype enctype)
{
    krb5_error_code ret;
    krb5_crypto crypto;
    krb5_data dec_data;
    size_t len;
    EncTicketPart decr_part;
    krb5_keyblock key;
    Ticket tkt;

    ret = decode_Ticket (ticket->data, ticket->length, &tkt, &len);
    if (ret)
	krb5_err (context, 1, ret, "decode_Ticket");

    ret = krb5_string_to_key (context, enctype, "foo", server, &key);
    if (ret)
	krb5_err (context, 1, ret, "krb5_string_to_key");

    ret = krb5_crypto_init(context, &key, 0, &crypto);
    if (ret)
	krb5_err (context, 1, ret, "krb5_crypto_init");

    ret = krb5_decrypt_EncryptedData (context, crypto, KRB5_KU_TICKET,
				      &tkt.enc_part, &dec_data);
    krb5_crypto_destroy (context, crypto);
    if (ret)
	krb5_err (context, 1, ret, "krb5_decrypt_EncryptedData");
    ret = decode_EncTicketPart (dec_data.data, dec_data.length,
				&decr_part, &len);
    krb5_data_free (&dec_data);
    if (ret)
	krb5_err (context, 1, ret, "krb5_decode_EncTicketPart");
    free_EncTicketPart(&decr_part);
}
示例#6
0
static int
v5_to_kt(krb5_creds *cred, uid_t uid, struct kafs_token *kt, int local524)
{
    int kvno, ret;

    kt->ticket = NULL;

    /* check if des key */
    if (cred->session.keyvalue.length != 8)
	return EINVAL;

    if (local524) {
	Ticket t;
	unsigned char *buf;
	size_t buf_len;
	size_t len;

	kvno = KAFS_RXKAD_2B_KVNO;

	ret = decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len);
	if (ret)
	    return ret;
	if (t.tkt_vno != 5)
	    return -1;

	ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_len, &t.enc_part,
			   &len, ret);
	free_Ticket(&t);
	if (ret)
	    return ret;
	if(buf_len != len) {
	    free(buf);
	    return KRB5KRB_ERR_GENERIC;
	}

	kt->ticket = buf;
	kt->ticket_len = buf_len;

    } else {
	kvno = KAFS_RXKAD_K5_KVNO;
	kt->ticket = malloc(cred->ticket.length);
	if (kt->ticket == NULL)
	    return ENOMEM;
	kt->ticket_len = cred->ticket.length;
	memcpy(kt->ticket, cred->ticket.data, kt->ticket_len);

	ret = 0;
    }


    /*
     * Build a struct ClearToken
     */

    kt->ct.AuthHandle = kvno;
    memcpy(kt->ct.HandShakeKey, cred->session.keyvalue.data, 8);
    kt->ct.ViceId = uid;
    kt->ct.BeginTimestamp = cred->times.starttime;
    kt->ct.EndTimestamp = cred->times.endtime;

    _kafs_fixup_viceid(&kt->ct, uid);

    return 0;
}
示例#7
0
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache cache;
    krb5_creds *out;
    int optidx = 0;
    int32_t nametype = KRB5_NT_UNKNOWN;
    krb5_get_creds_opt opt;
    krb5_principal server = NULL;
    krb5_principal impersonate;

    setprogname(argv[0]);

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

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

    if (help_flag)
	usage (0);

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

    argc -= optidx;
    argv += optidx;

    if (debug_flag) {
        ret = krb5_set_debug_dest(context, getprogname(), "STDERR");
        if (ret)
            krb5_warn(context, ret, "krb5_set_debug_dest");
    }

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

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

    if (etype_str) {
	krb5_enctype enctype;

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

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

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

    if (forwardable_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_FORWARDABLE);
    if (!transit_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_TRANSIT_CHECK);
    if (canonicalize_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CANONICALIZE);
    if (!store_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE);
    if (cached_only_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CACHED);

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

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

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

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

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

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

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

	krb5_get_creds_opt_add_options(context, opt,
				       KRB5_GC_CONSTRAINED_DELEGATION);
    }

    if (nametype_str != NULL) {
        ret = krb5_parse_nametype(context, nametype_str, &nametype);
        if (ret)
            krb5_err(context, 1, ret, "krb5_parse_nametype");
    }

    if (nametype == KRB5_NT_SRV_HST ||
        nametype == KRB5_NT_SRV_HST_NEEDS_CANON)
        is_hostbased_flag = 1;

    if (is_hostbased_flag) {
	const char *sname = NULL;
	const char *hname = NULL;

        if (nametype_str != NULL &&
            nametype != KRB5_NT_SRV_HST &&
            nametype != KRB5_NT_SRV_HST_NEEDS_CANON)
            krb5_errx(context, 1, "--hostbased not compatible with "
                      "non-hostbased --name-type");

        if (is_canonical_flag)
            nametype = KRB5_NT_SRV_HST;
        else
            nametype = KRB5_NT_SRV_HST_NEEDS_CANON;

        /*
         * Host-based service names can have more than one component.
         *
         * RFC5179 did not, but should have, assign a Kerberos name-type
         * corresponding to GSS_C_NT_DOMAINBASED.  But it's basically a
         * host-based service name type with one additional component.
         *
         * So that's how we're treating host-based service names here:
         * two or more components.
         */

        if (argc == 0) {
            usage(1);
        } else if (argc == 1) {
            krb5_principal server2;

            /*
             * In this case the one argument is a principal name, not the
             * service name.
             *
             * We parse the argument as a principal name, extract the service
             * and hostname components, use krb5_sname_to_principal(), then
             * extract the service and hostname components from that.
             */

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

            /*
             * If a single-component principal name is given, then we'll
             * default the hostname, as krb5_principal_get_comp_string()
             * returns NULL in this case.
             */
            hname = krb5_principal_get_comp_string(context, server, 1);

	    ret = krb5_sname_to_principal(context, hname, sname,
					   KRB5_NT_SRV_HST, &server2);
            sname = krb5_principal_get_comp_string(context, server2, 0);
            hname = krb5_principal_get_comp_string(context, server2, 1);

            /*
             * Modify the original with the new sname/hname.  This way we
             * retain any additional principal name components from the given
             * principal name.
             *
             * The name-type is set further below.
             */
            ret = krb5_principal_set_comp_string(context, server, 0, sname);
            if (ret)
                krb5_err(context, 1, ret, "krb5_principal_set_comp_string %s", argv[0]);
            ret = krb5_principal_set_comp_string(context, server, 1, hname);
            if (ret)
                krb5_err(context, 1, ret, "krb5_principal_set_comp_string %s", argv[0]);
            krb5_free_principal(context, server2);
        } else {
            size_t i;

            /*
             * In this case the arguments are principal name components.
             *
             * The service and hostname components can be defaulted by passing
             * empty strings.
             */
	    sname = argv[0];
            if (*sname == '\0')
                sname = NULL;
	    hname = argv[1];
            if (hname == NULL || *hname == '\0')
                hname = NULL;
	    ret = krb5_sname_to_principal(context, hname, sname,
                                          KRB5_NT_SRV_HST, &server);
	    if (ret)
		krb5_err(context, 1, ret, "krb5_sname_to_principal");

            for (i = 2; i < argc; i++) {
                ret = krb5_principal_set_comp_string(context, server, i, argv[i]);
                if (ret)
                    krb5_err(context, 1, ret, "krb5_principal_set_comp_string");
            }
	}
    } else if (argc == 1) {
	ret = krb5_parse_name(context, argv[0], &server);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_parse_name %s", argv[0]);
    } else {
	usage(1);
    }

    if (nametype != KRB5_NT_UNKNOWN)
        server->name.name_type = (NAME_TYPE)nametype;

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

    if (out_cache_str) {
	krb5_ccache id;

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

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

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

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

    return 0;
}
示例#8
0
文件: scache.c 项目: hyc/heimdal
static krb5_error_code KRB5_CALLCONV
scc_store_cred(krb5_context context,
	       krb5_ccache id,
	       krb5_creds *creds)
{
    sqlite_uint64 credid;
    krb5_scache *s = SCACHE(id);
    krb5_error_code ret;
    krb5_data data;

    ret = make_database(context, s);
    if (ret)
	return ret;

    ret = encode_creds(context, creds, &data);
    if (ret)
	return ret;

    sqlite3_bind_int(s->icred, 1, s->cid);
    {
	krb5_enctype etype = 0;
	int kvno = 0;
	Ticket t;
	size_t len;

	ret = decode_Ticket(creds->ticket.data,
			    creds->ticket.length, &t, &len);
	if (ret == 0) {
	    if(t.enc_part.kvno)
		kvno = *t.enc_part.kvno;

	    etype = t.enc_part.etype;

	    free_Ticket(&t);
	}

	sqlite3_bind_int(s->icred, 2, kvno);
	sqlite3_bind_int(s->icred, 3, etype);

    }

    sqlite3_bind_blob(s->icred, 4, data.data, data.length, free_data);
    sqlite3_bind_int(s->icred, 5, time(NULL));

    ret = exec_stmt(context, s->db, "BEGIN IMMEDIATE TRANSACTION", KRB5_CC_IO);
    if (ret) return ret;

    do {
	ret = sqlite3_step(s->icred);
    } while (ret == SQLITE_ROW);
    sqlite3_reset(s->icred);
    if (ret != SQLITE_DONE) {
	ret = KRB5_CC_IO;
	krb5_set_error_message(context, ret,
			       N_("Failed to add credential: %s", ""),
			       sqlite3_errmsg(s->db));
	goto rollback;
    }

    credid = sqlite3_last_insert_rowid(s->db);

    {
	bind_principal(context, s->db, s->iprincipal, 1, creds->server);
	sqlite3_bind_int(s->iprincipal, 2, 1);
	sqlite3_bind_int(s->iprincipal, 3, credid);

	do {
	    ret = sqlite3_step(s->iprincipal);
	} while (ret == SQLITE_ROW);
	sqlite3_reset(s->iprincipal);
	if (ret != SQLITE_DONE) {
	    ret = KRB5_CC_IO;
	    krb5_set_error_message(context, ret,
				   N_("Failed to add principal: %s", ""),
				   sqlite3_errmsg(s->db));
	    goto rollback;
	}
    }

    {
	bind_principal(context, s->db, s->iprincipal, 1, creds->client);
	sqlite3_bind_int(s->iprincipal, 2, 0);
	sqlite3_bind_int(s->iprincipal, 3, credid);

	do {
	    ret = sqlite3_step(s->iprincipal);
	} while (ret == SQLITE_ROW);
	sqlite3_reset(s->iprincipal);
	if (ret != SQLITE_DONE) {
	    ret = KRB5_CC_IO;
	    krb5_set_error_message(context, ret,
				   N_("Failed to add principal: %s", ""),
				   sqlite3_errmsg(s->db));
	    goto rollback;
	}
    }

    ret = exec_stmt(context, s->db, "COMMIT", KRB5_CC_IO);
    if (ret) return ret;

    return 0;

rollback:
    exec_stmt(context, s->db, "ROLLBACK", 0);

    return ret;
}
示例#9
0
krb5_error_code
_krb5_mk_req_internal(krb5_context context,
		      krb5_auth_context *auth_context,
		      const krb5_flags ap_req_options,
		      krb5_data *in_data,
		      krb5_creds *in_creds,
		      krb5_data *outbuf,
		      krb5_key_usage checksum_usage,
		      krb5_key_usage encrypt_usage)
{
  krb5_error_code ret;
  krb5_data authenticator;
  Checksum c;
  Checksum *c_opt;
  krb5_auth_context ac;

  if(auth_context) {
      if(*auth_context == NULL)
	  ret = krb5_auth_con_init(context, auth_context);
      else
	  ret = 0;
      ac = *auth_context;
  } else
      ret = krb5_auth_con_init(context, &ac);
  if(ret)
      return ret;
      
  if(ac->local_subkey == NULL && (ap_req_options & AP_OPTS_USE_SUBKEY)) {
      ret = krb5_auth_con_generatelocalsubkey(context, ac, &in_creds->session);
      if(ret)
	  goto out;
  }

#if 0
  {
      /* This is somewhat bogus since we're possibly overwriting a
         value specified by the user, but it's the easiest way to make
         the code use a compatible enctype */
      Ticket ticket;
      krb5_keytype ticket_keytype;

      ret = decode_Ticket(in_creds->ticket.data, 
			  in_creds->ticket.length, 
			  &ticket, 
			  NULL);
      krb5_enctype_to_keytype (context,
			       ticket.enc_part.etype,
			       &ticket_keytype);

      if (ticket_keytype == in_creds->session.keytype)
	  krb5_auth_setenctype(context, 
			       ac,
			       ticket.enc_part.etype);
      free_Ticket(&ticket);
  }
#endif

  krb5_free_keyblock(context, ac->keyblock);
  ret = krb5_copy_keyblock(context, &in_creds->session, &ac->keyblock);
  if (ret)
      goto out;
  
  /* it's unclear what type of checksum we can use.  try the best one, except:
   * a) if it's configured differently for the current realm, or
   * b) if the session key is des-cbc-crc
   */

  if (in_data) {
      if(ac->keyblock->keytype == ETYPE_DES_CBC_CRC) {
	  /* this is to make DCE secd (and older MIT kdcs?) happy */
	  ret = krb5_create_checksum(context, 
				     NULL,
				     0,
				     CKSUMTYPE_RSA_MD4,
				     in_data->data,
				     in_data->length,
				     &c);
      } else if(ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5 ||
		ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5_56) {
	  /* this is to make MS kdc happy */ 
	  ret = krb5_create_checksum(context, 
				     NULL,
				     0,
				     CKSUMTYPE_RSA_MD5,
				     in_data->data,
				     in_data->length,
				     &c);
      } else {
	  krb5_crypto crypto;

	  ret = krb5_crypto_init(context, ac->keyblock, 0, &crypto);
	  if (ret)
	      goto out;
	  ret = krb5_create_checksum(context, 
				     crypto,
				     checksum_usage,
				     0,
				     in_data->data,
				     in_data->length,
				     &c);
      	  krb5_crypto_destroy(context, crypto);
      }
      c_opt = &c;
  } else {
      c_opt = NULL;
  }

  if (ret)
      goto out;
  
  ret = krb5_build_authenticator (context,
				  ac,
				  ac->keyblock->keytype,
				  in_creds,
				  c_opt,
				  NULL,
				  &authenticator,
				  encrypt_usage);
  if (c_opt)
      free_Checksum (c_opt);
  if (ret)
    goto out;

  ret = krb5_build_ap_req (context, ac->keyblock->keytype, 
			   in_creds, ap_req_options, authenticator, outbuf);
out:
  if(auth_context == NULL)
      krb5_auth_con_free(context, ac);
  return ret;
}
示例#10
0
文件: klist.c 项目: crherar/Admin
static void
print_cred_verbose(krb5_context context, krb5_creds *cred)
{
    int j;
    char *str;
    krb5_error_code ret;
    krb5_timestamp sec;

    krb5_timeofday (context, &sec);

    ret = krb5_unparse_name(context, cred->server, &str);
    if(ret)
	exit(1);
    printf(N_("Server: %s\n", ""), str);
    free (str);
    
    ret = krb5_unparse_name(context, cred->client, &str);
    if(ret)
	exit(1);
    printf(N_("Client: %s\n", ""), str);
    free (str);
    
    {
	Ticket t;
	size_t len;
	char *s;
	
	decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len);
	ret = krb5_enctype_to_string(context, t.enc_part.etype, &s);
	printf(N_("Ticket etype: ", ""));
	if (ret == 0) {
	    printf("%s", s);
	    free(s);
	} else {
	    printf(N_("unknown-enctype(%d)", ""), t.enc_part.etype);
	}
	if(t.enc_part.kvno)
	    printf(N_(", kvno %d", ""), *t.enc_part.kvno);
	printf("\n");
	if(cred->session.keytype != t.enc_part.etype) {
	    ret = krb5_enctype_to_string(context, cred->session.keytype, &str);
	    if(ret)
		krb5_warn(context, ret, "session keytype");
	    else {
		printf(N_("Session key: %s\n", "enctype"), str);
		free(str);
	    }
	}
	free_Ticket(&t);
	printf(N_("Ticket length: %lu\n", ""),
	       (unsigned long)cred->ticket.length);
    }
    printf(N_("Auth time:  %s\n", ""),
	   printable_time_long(cred->times.authtime));
    if(cred->times.authtime != cred->times.starttime)
	printf(N_("Start time: %s\n", ""),
	       printable_time_long(cred->times.starttime));
    printf(N_("End time:   %s", ""),
	   printable_time_long(cred->times.endtime));
    if(sec > cred->times.endtime)
	printf(N_(" (expired)", ""));
    printf("\n");
    if(cred->flags.b.renewable)
	printf(N_("Renew till: %s\n", ""),
	       printable_time_long(cred->times.renew_till));
    {
	char flags[1024];
	unparse_flags(TicketFlags2int(cred->flags.b), 
		      asn1_TicketFlags_units(),
		      flags, sizeof(flags));
	printf(N_("Ticket flags: %s\n", ""), flags);
    }
    printf(N_("Addresses: ", ""));
    if (cred->addresses.len != 0) {
	for(j = 0; j < cred->addresses.len; j++){
	    char buf[128];
	    size_t len;
	    if(j) printf(", ");
	    ret = krb5_print_address(&cred->addresses.val[j],
				     buf, sizeof(buf), &len);
	
	    if(ret == 0)
		printf("%s", buf);
	}
    } else {
	printf(N_("addressless", ""));
    }
    printf("\n\n");
}
示例#11
0
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache src_cc = NULL;
    krb5_ccache dst_cc = NULL;
    krb5_cc_cursor cursor;
    krb5_principal me = NULL;
    krb5_creds cred;
    const char *during;
    Ticket t;
    size_t len;
    int make_kvno_absent = 0;
    int opt;

    memset(&cred, 0, sizeof (cred));
    during = "init_context";
    ret = krb5_init_context(&context);
    if (ret) goto err;

    while ((opt = getopt(argc, argv, "c:n")) != -1) {
	switch (opt) {
	case 'c':
	    during = "cc_resolve of source ccache";
	    ret = krb5_cc_resolve(context, optarg, &src_cc);
	    if (ret) goto err;
	    break;
	case 'n':
	    make_kvno_absent++;
	    break;
	case 'h':
	default:
	    fprintf(stderr, "Usage: %s [-n] [-c ccache]\n"
		    "\tThis utility edits a ccache, setting all ticket\n"
		    "\tenc_part kvnos to zero or absent (if -n is set).\n",
		    argv[0]);
	    return 1;
	}
    }

    if (!src_cc) {
	during = "cc_default";
	ret = krb5_cc_default(context, &src_cc);
	if (ret) goto err;
    }

    during = "cc_get_principal";
    ret = krb5_cc_get_principal(context, src_cc, &me);
    if (ret) goto err;

    if (optind != argc) {
	fprintf(stderr, "Usage: %s [-n] [-c ccache]\n"
		"\tThis utility edits a ccache, setting all ticket\n"
		"\tenc_part kvnos to zero or absent (if -n is set).\n",
		argv[0]);
	return 1;
    }

    during = "cc_new_unique of temporary ccache";
    ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, src_cc),
			     NULL, &dst_cc);

    during = "cc_initialize of temporary ccache";
    ret = krb5_cc_initialize(context, dst_cc, me);
    if (ret) goto err;

    during = "cc_start_seq_get";
    ret = krb5_cc_start_seq_get(context, src_cc, &cursor);
    if (ret) goto err;

    while ((ret = krb5_cc_next_cred(context, src_cc, &cursor, &cred)) == 0) {
	krb5_data data;

	during = "decode_Ticket";
	memset(&t, 0, sizeof (t));
	ret = decode_Ticket(cred.ticket.data, cred.ticket.length, &t, &len);
	if (ret == ASN1_MISSING_FIELD)
	    continue;
	if (ret) goto err;
	if (t.enc_part.kvno) {
	    *t.enc_part.kvno = 0;
	    if (make_kvno_absent) {
		free(t.enc_part.kvno);
		t.enc_part.kvno = NULL;
	    }
	    /*
	     * The new Ticket has to need less or same space as before, so
	     * we reuse cred->icket.data.
	     */
	    during = "encode_Ticket";
	    ASN1_MALLOC_ENCODE(Ticket, data.data, data.length, &t, &len, ret);
	    if (ret) {
		free_Ticket(&t);
		goto err;
	    }
	    krb5_data_free(&cred.ticket);
	    cred.ticket = data;
	}
	free_Ticket(&t);
	during = "cc_store_cred";
	ret = krb5_cc_store_cred(context, dst_cc, &cred);
	if (ret) goto err;
	krb5_free_cred_contents(context, &cred);
	memset(&cred, 0, sizeof (cred));
    }
    during = "cc_next_cred";
    if (ret != KRB5_CC_END) goto err;

    during = "cc_end_seq_get";
    ret = krb5_cc_end_seq_get(context, src_cc, &cursor);
    if (ret) goto err;

    during = "cc_move";
    ret = krb5_cc_move(context, dst_cc, src_cc);
    if (ret) goto err;
    dst_cc = NULL;

    during = "cc_switch";
    ret = krb5_cc_switch(context, src_cc);
    if (ret) goto err;

err:
    (void) krb5_free_principal(context, me);
    if (src_cc)
	(void) krb5_cc_close(context, src_cc);
    if (dst_cc)
	(void) krb5_cc_destroy(context, dst_cc);
    if (ret) {
	fprintf(stderr, "Failed while doing %s (%d)\n", during, ret);
	ret = 1;
    }
    return (ret);
}
示例#12
0
static void do_v5_kvno (int count, char *names[], 
                        char * ccache_name, char *etype_str, char *keytab_name,
			char *sname)
{
    krb5_error_code ret;
    krb5_context context = 0;
    int i, errors;
    krb5_enctype etype;
    krb5_ccache ccache;
    krb5_principal me;
    krb5_creds in_creds, *out_creds = NULL;
    Ticket ticket;
    size_t len;
    char *princ = NULL;
    krb5_keytab keytab = NULL;

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

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

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

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

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

    errors = 0;

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

	in_creds.client = me;

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

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

	in_creds.session.keytype = etype;

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

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

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

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

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

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

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

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

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

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

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

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

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

	krb5_free_principal(context, in_creds.server);

        free_Ticket(&ticket);
    }

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

    if (errors)
	exit(1);

    exit(0);
}
static void
test_dh2key(krb5_context context, int i, struct testcase *c)
{
    krb5_error_code ret;
    krb5_keyblock key;
    krb5_principal client, server;
    Ticket ticket;
    AlgorithmIdentifier ai;
    size_t size;

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

    ai.algorithm = *c->oid;
    ai.parameters = NULL;

    ret = decode_Ticket(c->ticket.data, c->ticket.length, &ticket, &size);
    if (ret)
	krb5_errx(context, 1, "decode ticket: %d", ret);

    ret = krb5_parse_name(context, c->client, &client);
    if (ret)
	krb5_err(context, 1, ret, "parse_name: %s", c->client);
    ret = krb5_parse_name(context, c->server, &server);
    if (ret)
	krb5_err(context, 1, ret, "parse_name: %s", c->server);

    if (verbose_flag) {
	char *str;
	hex_encode(c->Z.data, c->Z.length, &str);
	printf("Z: %s\n", str);
	free(str);
	printf("client: %s\n", c->client);
	printf("server: %s\n", c->server);
	printf("enctype: %d\n", (int)c->enctype);
	hex_encode(c->as_req.data, c->as_req.length, &str);
	printf("as-req: %s\n", str);
	free(str);
	hex_encode(c->pk_as_rep.data, c->pk_as_rep.length, &str);
	printf("pk-as-rep: %s\n", str);
	free(str);
	hex_encode(c->ticket.data, c->ticket.length, &str);
	printf("ticket: %s\n", str);
	free(str);
    }

    ret = _krb5_pk_kdf(context,
		       &ai,
		       c->Z.data,
		       c->Z.length,
		       client,
		       server,
		       c->enctype,
		       &c->as_req,
		       &c->pk_as_rep,
		       &ticket,
		       &key);
    krb5_free_principal(context, client);
    krb5_free_principal(context, server);
    if (ret)
	krb5_err(context, 1, ret, "_krb5_pk_kdf: %d", i);

    if (verbose_flag) {
	char *str;
	hex_encode(key.keyvalue.data, key.keyvalue.length, &str);
	printf("key: %s\n", str);
	free(str);
    }

    if (key.keyvalue.length != c->key.length ||
	memcmp(key.keyvalue.data, c->key.data, c->key.length) != 0)
	krb5_errx(context, 1, "resulting key wrong: %d", i);

    krb5_free_keyblock_contents(context, &key);
    free_Ticket(&ticket);
}
示例#14
0
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_forwarded_creds (krb5_context	    context,
			  krb5_auth_context auth_context,
			  krb5_ccache       ccache,
			  krb5_flags        flags,
			  const char        *hostname,
			  krb5_creds        *in_creds,
			  krb5_data         *out_data)
{
    krb5_error_code ret;
    krb5_creds *out_creds;
    krb5_addresses addrs, *paddrs;
    KRB_CRED cred;
    KrbCredInfo *krb_cred_info;
    EncKrbCredPart enc_krb_cred_part;
    size_t len;
    unsigned char *buf;
    size_t buf_size;
    krb5_kdc_flags kdc_flags;
    krb5_crypto crypto;
    struct addrinfo *ai;
    int save_errno;
    krb5_creds *ticket;
    char *realm;

    if (in_creds->client && in_creds->client->realm)
	realm = in_creds->client->realm;
    else
	realm = in_creds->server->realm;

    addrs.len = 0;
    addrs.val = NULL;
    paddrs = &addrs;

    /*
     * If tickets are address-less, forward address-less tickets.
     */

    ret = _krb5_get_krbtgt (context,
			    ccache,
			    realm,
			    &ticket);
    if(ret == 0) {
	if (ticket->addresses.len == 0)
	    paddrs = NULL;
	krb5_free_creds (context, ticket);
    }
    
    if (paddrs != NULL) {

	ret = getaddrinfo (hostname, NULL, NULL, &ai);
	if (ret) {
	    save_errno = errno;
	    krb5_set_error_string(context, "resolving %s: %s",
				  hostname, gai_strerror(ret));
	    return krb5_eai_to_heim_errno(ret, save_errno);
	}
	
	ret = add_addrs (context, &addrs, ai);
	freeaddrinfo (ai);
	if (ret)
	    return ret;
    }
    
    kdc_flags.b = int2KDCOptions(flags);

    ret = krb5_get_kdc_cred (context,
			     ccache,
			     kdc_flags,
			     paddrs,
			     NULL,
			     in_creds,
			     &out_creds);
    krb5_free_addresses (context, &addrs);
    if (ret) {
	return ret;
    }

    memset (&cred, 0, sizeof(cred));
    cred.pvno = 5;
    cred.msg_type = krb_cred;
    ALLOC_SEQ(&cred.tickets, 1);
    if (cred.tickets.val == NULL) {
	ret = ENOMEM;
	krb5_set_error_string(context, "malloc: out of memory");
	goto out2;
    }
    ret = decode_Ticket(out_creds->ticket.data,
			out_creds->ticket.length,
			cred.tickets.val, &len);
    if (ret)
	goto out3;

    memset (&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part));
    ALLOC_SEQ(&enc_krb_cred_part.ticket_info, 1);
    if (enc_krb_cred_part.ticket_info.val == NULL) {
	ret = ENOMEM;
	krb5_set_error_string(context, "malloc: out of memory");
	goto out4;
    }
    
    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
	krb5_timestamp sec;
	int32_t usec;
	
	krb5_us_timeofday (context, &sec, &usec);
	
	ALLOC(enc_krb_cred_part.timestamp, 1);
	if (enc_krb_cred_part.timestamp == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_string(context, "malloc: out of memory");
	    goto out4;
	}
	*enc_krb_cred_part.timestamp = sec;
	ALLOC(enc_krb_cred_part.usec, 1);
	if (enc_krb_cred_part.usec == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_string(context, "malloc: out of memory");
	    goto out4;
	}
	*enc_krb_cred_part.usec      = usec;
    } else {
	enc_krb_cred_part.timestamp = NULL;
	enc_krb_cred_part.usec = NULL;
    }

    if (auth_context->local_address && auth_context->local_port) {
	krb5_boolean noaddr;
	krb5_const_realm realm;

	realm = krb5_principal_get_realm(context, out_creds->server);
	krb5_appdefault_boolean(context, NULL, realm, "no-addresses", paddrs == NULL,
				&noaddr);
	if (!noaddr) {
	    ret = krb5_make_addrport (context,
				      &enc_krb_cred_part.s_address,
				      auth_context->local_address,
				      auth_context->local_port);
	    if (ret)
		goto out4;
	}
    }

    if (auth_context->remote_address) {
	if (auth_context->remote_port) {
	    krb5_boolean noaddr;
	    krb5_const_realm realm;

	    realm = krb5_principal_get_realm(context, out_creds->server);
	    /* Is this correct, and should we use the paddrs == NULL
               trick here as well? Having an address-less ticket may
               indicate that we don't know our own global address, but
               it does not necessary mean that we don't know the
               server's. */
	    krb5_appdefault_boolean(context, NULL, realm, "no-addresses",
				    FALSE, &noaddr);
	    if (!noaddr) {
		ret = krb5_make_addrport (context,
					  &enc_krb_cred_part.r_address,
					  auth_context->remote_address,
					  auth_context->remote_port);
		if (ret)
		    goto out4;
	    }
	} else {
	    ALLOC(enc_krb_cred_part.r_address, 1);
	    if (enc_krb_cred_part.r_address == NULL) {
		ret = ENOMEM;
		krb5_set_error_string(context, "malloc: out of memory");
		goto out4;
	    }

	    ret = krb5_copy_address (context, auth_context->remote_address,
				     enc_krb_cred_part.r_address);
	    if (ret)
		goto out4;
	}
    }

    /* fill ticket_info.val[0] */

    enc_krb_cred_part.ticket_info.len = 1;

    krb_cred_info = enc_krb_cred_part.ticket_info.val;

    copy_EncryptionKey (&out_creds->session, &krb_cred_info->key);
    ALLOC(krb_cred_info->prealm, 1);
    copy_Realm (&out_creds->client->realm, krb_cred_info->prealm);
    ALLOC(krb_cred_info->pname, 1);
    copy_PrincipalName(&out_creds->client->name, krb_cred_info->pname);
    ALLOC(krb_cred_info->flags, 1);
    *krb_cred_info->flags          = out_creds->flags.b;
    ALLOC(krb_cred_info->authtime, 1);
    *krb_cred_info->authtime       = out_creds->times.authtime;
    ALLOC(krb_cred_info->starttime, 1);
    *krb_cred_info->starttime      = out_creds->times.starttime;
    ALLOC(krb_cred_info->endtime, 1);
    *krb_cred_info->endtime        = out_creds->times.endtime;
    ALLOC(krb_cred_info->renew_till, 1);
    *krb_cred_info->renew_till = out_creds->times.renew_till;
    ALLOC(krb_cred_info->srealm, 1);
    copy_Realm (&out_creds->server->realm, krb_cred_info->srealm);
    ALLOC(krb_cred_info->sname, 1);
    copy_PrincipalName (&out_creds->server->name, krb_cred_info->sname);
    ALLOC(krb_cred_info->caddr, 1);
    copy_HostAddresses (&out_creds->addresses, krb_cred_info->caddr);

    krb5_free_creds (context, out_creds);

    /* encode EncKrbCredPart */

    ASN1_MALLOC_ENCODE(EncKrbCredPart, buf, buf_size, 
		       &enc_krb_cred_part, &len, ret);
    free_EncKrbCredPart (&enc_krb_cred_part);
    if (ret) {
	free_KRB_CRED(&cred);
	return ret;
    }
    if(buf_size != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");

    if (auth_context->flags & KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED) {
	cred.enc_part.etype = ENCTYPE_NULL;
	cred.enc_part.kvno = NULL;
	cred.enc_part.cipher.data = buf;
	cred.enc_part.cipher.length = buf_size;
    } else {
	krb5_keyblock *key;

	if (auth_context->local_subkey)
	    key = auth_context->local_subkey;
	else if (auth_context->remote_subkey)
	    key = auth_context->remote_subkey;
	else
	    key = auth_context->keyblock;
	
	ret = krb5_crypto_init(context, key, 0, &crypto);
	if (ret) {
	    free(buf);
	    free_KRB_CRED(&cred);
	    return ret;
	}
	ret = krb5_encrypt_EncryptedData (context,
					  crypto,
					  KRB5_KU_KRB_CRED,
					  buf,
					  len,
					  0,
					  &cred.enc_part);
	free(buf);
	krb5_crypto_destroy(context, crypto);
	if (ret) {
	    free_KRB_CRED(&cred);
	    return ret;
	}
    }

    ASN1_MALLOC_ENCODE(KRB_CRED, buf, buf_size, &cred, &len, ret);
    free_KRB_CRED (&cred);
    if (ret)
	return ret;
    if(buf_size != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");
    out_data->length = len;
    out_data->data   = buf;
    return 0;
 out4:
    free_EncKrbCredPart(&enc_krb_cred_part);
 out3:
    free_KRB_CRED(&cred);
 out2:
    krb5_free_creds (context, out_creds);
    return ret;
}
示例#15
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_forwarded_creds (krb5_context	    context,
			  krb5_auth_context auth_context,
			  krb5_ccache       ccache,
			  krb5_flags        flags,
			  const char        *hostname,
			  krb5_creds        *in_creds,
			  krb5_data         *out_data)
{
    krb5_error_code ret;
    krb5_creds *out_creds;
    krb5_addresses addrs, *paddrs;
    KRB_CRED cred;
    KrbCredInfo *krb_cred_info;
    EncKrbCredPart enc_krb_cred_part;
    size_t len;
    unsigned char *buf;
    size_t buf_size;
    krb5_kdc_flags kdc_flags;
    krb5_crypto crypto;
    struct addrinfo *ai;
    krb5_creds *ticket;

    paddrs = NULL;
    addrs.len = 0;
    addrs.val = NULL;

    ret = krb5_get_credentials(context, 0, ccache, in_creds, &ticket);
    if(ret == 0) {
	if (ticket->addresses.len)
	    paddrs = &addrs;
	krb5_free_creds (context, ticket);
    } else {
	krb5_boolean noaddr;
	krb5_appdefault_boolean(context, NULL,
				krb5_principal_get_realm(context,
							 in_creds->client),
				"no-addresses", KRB5_ADDRESSLESS_DEFAULT,
				&noaddr);
	if (!noaddr)
	    paddrs = &addrs;
    }

    /*
     * If tickets have addresses, get the address of the remote host.
     */

    if (paddrs != NULL) {

	ret = getaddrinfo (hostname, NULL, NULL, &ai);
	if (ret) {
	    krb5_error_code ret2 = krb5_eai_to_heim_errno(ret, errno);
	    krb5_set_error_message(context, ret2,
				   N_("resolving host %s failed: %s",
				      "hostname, error"),
				  hostname, gai_strerror(ret));
	    return ret2;
	}

	ret = add_addrs (context, &addrs, ai);
	freeaddrinfo (ai);
	if (ret)
	    return ret;
    }

    kdc_flags.b = int2KDCOptions(flags);

    ret = krb5_get_kdc_cred (context,
			     ccache,
			     kdc_flags,
			     paddrs,
			     NULL,
			     in_creds,
			     &out_creds);
    krb5_free_addresses (context, &addrs);
    if (ret)
	return ret;

    memset (&cred, 0, sizeof(cred));
    cred.pvno = 5;
    cred.msg_type = krb_cred;
    ALLOC_SEQ(&cred.tickets, 1);
    if (cred.tickets.val == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	goto out2;
    }
    ret = decode_Ticket(out_creds->ticket.data,
			out_creds->ticket.length,
			cred.tickets.val, &len);
    if (ret)
	goto out3;

    memset (&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part));
    ALLOC_SEQ(&enc_krb_cred_part.ticket_info, 1);
    if (enc_krb_cred_part.ticket_info.val == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	goto out4;
    }

    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
	krb5_timestamp sec;
	int32_t usec;

	krb5_us_timeofday (context, &sec, &usec);

	ALLOC(enc_krb_cred_part.timestamp, 1);
	if (enc_krb_cred_part.timestamp == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	    goto out4;
	}
	*enc_krb_cred_part.timestamp = sec;
	ALLOC(enc_krb_cred_part.usec, 1);
	if (enc_krb_cred_part.usec == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	    goto out4;
	}
	*enc_krb_cred_part.usec      = usec;
    } else {
	enc_krb_cred_part.timestamp = NULL;
	enc_krb_cred_part.usec = NULL;
    }

    if (auth_context->local_address && auth_context->local_port && paddrs) {

	ret = krb5_make_addrport (context,
				  &enc_krb_cred_part.s_address,
				  auth_context->local_address,
				  auth_context->local_port);
	if (ret)
	    goto out4;
    }

    if (auth_context->remote_address) {
	if (auth_context->remote_port) {
	    krb5_boolean noaddr;
	    krb5_const_realm srealm;

	    srealm = krb5_principal_get_realm(context, out_creds->server);
	    /* Is this correct, and should we use the paddrs == NULL
               trick here as well? Having an address-less ticket may
               indicate that we don't know our own global address, but
               it does not necessary mean that we don't know the
               server's. */
	    krb5_appdefault_boolean(context, NULL, srealm, "no-addresses",
				    FALSE, &noaddr);
	    if (!noaddr) {
		ret = krb5_make_addrport (context,
					  &enc_krb_cred_part.r_address,
					  auth_context->remote_address,
					  auth_context->remote_port);
		if (ret)
		    goto out4;
	    }
	} else {
	    ALLOC(enc_krb_cred_part.r_address, 1);
	    if (enc_krb_cred_part.r_address == NULL) {
		ret = ENOMEM;
		krb5_set_error_message(context, ret,
				       N_("malloc: out of memory", ""));
		goto out4;
	    }

	    ret = krb5_copy_address (context, auth_context->remote_address,
				     enc_krb_cred_part.r_address);
	    if (ret)
		goto out4;
	}
    }

    /* fill ticket_info.val[0] */

    enc_krb_cred_part.ticket_info.len = 1;

    krb_cred_info = enc_krb_cred_part.ticket_info.val;

    copy_EncryptionKey (&out_creds->session, &krb_cred_info->key);
    ALLOC(krb_cred_info->prealm, 1);
    copy_Realm (&out_creds->client->realm, krb_cred_info->prealm);
    ALLOC(krb_cred_info->pname, 1);
    copy_PrincipalName(&out_creds->client->name, krb_cred_info->pname);
    ALLOC(krb_cred_info->flags, 1);
    *krb_cred_info->flags          = out_creds->flags.b;
    ALLOC(krb_cred_info->authtime, 1);
    *krb_cred_info->authtime       = out_creds->times.authtime;
    ALLOC(krb_cred_info->starttime, 1);
    *krb_cred_info->starttime      = out_creds->times.starttime;
    ALLOC(krb_cred_info->endtime, 1);
    *krb_cred_info->endtime        = out_creds->times.endtime;
    ALLOC(krb_cred_info->renew_till, 1);
    *krb_cred_info->renew_till = out_creds->times.renew_till;
    ALLOC(krb_cred_info->srealm, 1);
    copy_Realm (&out_creds->server->realm, krb_cred_info->srealm);
    ALLOC(krb_cred_info->sname, 1);
    copy_PrincipalName (&out_creds->server->name, krb_cred_info->sname);
    ALLOC(krb_cred_info->caddr, 1);
    copy_HostAddresses (&out_creds->addresses, krb_cred_info->caddr);

    krb5_free_creds (context, out_creds);

    /* encode EncKrbCredPart */

    ASN1_MALLOC_ENCODE(EncKrbCredPart, buf, buf_size,
		       &enc_krb_cred_part, &len, ret);
    free_EncKrbCredPart (&enc_krb_cred_part);
    if (ret) {
	free_KRB_CRED(&cred);
	return ret;
    }
    if(buf_size != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");

    /**
     * Some older of the MIT gssapi library used clear-text tickets
     * (warped inside AP-REQ encryption), use the krb5_auth_context
     * flag KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED to support those
     * tickets. The session key is used otherwise to encrypt the
     * forwarded ticket.
     */

    if (auth_context->flags & KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED) {
	cred.enc_part.etype = KRB5_ENCTYPE_NULL;
	cred.enc_part.kvno = NULL;
	cred.enc_part.cipher.data = buf;
	cred.enc_part.cipher.length = buf_size;
    } else {
	/*
	 * Here older versions then 0.7.2 of Heimdal used the local or
	 * remote subkey. That is wrong, the session key should be
	 * used. Heimdal 0.7.2 and newer have code to try both in the
	 * receiving end.
	 */

	ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto);
	if (ret) {
	    free(buf);
	    free_KRB_CRED(&cred);
	    return ret;
	}
	ret = krb5_encrypt_EncryptedData (context,
					  crypto,
					  KRB5_KU_KRB_CRED,
					  buf,
					  len,
					  0,
					  &cred.enc_part);
	free(buf);
	krb5_crypto_destroy(context, crypto);
	if (ret) {
	    free_KRB_CRED(&cred);
	    return ret;
	}
    }

    ASN1_MALLOC_ENCODE(KRB_CRED, buf, buf_size, &cred, &len, ret);
    free_KRB_CRED (&cred);
    if (ret)
	return ret;
    if(buf_size != len)
	krb5_abortx(context, "internal error in ASN.1 encoder");
    out_data->length = len;
    out_data->data   = buf;
    return 0;
 out4:
    free_EncKrbCredPart(&enc_krb_cred_part);
 out3:
    free_KRB_CRED(&cred);
 out2:
    krb5_free_creds (context, out_creds);
    return ret;
}
示例#16
0
文件: kgetcred.c 项目: 2asoft/freebsd
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache cache;
    krb5_creds *out;
    int optidx = 0;
    krb5_get_creds_opt opt;
    krb5_principal server;
    krb5_principal impersonate = NULL;

    setprogname (argv[0]);

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

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

    if (help_flag)
	usage (0);

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

    argc -= optidx;
    argv += optidx;

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

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

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

    if (etype_str) {
	krb5_enctype enctype;

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

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

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

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

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

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

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

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

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

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

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

	krb5_get_creds_opt_add_options(context, opt,
				       KRB5_GC_CONSTRAINED_DELEGATION);
    }

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

    if (nametype_str) {
	int32_t nametype;

	ret = krb5_parse_nametype(context, nametype_str, &nametype);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_parse_nametype");

	server->name.name_type = (NAME_TYPE)nametype;
    }

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

    if (out_cache_str) {
	krb5_ccache id;

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

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

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

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

    return 0;
}
示例#17
0
static krb5_error_code
get_cred_kdc_usage(krb5_context context, 
		   krb5_ccache id, 
		   krb5_kdc_flags flags,
		   krb5_addresses *addresses, 
		   krb5_creds *in_creds, 
		   krb5_creds *krbtgt,
		   krb5_creds *out_creds,
		   krb5_key_usage usage)
{
    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;
    Ticket second_ticket;
    int send_to_kdc_flags = 0;
    
    krb5_data_zero(&resp);
    krb5_data_zero(&enc);

    krb5_generate_random_block(&nonce, sizeof(nonce));
    nonce &= 0xffffffff;
    
    if(flags.b.enc_tkt_in_skey){
	ret = decode_Ticket(in_creds->second_ticket.data, 
			    in_creds->second_ticket.length, 
			    &second_ticket, &len);
	if(ret)
	    return ret;
    }

    ret = init_tgs_req (context,
			id,
			addresses,
			flags,
			flags.b.enc_tkt_in_skey ? &second_ticket : NULL,
			in_creds,
			krbtgt,
			nonce,
			&subkey, 
			&req,
			usage);
    if(flags.b.enc_tkt_in_skey)
	free_Ticket(&second_ticket);
    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
     */
again:
    ret = krb5_sendto_kdc_flags (context, &enc, 
				 &krbtgt->server->name.name_string.val[1],
				 &resp,
				 send_to_kdc_flags);
    if(ret)
	goto out;

    memset(&rep, 0, sizeof(rep));
    if(decode_TGS_REP(resp.data, resp.length, &rep.kdc_rep, &len) == 0){
	ret = krb5_copy_principal(context, 
				  in_creds->client, 
				  &out_creds->client);
	if(ret)
	    goto out;
	ret = krb5_copy_principal(context, 
				  in_creds->server, 
				  &out_creds->server);
	if(ret)
	    goto out;
	/* this should go someplace else */
	out_creds->times.endtime = in_creds->times.endtime;

	ret = _krb5_extract_ticket(context,
				   &rep,
				   out_creds,
				   &krbtgt->session,
				   NULL,
				   KRB5_KU_TGS_REP_ENC_PART_SESSION,
				   &krbtgt->addresses,
				   nonce,
				   TRUE,
				   flags.b.request_anonymous,
				   decrypt_tkt_with_subkey,
				   subkey);
	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);

	if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG && !(send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG)) {
	    send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
	    krb5_data_free(&resp);
	    goto again;
	}
    } else if(resp.data && ((char*)resp.data)[0] == 4) {
	ret = KRB5KRB_AP_ERR_V4_REPLY;
	krb5_clear_error_string(context);
    } else {
	ret = KRB5KRB_AP_ERR_MSG_TYPE;
	krb5_clear_error_string(context);
    }

out:
    krb5_data_free(&resp);
    krb5_data_free(&enc);
    if(subkey){
	krb5_free_keyblock_contents(context, subkey);
	free(subkey);
    }
    return ret;
    
}
示例#18
0
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;
    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;

	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,
				   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;

}
示例#19
0
int
decode_KRB_CRED(const unsigned char *p, size_t len, KRB_CRED *data, size_t *size)
{
size_t ret = 0, reallen;
size_t l;
int e;

memset(data, 0, sizeof(*data));
reallen = 0;
e = der_match_tag_and_length (p, len, ASN1_C_APPL, CONS, 22, &reallen, &l);
FORW;
{
int dce_fix;
if((dce_fix = fix_dce(reallen, &len)) < 0)
return ASN1_BAD_FORMAT;
e = der_match_tag_and_length (p, len, ASN1_C_UNIV, CONS, UT_Sequence,&reallen, &l);
FORW;
{
int dce_fix;
if((dce_fix = fix_dce(reallen, &len)) < 0)
return ASN1_BAD_FORMAT;
{
size_t newlen, oldlen;

e = der_match_tag (p, len, ASN1_C_CONTEXT, CONS, 0, &l);
if (e)
return e;
else {
p += l;
len -= l;
ret += l;
e = der_get_length (p, len, &newlen, &l);
FORW;
{
int dce_fix;
oldlen = len;
if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT;
e = decode_integer(p, len, &(data)->pvno, &l);
FORW;
if(dce_fix){
e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l);
FORW;
}else 
len = oldlen - newlen;
}
}
}
{
size_t newlen, oldlen;

e = der_match_tag (p, len, ASN1_C_CONTEXT, CONS, 1, &l);
if (e)
return e;
else {
p += l;
len -= l;
ret += l;
e = der_get_length (p, len, &newlen, &l);
FORW;
{
int dce_fix;
oldlen = len;
if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT;
e = decode_MESSAGE_TYPE(p, len, &(data)->msg_type, &l);
FORW;
if(dce_fix){
e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l);
FORW;
}else 
len = oldlen - newlen;
}
}
}
{
size_t newlen, oldlen;

e = der_match_tag (p, len, ASN1_C_CONTEXT, CONS, 2, &l);
if (e)
return e;
else {
p += l;
len -= l;
ret += l;
e = der_get_length (p, len, &newlen, &l);
FORW;
{
int dce_fix;
oldlen = len;
if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT;
e = der_match_tag_and_length (p, len, ASN1_C_UNIV, CONS, UT_Sequence,&reallen, &l);
FORW;
if(len < reallen)
return ASN1_OVERRUN;
len = reallen;
{
size_t origlen = len;
int oldret = ret;
ret = 0;
(&(data)->tickets)->len = 0;
(&(data)->tickets)->val = NULL;
while(ret < origlen) {
(&(data)->tickets)->len++;
(&(data)->tickets)->val = realloc((&(data)->tickets)->val, sizeof(*((&(data)->tickets)->val)) * (&(data)->tickets)->len);
e = decode_Ticket(p, len, &(&(data)->tickets)->val[(&(data)->tickets)->len-1], &l);
FORW;
len = origlen - ret;
}
ret += oldret;
}
if(dce_fix){
e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l);
FORW;
}else 
len = oldlen - newlen;
}
}
}
{
size_t newlen, oldlen;

e = der_match_tag (p, len, ASN1_C_CONTEXT, CONS, 3, &l);
if (e)
return e;
else {
p += l;
len -= l;
ret += l;
e = der_get_length (p, len, &newlen, &l);
FORW;
{
int dce_fix;
oldlen = len;
if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT;
e = decode_EncryptedData(p, len, &(data)->enc_part, &l);
FORW;
if(dce_fix){
e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l);
FORW;
}else 
len = oldlen - newlen;
}
}
}
if(dce_fix){
e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l);
FORW;
}
}
if(dce_fix){
e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l);
FORW;
}
}
if(size) *size = ret;
return 0;
fail:
free_KRB_CRED(data);
return e;
}