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