diff options
author | Jeremy Allison <jra@samba.org> | 2018-04-30 15:06:39 -0700 |
---|---|---|
committer | Ralph Boehme <slow@samba.org> | 2018-05-04 22:34:24 +0200 |
commit | 6a42a24b27d8691be894c39df4f9fdb83aefa754 (patch) | |
tree | 8dcd7985e08daa11b645f5e14f8593fa9861c919 /source3/printing | |
parent | 631bca9e92e9aa7380140ff9e603d40fda9e3e66 (diff) | |
download | samba-6a42a24b27d8691be894c39df4f9fdb83aefa754.tar.gz |
s3: printing: Split handling of PE file into separate function.
This is *horrible* old code...
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Diffstat (limited to 'source3/printing')
-rw-r--r-- | source3/printing/nt_printing.c | 347 |
1 files changed, 188 insertions, 159 deletions
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 7a7a78b59e2..55720350dcc 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -342,6 +342,189 @@ static ssize_t vfs_read_data(files_struct *fsp, } /**************************************************************************** + Detect the major and minor version of a PE file. + Returns: + + 1 if file is a PE file and we got version numbers, + 0 if this file is a PE file and we couldn't get the version numbers, + -1 on error. + + NB. buf is passed into and freed inside this function. This is a + bad API design, but fixing this is a task for another day. +****************************************************************************/ + +static int handle_pe_file(files_struct *fsp, + char *fname, + char *buf, + uint32_t *major, + uint32_t *minor) +{ + unsigned int i; + unsigned int num_sections; + unsigned int section_table_bytes; + ssize_t byte_count; + off_t oret; + off_t pos; + int ret = -1; + + /* Just skip over optional header to get to section table */ + pos = SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)- + (NE_HEADER_SIZE-PE_HEADER_SIZE); + + oret = SMB_VFS_LSEEK(fsp, pos, SEEK_CUR); + if (oret == (off_t)-1) { + DBG_NOTICE("File [%s] Windows optional header " + "too short, errno = %d\n", + fname, + errno); + goto out; + } + + /* get the section table */ + num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS); + section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE; + if (section_table_bytes == 0) { + goto out; + } + + SAFE_FREE(buf); + buf = (char *)SMB_MALLOC(section_table_bytes); + if (buf == NULL) { + DBG_ERR("PE file [%s] section table malloc " + "failed bytes = %d\n", + fname, + section_table_bytes); + goto out; + } + + byte_count = vfs_read_data(fsp, buf, section_table_bytes); + if (byte_count < section_table_bytes) { + DBG_NOTICE("PE file [%s] Section header too short, " + "bytes read = %lu\n", + fname, + (unsigned long)byte_count); + goto out; + } + + /* + * Iterate the section table looking for + * the resource section ".rsrc" + */ + for (i = 0; i < num_sections; i++) { + int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE; + + if (strcmp(".rsrc", + &buf[sec_offset+ PE_HEADER_SECT_NAME_OFFSET]) == 0) { + unsigned int section_pos = IVAL(buf, + sec_offset+ + PE_HEADER_SECT_PTR_DATA_OFFSET); + unsigned int section_bytes = IVAL(buf, + sec_offset+ + PE_HEADER_SECT_SIZE_DATA_OFFSET); + + if (section_bytes == 0) { + goto out; + } + + SAFE_FREE(buf); + buf=(char *)SMB_MALLOC(section_bytes); + if (buf == NULL) { + DBG_ERR("PE file [%s] version malloc " + "failed bytes = %d\n", + fname, + section_bytes); + goto out; + } + + /* + * Seek to the start of the .rsrc + * section info + */ + oret = SMB_VFS_LSEEK(fsp, + section_pos, + SEEK_SET); + if (oret == (off_t)-1) { + DBG_NOTICE("PE file [%s] too short for " + "section info, errno = %d\n", + fname, + errno); + goto out; + } + + byte_count = vfs_read_data(fsp, + buf, + section_bytes); + if (byte_count < section_bytes) { + DBG_NOTICE("PE file " + "[%s] .rsrc section too short, " + "bytes read = %lu\n", + fname, + (unsigned long)byte_count); + goto out; + } + + if (section_bytes < VS_VERSION_INFO_UNICODE_SIZE) { + goto out; + } + + for (i=0; + i< section_bytes - VS_VERSION_INFO_UNICODE_SIZE; + i++) { + /* + * Scan for 1st 3 unicoded bytes + * followed by word aligned magic + * value. + */ + int mpos; + bool magic_match = false; + + if (buf[i] == 'V' && + buf[i+1] == '\0' && + buf[i+2] == 'S') { + magic_match = true; + } + + if (magic_match == false) { + continue; + } + + /* Align to next long address */ + mpos = (i + sizeof(VS_SIGNATURE)*2 + + 3) & 0xfffffffc; + + if (IVAL(buf,mpos) == VS_MAGIC_VALUE) { + *major = IVAL(buf, + mpos+ VS_MAJOR_OFFSET); + *minor = IVAL(buf, + mpos+ VS_MINOR_OFFSET); + + DBG_INFO("PE file [%s] Version = " + "%08x:%08x (%d.%d.%d.%d)\n", + fname, + *major, + *minor, + (*major>>16)&0xffff, + *major&0xffff, + (*minor>>16)&0xffff, + *minor&0xffff); + ret = 1; + goto out; + } + } + } + } + + /* Version info not found, fall back to origin date/time */ + DBG_DEBUG("PE file [%s] has no version info\n", fname); + ret = 0; + + out: + + SAFE_FREE(buf); + return ret; +} + +/**************************************************************************** Version information in Microsoft files is held in a VS_VERSION_INFO structure. There are two case to be covered here: PE (Portable Executable) and NE (New Executable) files. Both files support the same INFO structure, but PE files @@ -420,165 +603,11 @@ static int get_file_version(files_struct *fsp, * or an NE (New Executable). */ if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) { - unsigned int num_sections; - unsigned int section_table_bytes; - - /* Just skip over optional header to get to section table */ - pos = SVAL(buf,PE_HEADER_OPTIONAL_HEADER_SIZE)- - (NE_HEADER_SIZE-PE_HEADER_SIZE); - - oret = SMB_VFS_LSEEK(fsp, pos, SEEK_CUR); - if (oret == (off_t)-1) { - DBG_NOTICE("File [%s] Windows optional header " - "too short, errno = %d\n", - fname, - errno); - goto error_exit; - } - - /* get the section table */ - num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS); - section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE; - if (section_table_bytes == 0) { - goto error_exit; - } - - SAFE_FREE(buf); - buf = (char *)SMB_MALLOC(section_table_bytes); - if (buf == NULL) { - DBG_ERR("PE file [%s] section table malloc " - "failed bytes = %d\n", - fname, - section_table_bytes); - goto error_exit; - } - - byte_count = vfs_read_data(fsp, buf, section_table_bytes); - if (byte_count < section_table_bytes) { - DBG_NOTICE("PE file [%s] " - "Section header too short, bytes read = %lu\n", - fname, - (unsigned long)byte_count); - goto error_exit; - } - - /* - * Iterate the section table looking for - * the resource section ".rsrc" - */ - for (i = 0; i < num_sections; i++) { - int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE; - - if (strcmp(".rsrc", - &buf[sec_offset+ - PE_HEADER_SECT_NAME_OFFSET]) - == 0) { - unsigned int section_pos = - IVAL(buf, - sec_offset+ - PE_HEADER_SECT_PTR_DATA_OFFSET); - unsigned int section_bytes = - IVAL(buf, - sec_offset+ - PE_HEADER_SECT_SIZE_DATA_OFFSET); - - if (section_bytes == 0) { - goto error_exit; - } - - SAFE_FREE(buf); - buf=(char *)SMB_MALLOC(section_bytes); - if (buf == NULL) { - DBG_ERR("PE file [%s] version malloc " - "failed bytes = %d\n", - fname, - section_bytes); - goto error_exit; - } - - /* - * Seek to the start of the .rsrc - * section info - */ - oret = SMB_VFS_LSEEK(fsp, - section_pos, - SEEK_SET); - if (oret == (off_t)-1) { - DBG_NOTICE("PE file [%s] too short for " - "section info, errno = %d\n", - fname, - errno); - goto error_exit; - } - - byte_count = vfs_read_data(fsp, - buf, - section_bytes); - if (byte_count < section_bytes) { - DBG_NOTICE("PE file " - "[%s] .rsrc section too short, " - "bytes read = %lu\n", - fname, - (unsigned long)byte_count); - goto error_exit; - } - - if (section_bytes < - VS_VERSION_INFO_UNICODE_SIZE) { - goto error_exit; - } - - for (i=0; - i< section_bytes- - VS_VERSION_INFO_UNICODE_SIZE; - i++) { - /* - * Scan for 1st 3 unicoded bytes - * followed by word aligned magic - * value. - */ - if (buf[i] == 'V' && - buf[i+1] == '\0' && - buf[i+2] == 'S') { - /* Align to next long address */ - int mpos = - (i + - sizeof(VS_SIGNATURE)*2 + - 3) & 0xfffffffc; - - if (IVAL(buf,mpos) == - VS_MAGIC_VALUE) { - *major = IVAL(buf, - mpos+ - VS_MAJOR_OFFSET); - *minor = IVAL(buf, - mpos+ - VS_MINOR_OFFSET); - - DBG_INFO("PE file [%s] " - "Version = " - "%08x:%08x " - "(%d.%d.%d.%d)\n", - fname, - *major, - *minor, - (*major>>16)&0xffff, - *major&0xffff, - (*minor>>16)&0xffff, - *minor&0xffff); - SAFE_FREE(buf); - return 1; - } - } - } - } - } - - /* Version info not found, fall back to origin date/time */ - DBG_DEBUG("PE file [%s] has no version info\n", fname); - SAFE_FREE(buf); - return 0; - + return handle_pe_file(fsp, + fname, + buf, + major, + minor); } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) { if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != |