 7975f805b4
			
		
	
	7975f805b4
	
	
	
		
			
			git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@305 ec53bebd-3082-4978-b11e-865c3cabbd6b
		
			
				
	
	
		
			200 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			200 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "krb5_locl.h"
 | |
| #include <krb5_error.h>
 | |
| #include <d.h>
 | |
| #include <k5_der.h>
 | |
| 
 | |
| static krb5_error_code
 | |
| krb5_get_salt (krb5_principal princ,
 | |
| 	       krb5_data realm,
 | |
| 	       krb5_data *salt)
 | |
| {
 | |
|      size_t len;
 | |
|      int i;
 | |
|      krb5_error_code err;
 | |
|      char *p;
 | |
|      
 | |
|      len = realm.length;
 | |
|      for (i = 0; i < princ->ncomp; ++i)
 | |
| 	  len += princ->comp[i].length;
 | |
|      err = krb5_data_alloc (salt, len);
 | |
|      if (err)
 | |
| 	  return err;
 | |
|      p = salt->data;
 | |
|      strncpy (p, realm.data, realm.length);
 | |
|      p += realm.length;
 | |
|      for (i = 0; i < princ->ncomp; ++i) {
 | |
| 	  strncpy (p, princ->comp[i].data, princ->comp[i].length);
 | |
| 	  p += princ->comp[i].length;
 | |
|      }
 | |
|      return 0;
 | |
| }
 | |
| 
 | |
| static krb5_error_code
 | |
| decrypt_tkt (krb5_context context,
 | |
| 	     const krb5_keyblock *key,
 | |
| 	     krb5_const_pointer decrypt_arg,
 | |
| 	     krb5_kdc_rep *dec_rep)
 | |
| {
 | |
|      des_key_schedule sched;
 | |
|      char *buf;
 | |
|      Buffer buffer;
 | |
| 
 | |
|      des_set_key (key->contents.data, sched);
 | |
|      buf = malloc (dec_rep->enc_part.cipher.length);
 | |
|      if (buf == NULL)
 | |
| 	  return ENOMEM;
 | |
|      des_cbc_encrypt ((des_cblock *)dec_rep->enc_part.cipher.data,
 | |
| 		      (des_cblock *)buf,
 | |
| 		      dec_rep->enc_part.cipher.length,
 | |
| 		      sched,
 | |
| 		      key->contents.data,
 | |
| 		      DES_DECRYPT);
 | |
| 				/* XXX: Check CRC */
 | |
|      buf_init (&buffer, buf + 12, dec_rep->enc_part.cipher.length - 12);
 | |
|      if (der_get_enctgsreppart (&buffer, &dec_rep->enc_part2) == -1) {
 | |
| 	  free (buf);
 | |
| 	  return ASN1_PARSE_ERROR;
 | |
|      }
 | |
|      free (buf);
 | |
|      return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *
 | |
|  */
 | |
| 
 | |
| krb5_error_code
 | |
| krb5_get_in_tkt(krb5_context context,
 | |
| 		krb5_flags options,
 | |
| 		krb5_address *const *addrs,
 | |
| 		const krb5_enctype *etypes,
 | |
| 		const krb5_preauthtype *ptypes,
 | |
| 		krb5_key_proc key_proc,
 | |
| 		krb5_const_pointer keyseed,
 | |
| 		krb5_decrypt_proc decrypt_proc,
 | |
| 		krb5_const_pointer decryptarg,
 | |
| 		krb5_creds *creds,
 | |
| 		krb5_ccache ccache,
 | |
| 		krb5_kdc_rep **ret_as_reply)
 | |
| {
 | |
|      krb5_error_code err;
 | |
|      As_Req a;
 | |
|      krb5_kdc_rep rep;
 | |
|      krb5_data req, resp;
 | |
|      char buf[BUFSIZ];
 | |
|      Buffer buffer;
 | |
|      krb5_data salt;
 | |
|      krb5_keyblock *key;
 | |
| 
 | |
|      a.pvno = 5;
 | |
|      a.msg_type = KRB_AS_REQ;
 | |
| /* a.kdc_options */
 | |
|      a.cname = creds->client;
 | |
|      a.sname = creds->server;
 | |
|      a.realm = creds->client->realm;
 | |
|      a.till  = creds->times.endtime;
 | |
|      a.nonce = 17;
 | |
|      if (etypes)
 | |
| 	  a.etypes = etypes;
 | |
|      else {
 | |
| 	  err = krb5_get_default_in_tkt_etypes (context, &a.etypes);
 | |
| 	  if (err)
 | |
| 	       return err;
 | |
| 	  a.num_etypes = 1;
 | |
|      }
 | |
|      if (addrs){
 | |
|      } else {
 | |
| 	  err = krb5_get_all_client_addrs (&a.addrs);
 | |
| 	  if (err)
 | |
| 	       return err;
 | |
|      }
 | |
|      
 | |
|      req.length = der_put_as_req (buf + sizeof(buf) - 1, &a);
 | |
|      req.data   = buf + sizeof(buf) - req.length;
 | |
|      if (addrs == NULL) {
 | |
| 	  int i;
 | |
| 
 | |
| 	  for (i = 0; i < a.addrs.number; ++i)
 | |
| 	       krb5_data_free (&a.addrs.addrs[i].address);
 | |
| 	  free (a.addrs.addrs);
 | |
|      }
 | |
| 
 | |
|      err = krb5_sendto_kdc (context, &req, &a.realm, &resp);
 | |
|      if (err) {
 | |
| 	  return err;
 | |
|      }
 | |
|      buf_init (&buffer, resp.data, resp.length);
 | |
|      if (der_get_as_rep (&buffer, &rep) == -1) {
 | |
| 	  return ASN1_PARSE_ERROR;
 | |
|      }
 | |
|      krb5_data_free (&rep.realm);
 | |
|      krb5_principal_free (rep.cname);
 | |
|      creds->ticket.kvno  = rep.ticket.kvno;
 | |
|      creds->ticket.etype = rep.ticket.etype;
 | |
|      creds->ticket.enc_part.length = 0;
 | |
|      creds->ticket.enc_part.data   = NULL;
 | |
|      krb5_data_copy (&creds->ticket.enc_part,
 | |
| 		     rep.ticket.enc_part.data,
 | |
| 		     rep.ticket.enc_part.length);
 | |
|      krb5_data_free (&rep.ticket.enc_part);
 | |
| 
 | |
|      krb5_copy_principal (context,
 | |
| 			  rep.ticket.sprinc,
 | |
| 			  &creds->ticket.sprinc);
 | |
|      krb5_free_principal (rep.ticket.sprinc);
 | |
| 
 | |
|      salt.length = 0;
 | |
|      salt.data = NULL;
 | |
|      err = krb5_get_salt (creds->client, creds->client->realm, &salt);
 | |
|      if (err)
 | |
| 	  return err;
 | |
|      err = (*key_proc)(context, rep.enc_part.etype, &salt, keyseed, &key);
 | |
|      krb5_data_free (&salt);
 | |
|      if (err)
 | |
| 	  return err;
 | |
|      
 | |
|      if (decrypt_proc == NULL)
 | |
| 	  decrypt_proc = decrypt_tkt;
 | |
| 
 | |
|      err = (*decrypt_proc)(context, key, decryptarg, &rep);
 | |
|      memset (key->contents.data, 0, key->contents.length);
 | |
|      krb5_data_free (&key->contents);
 | |
|      free (key);
 | |
|      if (rep.enc_part2.key_expiration)
 | |
| 	  free (rep.enc_part2.key_expiration);
 | |
|      if (rep.enc_part2.starttime)
 | |
| 	  free (rep.enc_part2.starttime);
 | |
|      if (rep.enc_part2.renew_till)
 | |
| 	  free (rep.enc_part2.renew_till);
 | |
|      if (rep.enc_part2.req.values)
 | |
| 	  free (rep.enc_part2.req.values);
 | |
|      if (rep.enc_part2.caddr.addrs) {
 | |
| 	  int i;
 | |
| 
 | |
| 	  for (i = 0; i < rep.enc_part2.caddr.number; ++i) {
 | |
| 	       krb5_data_free (&rep.enc_part2.caddr.addrs[i].address);
 | |
| 	  }
 | |
| 	  free (rep.enc_part2.caddr.addrs);
 | |
|      }
 | |
|      krb5_principal_free (rep.enc_part2.sname);
 | |
|      krb5_data_free (&rep.enc_part2.srealm);
 | |
| 	  
 | |
|      if (err)
 | |
| 	  return err;
 | |
| 
 | |
|      creds->session.contents.length = 0;
 | |
|      creds->session.contents.data   = NULL;
 | |
|      creds->session.keytype = rep.enc_part2.key.keytype;
 | |
|      err = krb5_data_copy (&creds->session.contents,
 | |
| 			   rep.enc_part2.key.contents.data,
 | |
| 			   rep.enc_part2.key.contents.length);
 | |
|      memset (rep.enc_part2.key.contents.data, 0,
 | |
| 	     rep.enc_part2.key.contents.length);
 | |
|      krb5_data_free (&rep.enc_part2.key.contents);
 | |
| 
 | |
|      if (err)
 | |
| 	  return err;
 | |
| 
 | |
|      return krb5_cc_store_cred (context, ccache, creds);
 | |
| }
 |