Home | History | Annotate | Download | only in src
      1 /* Copyright (C) 2005 Red Hat, Inc. */
      2 
      3 struct semanage_user_base;
      4 struct semanage_user_key;
      5 typedef struct semanage_user_base record_t;
      6 typedef struct semanage_user_key record_key_t;
      7 #define DBASE_RECORD_DEFINED
      8 
      9 struct dbase_file;
     10 typedef struct dbase_file dbase_t;
     11 #define DBASE_DEFINED
     12 
     13 #include <stdlib.h>
     14 #include <stdio.h>
     15 #include <ctype.h>
     16 #include <string.h>
     17 #include <semanage/handle.h>
     18 #include "user_internal.h"
     19 #include "database_file.h"
     20 #include "parse_utils.h"
     21 #include "debug.h"
     22 
     23 static int user_base_print(semanage_handle_t * handle,
     24 			   semanage_user_base_t * user, FILE * str)
     25 {
     26 
     27 	const char **roles = NULL;
     28 	unsigned int i, nroles;
     29 
     30 	const char *name = semanage_user_base_get_name(user);
     31 	const char *mls_level = semanage_user_base_get_mlslevel(user);
     32 	const char *mls_range = semanage_user_base_get_mlsrange(user);
     33 
     34 	if (fprintf(str, "user %s roles { ", name) < 0)
     35 		goto err;
     36 
     37 	if (semanage_user_base_get_roles(handle, user, &roles, &nroles) < 0)
     38 		goto err;
     39 
     40 	for (i = 0; i < nroles; i++) {
     41 		if (fprintf(str, "%s ", roles[i]) < 0)
     42 			goto err;
     43 	}
     44 
     45 	if (fprintf(str, "} ") < 0)
     46 		goto err;
     47 
     48 	/* MLS */
     49 	if (mls_level != NULL && mls_range != NULL)
     50 		if (fprintf(str, "level %s range %s", mls_level, mls_range) < 0)
     51 			goto err;
     52 
     53 	if (fprintf(str, ";\n") < 0)
     54 		goto err;
     55 
     56 	free(roles);
     57 	return STATUS_SUCCESS;
     58 
     59       err:
     60 	free(roles);
     61 	ERR(handle, "could not print user %s to stream", name);
     62 	return STATUS_ERR;
     63 }
     64 
     65 static int user_base_parse(semanage_handle_t * handle,
     66 			   parse_info_t * info, semanage_user_base_t * user)
     67 {
     68 
     69 	int islist = 0;
     70 	char *str = NULL;
     71 	char *start;
     72 	char *name_str = NULL;
     73 
     74 	if (parse_skip_space(handle, info) < 0)
     75 		goto err;
     76 	if (!info->ptr)
     77 		goto last;
     78 
     79 	/* Parse user header */
     80 	if (parse_assert_str(handle, info, "user") < 0)
     81 		goto err;
     82 	if (parse_assert_space(handle, info) < 0)
     83 		goto err;
     84 
     85 	/* Parse user name */
     86 	if (parse_fetch_string(handle, info, &name_str, ' ') < 0)
     87 		goto err;
     88 
     89 	if (semanage_user_base_set_name(handle, user, name_str) < 0) {
     90 		free(name_str);
     91 		goto err;
     92 	}
     93 	free(name_str);
     94 
     95 	if (parse_assert_space(handle, info) < 0)
     96 		goto err;
     97 	if (parse_assert_str(handle, info, "roles") < 0)
     98 		goto err;
     99 	if (parse_assert_space(handle, info) < 0)
    100 		goto err;
    101 
    102 	islist = (parse_optional_ch(info, '{') != STATUS_NODATA);
    103 
    104 	/* For each role, loop */
    105 	do {
    106 		char delim;
    107 
    108 		if (parse_skip_space(handle, info) < 0)
    109 			goto err;
    110 		if (parse_assert_noeof(handle, info) < 0)
    111 			goto err;
    112 
    113 		start = info->ptr;
    114 		while (*(info->ptr) &&
    115 		       *(info->ptr) != ';' &&
    116 		       *(info->ptr) != '}' && !isspace(*(info->ptr)))
    117 			info->ptr++;
    118 
    119 		delim = *(info->ptr);
    120 		*(info->ptr)++ = '\0';
    121 
    122 		if (semanage_user_base_add_role(handle, user, start) < 0)
    123 			goto err;
    124 
    125 		if (delim && !isspace(delim)) {
    126 			if (islist && delim == '}')
    127 				break;
    128 			else if (!islist && delim == ';')
    129 				goto skip_semicolon;
    130 			else
    131 				goto err;
    132 		}
    133 
    134 		if (parse_skip_space(handle, info) < 0)
    135 			goto err;
    136 		if (parse_optional_ch(info, ';') != STATUS_NODATA)
    137 			goto skip_semicolon;
    138 		if (parse_optional_ch(info, '}') != STATUS_NODATA)
    139 			islist = 0;
    140 
    141 	} while (islist);
    142 
    143 	/* Handle mls */
    144 	/* Parse level header */
    145 	if (parse_skip_space(handle, info) < 0)
    146 		goto err;
    147 	if (parse_optional_str(info, "level") == STATUS_NODATA)
    148 		goto semicolon;
    149 	if (parse_assert_space(handle, info) < 0)
    150 		goto err;
    151 
    152 	/* NOTE: does not allow spaces/multiline */
    153 	if (parse_fetch_string(handle, info, &str, ' ') < 0)
    154 		goto err;
    155 	if (semanage_user_base_set_mlslevel(handle, user, str) < 0)
    156 		goto err;
    157 	free(str);
    158 	str = NULL;
    159 
    160 	/* Parse range header */
    161 	if (parse_assert_space(handle, info) < 0)
    162 		goto err;
    163 	if (parse_assert_str(handle, info, "range") < 0)
    164 		goto err;
    165 	if (parse_assert_space(handle, info) < 0)
    166 		goto err;
    167 
    168 	/* NOTE: does not allow spaces/multiline */
    169 	if (parse_fetch_string(handle, info, &str, ';') < 0)
    170 		goto err;
    171 	if (semanage_user_base_set_mlsrange(handle, user, str) < 0)
    172 		goto err;
    173 
    174 	free(str);
    175 	str = NULL;
    176 
    177 	/* Check for semicolon */
    178       semicolon:
    179 	if (parse_skip_space(handle, info) < 0)
    180 		goto err;
    181 	if (parse_assert_ch(handle, info, ';') < 0)
    182 		goto err;
    183 
    184       skip_semicolon:
    185 	return STATUS_SUCCESS;
    186 
    187       last:
    188 	parse_dispose_line(info);
    189 	return STATUS_NODATA;
    190 
    191       err:
    192 	ERR(handle, "could not parse user record");
    193 	free(str);
    194 	parse_dispose_line(info);
    195 	return STATUS_ERR;
    196 }
    197 
    198 /* USER BASE record: FILE extension: method table */
    199 record_file_table_t SEMANAGE_USER_BASE_FILE_RTABLE = {
    200 	.parse = user_base_parse,
    201 	.print = user_base_print,
    202 };
    203 
    204 int user_base_file_dbase_init(semanage_handle_t * handle,
    205 			      const char *path_ro,
    206 			      const char *path_rw,
    207 			      dbase_config_t * dconfig)
    208 {
    209 
    210 	if (dbase_file_init(handle,
    211 			    path_ro,
    212 			    path_rw,
    213 			    &SEMANAGE_USER_BASE_RTABLE,
    214 			    &SEMANAGE_USER_BASE_FILE_RTABLE,
    215 			    &dconfig->dbase) < 0)
    216 		return STATUS_ERR;
    217 
    218 	dconfig->dtable = &SEMANAGE_FILE_DTABLE;
    219 	return STATUS_SUCCESS;
    220 }
    221 
    222 void user_base_file_dbase_release(dbase_config_t * dconfig)
    223 {
    224 
    225 	dbase_file_release(dconfig->dbase);
    226 }
    227