Moved most of this to kerberos5.c
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1846 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
		
							
								
								
									
										629
									
								
								kdc/kdc.c
									
									
									
									
									
								
							
							
						
						
									
										629
									
								
								kdc/kdc.c
									
									
									
									
									
								
							| @@ -1,629 +0,0 @@ | ||||
| #include "kdc_locl.h" | ||||
|  | ||||
| RCSID("$Id$"); | ||||
|  | ||||
| struct timeval now; | ||||
| #define kdc_time now.tv_sec | ||||
|  | ||||
| #ifndef MIN | ||||
| #define MIN(A,B) ((A)<(B)?(A):(B)) | ||||
| #endif | ||||
|  | ||||
| #define MAX_TIME ((time_t)((1U << 31) - 1)) | ||||
|  | ||||
| hdb_entry* | ||||
| db_fetch(krb5_context context, PrincipalName *principal, char *realm) | ||||
| { | ||||
|     HDB *db; | ||||
|     hdb_entry *ent; | ||||
|  | ||||
|     ent = malloc(sizeof(*ent)); | ||||
|     principalname2krb5_principal(&ent->principal, *principal, realm); | ||||
|     hdb_open(context, &db, NULL, O_RDONLY, 0); | ||||
|     db->fetch(context, db, ent); | ||||
|     db->close(context, db); | ||||
|     return ent; | ||||
| } | ||||
|  | ||||
| krb5_error_code | ||||
| krb5_encrypt (krb5_context context, | ||||
| 	      void *ptr, | ||||
| 	      size_t len, | ||||
| 	      krb5_keyblock *keyblock, | ||||
| 	      krb5_data *result); | ||||
|  | ||||
| krb5_error_code | ||||
| krb5_mk_error(krb5_principal princ,  | ||||
| 	      krb5_error_code error_code, | ||||
| 	      char *e_text, | ||||
| 	      krb5_data *e_data, | ||||
| 	      krb5_data *err) | ||||
| { | ||||
|     KRB_ERROR msg; | ||||
|     unsigned char buf[1024]; | ||||
|      | ||||
|     memset(&msg, 0, sizeof(msg)); | ||||
|     msg.pvno = 5; | ||||
|     msg.msg_type = krb_error; | ||||
|     msg.stime = time(0); | ||||
|     msg.error_code = error_code; | ||||
|     msg.realm = princ->realm.data; | ||||
|     krb5_principal2principalname(&msg.sname, princ); | ||||
|     if (e_text) | ||||
| 	msg.e_text = &e_text; | ||||
|     if (e_data) | ||||
| 	msg.e_data = e_data; | ||||
|     err->length = encode_KRB_ERROR(buf + sizeof(buf) - 1, sizeof(buf), &msg); | ||||
|     err->data = malloc(err->length); | ||||
|     memcpy(err->data, buf + sizeof(buf) - err->length, err->length); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| krb5_error_code | ||||
| mk_des_keyblock(EncryptionKey *kb) | ||||
| { | ||||
|     kb->keytype = KEYTYPE_DES; | ||||
|     kb->keyvalue.data = malloc(sizeof(des_cblock)); | ||||
|     kb->keyvalue.length = sizeof(des_cblock); | ||||
|     des_rand_data_key(kb->keyvalue.data); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| krb5_error_code | ||||
| as_rep(krb5_context context,  | ||||
|        KDC_REQ *req,  | ||||
|        krb5_data *data) | ||||
| { | ||||
|     KDC_REQ_BODY *b = &req->req_body; | ||||
|     AS_REP rep; | ||||
|     KDCOptions f = b->kdc_options; | ||||
|     hdb_entry *client, *server; | ||||
|     int use_etype; | ||||
|     EncTicketPart *et = calloc(1, sizeof(*et)); | ||||
|     EncKDCRepPart *ek = calloc(1, sizeof(*ek)); | ||||
|     krb5_principal client_princ; | ||||
|  | ||||
|     client = db_fetch(context, b->cname, b->realm); | ||||
|     server = db_fetch(context, b->sname, b->realm); | ||||
|  | ||||
|     if(client == NULL) | ||||
| 	return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; | ||||
|     if(server == NULL){ | ||||
| 	hdb_free_entry(context, client); | ||||
| 	free(client); | ||||
| 	return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; | ||||
|     } | ||||
|  | ||||
|     principalname2krb5_principal (&client_princ, *(b->cname), b->realm); | ||||
|  | ||||
|     /* XXX Check for pa_enc_timestamp */ | ||||
|      | ||||
|     if(req->padata == NULL || req->padata->len < 1 || | ||||
|        req->padata->val->padata_type != pa_enc_timestamp) { | ||||
| 	PA_DATA foo; | ||||
| 	u_char buf[16]; | ||||
| 	int len; | ||||
| 	krb5_data foo_data; | ||||
|  | ||||
| 	foo.padata_type = pa_enc_timestamp; | ||||
| 	foo.padata_value.length = 0; | ||||
| 	foo.padata_value.data   = NULL; | ||||
|  | ||||
| 	len = encode_PA_DATA(buf + sizeof(buf) - 1, | ||||
| 			     sizeof(buf), | ||||
| 			     &foo); | ||||
| 	foo_data.length = len; | ||||
| 	foo_data.data   = buf + sizeof(buf) - len; | ||||
|  | ||||
| 	krb5_mk_error (client_princ, | ||||
| 		       KRB5KDC_ERR_PREAUTH_REQUIRED, | ||||
| 		       "Need to use PA-ENC-TIMESTAMP", | ||||
| 		       &foo_data, | ||||
| 		       data); | ||||
|  | ||||
| 	return 0; | ||||
|     } else { | ||||
| 	krb5_data ts_data; | ||||
| 	PA_ENC_TS_ENC p; | ||||
| 	int len; | ||||
|  | ||||
| 	krb5_decrypt (context, | ||||
| 		      req->padata->val->padata_value.data, | ||||
| 		      req->padata->val->padata_value.length, | ||||
| 		      &client->keyblock, | ||||
| 		      &ts_data); | ||||
| 	len = decode_PA_ENC_TS_ENC(ts_data.data, | ||||
| 				   ts_data.length, | ||||
| 				   &p); | ||||
| 	if (len < 0) { | ||||
| 	    krb5_mk_error (client_princ, | ||||
| 			   KRB5KRB_AP_ERR_BAD_INTEGRITY, | ||||
| 			   "Couldn't decode", | ||||
| 			   NULL, | ||||
| 			   data); | ||||
| 	    return 0; | ||||
| 	} | ||||
| 	if (kdc_time - p.patimestamp > 300) { | ||||
| 	    krb5_mk_error (client_princ, | ||||
| 			   KRB5KDC_ERR_PREAUTH_FAILED, | ||||
| 			   "Too large time skew", | ||||
| 			   NULL, | ||||
| 			   data); | ||||
| 	    return 0; | ||||
| 	} | ||||
|  | ||||
|     } | ||||
|  | ||||
|     if(b->etype.len == 0) | ||||
| 	return KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ | ||||
|     use_etype = b->etype.val[0]; | ||||
|  | ||||
|     memset(&rep, 0, sizeof(rep)); | ||||
|     rep.pvno = 5; | ||||
|     rep.msg_type = krb_as_rep; | ||||
|     copy_Realm(&b->realm, &rep.crealm); | ||||
|     copy_PrincipalName(b->cname, &rep.cname); | ||||
|     rep.ticket.tkt_vno = 5; | ||||
|     copy_Realm(&b->realm, &rep.ticket.realm); | ||||
|     copy_PrincipalName(b->sname, &rep.ticket.sname); | ||||
|  | ||||
|     if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey) | ||||
| 	return KRB5KDC_ERR_BADOPTION; | ||||
|      | ||||
|     et->flags.initial = 1; | ||||
|     et->flags.forwardable = f.forwardable; | ||||
|     et->flags.proxiable = f.proxiable; | ||||
|     et->flags.may_postdate = f.allow_postdate; | ||||
|  | ||||
|     mk_des_keyblock(&et->key); | ||||
|     copy_PrincipalName(b->cname, &et->cname); | ||||
|     copy_Realm(&b->realm, &et->crealm); | ||||
|      | ||||
|     { | ||||
| 	time_t start; | ||||
| 	time_t t; | ||||
| 	 | ||||
| 	start = et->authtime = kdc_time; | ||||
|      | ||||
| 	if(f.postdated && req->req_body.from){ | ||||
| 	    et->starttime = malloc(sizeof(*et->starttime)); | ||||
| 	    start = *et->starttime = *req->req_body.from; | ||||
| 	    et->flags.invalid = 1; | ||||
| 	    et->flags.postdated = 1; /* XXX ??? */ | ||||
| 	} | ||||
| 	if(b->till == 0) | ||||
| 	    b->till = MAX_TIME; | ||||
| 	t = b->till; | ||||
| 	if(client->max_life) | ||||
| 	    t = MIN(t, start + client->max_life); | ||||
| 	if(server->max_life) | ||||
| 	    t = MIN(t, start + server->max_life); | ||||
| #if 0 | ||||
| 	t = MIN(t, start + realm->max_life); | ||||
| #endif | ||||
| 	et->endtime = t; | ||||
| 	if(f.renewable_ok && et->endtime < b->till){ | ||||
| 	    f.renewable = 1; | ||||
| 	    if(b->rtime == NULL){ | ||||
| 		b->rtime = malloc(sizeof(*b->rtime)); | ||||
| 		*b->rtime = 0; | ||||
| 	    } | ||||
| 	    if(*b->rtime < b->till) | ||||
| 		*b->rtime = b->till; | ||||
| 	} | ||||
| 	if(f.renewable && b->rtime){ | ||||
| 	    t = *b->rtime; | ||||
| 	    if(t == 0) | ||||
| 		t = MAX_TIME; | ||||
| 	    if(client->max_renew) | ||||
| 		t = MIN(t, start + client->max_renew); | ||||
| 	    if(server->max_renew) | ||||
| 		t = MIN(t, start + server->max_renew); | ||||
| #if 0 | ||||
| 	    t = MIN(t, start + realm->max_renew); | ||||
| #endif | ||||
| 	    et->renew_till = malloc(sizeof(*et->renew_till)); | ||||
| 	    *et->renew_till = t; | ||||
| 	} | ||||
|     } | ||||
|     if(b->addresses){ | ||||
| 	et->caddr = malloc(sizeof(*et->caddr)); | ||||
| 	copy_HostAddresses(b->addresses, et->caddr); | ||||
|     } | ||||
|  | ||||
|     memset(ek, 0, sizeof(*ek)); | ||||
|     copy_EncryptionKey(&et->key, &ek->key); | ||||
|     /* MIT must have at least one last_req */ | ||||
|     ek->last_req.len = 1; | ||||
|     ek->last_req.val = malloc(sizeof(*ek->last_req.val)); | ||||
|     ek->last_req.val->lr_type = 0; | ||||
|     ek->last_req.val->lr_value = 0; | ||||
|     ek->nonce = b->nonce; | ||||
|     ek->flags = et->flags; | ||||
|     ek->authtime = et->authtime; | ||||
|     ek->starttime = et->starttime; | ||||
|     ek->endtime = et->endtime; | ||||
|     ek->renew_till = et->renew_till; | ||||
|     copy_Realm(&rep.ticket.realm, &ek->srealm); | ||||
|     copy_PrincipalName(&rep.ticket.sname, &ek->sname); | ||||
|     if(et->caddr){ | ||||
| 	ek->caddr = malloc(sizeof(*ek->caddr)); | ||||
| 	copy_HostAddresses(et->caddr, ek->caddr); | ||||
|     } | ||||
|  | ||||
|     { | ||||
| 	unsigned char buf[1024]; /* XXX The data could be indefinite */ | ||||
| 	int len; | ||||
| 	len = encode_EncTicketPart(buf + sizeof(buf) - 1, sizeof(buf), et); | ||||
| 	free_EncTicketPart(et); | ||||
| 	free(et); | ||||
| 	if(len < 0) | ||||
| 	    return ASN1_OVERFLOW; | ||||
|  | ||||
| 	rep.ticket.enc_part.etype = ETYPE_DES_CBC_CRC; | ||||
| 	rep.ticket.enc_part.kvno = NULL; | ||||
| 	krb5_encrypt(context, buf + sizeof(buf) - len, len, &server->keyblock,  | ||||
| 		     &rep.ticket.enc_part.cipher); | ||||
| 	 | ||||
| 	len = encode_EncASRepPart(buf + sizeof(buf) - 1, sizeof(buf), ek); | ||||
| 	free_EncKDCRepPart(ek); | ||||
| 	free(ek); | ||||
| 	if(len < 0) | ||||
| 	    return ASN1_OVERFLOW; | ||||
| 	rep.enc_part.etype = ETYPE_DES_CBC_CRC; | ||||
| 	rep.enc_part.kvno = NULL; | ||||
|  | ||||
| 	krb5_encrypt(context, buf + sizeof(buf) - len, len, &client->keyblock,  | ||||
| 		     &rep.enc_part.cipher); | ||||
| 	 | ||||
| 	len = encode_AS_REP(buf + sizeof(buf) - 1, sizeof(buf), &rep); | ||||
| 	if(len < 0) | ||||
| 	    return ASN1_OVERFLOW; | ||||
| 	free_AS_REP(&rep); | ||||
| 	 | ||||
| 	krb5_data_copy(data, buf + sizeof(buf) - len, len); | ||||
| 	 | ||||
|     } | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| krb5_error_code | ||||
| tgs_rep(krb5_context context,  | ||||
| 	KDC_REQ *req,  | ||||
| 	krb5_data *data) | ||||
| { | ||||
|     KDC_REQ_BODY *b = &req->req_body; | ||||
|     KDCOptions f = req->req_body.kdc_options; | ||||
|     EncTicketPart *tgt; | ||||
|     hdb_entry *server, *krbtgt, *client; | ||||
|     TGS_REP rep; | ||||
|     EncTicketPart *et = calloc(1, sizeof(*et)); | ||||
|     EncKDCRepPart *ek = calloc(1, sizeof(*ek)); | ||||
|      | ||||
|     if(req->padata == NULL || req->padata->len < 1) | ||||
| 	return KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */ | ||||
|     if(req->padata->val->padata_type != pa_tgs_req) | ||||
| 	return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; | ||||
|  | ||||
|     { | ||||
| 	krb5_auth_context ac = NULL; | ||||
| 	krb5_principal princ; | ||||
| 	krb5_flags ap_req_options; | ||||
| 	krb5_ticket *ticket; | ||||
| 	krb5_error_code err; | ||||
| 	hdb_entry *ent; | ||||
|  | ||||
| 	err = krb5_build_principal(context, | ||||
| 				   &princ, | ||||
| 				   strlen(req->req_body.realm), | ||||
| 				   req->req_body.realm, | ||||
| 				   "krbtgt", | ||||
| 				   req->req_body.realm, | ||||
| 				   NULL); | ||||
| 	if(err) return err; | ||||
| 	 | ||||
| 	{ | ||||
| 	    PrincipalName p; | ||||
| 	    p.name_string.val = calloc(2, sizeof(*p.name_string.val)); | ||||
| 	    p.name_string.len = 2; | ||||
| 	    p.name_string.val[0] = "krbtgt"; | ||||
| 	    p.name_string.val[1] = req->req_body.realm; | ||||
| 	    krbtgt = db_fetch(context, &p, req->req_body.realm); | ||||
| 	    free(p.name_string.val); | ||||
| 	} | ||||
| 	if(ent == NULL)  | ||||
| 	    return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; | ||||
|      | ||||
| 	err = krb5_rd_req_with_keyblock(context, &ac, | ||||
| 					&req->padata->val->padata_value, | ||||
| 					princ, | ||||
| 					&krbtgt->keyblock, | ||||
| 					&ap_req_options, | ||||
| 					&ticket); | ||||
| 	if(err)  | ||||
| 	    return err; | ||||
|  | ||||
| 	/* XXX Check authenticator */ | ||||
|  | ||||
| 	server = db_fetch(context, b->sname, b->realm); | ||||
| 	 | ||||
| 	if(server == NULL) | ||||
| 	    return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; | ||||
|  | ||||
| 	tgt = &ticket->tkt; | ||||
|  | ||||
| 	client = db_fetch(context, &tgt->cname, tgt->crealm); | ||||
| 	if(client == NULL) | ||||
| 	    return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; | ||||
|  | ||||
| 	memset(&rep, 0, sizeof(rep)); | ||||
| 	rep.pvno = 5; | ||||
| 	rep.msg_type = krb_tgs_rep; | ||||
| 	rep.crealm = tgt->crealm; | ||||
| 	rep.cname = tgt->cname; | ||||
| 	rep.ticket.tkt_vno = 5; | ||||
| 	rep.ticket.sname = *b->sname; | ||||
| 	rep.ticket.realm = b->realm; | ||||
|  | ||||
| 	et->caddr = ticket->tkt.caddr; | ||||
| 	 | ||||
| 	if(f.forwardable){ | ||||
| 	    if(!tgt->flags.forwardable) | ||||
| 		return KRB5KDC_ERR_BADOPTION; | ||||
| 	    et->flags.forwardable = 1; | ||||
| 	} | ||||
| 	if(f.forwarded){ | ||||
| 	    if(!tgt->flags.forwardable) | ||||
| 		return KRB5KDC_ERR_BADOPTION; | ||||
| 	    et->flags.forwarded = 1; | ||||
| 	    et->caddr = req->req_body.addresses; | ||||
| 	    /* resp.caddr := req.addresses */ | ||||
| 	} | ||||
| 	et->flags.forwarded = tgt->flags.forwarded; | ||||
|  | ||||
| 	if(f.proxiable){ | ||||
| 	    if(!tgt->flags.proxiable) | ||||
| 		return KRB5KDC_ERR_BADOPTION; | ||||
| 	    et->flags.proxiable = 1; | ||||
| 	} | ||||
| 	if(f.proxy){ | ||||
| 	    if(!tgt->flags.proxiable) | ||||
| 		return KRB5KDC_ERR_BADOPTION; | ||||
| 	    et->flags.proxy = 1; | ||||
| 	    et->caddr = req->req_body.addresses; | ||||
| 	    /* resp.caddr := req.addresses */ | ||||
| 	} | ||||
| 	if(f.allow_postdate){ | ||||
| 	    if(!tgt->flags.may_postdate) | ||||
| 		return KRB5KDC_ERR_BADOPTION; | ||||
| 	    et->flags.may_postdate = 1; | ||||
| 	} | ||||
| 	if(f.postdated){ | ||||
| 	    if(!tgt->flags.may_postdate) | ||||
| 		return KRB5KDC_ERR_BADOPTION; | ||||
| 	    et->flags.postdated = 1; | ||||
| 	    et->flags.invalid = 1; | ||||
| 	    et->starttime = malloc(sizeof(*et->starttime)); | ||||
| 	    *et->starttime = *req->req_body.from; | ||||
| 	} | ||||
| 	if(f.validate){ | ||||
| 	    if(!tgt->flags.invalid) | ||||
| 		return KRB5KDC_ERR_BADOPTION; | ||||
| 	    if(*tgt->starttime > kdc_time) | ||||
| 		return KRB5KRB_AP_ERR_TKT_NYV; | ||||
| 	    /* XXX  tkt = tgt */ | ||||
| 	    et->flags.invalid = 0; | ||||
| 	} | ||||
| 	/* check for excess flags */ | ||||
| 	 | ||||
| 	et->authtime = tgt->authtime; | ||||
| 	 | ||||
| 	if(f.renew){ | ||||
| 	    time_t old_life; | ||||
| 	    if(!tgt->flags.renewable) | ||||
| 		return KRB5KDC_ERR_BADOPTION; | ||||
| 	    if(*tgt->renew_till >= kdc_time) | ||||
| 		return KRB5KRB_AP_ERR_TKT_EXPIRED; | ||||
| 	    /* XXX tkt = tgt */ | ||||
| 	    et->starttime = malloc(sizeof(*et->starttime)); | ||||
| 	    *et->starttime = kdc_time; | ||||
| 	    old_life = tgt->endtime - *tgt->starttime; | ||||
| 	    et->endtime = MIN(*tgt->renew_till, | ||||
| 			      *et->starttime + old_life); | ||||
| 	}else{ | ||||
| 	    time_t till; | ||||
| 	    et->starttime = malloc(sizeof(*et->starttime)); | ||||
| 	    *et->starttime = kdc_time; | ||||
| 	    till = b->till; | ||||
| 	    if(till == 0) | ||||
| 		till = MAX_TIME; | ||||
| 	    if(client->max_life) | ||||
| 		till = MIN(till, *et->starttime + client->max_life); | ||||
| 	    if(server->max_life) | ||||
| 		till = MIN(till, *et->starttime + server->max_life); | ||||
| 	    till = MIN(till, tgt->endtime); | ||||
| #if 0 | ||||
| 	    till = MIN(till, et->starttime + realm->max_life); | ||||
| #endif | ||||
| 	    et->endtime = till; | ||||
| 	    if(f.renewable_ok &&  | ||||
| 	       et->endtime < b->till &&  | ||||
| 	       tgt->flags.renewable){ | ||||
| 		f.renewable = 1; | ||||
| 		b->rtime = malloc(sizeof(*b->rtime)); | ||||
| 		*b->rtime = MIN(b->till, *tgt->renew_till); | ||||
| 	    } | ||||
| 	} | ||||
| 	if(f.renewable && tgt->flags.renewable && b->rtime){ | ||||
| 	    time_t rtime; | ||||
| 	    rtime = *b->rtime; | ||||
| 	    if(rtime == 0) | ||||
| 		rtime = MAX_TIME; | ||||
| 	    et->flags.renewable = 1; | ||||
| 	    if(client->max_renew) | ||||
| 		rtime = MIN(rtime, *et->starttime + client->max_renew); | ||||
| 	    if(server->max_renew) | ||||
| 		rtime = MIN(rtime, *et->starttime + server->max_renew); | ||||
| 	    rtime = MIN(rtime, *tgt->renew_till); | ||||
| #if 0 | ||||
| 	    rtime = MIN(rtime, *et->starttime + realm->max_renew); | ||||
| #endif | ||||
| 	    et->renew_till = malloc(sizeof(*et->renew_till)); | ||||
| 	    *et->renew_till = rtime; | ||||
| 	} | ||||
|  | ||||
| 	/* XXX Check enc-authorization-data */ | ||||
|  | ||||
| 	 | ||||
| 	mk_des_keyblock(&et->key); | ||||
| 	et->crealm = tgt->crealm; | ||||
| 	et->cname = tgt->cname; | ||||
| 	et->transited = tgt->transited; | ||||
| 	 | ||||
|  | ||||
| 	memset(ek, 0, sizeof(*ek)); | ||||
| 	ek->key = et->key; | ||||
| 	/* MIT must have at least one last_req */ | ||||
| 	ek->last_req.len = 1; | ||||
| 	ek->last_req.val = malloc(sizeof(*ek->last_req.val)); | ||||
| 	ek->last_req.val->lr_type = 0; | ||||
| 	ek->last_req.val->lr_value = 0; | ||||
| 	ek->nonce = b->nonce; | ||||
| 	ek->flags = et->flags; | ||||
| 	ek->authtime = et->authtime; | ||||
| 	ek->starttime = et->starttime; | ||||
| 	ek->endtime = et->endtime; | ||||
| 	ek->renew_till = et->renew_till; | ||||
| 	ek->srealm = rep.ticket.realm; | ||||
| 	ek->sname = rep.ticket.sname; | ||||
| 	ek->caddr = et->caddr; | ||||
| 	 | ||||
| 	{ | ||||
| 	    unsigned char buf[1024]; /* XXX The data could be indefinite */ | ||||
| 	    int len; | ||||
| 	    len = encode_EncTicketPart(buf + sizeof(buf) - 1, sizeof(buf), et); | ||||
| 	    if(len < 0) | ||||
| 		return ASN1_OVERFLOW; | ||||
| 	    rep.ticket.enc_part.etype = ETYPE_DES_CBC_CRC; | ||||
| 	    rep.ticket.enc_part.kvno = NULL; | ||||
| 	    krb5_encrypt(context, buf + sizeof(buf) - len, len, &server->keyblock,  | ||||
| 			 &rep.ticket.enc_part.cipher); | ||||
| 	     | ||||
| 	    len = encode_EncTGSRepPart(buf + sizeof(buf) - 1, sizeof(buf), ek); | ||||
| 	    if(len < 0) | ||||
| 		return ASN1_OVERFLOW; | ||||
| 	    rep.enc_part.etype = ETYPE_DES_CBC_CRC; | ||||
| 	    rep.enc_part.kvno = NULL; | ||||
| 	    { | ||||
| 		krb5_keyblock kb; | ||||
| 		kb.keytype = tgt->key.keytype; | ||||
| 		kb.contents = tgt->key.keyvalue; | ||||
| 		krb5_encrypt(context, buf + sizeof(buf) - len, len, &kb,  | ||||
| 			     &rep.enc_part.cipher); | ||||
| 	    } | ||||
| 	     | ||||
| 	    len = encode_TGS_REP(buf + sizeof(buf) - 1, sizeof(buf), &rep); | ||||
| 	    if(len < 0) | ||||
| 		return ASN1_OVERFLOW; | ||||
| 	    free_TGS_REP(&rep); | ||||
| 	    krb5_data_copy(data, buf + sizeof(buf) - len, len); | ||||
| 	} | ||||
| 	 | ||||
| 	return 0; | ||||
|     } | ||||
| 	     | ||||
| } | ||||
|  | ||||
|  | ||||
| krb5_error_code | ||||
| process_request(krb5_context context,  | ||||
|     KDC_REQ *req,  | ||||
|     krb5_data *reply) | ||||
| { | ||||
|     gettimeofday(&now, NULL); | ||||
|  | ||||
|     if(req->msg_type == krb_as_req) | ||||
| 	return as_rep(context, req, reply); | ||||
|     else if(req->msg_type == krb_tgs_req) | ||||
| 	return tgs_rep(context, req, reply); | ||||
|     else | ||||
| 	return KRB5KRB_AP_ERR_MSG_TYPE;	/* XXX */ | ||||
| } | ||||
|  | ||||
| int | ||||
| kerberos(krb5_context context,  | ||||
| 	 unsigned char *buf,  | ||||
| 	 size_t len,  | ||||
| 	 krb5_data *reply) | ||||
| { | ||||
|     KDC_REQ req; | ||||
|     krb5_error_code err; | ||||
|     int i; | ||||
|     i = decode_AS_REQ(buf, len, &req); | ||||
|     if(i >= 0){ | ||||
| 	err = process_request(context, &req, reply); | ||||
| 	free_AS_REQ(&req); | ||||
| 	return err; | ||||
|     } | ||||
|     i = decode_TGS_REQ(buf, len, &req); | ||||
|     if(i >= 0){ | ||||
| 	err = process_request(context, &req, reply); | ||||
| 	free_TGS_REQ(&req); | ||||
| 	return err; | ||||
|     } | ||||
|     return -1; | ||||
| } | ||||
|  | ||||
| main(int argc, char **argv) | ||||
| { | ||||
|     krb5_context context; | ||||
|     int s = socket(AF_INET, SOCK_DGRAM, 0); | ||||
|     struct sockaddr_in sin; | ||||
|     int one = 1; | ||||
|     if(s < 0){ | ||||
| 	perror("socket"); | ||||
| 	exit(1); | ||||
|     } | ||||
|     krb5_init_context(&context); | ||||
|     memset(&sin, 0, sizeof(sin)); | ||||
|     sin.sin_family = AF_INET; | ||||
|     sin.sin_port = htons(88); | ||||
|     if(bind(s, (struct sockaddr*)&sin, sizeof(sin)) < 0){ | ||||
| 	perror("bind"); | ||||
| 	exit(1); | ||||
|     } | ||||
|     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); | ||||
|     while(1){ | ||||
| 	fd_set fds; | ||||
| 	unsigned char buf[1024]; | ||||
| 	size_t len; | ||||
| 	FD_ZERO(&fds); | ||||
| 	FD_SET(s, &fds); | ||||
| 	if(select(s + 1, &fds, NULL, NULL, NULL) < 0){ | ||||
| 	    perror("select"); | ||||
| 	    exit(1); | ||||
| 	} | ||||
| 	if(FD_ISSET(s, &fds)){ | ||||
| 	    struct sockaddr_in from; | ||||
| 	    int from_len = sizeof(from); | ||||
| 	    krb5_error_code err; | ||||
| 	    krb5_data reply; | ||||
| 	    len = recvfrom(s, buf, sizeof(buf), 0,  | ||||
| 			   (struct sockaddr*)&from, &from_len); | ||||
| 	    fprintf(stderr, "%d byte packet from %s\n",  | ||||
| 		    len, inet_ntoa(from.sin_addr)); | ||||
| 	    err = kerberos(context, buf, len, &reply); | ||||
| 	    if(err){ | ||||
| 		fprintf(stderr, "%s\n", krb5_get_err_text(context, err)); | ||||
| 	    }else{ | ||||
| 		fprintf(stderr, "sending %d bytes\n", reply.length); | ||||
| 		sendto(s, reply.data, reply.length, 0,  | ||||
| 		       (struct sockaddr*)&from, from_len); | ||||
| 		krb5_data_free(&reply); | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Johan Danielsson
					Johan Danielsson