Home | History | Annotate | Download | only in src
      1 /*
      2  * This file contains helper functions for labeling support.
      3  *
      4  * Author : Richard Haines <richard_c_haines (at) btinternet.com>
      5  */
      6 
      7 #include <stdlib.h>
      8 #include <stdarg.h>
      9 #include <ctype.h>
     10 #include <string.h>
     11 #include <stdio.h>
     12 #include <errno.h>
     13 #include <errno.h>
     14 #include "label_internal.h"
     15 
     16 /*
     17  * Read an entry from a spec file (e.g. file_contexts)
     18  * entry - Buffer to allocate for the entry.
     19  * ptr - current location of the line to be processed.
     20  * returns  - 0 on success and *entry is set to be a null
     21  *            terminated value. On Error it returns -1 and
     22  *            errno will be set.
     23  *
     24  */
     25 static inline int read_spec_entry(char **entry, char **ptr, int *len, const char **errbuf)
     26 {
     27 	*entry = NULL;
     28 	char *tmp_buf = NULL;
     29 
     30 	while (isspace(**ptr) && **ptr != '\0')
     31 		(*ptr)++;
     32 
     33 	tmp_buf = *ptr;
     34 	*len = 0;
     35 
     36 	while (!isspace(**ptr) && **ptr != '\0') {
     37 		if (!isascii(**ptr)) {
     38 			errno = EINVAL;
     39 			*errbuf = "Non-ASCII characters found";
     40 			return -1;
     41 		}
     42 		(*ptr)++;
     43 		(*len)++;
     44 	}
     45 
     46 	if (*len) {
     47 		*entry = strndup(tmp_buf, *len);
     48 		if (!*entry)
     49 			return -1;
     50 	}
     51 
     52 	return 0;
     53 }
     54 
     55 /*
     56  * line_buf - Buffer containing the spec entries .
     57  * errbuf   - Double pointer used for passing back specific error messages.
     58  * num_args - The number of spec parameter entries to process.
     59  * ...      - A 'char **spec_entry' for each parameter.
     60  * returns  - The number of items processed. On error, it returns -1 with errno
     61  *            set and may set errbuf to a specific error message.
     62  *
     63  * This function calls read_spec_entry() to do the actual string processing.
     64  * As such, can return anything from that function as well.
     65  */
     66 int hidden read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...)
     67 {
     68 	char **spec_entry, *buf_p;
     69 	int len, rc, items, entry_len = 0;
     70 	va_list ap;
     71 
     72 	*errbuf = NULL;
     73 
     74 	len = strlen(line_buf);
     75 	if (line_buf[len - 1] == '\n')
     76 		line_buf[len - 1] = '\0';
     77 	else
     78 		/* Handle case if line not \n terminated by bumping
     79 		 * the len for the check below (as the line is NUL
     80 		 * terminated by getline(3)) */
     81 		len++;
     82 
     83 	buf_p = line_buf;
     84 	while (isspace(*buf_p))
     85 		buf_p++;
     86 
     87 	/* Skip comment lines and empty lines. */
     88 	if (*buf_p == '#' || *buf_p == '\0')
     89 		return 0;
     90 
     91 	/* Process the spec file entries */
     92 	va_start(ap, num_args);
     93 
     94 	items = 0;
     95 	while (items < num_args) {
     96 		spec_entry = va_arg(ap, char **);
     97 
     98 		if (len - 1 == buf_p - line_buf) {
     99 			va_end(ap);
    100 			return items;
    101 		}
    102 
    103 		rc = read_spec_entry(spec_entry, &buf_p, &entry_len, errbuf);
    104 		if (rc < 0) {
    105 			va_end(ap);
    106 			return rc;
    107 		}
    108 		if (entry_len)
    109 			items++;
    110 	}
    111 	va_end(ap);
    112 	return items;
    113 }
    114 
    115 /* Once all the specfiles are in the hash_buf, generate the hash. */
    116 void hidden digest_gen_hash(struct selabel_digest *digest)
    117 {
    118 	Sha1Context context;
    119 
    120 	/* If SELABEL_OPT_DIGEST not set then just return */
    121 	if (!digest)
    122 		return;
    123 
    124 	Sha1Initialise(&context);
    125 	Sha1Update(&context, digest->hashbuf, digest->hashbuf_size);
    126 	Sha1Finalise(&context, (SHA1_HASH *)digest->digest);
    127 	free(digest->hashbuf);
    128 	digest->hashbuf = NULL;
    129 	return;
    130 }
    131 
    132 /**
    133  * digest_add_specfile - Add a specfile to the hashbuf and if gen_hash true
    134  *			 then generate the hash.
    135  * @digest: pointer to the selabel_digest struct
    136  * @fp: file pointer for fread(3) or NULL if not.
    137  * @from_addr: pointer at start of buffer for memcpy or NULL if not (used for
    138  *	       mmap(3) files).
    139  * @buf_len: length of buffer to copy.
    140  * @path: pointer to the specfile.
    141  *
    142  * Return %0 on success, -%1 with @errno set on failure.
    143  */
    144 int hidden digest_add_specfile(struct selabel_digest *digest, FILE *fp,
    145 				    char *from_addr, size_t buf_len,
    146 				    const char *path)
    147 {
    148 	unsigned char *tmp_buf;
    149 
    150 	/* If SELABEL_OPT_DIGEST not set then just return */
    151 	if (!digest)
    152 		return 0;
    153 
    154 	if (digest->hashbuf_size + buf_len < digest->hashbuf_size) {
    155 		errno = EOVERFLOW;
    156 		return -1;
    157 	}
    158 	digest->hashbuf_size += buf_len;
    159 
    160 	tmp_buf = realloc(digest->hashbuf, digest->hashbuf_size);
    161 	if (!tmp_buf)
    162 		return -1;
    163 
    164 	digest->hashbuf = tmp_buf;
    165 
    166 	if (fp) {
    167 		rewind(fp);
    168 		if (fread(digest->hashbuf + (digest->hashbuf_size - buf_len),
    169 					    1, buf_len, fp) != buf_len)
    170 			return -1;
    171 
    172 		rewind(fp);
    173 	} else if (from_addr) {
    174 		tmp_buf = memcpy(digest->hashbuf +
    175 				    (digest->hashbuf_size - buf_len),
    176 				    from_addr, buf_len);
    177 		if (!tmp_buf)
    178 			return -1;
    179 	}
    180 	/* Now add path to list */
    181 	digest->specfile_list[digest->specfile_cnt] = strdup(path);
    182 	if (!digest->specfile_list[digest->specfile_cnt])
    183 		return -1;
    184 
    185 	digest->specfile_cnt++;
    186 	if (digest->specfile_cnt > DIGEST_FILES_MAX) {
    187 		errno = EOVERFLOW;
    188 		return -1;
    189 	}
    190 
    191 	return 0;
    192 }
    193