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 31 /* 32 * Routines to deal with externalizing the krb5_authenticator: 33 * krb5_authenticator_size(); 34 * krb5_authenticator_externalize(); 35 * krb5_authenticator_internalize(); 36 */ 37 static krb5_error_code krb5_authenticator_size 38 KRB5_PROTOTYPE((krb5_context, krb5_pointer, size_t *)); 39 static krb5_error_code krb5_authenticator_externalize 40 KRB5_PROTOTYPE((krb5_context, krb5_pointer, krb5_octet **, size_t *)); 41 static krb5_error_code krb5_authenticator_internalize 42 KRB5_PROTOTYPE((krb5_context,krb5_pointer *, krb5_octet **, size_t *)); 43 44 /* Local data */ 45 static const krb5_ser_entry krb5_authenticator_ser_entry = { 46 KV5M_AUTHENTICATOR, /* Type */ 47 krb5_authenticator_size, /* Sizer routine */ 48 krb5_authenticator_externalize, /* Externalize routine */ 49 krb5_authenticator_internalize /* Internalize routine */ 50 }; 51 52 /* 53 * krb5_authenticator_size() - Determine the size required to externalize 54 * the krb5_authenticator. 55 */ 56 static krb5_error_code 57 krb5_authenticator_size(kcontext, arg, sizep) 58 krb5_context kcontext; 59 krb5_pointer arg; 60 size_t *sizep; 61 { 62 krb5_error_code kret; 63 krb5_authenticator *authenticator; 64 size_t required; 65 66 /* 67 * krb5_authenticator requires at minimum: 68 * krb5_int32 for KV5M_AUTHENTICATOR 69 * krb5_int32 for seconds 70 * krb5_int32 for cusec 71 * krb5_int32 for seq_number 72 * krb5_int32 for number in authorization_data array. 73 * krb5_int32 for KV5M_AUTHENTICATOR 74 */ 75 kret = EINVAL; 76 authenticator = (krb5_authenticator *) arg; 77 if (authenticator) { 78 required = sizeof(krb5_int32)*6; 79 80 /* Calculate size required by client, if appropriate */ 81 if (authenticator->client) 82 kret = krb5_size_opaque(kcontext, 83 KV5M_PRINCIPAL, 84 (krb5_pointer) authenticator->client, 85 &required); 86 else 87 kret = 0; 88 89 /* Calculate size required by checksum, if appropriate */ 90 if (!kret && authenticator->checksum) 91 kret = krb5_size_opaque(kcontext, 92 KV5M_CHECKSUM, 93 (krb5_pointer) authenticator->checksum, 94 &required); 95 96 /* Calculate size required by subkey, if appropriate */ 97 if (!kret && authenticator->subkey) 98 kret = krb5_size_opaque(kcontext, 99 KV5M_KEYBLOCK, 100 (krb5_pointer) authenticator->subkey, 101 &required); 102 103 /* Calculate size required by authorization_data, if appropriate */ 104 if (!kret && authenticator->authorization_data) { 105 int i; 106 107 for (i=0; !kret && authenticator->authorization_data[i]; i++) { 108 kret = krb5_size_opaque(kcontext, 109 KV5M_AUTHDATA, 110 (krb5_pointer) authenticator-> 111 authorization_data[i], 112 &required); 113 } 114 } 115 } 116 if (!kret) 117 *sizep += required; 118 return(kret); 119 } 120 121 /* 122 * krb5_authenticator_externalize() - Externalize the krb5_authenticator. 123 */ 124 static krb5_error_code 125 krb5_authenticator_externalize(kcontext, arg, buffer, lenremain) 126 krb5_context kcontext; 127 krb5_pointer arg; 128 krb5_octet **buffer; 129 size_t *lenremain; 130 { 131 krb5_error_code kret; 132 krb5_authenticator *authenticator; 133 size_t required; 134 krb5_octet *bp; 135 size_t remain; 136 int i; 137 138 required = 0; 139 bp = *buffer; 140 remain = *lenremain; 141 kret = EINVAL; 142 authenticator = (krb5_authenticator *) arg; 143 if (authenticator) { 144 kret = ENOMEM; 145 if (!krb5_authenticator_size(kcontext, arg, &required) && 146 (required <= remain)) { 147 /* First write our magic number */ 148 (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain); 149 150 /* Now ctime */ 151 (void) krb5_ser_pack_int32((krb5_int32) authenticator->ctime, 152 &bp, &remain); 153 154 /* Now cusec */ 155 (void) krb5_ser_pack_int32((krb5_int32) authenticator->cusec, 156 &bp, &remain); 157 158 /* Now seq_number */ 159 (void) krb5_ser_pack_int32(authenticator->seq_number, 160 &bp, &remain); 161 162 /* Now handle client, if appropriate */ 163 if (authenticator->client) 164 kret = krb5_externalize_opaque(kcontext, 165 KV5M_PRINCIPAL, 166 (krb5_pointer) 167 authenticator->client, 168 &bp, 169 &remain); 170 else 171 kret = 0; 172 173 /* Now handle checksum, if appropriate */ 174 if (!kret && authenticator->checksum) 175 kret = krb5_externalize_opaque(kcontext, 176 KV5M_CHECKSUM, 177 (krb5_pointer) 178 authenticator->checksum, 179 &bp, 180 &remain); 181 182 /* Now handle subkey, if appropriate */ 183 if (!kret && authenticator->subkey) 184 kret = krb5_externalize_opaque(kcontext, 185 KV5M_KEYBLOCK, 186 (krb5_pointer) 187 authenticator->subkey, 188 &bp, 189 &remain); 190 191 /* Now handle authorization_data, if appropriate */ 192 if (!kret) { 193 if (authenticator->authorization_data) 194 for (i=0; authenticator->authorization_data[i]; i++); 195 else 196 i = 0; 197 (void) krb5_ser_pack_int32((krb5_int32) i, &bp, &remain); 198 199 /* Now pound out the authorization_data */ 200 if (authenticator->authorization_data) { 201 for (i=0; !kret && authenticator->authorization_data[i]; 202 i++) 203 kret = krb5_externalize_opaque(kcontext, 204 KV5M_AUTHDATA, 205 (krb5_pointer) 206 authenticator-> 207 authorization_data[i], 208 &bp, 209 &remain); 210 } 211 } 212 213 /* 214 * If we were successful, write trailer then update the pointer and 215 * remaining length; 216 */ 217 if (!kret) { 218 /* Write our trailer */ 219 (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain); 220 *buffer = bp; 221 *lenremain = remain; 222 } 223 } 224 } 225 return(kret); 226 } 227 228 /* 229 * krb5_authenticator_internalize() - Internalize the krb5_authenticator. 230 */ 231 static krb5_error_code 232 krb5_authenticator_internalize(kcontext, argp, buffer, lenremain) 233 krb5_context kcontext; 234 krb5_pointer *argp; 235 krb5_octet **buffer; 236 size_t *lenremain; 237 { 238 krb5_error_code kret; 239 krb5_authenticator *authenticator; 240 krb5_int32 ibuf; 241 krb5_octet *bp; 242 size_t remain; 243 int i; 244 krb5_int32 nadata; 245 size_t len; 246 247 bp = *buffer; 248 remain = *lenremain; 249 kret = EINVAL; 250 /* Read our magic number */ 251 if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) 252 ibuf = 0; 253 if (ibuf == KV5M_AUTHENTICATOR) { 254 kret = ENOMEM; 255 256 /* Get memory for the authenticator */ 257 if ((remain >= (3*sizeof(krb5_int32))) && 258 (authenticator = (krb5_authenticator *) 259 MALLOC(sizeof(krb5_authenticator)))) { 260 (void) memset(authenticator, 0, sizeof(krb5_authenticator)); 261 262 /* Get ctime */ 263 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 264 authenticator->ctime = (krb5_timestamp) ibuf; 265 266 /* Get cusec */ 267 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 268 authenticator->cusec = ibuf; 269 270 /* Get seq_number */ 271 (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); 272 authenticator->seq_number = ibuf; 273 274 kret = 0; 275 276 /* Attempt to read in the client */ 277 kret = krb5_internalize_opaque(kcontext, 278 KV5M_PRINCIPAL, 279 (krb5_pointer *) 280 &authenticator->client, 281 &bp, 282 &remain); 283 if (kret == EINVAL) 284 kret = 0; 285 286 /* Attempt to read in the checksum */ 287 if (!kret) { 288 kret = krb5_internalize_opaque(kcontext, 289 KV5M_CHECKSUM, 290 (krb5_pointer *) 291 &authenticator->checksum, 292 &bp, 293 &remain); 294 if (kret == EINVAL) 295 kret = 0; 296 } 297 298 /* Attempt to read in the subkey */ 299 if (!kret) { 300 kret = krb5_internalize_opaque(kcontext, 301 KV5M_KEYBLOCK, 302 (krb5_pointer *) 303 &authenticator->subkey, 304 &bp, 305 &remain); 306 if (kret == EINVAL) 307 kret = 0; 308 } 309 310 /* Attempt to read in the authorization data count */ 311 if (!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) { 312 nadata = ibuf; 313 len = (size_t) (nadata + 1); 314 315 /* Get memory for the authorization data pointers */ 316 if ((authenticator->authorization_data = (krb5_authdata **) 317 MALLOC(sizeof(krb5_authdata *) * len))) { 318 (void) memset(authenticator->authorization_data, 0, 319 sizeof(krb5_authdata *) * len); 320 321 for (i=0; !kret && (i<nadata); i++) { 322 kret = krb5_internalize_opaque(kcontext, 323 KV5M_AUTHDATA, 324 (krb5_pointer *) 325 &authenticator-> 326 authorization_data[i], 327 &bp, 328 &remain); 329 } 330 331 /* Finally, find the trailer */ 332 if (!kret) { 333 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); 334 if (!kret && (ibuf == KV5M_AUTHENTICATOR)) 335 authenticator->magic = KV5M_AUTHENTICATOR; 336 else 337 kret = EINVAL; 338 } 339 } 340 } 341 if (!kret) { 342 *buffer = bp; 343 *lenremain = remain; 344 *argp = (krb5_pointer) authenticator; 345 } 346 else 347 krb5_free_authenticator(kcontext, authenticator); 348 } 349 } 350 return(kret); 351 } 352 353 /* 354 * Register the authenticator serializer. 355 */ 356 krb5_error_code 357 krb5_ser_authenticator_init(kcontext) 358 krb5_context kcontext; 359 { 360 return(krb5_register_serializer(kcontext, &krb5_authenticator_ser_entry)); 361 } 362