/ lib / krb5 / data.c
data.c
  1  /*
  2   * Copyright (c) 1997 - 2007 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  #undef HEIMDAL_PRINTF_ATTRIBUTE
 37  #define HEIMDAL_PRINTF_ATTRIBUTE(x)
 38  
 39  /**
 40   * Reset the (potentially uninitalized) krb5_data structure.
 41   *
 42   * @param p krb5_data to reset.
 43   *
 44   * @ingroup krb5
 45   */
 46  
 47  KRB5_LIB_FUNCTION void KRB5_LIB_CALL
 48  krb5_data_zero(krb5_data *p)
 49  {
 50      p->length = 0;
 51      p->data   = NULL;
 52  }
 53  
 54  /**
 55   * Free the content of krb5_data structure, its ok to free a zeroed
 56   * structure (with memset() or krb5_data_zero()). When done, the
 57   * structure will be zeroed. The same function is called
 58   * krb5_free_data_contents() in MIT Kerberos.
 59   *
 60   * @param p krb5_data to free.
 61   *
 62   * @ingroup krb5
 63   */
 64  
 65  KRB5_LIB_FUNCTION void KRB5_LIB_CALL
 66  krb5_data_free(krb5_data *p)
 67  {
 68      if(p->data != NULL)
 69  	free(p->data);
 70      krb5_data_zero(p);
 71  }
 72  
 73  /**
 74   * Free krb5_data (and its content).
 75   *
 76   * @param context Kerberos 5 context.
 77   * @param p krb5_data to free.
 78   *
 79   * @ingroup krb5
 80   */
 81  
 82  KRB5_LIB_FUNCTION void KRB5_LIB_CALL
 83  krb5_free_data(krb5_context context,
 84  	       krb5_data *p)
 85  {
 86      krb5_data_free(p);
 87      free(p);
 88  }
 89  
 90  /**
 91   * Allocate data of and krb5_data.
 92   *
 93   * @param p krb5_data to allocate.
 94   * @param len size to allocate.
 95   *
 96   * @return Returns 0 to indicate success. Otherwise an kerberos et
 97   * error code is returned.
 98   *
 99   * @ingroup krb5
100   */
101  
102  KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
103  krb5_data_alloc(krb5_data *p, size_t len)
104  {
105      p->data = calloc(1, len);
106      if(len && p->data == NULL)
107  	return ENOMEM;
108      p->length = len;
109      return 0;
110  }
111  
112  /**
113   * Grow (or shrink) the content of krb5_data to a new size.
114   *
115   * @param p krb5_data to free.
116   * @param len new size.
117   *
118   * @return Returns 0 to indicate success. Otherwise an kerberos et
119   * error code is returned.
120   *
121   * @ingroup krb5
122   */
123  
124  KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
125  krb5_data_realloc(krb5_data *p, size_t len)
126  {
127      void *tmp;
128      tmp = realloc(p->data, len);
129      if(len && !tmp)
130  	return ENOMEM;
131      p->data = tmp;
132      p->length = len;
133      return 0;
134  }
135  
136  /**
137   * Copy the data of len into the krb5_data.
138   *
139   * @param p krb5_data to copy into.
140   * @param data data to copy..
141   * @param len new size.
142   *
143   * @return Returns 0 to indicate success. Otherwise an kerberos et
144   * error code is returned.
145   *
146   * @ingroup krb5
147   */
148  
149  KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
150  krb5_data_copy(krb5_data *p, const void *data, size_t len)
151  {
152      if (len) {
153  	if(krb5_data_alloc(p, len))
154  	    return ENOMEM;
155  	memmove(p->data, data, len);
156      } else
157  	p->data = NULL;
158      p->length = len;
159      return 0;
160  }
161  
162  /**
163   * Copy the data into a newly allocated krb5_data.
164   *
165   * @param context Kerberos 5 context.
166   * @param indata the krb5_data data to copy
167   * @param outdata new krb5_date to copy too. Free with krb5_free_data().
168   *
169   * @return Returns 0 to indicate success. Otherwise an kerberos et
170   * error code is returned.
171   *
172   * @ingroup krb5
173   */
174  
175  KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
176  krb5_copy_data(krb5_context context,
177  	       const krb5_data *indata,
178  	       krb5_data **outdata)
179  {
180      krb5_error_code ret;
181      ALLOC(*outdata, 1);
182      if(*outdata == NULL) {
183  	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
184  	return ENOMEM;
185      }
186      ret = der_copy_octet_string(indata, *outdata);
187      if(ret) {
188  	krb5_clear_error_message (context);
189  	free(*outdata);
190  	*outdata = NULL;
191      }
192      return ret;
193  }
194  
195  /**
196   * Compare to data.
197   *
198   * @param data1 krb5_data to compare
199   * @param data2 krb5_data to compare
200   *
201   * @return return the same way as memcmp(), useful when sorting.
202   *
203   * @ingroup krb5
204   */
205  
206  KRB5_LIB_FUNCTION int KRB5_LIB_CALL
207  krb5_data_cmp(const krb5_data *data1, const krb5_data *data2)
208  {
209      if (data1->length != data2->length)
210  	return (int)(data1->length - data2->length);
211      return memcmp(data1->data, data2->data, data1->length);
212  }
213  
214  /**
215   * Print using a printf formater into a krb5_data.
216   * 
217   * NUL is not included in the length, but the string is allocated with
218   * one so its safe to print the string using "%s" if there is no
219   * embedded NULs.
220   *
221   */
222  
223  KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
224  krb5_data_format(krb5_data *data, const char *fmt, ...)
225      HEIMDAL_PRINTF_ATTRIBUTE((printf, 2, 3))
226  {
227      va_list args;
228      char *str = NULL;
229      int res;
230  
231      va_start(args, fmt);
232      res = vasprintf (&str, fmt, args);
233      va_end(args);
234      if (str == NULL || res < 0)
235  	return ENOMEM;
236  
237      data->length = res;
238      data->data = str;
239  
240      return 0;
241  }
242  
243  /**
244   * Compare to data not exposing timing information from the checksum data
245   *
246   * @param data1 krb5_data to compare
247   * @param data2 krb5_data to compare
248   *
249   * @return returns zero for same data, otherwise non zero.
250   *
251   * @ingroup krb5
252   */
253  
254  KRB5_LIB_FUNCTION int KRB5_LIB_CALL
255  krb5_data_ct_cmp(const krb5_data *data1, const krb5_data *data2)
256  {
257      if (data1->length != data2->length)
258  	return (int)(data1->length - data2->length);
259      return ct_memcmp(data1->data, data2->data, data1->length);
260  }