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