asn1_error_code asn1_encode_principal_name(asn1buf *buf, const krb5_principal val, unsigned int *retlen) { asn1_setup(); int n; if (val == NULL || val->data == NULL) return ASN1_MISSING_FIELD; for(n = (int) ((val->length)-1); n >= 0; n--){ if (val->data[n].length && val->data[n].data == NULL) return ASN1_MISSING_FIELD; retval = asn1_encode_generalstring(buf, (val->data)[n].length, (val->data)[n].data, &length); if(retval) return retval; sum += length; } asn1_makeseq(); retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,1,sum,&length); if(retval) return retval; sum += length; asn1_addfield(val->type,0,asn1_encode_integer); asn1_makeseq(); asn1_cleanup(); }
krb5_error_code encode_krb5_authenticator(const krb5_authenticator *rep, krb5_data **code) { krb5_setup(); /* authorization-data[8] AuthorizationData OPTIONAL */ if(rep->authorization_data != NULL && rep->authorization_data[0] != NULL){ retval = asn1_encode_authorization_data(buf, (const krb5_authdata **) rep->authorization_data, &length); if(retval){ asn1buf_destroy(&buf); return retval; } sum += length; retval = asn1_make_etag(buf,CONTEXT_SPECIFIC,8,length,&length); if(retval){ asn1buf_destroy(&buf); return retval; } sum += length; } /* seq-number[7] INTEGER OPTIONAL */ if(rep->seq_number != 0) krb5_addfield(rep->seq_number,7,asn1_encode_unsigned_integer); /* subkey[6] EncryptionKey OPTIONAL */ if(rep->subkey != NULL) krb5_addfield(rep->subkey,6,asn1_encode_encryption_key); /* ctime[5] KerberosTime */ krb5_addfield(rep->ctime,5,asn1_encode_kerberos_time); /* cusec[4] INTEGER */ krb5_addfield(rep->cusec,4,asn1_encode_integer); /* cksum[3] Checksum OPTIONAL */ if(rep->checksum != NULL) krb5_addfield(rep->checksum,3,asn1_encode_checksum); /* cname[2] PrincipalName */ krb5_addfield(rep->client,2,asn1_encode_principal_name); /* crealm[1] Realm */ krb5_addfield(rep->client,1,asn1_encode_realm); /* authenticator-vno[0] INTEGER */ krb5_addfield(KVNO,0,asn1_encode_integer); /* Authenticator ::= [APPLICATION 2] SEQUENCE */ krb5_makeseq(); krb5_apptag(2); krb5_cleanup(); }
asn1_error_code krb5int_asn1_encode_a_thing(asn1buf *buf, const void *val, const struct atype_info *a, unsigned int *retlen) { switch (a->type) { case atype_fn: assert(a->enc != NULL); return a->enc(buf, val, retlen); case atype_sequence: assert(a->seq != NULL); return just_encode_sequence(buf, val, a->seq, retlen); case atype_ptr: assert(a->basetype != NULL); return krb5int_asn1_encode_a_thing(buf, LOADPTR(val, a), a->basetype, retlen); case atype_field: assert(a->field != NULL); return encode_a_field(buf, val, a->field, retlen); case atype_nullterm_sequence_of: case atype_nonempty_nullterm_sequence_of: assert(a->basetype != NULL); return encode_nullterm_sequence_of(buf, val, a->basetype, a->type == atype_nullterm_sequence_of, retlen); case atype_tagged_thing: { asn1_error_code retval; unsigned int length, sum = 0; retval = krb5int_asn1_encode_a_thing(buf, val, a->basetype, &length); if (retval) return retval; sum = length; retval = asn1_make_etag(buf, a->tagtype, a->tagval, sum, &length); if (retval) return retval; sum += length; *retlen = sum; return 0; } case atype_int: assert(a->loadint != NULL); return asn1_encode_integer(buf, a->loadint(val), retlen); case atype_uint: assert(a->loaduint != NULL); return asn1_encode_unsigned_integer(buf, a->loaduint(val), retlen); case atype_min: case atype_max: case atype_fn_len: default: assert(a->type > atype_min); assert(a->type < atype_max); assert(a->type != atype_fn_len); abort(); } }
static asn1_error_code encode_a_field(asn1buf *buf, const void *val, const struct field_info *field, unsigned int *retlen) { asn1_error_code retval; unsigned int sum = 0; if (val == NULL) return ASN1_MISSING_FIELD; switch (field->ftype) { case field_immediate: { unsigned int length; retval = asn1_encode_integer(buf, (asn1_intmax) field->dataoff, &length); if (retval) return retval; sum += length; break; } case field_sequenceof_len: { const void *dataptr, *lenptr; int slen; unsigned int length; const struct atype_info *a; /* * The field holds a pointer to the array of objects. So the * address we compute is a pointer-to-pointer, and that's what * field->atype must help us dereference. */ dataptr = (const char *)val + field->dataoff; lenptr = (const char *)val + field->lenoff; assert(field->atype->type == atype_ptr); dataptr = LOADPTR(dataptr, field->atype); a = field->atype->basetype; assert(field->lentype != 0); assert(field->lentype->type == atype_int || field->lentype->type == atype_uint); assert(sizeof(int) <= sizeof(asn1_intmax)); assert(sizeof(unsigned int) <= sizeof(asn1_uintmax)); if (field->lentype->type == atype_int) { asn1_intmax xlen = field->lentype->loadint(lenptr); if (xlen < 0) return EINVAL; if ((unsigned int) xlen != (asn1_uintmax) xlen) return EINVAL; if ((unsigned int) xlen > INT_MAX) return EINVAL; slen = (int) xlen; } else { asn1_uintmax xlen = field->lentype->loaduint(lenptr); if ((unsigned int) xlen != xlen) return EINVAL; if (xlen > INT_MAX) return EINVAL; slen = (int) xlen; } if (slen != 0 && dataptr == NULL) return ASN1_MISSING_FIELD; retval = encode_sequence_of(buf, slen, dataptr, a, &length); if (retval) return retval; sum += length; break; } case field_normal: { const void *dataptr; const struct atype_info *a; unsigned int length; dataptr = (const char *)val + field->dataoff; a = field->atype; assert(a->type != atype_fn_len); retval = krb5int_asn1_encode_a_thing(buf, dataptr, a, &length); if (retval) { return retval; } sum += length; break; } case field_string: { const void *dataptr, *lenptr; const struct atype_info *a; size_t slen; unsigned int length; dataptr = (const char *)val + field->dataoff; lenptr = (const char *)val + field->lenoff; a = field->atype; assert(a->type == atype_fn_len); assert(field->lentype != 0); assert(field->lentype->type == atype_int || field->lentype->type == atype_uint); assert(sizeof(int) <= sizeof(asn1_intmax)); assert(sizeof(unsigned int) <= sizeof(asn1_uintmax)); if (field->lentype->type == atype_int) { asn1_intmax xlen = field->lentype->loadint(lenptr); if (xlen < 0) return EINVAL; if ((size_t) xlen != (asn1_uintmax) xlen) return EINVAL; slen = (size_t) xlen; } else { asn1_uintmax xlen = field->lentype->loaduint(lenptr); if ((size_t) xlen != xlen) return EINVAL; slen = (size_t) xlen; } dataptr = LOADPTR(dataptr, a); if (slen == SIZE_MAX) /* Error - negative or out of size_t range. */ return EINVAL; if (dataptr == NULL && slen != 0) return ASN1_MISSING_FIELD; /* * Currently our string encoders want "unsigned int" for * lengths. */ if (slen != (unsigned int) slen) return EINVAL; assert(a->enclen != NULL); retval = a->enclen(buf, (unsigned int) slen, dataptr, &length); if (retval) { return retval; } sum += length; break; } default: assert(field->ftype > field_min); assert(field->ftype < field_max); assert(__LINE__ == 0); abort(); } if (field->tag >= 0) { unsigned int length; retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, field->tag, sum, &length); if (retval) { return retval; } sum += length; } *retlen = sum; return 0; }