1 #pragma ident "%Z%%M% %I% %E% SMI" 2 /* 3 * lib/krb5/krb/ser_auth.c 4 * 5 * Copyright 1995 by the Massachusetts Institute of Technology. 6 * All Rights Reserved. 7 * 8 * Export of this software from the United States of America may 9 * require a specific license from the United States Government. 10 * It is the responsibility of any person or organization contemplating 11 * export to obtain such a license before exporting. 12 * 13 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 14 * distribute this software and its documentation for any purpose and 15 * without fee is hereby granted, provided that the above copyright 16 * notice appear in all copies and that both that copyright notice and 17 * this permission notice appear in supporting documentation, and that 18 * the name of M.I.T. not be used in advertising or publicity pertaining 19 * to distribution of the software without specific, written prior 20 * permission. M.I.T. makes no representations about the suitability of 21 * this software for any purpose. It is provided "as is" without express 22 * or implied warranty. 23 * 24 */ 25 26 /* 27 * ser_auth.c - Serialize krb5_authenticator structure. 28 */ 29 #include <k5-int.h> 30 #include <int-proto.h> 31 32 /* 33 * Routines to deal with externalizing the krb5_authenticator: 34 * krb5_authenticator_size(); 35 * krb5_authenticator_externalize(); 36 * krb5_authenticator_internalize(); 37 */ 38 static krb5_error_code krb5_authenticator_size 39 (krb5_context, krb5_pointer, size_t *); 40 static krb5_error_code krb5_authenticator_externalize 41 (krb5_context, krb5_pointer, krb5_octet **, size_t *); 42 static krb5_error_code krb5_authenticator_internalize 43 (krb5_context,krb5_pointer *, krb5_octet **, size_t *); 44 45 /* Local data */ 46 static const krb5_ser_entry krb5_authenticator_ser_entry = { 47 KV5M_AUTHENTICATOR, /* Type */ 48 krb5_authenticator_size, /* Sizer routine */ 49 krb5_authenticator_externalize, /* Externalize routine */ 50 krb5_authenticator_internalize /* Internalize routine */ 51 }; 52 53 /* 54 * krb5_authenticator_size() - Determine the size required to externalize 55 * the krb5_authenticator. 56 */ 57 static krb5_error_code 58 krb5_authenticator_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep) 59 { 60 krb5_error_code kret; 61 krb5_authenticator *authenticator; 62 size_t required; 63 64 /* 65 * krb5_authenticator requires at minimum: 66 * krb5_int32 for KV5M_AUTHENTICATOR 67 * krb5_int32 for seconds 68 * krb5_int32 for cusec 69 * krb5_int32 for seq_number 70 * krb5_int32 for number in authorization_data array. 71 * krb5_int32 for KV5M_AUTHENTICATOR 72 */ 73 kret = EINVAL; 74 authenticator = (krb5_authenticator *) arg; 75 if (authenticator) { 76 required = sizeof(krb5_int32)*6; 77 78 /* Calculate size required by client, if appropriate */ 79 if (authenticator->client) 80 kret = krb5_size_opaque(kcontext, 81 KV5M_PRINCIPAL, 82 (krb5_pointer) authenticator->client, 83 &required); 84 else 85 kret = 0; 86 87 /* Calculate size required by checksum, if appropriate */ 88 if (!kret && authenticator->checksum) 89 kret = krb5_size_opaque(kcontext, 90 KV5M_CHECKSUM, 91 (krb5_pointer) authenticator->checksum, 92 &required); 93 94 /* Calculate size required by subkey, if appropriate */ 95 if (!kret && authenticator->subkey) 96 kret = krb5_size_opaque(kcontext, 97 KV5M_KEYBLOCK, 98 (krb5_pointer) authenticator->subkey, 99 &required); 100 101 /* Calculate size required by authorization_data, if appropriate */ 102 if (!kret && authenticator->authorization_data) { 103 int i; 104 105 for (i=0; !kret && authenticator->authorization_data[i]; i++) { 106 kret = krb5_size_opaque(kcontext, 107 KV5M_AUTHDATA, 108 (krb5_pointer) authenticator-> 109 authorization_data[i], 110 &required); 111 } 112 } 113 } 114 if (!kret) 115 *sizep += required; 116 return(kret); 117 } 118 119 /* 120 * krb5_authenticator_externalize() - Externalize the krb5_authenticator. 121 */ 122 static krb5_error_code 123 krb5_authenticator_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain) 124 { 125 krb5_error_code kret; 126 krb5_authenticator *authenticator; 127 size_t required; 128 krb5_octet *bp; 129 size_t remain; 130 int i; 131 132 required = 0; 133 bp = *buffer; 134 remain = *lenremain; 135 kret = EINVAL; 136 authenticator = (krb5_authenticator *) arg; 137 if (authenticator) { 138 kret = ENOMEM; 139 if (!krb5_authenticator_size(kcontext, arg, &required) && 140 (required <= remain)) { 141 /* First write our magic number */ 142 (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain); 143 144 /* Now ctime */ 145 (void) krb5_ser_pack_int32((krb5_int32) authenticator->ctime, 146 &bp, &remain); 147 148 /* Now cusec */ 149 (void) krb5_ser_pack_int32((krb5_int32) authenticator->cusec, 150 &bp, &remain); 151 152 /* Now seq_number */ 153 (void) krb5_ser_pack_int32(authenticator->seq_number, 154 &bp, &remain); 155 156 /* Now handle client, if appropriate */ 157 if (authenticator->client) 158 kret = krb5_externalize_opaque(kcontext, 159 KV5M_PRINCIPAL, 160 (krb5_pointer) 161 authenticator->client, 162 &bp, 163 &remain); 164 else 165 kret = 0; 166 167 /* Now handle checksum, if appropriate */ 168 if (!kret && authenticator->checksum) 169 kret = krb5_externalize_opaque(kcontext, 170 KV5M_CHECKSUM, 171 (krb5_pointer) 172 authenticator->checksum, 173 &bp, 174 &remain); 175 176 /* Now handle subkey, if appropriate */ 177 if (!kret && authenticator->subkey) 178 kret = krb5_externalize_opaque(kcontext, 179 KV5M_KEYBLOCK, 180 (krb5_pointer) 181 authenticator->subkey, 182 &bp, 183 &remain); 184 185 /* Now handle authorization_data, if appropriate */ 186 if (!kret) { 187 if (authenticator->authorization_data) 188 for (i=0; authenticator->authorization_data[i]; i++); 189 else 190 i = 0; 191 (void) krb5_ser_pack_int32((krb5_int32) i, &bp, &remain); 192 193 /* Now pound out the authorization_data */ 194 if (authenticator->authorization_data) { 195 for (i=0; !kret && authenticator->authorization_data[i]; 196 i++) 197 kret = krb5_externalize_opaque(kcontext, 198 KV5M_AUTHDATA, 199 (krb5_pointer) 200 authenticator-> 201 authorization_data[i], 202 &bp, 203 &remain); 204 } 205 } 206 207 /* 208 * If we were successful, write trailer then update the pointer and 209 * remaining length; 210 */ 211 if (!kret) { 212 /* Write our trailer */ 213 (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain); 214 *buffer = bp; 215 *lenremain = remain; 216 } 217 } 218 } 219 return(kret); 220 } 221 222 /* 223 * krb5_authenticator_internalize() - Internalize the krb5_authenticator. 224 */ 225 static krb5_error_code 226 krb5_authenticator_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **buffer, size_t *lenremain) 227 { 228 krb5_error_code kret; 229 krb5_authenticator *authenticator; 230 krb5_int32 ibuf; 231 krb5_octet *bp; 232 size_t remain; 233 int i; 234 krb5_int32 nadata; 235 size_t len; 236 237 bp = *buffer; 238 remain = *lenremain; 239 kret = EINVAL; 240 /* Read our magic number */ 241 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) 242 ibuf = 0; 243 if (ibuf == KV5M_AUTHENTICATOR) { 244 kret = ENOMEM; 245 246 /* Get memory for the authenticator */ 247 if ((remain >= (3*sizeof(krb5_int32))) && 248 (authenticator = (krb5_authenticator *) 249 MALLOC(sizeof(krb5_authenticator)))) { 250 (void) memset(authenticator, 0, sizeof(krb5_authenticator)); 251 252 /* Get ctime */ 253 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 254 authenticator->ctime = (krb5_timestamp) ibuf; 255 256 /* Get cusec */ 257 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 258 authenticator->cusec = ibuf; 259 260 /* Get seq_number */ 261 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 262 authenticator->seq_number = ibuf; 263 264 kret = 0; 265 266 /* Attempt to read in the client */ 267 kret = krb5_internalize_opaque(kcontext, 268 KV5M_PRINCIPAL, 269 (krb5_pointer *) 270 &authenticator->client, 271 &bp, 272 &remain); 273 if (kret == EINVAL) 274 kret = 0; 275 276 /* Attempt to read in the checksum */ 277 if (!kret) { 278 kret = krb5_internalize_opaque(kcontext, 279 KV5M_CHECKSUM, 280 (krb5_pointer *) 281 &authenticator->checksum, 282 &bp, 283 &remain); 284 if (kret == EINVAL) 285 kret = 0; 286 } 287 288 /* Attempt to read in the subkey */ 289 if (!kret) { 290 kret = krb5_internalize_opaque(kcontext, 291 KV5M_KEYBLOCK, 292 (krb5_pointer *) 293 &authenticator->subkey, 294 &bp, 295 &remain); 296 if (kret == EINVAL) 297 kret = 0; 298 } 299 300 /* Attempt to read in the authorization data count */ 301 if (!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) { 302 nadata = ibuf; 303 len = (size_t) (nadata + 1); 304 305 /* Get memory for the authorization data pointers */ 306 if ((authenticator->authorization_data = (krb5_authdata **) 307 MALLOC(sizeof(krb5_authdata *) * len))) { 308 (void) memset(authenticator->authorization_data, 0, 309 sizeof(krb5_authdata *) * len); 310 311 for (i=0; !kret && (i<nadata); i++) { 312 kret = krb5_internalize_opaque(kcontext, 313 KV5M_AUTHDATA, 314 (krb5_pointer *) 315 &authenticator-> 316 authorization_data[i], 317 &bp, 318 &remain); 319 } 320 321 /* Finally, find the trailer */ 322 if (!kret) { 323 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); 324 if (!kret && (ibuf == KV5M_AUTHENTICATOR)) 325 authenticator->magic = KV5M_AUTHENTICATOR; 326 else 327 kret = EINVAL; 328 } 329 } 330 } 331 if (!kret) { 332 *buffer = bp; 333 *lenremain = remain; 334 *argp = (krb5_pointer) authenticator; 335 } 336 else 337 krb5_free_authenticator(kcontext, authenticator); 338 } 339 } 340 return(kret); 341 } 342 343 /* 344 * Register the authenticator serializer. 345 */ 346 krb5_error_code 347 krb5_ser_authenticator_init(krb5_context kcontext) 348 { 349 return(krb5_register_serializer(kcontext, &krb5_authenticator_ser_entry)); 350 } 351