/ lib / krb5 / mk_priv.c
mk_priv.c
  1  /*
  2   * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
  3   * (Royal Institute of Technology, Stockholm, Sweden).
  4   * All rights reserved.
  5   *
  6   * Redistribution and use in source and binary forms, with or without
  7   * modification, are permitted provided that the following conditions
  8   * are met:
  9   *
 10   * 1. Redistributions of source code must retain the above copyright
 11   *    notice, this list of conditions and the following disclaimer.
 12   *
 13   * 2. Redistributions in binary form must reproduce the above copyright
 14   *    notice, this list of conditions and the following disclaimer in the
 15   *    documentation and/or other materials provided with the distribution.
 16   *
 17   * 3. Neither the name of the Institute nor the names of its contributors
 18   *    may be used to endorse or promote products derived from this software
 19   *    without specific prior written permission.
 20   *
 21   * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 24   * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 25   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 27   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 28   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 29   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 30   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 31   * SUCH DAMAGE.
 32   */
 33  
 34  #include "krb5_locl.h"
 35  
 36  KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 37  krb5_mk_priv(krb5_context context,
 38  	     krb5_auth_context auth_context,
 39  	     const krb5_data *userdata,
 40  	     krb5_data *outbuf,
 41  	     krb5_replay_data *outdata)
 42  {
 43      krb5_error_code ret;
 44      KRB_PRIV s;
 45      EncKrbPrivPart part;
 46      u_char *buf = NULL;
 47      size_t buf_size;
 48      size_t len = 0;
 49      krb5_crypto crypto;
 50      krb5_keyblock *key;
 51      krb5_replay_data rdata;
 52  
 53      if ((auth_context->flags &
 54  	 (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
 55  	outdata == NULL)
 56  	return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */
 57  
 58      if (auth_context->local_subkey)
 59  	key = auth_context->local_subkey;
 60      else if (auth_context->remote_subkey)
 61  	key = auth_context->remote_subkey;
 62      else
 63  	key = auth_context->keyblock;
 64  
 65      memset(&rdata, 0, sizeof(rdata));
 66  
 67      part.user_data = *userdata;
 68  
 69      krb5_us_timeofday (context, &rdata.timestamp, &rdata.usec);
 70  
 71      if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
 72  	part.timestamp = &rdata.timestamp;
 73  	part.usec      = &rdata.usec;
 74      } else {
 75  	part.timestamp = NULL;
 76  	part.usec      = NULL;
 77      }
 78  
 79      if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_TIME) {
 80  	outdata->timestamp = rdata.timestamp;
 81  	outdata->usec = rdata.usec;
 82      }
 83  
 84      if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
 85  	rdata.seq = auth_context->local_seqnumber;
 86  	part.seq_number = &rdata.seq;
 87      } else
 88  	part.seq_number = NULL;
 89  
 90      if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)
 91  	outdata->seq = auth_context->local_seqnumber;
 92  
 93      part.s_address = auth_context->local_address;
 94      part.r_address = auth_context->remote_address;
 95  
 96      krb5_data_zero (&s.enc_part.cipher);
 97  
 98      ASN1_MALLOC_ENCODE(EncKrbPrivPart, buf, buf_size, &part, &len, ret);
 99      if (ret)
100  	goto fail;
101      if (buf_size != len)
102  	krb5_abortx(context, "internal error in ASN.1 encoder");
103  
104      s.pvno = 5;
105      s.msg_type = krb_priv;
106      s.enc_part.etype = key->keytype;
107      s.enc_part.kvno = NULL;
108  
109      ret = krb5_crypto_init(context, key, 0, &crypto);
110      if (ret) {
111  	free (buf);
112  	return ret;
113      }
114      ret = krb5_encrypt (context,
115  			crypto,
116  			KRB5_KU_KRB_PRIV,
117  			buf + buf_size - len,
118  			len,
119  			&s.enc_part.cipher);
120      krb5_crypto_destroy(context, crypto);
121      if (ret) {
122  	free(buf);
123  	return ret;
124      }
125      free(buf);
126  
127  
128      ASN1_MALLOC_ENCODE(KRB_PRIV, buf, buf_size, &s, &len, ret);
129      if (ret)
130  	goto fail;
131      if (buf_size != len)
132  	krb5_abortx(context, "internal error in ASN.1 encoder");
133  
134      krb5_data_free (&s.enc_part.cipher);
135  
136      ret = krb5_data_copy(outbuf, buf + buf_size - len, len);
137      if (ret) {
138  	krb5_set_error_message(context, ENOMEM,
139  			       N_("malloc: out of memory", ""));
140  	free(buf);
141  	return ENOMEM;
142      }
143      free (buf);
144      if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE)
145  	auth_context->local_seqnumber =
146  	    (auth_context->local_seqnumber + 1) & 0xFFFFFFFF;
147      return 0;
148  
149    fail:
150      free (buf);
151      krb5_data_free (&s.enc_part.cipher);
152      return ret;
153  }