コード例 #1
0
ファイル: kaserver.c プロジェクト: 2014-class/freerouter
static void
do_authenticate (krb5_context context, 
		 krb5_kdc_configuration *config,
		 struct rx_header *hdr,
		 krb5_storage *sp,
		 struct sockaddr_in *addr,
		 const char *from,
		 krb5_data *reply)
{
    krb5_error_code ret;
    char *name = NULL;
    char *instance = NULL;
    time_t start_time;
    time_t end_time;
    krb5_data request;
    int32_t max_seq_len;
    hdb_entry_ex *client_entry = NULL;
    hdb_entry_ex *server_entry = NULL;
    Key *ckey = NULL;
    Key *skey = NULL;
    krb5_storage *reply_sp;
    time_t max_life;
    uint8_t life;
    int32_t chal;
    char client_name[256];
    char server_name[256];
	
    krb5_data_zero (&request);

    ret = unparse_auth_args (sp, &name, &instance, &start_time, &end_time,
			     &request, &max_seq_len);
    if (ret != 0 || request.length < 8) {
	make_error_reply (hdr, KABADREQUEST, reply);
	goto out;
    }

    snprintf (client_name, sizeof(client_name), "%s.%s@%s",
	      name, instance, config->v4_realm);
    snprintf (server_name, sizeof(server_name), "%s.%s@%s",
	      "krbtgt", config->v4_realm, config->v4_realm);

    kdc_log(context, config, 0, "AS-REQ (kaserver) %s from %s for %s",
	    client_name, from, server_name);

    ret = _kdc_db_fetch4 (context, config, name, instance, 
			  config->v4_realm, HDB_F_GET_CLIENT,
			  &client_entry);
    if (ret) {
	kdc_log(context, config, 0, "Client not found in database: %s: %s",
		client_name, krb5_get_err_text(context, ret));
	make_error_reply (hdr, KANOENT, reply);
	goto out;
    }

    ret = _kdc_db_fetch4 (context, config, "krbtgt", 
			  config->v4_realm, config->v4_realm, 
			  HDB_F_GET_KRBTGT, &server_entry);
    if (ret) {
	kdc_log(context, config, 0, "Server not found in database: %s: %s",
		server_name, krb5_get_err_text(context, ret));
	make_error_reply (hdr, KANOENT, reply);
	goto out;
    }

    ret = _kdc_check_flags (context, config,
			    client_entry, client_name,
			    server_entry, server_name,
			    TRUE);
    if (ret) {
	make_error_reply (hdr, KAPWEXPIRED, reply);
	goto out;
    }

    /* find a DES key */
    ret = _kdc_get_des_key(context, client_entry, FALSE, TRUE, &ckey);
    if(ret){
	kdc_log(context, config, 0, "no suitable DES key for client");
	make_error_reply (hdr, KANOKEYS, reply);
	goto out;
    }

    /* find a DES key */
    ret = _kdc_get_des_key(context, server_entry, TRUE, TRUE, &skey);
    if(ret){
	kdc_log(context, config, 0, "no suitable DES key for server");
	make_error_reply (hdr, KANOKEYS, reply);
	goto out;
    }

    {
	DES_cblock key;
	DES_key_schedule schedule;
	
	/* try to decode the `request' */
	memcpy (&key, ckey->key.keyvalue.data, sizeof(key));
	DES_set_key (&key, &schedule);
	DES_pcbc_encrypt (request.data,
			  request.data,
			  request.length,
			  &schedule,
			  &key,
			  DES_DECRYPT);
	memset (&schedule, 0, sizeof(schedule));
	memset (&key, 0, sizeof(key));
    }

    /* check for the magic label */
    if (memcmp ((char *)request.data + 4, "gTGS", 4) != 0) {
	kdc_log(context, config, 0, "preauth failed for %s", client_name);
	make_error_reply (hdr, KABADREQUEST, reply);
	goto out;
    }

    reply_sp = krb5_storage_from_mem (request.data, 4);
    krb5_ret_int32 (reply_sp, &chal);
    krb5_storage_free (reply_sp);

    if (abs(chal - kdc_time) > context->max_skew) {
	make_error_reply (hdr, KACLOCKSKEW, reply);
	goto out;
    }

    /* life */
    max_life = end_time - kdc_time;
    /* end_time - kdc_time can sometimes be non-positive due to slight
       time skew between client and server. Let's make sure it is postive */
    if(max_life < 1)
	max_life = 1;
    if (client_entry->entry.max_life)
	max_life = min(max_life, *client_entry->entry.max_life);
    if (server_entry->entry.max_life)
	max_life = min(max_life, *server_entry->entry.max_life);

    life = krb_time_to_life(kdc_time, kdc_time + max_life);

    create_reply_ticket (context, 
			 hdr, skey,
			 name, instance, config->v4_realm,
			 addr, life, server_entry->entry.kvno,
			 max_seq_len,
			 "krbtgt", config->v4_realm,
			 chal + 1, "tgsT",
			 &ckey->key, reply);

 out:
    if (request.length) {
	memset (request.data, 0, request.length);
	krb5_data_free (&request);
    }
    if (name)
	free (name);
    if (instance)
	free (instance);
    if (client_entry)
	_kdc_free_ent (context, client_entry);
    if (server_entry)
	_kdc_free_ent (context, server_entry);
}
コード例 #2
0
ファイル: kaserver.c プロジェクト: 2014-class/freerouter
static void
do_getticket (krb5_context context, 
	      krb5_kdc_configuration *config,
	      struct rx_header *hdr,
	      krb5_storage *sp,
	      struct sockaddr_in *addr,
	      const char *from,
	      krb5_data *reply)
{
    krb5_error_code ret;
    int kvno;
    char *auth_domain = NULL;
    krb5_data aticket;
    char *name = NULL;
    char *instance = NULL;
    krb5_data times;
    int32_t max_seq_len;
    hdb_entry_ex *server_entry = NULL;
    hdb_entry_ex *client_entry = NULL;
    hdb_entry_ex *krbtgt_entry = NULL;
    Key *kkey = NULL;
    Key *skey = NULL;
    DES_cblock key;
    DES_key_schedule schedule;
    DES_cblock session;
    time_t max_life;
    int8_t life;
    time_t start_time, end_time;
    char server_name[256];
    char client_name[256];
    struct _krb5_krb_auth_data ad;

    krb5_data_zero (&aticket);
    krb5_data_zero (&times);

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

    unparse_getticket_args (sp, &kvno, &auth_domain, &aticket,
			    &name, &instance, &times, &max_seq_len);
    if (times.length < 8) {
	make_error_reply (hdr, KABADREQUEST, reply);
	goto out;
	
    }

    snprintf (server_name, sizeof(server_name),
	      "%s.%s@%s", name, instance, config->v4_realm);

    ret = _kdc_db_fetch4 (context, config, name, instance, 
			  config->v4_realm, HDB_F_GET_SERVER, &server_entry);
    if (ret) {
	kdc_log(context, config, 0, "Server not found in database: %s: %s",
		server_name, krb5_get_err_text(context, ret));
	make_error_reply (hdr, KANOENT, reply);
	goto out;
    }

    ret = _kdc_db_fetch4 (context, config, "krbtgt", 
		     config->v4_realm, config->v4_realm, HDB_F_GET_KRBTGT, &krbtgt_entry);
    if (ret) {
	kdc_log(context, config, 0,
		"Server not found in database: %s.%s@%s: %s",
		"krbtgt", config->v4_realm,  config->v4_realm,
		krb5_get_err_text(context, ret));
	make_error_reply (hdr, KANOENT, reply);
	goto out;
    }

    /* find a DES key */
    ret = _kdc_get_des_key(context, krbtgt_entry, TRUE, TRUE, &kkey);
    if(ret){
	kdc_log(context, config, 0, "no suitable DES key for krbtgt");
	make_error_reply (hdr, KANOKEYS, reply);
	goto out;
    }

    /* find a DES key */
    ret = _kdc_get_des_key(context, server_entry, TRUE, TRUE, &skey);
    if(ret){
	kdc_log(context, config, 0, "no suitable DES key for server");
	make_error_reply (hdr, KANOKEYS, reply);
	goto out;
    }

    /* decrypt the incoming ticket */
    memcpy (&key, kkey->key.keyvalue.data, sizeof(key));

    /* unpack the ticket */
    {
	char *sname = NULL;
	char *sinstance = NULL;

	ret = _krb5_krb_decomp_ticket(context, &aticket, &kkey->key, 
				      config->v4_realm, &sname,
				      &sinstance, &ad);
	if (ret) {
	    kdc_log(context, config, 0,
		    "kaserver: decomp failed for %s.%s with %d",
		    sname, sinstance, ret);
	    make_error_reply (hdr, KABADTICKET, reply);
	    goto out;
	}

	if (strcmp (sname, "krbtgt") != 0
	    || strcmp (sinstance, config->v4_realm) != 0) {
	    kdc_log(context, config, 0, "no TGT: %s.%s for %s.%s@%s",
		    sname, sinstance,
		    ad.pname, ad.pinst, ad.prealm);
	    make_error_reply (hdr, KABADTICKET, reply);
	    free(sname);
	    free(sinstance);
	    goto out;
	}
	free(sname);
	free(sinstance);

	if (kdc_time > _krb5_krb_life_to_time(ad.time_sec, ad.life)) {
	    kdc_log(context, config, 0, "TGT expired: %s.%s@%s",
		    ad.pname, ad.pinst, ad.prealm);
	    make_error_reply (hdr, KABADTICKET, reply);
	    goto out;
	}
    }

    snprintf (client_name, sizeof(client_name),
	      "%s.%s@%s", ad.pname, ad.pinst, ad.prealm);

    kdc_log(context, config, 0, "TGS-REQ (kaserver) %s from %s for %s",
	    client_name, from, server_name);

    ret = _kdc_db_fetch4 (context, config, 
			  ad.pname, ad.pinst, ad.prealm, HDB_F_GET_CLIENT,
			  &client_entry);
    if(ret && ret != HDB_ERR_NOENTRY) {
	kdc_log(context, config, 0,
		"Client not found in database: (krb4) %s: %s",
		client_name, krb5_get_err_text(context, ret));
	make_error_reply (hdr, KANOENT, reply);
	goto out;
    }
    if (client_entry == NULL && strcmp(ad.prealm, config->v4_realm) == 0) {
	kdc_log(context, config, 0, 
		"Local client not found in database: (krb4) "
		"%s", client_name);
	make_error_reply (hdr, KANOENT, reply);
	goto out;
    }

    ret = _kdc_check_flags (context, config, 
			    client_entry, client_name,
			    server_entry, server_name,
			    FALSE);
    if (ret) {
	make_error_reply (hdr, KAPWEXPIRED, reply);
	goto out;
    }

    /* decrypt the times */
    memcpy(&session, ad.session.keyvalue.data, sizeof(session));
    DES_set_key (&session, &schedule);
    DES_ecb_encrypt (times.data,
		     times.data,
		     &schedule,
		     DES_DECRYPT);
    memset (&schedule, 0, sizeof(schedule));
    memset (&session, 0, sizeof(session));

    /* and extract them */
    {
	krb5_storage *tsp;
	int32_t tmp;

	tsp = krb5_storage_from_mem (times.data, times.length);
	krb5_ret_int32 (tsp, &tmp);
	start_time = tmp;
	krb5_ret_int32 (tsp, &tmp);
	end_time = tmp;
	krb5_storage_free (tsp);
    }

    /* life */
    max_life = end_time - kdc_time;
    /* end_time - kdc_time can sometimes be non-positive due to slight
       time skew between client and server. Let's make sure it is postive */
    if(max_life < 1)
	max_life = 1;
    if (krbtgt_entry->entry.max_life)
	max_life = min(max_life, *krbtgt_entry->entry.max_life);
    if (server_entry->entry.max_life)
	max_life = min(max_life, *server_entry->entry.max_life);
    /* if this is a cross realm request, the client_entry will likely
       be NULL */
    if (client_entry && client_entry->entry.max_life)
	max_life = min(max_life, *client_entry->entry.max_life);

    life = _krb5_krb_time_to_life(kdc_time, kdc_time + max_life);

    create_reply_ticket (context, 
			 hdr, skey,
			 ad.pname, ad.pinst, ad.prealm,
			 addr, life, server_entry->entry.kvno,
			 max_seq_len,
			 name, instance,
			 0, "gtkt",
			 &ad.session, reply);
    
 out:
    _krb5_krb_free_auth_data(context, &ad);
    if (aticket.length) {
	memset (aticket.data, 0, aticket.length);
	krb5_data_free (&aticket);
    }
    if (times.length) {
	memset (times.data, 0, times.length);
	krb5_data_free (&times);
    }
    if (auth_domain)
	free (auth_domain);
    if (name)
	free (name);
    if (instance)
	free (instance);
    if (krbtgt_entry)
	_kdc_free_ent (context, krbtgt_entry);
    if (server_entry)
	_kdc_free_ent (context, server_entry);
}
コード例 #3
0
ファイル: ipropd_master.c プロジェクト: hyc/heimdal
static int
process_msg (krb5_context context, slave *s, int log_fd,
	     const char *database, uint32_t current_version)
{
    int ret = 0;
    krb5_data out;
    krb5_storage *sp;
    int32_t tmp;

    ret = krb5_read_priv_message(context, s->ac, &s->fd, &out);
    if(ret) {
	krb5_warn (context, ret, "error reading message from %s", s->name);
	return 1;
    }

    sp = krb5_storage_from_mem (out.data, out.length);
    if (sp == NULL) {
	krb5_warnx (context, "process_msg: no memory");
	krb5_data_free (&out);
	return 1;
    }
    if (krb5_ret_int32 (sp, &tmp) != 0) {
	krb5_warnx (context, "process_msg: client send too short command");
	krb5_data_free (&out);
	return 1;
    }
    switch (tmp) {
    case I_HAVE :
	ret = krb5_ret_int32 (sp, &tmp);
	if (ret != 0) {
	    krb5_warnx (context, "process_msg: client send too I_HAVE data");
	    break;
	}
	/* new started slave that have old log */
	if (s->version == 0 && tmp != 0) {
	    if (current_version < (uint32_t)tmp) {
		krb5_warnx (context, "Slave %s (version %lu) have later version "
			    "the master (version %lu) OUT OF SYNC",
			    s->name, (unsigned long)tmp,
			    (unsigned long)current_version);
	    }
	    s->version = tmp;
	}
	if ((uint32_t)tmp < s->version) {
	    krb5_warnx (context, "Slave claims to not have "
			"version we already sent to it");
	} else {
	    ret = send_diffs (context, s, log_fd, database, current_version);
	}
	break;
    case I_AM_HERE :
	break;
    case ARE_YOU_THERE:
    case FOR_YOU :
    default :
	krb5_warnx (context, "Ignoring command %d", tmp);
	break;
    }

    krb5_data_free (&out);
    krb5_storage_free (sp);

    slave_seen(s);

    return ret;
}
コード例 #4
0
static OM_uint32
import_cred(OM_uint32 *minor_status,
            gss_cred_id_t *cred_handle,
            const gss_buffer_t value)
{
    OM_uint32 major_stat;
    krb5_error_code ret;
    krb5_principal keytab_principal = NULL;
    krb5_keytab keytab = NULL;
    krb5_storage *sp = NULL;
    krb5_ccache id = NULL;
    char *str;

    if (cred_handle == NULL || *cred_handle != GSS_C_NO_CREDENTIAL) {
	*minor_status = 0;
	return GSS_S_FAILURE;
    }

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

    /* credential cache name */
    ret = krb5_ret_string(sp, &str);
    if (ret) {
	*minor_status = ret;
	major_stat =  GSS_S_FAILURE;
	goto out;
    }
    if (str[0]) {
	ret = krb5_cc_resolve(_gsskrb5_context, str, &id);
	if (ret) {
	    *minor_status = ret;
	    major_stat =  GSS_S_FAILURE;
	    goto out;
	}
    }
    free(str);
    str = NULL;

    /* keytab principal name */
    ret = krb5_ret_string(sp, &str);
    if (ret == 0 && str[0])
	ret = krb5_parse_name(_gsskrb5_context, str, &keytab_principal);
    if (ret) {
	*minor_status = ret;
	major_stat = GSS_S_FAILURE;
	goto out;
    }
    free(str);
    str = NULL;

    /* keytab principal */
    ret = krb5_ret_string(sp, &str);
    if (ret) {
	*minor_status = ret;
	major_stat =  GSS_S_FAILURE;
	goto out;
    }
    if (str[0]) {
	ret = krb5_kt_resolve(_gsskrb5_context, str, &keytab);
	if (ret) {
	    *minor_status = ret;
	    major_stat =  GSS_S_FAILURE;
	    goto out;
	}
    }
    free(str);
    str = NULL;

    major_stat = _gsskrb5_import_cred(minor_status, id, keytab_principal,
				      keytab, cred_handle);
out:
    if (id)
	krb5_cc_close(_gsskrb5_context, id);
    if (keytab_principal)
	krb5_free_principal(_gsskrb5_context, keytab_principal);
    if (keytab)
	krb5_kt_close(_gsskrb5_context, keytab);
    if (str)
	free(str);
    if (sp)
	krb5_storage_free(sp);

    return major_stat;
}
コード例 #5
0
ファイル: ipropd_master.c プロジェクト: hyc/heimdal
static int
write_dump (krb5_context context, krb5_storage *dump,
	    const char *database, uint32_t current_version)
{
    krb5_error_code ret;
    krb5_storage *sp;
    HDB *db;
    krb5_data data;
    char buf[8];

    /* we assume that the caller has obtained an exclusive lock */

    ret = krb5_storage_truncate(dump, 0);
    if (ret)
	return ret;

    /*
     * First we store zero as the HDB version, this will indicate to a
     * later reader that the dumpfile is invalid.  We later write the
     * correct version in the file after we have written all of the
     * messages.  A dump with a zero version will not be considered
     * to be valid.
     */

    ret = krb5_store_uint32(dump, 0);

    ret = hdb_create (context, &db, database);
    if (ret)
	krb5_err (context, 1, ret, "hdb_create: %s", database);
    ret = db->hdb_open (context, db, O_RDONLY, 0);
    if (ret)
	krb5_err (context, 1, ret, "db->open");

    sp = krb5_storage_from_mem (buf, 4);
    if (sp == NULL)
	krb5_errx (context, 1, "krb5_storage_from_mem");
    krb5_store_int32 (sp, TELL_YOU_EVERYTHING);
    krb5_storage_free (sp);

    data.data   = buf;
    data.length = 4;

    ret = krb5_store_data(dump, data);
    if (ret) {
	krb5_warn (context, ret, "write_dump");
	return ret;
    }

    ret = hdb_foreach (context, db, HDB_F_ADMIN_DATA, dump_one, dump);
    if (ret) {
	krb5_warn (context, ret, "write_dump: hdb_foreach");
	return ret;
    }

    (*db->hdb_close)(context, db);
    (*db->hdb_destroy)(context, db);

    sp = krb5_storage_from_mem (buf, 8);
    if (sp == NULL)
	krb5_errx (context, 1, "krb5_storage_from_mem");
    krb5_store_int32 (sp, NOW_YOU_HAVE);
    krb5_store_int32 (sp, current_version);
    krb5_storage_free (sp);

    data.length = 8;

    ret = krb5_store_data(dump, data);
    if (ret) {
	krb5_warn (context, ret, "write_dump");
	return ret;
    }

    /*
     * We must ensure that the entire valid dump is written to disk
     * before we write the current version at the front thus making
     * it a valid dump file.  If we crash around here, this can be
     * important upon reboot.
     */

    ret = krb5_storage_fsync(dump);
    if (ret == -1) {
	ret = errno;
	krb5_warn(context, ret, "syncing iprop dumpfile");
	return ret;
    }

    ret = krb5_storage_seek(dump, 0, SEEK_SET);
    if (ret == -1) {
	ret = errno;
	krb5_warn(context, ret, "krb5_storage_seek(dump, 0, SEEK_SET)");
	return ret;
    }

    /* Write current version at the front making the dump valid */

    ret = krb5_store_uint32(dump, current_version);
    if (ret) {
	krb5_warn(context, ret, "writing version to dumpfile");
	return ret;
    }

    /*
     * We don't need to fsync(2) after the real version is written as
     * it is not a disaster if it doesn't make it to disk if we crash.
     * After all, we'll just create a new dumpfile.
     */

    krb5_warnx(context, "wrote new dumpfile (version %u)", current_version);

    return 0;
}
コード例 #6
0
ファイル: ipropd_master.c プロジェクト: hyc/heimdal
static int
send_diffs (krb5_context context, slave *s, int log_fd,
	    const char *database, uint32_t current_version)
{
    krb5_storage *sp;
    uint32_t ver;
    time_t timestamp;
    enum kadm_ops op;
    uint32_t len;
    off_t right, left;
    krb5_data data;
    int ret = 0;

    if (s->version == current_version) {
	char buf[4];

	sp = krb5_storage_from_mem(buf, 4);
	if (sp == NULL)
	    krb5_errx(context, 1, "krb5_storage_from_mem");
	krb5_store_int32(sp, YOU_HAVE_LAST_VERSION);
	krb5_storage_free(sp);
	data.data   = buf;
	data.length = 4;
	ret = krb5_write_priv_message(context, s->ac, &s->fd, &data);
	krb5_warnx(context, "slave %s in sync already at version %ld",
		   s->name, (long)s->version);
	return ret;
    }

    if (s->flags & SLAVE_F_DEAD)
	return 0;

    sp = kadm5_log_goto_end (log_fd);
    right = krb5_storage_seek(sp, 0, SEEK_CUR);
    for (;;) {
	ret = kadm5_log_previous (context, sp, &ver, &timestamp, &op, &len);
	if (ret)
	    krb5_err(context, 1, ret,
		     "send_diffs: failed to find previous entry");
	left = krb5_storage_seek(sp, -16, SEEK_CUR);
	if (ver == s->version)
	    return 0;
	if (ver == s->version + 1)
	    break;
	if (left == 0) {
	    krb5_storage_free(sp);
	    krb5_warnx(context,
		       "slave %s (version %lu) out of sync with master "
		       "(first version in log %lu), sending complete database",
		       s->name, (unsigned long)s->version, (unsigned long)ver);
	    return send_complete (context, s, database, current_version, ver);
	}
    }

    krb5_warnx(context,
	       "syncing slave %s from version %lu to version %lu",
	       s->name, (unsigned long)s->version,
	       (unsigned long)current_version);

    ret = krb5_data_alloc (&data, right - left + 4);
    if (ret) {
	krb5_storage_free(sp);
	krb5_warn (context, ret, "send_diffs: krb5_data_alloc");
	slave_dead(context, s);
	return 1;
    }
    krb5_storage_read (sp, (char *)data.data + 4, data.length - 4);
    krb5_storage_free(sp);

    sp = krb5_storage_from_data (&data);
    if (sp == NULL) {
	krb5_warnx (context, "send_diffs: krb5_storage_from_data");
	slave_dead(context, s);
	return 1;
    }
    krb5_store_int32 (sp, FOR_YOU);
    krb5_storage_free(sp);

    ret = krb5_write_priv_message(context, s->ac, &s->fd, &data);
    krb5_data_free(&data);

    if (ret) {
	krb5_warn (context, ret, "send_diffs: krb5_write_priv_message");
	slave_dead(context, s);
	return 1;
    }
    slave_seen(s);

    s->version = current_version;

    return 0;
}
コード例 #7
0
ファイル: set_cred_option.c プロジェクト: 2asoft/freebsd
static OM_uint32
allowed_enctypes(OM_uint32 *minor_status,
		 krb5_context context,
		 gss_cred_id_t *cred_handle,
		 const gss_buffer_t value)
{
    OM_uint32 major_stat;
    krb5_error_code ret;
    size_t len, i;
    krb5_enctype *enctypes = NULL;
    krb5_storage *sp = NULL;
    gsskrb5_cred cred;

    if (cred_handle == NULL || *cred_handle == GSS_C_NO_CREDENTIAL) {
	*minor_status = 0;
	return GSS_S_FAILURE;
    }

    cred = (gsskrb5_cred)*cred_handle;

    if ((value->length % 4) != 0) {
	*minor_status = 0;
	major_stat = GSS_S_FAILURE;
	goto out;
    }

    len = value->length / 4;
    enctypes = malloc((len + 1) * 4);
    if (enctypes == NULL) {
	*minor_status = ENOMEM;
	major_stat = GSS_S_FAILURE;
	goto out;
    }

    sp = krb5_storage_from_mem(value->value, value->length);
    if (sp == NULL) {
	*minor_status = ENOMEM;
	major_stat = GSS_S_FAILURE;
	goto out;
    }

    for (i = 0; i < len; i++) {
	uint32_t e;

	ret = krb5_ret_uint32(sp, &e);
	if (ret) {
	    *minor_status = ret;
	    major_stat =  GSS_S_FAILURE;
	    goto out;
	}
	enctypes[i] = e;
    }
    enctypes[i] = 0;

    if (cred->enctypes)
	free(cred->enctypes);
    cred->enctypes = enctypes;

    krb5_storage_free(sp);

    return GSS_S_COMPLETE;

out:
    if (sp)
	krb5_storage_free(sp);
    if (enctypes)
	free(enctypes);

    return major_stat;
}
コード例 #8
0
ファイル: randkey_c.c プロジェクト: InvLim/heimdal
kadm5_ret_t
kadm5_c_randkey_principal(void *server_handle,
			  krb5_principal princ,
			  krb5_boolean keepold,
			  int n_ks_tuple,
			  krb5_key_salt_tuple *ks_tuple,
			  krb5_keyblock **new_keys,
			  int *n_keys)
{
    kadm5_client_context *context = server_handle;
    kadm5_ret_t ret;
    krb5_storage *sp;
    unsigned char buf[1536];
    int32_t tmp;
    size_t i;
    krb5_data reply;

    ret = _kadm5_connect(server_handle);
    if(ret)
	return ret;

    sp = krb5_storage_from_mem(buf, sizeof(buf));
    if (sp == NULL) {
	krb5_clear_error_message(context->context);
	return ENOMEM;
    }

    /*
     * NOTE WELL: This message is extensible.  It currently consists of:
     *
     *  - opcode (kadm_randkey)
     *  - principal name (princ)
     *
     * followed by optional items, each of which must be present if
     * there are any items following them that are also present:
     *
     *  - keepold boolean (whether to delete old kvnos)
     *  - number of key/salt type tuples
     *  - array of {enctype, salttype}
     *
     * Eventually we may add:
     *
     *  - opaque string2key parameters (salt, rounds, ...)
     */
    krb5_store_int32(sp, kadm_randkey);
    krb5_store_principal(sp, princ);

    if (keepold == TRUE || n_ks_tuple > 0)
	krb5_store_uint32(sp, keepold);
    if (n_ks_tuple > 0)
	krb5_store_uint32(sp, n_ks_tuple);
    for (i = 0; i < n_ks_tuple; i++) {
	krb5_store_int32(sp, ks_tuple[i].ks_enctype);
	krb5_store_int32(sp, ks_tuple[i].ks_salttype);
    }
    /* Future extensions go here */

    ret = _kadm5_client_send(context, sp);
    krb5_storage_free(sp);
    if (ret)
	return ret;
    ret = _kadm5_client_recv(context, &reply);
    if(ret)
	return ret;
    sp = krb5_storage_from_data(&reply);
    if (sp == NULL) {
	krb5_clear_error_message(context->context);
	krb5_data_free (&reply);
	return ENOMEM;
    }
    krb5_clear_error_message(context->context);
    krb5_ret_int32(sp, &tmp);
    ret = tmp;
    if(ret == 0){
	krb5_keyblock *k;

	krb5_ret_int32(sp, &tmp);
	if (tmp < 0) {
	    ret = EOVERFLOW;
	    goto out;
	}
	k = malloc(tmp * sizeof(*k));
	if (k == NULL) {
	    ret = ENOMEM;
	    goto out;
	}
	for(i = 0; i < tmp; i++)
	    krb5_ret_keyblock(sp, &k[i]);
	if (n_keys && new_keys) {
	    *n_keys = tmp;
	    *new_keys = k;
	}
    }
out:
    krb5_storage_free(sp);
    krb5_data_free (&reply);
    return ret;
}
コード例 #9
0
ファイル: pac.c プロジェクト: Henauxg/minix
static krb5_error_code
verify_checksum(krb5_context context,
		const struct PAC_INFO_BUFFER *sig,
		const krb5_data *data,
		void *ptr, size_t len,
		const krb5_keyblock *key)
{
    krb5_storage *sp = NULL;
    uint32_t type;
    krb5_error_code ret;
    Checksum cksum;

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

    sp = krb5_storage_from_mem((char *)data->data + sig->offset_lo,
			       sig->buffersize);
    if (sp == NULL)
	return krb5_enomem(context);

    krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);

    CHECK(ret, krb5_ret_uint32(sp, &type), out);
    cksum.cksumtype = type;
    cksum.checksum.length =
	sig->buffersize - krb5_storage_seek(sp, 0, SEEK_CUR);
    cksum.checksum.data = malloc(cksum.checksum.length);
    if (cksum.checksum.data == NULL) {
	ret = krb5_enomem(context);
	goto out;
    }
    ret = krb5_storage_read(sp, cksum.checksum.data, cksum.checksum.length);
    if (ret != (int)cksum.checksum.length) {
	ret = EINVAL;
	krb5_set_error_message(context, ret, "PAC checksum missing checksum");
	goto out;
    }

    if (!krb5_checksum_is_keyed(context, cksum.cksumtype)) {
	ret = EINVAL;
	krb5_set_error_message(context, ret, "Checksum type %d not keyed",
			       cksum.cksumtype);
	goto out;
    }

    /* If the checksum is HMAC-MD5, the checksum type is not tied to
     * the key type, instead the HMAC-MD5 checksum is applied blindly
     * on whatever key is used for this connection, avoiding issues
     * with unkeyed checksums on des-cbc-md5 and des-cbc-crc.  See
     * http://comments.gmane.org/gmane.comp.encryption.kerberos.devel/8743
     * for the same issue in MIT, and
     * http://blogs.msdn.com/b/openspecification/archive/2010/01/01/verifying-the-server-signature-in-kerberos-privilege-account-certificate.aspx
     * for Microsoft's explaination */

    if (cksum.cksumtype == CKSUMTYPE_HMAC_MD5) {
	Checksum local_checksum;

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

	ret = HMAC_MD5_any_checksum(context, key, ptr, len,
				    KRB5_KU_OTHER_CKSUM, &local_checksum);

	if (ret != 0 || krb5_data_ct_cmp(&local_checksum.checksum, &cksum.checksum) != 0) {
	    ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
	    krb5_set_error_message(context, ret,
				   N_("PAC integrity check failed for "
				      "hmac-md5 checksum", ""));
	}
	krb5_data_free(&local_checksum.checksum);

   } else {
	krb5_crypto crypto = NULL;

	ret = krb5_crypto_init(context, key, 0, &crypto);
	if (ret)
		goto out;

	ret = krb5_verify_checksum(context, crypto, KRB5_KU_OTHER_CKSUM,
				   ptr, len, &cksum);
	krb5_crypto_destroy(context, crypto);
    }
    free(cksum.checksum.data);
    krb5_storage_free(sp);

    return ret;

out:
    if (cksum.checksum.data)
	free(cksum.checksum.data);
    if (sp)
	krb5_storage_free(sp);
    return ret;
}
コード例 #10
0
ファイル: import_sec_context.c プロジェクト: gojdic/samba
OM_uint32
_gsskrb5_import_sec_context (
    OM_uint32 * minor_status,
    const gss_buffer_t interprocess_token,
    gss_ctx_id_t * context_handle
    )
{
    OM_uint32 ret = GSS_S_FAILURE;
    krb5_context context;
    krb5_error_code kret;
    krb5_storage *sp;
    krb5_auth_context ac;
    krb5_address local, remote;
    krb5_address *localp, *remotep;
    krb5_data data;
    gss_buffer_desc buffer;
    krb5_keyblock keyblock;
    int32_t flags, tmp;
    gsskrb5_ctx ctx;
    gss_name_t name;

    GSSAPI_KRB5_INIT (&context);

    *context_handle = GSS_C_NO_CONTEXT;

    localp = remotep = NULL;

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

    ctx = calloc(1, sizeof(*ctx));
    if (ctx == NULL) {
	*minor_status = ENOMEM;
	krb5_storage_free (sp);
	return GSS_S_FAILURE;
    }
    HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex);

    kret = krb5_auth_con_init (context,
			       &ctx->auth_context);
    if (kret) {
	*minor_status = kret;
	ret = GSS_S_FAILURE;
	goto failure;
    }

    /* flags */

    *minor_status = 0;

    if (krb5_ret_int32 (sp, &flags) != 0)
	goto failure;

    /* retrieve the auth context */

    ac = ctx->auth_context;
    if (krb5_ret_int32 (sp, &tmp) != 0)
	goto failure;
    ac->flags = tmp;
    if (flags & SC_LOCAL_ADDRESS) {
	if (krb5_ret_address (sp, localp = &local) != 0)
	    goto failure;
    }

    if (flags & SC_REMOTE_ADDRESS) {
	if (krb5_ret_address (sp, remotep = &remote) != 0)
	    goto failure;
    }

    krb5_auth_con_setaddrs (context, ac, localp, remotep);
    if (localp)
	krb5_free_address (context, localp);
    if (remotep)
	krb5_free_address (context, remotep);
    localp = remotep = NULL;

    if (krb5_ret_int16 (sp, &ac->local_port) != 0)
	goto failure;

    if (krb5_ret_int16 (sp, &ac->remote_port) != 0)
	goto failure;
    if (flags & SC_KEYBLOCK) {
	if (krb5_ret_keyblock (sp, &keyblock) != 0)
	    goto failure;
	krb5_auth_con_setkey (context, ac, &keyblock);
	krb5_free_keyblock_contents (context, &keyblock);
    }
    if (flags & SC_LOCAL_SUBKEY) {
	if (krb5_ret_keyblock (sp, &keyblock) != 0)
	    goto failure;
	krb5_auth_con_setlocalsubkey (context, ac, &keyblock);
	krb5_free_keyblock_contents (context, &keyblock);
    }
    if (flags & SC_REMOTE_SUBKEY) {
	if (krb5_ret_keyblock (sp, &keyblock) != 0)
	    goto failure;
	krb5_auth_con_setremotesubkey (context, ac, &keyblock);
	krb5_free_keyblock_contents (context, &keyblock);
    }
    if (krb5_ret_uint32 (sp, &ac->local_seqnumber))
	goto failure;
    if (krb5_ret_uint32 (sp, &ac->remote_seqnumber))
	goto failure;

    if (krb5_ret_int32 (sp, &tmp) != 0)
	goto failure;
    ac->keytype = tmp;
    if (krb5_ret_int32 (sp, &tmp) != 0)
	goto failure;
    ac->cksumtype = tmp;

    /* names */

    if (krb5_ret_data (sp, &data))
	goto failure;
    buffer.value  = data.data;
    buffer.length = data.length;

    ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME,
				&name);
    if (ret) {
	ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NO_OID,
				    &name);
	if (ret) {
	    krb5_data_free (&data);
	    goto failure;
	}
    }
    ctx->source = (krb5_principal)name;
    krb5_data_free (&data);

    if (krb5_ret_data (sp, &data) != 0)
	goto failure;
    buffer.value  = data.data;
    buffer.length = data.length;

    ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME,
				&name);
    if (ret) {
	ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NO_OID,
				    &name);
	if (ret) {
	    krb5_data_free (&data);
	    goto failure;
	}
    }
    ctx->target = (krb5_principal)name;
    krb5_data_free (&data);

    if (krb5_ret_int32 (sp, &tmp))
	goto failure;
    ctx->flags = tmp;
    if (krb5_ret_int32 (sp, &tmp))
	goto failure;
    ctx->more_flags = tmp;
    if (krb5_ret_int32 (sp, &tmp))
	goto failure;
    ctx->lifetime = tmp;

    ret = _gssapi_msg_order_import(minor_status, sp, &ctx->order);
    if (ret)
        goto failure;

    krb5_storage_free (sp);

    *context_handle = (gss_ctx_id_t)ctx;

    return GSS_S_COMPLETE;

failure:
    krb5_auth_con_free (context,
			ctx->auth_context);
    if (ctx->source != NULL)
	krb5_free_principal(context, ctx->source);
    if (ctx->target != NULL)
	krb5_free_principal(context, ctx->target);
    if (localp)
	krb5_free_address (context, localp);
    if (remotep)
	krb5_free_address (context, remotep);
    if(ctx->order)
	_gssapi_msg_order_destroy(&ctx->order);
    HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex);
    krb5_storage_free (sp);
    free (ctx);
    *context_handle = GSS_C_NO_CONTEXT;
    return ret;
}
コード例 #11
0
static int
send_complete (krb5_context context, slave *s,
	       const char *database, uint32_t current_version)
{
    krb5_error_code ret;
    krb5_storage *sp;
    HDB *db;
    krb5_data data;
    char buf[8];

    ret = hdb_create (context, &db, database);
    if (ret)
	krb5_err (context, 1, ret, "hdb_create: %s", database);
    ret = db->hdb_open (context, db, O_RDONLY, 0);
    if (ret)
	krb5_err (context, 1, ret, "db->open");

    sp = krb5_storage_from_mem (buf, 4);
    if (sp == NULL)
	krb5_errx (context, 1, "krb5_storage_from_mem");
    krb5_store_int32 (sp, TELL_YOU_EVERYTHING);
    krb5_storage_free (sp);

    data.data   = buf;
    data.length = 4;

    ret = krb5_write_priv_message(context, s->ac, &s->fd, &data);

    if (ret) {
	krb5_warn (context, ret, "krb5_write_priv_message");
	slave_dead(context, s);
	return ret;
    }

    ret = hdb_foreach (context, db, HDB_F_ADMIN_DATA, prop_one, s);
    if (ret) {
	krb5_warn (context, ret, "hdb_foreach");
	slave_dead(context, s);
	return ret;
    }

    (*db->hdb_close)(context, db);
    (*db->hdb_destroy)(context, db);

    sp = krb5_storage_from_mem (buf, 8);
    if (sp == NULL)
	krb5_errx (context, 1, "krb5_storage_from_mem");
    krb5_store_int32 (sp, NOW_YOU_HAVE);
    krb5_store_int32 (sp, current_version);
    krb5_storage_free (sp);

    data.length = 8;

    s->version = current_version;

    ret = krb5_write_priv_message(context, s->ac, &s->fd, &data);
    if (ret) {
	slave_dead(context, s);
	krb5_warn (context, ret, "krb5_write_priv_message");
	return ret;
    }

    slave_seen(s);

    return 0;
}