Beispiel #1
0
krb5_error_code
_krb5_pac_sign(krb5_context context,
	       krb5_pac p,
	       time_t authtime,
	       krb5_principal principal,
	       const krb5_keyblock *server_key,
	       const krb5_keyblock *priv_key,
	       krb5_data *data)
{
    krb5_error_code ret;
    krb5_storage *sp = NULL, *spdata = NULL;
    uint32_t end;
    size_t server_size, priv_size;
    uint32_t server_offset = 0, priv_offset = 0;
    uint32_t server_cksumtype = 0, priv_cksumtype = 0;
    int i, num = 0;
    krb5_data logon, d;

    krb5_data_zero(&logon);

    if (p->logon_name == NULL)
	num++;
    if (p->server_checksum == NULL)
	num++;
    if (p->privsvr_checksum == NULL)
	num++;

    if (num) {
	void *ptr;

	ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (p->pac->numbuffers + num - 1)));
	if (ptr == NULL)
	    return krb5_enomem(context);

	p->pac = ptr;

	if (p->logon_name == NULL) {
	    p->logon_name = &p->pac->buffers[p->pac->numbuffers++];
	    memset(p->logon_name, 0, sizeof(*p->logon_name));
	    p->logon_name->type = PAC_LOGON_NAME;
	}
	if (p->server_checksum == NULL) {
	    p->server_checksum = &p->pac->buffers[p->pac->numbuffers++];
	    memset(p->server_checksum, 0, sizeof(*p->server_checksum));
	    p->server_checksum->type = PAC_SERVER_CHECKSUM;
	}
	if (p->privsvr_checksum == NULL) {
	    p->privsvr_checksum = &p->pac->buffers[p->pac->numbuffers++];
	    memset(p->privsvr_checksum, 0, sizeof(*p->privsvr_checksum));
	    p->privsvr_checksum->type = PAC_PRIVSVR_CHECKSUM;
	}
    }

    /* Calculate LOGON NAME */
    ret = build_logon_name(context, authtime, principal, &logon);
    if (ret)
	goto out;

    /* Set lengths for checksum */
    ret = pac_checksum(context, server_key, &server_cksumtype, &server_size);
    if (ret)
	goto out;
    ret = pac_checksum(context, priv_key, &priv_cksumtype, &priv_size);
    if (ret)
	goto out;

    /* Encode PAC */
    sp = krb5_storage_emem();
    if (sp == NULL)
	return krb5_enomem(context);

    krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);

    spdata = krb5_storage_emem();
    if (spdata == NULL) {
	krb5_storage_free(sp);
	return krb5_enomem(context);
    }
    krb5_storage_set_flags(spdata, KRB5_STORAGE_BYTEORDER_LE);

    CHECK(ret, krb5_store_uint32(sp, p->pac->numbuffers), out);
    CHECK(ret, krb5_store_uint32(sp, p->pac->version), out);

    end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers);

    for (i = 0; i < p->pac->numbuffers; i++) {
	uint32_t len;
	size_t sret;
	void *ptr = NULL;

	/* store data */

	if (p->pac->buffers[i].type == PAC_SERVER_CHECKSUM) {
	    len = server_size + 4;
	    server_offset = end + 4;
	    CHECK(ret, krb5_store_uint32(spdata, server_cksumtype), out);
	    CHECK(ret, fill_zeros(context, spdata, server_size), out);
	} else if (p->pac->buffers[i].type == PAC_PRIVSVR_CHECKSUM) {
	    len = priv_size + 4;
	    priv_offset = end + 4;
	    CHECK(ret, krb5_store_uint32(spdata, priv_cksumtype), out);
	    CHECK(ret, fill_zeros(context, spdata, priv_size), out);
	} else if (p->pac->buffers[i].type == PAC_LOGON_NAME) {
	    len = krb5_storage_write(spdata, logon.data, logon.length);
	    if (logon.length != len) {
		ret = EINVAL;
		goto out;
	    }
	} else {
	    len = p->pac->buffers[i].buffersize;
	    ptr = (char *)p->data.data + p->pac->buffers[i].offset_lo;

	    sret = krb5_storage_write(spdata, ptr, len);
	    if (sret != len) {
		ret = krb5_enomem(context);
		goto out;
	    }
	    /* XXX if not aligned, fill_zeros */
	}

	/* write header */
	CHECK(ret, krb5_store_uint32(sp, p->pac->buffers[i].type), out);
	CHECK(ret, krb5_store_uint32(sp, len), out);
	CHECK(ret, krb5_store_uint32(sp, end), out);
	CHECK(ret, krb5_store_uint32(sp, 0), out);

	/* advance data endpointer and align */
	{
	    int32_t e;

	    end += len;
	    e = ((end + PAC_ALIGNMENT - 1) / PAC_ALIGNMENT) * PAC_ALIGNMENT;
	    if (end != e) {
		CHECK(ret, fill_zeros(context, spdata, e - end), out);
	    }
	    end = e;
	}

    }

    /* assert (server_offset != 0 && priv_offset != 0); */

    /* export PAC */
    ret = krb5_storage_to_data(spdata, &d);
    if (ret) {
	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
	goto out;
    }
    ret = krb5_storage_write(sp, d.data, d.length);
    if (ret != d.length) {
	krb5_data_free(&d);
	ret = krb5_enomem(context);
	goto out;
    }
    krb5_data_free(&d);

    ret = krb5_storage_to_data(sp, &d);
    if (ret) {
	ret = krb5_enomem(context);
	goto out;
    }

    /* sign */
    ret = create_checksum(context, server_key, server_cksumtype,
			  d.data, d.length,
			  (char *)d.data + server_offset, server_size);
    if (ret) {
	krb5_data_free(&d);
	goto out;
    }
    ret = create_checksum(context, priv_key, priv_cksumtype,
			  (char *)d.data + server_offset, server_size,
			  (char *)d.data + priv_offset, priv_size);
    if (ret) {
	krb5_data_free(&d);
	goto out;
    }

    /* done */
    *data = d;

    krb5_data_free(&logon);
    krb5_storage_free(sp);
    krb5_storage_free(spdata);

    return 0;
out:
    krb5_data_free(&logon);
    if (sp)
	krb5_storage_free(sp);
    if (spdata)
	krb5_storage_free(spdata);
    return ret;
}
Beispiel #2
0
int et_boot_catalog(struct ISO_data_t ISO_data) {
   struct stat EFI_boot_file_stat;
   void *boot_cat_data = (void *) malloc(BLOCK_SIZE);
   void *boot_cat_start = boot_cat_data;
   void *rr = NULL;
   int rv = 0;
   
   char id_string[24];
   FILE *boot_catalog = NULL;
   uint32_t boot_cat_size = 0;
   uint16_t unused = 0;
   uint16_t checksum = 0x0000;
   uint16_t signature = 0xAA55;
   uint8_t header_id = 0x01;        // Always 0x01
   uint8_t platform_id = 0x00;      // x86
   
   uint16_t load_segment = 0x00;
   uint16_t sector_count = 0x00;
   uint8_t boot_indicator = 0x88;   // Bootable 
   uint8_t media_type = 0x00;       // No emulation
   uint8_t system_type = 0x00;
   
   memset(&EFI_boot_file_stat, 0, sizeof(struct stat));
   memset(id_string, 0, sizeof(id_string));
   memset(boot_cat_start, 0, BLOCK_SIZE);
   
   /* Move to LBA of UEFI boot image */
   (ISO_data.boot_cat_LBA)++;
   
   stat(ISO_data.efi_boot_file_full, &EFI_boot_file_stat);
   sector_count = EFI_boot_file_stat.st_size / 512;
   
   iso9660_cp2heap(&boot_cat_data, &header_id, sizeof(uint8_t), &boot_cat_size);
   iso9660_cp2heap(&boot_cat_data, &platform_id, sizeof(uint8_t), &boot_cat_size);
   iso9660_cp2heap(&boot_cat_data, &unused, sizeof(uint16_t), &boot_cat_size);
   iso9660_cp2heap(&boot_cat_data, &id_string, sizeof(id_string), &boot_cat_size);
   iso9660_cp2heap(&boot_cat_data, &checksum, sizeof(uint16_t), &boot_cat_size);
   iso9660_cp2heap(&boot_cat_data, &signature, sizeof(uint16_t), &boot_cat_size);
   
   /* Calculate checksum of words so far written */
   checksum = create_checksum(boot_cat_start, boot_cat_size);
   rr = boot_cat_data - 4;             // Return back 4 bytes and write checksum
   boot_cat_size -= sizeof(uint16_t);  // This will be counted back in next step
   iso9660_cp2heap(&rr, &checksum, sizeof(uint16_t), &boot_cat_size);
   
   iso9660_cp2heap(&boot_cat_data, &boot_indicator, sizeof(uint8_t), &boot_cat_size);
   iso9660_cp2heap(&boot_cat_data, &media_type, sizeof(uint8_t), &boot_cat_size);
   iso9660_cp2heap(&boot_cat_data, &load_segment, sizeof(uint16_t), &boot_cat_size);
   iso9660_cp2heap(&boot_cat_data, &system_type, sizeof(uint8_t), &boot_cat_size);
   iso9660_cp2heap(&boot_cat_data, &unused, sizeof(uint8_t), &boot_cat_size);
   iso9660_cp2heap(&boot_cat_data, &sector_count, sizeof(uint16_t), &boot_cat_size);               // Size of UEFI boot image (this will overflow because of size)
   iso9660_cp2heap(&boot_cat_data, &ISO_data.boot_cat_LBA, sizeof(uint32_t), &boot_cat_size);      // LBA of UEFI boot image (virtual disk)
   
   boot_catalog = fopen(ISO_data.boot_cat_file, "w");
   if (fwrite(boot_cat_start, 1, BLOCK_SIZE, boot_catalog) != BLOCK_SIZE) {
      perror("Error: et_boot_catalog()");
      rv = E_IO;
   }
   
   fclose(boot_catalog);
   free(boot_cat_start);
   
   return rv;
}