Пример #1
0
int
_kafs_v4_to_kt(CREDENTIALS *c, uid_t uid, struct kafs_token *kt)
{
    kt->ticket = NULL;

    if (c->ticket_st.length > MAX_KTXT_LEN)
	return EINVAL;

    kt->ticket = malloc(c->ticket_st.length);
    if (kt->ticket == NULL)
	return ENOMEM;
    kt->ticket_len = c->ticket_st.length;
    memcpy(kt->ticket, c->ticket_st.dat, kt->ticket_len);

    /*
     * Build a struct ClearToken
     */
    kt->ct.AuthHandle = c->kvno;
    memcpy (kt->ct.HandShakeKey, c->session, sizeof(c->session));
    kt->ct.ViceId = uid;
    kt->ct.BeginTimestamp = c->issue_date;
    kt->ct.EndTimestamp = krb_life_to_time(c->issue_date, c->lifetime);

    _kafs_fixup_viceid(&kt->ct, uid);

    return 0;
}
Пример #2
0
int
krb_mk_req(KTEXT authent,
	   char *service, char *instance, char *realm, 
	   int32_t checksum)

#endif
{
    CREDENTIALS cr;
    KTEXT_ST req;
    krb5_storage *sp;
    int code;
    /* XXX get user realm */
    const char *myrealm = realm;
    krb5_data a;

    code = krb_get_cred(service, instance, realm, &cr);
    if(code || time(NULL) > krb_life_to_time(cr.issue_date, cr.lifetime)){
	code = get_ad_tkt((char *)service,
			  (char *)instance, (char *)realm, lifetime);
	if(code == KSUCCESS)
	    code = krb_get_cred(service, instance, realm, &cr);
    }

    if(code)
	return code;

    sp = krb5_storage_emem();

    krb5_store_int8(sp, KRB_PROT_VERSION);
    krb5_store_int8(sp, AUTH_MSG_APPL_REQUEST);
    
    krb5_store_int8(sp, cr.kvno);
    krb5_store_stringz(sp, realm);
    krb5_store_int8(sp, cr.ticket_st.length);

    build_request(&req, cr.pname, cr.pinst, myrealm, checksum);
    encrypt_ktext(&req, &cr.session, DES_ENCRYPT);

    krb5_store_int8(sp, req.length);

    krb5_storage_write(sp, cr.ticket_st.dat, cr.ticket_st.length);
    krb5_storage_write(sp, req.dat, req.length);
    krb5_storage_to_data(sp, &a);
    krb5_storage_free(sp);
    memcpy(authent->dat, a.data, a.length);
    authent->length = a.length;
    krb5_data_free(&a);

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

    return KSUCCESS;
}
Пример #3
0
int
v4_prop(void *arg, struct v4_principal *p)
{
    struct prop_data *pd = arg;
    hdb_entry ent;
    krb5_error_code ret;

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

    ret = krb5_425_conv_principal(pd->context, p->name, p->instance, v4_realm,
				  &ent.principal);
    if(ret) {
	krb5_warn(pd->context, ret,
		  "krb5_425_conv_principal %s.%s@%s",
		  p->name, p->instance, v4_realm);
	return 0;
    }

    if(verbose_flag) {
	char *s;
	krb5_unparse_name_short(pd->context, ent.principal, &s);
	krb5_warnx(pd->context, "%s.%s -> %s", p->name, p->instance, s);
	free(s);
    }

    ent.kvno = p->kvno;
    ent.keys.len = 3;
    ent.keys.val = malloc(ent.keys.len * sizeof(*ent.keys.val));
    if(p->mkvno != -1) {
	ent.keys.val[0].mkvno = malloc (sizeof(*ent.keys.val[0].mkvno));
	*(ent.keys.val[0].mkvno) = p->mkvno;
    } else
	ent.keys.val[0].mkvno = NULL;
    ent.keys.val[0].salt = calloc(1, sizeof(*ent.keys.val[0].salt));
    ent.keys.val[0].salt->type = KRB5_PADATA_PW_SALT;
    ent.keys.val[0].key.keytype = ETYPE_DES_CBC_MD5;
    krb5_data_alloc(&ent.keys.val[0].key.keyvalue, DES_KEY_SZ);
    memcpy(ent.keys.val[0].key.keyvalue.data, p->key, 8);

    copy_Key(&ent.keys.val[0], &ent.keys.val[1]);
    ent.keys.val[1].key.keytype = ETYPE_DES_CBC_MD4;
    copy_Key(&ent.keys.val[0], &ent.keys.val[2]);
    ent.keys.val[2].key.keytype = ETYPE_DES_CBC_CRC;

    {
	int life = krb_life_to_time(0, p->max_life);
	if(life == NEVERDATE){
	    ent.max_life = NULL;
	} else {
	    /* clean up lifetime a bit */
	    if(life > 86400)
		life = (life + 86399) / 86400 * 86400;
	    else if(life > 3600)
		life = (life + 3599) / 3600 * 3600;
	    ALLOC(ent.max_life);
	    *ent.max_life = life;
	}
    }

    ALLOC(ent.valid_end);
    *ent.valid_end = p->exp_date;

    ret = krb5_make_principal(pd->context, &ent.created_by.principal,
			      v4_realm,
			      "kadmin",
			      "hprop",
			      NULL);
    if(ret){
	krb5_warn(pd->context, ret, "krb5_make_principal");
	ret = 0;
	goto out;
    }
    ent.created_by.time = time(NULL);
    ALLOC(ent.modified_by);
    ret = krb5_425_conv_principal(pd->context, p->mod_name, p->mod_instance, 
				  v4_realm, &ent.modified_by->principal);
    if(ret){
	krb5_warn(pd->context, ret, "%s.%s@%s", p->name, p->instance, v4_realm);
	ent.modified_by->principal = NULL;
	ret = 0;
	goto out;
    }
    ent.modified_by->time = p->mod_date;

    ent.flags.forwardable = 1;
    ent.flags.renewable = 1;
    ent.flags.proxiable = 1;
    ent.flags.postdate = 1;
    ent.flags.client = 1;
    ent.flags.server = 1;
    
    /* special case password changing service */
    if(strcmp(p->name, "changepw") == 0 && 
       strcmp(p->instance, "kerberos") == 0) {
	ent.flags.forwardable = 0;
	ent.flags.renewable = 0;
	ent.flags.proxiable = 0;
	ent.flags.postdate = 0;
	ent.flags.initial = 1;
	ent.flags.change_pw = 1;
    }

    ret = v5_prop(pd->context, NULL, &ent, pd);

    if (strcmp (p->name, "krbtgt") == 0
	&& strcmp (v4_realm, p->instance) != 0) {
	krb5_free_principal (pd->context, ent.principal);
	ret = krb5_425_conv_principal (pd->context, p->name,
				       v4_realm, p->instance,
				       &ent.principal);
	if (ret == 0)
	    ret = v5_prop (pd->context, NULL, &ent, pd);
    }

  out:
    hdb_free_entry(pd->context, &ent);
    return ret;
}
Пример #4
0
void
kerberos_v4(struct sockaddr_in *client, KTEXT pkt)
{
    static KTEXT_ST rpkt_st;
    KTEXT   rpkt = &rpkt_st;
    static KTEXT_ST ciph_st;
    KTEXT   ciph = &ciph_st;
    static KTEXT_ST tk_st;
    KTEXT   tk = &tk_st;
    static KTEXT_ST auth_st;
    KTEXT   auth = &auth_st;
    AUTH_DAT ad_st;
    AUTH_DAT *ad = &ad_st;


    static struct in_addr client_host;
    static int msg_byte_order;
    static int swap_bytes;
    static u_char k_flags;
 /* char   *p_name, *instance; */
    int     lifetime = 0;
    int     i;
    C_Block key;
    Key_schedule key_s;
    char   *ptr;

    krb5_keyblock k5key;
    krb5_kvno kvno;
    krb5_deltat sk5life, ck5life;
    KRB4_32 v4endtime, v4req_end;

    k5key.contents = NULL;	/* in case we have to free it */

    ciph->length = 0;

    client_host = client->sin_addr;

    /* eval macros and correct the byte order and alignment as needed */
    req_version = pkt_version(pkt);	/* 1 byte, version */
    req_msg_type = pkt_msg_type(pkt);	/* 1 byte, Kerberos msg type */

    /* set these to point to something safe */
    req_name_ptr = req_inst_ptr = req_realm_ptr = "";

    /* check if disabled, but we tell client */
    if (kdc_v4 == KDC_V4_DISABLE) {
	lt = klog(L_KRB_PERR,
	"KRB will not handle v4 request from %s",
		  inet_ntoa(client_host));
	/* send an error reply */
	req_name_ptr = req_inst_ptr = req_realm_ptr = "";
	kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
	return;
    }

    /* check packet version */
    if (req_version != KRB_PROT_VERSION) {
	lt = klog(L_KRB_PERR,
	"KRB prot version mismatch: KRB =%d request = %d",
		  KRB_PROT_VERSION, req_version, 0);
	/* send an error reply */
	req_name_ptr = req_inst_ptr = req_realm_ptr = "";
	kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt);
	return;
    }
    msg_byte_order = req_msg_type & 1;

    swap_bytes = 0;
    if (msg_byte_order != HOST_BYTE_ORDER) {
	swap_bytes++;
    }
    klog(L_KRB_PINFO,
	"Prot version: %d, Byte order: %d, Message type: %d",
	 (int) req_version, msg_byte_order, req_msg_type);

    switch (req_msg_type & ~1) {

    case AUTH_MSG_KDC_REQUEST:
	{
	    int    req_life;	/* Requested liftime */
	    unsigned int request_backdate =  0; /*How far to backdate
						  in seconds.*/
	    char   *service;	/* Service name */
	    char   *instance;	/* Service instance */
#ifdef notdef
	    int     kerno;	/* Kerberos error number */
#endif
	    n_auth_req++;
	    tk->length = 0;
	    k_flags = 0;	/* various kerberos flags */


	    /* set up and correct for byte order and alignment */
	    req_name_ptr = (char *) pkt_a_name(pkt);
	    str_length_check(req_name_ptr, ANAME_SZ);
	    req_inst_ptr = (char *) pkt_a_inst(pkt);
	    str_length_check(req_inst_ptr, INST_SZ);
	    req_realm_ptr = (char *) pkt_a_realm(pkt);
	    str_length_check(req_realm_ptr, REALM_SZ);
	    memcpy(&req_time_ws, pkt_time_ws(pkt), sizeof(req_time_ws));
	    /* time has to be diddled */
	    if (swap_bytes) {
		swap_u_long(req_time_ws);
	    }
	    ptr = (char *) pkt_time_ws(pkt) + 4;

	    req_life = (*ptr++) & 0xff;

	    service = ptr;
	    str_length_check(service, SNAME_SZ);
	    instance = ptr + strlen(service) + 1;
	    str_length_check(instance, INST_SZ);

	    rpkt = &rpkt_st;

	    klog(L_INI_REQ,
	    "Initial ticket request Host: %s User: \"%s\" \"%s\"",
	       inet_ntoa(client_host), req_name_ptr, req_inst_ptr, 0);

	    if ((i = check_princ(req_name_ptr, req_inst_ptr, 0,
				 &a_name_data, &k5key, 0, &ck5life))) {
		kerb_err_reply(client, pkt, i, "check_princ failed");
		a_name_data.key_low = a_name_data.key_high = 0;
		krb5_free_keyblock_contents(kdc_context, &k5key);
		return;
	    }
	    /* don't use k5key for client */
	    krb5_free_keyblock_contents(kdc_context, &k5key);
	    tk->length = 0;	/* init */
	    if (strcmp(service, "krbtgt"))
		klog(L_NTGT_INTK,
		    "INITIAL request from %s.%s for %s.%s", req_name_ptr,
		    req_inst_ptr, service, instance, 0);
	    /* this does all the checking */
	    if ((i = check_princ(service, instance, lifetime,
				 &s_name_data, &k5key, 1, &sk5life))) {
		kerb_err_reply(client, pkt, i, "check_princ failed");
		a_name_data.key_high = a_name_data.key_low = 0;
		s_name_data.key_high = s_name_data.key_low = 0;
		krb5_free_keyblock_contents(kdc_context, &k5key);
		return;
	    }
	    /* Bound requested lifetime with service and user */
	    v4req_end = krb_life_to_time(kerb_time.tv_sec, req_life);
	    v4req_end = min(v4req_end, kerb_time.tv_sec + ck5life);
	    v4req_end = min(v4req_end, kerb_time.tv_sec + sk5life);
	    lifetime = krb_time_to_life(kerb_time.tv_sec, v4req_end);
	    v4endtime = krb_life_to_time(kerb_time.tv_sec, lifetime);
	    /*
	     * Adjust issue time backwards if necessary, due to
	     * roundup in krb_time_to_life().
	     */
	    if (v4endtime > v4req_end)
		request_backdate = v4endtime - v4req_end;

#ifdef NOENCRYPTION
	    memset(session_key, 0, sizeof(C_Block));
#else
	    /* random session key */
	    des_new_random_key(session_key);
#endif

	    /* unseal server's key from master key */
	    memcpy( key,                &s_name_data.key_low,  4);
	    memcpy( ((krb5_ui_4 *) key) + 1, &s_name_data.key_high, 4);

	    s_name_data.key_low = s_name_data.key_high = 0;
	    kdb_encrypt_key(key, key, master_key,
			    master_key_schedule, DECRYPT);
	    /* construct and seal the ticket */
	    /* We always issue des tickets; the 3des tickets are a broken hack*/
	    krb_create_ticket(tk, k_flags, a_name_data.name,
			      a_name_data.instance, local_realm,
			      client_host.s_addr, (char *) session_key,
			      lifetime, kerb_time.tv_sec - request_backdate,
			      s_name_data.name, s_name_data.instance,
			      key);

	    krb5_free_keyblock_contents(kdc_context, &k5key);
	    memset(key, 0, sizeof(key));
	    memset(key_s, 0, sizeof(key_s));

	    /*
	     * get the user's key, unseal it from the server's key, and
	     * use it to seal the cipher 
	     */

	    /* a_name_data.key_low a_name_data.key_high */
	    memcpy( key,                &a_name_data.key_low,  4);
	    memcpy( ((krb5_ui_4 *) key) + 1, &a_name_data.key_high, 4);
	    a_name_data.key_low= a_name_data.key_high = 0;

	    /* unseal the a_name key from the master key */
	    kdb_encrypt_key(key, key, master_key, 
			    master_key_schedule, DECRYPT);

	    create_ciph(ciph, session_key, s_name_data.name,
			s_name_data.instance, local_realm, lifetime,
		  s_name_data.key_version, tk, kerb_time.tv_sec, key);

	    /* clear session key */
	    memset(session_key, 0, sizeof(session_key));

	    memset(key, 0, sizeof(key));



	    /* always send a reply packet */
	    rpkt = create_auth_reply(req_name_ptr, req_inst_ptr,
		req_realm_ptr, req_time_ws, 0, a_name_data.exp_date,
		a_name_data.key_version, ciph);
	    krb4_sendto(f, (char *) rpkt->dat, rpkt->length, 0,
		   (struct sockaddr *) client, sizeof (struct sockaddr_in));
	    memset(&a_name_data, 0, sizeof(a_name_data));
	    memset(&s_name_data, 0, sizeof(s_name_data));
	    break;
	}
    case AUTH_MSG_APPL_REQUEST:
	{
	    krb5_ui_4  time_ws;	/* Workstation time */
	    int    req_life;	/* Requested liftime */
	    char   *service;	/* Service name */
	    char   *instance;	/* Service instance */
	    int     kerno = 0;	/* Kerberos error number */
	    unsigned int request_backdate =  0; /*How far to backdate
						  in seconds.*/
	    char    tktrlm[REALM_SZ];

	    n_appl_req++;
	    tk->length = 0;
	    k_flags = 0;	/* various kerberos flags */

	    auth->mbz = 0;	/* pkt->mbz already zeroed */
	    auth->length = 4 + strlen((char *)pkt->dat + 3);
	    if (auth->length + 1 > MAX_KTXT_LEN) {
		lt = klog(L_KRB_PERR,
			  "APPL request with realm length too long from %s",
			  inet_ntoa(client_host));
		kerb_err_reply(client, pkt, RD_AP_INCON,
			       "realm length too long");
		return;
	    }

	    auth->length += (int) *(pkt->dat + auth->length) +
		(int) *(pkt->dat + auth->length + 1) + 2;
	    if (auth->length > MAX_KTXT_LEN) {
		lt = klog(L_KRB_PERR,
			  "APPL request with funky tkt or req_id length from %s",
			  inet_ntoa(client_host));
		kerb_err_reply(client, pkt, RD_AP_INCON,
			       "funky tkt or req_id length");
		return;
	    }

	    memcpy(auth->dat, pkt->dat, auth->length);

	    strncpy(tktrlm, (char *)auth->dat + 3, REALM_SZ);
	    tktrlm[REALM_SZ-1] = '\0';
	    kvno = (krb5_kvno)auth->dat[2];
	    if ((!allow_v4_crossrealm)&&strcmp(tktrlm, local_realm) != 0) {
	      lt = klog(L_ERR_UNK,
			"Cross realm ticket from %s denied by policy,", tktrlm);
	      kerb_err_reply(client, pkt,
			       KERB_ERR_PRINCIPAL_UNKNOWN, lt);
		return;
	    }
	    if (set_tgtkey(tktrlm, kvno, 0)) {
	      lt = klog(L_ERR_UNK,
			  "FAILED set_tgtkey realm %s, kvno %d. Host: %s ",
			  tktrlm, kvno, inet_ntoa(client_host));
		/* no better error code */
		kerb_err_reply(client, pkt,
			       KERB_ERR_PRINCIPAL_UNKNOWN, lt);
		return;
	    }
	    kerno = krb_rd_req(auth, "krbtgt", tktrlm, client_host.s_addr,
		ad, 0);
	    if (kerno) {
		if (set_tgtkey(tktrlm, kvno, 1)) {
		    lt = klog(L_ERR_UNK,
			      "FAILED 3des set_tgtkey realm %s, kvno %d. Host: %s ",
			      tktrlm, kvno, inet_ntoa(client_host));
		    /* no better error code */
		    kerb_err_reply(client, pkt,
				   KERB_ERR_PRINCIPAL_UNKNOWN, lt);
		    return;
		}
		kerno = krb_rd_req(auth, "krbtgt", tktrlm, client_host.s_addr,
				   ad, 0);
	    }

	    if (kerno) {
		klog(L_ERR_UNK, "FAILED krb_rd_req from %s: %s",
		     inet_ntoa(client_host), krb_get_err_text(kerno));
		req_name_ptr = req_inst_ptr = req_realm_ptr = "";
		kerb_err_reply(client, pkt, kerno, "krb_rd_req failed");
		return;
	    }
	    ptr = (char *) pkt->dat + auth->length;

	    memcpy(&time_ws, ptr, 4);
	    ptr += 4;

	    req_life = (*ptr++) & 0xff;

	    service = ptr;
	    str_length_check(service, SNAME_SZ);
	    instance = ptr + strlen(service) + 1;
	    str_length_check(instance, INST_SZ);

	    klog(L_APPL_REQ, "APPL Request %s.%s@%s on %s for %s.%s",
	     ad->pname, ad->pinst, ad->prealm,
	     inet_ntoa(client_host), service, instance, 0);
	    req_name_ptr = ad->pname;
	    req_inst_ptr = ad->pinst;
	    req_realm_ptr = ad->prealm;

	    if (strcmp(ad->prealm, tktrlm)) {
		kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
		     "Can't hop realms");
		return;
	    }
	    if (!strcmp(service, "changepw")) {
		kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN,
		     "Can't authorize password changed based on TGT");
		return;
	    }
	    kerno = check_princ(service, instance, req_life,
				&s_name_data, &k5key, 1, &sk5life);
	    if (kerno) {
		kerb_err_reply(client, pkt, kerno, "check_princ failed");
		s_name_data.key_high = s_name_data.key_low = 0;
		krb5_free_keyblock_contents(kdc_context, &k5key);
		return;
	    }
	    /* Bound requested lifetime with service and user */
	    v4endtime = krb_life_to_time((KRB4_32)ad->time_sec, ad->life);
	    v4req_end = krb_life_to_time(kerb_time.tv_sec, req_life);
	    v4req_end = min(v4endtime, v4req_end);
	    v4req_end = min(v4req_end, kerb_time.tv_sec + sk5life);

	    lifetime = krb_time_to_life(kerb_time.tv_sec, v4req_end);
	    v4endtime = krb_life_to_time(kerb_time.tv_sec, lifetime);
	    /*
	     * Adjust issue time backwards if necessary, due to
	     * roundup in krb_time_to_life().
	     */
	    if (v4endtime > v4req_end)
		request_backdate = v4endtime - v4req_end;

	    /* unseal server's key from master key */
	    memcpy(key,                &s_name_data.key_low,  4);
	    memcpy(((krb5_ui_4 *) key) + 1, &s_name_data.key_high, 4);
	    s_name_data.key_low = s_name_data.key_high = 0;
	    kdb_encrypt_key(key, key, master_key,
			    master_key_schedule, DECRYPT);
	    /* construct and seal the ticket */

#ifdef NOENCRYPTION
	    memset(session_key, 0, sizeof(C_Block));
#else
	    /* random session key */
	    des_new_random_key(session_key);
#endif

	    /* ALways issue des tickets*/
	    krb_create_ticket(tk, k_flags, ad->pname, ad->pinst,
			      ad->prealm, client_host.s_addr,
			      (char *) session_key, lifetime,
			      kerb_time.tv_sec - request_backdate,
			      s_name_data.name, s_name_data.instance,
			      key);
	    krb5_free_keyblock_contents(kdc_context, &k5key);
	    memset(key, 0, sizeof(key));
	    memset(key_s, 0, sizeof(key_s));

	    create_ciph(ciph, session_key, service, instance,
			local_realm,
			lifetime, s_name_data.key_version, tk,
			kerb_time.tv_sec, ad->session);

	    /* clear session key */
	    memset(session_key, 0, sizeof(session_key));

	    memset(ad->session, 0, sizeof(ad->session));

	    rpkt = create_auth_reply(ad->pname, ad->pinst,
				     ad->prealm, time_ws,
				     0, 0, 0, ciph);
	    krb4_sendto(f, (char *) rpkt->dat, rpkt->length, 0,
		   (struct sockaddr *) client, sizeof (struct sockaddr_in));
	    memset(&s_name_data, 0, sizeof(s_name_data));
	    break;
	}


#ifdef notdef_DIE
    case AUTH_MSG_DIE:
	{
	    lt = klog(L_DEATH_REQ,
	        "Host: %s User: \"%s\" \"%s\" Kerberos killed",
	        inet_ntoa(client_host), req_name_ptr, req_inst_ptr, 0);
	    exit(0);
	}
#endif /* notdef_DIE */

    default:
	{
	    lt = klog(L_KRB_PERR,
		"Unknown message type: %d from %s port %u",
		req_msg_type, inet_ntoa(client_host),
		ntohs(client->sin_port));
	    break;
	}
    }
}