1 #include <stdio.h> 2 3 #include <stdlib.h> 4 #include <ctype.h> 5 #include <errno.h> 6 #include <limits.h> 7 8 #include <sepol/policydb/policydb.h> 9 10 #ifndef __APPLE__ 11 #include <stdio_ext.h> 12 #endif 13 14 #include <stdarg.h> 15 16 #include "debug.h" 17 #include "private.h" 18 #include "dso.h" 19 #include "mls.h" 20 21 /* -- Deprecated -- */ 22 23 void sepol_set_delusers(int on __attribute((unused))) 24 { 25 WARN(NULL, "Deprecated interface"); 26 } 27 28 #undef BADLINE 29 #define BADLINE() { \ 30 ERR(NULL, "invalid entry %s (%s:%u)", \ 31 buffer, path, lineno); \ 32 continue; \ 33 } 34 35 static int load_users(struct policydb *policydb, const char *path) 36 { 37 FILE *fp; 38 char *buffer = NULL, *p, *q, oldc; 39 ssize_t nread; 40 unsigned lineno = 0, islist = 0, bit; 41 user_datum_t *usrdatum; 42 role_datum_t *roldatum; 43 ebitmap_node_t *rnode; 44 45 fp = fopen(path, "r"); 46 if (fp == NULL) 47 return -1; 48 49 #ifdef __APPLE__ 50 if ((buffer = (char *)malloc(255 * sizeof(char))) == NULL) { 51 ERR(NULL, "out of memory"); 52 return -1; 53 } 54 55 while(fgets(buffer, 255, fp) != NULL) { 56 nread = strlen(buffer); 57 #else 58 size_t len = 0; 59 __fsetlocking(fp, FSETLOCKING_BYCALLER); 60 while ((nread = getline(&buffer, &len, fp)) > 0) { 61 #endif 62 63 lineno++; 64 if (buffer[nread - 1] == '\n') 65 buffer[nread - 1] = 0; 66 p = buffer; 67 while (*p && isspace(*p)) 68 p++; 69 if (!(*p) || *p == '#') 70 continue; 71 72 if (strncasecmp(p, "user", 4)) 73 BADLINE(); 74 p += 4; 75 if (!isspace(*p)) 76 BADLINE(); 77 while (*p && isspace(*p)) 78 p++; 79 if (!(*p)) 80 BADLINE(); 81 q = p; 82 while (*p && !isspace(*p)) 83 p++; 84 if (!(*p)) 85 BADLINE(); 86 *p++ = 0; 87 88 usrdatum = hashtab_search(policydb->p_users.table, q); 89 if (usrdatum) { 90 /* Replacing an existing user definition. */ 91 ebitmap_destroy(&usrdatum->roles.roles); 92 ebitmap_init(&usrdatum->roles.roles); 93 } else { 94 char *id = strdup(q); 95 96 if (!id) { 97 ERR(NULL, "out of memory"); 98 free(buffer); 99 fclose(fp); 100 return -1; 101 } 102 103 /* Adding a new user definition. */ 104 usrdatum = malloc(sizeof(user_datum_t)); 105 if (!usrdatum) { 106 ERR(NULL, "out of memory"); 107 free(buffer); 108 free(id); 109 fclose(fp); 110 return -1; 111 } 112 113 user_datum_init(usrdatum); 114 usrdatum->s.value = ++policydb->p_users.nprim; 115 if (hashtab_insert(policydb->p_users.table, 116 id, (hashtab_datum_t) usrdatum)) { 117 ERR(NULL, "out of memory"); 118 free(buffer); 119 free(id); 120 user_datum_destroy(usrdatum); 121 free(usrdatum); 122 fclose(fp); 123 return -1; 124 } 125 } 126 127 while (*p && isspace(*p)) 128 p++; 129 if (!(*p)) 130 BADLINE(); 131 if (strncasecmp(p, "roles", 5)) 132 BADLINE(); 133 p += 5; 134 if (!isspace(*p)) 135 BADLINE(); 136 while (*p && isspace(*p)) 137 p++; 138 if (!(*p)) 139 BADLINE(); 140 if (*p == '{') { 141 islist = 1; 142 p++; 143 } else 144 islist = 0; 145 146 oldc = 0; 147 do { 148 while (*p && isspace(*p)) 149 p++; 150 if (!(*p)) 151 break; 152 153 q = p; 154 while (*p && *p != ';' && *p != '}' && !isspace(*p)) 155 p++; 156 if (!(*p)) 157 break; 158 if (*p == '}') 159 islist = 0; 160 oldc = *p; 161 *p++ = 0; 162 if (!q[0]) 163 break; 164 165 roldatum = hashtab_search(policydb->p_roles.table, q); 166 if (!roldatum) { 167 ERR(NULL, "undefined role %s (%s:%u)", 168 q, path, lineno); 169 continue; 170 } 171 /* Set the role and every role it dominates */ 172 ebitmap_for_each_bit(&roldatum->dominates, rnode, bit) { 173 if (ebitmap_node_get_bit(rnode, bit)) 174 if (ebitmap_set_bit 175 (&usrdatum->roles.roles, bit, 1)) { 176 ERR(NULL, "out of memory"); 177 free(buffer); 178 fclose(fp); 179 return -1; 180 } 181 } 182 } while (islist); 183 if (oldc == 0) 184 BADLINE(); 185 186 if (policydb->mls) { 187 context_struct_t context; 188 char *scontext, *r, *s; 189 190 while (*p && isspace(*p)) 191 p++; 192 if (!(*p)) 193 BADLINE(); 194 if (strncasecmp(p, "level", 5)) 195 BADLINE(); 196 p += 5; 197 if (!isspace(*p)) 198 BADLINE(); 199 while (*p && isspace(*p)) 200 p++; 201 if (!(*p)) 202 BADLINE(); 203 q = p; 204 while (*p && strncasecmp(p, "range", 5)) 205 p++; 206 if (!(*p)) 207 BADLINE(); 208 *--p = 0; 209 p++; 210 211 scontext = malloc(p - q); 212 if (!scontext) { 213 ERR(NULL, "out of memory"); 214 free(buffer); 215 fclose(fp); 216 return -1; 217 } 218 r = scontext; 219 s = q; 220 while (*s) { 221 if (!isspace(*s)) 222 *r++ = *s; 223 s++; 224 } 225 *r = 0; 226 r = scontext; 227 228 context_init(&context); 229 if (mls_context_to_sid(policydb, oldc, &r, &context) < 230 0) { 231 ERR(NULL, "invalid level %s (%s:%u)", scontext, 232 path, lineno); 233 free(scontext); 234 continue; 235 236 } 237 free(scontext); 238 memcpy(&usrdatum->dfltlevel, &context.range.level[0], 239 sizeof(usrdatum->dfltlevel)); 240 241 if (strncasecmp(p, "range", 5)) 242 BADLINE(); 243 p += 5; 244 if (!isspace(*p)) 245 BADLINE(); 246 while (*p && isspace(*p)) 247 p++; 248 if (!(*p)) 249 BADLINE(); 250 q = p; 251 while (*p && *p != ';') 252 p++; 253 if (!(*p)) 254 BADLINE(); 255 *p++ = 0; 256 257 scontext = malloc(p - q); 258 if (!scontext) { 259 ERR(NULL, "out of memory"); 260 free(buffer); 261 fclose(fp); 262 return -1; 263 } 264 r = scontext; 265 s = q; 266 while (*s) { 267 if (!isspace(*s)) 268 *r++ = *s; 269 s++; 270 } 271 *r = 0; 272 r = scontext; 273 274 context_init(&context); 275 if (mls_context_to_sid(policydb, oldc, &r, &context) < 276 0) { 277 ERR(NULL, "invalid range %s (%s:%u)", scontext, 278 path, lineno); 279 free(scontext); 280 continue; 281 } 282 free(scontext); 283 memcpy(&usrdatum->range, &context.range, 284 sizeof(usrdatum->range)); 285 } 286 } 287 288 free(buffer); 289 fclose(fp); 290 return 0; 291 } 292 293 int sepol_genusers(void *data, size_t len, 294 const char *usersdir, void **newdata, size_t * newlen) 295 { 296 struct policydb policydb; 297 char path[PATH_MAX]; 298 299 /* Construct policy database */ 300 if (policydb_init(&policydb)) 301 goto err; 302 if (policydb_from_image(NULL, data, len, &policydb) < 0) 303 goto err; 304 305 /* Load locally defined users. */ 306 snprintf(path, sizeof path, "%s/local.users", usersdir); 307 if (load_users(&policydb, path) < 0) 308 goto err_destroy; 309 310 /* Write policy database */ 311 if (policydb_to_image(NULL, &policydb, newdata, newlen) < 0) 312 goto err_destroy; 313 314 policydb_destroy(&policydb); 315 return 0; 316 317 err_destroy: 318 policydb_destroy(&policydb); 319 320 err: 321 return -1; 322 } 323 324 int hidden sepol_genusers_policydb(policydb_t * policydb, const char *usersdir) 325 { 326 char path[PATH_MAX]; 327 328 /* Load locally defined users. */ 329 snprintf(path, sizeof path, "%s/local.users", usersdir); 330 if (load_users(policydb, path) < 0) { 331 ERR(NULL, "unable to load local.users: %s", strerror(errno)); 332 return -1; 333 } 334 335 if (policydb_reindex_users(policydb) < 0) { 336 ERR(NULL, "unable to reindex users: %s", strerror(errno)); 337 return -1; 338 339 } 340 341 return 0; 342 } 343 344 /* -- End Deprecated -- */ 345