1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * lib/krb5/krb/serialize.c 8 * 9 * Copyright 1995 by the Massachusetts Institute of Technology. 10 * All Rights Reserved. 11 * 12 * Export of this software from the United States of America may 13 * require a specific license from the United States Government. 14 * It is the responsibility of any person or organization contemplating 15 * export to obtain such a license before exporting. 16 * 17 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 18 * distribute this software and its documentation for any purpose and 19 * without fee is hereby granted, provided that the above copyright 20 * notice appear in all copies and that both that copyright notice and 21 * this permission notice appear in supporting documentation, and that 22 * the name of M.I.T. not be used in advertising or publicity pertaining 23 * to distribution of the software without specific, written prior 24 * permission. Furthermore if you modify this software you must label 25 * your software as modified software and not distribute it in such a 26 * fashion that it might be confused with the original M.I.T. software. 27 * M.I.T. makes no representations about the suitability of 28 * this software for any purpose. It is provided "as is" without express 29 * or implied warranty. 30 * 31 */ 32 33 /* 34 * Base routines to deal with serialization of Kerberos metadata. 35 */ 36 #include "k5-int.h" 37 38 /* Solaris Kerberos */ 39 #include <k5-platform.h> 40 #include <k5-platform-store_64.h> 41 #include <k5-platform-load_64.h> 42 43 /* 44 * krb5_find_serializer() - See if a particular type is registered. 45 */ 46 krb5_ser_handle 47 krb5_find_serializer(krb5_context kcontext, krb5_magic odtype) 48 { 49 krb5_ser_handle res; 50 krb5_ser_handle sctx; 51 int i; 52 53 res = (krb5_ser_handle) NULL; 54 sctx = (krb5_ser_handle) kcontext->ser_ctx; 55 for (i=0; i<kcontext->ser_ctx_count; i++) { 56 if (sctx[i].odtype == odtype) { 57 res = &sctx[i]; 58 break; 59 } 60 } 61 return(res); 62 } 63 64 /* 65 * krb5_register_serializer() - Register a particular serializer. 66 */ 67 krb5_error_code 68 krb5_register_serializer(krb5_context kcontext, const krb5_ser_entry *entry) 69 { 70 krb5_error_code kret; 71 krb5_ser_handle stable; 72 73 kret = 0; 74 /* See if it's already there, if so, we're good to go. */ 75 if (!(stable = krb5_find_serializer(kcontext, entry->odtype))) { 76 /* 77 * Can't find our type. Create a new entry. 78 */ 79 if ((stable = (krb5_ser_handle) MALLOC(sizeof(krb5_ser_entry) * 80 (kcontext->ser_ctx_count+1)))) { 81 /* Copy in old table */ 82 if (kcontext->ser_ctx_count) 83 (void) memcpy((void*)stable, kcontext->ser_ctx, 84 sizeof(krb5_ser_entry) * kcontext->ser_ctx_count); 85 /* Copy in new entry */ 86 (void) memcpy((void*)&stable[kcontext->ser_ctx_count], entry, 87 sizeof(krb5_ser_entry)); 88 if (kcontext->ser_ctx) 89 krb5_xfree_wrap(kcontext->ser_ctx, 90 sizeof(krb5_ser_entry) * (kcontext->ser_ctx_count)); 91 kcontext->ser_ctx = (void *) stable; 92 kcontext->ser_ctx_count++; 93 } 94 else 95 kret = ENOMEM; 96 } 97 else 98 (void) memcpy((void*)stable, entry, sizeof(krb5_ser_entry)); 99 return(kret); 100 } 101 102 /* 103 * krb5_size_opaque() - Determine the size necessary to serialize a given 104 * piece of opaque data. 105 */ 106 krb5_error_code KRB5_CALLCONV 107 krb5_size_opaque(krb5_context kcontext, krb5_magic odtype, krb5_pointer arg, size_t *sizep) 108 { 109 krb5_error_code kret; 110 krb5_ser_handle shandle; 111 112 kret = ENOENT; 113 /* See if the type is supported, if so, do it */ 114 if ((shandle = krb5_find_serializer(kcontext, odtype))) 115 kret = (shandle->sizer) ? (*shandle->sizer)(kcontext, arg, sizep) : 0; 116 return(kret); 117 } 118 119 /* 120 * krb5_externalize_opaque() - Externalize a piece of opaque data. 121 */ 122 krb5_error_code KRB5_CALLCONV 123 krb5_externalize_opaque(krb5_context kcontext, krb5_magic odtype, krb5_pointer arg, krb5_octet **bufpp, size_t *sizep) 124 { 125 krb5_error_code kret; 126 krb5_ser_handle shandle; 127 128 kret = ENOENT; 129 /* See if the type is supported, if so, do it */ 130 if ((shandle = krb5_find_serializer(kcontext, odtype))) 131 kret = (shandle->externalizer) ? 132 (*shandle->externalizer)(kcontext, arg, bufpp, sizep) : 0; 133 return(kret); 134 } 135 136 /* 137 * Externalize a piece of arbitrary data. 138 */ 139 krb5_error_code 140 krb5_externalize_data(krb5_context kcontext, krb5_pointer arg, krb5_octet **bufpp, size_t *sizep) 141 { 142 krb5_error_code kret; 143 krb5_magic *mp; 144 krb5_octet *buffer, *bp; 145 size_t bufsize, bsize; 146 147 mp = (krb5_magic *) arg; 148 bufsize = 0; 149 if (!(kret = krb5_size_opaque(kcontext, *mp, arg, &bufsize))) { 150 if ((buffer = (krb5_octet *) MALLOC(bufsize))) { 151 bp = buffer; 152 bsize = bufsize; 153 if (!(kret = krb5_externalize_opaque(kcontext, 154 *mp, 155 arg, 156 &bp, 157 &bsize))) { 158 if (bsize != 0) 159 bufsize -= bsize; 160 *bufpp = buffer; 161 *sizep = bufsize; 162 } 163 } 164 else 165 kret = ENOMEM; 166 } 167 return(kret); 168 } 169 170 /* 171 * krb5_internalize_opaque() - Convert external representation into a data 172 * structure. 173 */ 174 krb5_error_code KRB5_CALLCONV 175 krb5_internalize_opaque(krb5_context kcontext, krb5_magic odtype, krb5_pointer *argp, krb5_octet **bufpp, size_t *sizep) 176 { 177 krb5_error_code kret; 178 krb5_ser_handle shandle; 179 180 kret = ENOENT; 181 /* See if the type is supported, if so, do it */ 182 if ((shandle = krb5_find_serializer(kcontext, odtype))) 183 kret = (shandle->internalizer) ? 184 (*shandle->internalizer)(kcontext, argp, bufpp, sizep) : 0; 185 return(kret); 186 } 187 188 /* 189 * krb5_ser_pack_int32() - Pack a 4-byte integer if space is available. 190 * Update buffer pointer and remaining space. 191 */ 192 krb5_error_code KRB5_CALLCONV 193 krb5_ser_pack_int32(krb5_int32 iarg, krb5_octet **bufp, size_t *remainp) 194 { 195 if (*remainp >= sizeof(krb5_int32)) { 196 (*bufp)[0] = (krb5_octet) ((iarg >> 24) & 0xff); 197 (*bufp)[1] = (krb5_octet) ((iarg >> 16) & 0xff); 198 (*bufp)[2] = (krb5_octet) ((iarg >> 8) & 0xff); 199 (*bufp)[3] = (krb5_octet) (iarg & 0xff); 200 *bufp += sizeof(krb5_int32); 201 *remainp -= sizeof(krb5_int32); 202 return(0); 203 } 204 else 205 return(ENOMEM); 206 } 207 208 /* 209 * krb5_ser_pack_int64() - Pack an 8-byte integer if space is available. 210 * Update buffer pointer and remaining space. 211 */ 212 krb5_error_code KRB5_CALLCONV 213 krb5_ser_pack_int64(krb5_int64 iarg, krb5_octet **bufp, size_t *remainp) 214 { 215 if (*remainp >= sizeof(krb5_int64)) { 216 store_64_be(iarg, (unsigned char *)*bufp); 217 *bufp += sizeof(krb5_int64); 218 *remainp -= sizeof(krb5_int64); 219 return(0); 220 } 221 else 222 return(ENOMEM); 223 } 224 225 /* 226 * krb5_ser_pack_bytes() - Pack a string of bytes. 227 */ 228 krb5_error_code KRB5_CALLCONV 229 krb5_ser_pack_bytes(krb5_octet *ostring, size_t osize, krb5_octet **bufp, size_t *remainp) 230 { 231 if (*remainp >= osize) { 232 (void) memcpy(*bufp, ostring, osize); 233 *bufp += osize; 234 *remainp -= osize; 235 return(0); 236 } 237 else 238 return(ENOMEM); 239 } 240 241 /* 242 * krb5_ser_unpack_int32() - Unpack a 4-byte integer if it's there. 243 */ 244 krb5_error_code KRB5_CALLCONV 245 krb5_ser_unpack_int32(krb5_int32 *intp, krb5_octet **bufp, size_t *remainp) 246 { 247 if (*remainp >= sizeof(krb5_int32)) { 248 *intp = (((krb5_int32) ((unsigned char) (*bufp)[0]) << 24) | 249 ((krb5_int32) ((unsigned char) (*bufp)[1]) << 16) | 250 ((krb5_int32) ((unsigned char) (*bufp)[2]) << 8) | 251 ((krb5_int32) ((unsigned char) (*bufp)[3]))); 252 *bufp += sizeof(krb5_int32); 253 *remainp -= sizeof(krb5_int32); 254 return(0); 255 } 256 else 257 return(ENOMEM); 258 } 259 260 /* 261 * krb5_ser_unpack_int64() - Unpack an 8-byte integer if it's there. 262 */ 263 krb5_error_code KRB5_CALLCONV 264 krb5_ser_unpack_int64(krb5_int64 *intp, krb5_octet **bufp, size_t *remainp) 265 { 266 if (*remainp >= sizeof(krb5_int64)) { 267 *intp = load_64_be((unsigned char *)*bufp); 268 *bufp += sizeof(krb5_int64); 269 *remainp -= sizeof(krb5_int64); 270 return(0); 271 } 272 else 273 return(ENOMEM); 274 } 275 276 /* 277 * krb5_ser_unpack_bytes() - Unpack a byte string if it's there. 278 */ 279 krb5_error_code KRB5_CALLCONV 280 krb5_ser_unpack_bytes(krb5_octet *istring, size_t isize, krb5_octet **bufp, size_t *remainp) 281 { 282 if (*remainp >= isize) { 283 (void) memcpy(istring, *bufp, isize); 284 *bufp += isize; 285 *remainp -= isize; 286 return(0); 287 } 288 else 289 return(ENOMEM); 290 } 291