diff --git a/lib/krb5/build_auth.c b/lib/krb5/build_auth.c index 9812b34e4..d7940ef7c 100644 --- a/lib/krb5/build_auth.c +++ b/lib/krb5/build_auth.c @@ -50,7 +50,8 @@ krb5_build_authenticator (krb5_context context, krb5_data *result) { Authenticator *auth; - unsigned char buf[1024]; + u_char *buf = NULL; + size_t buf_size; size_t len; krb5_error_code ret; @@ -58,6 +59,7 @@ krb5_build_authenticator (krb5_context context, if (auth == NULL) return ENOMEM; + memset (auth, 0, sizeof(*auth)); auth->authenticator_vno = 5; copy_Realm(&cred->client->realm, &auth->crealm); copy_PrincipalName(&cred->client->name, &auth->cname); @@ -70,13 +72,14 @@ krb5_build_authenticator (krb5_context context, auth->cusec = usec; } ret = krb5_auth_con_getlocalsubkey(context, auth_context, &auth->subkey); - if(ret == ENOMEM) - /* XXX */; + if(ret) + goto fail; + if(auth->subkey == NULL) { krb5_generate_subkey (context, &cred->session, &auth->subkey); ret = krb5_auth_con_setlocalsubkey(context, auth_context, auth->subkey); - if(ret == ENOMEM) - /* XXX */; + if(ret) + goto fail; } if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { @@ -97,15 +100,45 @@ krb5_build_authenticator (krb5_context context, auth_context->authenticator->cusec = auth->cusec; } - memset (buf, 0, sizeof(buf)); - ret = krb5_encode_Authenticator (context, buf + sizeof(buf) - 1, sizeof(buf), - auth, &len); + buf_size = 1024; + buf = malloc (buf_size); + if (buf == NULL) { + ret = ENOMEM; + goto fail; + } - ret = krb5_encrypt (context, buf + sizeof(buf) - len, len, + do { + ret = krb5_encode_Authenticator (context, + buf + buf_size - 1, + buf_size, + auth, &len); + if (ret) { + if (ret == ASN1_OVERFLOW) { + u_char *tmp; + + buf_size *= 2; + tmp = realloc (tmp, buf_size); + if (tmp == NULL) { + ret = ENOMEM; + goto fail; + } + buf = tmp; + } else { + goto fail; + } + } + } while(ret == ASN1_OVERFLOW); + + ret = krb5_encrypt (context, buf + buf_size - len, len, enctype, &cred->session, result); + if (ret) + goto fail; + + free (buf); + if (auth_result) *auth_result = auth; else { @@ -115,4 +148,9 @@ krb5_build_authenticator (krb5_context context, free (auth); } return ret; +fail: + free_Authenticator (auth); + free (auth); + free (buf); + return ret; } diff --git a/lib/krb5/mk_priv.c b/lib/krb5/mk_priv.c index 9a170f930..54dde673e 100644 --- a/lib/krb5/mk_priv.c +++ b/lib/krb5/mk_priv.c @@ -47,10 +47,11 @@ krb5_mk_priv(krb5_context context, krb5_data *outbuf, /*krb5_replay_data*/ void *outdata) { - krb5_error_code r; + krb5_error_code ret; KRB_PRIV s; EncKrbPrivPart part; - u_char buf[10240]; + u_char *buf; + size_t buf_size; size_t len; unsigned tmp_seq; krb5_keyblock *key; @@ -71,9 +72,9 @@ krb5_mk_priv(krb5_context context, if (auth_context->enctype) enctype = auth_context->enctype; else { - r = krb5_keytype_to_etype (context, key->keytype, &enctype); - if (r) - return r; + ret = krb5_keytype_to_etype (context, key->keytype, &enctype); + if (ret) + return ret; } krb5_us_timeofday (context, &sec, &usec); @@ -93,28 +94,78 @@ krb5_mk_priv(krb5_context context, part.s_address = auth_context->local_address; part.r_address = auth_context->remote_address; - r = encode_EncKrbPrivPart (buf + sizeof(buf) - 1, sizeof(buf), &part, &len); - if (r) - return r; + buf_size = 1024; + buf = malloc (buf_size); + if (buf == NULL) + return ENOMEM; + + krb5_data_zero (&s.enc_part.cipher); + + do { + ret = encode_EncKrbPrivPart (buf + buf_size - 1, buf_size, + &part, &len); + if (ret) { + if (ret == ASN1_OVERFLOW) { + u_char *tmp; + + buf_size *= 2; + tmp = realloc (buf, buf_size); + if (tmp == NULL) { + ret = ENOMEM; + goto fail; + } + buf = tmp; + } else { + goto fail; + } + } + } while(ret == ASN1_OVERFLOW); s.pvno = 5; s.msg_type = krb_priv; s.enc_part.etype = enctype; s.enc_part.kvno = NULL; - r = krb5_encrypt (context, buf + sizeof(buf) - len, len, + ret = krb5_encrypt (context, buf + buf_size - len, len, enctype, key, &s.enc_part.cipher); - if (r) - return r; + if (ret) { + free(buf); + return ret; + } - r = encode_KRB_PRIV (buf + sizeof(buf) - 1, sizeof(buf), &s, &len); + do { + ret = encode_KRB_PRIV (buf + buf_size - 1, buf_size, &s, &len); + + if (ret){ + if (ret == ASN1_OVERFLOW) { + u_char *tmp; + + buf_size *= 2; + tmp = realloc (tmp, buf_size); + if (tmp == NULL) { + ret = ENOMEM; + goto fail; + } + buf = tmp; + } else { + goto fail; + } + } + } while(ret == ASN1_OVERFLOW); krb5_data_free (&s.enc_part.cipher); - if (r) - return r; + outbuf->length = len; outbuf->data = malloc (len); - if (outbuf->data == NULL) - return ENOMEM; - memcpy (outbuf->data, buf + sizeof(buf) - len, len); + if (outbuf->data == NULL) { + free(buf); + return ENOMEM; + } + memcpy (outbuf->data, buf + buf_size - len, len); + free (buf); return 0; + +fail: + free (buf); + krb5_data_free (&s.enc_part.cipher); + return ret; } diff --git a/lib/krb5/mk_rep.c b/lib/krb5/mk_rep.c index 4f28e4900..dd0cac1a9 100644 --- a/lib/krb5/mk_rep.c +++ b/lib/krb5/mk_rep.c @@ -49,12 +49,15 @@ krb5_mk_rep(krb5_context context, AP_REP ap; EncAPRepPart body; krb5_enctype etype; - u_char buf[1024]; + u_char *buf = NULL; + size_t buf_size; size_t len; ap.pvno = 5; ap.msg_type = krb_ap_rep; + memset (&body, 0, sizeof(body)); + body.ctime = (*auth_context)->authenticator->ctime; body.cusec = (*auth_context)->authenticator->cusec; body.subkey = NULL; @@ -63,6 +66,8 @@ krb5_mk_rep(krb5_context context, (*auth_context)->keyblock, &(*auth_context)->local_seqnumber); body.seq_number = malloc (sizeof(*body.seq_number)); + if (body.seq_number == NULL) + return ENOMEM; *(body.seq_number) = (*auth_context)->local_seqnumber; } else body.seq_number = NULL; @@ -70,20 +75,83 @@ krb5_mk_rep(krb5_context context, krb5_keytype_to_etype(context, (*auth_context)->keyblock->keytype, &etype); ap.enc_part.etype = etype; ap.enc_part.kvno = NULL; - krb5_encode_EncAPRepPart (context, buf + sizeof(buf) - 1, sizeof(buf), - &body, &len); - ret = krb5_encrypt (context, buf + sizeof(buf) - len, len, - ap.enc_part.etype, - (*auth_context)->keyblock, &ap.enc_part.cipher); - if (ret) - return ret; - encode_AP_REP (buf + sizeof(buf) - 1, sizeof(buf), &ap, &len); - free (ap.enc_part.cipher.data); + buf_size = 1024; + buf = malloc (buf_size); + if (buf == NULL) { + free_EncAPRepPart (&body); + return ENOMEM; + } + + do { + ret = krb5_encode_EncAPRepPart (context, buf + buf_size - 1, + buf_size, + &body, &len); + if (ret) { + if (ret == ASN1_OVERFLOW) { + u_char *tmp; + + buf_size *= 2; + tmp = realloc (buf, buf_size); + if (tmp == NULL) { + free(buf); + free_EncAPRepPart (&body); + return ENOMEM; + } + buf = tmp; + } else { + free_EncAPRepPart (&body); + free(buf); + return ret; + } + } + } while(ret == ASN1_OVERFLOW); + + ret = krb5_encrypt (context, + buf + buf_size - len, len, + ap.enc_part.etype, + (*auth_context)->keyblock, + &ap.enc_part.cipher); + if (ret) { + free(buf); + free_EncAPRepPart (&body); + return ret; + } + + do { + ret = encode_AP_REP (buf + buf_size - 1, buf_size, &ap, &len); + if (ret) { + if (ret == ASN1_OVERFLOW) { + u_char *tmp; + + buf_size *= 2; + tmp = realloc (buf, buf_size); + if (tmp == NULL) { + free_AP_REP (&ap); + free_EncAPRepPart (&body); + free (buf); + return ENOMEM; + } + buf = tmp; + } else { + free_AP_REP (&ap); + free_EncAPRepPart (&body); + free(buf); + return ret; + } + } + } while (ret == ASN1_OVERFLOW); + + free_AP_REP (&ap); + free_EncAPRepPart (&body); + outbuf->length = len; outbuf->data = malloc(len); - if (outbuf->data == NULL) + if (outbuf->data == NULL) { + free (buf); return ENOMEM; - memcpy(outbuf->data, buf + sizeof(buf) - len, len); + } + memcpy(outbuf->data, buf + buf_size - len, len); + free (buf); return 0; } diff --git a/lib/krb5/mk_safe.c b/lib/krb5/mk_safe.c index 45a186056..ca87c80e4 100644 --- a/lib/krb5/mk_safe.c +++ b/lib/krb5/mk_safe.c @@ -47,12 +47,13 @@ krb5_mk_safe(krb5_context context, krb5_data *outbuf, /*krb5_replay_data*/ void *outdata) { - krb5_error_code r; + krb5_error_code ret; KRB_SAFE s; int32_t sec, usec; KerberosTime sec2; unsigned usec2; - u_char buf[1024]; + u_char *buf = NULL; + size_t buf_size; size_t len; unsigned tmp_seq; krb5_cksumtype cksumtype; @@ -60,11 +61,11 @@ krb5_mk_safe(krb5_context context, if (auth_context->cksumtype) cksumtype = auth_context->cksumtype; else { - r = krb5_keytype_to_cksumtype (context, - auth_context->keyblock->keytype, - &cksumtype); - if (r) - return r; + ret = krb5_keytype_to_cksumtype (context, + auth_context->keyblock->keytype, + &cksumtype); + if (ret) + return ret; } s.pvno = 5; @@ -90,31 +91,78 @@ krb5_mk_safe(krb5_context context, s.cksum.checksum.data = NULL; s.cksum.checksum.length = 0; - r = encode_KRB_SAFE (buf + sizeof(buf) - 1, - sizeof(buf), - &s, - &len); - if (r) - return r; + buf_size = 1024; + buf = malloc (buf_size); + if (buf == NULL) { + return ENOMEM; + } - r = krb5_create_checksum (context, - cksumtype, - buf + sizeof(buf) - len, - len, - auth_context->keyblock, - &s.cksum); - if (r) - return r; + do { + ret = encode_KRB_SAFE (buf + buf_size - 1, + buf_size, + &s, + &len); + if (ret) { + if (ret == ASN1_OVERFLOW) { + u_char *tmp; - r = encode_KRB_SAFE (buf + sizeof(buf) - 1, sizeof(buf), &s, &len); - if (r) - return r; + buf_size *= 2; + tmp = realloc (buf, buf_size); + if (tmp == NULL) { + free (buf); + return ENOMEM; + } + buf = tmp; + } else { + free (buf); + return ENOMEM; + } + } + } while (ret == ASN1_OVERFLOW); + + ret = krb5_create_checksum (context, + cksumtype, + buf + buf_size - len, + len, + auth_context->keyblock, + &s.cksum); + if (ret) { + free (buf); + return ret; + } + + do { + ret = encode_KRB_SAFE (buf + buf_size - 1, buf_size, &s, &len); + if (ret) { + if (ret == ASN1_OVERFLOW) { + u_char *tmp; + + buf_size *= 2; + tmp = realloc (buf, buf_size); + if (tmp == NULL) { + free (buf); + free_Checksum (&s.cksum); + return ENOMEM; + } + buf = tmp; + } else { + free (buf); + free_Checksum (&s.cksum); + return ret; + } + } + } while (ret == ASN1_OVERFLOW); + + free_Checksum (&s.cksum); outbuf->length = len; outbuf->data = malloc (len); - if (outbuf->data == NULL) - return ENOMEM; + if (outbuf->data == NULL) { + free (buf); + return ENOMEM; + } memcpy (outbuf->data, buf + sizeof(buf) - len, len); + free (buf); return 0; } diff --git a/lib/krb5/rd_safe.c b/lib/krb5/rd_safe.c index a12542d84..a35156d26 100644 --- a/lib/krb5/rd_safe.c +++ b/lib/krb5/rd_safe.c @@ -40,6 +40,62 @@ RCSID("$Id$"); +static krb5_error_code +verify_checksum(krb5_context context, + krb5_auth_context auth_context, + KRB_SAFE *safe) +{ + krb5_error_code ret; + u_char *buf; + size_t buf_size; + size_t len; + Checksum c; + + c = safe->cksum; + safe->cksum.cksumtype = 0; + safe->cksum.checksum.data = NULL; + safe->cksum.checksum.length = 0; + + buf_size = 1024; + buf = malloc (buf_size); + if (buf == NULL) { + free_Checksum(&c); + return ENOMEM; + } + + do { + ret = encode_KRB_SAFE (buf + buf_size - 1, + buf_size, + safe, + &len); + if (ret) { + if (ret == ASN1_OVERFLOW) { + u_char *tmp; + + buf_size *= 2; + tmp = realloc (buf, buf_size); + if (tmp == NULL) { + ret = ENOMEM; + goto out; + } + buf = tmp; + } else { + goto out; + } + } + } while(ret == ASN1_OVERFLOW); + + ret = krb5_verify_checksum (context, + buf + buf_size - len, + len, + auth_context->keyblock, + &c); +out: + free_Checksum (&c); + free (buf); + return ret; +} + krb5_error_code krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, @@ -53,7 +109,7 @@ krb5_rd_safe(krb5_context context, ret = decode_KRB_SAFE (inbuf->data, inbuf->length, &safe, &len); if (ret) - goto failure; + return ret; if (safe.pvno != 5) { ret = KRB5KRB_AP_ERR_BADVERSION; goto failure; @@ -114,31 +170,10 @@ krb5_rd_safe(krb5_context context, } } - { - u_char buf[1024]; - size_t len; - Checksum c; - - copy_Checksum (&safe.cksum, &c); - - safe.cksum.cksumtype = 0; - safe.cksum.checksum.data = NULL; - safe.cksum.checksum.length = 0; - - encode_KRB_SAFE (buf + sizeof(buf) - 1, - sizeof(buf), - &safe, - &len); - - ret = krb5_verify_checksum (context, - buf + sizeof(buf) - len, - len, - auth_context->keyblock, - &c); - free_Checksum (&c); - if (ret) - goto failure; - } + ret = verify_checksum (context, auth_context, &safe); + if (ret) + goto failure; + outbuf->length = safe.safe_body.user_data.length; outbuf->data = malloc(outbuf->length); if (outbuf->data == NULL) {